@@ -114,30 +114,17 @@ Auth.prototype._loadRoles = function() {
114114 this . rolePromise = null ;
115115 return Promise . resolve ( this . userRoles ) ;
116116 }
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 : [ ] } ) ;
117122
118- var roleIDs = results . map ( r => r . objectId ) ;
119- var promises = [ Promise . resolve ( roleIDs ) ] ;
120- 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 ;
123+ // run the recursive finding
124+ return this . _getAllRolesNamesForRoleIds ( rolesMap . ids , rolesMap . names )
125+ . then ( ( roleNames ) => {
126+ this . userRoles = roleNames . map ( ( r ) => {
127+ return 'role:' + r ;
141128 } ) ;
142129 this . fetchedRoles = true ;
143130 this . rolePromise = null ;
@@ -146,50 +133,52 @@ Auth.prototype._loadRoles = function() {
146133 } ) ;
147134} ;
148135
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 ( [ ] ) ;
136+ // Given a list of roleIds, find all the parent roles, returns a promise with all names
137+ Auth . prototype . _getAllRolesNamesForRoleIds = function ( roleIDs , names = [ ] , queriedRoles = { } ) {
138+ let ins = roleIDs . filter ( ( roleID ) => {
139+ return queriedRoles [ roleID ] !== true ;
140+ } ) . map ( ( roleID ) => {
141+ // mark as queried
142+ queriedRoles [ roleID ] = true ;
143+ return {
144+ __type : 'Pointer' ,
145+ className : '_Role' ,
146+ objectId : roleID
147+ }
148+ } ) ;
149+
150+ // all roles are accounted for, return the names
151+ if ( ins . length == 0 ) {
152+ return Promise . resolve ( [ ...new Set ( names ) ] ) ;
154153 }
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 = {
160- __type : 'Pointer' ,
161- className : '_Role' ,
162- objectId : roleID
163- } ;
164- var restWhere = {
165- 'roles' : rolePointer
166- } ;
167- var query = new RestQuery ( this . config , master ( this . config ) , '_Role' ,
168- restWhere , { } ) ;
154+ // Build an OR query across all parentRoles
155+ let restWhere ;
156+ if ( ins . length == 1 ) {
157+ restWhere = { 'roles' : ins [ 0 ] } ;
158+ } else {
159+ restWhere = { 'roles' : { '$in' : ins } }
160+ }
161+ let query = new RestQuery ( this . config , master ( this . config ) , '_Role' , restWhere , { } ) ;
169162 return query . execute ( ) . then ( ( response ) => {
170163 var results = response . results ;
164+ // Nothing found
171165 if ( ! results . length ) {
172- return Promise . resolve ( [ ] ) ;
166+ return Promise . resolve ( names ) ;
173167 }
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- } ;
168+ // Map the results with all Ids and names
169+ let resultMap = results . reduce ( ( memo , role ) => {
170+ memo . names . push ( role . name ) ;
171+ memo . ids . push ( role . objectId ) ;
172+ return memo ;
173+ } , { ids : [ ] , names : [ ] } ) ;
174+ // store the new found names
175+ names = names . concat ( resultMap . names ) ;
176+ // find the next ones, circular roles will be cut
177+ return this . _getAllRolesNamesForRoleIds ( resultMap . ids , names , queriedRoles )
178+ } ) . then ( ( names ) => {
179+ return Promise . resolve ( [ ...new Set ( names ) ] )
180+ } )
181+ }
193182
194183module . exports = {
195184 Auth : Auth ,
0 commit comments