Skip to content

Commit

Permalink
fix: export activity interceptor (#3926)
Browse files Browse the repository at this point in the history
* fix: export activity interceptor

* fix: import path

* fix: improve export logging tests

* fix: tidy up implementation

* fix: commenting for clarity
  • Loading branch information
ColinBuyck authored Mar 7, 2024
1 parent e5bf474 commit 5662226
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "activity_log" ALTER COLUMN "record_id" DROP NOT NULL;
2 changes: 1 addition & 1 deletion api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ model ActivityLog {
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(6)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamp(6)
module String @db.VarChar
recordId String @map("record_id") @db.Uuid
action String @db.VarChar
metadata Json?
recordId String? @map("record_id") @db.Uuid
userId String? @map("user_id") @db.Uuid
userAccounts UserAccounts? @relation(fields: [userId], references: [id], onUpdate: NoAction)
Expand Down
2 changes: 2 additions & 0 deletions api/src/controllers/application.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { permissionActions } from '../enums/permissions/permission-actions-enum'
import { PermissionAction } from '../decorators/permission-action.decorator';
import { ApplicationCsvExporterService } from '../services/application-csv-export.service';
import { ApplicationCsvQueryParams } from '../dtos/applications/application-csv-query-params.dto';
import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';

@Controller('applications')
@ApiTags('applications')
Expand Down Expand Up @@ -82,6 +83,7 @@ export class ApplicationController {
operationId: 'listAsCsv',
})
@Header('Content-Type', 'text/csv')
@UseInterceptors(ExportLogInterceptor)
async listAsCsv(
@Request() req: ExpressRequest,
@Res({ passthrough: true }) res: Response,
Expand Down
2 changes: 2 additions & 0 deletions api/src/controllers/listing.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { AdminOrJurisdictionalAdminGuard } from '../guards/admin-or-jurisdiction
import { ListingCsvExporterService } from '../services/listing-csv-export.service';
import { ListingCsvQueryParams } from '../dtos/listings/listing-csv-query-params.dto';
import { PermissionGuard } from '../guards/permission.guard';
import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';

@Controller('listings')
@ApiTags('listings')
Expand Down Expand Up @@ -91,6 +92,7 @@ export class ListingController {
})
@Header('Content-Type', 'application/zip')
@UseGuards(OptionalAuthGuard, PermissionGuard)
@UseInterceptors(ExportLogInterceptor)
async listAsCsv(
@Request() req: ExpressRequest,
@Res({ passthrough: true }) res: Response,
Expand Down
2 changes: 2 additions & 0 deletions api/src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { ActivityLogInterceptor } from '../interceptors/activity-log.interceptor
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { UserFilterParams } from '../dtos/users/user-filter-params.dto';
import { UserCsvExporterService } from '../services/user-csv-export.service';
import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';

@Controller('user')
@ApiTags('user')
Expand Down Expand Up @@ -98,6 +99,7 @@ export class UserController {
})
@Header('Content-Type', 'text/csv')
@UseGuards(OptionalAuthGuard, AdminOrJurisdictionalAdminGuard)
@UseInterceptors(ExportLogInterceptor)
async listAsCsv(
@Request() req: ExpressRequest,
@Res({ passthrough: true }) res: Response,
Expand Down
2 changes: 1 addition & 1 deletion api/src/interceptors/activity-log.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type ActivityLogMetadataType = Array<{

@Injectable()
export class ActivityLogInterceptor implements NestInterceptor {
constructor(private reflector: Reflector, private prisma: PrismaService) {}
constructor(private reflector: Reflector, protected prisma: PrismaService) {}

/*
builds the metadata that gets stored in the activity log
Expand Down
43 changes: 43 additions & 0 deletions api/src/interceptors/export-log.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CallHandler, ExecutionContext, Injectable } from '@nestjs/common';
import { ActivityLogInterceptor } from './activity-log.interceptor';
import { endWith, from, ignoreElements, mergeMap } from 'rxjs';
import { PrismaService } from '../services/prisma.service';
import { Reflector } from '@nestjs/core';

@Injectable()
export class ExportLogInterceptor extends ActivityLogInterceptor {
constructor(reflector: Reflector, prisma: PrismaService) {
super(reflector, prisma);
}

intercept(context: ExecutionContext, next: CallHandler) {
const { module, user } = this.getBasicRequestInfo(context);
return next.handle().pipe(
mergeMap((value) => {
let resourceId;
// only export type tied to a single resourceId
if (module === 'application') {
const req = context.switchToHttp().getRequest();
resourceId = req.query.listingId;
}
return from(
this.prisma.activityLog.create({
include: {
userAccounts: true,
},
data: {
module,
recordId: resourceId,
action: 'export',
userAccounts: {
connect: {
id: user.id,
},
},
},
}),
).pipe(ignoreElements(), endWith(value));
}),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ describe('Testing Permissioning of endpoints as Admin User', () => {
.expect(201);
});

it('should succeed for csv endpoint', async () => {
it('should succeed for csv endpoint & create an activity log entry', async () => {
const jurisdiction = await generateJurisdiction(
prisma,
'permission juris csv endpoint admin',
Expand All @@ -445,6 +445,15 @@ describe('Testing Permissioning of endpoints as Admin User', () => {
.get(`/applications/csv?listingId=${listing1Created.id}`)
.set('Cookie', cookies)
.expect(200);
const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'application',
action: 'export',
recordId: listing1Created.id,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down Expand Up @@ -1034,11 +1043,21 @@ describe('Testing Permissioning of endpoints as Admin User', () => {
expect(activityLogResult).not.toBeNull();
});

it('should succeed for csv export endpoint', async () => {
it('should succeed for csv export endpoint & create an activity log entry', async () => {
await request(app.getHttpServer())
.get('/user/csv')
.set('Cookie', cookies)
.expect(200);

const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'user',
action: 'export',
recordId: null,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down Expand Up @@ -1191,11 +1210,20 @@ describe('Testing Permissioning of endpoints as Admin User', () => {
.expect(200);
});

it('should succeed for csv endpoint', async () => {
it('should succeed for csv endpoint & create an activity log entry', async () => {
await request(app.getHttpServer())
.get(`/listings/csv`)
.set('Cookie', cookies)
.expect(200);
const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'listing',
action: 'export',
recordId: null,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the corr
.expect(201);
});

it('should succeed for csv endpoint', async () => {
it('should succeed for csv endpoint & create an activity log entry', async () => {
const application = await applicationFactory();
const listing1 = await listingFactory(jurisId, prisma, {
applications: [application],
Expand All @@ -413,6 +413,15 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the corr
.get(`/applications/csv?listingId=${listing1Created.id}`)
.set('Cookie', cookies)
.expect(200);
const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'application',
action: 'export',
recordId: listing1Created.id,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down Expand Up @@ -933,11 +942,21 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the corr
.expect(403);
});

it('should succeed for csv export endpoint', async () => {
it('should succeed for csv export endpoint & create an activity log entry', async () => {
await request(app.getHttpServer())
.get('/user/csv')
.set('Cookie', cookies)
.expect(200);

const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'user',
action: 'export',
recordId: null,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down Expand Up @@ -1065,11 +1084,20 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the corr
.expect(200);
});

it('should succeed for csv endpoint', async () => {
it('should succeed for csv endpoint & create an activity log entry', async () => {
await request(app.getHttpServer())
.get(`/listings/csv`)
.set('Cookie', cookies)
.expect(200);
const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'listing',
action: 'export',
recordId: null,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,11 +910,21 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the wron
.expect(403);
});

it('should succeed for csv export endpoint', async () => {
it('should succeed for csv export endpoint & create an activity log entry', async () => {
await request(app.getHttpServer())
.get('/user/csv')
.set('Cookie', cookies)
.expect(200);

const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'user',
action: 'export',
recordId: null,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down Expand Up @@ -1012,11 +1022,20 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the wron
.expect(200);
});

it('should succeed for csv endpoint', async () => {
it('should succeed for csv endpoint & create an activity log entry', async () => {
await request(app.getHttpServer())
.get(`/listings/csv`)
.set('Cookie', cookies)
.expect(200);
const activityLogResult = await prisma.activityLog.findFirst({
where: {
module: 'listing',
action: 'export',
recordId: null,
},
});

expect(activityLogResult).not.toBeNull();
});
});

Expand Down

0 comments on commit 5662226

Please sign in to comment.