chore: add the access log to the ticket
This commit is contained in:
@@ -6,8 +6,11 @@ import { DataSource, MoreThanOrEqual, Not, QueryRunner } from "typeorm";
|
||||
|
||||
import { TICKET } from "../constant";
|
||||
import { ReferralService } from "./referral.service";
|
||||
import { IUserIpAndHeaders } from "../../../common/decorators/user.decorator";
|
||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
import { CommonMessage, TicketMessageEnum, UserMessage } from "../../../common/enums/message.enum";
|
||||
import { UserType } from "../../access-logs/enums/user-type.enum";
|
||||
import { AccessLogService } from "../../access-logs/providers/access-log.service";
|
||||
import { DanakService } from "../../danak-services/entities/danak-service.entity";
|
||||
import { NotificationQueue } from "../../notifications/queue/notification.queue";
|
||||
import { SupportPlanFeatureKey } from "../../support-plans/enums/support-plan-feature-key.enum";
|
||||
@@ -46,6 +49,7 @@ export class TicketsService implements OnModuleInit {
|
||||
private readonly referralService: ReferralService,
|
||||
private readonly dataSource: DataSource,
|
||||
private readonly supportPlansService: SupportPlansService,
|
||||
private readonly accessLogService: AccessLogService,
|
||||
) {}
|
||||
|
||||
async onModuleInit() {
|
||||
@@ -67,7 +71,7 @@ export class TicketsService implements OnModuleInit {
|
||||
return { categories, count, paginate: true };
|
||||
}
|
||||
//******************************** */
|
||||
async createTicketCategory(createDto: CreateTicketCategoryDto) {
|
||||
async createTicketCategory(createDto: CreateTicketCategoryDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const { userGroup } = await this.usersService.getUserGroupById(createDto.userGroupId);
|
||||
const existCategory = await this.ticketsCategoryRepository.findCategoryByTitle(createDto.title);
|
||||
|
||||
@@ -76,15 +80,29 @@ export class TicketsService implements OnModuleInit {
|
||||
...createDto,
|
||||
group: userGroup,
|
||||
});
|
||||
|
||||
await this.ticketsCategoryRepository.save(ticketCategory);
|
||||
|
||||
await this.accessLogService.logCreate("TicketCategory", UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets/categories",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin created ticket category: ${createDto.title}`,
|
||||
metadata: {
|
||||
categoryId: ticketCategory.id,
|
||||
categoryTitle: ticketCategory.title,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
message: TicketMessageEnum.CATEGORY_CREATED,
|
||||
};
|
||||
}
|
||||
|
||||
//******************************** */
|
||||
async updateCategory(paramDto: ParamDto, updateCategoryDto: UpdateTicketCategoryDto) {
|
||||
async updateCategory(paramDto: ParamDto, updateCategoryDto: UpdateTicketCategoryDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const category = await this.ticketsCategoryRepository.findCategoryById(paramDto.id);
|
||||
if (!category) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
|
||||
|
||||
@@ -101,18 +119,47 @@ export class TicketsService implements OnModuleInit {
|
||||
...updateCategoryDto,
|
||||
});
|
||||
|
||||
await this.accessLogService.logUpdate("TicketCategory", paramDto.id, UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets/categories",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin updated ticket category: ${category.title}`,
|
||||
metadata: {
|
||||
categoryId: category.id,
|
||||
categoryTitle: category.title,
|
||||
},
|
||||
oldValues: JSON.stringify({ ...category }),
|
||||
newValues: JSON.stringify({ ...updateCategoryDto }),
|
||||
});
|
||||
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
};
|
||||
}
|
||||
//******************************** */
|
||||
async toggleCategoryStatus(paramDto: ParamDto) {
|
||||
async toggleCategoryStatus(paramDto: ParamDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const category = await this.ticketsCategoryRepository.findCategoryById(paramDto.id);
|
||||
if (!category) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
|
||||
//
|
||||
category.isActive = !category.isActive;
|
||||
await this.ticketsCategoryRepository.save(category);
|
||||
//
|
||||
await this.accessLogService.logUpdate("TicketCategory", paramDto.id, UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets/categories",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin toggled ticket category status: ${category.title}`,
|
||||
metadata: {
|
||||
categoryId: category.id,
|
||||
categoryTitle: category.title,
|
||||
isActive: category.isActive,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
isActive: category.isActive,
|
||||
@@ -209,7 +256,7 @@ export class TicketsService implements OnModuleInit {
|
||||
}
|
||||
//******************************** */
|
||||
|
||||
async createTicketByAdmin(createDto: CreateTicketByAdminDto, adminId: string) {
|
||||
async createTicketByAdmin(createDto: CreateTicketByAdminDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
try {
|
||||
@@ -218,7 +265,7 @@ export class TicketsService implements OnModuleInit {
|
||||
|
||||
const [user, admin, ticketCategory] = await Promise.all([
|
||||
this.usersService.findOneByIdWithQueryRunner(createDto.userId, queryRunner),
|
||||
this.usersService.findOneByIdWithQueryRunner(adminId, queryRunner),
|
||||
this.usersService.findOneByIdWithQueryRunner(userIpAndHeaders.userId, queryRunner),
|
||||
queryRunner.manager.findOne(TicketCategory, { where: { id: createDto.categoryId }, relations: { group: { users: true } } }),
|
||||
]);
|
||||
|
||||
@@ -244,6 +291,19 @@ export class TicketsService implements OnModuleInit {
|
||||
userEmail: user.email,
|
||||
});
|
||||
|
||||
await this.accessLogService.logCreate("Ticket", UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin created ticket: ${ticket.subject}`,
|
||||
metadata: {
|
||||
ticketId: ticket.id,
|
||||
ticketSubject: ticket.subject,
|
||||
},
|
||||
});
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
return {
|
||||
@@ -347,13 +407,13 @@ export class TicketsService implements OnModuleInit {
|
||||
|
||||
//******************************** */
|
||||
|
||||
async closeTicketByUser(ticketId: string, userId: string, isAdmin: boolean) {
|
||||
async closeTicketByUser(ticketId: string, isAdmin: boolean, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
let ticket: null | Ticket = null;
|
||||
|
||||
if (isAdmin) {
|
||||
ticket = await this.ticketsRepository.findTicketById(ticketId);
|
||||
} else {
|
||||
ticket = await this.ticketsRepository.findTicketById(ticketId, userId);
|
||||
ticket = await this.ticketsRepository.findTicketById(ticketId, userIpAndHeaders.userId);
|
||||
}
|
||||
|
||||
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
|
||||
@@ -361,32 +421,58 @@ export class TicketsService implements OnModuleInit {
|
||||
ticket.status = TicketStatus.CLOSED;
|
||||
await this.ticketsRepository.save(ticket);
|
||||
|
||||
await this.accessLogService.logUpdate("Ticket", ticketId, UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin closed ticket: ${ticket.subject}`,
|
||||
metadata: {
|
||||
ticketId: ticket.id,
|
||||
ticketSubject: ticket.subject,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
message: TicketMessageEnum.CLOSED,
|
||||
};
|
||||
}
|
||||
//******************************** * /
|
||||
async openTicketByAdmin(ticketId: string) {
|
||||
async openTicketByAdmin(ticketId: string, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const ticket = await this.ticketsRepository.findTicketById(ticketId);
|
||||
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
|
||||
|
||||
ticket.status = TicketStatus.PENDING;
|
||||
await this.ticketsRepository.save(ticket);
|
||||
|
||||
await this.accessLogService.logUpdate("Ticket", ticketId, UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin opened ticket: ${ticket.subject}`,
|
||||
metadata: {
|
||||
ticketId: ticket.id,
|
||||
ticketSubject: ticket.subject,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
message: TicketMessageEnum.OPENED,
|
||||
};
|
||||
}
|
||||
|
||||
//******************************** */
|
||||
async referTicket(ticketId: string, userId: string, referDto: ReferTicketDto) {
|
||||
async referTicket(ticketId: string, referDto: ReferTicketDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
try {
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
const isSuperAdmin = await this.usersService.isSuperAdmin(userId);
|
||||
const isSuperAdmin = await this.usersService.isSuperAdmin(userIpAndHeaders.userId);
|
||||
// if (!isSuperAdmin) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_ASSIGNED_TO_USER);
|
||||
console.log("isSuperAdmin", isSuperAdmin);
|
||||
|
||||
@@ -408,6 +494,19 @@ export class TicketsService implements OnModuleInit {
|
||||
});
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
await this.accessLogService.logUpdate("Ticket", ticketId, UserType.ADMIN, {
|
||||
user: { id: userIpAndHeaders.userId },
|
||||
endpoint: "/tickets",
|
||||
requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
ipAddress: userIpAndHeaders.ip,
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin referred ticket: ${ticket.subject}`,
|
||||
metadata: {
|
||||
ticketId: ticket.id,
|
||||
ticketSubject: ticket.subject,
|
||||
},
|
||||
});
|
||||
return {
|
||||
message: TicketMessageEnum.REFERRED,
|
||||
ticket,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { TicketsService } from "./providers/tickets.service";
|
||||
import { AdminRoute } from "../../common/decorators/admin.decorator";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { PermissionsDec } from "../../common/decorators/permission.decorator";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
import { IUserIpAndHeaders, UserDec, UserIpAndHeaders } from "../../common/decorators/user.decorator";
|
||||
import { ParamDto } from "../../common/DTO/param.dto";
|
||||
import { PermissionEnum } from "../users/enums/permission.enum";
|
||||
@Controller("tickets")
|
||||
@@ -26,20 +26,23 @@ export class TicketsController {
|
||||
@ApiOperation({ summary: "Create ticket category => admin route" })
|
||||
@PermissionsDec(PermissionEnum.TICKETS)
|
||||
@Post("category")
|
||||
createTicketCategory(@Body() createDto: CreateTicketCategoryDto) {
|
||||
return this.ticketsService.createTicketCategory(createDto);
|
||||
createTicketCategory(@Body() createDto: CreateTicketCategoryDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
return this.ticketsService.createTicketCategory(createDto, userIpAndHeaders);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Update ticket category => admin route" })
|
||||
@PermissionsDec(PermissionEnum.TICKETS)
|
||||
@Patch("category/:id")
|
||||
updateCategory(@Param() paramDto: ParamDto, @Body() updateCategoryDto: UpdateTicketCategoryDto) {
|
||||
return this.ticketsService.updateCategory(paramDto, updateCategoryDto);
|
||||
updateCategory(
|
||||
@Param() paramDto: ParamDto,
|
||||
@Body() updateCategoryDto: UpdateTicketCategoryDto,
|
||||
@UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders,
|
||||
) {
|
||||
return this.ticketsService.updateCategory(paramDto, updateCategoryDto, userIpAndHeaders);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Get ticket categories " })
|
||||
@Get("categories")
|
||||
// @PermissionsDec(PermissionEnum.TICKETS)
|
||||
getTicketCategories() {
|
||||
return this.ticketsService.getTicketCategories();
|
||||
}
|
||||
@@ -57,8 +60,8 @@ export class TicketsController {
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@PermissionsDec(PermissionEnum.TICKETS)
|
||||
@Post("category/toggle-status/:id")
|
||||
toggleCategoryStatus(@Param() paramDto: ParamDto) {
|
||||
return this.ticketsService.toggleCategoryStatus(paramDto);
|
||||
toggleCategoryStatus(@Param() paramDto: ParamDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
return this.ticketsService.toggleCategoryStatus(paramDto, userIpAndHeaders);
|
||||
}
|
||||
|
||||
//----------------- ticket and ticket messages -------------------
|
||||
@@ -73,8 +76,8 @@ export class TicketsController {
|
||||
@AdminRoute()
|
||||
@PermissionsDec(PermissionEnum.TICKETS)
|
||||
@Post("admin")
|
||||
createTicketByAdmin(@Body() createDto: CreateTicketByAdminDto, @UserDec("id") adminId: string) {
|
||||
return this.ticketsService.createTicketByAdmin(createDto, adminId);
|
||||
createTicketByAdmin(@Body() createDto: CreateTicketByAdminDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
return this.ticketsService.createTicketByAdmin(createDto, userIpAndHeaders);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Get all tickets of user ==> user route" })
|
||||
@@ -111,23 +114,27 @@ export class TicketsController {
|
||||
@ApiOperation({ summary: "close ticket by user or admin" })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post(":id/close")
|
||||
closedTicketByUser(@Param() paramDto: ParamDto, @UserDec("id") userId: string, @UserDec("isAdmin") isAdmin: boolean) {
|
||||
return this.ticketsService.closeTicketByUser(paramDto.id, userId, isAdmin);
|
||||
closedTicketByUser(
|
||||
@Param() paramDto: ParamDto,
|
||||
@UserDec("isAdmin") isAdmin: boolean,
|
||||
@UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders,
|
||||
) {
|
||||
return this.ticketsService.closeTicketByUser(paramDto.id, isAdmin, userIpAndHeaders);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "open ticket by admin" })
|
||||
@AdminRoute()
|
||||
@PermissionsDec(PermissionEnum.TICKETS)
|
||||
@Post(":id/open")
|
||||
openTicketByAdmin(@Param() paramDto: ParamDto) {
|
||||
return this.ticketsService.openTicketByAdmin(paramDto.id);
|
||||
openTicketByAdmin(@Param() paramDto: ParamDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
return this.ticketsService.openTicketByAdmin(paramDto.id, userIpAndHeaders);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "referer ticket ==> admin route" })
|
||||
@AdminRoute()
|
||||
@PermissionsDec(PermissionEnum.TICKETS)
|
||||
@Post(":id/refer")
|
||||
referTicket(@Param() paramDto: ParamDto, @UserDec("id") userId: string, @Body() referDto: ReferTicketDto) {
|
||||
return this.ticketsService.referTicket(paramDto.id, userId, referDto);
|
||||
referTicket(@Param() paramDto: ParamDto, @Body() referDto: ReferTicketDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
return this.ticketsService.referTicket(paramDto.id, referDto, userIpAndHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user