Skip to content

Commit

Permalink
ORV2-1217 Document regeneration on send notification (#1272)
Browse files Browse the repository at this point in the history
  • Loading branch information
praju-aot authored Mar 19, 2024
1 parent 5082c69 commit 9398018
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 30 deletions.
28 changes: 14 additions & 14 deletions dops/src/helper/auth.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ function isRoleArray(obj: Role[] | IRole[]): obj is Role[] {
return Array.isArray(obj) && obj.every((item) => typeof item === 'string');
}

/**
* Evaluates if a user has at least one of the specified roles or meets complex role criteria.
*
* This method supports two kinds of inputs for role requirements:
* 1. Simple list of roles (Role[]): In this case, it checks if any of the roles assigned to the user matches at least one of
* the roles specified in the 'roles' parameter. It returns true if there's a match, indicating the user has one of the necessary roles.
* 2. Complex role requirements (IRole[]): When 'roles' is an array of objects implementing the IRole interface (meaning it can specify
* complex role combinations with 'allOf' and 'oneOf' properties), it evaluates these conditions for each role object. It returns true
* if for any role object, either all of the 'allOf' roles or at least one of the 'oneOf' roles are present in the 'userRoles' array.
*
* @param {Role[] | IRole[]} roles - An array of roles or role requirement objects to be matched against the user's roles.
* @param {Role[]} userRoles - An array of roles assigned to the user.
* @returns {boolean} Returns true if the user has at least one of the required roles or meets the complex role requirements, false otherwise.
*/
export const matchRoles = (roles: Role[] | IRole[], userRoles: Role[]) => {
/**
* Evaluates if a user has at least one of the specified roles or meets complex role criteria.
*
* This method supports two kinds of inputs for role requirements:
* 1. Simple list of roles (Role[]): In this case, it checks if any of the roles assigned to the user matches at least one of
* the roles specified in the 'roles' parameter. It returns true if there's a match, indicating the user has one of the necessary roles.
* 2. Complex role requirements (IRole[]): When 'roles' is an array of objects implementing the IRole interface (meaning it can specify
* complex role combinations with 'allOf' and 'oneOf' properties), it evaluates these conditions for each role object. It returns true
* if for any role object, either all of the 'allOf' roles or at least one of the 'oneOf' roles are present in the 'userRoles' array.
*
* @param {Role[] | IRole[]} roles - An array of roles or role requirement objects to be matched against the user's roles.
* @param {Role[]} userRoles - An array of roles assigned to the user.
* @returns {boolean} Returns true if the user has at least one of the required roles or meets the complex role requirements, false otherwise.
*/
if (isRoleArray(roles)) {
// Scenario: roles is a simple list of Role objects.
// This block checks if any of the roles assigned to the user (userRoles)
Expand Down
6 changes: 6 additions & 0 deletions dops/src/interface/role.interface.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Role } from '../enum/roles.enum';

/**
* Defines criteria for role checking.
* @oneOf Optional array of roles where any one role is sufficient
* @allOf Optional array of roles where all roles are required
* Note: Only one of `oneOf` or `allOf` should be specified at any given time.
*/
export interface IRole {
oneOf?: Role[];
allOf?: Role[];
Expand Down
28 changes: 14 additions & 14 deletions vehicles/src/common/helper/auth.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ function isRoleArray(obj: Role[] | IRole[]): obj is Role[] {
return Array.isArray(obj) && obj.every((item) => typeof item === 'string');
}

/**
* Evaluates if a user has at least one of the specified roles or meets complex role criteria.
*
* This method supports two kinds of inputs for role requirements:
* 1. Simple list of roles (Role[]): In this case, it checks if any of the roles assigned to the user matches at least one of
* the roles specified in the 'roles' parameter. It returns true if there's a match, indicating the user has one of the necessary roles.
* 2. Complex role requirements (IRole[]): When 'roles' is an array of objects implementing the IRole interface (meaning it can specify
* complex role combinations with 'allOf' and 'oneOf' properties), it evaluates these conditions for each role object. It returns true
* if for any role object, either all of the 'allOf' roles or at least one of the 'oneOf' roles are present in the 'userRoles' array.
*
* @param {Role[] | IRole[]} roles - An array of roles or role requirement objects to be matched against the user's roles.
* @param {Role[]} userRoles - An array of roles assigned to the user.
* @returns {boolean} Returns true if the user has at least one of the required roles or meets the complex role requirements, false otherwise.
*/
export const matchRoles = (roles: Role[] | IRole[], userRoles: Role[]) => {
/**
* Evaluates if a user has at least one of the specified roles or meets complex role criteria.
*
* This method supports two kinds of inputs for role requirements:
* 1. Simple list of roles (Role[]): In this case, it checks if any of the roles assigned to the user matches at least one of
* the roles specified in the 'roles' parameter. It returns true if there's a match, indicating the user has one of the necessary roles.
* 2. Complex role requirements (IRole[]): When 'roles' is an array of objects implementing the IRole interface (meaning it can specify
* complex role combinations with 'allOf' and 'oneOf' properties), it evaluates these conditions for each role object. It returns true
* if for any role object, either all of the 'allOf' roles or at least one of the 'oneOf' roles are present in the 'userRoles' array.
*
* @param {Role[] | IRole[]} roles - An array of roles or role requirement objects to be matched against the user's roles.
* @param {Role[]} userRoles - An array of roles assigned to the user.
* @returns {boolean} Returns true if the user has at least one of the required roles or meets the complex role requirements, false otherwise.
*/
if (isRoleArray(roles)) {
// Scenario: roles is a simple list of Role objects.
// This block checks if any of the roles assigned to the user (userRoles)
Expand Down
6 changes: 6 additions & 0 deletions vehicles/src/common/interface/role.interface.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Role } from '../enum/roles.enum';

/**
* Defines criteria for role checking.
* @oneOf Optional array of roles where any one role is sufficient
* @allOf Optional array of roles where all roles are required
* Note: Only one of `oneOf` or `allOf` should be specified at any given time.
*/
export interface IRole {
oneOf?: Role[];
allOf?: Role[];
Expand Down
3 changes: 2 additions & 1 deletion vehicles/src/modules/common/dops.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ClsService } from 'nestjs-cls';
import { LogAsyncMethodExecution } from '../../common/decorator/log-async-method-execution.decorator';
import { LogMethodExecution } from '../../common/decorator/log-method-execution.decorator';
import { INotificationDocument } from '../../common/interface/notification-document.interface';
import { ReadNotificationDto } from './dto/response/read-notification.dto';

@Injectable()
export class DopsService {
Expand Down Expand Up @@ -298,6 +299,6 @@ export class DopsService {
});

// Return the response data after casting it to the expected type
return dopsResponse.data as { message: string; transactionId: string };
return dopsResponse.data as ReadNotificationDto;
}
}
34 changes: 34 additions & 0 deletions vehicles/src/modules/common/dto/request/create-notification.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { AutoMap } from '@automapper/classes';
import { ApiProperty } from '@nestjs/swagger';
import {
ArrayMinSize,
IsEmail,
IsOptional,
IsString,
Length,
} from 'class-validator';

export class CreateNotificationDto {
@ApiProperty({
description: 'Notification email ids.',
example: ['[email protected]', '[email protected]'],
})
@IsEmail(undefined, {
each: true,
})
@ArrayMinSize(1)
to: string[];

@AutoMap()
@ApiProperty({
description: 'The fax number to send the notification to.',
required: false,
maxLength: 20,
minLength: 10,
example: '9999999999',
})
@IsOptional()
@IsString()
@Length(10, 20)
fax?: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class ReadNotificationDto {
message: string;
transactionId: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export class PaymentService {
private dataSource: DataSource,
@InjectRepository(Transaction)
private transactionRepository: Repository<Transaction>,
@InjectRepository(Receipt)
private receiptRepository: Repository<Receipt>,
@InjectRepository(PaymentMethodType)
private paymentMethodTypeRepository: Repository<PaymentMethodType>,
@InjectRepository(PaymentCardType)
Expand Down Expand Up @@ -352,6 +354,30 @@ export class PaymentService {
return readTransactionDto;
}

async updateReceiptDocument(
currentUser: IUserJWT,
receiptId: string,
documentId: string,
) {
const updateResult = await this.receiptRepository
.createQueryBuilder()
.update()
.set({
receiptDocumentId: documentId,
updatedUser: currentUser.userName,
updatedDateTime: new Date(),
updatedUserDirectory: currentUser.orbcUserDirectory,
updatedUserGuid: currentUser.userGUID,
})
.where('receiptId = :receiptId', { receiptId: receiptId })
.execute();

if (updateResult.affected === 0) {
throw new InternalServerErrorException('Update failed');
}
return true;
}

/**
* Updates details returned by Payment Gateway in ORBC System.
* @param currentUser - The current user object of type {@link IUserJWT}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Query,
Res,
BadRequestException,
ForbiddenException,
} from '@nestjs/common';
import { PermitService } from './permit.service';
import { ExceptionDto } from '../../../common/exception/exception.dto';
Expand Down Expand Up @@ -41,6 +42,8 @@ import {
} from 'src/common/enum/user-auth-group.enum';
import { ReadPermitMetadataDto } from './dto/response/read-permit-metadata.dto';
import { doesUserHaveAuthGroup } from '../../../common/helper/auth.helper';
import { CreateNotificationDto } from '../../common/dto/request/create-notification.dto';
import { ReadNotificationDto } from '../../common/dto/response/read-notification.dto';

@ApiBearerAuth()
@ApiTags('Permit')
Expand Down Expand Up @@ -229,4 +232,51 @@ export class PermitController {
);
return permit;
}

/**
* Sends a notification related to a specific permit.
*
* This method checks if the current user belongs to the specified user authentication group before proceeding.
* If the user does not belong to the required auth group, a ForbiddenException is thrown.
*
* @param request The incoming request object containing the current user information.
* @param permitId The ID of the permit to associate the notification with.
* @param createNotificationDto The data transfer object containing the notification details.
* @returns A promise resolved with the details of the sent notification.
*/
@ApiCreatedResponse({
description: 'The Notification resource with transaction details',
type: ReadNotificationDto,
})
@ApiOperation({
summary: 'Send Permit Notification',
description:
'Sends a notification related to a specific permit after checking user authorization.',
})
@Roles(Role.SEND_NOTIFICATION)
@Post('/:permitId/notification')
async notification(
@Req() request: Request,
@Param('permitId') permitId: string,
@Body()
createNotificationDto: CreateNotificationDto,
): Promise<ReadNotificationDto> {
const currentUser = request.user as IUserJWT;

// Throws ForbiddenException if user does not belong to the specified user auth group.
if (
!doesUserHaveAuthGroup(
currentUser.orbcUserAuthGroup,
IDIR_USER_AUTH_GROUP_LIST,
)
) {
throw new ForbiddenException();
}

return await this.permitService.sendNotification(
currentUser,
permitId,
createNotificationDto,
);
}
}
Loading

0 comments on commit 9398018

Please sign in to comment.