Skip to content

Commit 1e37cdd

Browse files
Merge pull request #96 from Amruth-Vamshi/feature/login-with-unique-id
2 parents 469c047 + 46b8f7d commit 1e37cdd

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

src/api/api.controller.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {
1717
SignupResponse,
1818
UserRegistration,
1919
UsersResponse,
20+
ResponseCode,
21+
ResponseStatus
2022
} from './api.interface';
2123
import { ApiService } from './api.service';
2224
import { ConfigResolverService } from './config.resolver.service';
@@ -27,10 +29,12 @@ import { RefreshRequest } from '@fusionauth/typescript-client/build/src/FusionAu
2729
import { ChangePasswordDTO } from './dto/changePassword.dto';
2830
import { SentryInterceptor } from '../interceptors/sentry.interceptor';
2931
import * as Sentry from '@sentry/node';
30-
import { LoginDto } from './dto/login.dto';
32+
import { LoginDto, LoginWithUniqueIdDto } from './dto/login.dto';
3133
import { SendOtpDto } from './dto/send-otp.dto';
3234
import { VerifyOtpDto } from './dto/verify-otp.dto';
3335
import { Throttle, SkipThrottle} from '@nestjs/throttler';
36+
import { ConfigService } from '@nestjs/config';
37+
import { v4 as uuidv4 } from 'uuid';
3438
// eslint-disable-next-line @typescript-eslint/no-var-requires
3539
const CryptoJS = require('crypto-js');
3640

@@ -40,6 +44,7 @@ CryptoJS.lib.WordArray.words;
4044
@UseInterceptors(SentryInterceptor)
4145
export class ApiController {
4246
constructor(
47+
private configService: ConfigService,
4348
private readonly fusionAuthService: FusionauthService,
4449
private readonly otpService: OtpService,
4550
private readonly apiService: ApiService,
@@ -358,4 +363,22 @@ export class ApiController {
358363
): Promise<any> {
359364
return await this.apiService.loginWithOtp(user, authHeader);
360365
}
366+
367+
@Post('login-with-unique-id')
368+
@UsePipes(new ValidationPipe({ transform: true }))
369+
async loginWithUniqueId(
370+
@Body() user: LoginWithUniqueIdDto,
371+
@Headers('authorization') authHeader,
372+
@Headers('ADMIN-API-KEY') adminApiKey
373+
): Promise<any> {
374+
if(adminApiKey!=this.configService.get('ADMIN_API_KEY')){
375+
const response: SignupResponse = new SignupResponse().init(uuidv4());
376+
response.responseCode = ResponseCode.FAILURE;
377+
response.params.err = 'UNAUTHORIZED';
378+
response.params.errMsg = 'Invalid admin api key';
379+
response.params.status = ResponseStatus.failure;
380+
return response;
381+
}
382+
return await this.apiService.loginWithUniqueId(user, authHeader);
383+
}
361384
}

src/api/api.service.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const CryptoJS = require('crypto-js');
3030
// eslint-disable-next-line @typescript-eslint/no-var-requires
3131
const AES = require('crypto-js/aes');
3232
import Flagsmith from 'flagsmith-nodejs';
33+
import { LoginWithUniqueIdDto } from './dto/login.dto';
3334

3435
CryptoJS.lib.WordArray.words;
3536

@@ -637,6 +638,56 @@ export class ApiService {
637638
}
638639
}
639640

641+
async loginWithUniqueId(loginDto: LoginWithUniqueIdDto, authHeader: null | string): Promise<SignupResponse> {
642+
/* Execution flow
643+
1. Check if user exists for the given applicationId and loginId.
644+
3.1. If existing user, login user with default password.
645+
3.2. If new user, register to this application.
646+
4. Send login response with the token
647+
*/
648+
const salt = this.configResolverService.getSalt(loginDto.applicationId);
649+
let password = salt + this.configService.get("DEFAULT_USER_PASSWORD"); // mix OTP with salt
650+
console.log(password)
651+
652+
const {
653+
statusFA
654+
}: { statusFA: FAStatus} =
655+
await this.fusionAuthService.getUser(
656+
loginDto.loginId,
657+
loginDto.applicationId,
658+
authHeader,
659+
);
660+
if (statusFA === FAStatus.USER_EXISTS) {
661+
return this.login({...loginDto,password}, authHeader);
662+
} else {
663+
// create a new user
664+
const createUserPayload: UserRegistration = {
665+
user: {
666+
timezone: "Asia/Kolkata",
667+
username: loginDto.loginId,
668+
password: password
669+
},
670+
registration: {
671+
applicationId: loginDto.applicationId,
672+
preferredLanguages: [
673+
"en"
674+
],
675+
roles: [],
676+
}
677+
}
678+
const { userId, user, err }: { userId: UUID; user: User; err: Error } =
679+
await this.fusionAuthService.createAndRegisterUser(
680+
createUserPayload,
681+
loginDto.applicationId,
682+
authHeader,
683+
);
684+
if (userId == null || user == null) {
685+
throw new HttpException(err, HttpStatus.BAD_REQUEST);
686+
}
687+
return this.login({...loginDto,password}, authHeader);
688+
}
689+
}
690+
640691
async updateUserRegistration(
641692
applicationId: UUID,
642693
authHeader: null | string,

src/api/dto/login.dto.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,15 @@ export class LoginDto {
1717
@IsNotEmpty()
1818
applicationId: string;
1919
}
20+
21+
22+
export class LoginWithUniqueIdDto {
23+
@IsString()
24+
@IsNotEmpty()
25+
@MaxLength(80)
26+
loginId: string;
27+
28+
@IsUUID()
29+
@IsNotEmpty()
30+
applicationId: string;
31+
}

0 commit comments

Comments
 (0)