Files
superport/lib/core/widgets/auth_guard.dart
JiWoong Sul 5839a2be8e
Some checks failed
Flutter Test & Quality Check / Test on macos-latest (push) Has been cancelled
Flutter Test & Quality Check / Test on ubuntu-latest (push) Has been cancelled
Flutter Test & Quality Check / Build APK (push) Has been cancelled
feat: Phase 11 완료 - API 엔드포인트 완전성 + 코드 품질 최종 달성
🎊 Phase 11 핵심 성과 (68개 → 38개 이슈, 30개 해결, 44.1% 감소)

 Phase 11-1: API 엔드포인트 누락 해결
• equipment, warehouseLocations, rents* 엔드포인트 완전 추가
• lib/core/constants/api_endpoints.dart 구조 최적화

 Phase 11-2: VendorStatsDto 완전 구현
• lib/data/models/vendor_stats_dto.dart 신규 생성
• Freezed 패턴 적용 + build_runner 코드 생성
• 벤더 통계 기능 완전 복구

 Phase 11-3: 코드 품질 개선
• unused_field 제거 (stock_in_form.dart)
• unnecessary null-aware operators 정리
• maintenance_controller.dart, maintenance_alert_dashboard.dart 타입 안전성 개선

🚀 과잉 기능 완전 제거
• Dashboard 관련 11개 파일 정리 (license, overview, stats)
• backend_compatibility_config.dart 제거
• 백엔드 100% 호환 구조로 단순화

🏆 최종 달성
• 모든 ERROR 0개 완전 달성
• API 엔드포인트 완전성 100%
• 총 92.2% 개선률 (488개 → 38개)
• 완전한 운영 환경 달성

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 16:38:38 +09:00

167 lines
5.0 KiB
Dart

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<String> 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<AuthService>();
return FutureBuilder<AuthUser?>(
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<String>? 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<String> adminAndManager = [admin, manager];
/// 모든 권한
static const List<String> all = [admin, manager, member];
/// 관리자 전용
static const List<String> adminOnly = [admin];
}