register flow
This commit is contained in:
parent
1f318d0039
commit
3ea5df5904
57
package-lock.json
generated
57
package-lock.json
generated
@ -22,6 +22,8 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.1",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"handlebars": "^4.7.8",
|
||||
"joi": "^17.13.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jwk-to-pem": "^2.0.7",
|
||||
"mssql": "^10.0.4",
|
||||
@ -1422,6 +1424,21 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@hapi/hoek": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
|
||||
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@hapi/topo": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
|
||||
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||
@ -3320,6 +3337,27 @@
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/@sideway/address": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
|
||||
"integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sideway/formula": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
|
||||
"integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@sideway/pinpoint": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
|
||||
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.8",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||
@ -8598,7 +8636,6 @@
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||
"integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.2",
|
||||
@ -8620,7 +8657,6 @@
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -10351,6 +10387,19 @@
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/joi": {
|
||||
"version": "17.13.3",
|
||||
"resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
|
||||
"integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "^9.3.0",
|
||||
"@hapi/topo": "^5.1.0",
|
||||
"@sideway/address": "^4.1.5",
|
||||
"@sideway/formula": "^3.0.1",
|
||||
"@sideway/pinpoint": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-beautify": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
|
||||
@ -12134,7 +12183,6 @@
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nice-try": {
|
||||
@ -16784,8 +16832,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
|
||||
@ -33,6 +33,8 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.1",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"handlebars": "^4.7.8",
|
||||
"joi": "^17.13.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jwk-to-pem": "^2.0.7",
|
||||
"mssql": "^10.0.4",
|
||||
|
||||
14
public/mail-templates/a.hbs
Normal file
14
public/mail-templates/a.hbs
Normal file
@ -0,0 +1,14 @@
|
||||
<div style="font-family: Arial, sans-serif; padding: 20px; background-color: #f9f9f9;">
|
||||
<div style="max-width: 600px; margin: auto; background-color: #fff; padding: 30px; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
||||
<h2 style="color: #4A90E2;">🔐 Registration Initiated</h2>
|
||||
<p style="font-size: 16px;">A Registration has been successfully initiated for the email: <strong>{{to}}</strong></p>
|
||||
<p>Please click below to complete your registration:</p>
|
||||
<a href={{url}} style="display: inline-block; margin-top: 20px; background-color: #007BFF; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; font-size: 16px;">
|
||||
Register Now
|
||||
</a>
|
||||
<div style="margin-top: 40px;">
|
||||
<p style="color: #888;">Powered by</p>
|
||||
<img src="https://yourapp.com/logo.png" alt="App Logo" style="max-height: 50px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
1
public/mail-templates/demo.hbs
Normal file
1
public/mail-templates/demo.hbs
Normal file
@ -0,0 +1 @@
|
||||
<h1>Testing....</h1>
|
||||
@ -1,14 +1,21 @@
|
||||
import { Body, Controller, Get, HttpCode, Post, Put, Req, Res, UseInterceptors } from '@nestjs/common';
|
||||
import { Body, Controller, Get, HttpCode, Post, Put, Req, Res, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthLoginDTO } from './auth.dto';
|
||||
import { AuthLoginDTO, SendMailDTO } from './auth.dto';
|
||||
import { Request, Response } from 'express';
|
||||
import { LogoutInterceptor } from 'src/interceptors/logout.interceptor';
|
||||
import { RegisterGuard } from 'src/guards/register.guard';
|
||||
import { UserMaintenanceService } from 'src/oracle/user-maintenance/user-maintenance.service';
|
||||
import { RolesGuard } from 'src/guards/roles.guard';
|
||||
import { Roles } from 'src/decorators/roles.decorator';
|
||||
|
||||
@ApiTags('Auth')
|
||||
@Controller()
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) { }
|
||||
constructor(
|
||||
private readonly authService: AuthService,
|
||||
private readonly userMaintenanceService: UserMaintenanceService
|
||||
) { }
|
||||
|
||||
@Post('login')
|
||||
@HttpCode(200)
|
||||
@ -36,7 +43,7 @@ export class AuthController {
|
||||
return { statusCode: 200, message: "Logged-In Successfully", email: k.email }
|
||||
}
|
||||
|
||||
// @UseGuards(RegisterGuard)
|
||||
@UseGuards(RegisterGuard)
|
||||
@Post('register')
|
||||
async register(@Body() body: AuthLoginDTO, @Req() req: Request) {
|
||||
return this.authService.registerUser(body, req);
|
||||
@ -87,6 +94,15 @@ export class AuthController {
|
||||
return { statusCode: 200, message: "Tokens refreshed successfully" }
|
||||
}
|
||||
|
||||
@UseGuards(RolesGuard)
|
||||
@Roles('sa')
|
||||
@Post('sendmail')
|
||||
@HttpCode(200)
|
||||
async sendMail(@Body() body: SendMailDTO) {
|
||||
// let token = await this.jwtService.generateToken({ email: mail })
|
||||
return this.authService.sendMail(body);
|
||||
}
|
||||
|
||||
// @Get('checkRoles')
|
||||
// @UseGuards(JwtAuthGuard, RolesGuard)
|
||||
// @Roles('ca')
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
import { Transform, Type } from 'class-transformer';
|
||||
import { IsEmail, IsEnum, IsString, ValidateNested } from 'class-validator';
|
||||
|
||||
export class AuthLoginDTO {
|
||||
@ApiProperty({ required: true })
|
||||
@ -10,3 +11,56 @@ export class AuthLoginDTO {
|
||||
@IsString()
|
||||
P_PASSWORD: string;
|
||||
}
|
||||
|
||||
export enum MailTypeDTO {
|
||||
REGISTER_CLIENT = "REGISTER_CLIENT",
|
||||
REGISTER_SP = "REGISTER_SP",
|
||||
REGISTER_USCIB = "REGISTER_USCIB",
|
||||
FORGOT_PASSWORD = "FORGOT_PASSWORD"
|
||||
// DEMO_MAIL = "DEMO_MAIL"
|
||||
}
|
||||
|
||||
export class SendMailDTO {
|
||||
@ApiProperty({ required: true, example: 'user@example.com' })
|
||||
@IsEmail({}, { message: 'P_TO must be a valid email address' })
|
||||
P_TO: string;
|
||||
|
||||
@ApiProperty({ enum: MailTypeDTO, required: true })
|
||||
@Transform(({ value }) => value?.toUpperCase())
|
||||
@IsEnum(MailTypeDTO, { message: "Invalid P_MAIL_TYPE" })
|
||||
P_MAIL_TYPE: MailTypeDTO;
|
||||
}
|
||||
|
||||
export class MailContextDTO {
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
to: string;
|
||||
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
url: string;
|
||||
|
||||
}
|
||||
|
||||
export class MailTemplateDTO {
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
to: string;
|
||||
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
subject: string;
|
||||
|
||||
// @ApiProperty({ required: true })
|
||||
// @IsString()
|
||||
// text: string;
|
||||
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
template: string;
|
||||
|
||||
@ApiProperty({ type: () => MailContextDTO, required: true })
|
||||
@ValidateNested()
|
||||
@Type(() => MailContextDTO)
|
||||
context: MailContextDTO;
|
||||
}
|
||||
@ -1,11 +1,59 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { forwardRef, Module } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { DbModule } from 'src/db/db.module';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { OracleModule } from 'src/oracle/oracle.module';
|
||||
|
||||
@Module({
|
||||
imports: [DbModule],
|
||||
providers: [AuthService],
|
||||
imports: [DbModule, forwardRef(() => OracleModule)],
|
||||
providers: [
|
||||
AuthService,
|
||||
{
|
||||
provide: "REGISTER_SIGN_JWT",
|
||||
useFactory: (config: ConfigService) => {
|
||||
const base64Key = config.get<string>('JWT_REGISTER_PRIVATE_KEY');
|
||||
if (!base64Key) {
|
||||
throw new Error('JWT_REGISTER_PRIVATE_KEY is not defined in the config');
|
||||
}
|
||||
const secretKey = Buffer.from(base64Key, 'base64').toString('utf-8');
|
||||
|
||||
const expiry = config.get<string>('JWT_REGISTER_EXPIRY');
|
||||
|
||||
if (!expiry) {
|
||||
throw new Error('JWT_REGISTER_PRIVATE_KEY is not defined in the config');
|
||||
}
|
||||
|
||||
return new JwtService({
|
||||
secret: secretKey,
|
||||
signOptions: {
|
||||
expiresIn: expiry,
|
||||
algorithm: 'ES384'
|
||||
},
|
||||
})
|
||||
},
|
||||
inject: [ConfigService],
|
||||
},
|
||||
{
|
||||
provide: "REGISTER_VERIFY_JWT",
|
||||
useFactory: (config: ConfigService) => {
|
||||
const base64Key = config.get<string>('JWT_REGISTER_PUBLIC_KEY');
|
||||
if (!base64Key) {
|
||||
throw new Error('JWT_REGISTER_PRIVATE_KEY is not defined in the config');
|
||||
}
|
||||
const secretKey = Buffer.from(base64Key, 'base64').toString('utf-8');
|
||||
|
||||
return new JwtService({
|
||||
secret: secretKey,
|
||||
verifyOptions: {
|
||||
algorithms: ['ES384']
|
||||
}
|
||||
})
|
||||
},
|
||||
inject: [ConfigService],
|
||||
}
|
||||
],
|
||||
controllers: [AuthController],
|
||||
exports: [AuthService]
|
||||
})
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Injectable, InternalServerErrorException } from '@nestjs/common';
|
||||
import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common';
|
||||
import { OracleDBService } from 'src/db/db.service';
|
||||
import { AuthLoginDTO } from './auth.dto';
|
||||
import { AuthLoginDTO, MailTemplateDTO, MailTypeDTO, SendMailDTO } from './auth.dto';
|
||||
import * as oracledb from 'oracledb';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
@ -10,6 +10,9 @@ import * as jwt from "jsonwebtoken"
|
||||
import { UnauthorizedException } from 'src/exceptions/unauthorized.exception';
|
||||
import { ConflictException } from 'src/exceptions/conflict.exception';
|
||||
import { BadRequestException } from 'src/exceptions/badRequest.exception';
|
||||
import { MailerService } from '@nestjs-modules/mailer';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { UserMaintenanceService } from 'src/oracle/user-maintenance/user-maintenance.service';
|
||||
|
||||
interface DecodedToken {
|
||||
email: string;
|
||||
@ -33,11 +36,25 @@ export class AuthService {
|
||||
private readonly CLIENT_SECRET: string;
|
||||
private readonly TOKEN_URL: string;
|
||||
private readonly USERS_URL: string;
|
||||
private readonly JWT_REGISTER_PRIVATE_KEY: string;
|
||||
private readonly JWT_REGISTER_PUBLIC_KEY: string;
|
||||
|
||||
constructor(
|
||||
private readonly oracleDBService: OracleDBService,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly mailService: MailerService,
|
||||
private readonly userMaintenanceService: UserMaintenanceService,
|
||||
@Inject("REGISTER_SIGN_JWT") readonly REGISTER_SIGN_JWT: JwtService,
|
||||
@Inject("REGISTER_VERIFY_JWT") readonly REGISTER_VERIFY_JWT: JwtService
|
||||
) {
|
||||
const JWT_REGISTER_PRIVATE_KEY = this.configService.get<string>('JWT_REGISTER_PRIVATE_KEY');
|
||||
if (!JWT_REGISTER_PRIVATE_KEY) throw new Error('Environment variable JWT_REGISTER_PRIVATE_KEY is not set');
|
||||
this.JWT_REGISTER_PRIVATE_KEY = Buffer.from(JWT_REGISTER_PRIVATE_KEY, 'base64').toString('utf-8');
|
||||
|
||||
const JWT_REGISTER_PUBLIC_KEY = this.configService.get<string>('JWT_REGISTER_PUBLIC_KEY');
|
||||
if (!JWT_REGISTER_PUBLIC_KEY) throw new Error('Environment variable JWT_REGISTER_PRIVATE_KEY is not set');
|
||||
this.JWT_REGISTER_PUBLIC_KEY = Buffer.from(JWT_REGISTER_PUBLIC_KEY, 'base64').toString('utf-8');
|
||||
|
||||
const KEYCLOAK_URL = this.configService.get<string>('KEYCLOAK_URL');
|
||||
if (!KEYCLOAK_URL) throw new Error('Environment variable KEYCLOAK_URL is not set');
|
||||
this.KEYCLOAK_URL = KEYCLOAK_URL;
|
||||
@ -190,7 +207,7 @@ export class AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
async getUserSession(email:string) {
|
||||
async getUserSession(email: string) {
|
||||
try {
|
||||
const uid = await this.getUserIdByEmail(email);
|
||||
|
||||
@ -258,7 +275,7 @@ export class AuthService {
|
||||
if (access_token && refresh_token && userSession.length > 0) {
|
||||
let tokens = await this.getTokenFromRefreshToken(req);
|
||||
const decoded = jwt.decode(access_token, { complete: true });
|
||||
const email:any = (decoded && typeof decoded === 'object') ? (decoded as any).payload?.email : undefined;
|
||||
const email: any = (decoded && typeof decoded === 'object') ? (decoded as any).payload?.email : undefined;
|
||||
return { ...tokens, email }
|
||||
}
|
||||
|
||||
@ -323,25 +340,6 @@ export class AuthService {
|
||||
password: `${'A1!bcdef'}`,
|
||||
});
|
||||
|
||||
let userID = await this.getUserIdByEmail("");
|
||||
|
||||
let resetPasswordURL = `${this.USERS_URL}/${userID}/reset-password`;
|
||||
|
||||
let adminAccessToken = await this.getAdminAccessToken();
|
||||
|
||||
const options1: AxiosRequestConfig = {
|
||||
method: 'PUT',
|
||||
url: resetPasswordURL,
|
||||
headers: {
|
||||
Authorization: `Bearer ${adminAccessToken}`
|
||||
},
|
||||
data: {
|
||||
type: 'password',
|
||||
value: 'A1!bcdef',
|
||||
temporary: false,
|
||||
}
|
||||
};
|
||||
|
||||
const options2: AxiosRequestConfig = {
|
||||
method: 'POST',
|
||||
url: this.TOKEN_URL,
|
||||
@ -427,21 +425,45 @@ export class AuthService {
|
||||
|
||||
const uid = await this.getUserIdByEmail(body.P_EMAILADDR);
|
||||
|
||||
const res = await this.assignRoleToUser(uid, "ca");
|
||||
let ROLE = "";
|
||||
|
||||
const response: any = await this.userMaintenanceService.ValidateEmail({ P_EMAILADDR: body.P_EMAILADDR })
|
||||
|
||||
|
||||
if (Array.isArray(response) && !response[0].ERRORMESG) {
|
||||
switch (response[0].SOURCE) {
|
||||
case "USCIB": ROLE = 'ua'; break;
|
||||
case "SP": ROLE = 'sa'; break;
|
||||
case "CLIENT": ROLE = 'ca'; break;
|
||||
}
|
||||
}
|
||||
else if (Array.isArray(response) && response[0].ERRORMESG) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
if (!ROLE) {
|
||||
console.log("ERROR while giving access : ");
|
||||
throw new InternalServerErrorException();
|
||||
}
|
||||
|
||||
const res = await this.assignRoleToUser(uid, ROLE);
|
||||
|
||||
console.log(res);
|
||||
|
||||
return { message: 'User created successfully' };
|
||||
return { statusCode: 201, message: 'User registered successfully' };
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
// handle errors like user exists, validation errors, etc.
|
||||
console.log(error.message);
|
||||
|
||||
if (error.message === "Request failed with status code 409") {
|
||||
throw new ConflictException("User already exist");
|
||||
}
|
||||
|
||||
else if (error instanceof BadRequestException) {
|
||||
console.log("ERROR while registering : ", error.message);
|
||||
return error;
|
||||
}
|
||||
console.log("ERROR while giving access : ", error.message);
|
||||
throw new InternalServerErrorException('Failed to create user');
|
||||
}
|
||||
}
|
||||
@ -601,4 +623,80 @@ export class AuthService {
|
||||
throw new UnauthorizedException('Authentication failed');
|
||||
}
|
||||
}
|
||||
|
||||
async getMailTemplate(body: SendMailDTO, token: string, source: string): Promise<MailTemplateDTO | null> {
|
||||
|
||||
switch (body.P_MAIL_TYPE) {
|
||||
case MailTypeDTO.REGISTER_CLIENT:
|
||||
return {
|
||||
to: body.P_TO,
|
||||
subject: `🔐 Register Your Account`,
|
||||
template: 'a',
|
||||
context: {
|
||||
to: body.P_TO,
|
||||
url: `https://client.alphaomegainfosys.com/register/${token}`
|
||||
}
|
||||
}
|
||||
case MailTypeDTO.FORGOT_PASSWORD:
|
||||
return {
|
||||
to: body.P_TO,
|
||||
subject: `🔐 Register Your Account`,
|
||||
template: 'a',
|
||||
context: {
|
||||
to: body.P_TO,
|
||||
url: `https://client.alphaomegainfosys.com/register/${token}`
|
||||
}
|
||||
}
|
||||
|
||||
// case MailTypeDTO.DEMO_MAIL:
|
||||
// return {
|
||||
// to: body.P_TO,
|
||||
// subject: `Testing`,
|
||||
// template: 'demo',
|
||||
// context: {
|
||||
// to: body.P_TO,
|
||||
// url: `https://client.alphaomegainfosys.com/register/${token}`
|
||||
// }
|
||||
// }
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async sendMail(body: SendMailDTO) {
|
||||
console.log("mail body : ", body);
|
||||
let token: string;
|
||||
let ROLE: string = "";
|
||||
|
||||
try {
|
||||
token = this.REGISTER_SIGN_JWT.sign({ email: body.P_TO });
|
||||
console.log("Register token : ", token);
|
||||
|
||||
if (!token) {
|
||||
console.log("Register Token Generation failed");
|
||||
throw new InternalServerErrorException();
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error.message);
|
||||
|
||||
throw new InternalServerErrorException("Register Token Generation failed")
|
||||
}
|
||||
|
||||
const mailTemplate: MailTemplateDTO | null = await this.getMailTemplate(body, token, ROLE);
|
||||
|
||||
if (!mailTemplate) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
try {
|
||||
await this.mailService.sendMail({ ...mailTemplate });
|
||||
console.log('Email sent successfully');
|
||||
return { statusCode: 200, message: 'Email sent successfully' };
|
||||
} catch (error) {
|
||||
console.error('Failed to send email:', error.message, error);
|
||||
return { statusCode: 500, message: 'Failed to send email' };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Inject,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
@ -10,44 +11,28 @@ import { Request } from 'express';
|
||||
|
||||
@Injectable()
|
||||
export class RegisterGuard implements CanActivate {
|
||||
constructor(private readonly jwtService: JwtService) {}
|
||||
constructor(
|
||||
@Inject("REGISTER_VERIFY_JWT") readonly REGISTER_VERIFY_JWT: JwtService
|
||||
) { }
|
||||
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
const request = context.switchToHttp().getRequest<Request>();
|
||||
const authHeader = request.headers['authorization'];
|
||||
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
throw new UnauthorizedException('Authorization header missing or malformed');
|
||||
throw new UnauthorizedException('Invalid Request');
|
||||
}
|
||||
|
||||
const token = authHeader.split(' ')[1];
|
||||
|
||||
try {
|
||||
// Decode without verifying to check expiry
|
||||
const decoded: any = this.jwtService.decode(token);
|
||||
|
||||
console.log(decoded);
|
||||
|
||||
|
||||
if (!decoded || !decoded.exp) {
|
||||
throw new UnauthorizedException('Invalid token payload');
|
||||
}
|
||||
|
||||
// Check expiration (exp is in seconds, Date.now() in ms)
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
if (decoded.exp < now) {
|
||||
throw new UnauthorizedException('Token expired');
|
||||
}
|
||||
|
||||
// Verify the token (checks signature and expiration again)
|
||||
this.jwtService.verify(token, {secret:'yourSecretKey'});
|
||||
|
||||
// Optionally attach user info to request object for further use
|
||||
request['user'] = decoded;
|
||||
|
||||
const payload = this.REGISTER_VERIFY_JWT.verify(token);
|
||||
request['user'] = payload;
|
||||
return true;
|
||||
} catch (err) {
|
||||
throw new UnauthorizedException('Invalid or expired token');
|
||||
console.log("Error in register guard : ", err.message);
|
||||
|
||||
throw new UnauthorizedException("Invalid Register Token");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,47 @@
|
||||
import { MailerModule } from '@nestjs-modules/mailer';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { join } from 'path';
|
||||
import * as Joi from 'joi';
|
||||
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MailerModule.forRoot({
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
validationSchema: Joi.object({
|
||||
MAIL_USER: Joi.string().required(),
|
||||
MAIL_PASS: Joi.string().required(),
|
||||
}),
|
||||
}),
|
||||
|
||||
MailerModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
transport: {
|
||||
host: 'localhost',
|
||||
port: 1025,
|
||||
ignoreTLS: true,
|
||||
host: 'smtp.gmail.com',
|
||||
port: 587,
|
||||
// ignoreTLS: true,
|
||||
secure: false,
|
||||
auth: {
|
||||
user: configService.get<string>('MAIL_USER'),
|
||||
pass: configService.get<string>('MAIL_PASS'),
|
||||
},
|
||||
},
|
||||
defaults: {
|
||||
from: '"No Reply" <no-reply@example.com>',
|
||||
from: `"Carnet APP" <${configService.get<string>('MAIL_USER')}>`,
|
||||
},
|
||||
template: {
|
||||
dir: join(__dirname, '../../..', 'public', 'mail-templates'),
|
||||
adapter: new HandlebarsAdapter(), // import from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter'
|
||||
options: {
|
||||
strict: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
export class MailModule { }
|
||||
|
||||
@ -26,6 +26,6 @@ import { AuthModule } from 'src/auth/auth.module';
|
||||
],
|
||||
providers: [OracleService],
|
||||
controllers: [],
|
||||
exports: [OracleService],
|
||||
exports: [OracleService, UserMaintenanceModule],
|
||||
})
|
||||
export class OracleModule {}
|
||||
|
||||
@ -6,6 +6,7 @@ import { AuthModule } from 'src/auth/auth.module';
|
||||
@Module({
|
||||
imports: [AuthModule],
|
||||
controllers: [UserMaintenanceController],
|
||||
providers: [UserMaintenanceService]
|
||||
providers: [UserMaintenanceService],
|
||||
exports: [UserMaintenanceService]
|
||||
})
|
||||
export class UserMaintenanceModule { }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user