refactor(admin): remove hardcoded email and dynamically resolve admin privileges via Firestore Admins collection
Build Android APK / Build Release APKs (push) Successful in 16m46s
Build Android APK / Build Release APKs (push) Successful in 16m46s
This commit is contained in:
+8
-1
@@ -10,7 +10,8 @@ service cloud.firestore {
|
|||||||
function isAdmin() {
|
function isAdmin() {
|
||||||
return request.auth != null && (
|
return request.auth != null && (
|
||||||
request.auth.token.admin == true ||
|
request.auth.token.admin == true ||
|
||||||
request.auth.token.email == 'nicolas@gruber.info'
|
exists(/databases/$(database)/documents/Admins/$(request.auth.uid)) ||
|
||||||
|
(request.auth.token.email != null && exists(/databases/$(database)/documents/Admins/$(request.auth.token.email)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,6 +23,12 @@ service cloud.firestore {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Admins-Sammlung: Angemeldete Nutzer können prüfen, nur Admins schreiben
|
||||||
|
match /Admins/{adminDoc} {
|
||||||
|
allow read: if isAuthenticated();
|
||||||
|
allow write: if isAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
// Öffentliche Sammlungen: News, Mängel (Issues) & Ideen (CitizensForum)
|
// Öffentliche Sammlungen: News, Mängel (Issues) & Ideen (CitizensForum)
|
||||||
match /{collection}/{document=**} {
|
match /{collection}/{document=**} {
|
||||||
// Jeder darf News, Mängel & Ideen öffentlich lesen
|
// Jeder darf News, Mängel & Ideen öffentlich lesen
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class AuthService extends ChangeNotifier {
|
class AuthService extends ChangeNotifier {
|
||||||
@@ -47,21 +48,64 @@ class AuthService extends ChangeNotifier {
|
|||||||
_initAuth();
|
_initAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const List<String> adminEmails = [
|
|
||||||
'nicolas@gruber.info',
|
|
||||||
];
|
|
||||||
|
|
||||||
Future<void> _checkAdminClaim(User? user) async {
|
Future<void> _checkAdminClaim(User? user) async {
|
||||||
if (user != null && !user.isAnonymous) {
|
if (user != null && !user.isAnonymous) {
|
||||||
final email = user.email?.trim().toLowerCase();
|
|
||||||
if (email != null && adminEmails.contains(email)) {
|
|
||||||
_isAdmin = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
|
// 1. Custom claims check (token.admin == true)
|
||||||
final tokenResult = await user.getIdTokenResult();
|
final tokenResult = await user.getIdTokenResult();
|
||||||
_isAdmin = tokenResult.claims?['admin'] == true;
|
if (tokenResult.claims?['admin'] == true) {
|
||||||
} catch (_) {
|
_isAdmin = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final firestore = FirebaseFirestore.instance;
|
||||||
|
|
||||||
|
// 2. Check Firestore 'Admins' collection by user UID (doc id)
|
||||||
|
final docByUid =
|
||||||
|
await firestore.collection('Admins').doc(user.uid).get();
|
||||||
|
if (docByUid.exists) {
|
||||||
|
_isAdmin = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Check Firestore 'Admins' collection by email (doc id)
|
||||||
|
final userEmail = user.email?.trim().toLowerCase();
|
||||||
|
if (userEmail != null && userEmail.isNotEmpty) {
|
||||||
|
final docByEmail =
|
||||||
|
await firestore.collection('Admins').doc(userEmail).get();
|
||||||
|
if (docByEmail.exists) {
|
||||||
|
_isAdmin = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Check Firestore 'Admins' collection where email field == userEmail
|
||||||
|
final queryByEmail = await firestore
|
||||||
|
.collection('Admins')
|
||||||
|
.where('email', isEqualTo: userEmail)
|
||||||
|
.limit(1)
|
||||||
|
.get();
|
||||||
|
if (queryByEmail.docs.isNotEmpty) {
|
||||||
|
_isAdmin = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Check Firestore 'Admins' collection where uid field == user.uid
|
||||||
|
final queryByUid = await firestore
|
||||||
|
.collection('Admins')
|
||||||
|
.where('uid', isEqualTo: user.uid)
|
||||||
|
.limit(1)
|
||||||
|
.get();
|
||||||
|
if (queryByUid.docs.isNotEmpty) {
|
||||||
|
_isAdmin = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isAdmin = false;
|
||||||
|
} catch (e) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint('Error checking admin status: $e');
|
||||||
|
}
|
||||||
_isAdmin = false;
|
_isAdmin = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-2
@@ -15,8 +15,7 @@ service firebase.storage {
|
|||||||
// Nur der Verfasser oder ein Admin darf sein Foto löschen
|
// Nur der Verfasser oder ein Admin darf sein Foto löschen
|
||||||
allow delete: if request.auth != null && (
|
allow delete: if request.auth != null && (
|
||||||
request.auth.uid == userId ||
|
request.auth.uid == userId ||
|
||||||
request.auth.token.admin == true ||
|
request.auth.token.admin == true
|
||||||
request.auth.token.email == 'nicolas@gruber.info'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user