-
Notifications
You must be signed in to change notification settings - Fork 8
/
schema.bolt
97 lines (73 loc) · 2.58 KB
/
schema.bolt
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
/* ************************************* FUNCTIONS ************************************* */
isValidSecurityType(it) { it == 'anonymous' || it == 'unverified' || it == 'verified' }
isExtantUser(id) { root.user[id] != null }
isExtantPoll(id) { root.poll[id] != null }
isAuthUser(id) { auth != null && auth.uid == id }
allowsAnonymousVotes(pollId) { root.poll[id].security == 'anonymous'}
allowsUnverifiedVotes(pollId) { root.poll[id].security == 'unverified' || root.poll[id].security == 'anonymous' }
userIsVerified() { auth != null && root.user_private[auth.uid].emailVerified == true }
/* ************************************* TYPES ************************************* */
type PollOption {
text: String;
color: String;
image: String|Null;
validate() { this.text.length <= 50 }
}
type Poll {
prompt: String;
options: PollOption[];
security: String;
isPublic: Boolean;
timeCreated: String;
timeEdited: String;
timeClosed: String|Null;
owner: String;
validate() { isValidSecurityType(this.security) && isExtantUser(this.owner) }
}
type Vote {
choices: String[];
owner: String;
timeCast: String;
validate() { this.choices.length > 0 && isExtantUser(this.owner) }
}
type UserPublicData {
displayName: String;
photoUrl: String|Null;
}
type UserPrivateData {
email: String;
emailVerified: String;
polls: Map<String, Boolean>;
votes: Map<String, String>;
}
/* ************************************* PATHS ************************************* */
path /poll {
read() { true }
}
path /poll/{pollId} is Poll {
//allow if an authenticated user is creating a new poll, or editing a poll they own
write(){ auth != null && (prior(this) == null || auth.uid == this.owner ) }
}
path /vote {
read() { true }
}
path /vote/{pollId}/{voteId} is Vote {
write() {
(prior(this) != null && auth != null && auth.uid == this.owner) || //always allow a user to edit an existing vote
prior(this) == null && ( //or if we're creating a new vote, allow if:
allowsAnonymousVotes(pollId) || // the poll allows anonymous votes, OR
(allowsUnverifiedVotes(pollId) && auth != null) || // poll allows unverified votes and user is authenticated, OR
userIsVerified() // the user is verified, thus can vote in any poll
)
}
}
path /user {
read() { true }
}
path /user/{id} is UserPublicData {
write() { isAuthUser(id) }
}
path /user_private/{id} is UserPrivateData {
read() { isAuthUser(id) }
write() { isAuthUser(id) }
}