Compare commits

..

No commits in common. "0f6edbe8c14818e9e007a5e18f648afc410cb9d6" and "63b08e9883277ca576cda23c13f7ccf7df6185f9" have entirely different histories.

10 changed files with 137 additions and 251 deletions

40
package-lock.json generated
View File

@ -21,7 +21,6 @@
"axios": "^1.10.0", "axios": "^1.10.0",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"cookie-parser": "^1.4.7",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"jwk-to-pem": "^2.0.7", "jwk-to-pem": "^2.0.7",
"mssql": "^10.0.4", "mssql": "^10.0.4",
@ -43,7 +42,6 @@
"@nestjs/testing": "^11.0.1", "@nestjs/testing": "^11.0.1",
"@swc/cli": "^0.6.0", "@swc/cli": "^0.6.0",
"@swc/core": "^1.10.7", "@swc/core": "^1.10.7",
"@types/cookie-parser": "^1.4.9",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/jwk-to-pem": "^2.0.3", "@types/jwk-to-pem": "^2.0.3",
@ -3800,16 +3798,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/cookie-parser": {
"version": "1.4.9",
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz",
"integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"@types/express": "*"
}
},
"node_modules/@types/cookiejar": { "node_modules/@types/cookiejar": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz",
@ -6217,34 +6205,6 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/cookie-parser": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
"license": "MIT",
"dependencies": {
"cookie": "0.7.2",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-parser/node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
"node_modules/cookie-signature": { "node_modules/cookie-signature": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",

View File

@ -32,7 +32,6 @@
"axios": "^1.10.0", "axios": "^1.10.0",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"cookie-parser": "^1.4.7",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"jwk-to-pem": "^2.0.7", "jwk-to-pem": "^2.0.7",
"mssql": "^10.0.4", "mssql": "^10.0.4",
@ -54,7 +53,6 @@
"@nestjs/testing": "^11.0.1", "@nestjs/testing": "^11.0.1",
"@swc/cli": "^0.6.0", "@swc/cli": "^0.6.0",
"@swc/core": "^1.10.7", "@swc/core": "^1.10.7",
"@types/cookie-parser": "^1.4.9",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/jwk-to-pem": "^2.0.3", "@types/jwk-to-pem": "^2.0.3",

View File

@ -90,11 +90,4 @@ export class AuthController {
return { statusCode: 200, message: "Tokens refreshed successfully" } return { statusCode: 200, message: "Tokens refreshed successfully" }
} }
// @Get('checkRoles')
// @UseGuards(JwtAuthGuard, RolesGuard)
// @Roles('ca')
roleChecking() {
return { message: "role checking successfull..." }
}
} }

View File

@ -14,46 +14,10 @@ import { ConflictException } from 'src/exceptions/conflict.exception';
export class AuthService { export class AuthService {
private keyCache: Record<string, string> = {}; private keyCache: Record<string, string> = {};
private readonly KEYCLOAK_URL: string;
private readonly KEYCLOAK_REALM: string;
private readonly KEYCLOAK_BASE_URL: string;
private readonly JWKS_URL: string;
private readonly TOKENS_INTROSPECT_URL: string;
private readonly CLIENT_ID: string;
private readonly CLIENT_SECRET: string;
private readonly TOKEN_URL: string;
private readonly USERS_URL: string;
constructor( constructor(
private readonly oracleDBService: OracleDBService, private readonly oracleDBService: OracleDBService,
private readonly configService: ConfigService, private readonly configService: ConfigService,
) { ) { }
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;
const KEYCLOAK_REALM = this.configService.get<string>('KEYCLOAK_REALM');
if (!KEYCLOAK_REALM) throw new Error('Environment variable KEYCLOAK_REALM is not set');
this.KEYCLOAK_REALM = KEYCLOAK_REALM;
const CLIENT_ID = this.configService.get<string>('CLIENT_ID');
if (!CLIENT_ID) throw new Error('Environment variable KEYCLOAK CLIENT_ID is not set');
this.CLIENT_ID = CLIENT_ID;
const CLIENT_SECRET = this.configService.get<string>('CLIENT_SECRET');
if (!CLIENT_SECRET) throw new Error('Environment variable KEYCLOAK CLIENT_SECRET is not set');
this.CLIENT_SECRET = CLIENT_SECRET;
this.KEYCLOAK_BASE_URL = `${this.KEYCLOAK_URL}/realms/${this.KEYCLOAK_REALM}/protocol/openid-connect`;
this.JWKS_URL = `${this.KEYCLOAK_BASE_URL}/certs`
this.TOKENS_INTROSPECT_URL = `${this.KEYCLOAK_BASE_URL}/token/introspect`
this.TOKEN_URL = `${this.KEYCLOAK_BASE_URL}/token`
this.USERS_URL = `${this.KEYCLOAK_URL}/realms/${this.KEYCLOAK_REALM}/users`;
}
async login(body: AuthLoginDTO) { async login(body: AuthLoginDTO) {
let connection; let connection;
@ -123,23 +87,32 @@ export class AuthService {
private async getPublicKey(kid: string): Promise<string> { private async getPublicKey(kid: string): Promise<string> {
if (this.keyCache[kid]) return this.keyCache[kid]; if (this.keyCache[kid]) return this.keyCache[kid];
const { data } = await axios.get(this.JWKS_URL);
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); const key = data.keys.find((k) => k.kid === kid);
if (!key) throw new InternalServerErrorException('Key not found'); if (!key) throw new InternalServerErrorException('Key not found');
const pem = jwkToPem(key); const pem = jwkToPem(key);
this.keyCache[kid] = pem; this.keyCache[kid] = pem;
return pem; return pem;
} }
async introspectToken(token: string): Promise<any> { 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(); const params = new URLSearchParams();
params.append('token', token); params.append('token', token);
params.append('client_id', this.CLIENT_ID); params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.CLIENT_SECRET); params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
const response = await axios.post(this.TOKENS_INTROSPECT_URL, params, { const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}); });
@ -157,6 +130,8 @@ export class AuthService {
const introspection = await this.introspectToken(token); const introspection = await this.introspectToken(token);
console.log('introspec : ', introspection);
if (!introspection.active) { if (!introspection.active) {
throw new Error('Unauthorized'); throw new Error('Unauthorized');
} }
@ -168,10 +143,11 @@ export class AuthService {
async getAdminAccessTokenx(): Promise<string> { async getAdminAccessTokenx(): Promise<string> {
const data = new URLSearchParams(); const data = new URLSearchParams();
data.append('grant_type', 'client_credentials'); data.append('grant_type', 'client_credentials');
data.append('client_id', this.CLIENT_ID); data.append('client_id', this.configService.get('CLIENT_ID') || '');
data.append('client_secret', this.CLIENT_SECRET); data.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
let KEYCLOAK_URL = await this.configService.get('KEYCLOAK_URL');
try { try {
const response: AxiosResponse = await axios.post(this.KEYCLOAK_URL, data, { const response: AxiosResponse = await axios.post(KEYCLOAK_URL, data, {
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
@ -185,27 +161,39 @@ export class AuthService {
async loginUser(username: string, password: string, req: Request): Promise<any> { async loginUser(username: string, password: string, req: Request): Promise<any> {
console.log(username, password);
const accessToken = req.cookies['access_token']; const accessToken = req.cookies['access_token'];
const refreshToken = req.cookies['refresh_token']; const refreshToken = req.cookies['refresh_token'];
console.log("---------cookies--------------");
console.log(accessToken, refreshToken);
// return {accessToken, refreshToken, expires_in:2000}
if (!accessToken && !refreshToken) { 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(); const params = new URLSearchParams();
params.append('grant_type', 'password'); params.append('grant_type', 'password');
params.append('client_id', this.CLIENT_ID); params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.CLIENT_SECRET); params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
params.append('username', username); params.append('username', username);
params.append('password', password); params.append('password', password);
try { try {
const response = await axios.post(this.TOKEN_URL, params, { const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}); });
console.log('first time data ...'); console.log('first time data ...');
let k = { ...response.data, email: username }; let k = { ...response.data, email: username };
return k; return k; // tokens and user info
} catch (error) { } catch (error) {
console.log(error.message); console.log(error.message);
@ -218,9 +206,9 @@ export class AuthService {
} }
} }
async getUserIdByEmail(email: string) { async getUserIdByEmail() {
let url = `${this.USERS_URL}?email=${email}`; let url = `${this.configService.get('KEYCLOAK_URL')}/admin/realms/${this.configService.get('REALM')}/users?email=a@gmail.com`;
let adminAccessToken = await this.getAdminAccessToken(); let adminAccessToken = await this.getAdminAccessToken();
@ -243,21 +231,37 @@ export class AuthService {
} }
async forgotPassword() { 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({ const validatePasswordURLSearchParams = new URLSearchParams({
grant_type: 'password', grant_type: 'password',
client_id: `${this.CLIENT_ID}`, client_id: `${this.configService.get('CLIENT_ID')}`,
client_secret: `${this.CLIENT_SECRET}`, client_secret: `${this.configService.get('CLIENT_SECRET')}`,
username: `${'a@gmail.com'}`, username: `${'a@gmail.com'}`,
password: `${'A1!bcdef'}`, password: `${'A1!bcdef'}`,
}); });
let userID = await this.getUserIdByEmail(""); let userID = await this.getUserIdByEmail();
let resetPasswordURL = `${this.USERS_URL}/${userID}/reset-password`; 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(); let adminAccessToken = await this.getAdminAccessToken();
const options: AxiosRequestConfig = {
method: 'GET',
url,
headers: {
Authorization: `Bearer ${adminAccessToken}`,
"Content-Type": "application/json"
}
};
const options1: AxiosRequestConfig = { const options1: AxiosRequestConfig = {
method: 'PUT', method: 'PUT',
url: resetPasswordURL, url: resetPasswordURL,
@ -273,7 +277,7 @@ export class AuthService {
const options2: AxiosRequestConfig = { const options2: AxiosRequestConfig = {
method: 'POST', method: 'POST',
url: this.TOKEN_URL, url: validatePasswordURL,
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
@ -294,12 +298,16 @@ export class AuthService {
async getAdminAccessToken() { async getAdminAccessToken() {
try { try {
const adminTokenUrl = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/token`;
console.log(adminTokenUrl);
const adminParams = new URLSearchParams(); const adminParams = new URLSearchParams();
adminParams.append('grant_type', 'client_credentials'); adminParams.append('grant_type', 'client_credentials');
adminParams.append('client_id', this.CLIENT_ID); adminParams.append('client_id', this.configService.get('CLIENT_ID') || '');
adminParams.append('client_secret', this.CLIENT_SECRET); adminParams.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
const adminTokenResponse = await axios.post(this.TOKEN_URL, const adminTokenResponse = await axios.post(adminTokenUrl,
adminParams, adminParams,
{ {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
@ -316,10 +324,35 @@ export class AuthService {
} }
async registerUser(body: AuthLoginDTO, req: Request) { async registerUser(body: AuthLoginDTO, req: Request) {
// First, get an admin access token using client credentials
let det = await req['user']; let det = await req['user'];
if (det?.email !== body.P_EMAILADDR) { if (det?.email !== body.P_EMAILADDR) {
throw new BadRequestException(); 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 = { const userPayload = {
username: body.P_EMAILADDR, username: body.P_EMAILADDR,
// firstName:"A", // firstName:"A",
@ -338,10 +371,9 @@ export class AuthService {
console.log(userPayload); console.log(userPayload);
const adminAccessToken = await this.getAdminAccessToken();
try { try {
const response = await axios.post(this.USERS_URL, userPayload, { const response = await axios.post(createUserUrl, userPayload, {
headers: { headers: {
Authorization: `Bearer ${adminAccessToken}`, Authorization: `Bearer ${adminAccessToken}`,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -349,13 +381,6 @@ export class AuthService {
}); });
if (response.status === 201) { if (response.status === 201) {
const uid = await this.getUserIdByEmail(body.P_EMAILADDR);
const res = await this.assignRoleToUser(uid, "ca");
console.log(res);
return { message: 'User created successfully' }; return { message: 'User created successfully' };
} }
@ -372,11 +397,11 @@ export class AuthService {
} }
async logoutUser(refreshToken: string): Promise<any> { async logoutUser(refreshToken: string): Promise<any> {
const url = `${this.KEYCLOAK_BASE_URL}/logout`; const url = `${this.configService.get('KEYCLOAK_URL')}/realms/${this.configService.get('REALM')}/protocol/openid-connect/logout`;
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append('client_id', this.CLIENT_ID); params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.CLIENT_SECRET); params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
params.append('refresh_token', refreshToken); params.append('refresh_token', refreshToken);
try { try {
@ -389,104 +414,6 @@ export class AuthService {
} }
} }
async getClientUUID(): Promise<string> {
try {
const token = await this.getAdminAccessToken();
const realm = this.KEYCLOAK_REALM;
const clientId = this.CLIENT_ID;
const keycloakUrl = this.KEYCLOAK_URL;
const response = await axios.get(
`${keycloakUrl}/admin/realms/${realm}/clients?clientId=${encodeURIComponent(clientId)}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
validateStatus: () => true, // manually handle status codes
}
);
if (response.status !== 200) {
throw new Error(`Failed to fetch client list. Status: ${response.status}. Message: ${JSON.stringify(response.data)}`);
}
const clients = response.data;
if (!Array.isArray(clients) || clients.length === 0) {
throw new Error(`Client with ID '${clientId}' not found in realm '${realm}'.`);
}
const clientUUID = clients[0].id;
if (!clientUUID) {
throw new Error(`Client UUID is missing in the response for clientId '${clientId}'.`);
}
return clientUUID;
} catch (error) {
console.error('❌ Error in getClientUUID:', error.message || error);
throw error; // rethrow for upstream handling
}
}
async getClientRole(roleName: string): Promise<any> {
const token = await this.getAdminAccessToken();
const clientUUID = await this.getClientUUID();
try {
const response = await axios.get(
`${this.KEYCLOAK_URL}/admin/realms/${this.KEYCLOAK_REALM}/clients/${clientUUID}/roles/${roleName}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
return response.data;
} catch (error) {
console.error(`Error getting client role '${roleName}'`);
console.error(error.response?.data || error.message);
throw new InternalServerErrorException(`Could not find client role '${roleName}'`);
}
}
async assignRoleToUser(userId: string, roleName: string): Promise<any> {
try {
const token = await this.getAdminAccessToken();
const clientId = await this.getClientUUID();
const role = await this.getClientRole(roleName);
const url = `${this.KEYCLOAK_URL}/admin/realms/${this.KEYCLOAK_REALM}/users/${userId}/role-mappings/clients/${clientId}`;
const response = await axios.post(
url,
[role],
{
headers: {
Authorization: `Bearer ${token}`,
},
validateStatus: () => true, // To manually check status if needed
}
);
if (response.status >= 200 && response.status < 300) {
console.log(`✅ Role "${roleName}" successfully assigned to user ${userId}.`);
return { message: "Successfully assigned to user" }
} else {
throw new Error(`❌ Failed to assign role. Status: ${response.status}. Data: ${JSON.stringify(response.data)}`);
}
} catch (error) {
console.error(`🔥 Error assigning role "${roleName}" to user ${userId}:`, error.message || error);
throw error; // Rethrow to allow upstream handling
}
}
async getTokenFromRefreshToken(req: Request) { async getTokenFromRefreshToken(req: Request) {
const refreshToken = req.cookies['refresh_token']; const refreshToken = req.cookies['refresh_token'];
@ -494,18 +421,35 @@ export class AuthService {
throw new UnauthorizedException('Authentication failed'); 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(); const params = new URLSearchParams();
params.append('grant_type', 'refresh_token'); params.append('grant_type', 'refresh_token');
params.append('client_id', this.CLIENT_ID); params.append('client_id', this.configService.get('CLIENT_ID') || '');
params.append('client_secret', this.CLIENT_SECRET); params.append('client_secret', this.configService.get('CLIENT_SECRET') || '');
params.append('refresh_token', refreshToken); params.append('refresh_token', refreshToken);
try { try {
const response = await axios.post(this.TOKEN_URL, params, { const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}); });
return response.data; 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) { } catch (error) {
console.log(error.message); console.log(error.message);
throw new UnauthorizedException('Authentication failed'); throw new UnauthorizedException('Authentication failed');

View File

@ -1,5 +0,0 @@
// roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const ROLES_KEY = 'roles';
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);

View File

@ -29,7 +29,6 @@ export class CLIENT_CONTACTID_DTO {
@Min(0, { message: 'Property P_CLIENTCONTACTID must be at least 0 or more' }) @Min(0, { message: 'Property P_CLIENTCONTACTID must be at least 0 or more' })
@IsInt({ message: 'Property P_CLIENTCONTACTID allows only whole numbers' }) @IsInt({ message: 'Property P_CLIENTCONTACTID allows only whole numbers' })
@IsNumber({}, { message: 'Property P_CLIENTCONTACTID must be a number' }) @IsNumber({}, { message: 'Property P_CLIENTCONTACTID must be a number' })
@Transform(({ value }) => Number(value))
@IsDefined({ message: 'Property P_CLIENTCONTACTID is required' }) @IsDefined({ message: 'Property P_CLIENTCONTACTID is required' })
P_CLIENTCONTACTID: number; P_CLIENTCONTACTID: number;
} }

View File

@ -7,7 +7,6 @@ import {
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { SwaggerDocumentOptions } from '@nestjs/swagger'; import { SwaggerDocumentOptions } from '@nestjs/swagger';
import { BadRequestException } from './exceptions/badRequest.exception'; import { BadRequestException } from './exceptions/badRequest.exception';
import * as cookieParser from 'cookie-parser';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule, { const app = await NestFactory.create(AppModule, {
@ -21,17 +20,23 @@ async function bootstrap() {
}, },
}); });
app.use(cookieParser());
function extractConstraints(validationErrors: ValidationError[]) { function extractConstraints(validationErrors: ValidationError[]) {
const constraints: { [key: string]: string }[] = []; const constraints: { [key: string]: string }[] = [];
function traverse(errors: ValidationError[]) { function traverse(errors: ValidationError[]) {
// console.log(errors);
// console.log("--------------");
for (const error of errors) { for (const error of errors) {
// If the error has constraints, add them to the list
// console.log(error);
// console.log("--------------");
if (error.constraints) { if (error.constraints) {
constraints.push(error.constraints); constraints.push(error.constraints);
} }
// // If there are children, recursively traverse them
if (error.children && error.children.length > 0) { if (error.children && error.children.length > 0) {
traverse(error.children); traverse(error.children);
} }

View File

@ -16,10 +16,10 @@ export class OriginCheckMiddleware implements NestMiddleware {
req.headers['x-forwarded-for']?.toString().split(',')[0].trim() || req.headers['x-forwarded-for']?.toString().split(',')[0].trim() ||
req.socket.remoteAddress; req.socket.remoteAddress;
// this.logger.warn(`Client IP: ${ip}`); this.logger.warn(`Client IP: ${ip}`);
// this.logger.warn(`User-Agent: ${req.headers['user-agent']}`); this.logger.warn(`User-Agent: ${req.headers['user-agent']}`);
// this.logger.warn(`Origin: ${origin}`); this.logger.warn(`Origin: ${origin}`);
// this.logger.warn(`Host: ${req.headers.host}`); this.logger.warn(`Host: ${req.headers.host}`);
// if (origin === allowedOrigin) { // if (origin === allowedOrigin) {

View File

@ -397,13 +397,13 @@ export class ManageClientsService {
const result = await connection.execute( const result = await connection.execute(
`BEGIN `BEGIN
MANAGEPREPARER_PKG.SetDefaultClientContacts( MANAGEPREPARER_PKG.CreateClientContact(
:P_SPID, :P_CLIENTCONTACTID, :P_USERID, :P_CURSOR :P_SPID, :P_CLIENTID, :P_USERID, :P_CURSOR
); );
END;`, END;`,
{ {
P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_CLIENTCONTACTID: { val: body.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: body.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
}, },
@ -441,13 +441,13 @@ export class ManageClientsService {
const result = await connection.execute( const result = await connection.execute(
`BEGIN `BEGIN
MANAGEPREPARER_PKG.InactivateClientContacts( MANAGEPREPARER_PKG.CreateClientContact(
:P_SPID, :P_CLIENTCONTACTID, :P_USERID, :P_CURSOR :P_SPID, :P_CLIENTID, :P_USERID, :P_CURSOR
); );
END;`, END;`,
{ {
P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_CLIENTCONTACTID: { val: body.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: body.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
}, },
@ -485,13 +485,13 @@ export class ManageClientsService {
const result = await connection.execute( const result = await connection.execute(
`BEGIN `BEGIN
MANAGEPREPARER_PKG.ReactivateClientContacts( MANAGEPREPARER_PKG.CreateClientContact(
:P_SPID, :P_CLIENTCONTACTID, :P_USERID, :P_CURSOR :P_SPID, :P_CLIENTID, :P_USERID, :P_CURSOR
); );
END;`, END;`,
{ {
P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_CLIENTCONTACTID: { val: body.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: body.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
}, },

View File

@ -93,8 +93,6 @@ export class UserMaintenanceService {
{ outFormat: oracledb.OUT_FORMAT_OBJECT } { outFormat: oracledb.OUT_FORMAT_OBJECT }
); );
await connection.commit();
const outBinds = result.outBinds; const outBinds = result.outBinds;
if (!outBinds?.P_CURSOR) { if (!outBinds?.P_CURSOR) {
this.logger.error('One or more expected cursors are missing from stored procedure output.'); this.logger.error('One or more expected cursors are missing from stored procedure output.');
@ -169,8 +167,6 @@ export class UserMaintenanceService {
{ outFormat: oracledb.OUT_FORMAT_OBJECT } { outFormat: oracledb.OUT_FORMAT_OBJECT }
); );
await connection.commit();
const outBinds = result.outBinds; const outBinds = result.outBinds;
if (!outBinds?.P_CURSOR) { if (!outBinds?.P_CURSOR) {
this.logger.error('One or more expected cursors are missing from stored procedure output.'); this.logger.error('One or more expected cursors are missing from stored procedure output.');
@ -255,8 +251,6 @@ export class UserMaintenanceService {
{ outFormat: oracledb.OUT_FORMAT_OBJECT } { outFormat: oracledb.OUT_FORMAT_OBJECT }
); );
await connection.commit();
const outBinds = result.outBinds; const outBinds = result.outBinds;
if (!outBinds?.P_CURSOR) { if (!outBinds?.P_CURSOR) {
this.logger.error('One or more expected cursors are missing from stored procedure output.'); this.logger.error('One or more expected cursors are missing from stored procedure output.');
@ -374,8 +368,6 @@ export class UserMaintenanceService {
{ outFormat: oracledb.OUT_FORMAT_OBJECT } { outFormat: oracledb.OUT_FORMAT_OBJECT }
); );
await connection.commit();
const outBinds = result.outBinds; const outBinds = result.outBinds;
if (!outBinds?.P_CURSOR) { if (!outBinds?.P_CURSOR) {
this.logger.error('One or more expected cursors are missing from stored procedure output.'); this.logger.error('One or more expected cursors are missing from stored procedure output.');