@@ -8,11 +8,13 @@ import {
88 updateUserValidationBackendSchema ,
99} from '@user-office-software/duo-validation' ;
1010import * as bcrypt from 'bcryptjs' ;
11+ import { DateTime } from 'luxon' ;
1112import { inject , injectable } from 'tsyringe' ;
1213import { Args } from 'type-graphql' ;
1314
1415import { UserAuthorization } from '../auth/UserAuthorization' ;
1516import { Tokens } from '../config/Tokens' ;
17+ import { AdminDataSource } from '../datasources/AdminDataSource' ;
1618import { RedeemCodesDataSource } from '../datasources/RedeemCodesDataSource' ;
1719import { UserDataSource } from '../datasources/UserDataSource' ;
1820import { Authorized , EventBus , ValidateArgs } from '../decorators' ;
@@ -34,6 +36,7 @@ import {
3436 UpdateUserByOidcSubArgs ,
3537 UpdateUserByIdArgs ,
3638} from '../resolvers/mutations/UpdateUserMutation' ;
39+ import { UpsertUserByOidcSubArgs } from '../resolvers/mutations/UpsertUserMutation' ;
3740import { signToken , verifyToken } from '../utils/jwt' ;
3841import { ApolloServerErrorCodeExtended } from '../utils/utilTypes' ;
3942
@@ -42,6 +45,7 @@ export default class UserMutations {
4245 constructor (
4346 @inject ( Tokens . UserAuthorization ) private userAuth : UserAuthorization ,
4447 @inject ( Tokens . UserDataSource ) private dataSource : UserDataSource ,
48+ @inject ( Tokens . AdminDataSource ) private adminDataSource : AdminDataSource ,
4549 @inject ( Tokens . RedeemCodesDataSource )
4650 private redeemCodeDataSource : RedeemCodesDataSource
4751 ) { }
@@ -507,4 +511,84 @@ export default class UserMutations {
507511 ) : Promise < User | null > {
508512 return this . dataSource . setUserNotPlaceholder ( id ) ;
509513 }
514+
515+ @Authorized ( [ Roles . USER_OFFICER ] )
516+ async upsertUserByOidcSub (
517+ agent : UserWithRole | null ,
518+ args : UpsertUserByOidcSubArgs
519+ ) {
520+ const {
521+ userTitle,
522+ firstName,
523+ lastName,
524+ username,
525+ preferredName,
526+ oidcSub,
527+ gender,
528+ birthDate,
529+ institutionRoRId,
530+ department,
531+ position,
532+ email,
533+ telephone,
534+ } = args ;
535+
536+ const userWithOAuthSubMatch = await this . dataSource . getByOIDCSub ( oidcSub ) ;
537+
538+ let formattedBirthDate : DateTime | null = null ;
539+ formattedBirthDate = birthDate ? DateTime . fromISO ( birthDate ) : null ;
540+ if ( formattedBirthDate && ! formattedBirthDate . isValid ) {
541+ return rejection ( 'Invalid birth date format' , { birthDate, args } ) ;
542+ }
543+
544+ // Fetch Institution ID from ROR ID
545+ const institution =
546+ await this . adminDataSource . getInstitutionByRorId ( institutionRoRId ) ;
547+
548+ if ( userWithOAuthSubMatch ) {
549+ const updatedUser = await this . dataSource . update ( {
550+ ...userWithOAuthSubMatch ,
551+ birthdate : formattedBirthDate ?. toJSDate ( ) ,
552+ department : department ?? undefined ,
553+ email,
554+ firstname : firstName ,
555+ username : username ?? undefined ,
556+ gender : gender ?? undefined ,
557+ lastname : lastName ,
558+ oidcSub : oidcSub ,
559+ institutionId : institution ?. id ,
560+ position : position ,
561+ preferredname : preferredName ?? undefined ,
562+ telephone : telephone ?? undefined ,
563+ user_title : userTitle ?? undefined ,
564+ } ) ;
565+
566+ return updatedUser ;
567+ } else {
568+ const newUser = await this . dataSource . create (
569+ userTitle ?? '' ,
570+ firstName ,
571+ lastName ,
572+ username ?? '' ,
573+ preferredName ?? '' ,
574+ oidcSub ,
575+ '' ,
576+ '' ,
577+ gender ?? '' ,
578+ formattedBirthDate ?. toJSDate ( ) ?? new Date ( ) ,
579+ institution ?. id ?? undefined ,
580+ department ?? '' ,
581+ position ,
582+ email ,
583+ telephone ?? ''
584+ ) ;
585+
586+ await this . dataSource . addUserRole ( {
587+ userID : newUser . id ,
588+ roleID : UserRole . USER ,
589+ } ) ;
590+
591+ return newUser ;
592+ }
593+ }
510594}
0 commit comments