import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../../services/auth_service.dart'; import '../../data/models/auth/auth_user.dart'; /// 역할 기반 접근 제어를 위한 AuthGuard 위젯 /// /// 사용자의 역할을 확인하여 허용된 역할만 child 위젯에 접근할 수 있도록 제어합니다. /// 권한이 없는 경우 UnauthorizedScreen을 표시합니다. class AuthGuard extends StatelessWidget { /// 접근을 허용할 역할 목록 final List allowedRoles; /// 권한이 있을 때 표시할 위젯 final Widget child; /// 권한이 없을 때 표시할 커스텀 위젯 (선택사항) final Widget? unauthorizedWidget; /// 권한 체크를 건너뛸지 여부 (개발 모드용) final bool skipCheck; const AuthGuard({ super.key, required this.allowedRoles, required this.child, this.unauthorizedWidget, this.skipCheck = false, }); @override Widget build(BuildContext context) { // 개발 모드에서 권한 체크 건너뛰기 if (skipCheck) { return child; } // AuthService에서 현재 사용자 정보 가져오기 final authService = context.read(); return FutureBuilder( future: authService.getCurrentUser(), builder: (context, snapshot) { // 로딩 중 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 현재 사용자 정보 final currentUser = snapshot.data; // 로그인하지 않은 경우 if (currentUser == null) { return unauthorizedWidget ?? const UnauthorizedScreen( message: '로그인이 필요합니다.', ); } // 역할 확인 - 대소문자 구분 없이 비교 final userRole = currentUser.role.toLowerCase(); final hasPermission = allowedRoles.any( (role) => role.toLowerCase() == userRole, ); // 권한이 있는 경우 if (hasPermission) { return child; } // 권한이 없는 경우 return unauthorizedWidget ?? UnauthorizedScreen( message: '이 페이지에 접근할 권한이 없습니다.', userRole: currentUser.role, requiredRoles: allowedRoles, ); }, ); } } /// 권한이 없을 때 표시되는 기본 화면 class UnauthorizedScreen extends StatelessWidget { final String message; final String? userRole; final List? requiredRoles; const UnauthorizedScreen({ super.key, required this.message, this.userRole, this.requiredRoles, }); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Container( padding: const EdgeInsets.all(32), constraints: const BoxConstraints(maxWidth: 400), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( Icons.lock_outline, size: 80, color: Colors.grey, ), const SizedBox(height: 24), Text( '접근 권한 없음', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox(height: 16), Text( message, textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyLarge, ), if (userRole != null) ...[ const SizedBox(height: 16), Text( '현재 권한: $userRole', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.grey, ), ), ], if (requiredRoles != null && requiredRoles!.isNotEmpty) ...[ const SizedBox(height: 8), Text( '필요한 권한: ${requiredRoles!.join(", ")}', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.grey, ), ), ], const SizedBox(height: 32), ElevatedButton( onPressed: () { Navigator.of(context).pushReplacementNamed('/'); }, child: const Text('홈으로 이동'), ), ], ), ), ), ); } } /// 역할 상수 정의 class UserRole { static const String admin = 'Admin'; static const String manager = 'Manager'; static const String member = 'Member'; /// 관리자 및 매니저 권한 static const List adminAndManager = [admin, manager]; /// 모든 권한 static const List all = [admin, manager, member]; /// 관리자 전용 static const List adminOnly = [admin]; }