我是 Flutter x Firebase 的初学者,过去三天一直被困在这里。请帮我解决这个问题,并解释一下原因
/Firestore(30190): (25.0.0) [Firestore]: 侦听查询(target=Query( collectionGroup=leaves where status==pending order by name);limitType=LIMIT_TO_FIRST) 失败: Status{code=PERMISSION_DENIED ,描述=权限缺失或不足。,原因=空}
我的代码:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class AdminDashboardScreen extends StatefulWidget {
const AdminDashboardScreen({super.key});
@override
_AdminDashboardScreenState createState() => _AdminDashboardScreenState();
}
class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
bool isAdmin = false;
Future<bool> _isAdmin(String uid) async {
var doc = await FirebaseFirestore.instance.collection('admins').doc(uid).get();
return doc.exists;
}
@override
void initState() {
super.initState();
_checkIfAdmin();
}
Future<void> _checkIfAdmin() async {
String uid = FirebaseAuth.instance.currentUser!.uid;
bool admin = await _isAdmin(uid);
setState(() {
isAdmin = admin;
});
}
@override
Widget build(BuildContext context) {
if (!isAdmin) {
return Scaffold(
appBar: AppBar(
title: Text('Admin Panel'),
),
body: Center(child: Text('You do not have admin privileges.')),
);
}
return Scaffold(
appBar: AppBar(
title: Text('Admin Panel'),
),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collectionGroup('leaves')
.where('status', isEqualTo: 'pending').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
return Center(child: Text('No pending leave requests.'));
}
var leaveRequests = snapshot.data!.docs;
return ListView.builder(
itemCount: leaveRequests.length,
itemBuilder: (context, index) {
var leave = leaveRequests[index];
return ListTile(
title: Text('${leave['studentName']} is requesting for a leave'),
subtitle: Text('Reason: ${leave['reason']}'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.check),
onPressed: () => _updateLeaveStatus(leave, 'approved'),
),
IconButton(
icon: Icon(Icons.close),
onPressed: () => _updateLeaveStatus(leave, 'rejected'),
),
],
),
);
},
);
},
),
);
}
void _updateLeaveStatus(QueryDocumentSnapshot leave, String status) async {
try {
await leave.reference.update({'status': status});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Leave request $status')));
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Error updating status: $e')));
}
}
}
我的数据库安全规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated users to read/write their own documents
match /students/{studentId}/{documents=**} {
allow read, write: if request.auth != null && request.auth.uid == studentId;
}
// Admin collection
match /admins/{adminId} {
allow read, write: if request.auth != null && request.auth.uid == adminId;
}
// Allow admins to read and write any student data
match /students/{studentId}/{documents=**} {
allow read, write: if request.auth != null && isAdmin(request.auth.uid);
}
}
}
您的安全规则也在此处调用
isAdmin
函数:
match /students/{studentId}/{documents=**} {
allow read, write: if request.auth != null && isAdmin(request.auth.uid);
}
isAdmin
未在您显示的安全规则中定义,因此调用将失败。请记住,您的安全规则在 Flutter 代码之外的其他地方运行,因此规则无法调用 Flutter 代码中的函数。
如果您希望安全规则能够测试某人是否是管理员,您还必须在规则中编写
isAdmin
实现。