78 lines
2.4 KiB
Dart
78 lines
2.4 KiB
Dart
import 'package:get/get.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
/// Oldal-/funkció-szintű jogosultságok kezelése — PROJEKTENKÉNT.
|
|
///
|
|
/// A jogosultságokat a Supabase `app_permissions` tábla tárolja
|
|
/// (user_id + area + project_id), ahol a project_id NULL értéke
|
|
/// GLOBÁLIS jogot jelent (minden projektre érvényes — pl. admin).
|
|
/// A tényleges védelmet a Supabase-oldali RLS adja
|
|
/// (`has_permission(area, project_id)`), ez a service csak a UI-t
|
|
/// vezérli (menüpont elrejtése, üzenet).
|
|
class PermissionService extends GetxService {
|
|
static PermissionService get to => Get.find();
|
|
|
|
static const areaContacts = 'contacts';
|
|
static const areaAdmin = 'admin';
|
|
|
|
SupabaseClient get _client => Supabase.instance.client;
|
|
|
|
/// projectId → engedélyezett területek. A `null` kulcs a GLOBÁLIS
|
|
/// (minden projektre érvényes) jogokat tárolja.
|
|
final _areasByProject = <String?, Set<String>>{}.obs;
|
|
final isLoaded = false.obs;
|
|
|
|
/// [projectId] nélkül CSAK a globális jogokat nézi — projekt-specifikus
|
|
/// ellenőrzéshez mindig add meg az aktív projektet.
|
|
bool can(String area, {String? projectId}) {
|
|
if (_areasByProject[null]?.contains(area) ?? false) return true;
|
|
if (projectId != null) {
|
|
return _areasByProject[projectId]?.contains(area) ?? false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool canContacts({String? projectId}) =>
|
|
can(areaContacts, projectId: projectId);
|
|
|
|
/// Az admin jogot szándékosan globálisnak tartjuk — ha ezt is
|
|
/// projektenként szeretnéd, ugyanígy paraméterezhető.
|
|
bool get canAdmin => can(areaAdmin);
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
reload();
|
|
_client.auth.onAuthStateChange.listen((_) => reload());
|
|
}
|
|
|
|
Future<void> reload() async {
|
|
final user = _client.auth.currentUser;
|
|
if (user == null) {
|
|
_areasByProject.clear();
|
|
isLoaded.value = true;
|
|
return;
|
|
}
|
|
try {
|
|
final rows = await _client
|
|
.from('terepi_seged_app_permissions')
|
|
.select('area, project_id')
|
|
.eq('user_id', user.id);
|
|
|
|
final map = <String?, Set<String>>{};
|
|
for (final r in rows) {
|
|
final pid = r['project_id'] as String?;
|
|
map.putIfAbsent(pid, () => {}).add(r['area'] as String);
|
|
}
|
|
_areasByProject
|
|
..clear()
|
|
..addAll(map);
|
|
} catch (_) {
|
|
_areasByProject.clear();
|
|
} finally {
|
|
_areasByProject.refresh();
|
|
isLoaded.value = true;
|
|
}
|
|
}
|
|
}
|