Compare commits

..

3 Commits

Author SHA1 Message Date
Kallesh B S
63b08e9883 auth template 2025-06-16 15:53:15 +05:30
Kallesh B S
d932953950 updated faxno as optional every-where and create-logins response updated 2025-06-16 10:33:27 +05:30
Kallesh B S
c79b37d2e0 client contact controls API updated 2025-06-13 12:54:08 +05:30
16 changed files with 3935 additions and 330 deletions

3548
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -20,17 +20,26 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs-modules/mailer": "^2.0.2",
"@nestjs/common": "^11.0.1",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^11.0.1",
"@nestjs/jwt": "^11.0.0",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^11.0.1",
"@nestjs/swagger": "^11.0.6",
"@nestjs/typeorm": "^11.0.0",
"axios": "^1.10.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"jsonwebtoken": "^9.0.2",
"jwk-to-pem": "^2.0.7",
"mssql": "^10.0.4",
"mysql2": "^3.12.0",
"nodemailer": "^7.0.3",
"oracledb": "^6.7.2",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"pg": "^8.13.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
@ -46,6 +55,7 @@
"@swc/core": "^1.10.7",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.14",
"@types/jwk-to-pem": "^2.0.3",
"@types/mssql": "^9.1.7",
"@types/node": "^22.10.7",
"@types/oracledb": "^6.5.4",

View File

@ -2,15 +2,15 @@ import { MiddlewareConsumer, Module } from '@nestjs/common';
import { DbModule } from './db/db.module';
import { OracleModule } from './oracle/oracle.module';
import { AuthModule } from './auth/auth.module';
import { MssqlModule } from './mssql/mssql.module';
import { OriginCheckMiddleware } from './middleware/OriginCheck.middleware';
import { ReqBodyKeysToUppercaseMiddleware } from './middleware/reqBodyKeysToUppercase.middleware';
import { ConfigModule } from '@nestjs/config';
import { MailModule } from './mail/mail.module';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
AuthModule, DbModule, OracleModule
AuthModule, DbModule, OracleModule, MailModule
],
controllers: [],
providers: [],

View File

@ -1,15 +1,93 @@
import { Body, Controller, Post } from '@nestjs/common';
import { Body, Controller, Get, HttpCode, Post, Put, Req, Res } from '@nestjs/common';
import { AuthService } from './auth.service';
import { ApiTags } from '@nestjs/swagger';
import { AuthLoginDTO } from './auth.dto';
import { Request, Response } from 'express';
@Controller()
export class AuthController {
constructor(private readonly authService: AuthService) {}
constructor(private readonly authService: AuthService) { }
@ApiTags('Auth')
@Post('/login')
login(@Body() body: AuthLoginDTO) {
return this.authService.login(body);
}
@Post('login-client')
@HttpCode(200)
async loginClient(@Body() body: AuthLoginDTO, @Res({ passthrough: true }) res: Response, @Req() req: Request) {
let k: any = await this.authService.loginUser(body.P_EMAILADDR, body.P_PASSWORD, req);
if (k.access_token) {
res.cookie('access_token', k.access_token, {
httpOnly: true,
secure: false, // set to true if you're on HTTPS
sameSite: 'lax', // adjust based on your needs (strict, lax , none)
maxAge: 90 * 1000, // convert seconds to ms if applicable
});
}
if (k.refresh_token) {
res.cookie('refresh_token', k.refresh_token, {
httpOnly: true,
secure: false, // set to true if you're on HTTPS
sameSite: 'lax', // adjust based on your needs (strict, lax , none)
maxAge: 90 * 1000, // convert seconds to ms if applicable
});
}
return { statusCode: 200, message: "Logged-In Successfully", email: k.email }
}
// @UseGuards(RegisterGuard)
@Post('register-client')
async register(@Body() body: AuthLoginDTO, @Req() req: Request) {
return this.authService.registerUser(body, req);
}
// @UseInterceptors(LogoutInterceptor)
@HttpCode(200)
@Post('logout-client')
async logout(@Req() req: any, @Res() res: Response) {
const refreshToken = req.user?.refreshToken;
let rst: any = await this.authService.logoutUser(refreshToken);
if (rst.statusCode === 200) {
res.clearCookie('access_token');
res.clearCookie('refresh_token');
}
res.json({ ...rst })
}
@Put('forgot-password-client')
async forgotPassword() {
return this.authService.forgotPassword();
}
@Get('refresh-client-tokens')
async getTokenFromRefreshToken(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
let k: any = await this.authService.getTokenFromRefreshToken(req)
if (k.access_token) {
res.cookie('access_token', k.access_token, {
httpOnly: true,
secure: false, // set to true if you're on HTTPS
sameSite: 'lax', // adjust based on your needs (strict, lax , none)
maxAge: 90 * 1000, // convert seconds to ms if applicable
path: '/'
});
}
if (k.refresh_token) {
res.cookie('refresh_token', k.refresh_token, {
httpOnly: true,
secure: false, // set to true if you're on HTTPS
sameSite: 'lax', // adjust based on your needs (strict, lax , none)
maxAge: 90 * 1000, // convert seconds to ms if applicable
path: '/'
});
}
return { statusCode: 200, message: "Tokens refreshed successfully" }
}
}

View File

@ -9,4 +9,4 @@ export class AuthLoginDTO {
@ApiProperty({ required: true })
@IsString()
P_PASSWORD: string;
}
}

View File

@ -1,11 +1,23 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common';
import { OracleDBService } from 'src/db/db.service';
import { AuthLoginDTO } from './auth.dto';
import * as oracledb from 'oracledb';
import { ConfigService } from '@nestjs/config';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { Request } from 'express';
import * as jwkToPem from "jwk-to-pem"
import * as jwt from "jsonwebtoken"
import { UnauthorizedException } from 'src/exceptions/unauthorized.exception';
import { ConflictException } from 'src/exceptions/conflict.exception';
@Injectable()
export class AuthService {
constructor(private readonly oracleDBService: OracleDBService) { }
private keyCache: Record<string, string> = {};
constructor(
private readonly oracleDBService: OracleDBService,
private readonly configService: ConfigService,
) { }
async login(body: AuthLoginDTO) {
let connection;
@ -72,4 +84,375 @@ export class AuthService {
}
}
}
private async getPublicKey(kid: string): Promise<string> {
if (this.keyCache[kid]) return this.keyCache[kid];
const jwksUri = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get(
'REALM',
)}/protocol/openid-connect/certs`;
const { data } = await axios.get(jwksUri);
const key = data.keys.find((k) => k.kid === kid);
if (!key) throw new InternalServerErrorException('Key not found');
const pem = jwkToPem(key);
this.keyCache[kid] = pem;
return pem;
}
async introspectToken(token: string): Promise<any> {
const url = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get(
'REALM',
)}/protocol/openid-connect/token/introspect`;
const params = new URLSearchParams();
params.append('token', token);
params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
return response.data;
}
async decodeToken(token: string): Promise<any> {
const decodedHeader = jwt.decode(token, { complete: true });
if (!decodedHeader || typeof decodedHeader !== 'object') {
throw new Error('Invalid token format');
}
const kid: any = decodedHeader.header.kid;
const publicKey = await this.getPublicKey(kid);
const introspection = await this.introspectToken(token);
console.log('introspec : ', introspection);
if (!introspection.active) {
throw new Error('Unauthorized');
}
const verified = jwt.verify(token, publicKey, { algorithms: ['RS256'] });
return verified;
}
async getAdminAccessTokenx(): Promise<string> {
const data = new URLSearchParams();
data.append('grant_type', 'client_credentials');
data.append('client_id', this.configService.get('CLIENT_ID') || '');
data.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
let KEYCLOAK_URL = await this.configService.get('KEYCLOAK_URL');
try {
const response: AxiosResponse = await axios.post(KEYCLOAK_URL, data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
return response.data.access_token;
} catch (error) {
console.error('Error getting Keycloak access token:', error.response ? error.response.data : error.message);
throw new Error('Failed to obtain Keycloak access token');
}
}
async loginUser(username: string, password: string, req: Request): Promise<any> {
console.log(username, password);
const accessToken = req.cookies['access_token'];
const refreshToken = req.cookies['refresh_token'];
console.log("---------cookies--------------");
console.log(accessToken, refreshToken);
// return {accessToken, refreshToken, expires_in:2000}
if (!accessToken && !refreshToken) {
console.log("I am here getting token ....");
const url = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/token`;
const params = new URLSearchParams();
params.append('grant_type', 'password');
params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
params.append('username', username);
params.append('password', password);
try {
const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
console.log('first time data ...');
let k = { ...response.data, email: username };
return k; // tokens and user info
} catch (error) {
console.log(error.message);
throw new BadRequestException('Invalid username or password');
}
}
else if (accessToken && refreshToken) {
return { access_token: accessToken, refresh_token: refreshToken, email: username }
}
}
async getUserIdByEmail() {
let url = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users?email=a@gmail.com`;
let adminAccessToken = await this.getAdminAccessToken();
const options: AxiosRequestConfig = {
method: 'GET',
url,
headers: {
Authorization: `Bearer ${adminAccessToken}`,
"Content-Type": "application/json"
}
};
try {
const { data } = await axios.request(options);
return data[0]?.id;
} catch (error) {
// console.error(error);
console.log(error.message);
}
}
async forgotPassword() {
let urlx = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users`;
let urlxx = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users?email=${encodeURIComponent('a@gmail.com')}`;
let url = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users?email=a@gmail.com`;
let validatePasswordURL = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/token`
const validatePasswordURLSearchParams = new URLSearchParams({
grant_type: 'password',
client_id: `${this.configService.get('CLIENT_ID')}`,
client_secret: `${this.configService.get('CLIENT_SECRET')}`,
username: `${'a@gmail.com'}`,
password: `${'A1!bcdef'}`,
});
let userID = await this.getUserIdByEmail();
console.log("userID: ", userID);
let resetPasswordURL = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users/${userID}/reset-password`;
let adminAccessToken = await this.getAdminAccessToken();
const options: AxiosRequestConfig = {
method: 'GET',
url,
headers: {
Authorization: `Bearer ${adminAccessToken}`,
"Content-Type": "application/json"
}
};
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: validatePasswordURL,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: validatePasswordURLSearchParams
};
try {
const { data } = await axios.request(options2);
return { statusCode: 200, message: 'password reset successfull' }
} catch (error) {
// console.error(error);
console.log(error.message);
throw new InternalServerErrorException()
}
}
async getAdminAccessToken() {
try {
const adminTokenUrl = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/token`;
console.log(adminTokenUrl);
const adminParams = new URLSearchParams();
adminParams.append('grant_type', 'client_credentials');
adminParams.append('client_id', this.configService.get('CLIENT_ID') || '');
adminParams.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
const adminTokenResponse = await axios.post(adminTokenUrl,
adminParams,
{
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
console.log(adminTokenResponse.data);
const adminAccessToken = adminTokenResponse.data.access_token;
return adminAccessToken;
} catch (error) {
console.log(error.message);
throw error
}
}
async registerUser(body: AuthLoginDTO, req: Request) {
// First, get an admin access token using client credentials
let det = await req['user'];
if (det?.email !== body.P_EMAILADDR) {
throw new BadRequestException();
}
const adminTokenUrl = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/token`;
console.log(adminTokenUrl);
const adminParams = new URLSearchParams();
adminParams.append('grant_type', 'client_credentials');
adminParams.append('client_id', this.configService.get('CLIENT_ID') || '');
adminParams.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
const adminTokenResponse = await axios.post(adminTokenUrl,
adminParams,
{
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
console.log(adminTokenResponse.data);
// const adminAccessToken = adminTokenResponse.data.access_token;
const adminAccessToken = adminTokenResponse.data.access_token;
// Now create user
const createUserUrl = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users`;
const userPayload = {
username: body.P_EMAILADDR,
// firstName:"A",
// lastName:"B",
email: body.P_EMAILADDR,
emailVerified: true,
enabled: true,
credentials: [
{
type: 'password',
value: body.P_PASSWORD,
temporary: false,
},
],
};
console.log(userPayload);
try {
const response = await axios.post(createUserUrl, userPayload, {
headers: {
Authorization: `Bearer ${adminAccessToken}`,
'Content-Type': 'application/json',
},
});
if (response.status === 201) {
return { message: 'User created 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");
}
throw new InternalServerErrorException('Failed to create user');
}
}
async logoutUser(refreshToken: string): Promise<any> {
const url = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/logout`;
const params = new URLSearchParams();
params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
params.append('refresh_token', refreshToken);
try {
const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
return { statusCode: 200, message: 'Logged-Out successfully' };
} catch (error) {
throw new UnauthorizedException('Logout failed');
}
}
async getTokenFromRefreshToken(req: Request) {
const refreshToken = req.cookies['refresh_token'];
if (!refreshToken) {
throw new UnauthorizedException('Authentication failed');
}
let dk = await this.introspectToken(refreshToken);
console.log('--------------validation------------------------');
console.log(dk);
console.log('--------------validation------------------------');
const url = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/token`;
const params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
params.append('refresh_token', refreshToken);
try {
const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
console.log('refresh token response...');
console.log(response.data);
return response.data; // tokens and user info
// console.log(response.data);
// return { message: "tokens refreshed successfully...." }
} catch (error) {
console.log(error.message);
throw new UnauthorizedException('Authentication failed');
}
}
}

View File

@ -60,7 +60,7 @@ export class UpdateClientContactsDTO extends IntersectionType(
PartialType(MIDDLE_INITIAL_DTO),
PartialType(TITLE_DTO),
PHONE_NO_DTO,
FAX_NO_DTO,
PartialType(FAX_NO_DTO),
PartialType(MOBILE_NO_DTO),
EMAIL_ADDRESS_DTO,
USERID_DTO

View File

@ -1,4 +1,4 @@
import { IntersectionType } from '@nestjs/swagger';
import { IntersectionType, PartialType } from '@nestjs/swagger';
import {
DEFAULT_CONTACT_FLAG_DTO, EMAIL_ADDRESS_DTO, FAX_NO_DTO,
@ -10,11 +10,11 @@ import { SPID_DTO } from '../sp/sp-property.dto';
export class InsertSPContactsDTO extends IntersectionType(
SPID_DTO, DEFAULT_CONTACT_FLAG_DTO, FIRSTNAME_DTO, LASTNAME_DTO, MIDDLE_INITIAL_DTO, TITLE_DTO,
PHONE_NO_DTO, MOBILE_NO_DTO, FAX_NO_DTO, EMAIL_ADDRESS_DTO, USER_ID_DTO
PHONE_NO_DTO, MOBILE_NO_DTO, PartialType(FAX_NO_DTO), EMAIL_ADDRESS_DTO, USER_ID_DTO
) { }
export class UpdateSPContactsDTO extends IntersectionType(
SP_CONTACTID_DTO, FIRSTNAME_DTO, LASTNAME_DTO, MIDDLE_INITIAL_DTO, TITLE_DTO, PHONE_NO_DTO,
MOBILE_NO_DTO, FAX_NO_DTO, EMAIL_ADDRESS_DTO, USER_ID_DTO
MOBILE_NO_DTO, PartialType(FAX_NO_DTO), EMAIL_ADDRESS_DTO, USER_ID_DTO
) { }

View File

@ -0,0 +1,19 @@
import { HttpException, HttpStatus } from '@nestjs/common';
export class ConflictException extends HttpException {
constructor(
message = 'CONFLICT',
errorCode = 'INTERNAL_ERROR',
data: any = null,
) {
super(
{
statusCode: HttpStatus.CONFLICT,
message,
// errorCode,
// data,
},
HttpStatus.CONFLICT,
);
}
}

View File

@ -0,0 +1,19 @@
import { HttpException, HttpStatus } from '@nestjs/common';
export class UnauthorizedException extends HttpException {
constructor(
message = 'Unauthorized',
errorCode = 'INTERNAL_ERROR',
data: any = null,
) {
super(
{
statusCode: HttpStatus.UNAUTHORIZED,
message,
// errorCode,
// data,
},
HttpStatus.UNAUTHORIZED,
);
}
}

View File

@ -0,0 +1,46 @@
import {
Injectable,
CanActivate,
ExecutionContext,
UnauthorizedException,
Global,
} from '@nestjs/common';
import { AuthService } from 'src/auth/auth.service';
@Global()
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private readonly authService: AuthService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
// Read token from cookie
console.log('------------------------------');
let g = await request.cookies
console.log("g : ",g);
console.log(' guard cookies ------------------------------');
const token = request.cookies?.access_token;
if (!token) {
console.log('error from inspect token .....');
throw new UnauthorizedException('Authentication failed');
}
try {
const decoded = await this.authService.decodeToken(token);
request.user = decoded;
return true;
} catch (err) {
console.log(err.message);
throw new UnauthorizedException({
message: 'Invalid Token',
error: 'Unauthorized',
statusCode: 401,
});
}
}
}

View File

@ -0,0 +1,53 @@
// jwt-auth.guard.ts
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';
@Injectable()
export class RegisterGuard implements CanActivate {
constructor(private readonly jwtService: 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');
}
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;
return true;
} catch (err) {
throw new UnauthorizedException('Invalid or expired token');
}
}
}

View File

@ -0,0 +1,30 @@
// refresh-token.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
BadRequestException,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class LogoutInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const refreshToken = request.cookies?.refresh_token;
if (!refreshToken) {
throw new BadRequestException('Refresh token not found in cookies');
}
// Attach refresh token to request object for later use
request.user = {
...(request.user || {}),
refreshToken,
};
return next.handle();
}
}

18
src/mail/mail.module.ts Normal file
View File

@ -0,0 +1,18 @@
import { MailerModule } from '@nestjs-modules/mailer';
import { Module } from '@nestjs/common';
@Module({
imports: [
MailerModule.forRoot({
transport: {
host: 'localhost',
port: 1025,
ignoreTLS: true,
},
defaults: {
from: '"No Reply" <no-reply@example.com>',
},
}),
],
})
export class MailModule { }

View File

@ -45,19 +45,19 @@ export class ManageClientsController {
}
@ApiTags('Manage Clients - Oracle')
@Patch('SetDefaultClientContacts/:P_SPID/:P_CLIENTID/:P_USERID')
@Patch('SetDefaultClientContacts/:P_SPID/:P_CLIENTCONTACTID/:P_USERID')
SetDefaultClientContacts(@Param() param: ClientContactControlsDTO) {
return this.manageClientsService.SetDefaultClientContacts(param);
}
@ApiTags('Manage Clients - Oracle')
@Patch('InactivateClientContacts/:P_SPID/:P_CLIENTID/:P_USERID')
@Patch('InactivateClientContacts/:P_SPID/:P_CLIENTCONTACTID/:P_USERID')
InactivateClientContacts(@Param() param: ClientContactControlsDTO) {
return this.manageClientsService.InactivateClientContacts(param);
}
@ApiTags('Manage Clients - Oracle')
@Patch('ReactivateClientContacts/:P_SPID/:P_CLIENTID/:P_USERID')
@Patch('ReactivateClientContacts/:P_SPID/:P_CLIENTCONTACTID/:P_USERID')
ReactivateClientContacts(@Param() param: ClientContactControlsDTO) {
return this.manageClientsService.ReactivateClientContacts(param);
}

View File

@ -9,6 +9,7 @@ import {
EMAIL_DTO, USERID_DTO,
CreateClientLoginsDTO, CreateSPLoginsDTO, CreateUSCIBLoginsDTO, SPID_CLIENTID_DTO, SPID_EMAIL_DTO
} from 'src/dto/property.dto';
import { BadRequestException } from 'src/exceptions/badRequest.exception';
interface RoleDetail { [key: string]: any; }
@ -172,9 +173,15 @@ export class UserMaintenanceService {
throw new InternalServerException("Incomplete data received from the database.");
}
return {
data: await fetchCursor(outBinds.P_CURSOR),
};
const fres: any = await fetchCursor(outBinds.P_CURSOR, UserMaintenanceService.name);
if (fres.length > 0 && fres[0].ERRORMESG) {
this.logger.warn(fres[0].ERRORMESG);
throw new BadRequestException(fres[0].ERRORMESG)
}
return { statusCode: 201, message: "Created successfully", ...fres[0] };
} catch (error) {
handleError(error, UserMaintenanceService.name)
} finally {
@ -250,7 +257,15 @@ export class UserMaintenanceService {
throw new InternalServerException("Incomplete data received from the database.");
}
return await fetchCursor(outBinds.P_CURSOR, UserMaintenanceService.name);
const fres: any = await fetchCursor(outBinds.P_CURSOR, UserMaintenanceService.name);
if (fres.length > 0 && fres[0].ERRORMESG) {
this.logger.warn(fres[0].ERRORMESG);
throw new BadRequestException(fres[0].ERRORMESG)
}
return { statusCode: 201, message: "Created successfully", ...fres[0] };
} catch (error) {
handleError(error, UserMaintenanceService.name)
} finally {
@ -359,7 +374,15 @@ export class UserMaintenanceService {
throw new InternalServerException("Incomplete data received from the database.");
}
return await fetchCursor(outBinds.P_CURSOR, UserMaintenanceService.name);
const fres: any = await fetchCursor(outBinds.P_CURSOR, UserMaintenanceService.name);
if (fres.length > 0 && fres[0].ERRORMESG) {
this.logger.warn(fres[0].ERRORMESG);
throw new BadRequestException(fres[0].ERRORMESG)
}
return { statusCode: 201, message: "Created successfully", ...fres[0] };
} catch (error) {
handleError(error, UserMaintenanceService.name)
} finally {