-
Notifications
You must be signed in to change notification settings - Fork 6
/
rules.yaml
111 lines (107 loc) · 3.75 KB
/
rules.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# Copyright 2015 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
functions:
- isLoggedIn(): auth.uid !== null
- userIs(user): auth.uid === user
# A user can create an ownership field with themself as the contents, or they
# can give away ownership. The ownership field must always contain a known user.
- ownershipField(): root.users[next].exists() && ((!prev.exists() && userIs(next)) || userIs(prev))
# A creator field irrevocably identifies the user who created it.
- creatorField(): root.users[next].exists() && !prev.exists() && userIs(next)
schema:
type: object
properties:
users:
type: object
$user:
type: object
constraint: userIs($user)
properties:
name: {type: string}
organizations:
type: object
$orgId:
type: boolean
constraint: (root.organizations[$orgId].exists() && next === true) || !next.exists()
organizations:
type: object
# The orgId is derived from the initial name of the organization, and is used in URLs.
$orgId:
type: object
required: [owner, name]
properties:
owner:
type: string
# The owner must be a user.
constraint: ownershipField()
name:
type: string
constraint: userIs(next.parent().owner)
# Holds an organization's polls in the rough order they were added, separate
# from the organization metadata. Avoiding a wildchild under the
# organization itself lets us create organizations atomically
organizationPolls:
type: object
$orgId:
type: object
constraint: root.organizations[$orgId].exists()
$index:
type: string
constraint: root.polls[next].organization == $orgId
polls:
type: object
# The pollId is derived from the initial name of the poll, and is used in URLs.
$pollId:
type: object
required: [name, organization, state]
properties:
owner:
type: string
# The owner must be a user.
constraint: ownershipField()
name: { type: string }
organization:
type: string
constraint: !prev.exists() && root.organizations[next].exists()
state:
type: string
enum: [creating, open, closed]
pollOptions:
type: object
$pollId:
type: object
constraint: root.polls[$pollId].exists()
$optionId: # A push ID.
type: object
properties:
author:
type: string
constraint: ownershipField()
value: { type: string }
# Split from polls so we can retrieve metadata without retrieving all the votes.
pollVotes:
type: object
$pollId:
type: object
constraint: root.polls[$pollId].exists()
$voter: # A user ID.
# A vote is a json string holding an array of arrays of
# $optionIds. This isn't interpreted at the Firebase level: if you
# want to write an invalid vote, go ahead.
type: string
constraint: userIs($voter) && root.users[$voter].exists()
access:
- location: /
read: true
write: true && isLoggedIn()