@@ -114,30 +114,20 @@ Auth.prototype._loadRoles = function() {
114114 this . rolePromise = null ;
115115 return Promise . resolve ( this . userRoles ) ;
116116 }
117-
118- var roleIDs = results . map ( r => r . objectId ) ;
119- var promises = [ Promise . resolve ( roleIDs ) ] ;
117+ var rolesMap = results . reduce ( ( m , r ) => {
118+ m . names . push ( r . name ) ;
119+ m . ids . push ( r . objectId ) ;
120+ return m ;
121+ } , { ids : [ ] , names : [ ] } ) ;
122+ // Mount the initially queried roles
120123 var queriedRoles = { } ;
121- for ( var role of roleIDs ) {
122- promises . push ( this . _getAllRoleNamesForId ( role , queriedRoles ) ) ;
123- }
124- return Promise . all ( promises ) . then ( ( results ) => {
125- var allIDs = [ ] ;
126- for ( var x of results ) {
127- Array . prototype . push . apply ( allIDs , x ) ;
128- }
129- var restWhere = {
130- objectId : {
131- '$in' : allIDs
132- }
133- } ;
134- var query = new RestQuery ( this . config , master ( this . config ) ,
135- '_Role' , restWhere , { } ) ;
136- return query . execute ( ) ;
137- } ) . then ( ( response ) => {
138- var results = response . results ;
139- this . userRoles = results . map ( ( r ) => {
140- return 'role:' + r . name ;
124+
125+ // run the recursive finding
126+ var roleIDs = rolesMap . ids ;
127+ return this . _getAllRolesNamesForRoleIds ( roleIDs , rolesMap . names , queriedRoles )
128+ . then ( ( roleNames ) => {
129+ this . userRoles = roleNames . map ( ( r ) => {
130+ return 'role:' + r ;
141131 } ) ;
142132 this . fetchedRoles = true ;
143133 this . rolePromise = null ;
@@ -146,50 +136,54 @@ Auth.prototype._loadRoles = function() {
146136 } ) ;
147137} ;
148138
149- // Given a role object id, get any other roles it is part of
150- Auth . prototype . _getAllRoleNamesForId = function ( roleID , queriedRoles = { } ) {
151- // Don't need to requery this role as it is already being queried for.
152- if ( queriedRoles [ roleID ] != null ) {
153- return Promise . resolve ( [ ] ) ;
154- }
155- queriedRoles [ roleID ] = true ;
156- // As per documentation, a Role inherits AnotherRole
157- // if this Role is in the roles pointer of this AnotherRole
158- // Let's find all the roles where this role is in a roles relation
159- var rolePointer = {
139+ function parentRolesWhere ( roleID ) {
140+ let rolePointer = {
160141 __type : 'Pointer' ,
161142 className : '_Role' ,
162143 objectId : roleID
163144 } ;
164- var restWhere = {
145+ return {
165146 'roles' : rolePointer
166147 } ;
167- var query = new RestQuery ( this . config , master ( this . config ) , '_Role' ,
168- restWhere , { } ) ;
148+ }
149+
150+ // Given a list of roleIds, find all the parent roles, returns a promise with all names
151+ Auth . prototype . _getAllRolesNamesForRoleIds = function ( roleIDs , names = [ ] , queriedRoles = { } ) {
152+ let wheres = roleIDs . filter ( ( roleID ) => {
153+ return queriedRoles [ roleID ] !== true ;
154+ } ) . map ( ( roleID ) => {
155+ // mark as queried
156+ queriedRoles [ roleID ] = true ;
157+ return parentRolesWhere ( roleID ) ;
158+ } ) ;
159+
160+ // all roles are accounted for, return the names
161+ if ( wheres . length == 0 ) {
162+ return Promise . resolve ( [ ...new Set ( names ) ] ) ;
163+ }
164+ // Build an OR query across all parentRoles
165+ let restWhere = { '$or' : wheres } ;
166+ let query = new RestQuery ( this . config , master ( this . config ) , '_Role' , restWhere , { } ) ;
169167 return query . execute ( ) . then ( ( response ) => {
170168 var results = response . results ;
169+ // Nothing found
171170 if ( ! results . length ) {
172- return Promise . resolve ( [ ] ) ;
171+ return Promise . resolve ( names ) ;
173172 }
174- var roleIDs = results . map ( r => r . objectId ) ;
175-
176- // we found a list of roles where the roleID
177- // is referenced in the roles relation,
178- // Get the roles where those found roles are also
179- // referenced the same way
180- var parentRolesPromises = roleIDs . map ( ( roleId ) => {
181- return this . _getAllRoleNamesForId ( roleId , queriedRoles ) ;
182- } ) ;
183- parentRolesPromises . push ( Promise . resolve ( roleIDs ) ) ;
184- return Promise . all ( parentRolesPromises ) ;
185- } ) . then ( function ( results ) {
186- // Flatten
187- let roleIDs = results . reduce ( ( memo , result ) => {
188- return memo . concat ( result ) ;
189- } , [ ] ) ;
190- return Promise . resolve ( [ ...new Set ( roleIDs ) ] ) ;
191- } ) ;
192- } ;
173+ // Map the results with all Ids and names
174+ let resultMap = results . reduce ( ( memo , role ) => {
175+ memo . names . push ( role . name ) ;
176+ memo . ids . push ( role . objectId ) ;
177+ return memo ;
178+ } , { ids : [ ] , names : [ ] } ) ;
179+ // store the new found names
180+ names = names . concat ( resultMap . names ) ;
181+ // find the next ones, circular roles will be cut
182+ return this . _getAllRolesNamesForRoleIds ( resultMap . ids , names , queriedRoles )
183+ } ) . then ( ( names ) => {
184+ return Promise . resolve ( [ ...new Set ( names ) ] )
185+ } )
186+ }
193187
194188module . exports = {
195189 Auth : Auth ,
0 commit comments