1
+ 'use strict' ;
2
+
3
+ var _ = require ( 'underscore' ) ;
4
+
5
+ module . exports = function ( AV ) {
6
+ var PUBLIC_KEY = "*" ;
7
+
8
+ /**
9
+ * Creates a new ACL.
10
+ * If no argument is given, the ACL has no permissions for anyone.
11
+ * If the argument is a AV.User, the ACL will have read and write
12
+ * permission for only that user.
13
+ * If the argument is any other JSON object, that object will be interpretted
14
+ * as a serialized ACL created with toJSON().
15
+ * @see AV.Object#setACL
16
+ * @class
17
+ *
18
+ * <p>An ACL, or Access Control List can be added to any
19
+ * <code>AV.Object</code> to restrict access to only a subset of users
20
+ * of your application.</p>
21
+ */
22
+ AV . ACL = function ( arg1 ) {
23
+ var self = this ;
24
+ self . permissionsById = { } ;
25
+ if ( _ . isObject ( arg1 ) ) {
26
+ if ( arg1 instanceof AV . User ) {
27
+ self . setReadAccess ( arg1 , true ) ;
28
+ self . setWriteAccess ( arg1 , true ) ;
29
+ } else {
30
+ if ( _ . isFunction ( arg1 ) ) {
31
+ throw new Error ( 'AV.ACL() called with a function. Did you forget ()?' ) ;
32
+ }
33
+ AV . _objectEach ( arg1 , function ( accessList , userId ) {
34
+ if ( ! _ . isString ( userId ) ) {
35
+ throw new Error ( 'Tried to create an ACL with an invalid userId.' ) ;
36
+ }
37
+ self . permissionsById [ userId ] = { } ;
38
+ AV . _objectEach ( accessList , function ( allowed , permission ) {
39
+ if ( permission !== "read" && permission !== "write" ) {
40
+ throw new Error ( 'Tried to create an ACL with an invalid permission type.' ) ;
41
+ }
42
+ if ( ! _ . isBoolean ( allowed ) ) {
43
+ throw new Error ( 'Tried to create an ACL with an invalid permission value.' ) ;
44
+ }
45
+ self . permissionsById [ userId ] [ permission ] = allowed ;
46
+ } ) ;
47
+ } ) ;
48
+ }
49
+ }
50
+ } ;
51
+
52
+ /**
53
+ * Returns a JSON-encoded version of the ACL.
54
+ * @return {Object }
55
+ */
56
+ AV . ACL . prototype . toJSON = function ( ) {
57
+ return _ . clone ( this . permissionsById ) ;
58
+ } ;
59
+
60
+ AV . ACL . prototype . _setAccess = function ( accessType , userId , allowed ) {
61
+ if ( userId instanceof AV . User ) {
62
+ userId = userId . id ;
63
+ } else if ( userId instanceof AV . Role ) {
64
+ userId = "role:" + userId . getName ( ) ;
65
+ }
66
+ if ( ! _ . isString ( userId ) ) {
67
+ throw new Error ( 'userId must be a string.' ) ;
68
+ }
69
+ if ( ! _ . isBoolean ( allowed ) ) {
70
+ throw new Error ( 'allowed must be either true or false.' ) ;
71
+ }
72
+ var permissions = this . permissionsById [ userId ] ;
73
+ if ( ! permissions ) {
74
+ if ( ! allowed ) {
75
+ // The user already doesn't have this permission, so no action needed.
76
+ return ;
77
+ } else {
78
+ permissions = { } ;
79
+ this . permissionsById [ userId ] = permissions ;
80
+ }
81
+ }
82
+
83
+ if ( allowed ) {
84
+ this . permissionsById [ userId ] [ accessType ] = true ;
85
+ } else {
86
+ delete permissions [ accessType ] ;
87
+ if ( _ . isEmpty ( permissions ) ) {
88
+ delete this . permissionsById [ userId ] ;
89
+ }
90
+ }
91
+ } ;
92
+
93
+ AV . ACL . prototype . _getAccess = function ( accessType , userId ) {
94
+ if ( userId instanceof AV . User ) {
95
+ userId = userId . id ;
96
+ } else if ( userId instanceof AV . Role ) {
97
+ userId = "role:" + userId . getName ( ) ;
98
+ }
99
+ var permissions = this . permissionsById [ userId ] ;
100
+ if ( ! permissions ) {
101
+ return false ;
102
+ }
103
+ return permissions [ accessType ] ? true : false ;
104
+ } ;
105
+
106
+ /**
107
+ * Set whether the given user is allowed to read this object.
108
+ * @param userId An instance of AV.User or its objectId.
109
+ * @param {Boolean } allowed Whether that user should have read access.
110
+ */
111
+ AV . ACL . prototype . setReadAccess = function ( userId , allowed ) {
112
+ this . _setAccess ( "read" , userId , allowed ) ;
113
+ } ;
114
+
115
+ /**
116
+ * Get whether the given user id is *explicitly* allowed to read this object.
117
+ * Even if this returns false, the user may still be able to access it if
118
+ * getPublicReadAccess returns true or a role that the user belongs to has
119
+ * write access.
120
+ * @param userId An instance of AV.User or its objectId, or a AV.Role.
121
+ * @return {Boolean }
122
+ */
123
+ AV . ACL . prototype . getReadAccess = function ( userId ) {
124
+ return this . _getAccess ( "read" , userId ) ;
125
+ } ;
126
+
127
+ /**
128
+ * Set whether the given user id is allowed to write this object.
129
+ * @param userId An instance of AV.User or its objectId, or a AV.Role..
130
+ * @param {Boolean } allowed Whether that user should have write access.
131
+ */
132
+ AV . ACL . prototype . setWriteAccess = function ( userId , allowed ) {
133
+ this . _setAccess ( "write" , userId , allowed ) ;
134
+ } ;
135
+
136
+ /**
137
+ * Get whether the given user id is *explicitly* allowed to write this object.
138
+ * Even if this returns false, the user may still be able to write it if
139
+ * getPublicWriteAccess returns true or a role that the user belongs to has
140
+ * write access.
141
+ * @param userId An instance of AV.User or its objectId, or a AV.Role.
142
+ * @return {Boolean }
143
+ */
144
+ AV . ACL . prototype . getWriteAccess = function ( userId ) {
145
+ return this . _getAccess ( "write" , userId ) ;
146
+ } ;
147
+
148
+ /**
149
+ * Set whether the public is allowed to read this object.
150
+ * @param {Boolean } allowed
151
+ */
152
+ AV . ACL . prototype . setPublicReadAccess = function ( allowed ) {
153
+ this . setReadAccess ( PUBLIC_KEY , allowed ) ;
154
+ } ;
155
+
156
+ /**
157
+ * Get whether the public is allowed to read this object.
158
+ * @return {Boolean }
159
+ */
160
+ AV . ACL . prototype . getPublicReadAccess = function ( ) {
161
+ return this . getReadAccess ( PUBLIC_KEY ) ;
162
+ } ;
163
+
164
+ /**
165
+ * Set whether the public is allowed to write this object.
166
+ * @param {Boolean } allowed
167
+ */
168
+ AV . ACL . prototype . setPublicWriteAccess = function ( allowed ) {
169
+ this . setWriteAccess ( PUBLIC_KEY , allowed ) ;
170
+ } ;
171
+
172
+ /**
173
+ * Get whether the public is allowed to write this object.
174
+ * @return {Boolean }
175
+ */
176
+ AV . ACL . prototype . getPublicWriteAccess = function ( ) {
177
+ return this . getWriteAccess ( PUBLIC_KEY ) ;
178
+ } ;
179
+
180
+ /**
181
+ * Get whether users belonging to the given role are allowed
182
+ * to read this object. Even if this returns false, the role may
183
+ * still be able to write it if a parent role has read access.
184
+ *
185
+ * @param role The name of the role, or a AV.Role object.
186
+ * @return {Boolean } true if the role has read access. false otherwise.
187
+ * @throws {String } If role is neither a AV.Role nor a String.
188
+ */
189
+ AV . ACL . prototype . getRoleReadAccess = function ( role ) {
190
+ if ( role instanceof AV . Role ) {
191
+ // Normalize to the String name
192
+ role = role . getName ( ) ;
193
+ }
194
+ if ( _ . isString ( role ) ) {
195
+ return this . getReadAccess ( "role:" + role ) ;
196
+ }
197
+ throw new Error ( 'role must be a AV.Role or a String' ) ;
198
+ } ;
199
+
200
+ /**
201
+ * Get whether users belonging to the given role are allowed
202
+ * to write this object. Even if this returns false, the role may
203
+ * still be able to write it if a parent role has write access.
204
+ *
205
+ * @param role The name of the role, or a AV.Role object.
206
+ * @return {Boolean } true if the role has write access. false otherwise.
207
+ * @throws {String } If role is neither a AV.Role nor a String.
208
+ */
209
+ AV . ACL . prototype . getRoleWriteAccess = function ( role ) {
210
+ if ( role instanceof AV . Role ) {
211
+ // Normalize to the String name
212
+ role = role . getName ( ) ;
213
+ }
214
+ if ( _ . isString ( role ) ) {
215
+ return this . getWriteAccess ( "role:" + role ) ;
216
+ }
217
+ throw new Error ( 'role must be a AV.Role or a String' ) ;
218
+ } ;
219
+
220
+ /**
221
+ * Set whether users belonging to the given role are allowed
222
+ * to read this object.
223
+ *
224
+ * @param role The name of the role, or a AV.Role object.
225
+ * @param {Boolean } allowed Whether the given role can read this object.
226
+ * @throws {String } If role is neither a AV.Role nor a String.
227
+ */
228
+ AV . ACL . prototype . setRoleReadAccess = function ( role , allowed ) {
229
+ if ( role instanceof AV . Role ) {
230
+ // Normalize to the String name
231
+ role = role . getName ( ) ;
232
+ }
233
+ if ( _ . isString ( role ) ) {
234
+ this . setReadAccess ( "role:" + role , allowed ) ;
235
+ return ;
236
+ }
237
+ throw new Error ( 'role must be a AV.Role or a String' ) ;
238
+ } ;
239
+
240
+ /**
241
+ * Set whether users belonging to the given role are allowed
242
+ * to write this object.
243
+ *
244
+ * @param role The name of the role, or a AV.Role object.
245
+ * @param {Boolean } allowed Whether the given role can write this object.
246
+ * @throws {String } If role is neither a AV.Role nor a String.
247
+ */
248
+ AV . ACL . prototype . setRoleWriteAccess = function ( role , allowed ) {
249
+ if ( role instanceof AV . Role ) {
250
+ // Normalize to the String name
251
+ role = role . getName ( ) ;
252
+ }
253
+ if ( _ . isString ( role ) ) {
254
+ this . setWriteAccess ( "role:" + role , allowed ) ;
255
+ return ;
256
+ }
257
+ throw new Error ( 'role must be a AV.Role or a String' ) ;
258
+ } ;
259
+ } ;
0 commit comments