전역 구조 리팩터링 및 테스트 확장

This commit is contained in:
JiWoong Sul
2025-09-29 01:51:47 +09:00
parent c00c0c9ab2
commit fef7108479
70 changed files with 7709 additions and 3185 deletions

View File

@@ -0,0 +1,87 @@
import 'package:flutter/widgets.dart';
import '../config/environment.dart';
enum PermissionAction { view, create, edit, delete, restore, approve }
class PermissionManager extends ChangeNotifier {
PermissionManager({Map<String, Set<PermissionAction>>? overrides}) {
if (overrides != null) {
_overrides.addAll(overrides);
}
}
final Map<String, Set<PermissionAction>> _overrides = {};
bool can(String resource, PermissionAction action) {
final override = _overrides[resource];
if (override != null) {
if (override.contains(PermissionAction.view) &&
action == PermissionAction.view) {
return true;
}
return override.contains(action);
}
return Environment.hasPermission(resource, action.name);
}
void updateOverrides(Map<String, Set<PermissionAction>> overrides) {
_overrides
..clear()
..addAll(overrides);
notifyListeners();
}
}
class PermissionScope extends InheritedNotifier<PermissionManager> {
const PermissionScope({
super.key,
required PermissionManager manager,
required super.child,
}) : super(notifier: manager);
static PermissionManager of(BuildContext context) {
final scope = context.dependOnInheritedWidgetOfExactType<PermissionScope>();
assert(
scope != null,
'PermissionScope.of() called with no PermissionScope ancestor.',
);
return scope!.notifier!;
}
}
class PermissionGate extends StatelessWidget {
const PermissionGate({
super.key,
required this.resource,
required this.action,
required this.child,
this.fallback,
this.hide = true,
});
final String resource;
final PermissionAction action;
final Widget child;
final Widget? fallback;
final bool hide;
@override
Widget build(BuildContext context) {
final allowed = PermissionScope.of(context).can(resource, action);
if (allowed) {
return child;
}
if (hide) {
return fallback ?? const SizedBox.shrink();
}
return IgnorePointer(
ignoring: true,
child: Opacity(opacity: 0.4, child: fallback ?? child),
);
}
}
extension PermissionActionKey on PermissionAction {
String get key => name;
}