mirror of https://github.com/nocodb/nocodb
Pranav C
2 years ago
5 changed files with 220 additions and 0 deletions
@ -0,0 +1,20 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing'; |
||||
import { AuditsController } from './audits.controller'; |
||||
import { AuditsService } from './audits.service'; |
||||
|
||||
describe('AuditsController', () => { |
||||
let controller: AuditsController; |
||||
|
||||
beforeEach(async () => { |
||||
const module: TestingModule = await Test.createTestingModule({ |
||||
controllers: [AuditsController], |
||||
providers: [AuditsService], |
||||
}).compile(); |
||||
|
||||
controller = module.get<AuditsController>(AuditsController); |
||||
}); |
||||
|
||||
it('should be defined', () => { |
||||
expect(controller).toBeDefined(); |
||||
}); |
||||
}); |
@ -0,0 +1,88 @@
|
||||
import { |
||||
Body, |
||||
Controller, |
||||
Get, |
||||
Param, |
||||
Patch, |
||||
Post, |
||||
Query, |
||||
Request, |
||||
} from '@nestjs/common'; |
||||
import { PagedResponseImpl } from '../../helpers/PagedResponse'; |
||||
import { Acl } from '../../middlewares/extract-project-id/extract-project-id.middleware'; |
||||
import { Audit } from '../../models'; |
||||
import { AuditsService } from './audits.service'; |
||||
|
||||
@Controller('audits') |
||||
export class AuditsController { |
||||
constructor(private readonly auditsService: AuditsService) {} |
||||
|
||||
@Post('/api/v1/db/meta/audits/comments') |
||||
@Acl('commentRow') |
||||
async commentRow(@Request() req) { |
||||
return await this.auditsService.commentRow({ |
||||
// todo: correct this
|
||||
rowId: req.params.rowId ?? req.query.rowId, |
||||
user: (req as any).user, |
||||
body: req.body, |
||||
}); |
||||
} |
||||
|
||||
@Post('/api/v1/db/meta/audits/rows/:rowId/update') |
||||
@Acl('auditRowUpdate') |
||||
async auditRowUpdate(@Param('rowId') rowId: string, @Body() body: any) { |
||||
return await this.auditsService.auditRowUpdate({ |
||||
rowId, |
||||
body, |
||||
}); |
||||
} |
||||
|
||||
@Get('/api/v1/db/meta/audits/comments') |
||||
@Acl('commentList') |
||||
async commentList(@Request() req) { |
||||
return new PagedResponseImpl( |
||||
await this.auditsService.commentList({ query: req.query }), |
||||
); |
||||
} |
||||
|
||||
@Patch('/api/v1/db/meta/audits/:auditId/comment') |
||||
@Acl('commentUpdate') |
||||
async commentUpdate( |
||||
@Param('auditId') auditId: string, |
||||
@Request() req, |
||||
@Body() body: any, |
||||
) { |
||||
return await this.auditsService.commentUpdate({ |
||||
auditId, |
||||
userEmail: req.user?.email, |
||||
body: body, |
||||
}); |
||||
} |
||||
|
||||
@Get('/api/v1/db/meta/projects/:projectId/audits') |
||||
@Acl('auditList') |
||||
async auditList(@Request() req, @Param('projectId') projectId: string) { |
||||
return new PagedResponseImpl( |
||||
await this.auditsService.auditList({ |
||||
query: req.query, |
||||
projectId, |
||||
}), |
||||
{ |
||||
count: await Audit.projectAuditCount(projectId), |
||||
...req.query, |
||||
}, |
||||
); |
||||
} |
||||
|
||||
@Get('/api/v1/db/meta/audits/comments/count') |
||||
@Acl('commentsCount') |
||||
async commentsCount( |
||||
@Query('fk_model_id') fk_model_id: string, |
||||
@Query('ids') ids: string[], |
||||
) { |
||||
return await this.auditsService.commentsCount({ |
||||
fk_model_id, |
||||
ids, |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common'; |
||||
import { AuditsService } from './audits.service'; |
||||
import { AuditsController } from './audits.controller'; |
||||
|
||||
@Module({ |
||||
controllers: [AuditsController], |
||||
providers: [AuditsService] |
||||
}) |
||||
export class AuditsModule {} |
@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing'; |
||||
import { AuditsService } from './audits.service'; |
||||
|
||||
describe('AuditsService', () => { |
||||
let service: AuditsService; |
||||
|
||||
beforeEach(async () => { |
||||
const module: TestingModule = await Test.createTestingModule({ |
||||
providers: [AuditsService], |
||||
}).compile(); |
||||
|
||||
service = module.get<AuditsService>(AuditsService); |
||||
}); |
||||
|
||||
it('should be defined', () => { |
||||
expect(service).toBeDefined(); |
||||
}); |
||||
}); |
@ -0,0 +1,85 @@
|
||||
import { Injectable } from '@nestjs/common'; |
||||
import DOMPurify from 'isomorphic-dompurify'; |
||||
import { |
||||
AuditOperationSubTypes, |
||||
AuditOperationTypes, |
||||
AuditRowUpdateReqType, |
||||
CommentUpdateReqType, |
||||
} from 'nocodb-sdk'; |
||||
import { validatePayload } from '../../helpers'; |
||||
import { NcError } from '../../helpers/catchError'; |
||||
import { Audit, Model } from '../../models'; |
||||
|
||||
@Injectable() |
||||
export class AuditsService { |
||||
async commentRow(param: { |
||||
rowId: string; |
||||
body: AuditRowUpdateReqType; |
||||
user: any; |
||||
}) { |
||||
validatePayload('swagger.json#/components/schemas/CommentReq', param.body); |
||||
|
||||
return await Audit.insert({ |
||||
...param.body, |
||||
user: param.user?.email, |
||||
op_type: AuditOperationTypes.COMMENT, |
||||
}); |
||||
} |
||||
|
||||
async auditRowUpdate(param: { rowId: string; body: AuditRowUpdateReqType }) { |
||||
validatePayload( |
||||
'swagger.json#/components/schemas/AuditRowUpdateReq', |
||||
param.body, |
||||
); |
||||
|
||||
const model = await Model.getByIdOrName({ id: param.body.fk_model_id }); |
||||
return await Audit.insert({ |
||||
fk_model_id: param.body.fk_model_id, |
||||
row_id: param.rowId, |
||||
op_type: AuditOperationTypes.DATA, |
||||
op_sub_type: AuditOperationSubTypes.UPDATE, |
||||
description: DOMPurify.sanitize( |
||||
`Table ${model.table_name} : field ${param.body.column_name} got changed from ${param.body.prev_value} to ${param.body.value}`, |
||||
), |
||||
details: |
||||
DOMPurify.sanitize(`<span class="">${param.body.column_name}</span>
|
||||
: <span class="text-decoration-line-through red px-2 lighten-4 black--text">${param.body.prev_value}</span> |
||||
<span class="black--text green lighten-4 px-2">${param.body.value}</span>`),
|
||||
ip: (param as any).clientIp, |
||||
user: (param as any).user?.email, |
||||
}); |
||||
} |
||||
|
||||
async commentList(param: { query: any }) { |
||||
return await Audit.commentsList(param.query); |
||||
} |
||||
|
||||
async auditList(param: { query: any; projectId: string }) { |
||||
return await Audit.projectAuditList(param.projectId, param.query); |
||||
} |
||||
|
||||
async commentsCount(param: { fk_model_id: string; ids: string[] }) { |
||||
return await Audit.commentsCount({ |
||||
fk_model_id: param.fk_model_id as string, |
||||
ids: param.ids as string[], |
||||
}); |
||||
} |
||||
|
||||
async commentUpdate(param: { |
||||
auditId: string; |
||||
userEmail: string; |
||||
body: CommentUpdateReqType; |
||||
}) { |
||||
validatePayload( |
||||
'swagger.json#/components/schemas/CommentUpdateReq', |
||||
param.body, |
||||
); |
||||
|
||||
const log = await Audit.get(param.auditId); |
||||
|
||||
if (log.user !== param.userEmail) { |
||||
NcError.unauthorized('Unauthorized access'); |
||||
} |
||||
return await Audit.commentUpdate(param.auditId, param.body); |
||||
} |
||||
} |
Loading…
Reference in new issue