nkbmusic/admin/lib/session.dart
metatroncubeswdev cf645071aa Add NK Admin dashboard (Flutter web) for admin.nkbmusic.com
Email-code sign-in for admins only; Overview with a needs-attention list;
Songs with search, playback, editing, approve/hide and bulk edit; Albums
and Singers with merge; creator applications queue. Adds the admin views,
functions and creator_applications table, a deploy-admin script and a
how-to guide. The admin nginx config no longer caches unhashed JS and
sends its security headers again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 11:35:44 -04:00

56 lines
1.5 KiB
Dart

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'api.dart';
enum SessionState { checking, signedOut, admin }
/// Who is signed in. Only admin accounts get past the sign-in page: anyone else is
/// signed straight out again (the database refuses their changes either way).
class AdminSession extends ChangeNotifier {
AdminSession._();
static final instance = AdminSession._();
SessionState state = SessionState.checking;
String? email;
/// Shown on the sign-in page after a non-admin account tried to sign in.
String? refusal;
StreamSubscription<AuthState>? _sub;
void start() {
_sub ??= Supabase.instance.client.auth.onAuthStateChange.listen((e) => _check(e.session));
_check(Supabase.instance.client.auth.currentSession);
}
Future<void> _check(Session? session) async {
if (session == null) {
_set(SessionState.signedOut, null);
return;
}
if (state == SessionState.admin && email == session.user.email) return;
try {
if (await AdminApi.isAdmin()) {
refusal = null;
_set(SessionState.admin, session.user.email);
return;
}
refusal = '${session.user.email} is not an admin account.';
} catch (e) {
refusal = 'Could not check your account: $e';
}
await AdminApi.signOut();
_set(SessionState.signedOut, null);
}
void _set(SessionState s, String? e) {
if (s == state && e == email) return;
state = s;
email = e;
notifyListeners();
}
}