@@ -25,7 +25,7 @@ type StfcRolesToEssRole = { [key: string]: Roles[] };
2525/*
2626 * Must not contain user role, this is appended at the very last step.
2727 */
28- const stfcRolesToEssRoleDefinitions : StfcRolesToEssRole = {
28+ const stfcRolesToSystemRoleDefinitions : StfcRolesToEssRole = {
2929 'User Officer' : [ Roles . USER_OFFICER , Roles . INSTRUMENT_SCIENTIST ] ,
3030 'ISIS Instrument Scientist' : [ Roles . INSTRUMENT_SCIENTIST ] ,
3131 'CLF Artemis FAP Secretary' : [ Roles . INSTRUMENT_SCIENTIST ] ,
@@ -395,7 +395,40 @@ export class StfcUserDataSource implements UserDataSource {
395395 }
396396
397397 async setUserRoles ( id : number , roles : number [ ] ) : Promise < void > {
398- throw new Error ( 'Method not implemented.' ) ;
398+ try {
399+ const roleDefinitions = await this . getRoles ( ) ;
400+ if ( ! roleDefinitions ) {
401+ throw new Error ( 'Role definitions not set up in the system' ) ;
402+ }
403+ const userRole : Role | undefined = roleDefinitions . find (
404+ ( role ) => role . shortCode == Roles . USER
405+ ) ;
406+ const stfcRoles = await this . getRolesForUser ( id ) ;
407+
408+ const assignedRoleIds = new Set (
409+ this . mapStfcRolesToSystemRoleDefinitions (
410+ stfcRoles ,
411+ roleDefinitions
412+ ) . map ( ( r ) => r . id )
413+ ) ;
414+ const newRolesToAssign = Array . from ( new Set ( roles ) ) . filter (
415+ ( roleId ) => ! assignedRoleIds . has ( roleId ) && roleId !== userRole ?. id
416+ ) ;
417+
418+ if ( newRolesToAssign . length > 0 ) {
419+ await postgresUserDataSource . setUserRoles ( id , newRolesToAssign ) ;
420+ this . stfcRolesCache . remove ( String ( id ) ) ;
421+ this . uopRolesCache . remove ( String ( id ) ) ;
422+ }
423+
424+ return ;
425+ } catch ( error ) {
426+ logger . logError ( 'Error setting user roles in' , {
427+ error,
428+ userId : id ,
429+ } ) ;
430+ throw error ;
431+ }
399432 }
400433 async getRolesForUser ( id : number ) : Promise < RoleDTO [ ] > {
401434 const cachedRoles = this . stfcRolesCache . get ( String ( id ) ) ;
@@ -417,63 +450,68 @@ export class StfcUserDataSource implements UserDataSource {
417450
418451 return stfcRawRolesRequest ! ;
419452 }
420-
421453 async getUserRoles ( id : number ) : Promise < Role [ ] > {
422454 const cachedRoles = this . uopRolesCache . get ( String ( id ) ) ;
423455 if ( cachedRoles ) {
424456 return cachedRoles ;
425457 }
426458
427- const stfcRawRolesRequest = this . getRolesForUser ( id ) ;
459+ const roleDefinitions = await this . getRoles ( ) ;
460+ if ( ! roleDefinitions ) {
461+ return [ ] ;
462+ }
428463
429- const stfcRolesRequest = stfcRawRolesRequest . then ( ( stfcRoles ) => {
430- return this . getRoles ( ) . then ( ( roleDefinitions ) => {
431- const userRole : Role | undefined = roleDefinitions . find (
432- ( role ) => role . shortCode == Roles . USER
433- ) ;
434- if ( ! userRole ) {
435- return [ ] ;
436- }
464+ const [ assignedSystemUserRoles , stfcRoles ] = await Promise . all ( [
465+ postgresUserDataSource . getUserRoles ( id ) ,
466+ this . getRolesForUser ( id ) ,
467+ ] ) ;
437468
438- if ( ! stfcRoles || stfcRoles . length == 0 ) {
439- return [ userRole ] ;
440- }
469+ const userRole : Role | undefined = roleDefinitions . find (
470+ ( role ) => role . shortCode == Roles . USER
471+ ) ;
472+ if ( ! userRole ) {
473+ return [ ] ;
474+ }
441475
442- /*
443- * Convert the STFC roles to the Roles enums which refers to roles
444- * by short code. We will use the short code to filter relevant
445- * roles.
446- */
447- const userRolesAsEnum : Roles [ ] = stfcRoles
448- . flatMap ( ( stfcRole ) => stfcRolesToEssRoleDefinitions [ stfcRole . name ! ] )
449- . filter ( ( r ) => r !== undefined ) as Roles [ ] ;
450-
451- /*
452- * Filter relevant roles by short code.
453- */
454- const userRolesAsRole : Role [ ] = userRolesAsEnum
455- . map ( ( r ) => roleDefinitions . find ( ( d ) => d . shortCode === r ) )
456- . filter ( ( r ) => r !== undefined ) as Role [ ] ;
457-
458- /*
459- * We can't return non-unique roles.
460- */
461- const uniqueRoles : Role [ ] = [ ...new Set ( userRolesAsRole ) ] ;
462-
463- uniqueRoles . sort ( ( a , b ) => a . id - b . id ) ;
464-
465- /*
466- * Prepend the user role as it must be first.
467- */
468- const userRoles = [ userRole , ...uniqueRoles ] ;
469-
470- return userRoles ;
471- } ) ;
472- } ) ;
476+ if ( ! stfcRoles || stfcRoles . length == 0 ) {
477+ return [ userRole ] ;
478+ }
479+
480+ const externalRoles = this . mapStfcRolesToSystemRoleDefinitions (
481+ stfcRoles ,
482+ roleDefinitions
483+ ) ;
484+
485+ const combinedUserRoles = [ ...externalRoles , ...assignedSystemUserRoles ] ;
486+
487+ const uniqueRoles : Role [ ] = [ ...new Set ( combinedUserRoles ) ] ;
488+
489+ uniqueRoles . sort ( ( a , b ) => a . id - b . id ) ;
490+
491+ const userRoles = [ userRole , ...uniqueRoles ] ;
492+
493+ this . uopRolesCache . put ( String ( id ) , Promise . resolve ( userRoles ) ) ;
494+
495+ return userRoles ;
496+ }
497+
498+ private mapStfcRolesToSystemRoleDefinitions (
499+ stfcRoles : RoleDTO [ ] | undefined ,
500+ roleDefinitions : Role [ ]
501+ ) : Role [ ] {
502+ if ( ! stfcRoles ?. length ) {
503+ return [ ] ;
504+ }
505+
506+ const userRolesAsEnum : Roles [ ] = stfcRoles
507+ . flatMap ( ( stfcRole ) => stfcRolesToSystemRoleDefinitions [ stfcRole . name ! ] )
508+ . filter ( ( r ) => r !== undefined ) as Roles [ ] ;
473509
474- this . uopRolesCache . put ( String ( id ) , stfcRolesRequest ) ;
510+ const mappedRoles : Role [ ] = userRolesAsEnum
511+ . map ( ( r ) => roleDefinitions . find ( ( d ) => d . shortCode === r ) )
512+ . filter ( ( r ) => r !== undefined ) as Role [ ] ;
475513
476- return stfcRolesRequest ;
514+ return mappedRoles ;
477515 }
478516
479517 async getRoles ( ) : Promise < Role [ ] > {
0 commit comments