tasq/lib/providers/admin_user_provider.dart
2026-02-11 20:12:48 +08:00

110 lines
2.9 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'supabase_provider.dart';
import '../utils/app_time.dart';
final adminUserControllerProvider = Provider<AdminUserController>((ref) {
final client = ref.watch(supabaseClientProvider);
return AdminUserController(client);
});
class AdminUserStatus {
AdminUserStatus({required this.email, required this.bannedUntil});
final String? email;
final DateTime? bannedUntil;
bool get isLocked {
if (bannedUntil == null) return false;
return bannedUntil!.isAfter(AppTime.now());
}
}
class AdminUserController {
AdminUserController(this._client);
final SupabaseClient _client;
Future<void> updateProfile({
required String userId,
required String fullName,
required String role,
}) async {
await _client
.from('profiles')
.update({'full_name': fullName, 'role': role})
.eq('id', userId);
}
Future<void> updateRole({
required String userId,
required String role,
}) async {
await _client.from('profiles').update({'role': role}).eq('id', userId);
}
Future<void> setPassword({
required String userId,
required String password,
}) async {
await _invokeAdminFunction(
action: 'set_password',
payload: {'userId': userId, 'password': password},
);
}
Future<void> setLock({required String userId, required bool locked}) async {
await _invokeAdminFunction(
action: 'set_lock',
payload: {'userId': userId, 'locked': locked},
);
}
Future<AdminUserStatus> fetchStatus(String userId) async {
final data = await _invokeAdminFunction(
action: 'get_user',
payload: {'userId': userId},
);
final user = (data as Map<String, dynamic>)['user'] as Map<String, dynamic>;
final bannedUntilRaw = user['banned_until'] as String?;
final bannedUntilParsed = bannedUntilRaw == null
? null
: DateTime.tryParse(bannedUntilRaw);
return AdminUserStatus(
email: user['email'] as String?,
bannedUntil: bannedUntilParsed == null
? null
: AppTime.toAppTime(bannedUntilParsed),
);
}
Future<dynamic> _invokeAdminFunction({
required String action,
required Map<String, dynamic> payload,
}) async {
final response = await _client.functions.invoke(
'admin_user_management',
body: {'action': action, ...payload},
);
if (response.status != 200) {
throw Exception(_extractErrorMessage(response.data));
}
return response.data;
}
String _extractErrorMessage(dynamic data) {
if (data is Map<String, dynamic>) {
final error = data['error'];
if (error is String && error.trim().isNotEmpty) {
return error;
}
final message = data['message'];
if (message is String && message.trim().isNotEmpty) {
return message;
}
}
return 'Admin request failed.';
}
}