Flutter Firebase规则管理插件firebase_rules的使用
Flutter Firebase规则管理插件firebase_rules的使用
firebase_rules
是一个类型安全的Firebase规则生成器,适用于Firestore、Storage和Realtime Database。它提供了一种在Dart中定义Firebase规则的方法,并通过代码补全和自定义lint规则来确保规则的质量。
功能特性
- 类型安全:为Firestore、Storage和Realtime Database创建规则时提供类型安全的环境。
- 自定义Lint规则:在部署前捕捉问题。
- 语法相似性:模仿Firebase规则语法,便于迁移。
- 易读性和维护性:规则更易于阅读和维护,并且可以在Realtime Database规则中添加注释。
限制
- Realtime Database规则不是真正类型的,但提供了代码补全的好处。
安装
为了防止潜在的问题,建议在一个专门的项目中创建规则。以下是安装步骤:
pubspec.yaml
dependencies:
firebase_rules: latest
# 如果你正在使用来自 `cloud_firestore_platform_interface` 的类型
firebase_rules_convert: latest
dev_dependencies:
build_runner: latest
firebase_rules_generator: latest
# 使用 `firebase_rules_linter`
custom_lint: latest
firebase_rules_linter: latest
analysis_options.yaml
# 使用 `firebase_rules_linter`
analyzer:
plugins:
- custom_lint
使用指南
注解
所有规则的起点是注解。Firestore、Storage和Database规则应分别定义在不同的文件中以避免冲突。
import 'package:firebase_rules/database.dart';
import 'package:firebase_rules/firebase.dart';
/// 创建Firestore规则
@FirebaseRules(service: Service.firestore)
final firestoreRules = [];
/// 创建Storage规则
@FirebaseRules(service: Service.storage)
final storageRules = [];
/// 创建Realtime Database规则
@DatabaseRules()
final databaseRules = [];
匹配规则(Matches)
现在可以开始定义匹配语句。
import 'package:firebase_rules/firebase.dart';
import 'shared.dart';
@FirebaseRules(service: Service.firestore)
final firestoreRules = [
Match<FirestoreResource>(
firestoreRoot,
matches: (database, request, resource) => [
Match<FirestoreResource<User>>(
'/users/{userId}',
rules: (userId, request, resource) => [],
),
Match<FirestoreResource>(
'/other/stuff',
rules: (_, request, resource) => [],
),
],
),
];
@FirebaseRules(service: Service.storage)
final storageRules = [
Match<StorageResource>(
storageRoot,
matches: (bucket, request, resource) => [
Match<StorageResource>(
'/images/{imageId}',
),
],
),
];
规则定义(Rules)
规则是核心部分。
import 'package:firebase_rules/firebase.dart';
import 'shared.dart';
@FirebaseRules(service: Service.firestore)
final firestoreRules = [
Match<FirestoreResource>(
firestoreRoot,
matches: (database, request, resource) => [
Match<FirestoreResource<User>>(
'/users/{userId}',
rules: (userId, request, resource) => [
Allow([Operation.read], resource.data.userId.rules() == userId),
],
),
],
),
];
规则语言
该包包含了一个用Dart重新实现的Firebase规则语言。这些调用将由生成器转换为正确的Firebase规则语法。
import 'package:firebase_rules/firebase.dart';
void example() {
''.rules().range(0, 1);
[].rules<RulesString>().concat([].rules());
rules.string(true);
rules.raw<bool>("foo.bar.baz == 'qux'");
}
函数
顶级函数可以用作规则函数。
import 'package:firebase_rules/firebase.dart';
bool isSignedIn() {
return request.auth?.uid != null;
}
@FirebaseRules(
service: Service.firestore,
functions: [isSignedIn],
)
final rules = [
Match<FirestoreResource>(firestoreRoot),
];
组织
匹配语句的任何函数参数都可以拆分以进行组织。
import 'package:firebase_rules/firebase.dart';
import 'shared.dart';
List<Match> detached(
RulesString database,
RulesRequest<FirestoreResource> request,
FirestoreResource resource,
) =>
[
Match<FirestoreResource<User>>(
'/users/{userId}',
rules: (userId, request, resource) => [
Allow([Operation.read], resource.data.userId.rules() == userId),
],
),
];
@FirebaseRules(service: Service.firestore)
final firestoreRules = [
Match<FirestoreResource>(firestoreRoot, matches: detached),
];
枚举
枚举可以通过生成器替换为原始字符串。
import 'package:firebase_rules/firebase.dart';
@FirebaseRules(
service: Service.firestore,
enums: [Test.map],
)
final firestoreRules = [
Match<FirestoreResource>(
firestoreRoot,
matches: (database, request, resource) => [
Match<FirestoreResource<TestResource>>(
'/test',
rules: (_, request, resource) => [
Allow([Operation.read], resource.data.test == Test.a),
],
),
],
),
];
enum Test { a, b, c }
abstract class TestResource {
Test get test;
}
生成规则
最后,可以运行生成器。
$ dart pub run build_runner build
对于每个rules.dart
文件,这将在同一目录下生成一个rules.rules
文件。将你的Firebase配置指向这个文件以使用规则。
Realtime Database规则
数据库规则与Firestore和Storage规则类似,但有一些不同之处:
- 第一个匹配必须以
rules
开头,这是数据库的根。 - 通配符用
$
表示。
import 'package:firebase_rules/database.dart';
@DatabaseRules()
final databaseRules = [
Match(
r'rules/users/$userId',
read: (userId) => auth != null && auth?.uid == userId,
write: (userId) => userId == 'user1'.rules(),
validate: (userId) => !data.exists(),
indexOn: ['uid', 'email'],
matches: (userId) => [
Match(
r'contracts/$contractId',
read: (contractId) =>
root.child('users'.rules()).child(userId).child(contractId).val<int?>() != null,
write: (contractId) =>
root.child('users'.rules()).child(userId).child(contractId).val() != null,
),
],
),
];
示例代码
以下是一个完整的示例,展示了如何使用firebase_rules
定义Firestore规则。
import 'package:firebase_rules/firebase.dart';
import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart';
bool isSignedIn(RulesRequest request) => request.auth != null;
bool isOwner(RulesRequest request, RulesString uid) {
final requestingUid = request.auth?.uid;
return requestingUid == uid;
}
@FirebaseRules(
service: Service.firestore,
functions: [isSignedIn, isOwner],
)
final firestoreRules = [
Match<FirestoreResource>(
firestoreRoot,
rules: (database, request, resource) => [
Allow([Operation.read], request.auth?.uid == 'god'.rules()),
],
matches: (database, request, resource) => [
Match<FirestoreResource<User>>(
'/users/{userId}',
rules: (userId, request, resource) => [
Allow([Operation.read], isSignedIn(request)),
Allow([Operation.create, Operation.update], isOwner(request, userId)),
],
),
Match<FirestoreResource<Content>>(
'/content/{contentId}',
rules: (contentId, request, resource) => [
Allow([Operation.read], isSignedIn(request) && resource.data.public),
Allow(
[Operation.write],
rules.firestore.get<User>(rules.path('/users/${request.auth?.uid}'.rules())).data.contentIds.rules<RulesString>().contains(contentId) &&
rules.firestore.exists(rules.path('/users/${request.auth?.uid}'.rules(), database: 'default')),
),
],
),
],
),
];
abstract class User {
List<String> get contentIds;
Blob get profileImage;
}
abstract class Content {
bool get public;
}
希望以上内容能帮助你更好地理解和使用firebase_rules
插件。如果有任何问题或需要进一步的帮助,请随时提问!
更多关于Flutter Firebase规则管理插件firebase_rules的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Firebase规则管理插件firebase_rules的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter项目中,管理Firebase实时数据库或Firestore的安全规则可以通过firebase_rules
插件来实现自动化和版本控制。虽然firebase_rules
插件本身并不直接提供命令行工具来部署规则,但它可以帮助你在项目中管理这些规则文件,并通过CI/CD流程部署它们。
以下是如何在Flutter项目中设置和使用firebase_rules
插件来管理Firebase安全规则的一个基本示例。
1. 安装firebase_rules插件
首先,确保你的Flutter项目已经初始化,并且位于项目根目录下。然后,在pubspec.yaml
文件中添加firebase_rules
依赖:
dependencies:
flutter:
sdk: flutter
# 其他依赖...
dev_dependencies:
firebase_rules: ^x.y.z # 替换为最新版本号
运行flutter pub get
来安装依赖。
2. 创建Firebase规则文件
在你的Flutter项目根目录下,创建一个名为firebase.rules
的文件,并在其中编写你的Firebase安全规则。例如,对于Firestore:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
3. 配置firebase_rules插件
在pubspec.yaml
文件中,配置firebase_rules
插件以指向你的规则文件:
firebase_rules:
rules: firebase.rules
4. 部署规则(手动或使用CI/CD)
虽然firebase_rules
插件本身不直接提供部署功能,但你可以使用Firebase CLI来部署这些规则。首先,确保你已经安装了Firebase CLI,并且已经通过firebase login
命令登录。
然后,在命令行中导航到你的Flutter项目根目录,并运行以下命令来初始化Firebase项目(如果尚未初始化):
firebase init
按照提示选择你的项目和其他配置选项。之后,你可以使用以下命令来部署Firebase规则:
firebase deploy --only firestore:rules
或者,如果你使用的是实时数据库:
firebase deploy --only database:rules
5. 自动化部署(可选)
为了自动化部署过程,你可以将上述部署命令集成到你的CI/CD管道中。例如,在GitHub Actions中,你可以创建一个工作流文件(.github/workflows/deploy-firebase-rules.yml
),并在其中添加如下步骤:
name: Deploy Firebase Rules
on:
push:
paths:
- 'firebase.rules'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install Firebase CLI
run: npm install -g firebase-tools
- name: Login to Firebase
run: firebase login --no-localhost
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
- name: Use Firebase CLI to deploy rules
run: firebase deploy --only firestore:rules
注意:在上面的GitHub Actions示例中,你需要创建一个名为FIREBASE_TOKEN
的仓库秘密,该秘密包含你的Firebase CLI登录令牌。你可以通过运行firebase login:ci
命令来获取这个令牌。
通过以上步骤,你就可以在Flutter项目中有效地管理和部署Firebase安全规则了。