Role-based access control with User and Admin capabilities
LarpLand implements a simple but effective role-based access control (RBAC) system with two roles: User (rol=0) and Admin (rol=1). The role determines which features and UI components are accessible.
The User model doesn’t include the role field, but it’s stored in Firestore:
lib/model/user.dart
class User { final int id; final String name; final String email; const User({ required this.id, required this.name, required this.email, }); factory User.fromJson(Map<String, dynamic> json) { final rawId = json['id']; final rawName = json['name']; final rawEmail = json['email']; final id = switch (rawId) { int value => value, num value => value.toInt(), String value => int.tryParse(value), _ => null, }; if (id == null || rawName is! String || rawEmail is! String) { throw const FormatException('Fallo al cargar el usuario'); } return User( id: id, name: rawName, email: rawEmail, ); }}
The rol field is accessed through the Firestore profile data or AuthSession.rol, not through the User model.
The user’s role is stored in the AuthSession singleton:
lib/service/auth_session.dart
class AuthSession { static String? token; static String? firebaseUid; static int? userId; static int? rol; // Role stored here static void bind({ String? idToken, String? uid, int? sessionUserId, int? sessionRol, }) { token = idToken; firebaseUid = uid; userId = sessionUserId; rol = sessionRol; // Set during login }}
The role is set during login and persists throughout the user’s session:
lib/service/login.dart
final profile = await FirebaseBackend.ensureUserProfile(firebaseUser: user);final rol = _asInt(profile['rol']) ?? 0;AuthSession.bind( idToken: idToken, uid: user.uid, sessionUserId: userId, sessionRol: rol, // Store role in session);
The current implementation performs role checks on the client side. For production apps, you should also enforce role-based security rules in Firebase Firestore to prevent unauthorized access.
Firestore Security Rules
Implement Firestore security rules to validate user roles server-side:
rules_version = '2';service cloud.firestore { match /databases/{database}/documents { // Only admins can write to products match /products/{product} { allow read: if true; allow write: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.rol == 1; } // Users can only read their own orders match /orders/{order} { allow read: if request.auth != null && (resource.data.user_id == request.auth.uid || get(/databases/$(database)/documents/users/$(request.auth.uid)).data.rol == 1); allow write: if request.auth != null; } }}
Role Modification
Never allow users to modify their own rol field. Role changes should only be performed by admins through a secure admin interface or directly in Firestore.