diff options
Diffstat (limited to 'player-android/lib/providers')
| -rw-r--r-- | player-android/lib/providers/current_user_provider.dart | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/player-android/lib/providers/current_user_provider.dart b/player-android/lib/providers/current_user_provider.dart index 560feb0..f1c7b12 100644 --- a/player-android/lib/providers/current_user_provider.dart +++ b/player-android/lib/providers/current_user_provider.dart @@ -6,17 +6,16 @@ import 'api_client_provider.dart'; /// Provides the currently authenticated [User] object. /// -/// Calls [PlayerApiClient.login] is not used here — instead, the logged-in -/// user is fetched lazily via [listUsers] or derived from the auth context. -/// Since the server does not expose a "GET /api/v1/auth/me" endpoint, we -/// obtain the current user by calling [listUsers] and matching against the -/// stored username token. +/// The [PlayerApiClient.login] call is not used here — instead, the logged-in +/// user is fetched lazily via [listUsers] and matched against the stored +/// username token. Since the server does not expose a "GET /api/v1/auth/me" +/// endpoint, this round-trip is the only way to obtain the [User.isAdmin] flag. /// /// The provider is autoDispose so it is released when no screen is watching it, /// and keepAlive is not used — a fresh fetch is acceptable when navigating back. /// -/// Returns null when the user list cannot be fetched or the username is not -/// found among the registered users (e.g. during a race with logout). +/// Returns null when the user list cannot be fetched, or when the username is +/// not found among the registered users (e.g. during a race with logout). final currentUserProvider = FutureProvider.autoDispose<User?>((ref) async { // Obtain the stored username from token storage (same source as the settings // screen's _currentUsernameProvider) to identify which user is logged in. @@ -31,13 +30,18 @@ final currentUserProvider = FutureProvider.autoDispose<User?>((ref) async { final client = ref.watch(apiClientProvider); try { final users = await client.listUsers(); - return users.firstWhere( - (u) => u.username == username, - orElse: () => User(id: 0, username: username, isAdmin: false), + // Cast to User? so orElse can return null when the username is not in the + // list (e.g. the account was deleted). null is the safest sentinel because + // it does not collide with the id=0 placeholder used in AdminUsersScreen. + return users.cast<User?>().firstWhere( + (u) => u?.username == username, + orElse: () => null, ); } catch (_) { - // If listUsers fails (e.g. non-admin user, network error) fall back to a - // minimal user object with isAdmin=false so gating logic fails safely. - return User(id: 0, username: username, isAdmin: false); + // If listUsers fails (e.g. non-admin user, network error) return null so + // callers that gate on isAdmin fail safely without a fake User(id:0) object + // that could collide with the optimistic placeholder sentinel in + // AdminUsersScreen. + return null; } }); |
