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 "AV.ACL() called with a function. Did you forget ()?" ;
32+ }
33+ AV . _objectEach ( arg1 , function ( accessList , userId ) {
34+ if ( ! _ . isString ( userId ) ) {
35+ throw "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 "Tried to create an ACL with an invalid permission type." ;
41+ }
42+ if ( ! _ . isBoolean ( allowed ) ) {
43+ throw "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 "userId must be a string." ;
68+ }
69+ if ( ! _ . isBoolean ( allowed ) ) {
70+ throw "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 permissions [ 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 "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 "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 "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 "role must be a AV.Role or a String" ;
258+ } ;
259+ } ;
0 commit comments