diff --git a/apps/api/src/variable/controller/variable.controller.ts b/apps/api/src/variable/controller/variable.controller.ts index 3a784fc2..a890813a 100644 --- a/apps/api/src/variable/controller/variable.controller.ts +++ b/apps/api/src/variable/controller/variable.controller.ts @@ -99,4 +99,24 @@ export class VariableController { environmentId ) } + + @Get('/:variableId/revisions/:environmentId') + @RequiredApiKeyAuthorities(Authority.READ_VARIABLE) + async getRevisionsOfVariable( + @CurrentUser() user: User, + @Param('variableId') variableId: string, + @Param('environmentId') environmentId: string, + @Query('page') page: number = 0, + @Query('limit') limit: number = 10, + @Query('order') order: 'asc' | 'desc' = 'desc' + ) { + return await this.variableService.getRevisionsOfVariable( + user, + variableId, + environmentId, + page, + limit, + order + ) + } } diff --git a/apps/api/src/variable/service/variable.service.ts b/apps/api/src/variable/service/variable.service.ts index 9a932952..38f8598e 100644 --- a/apps/api/src/variable/service/variable.service.ts +++ b/apps/api/src/variable/service/variable.service.ts @@ -625,6 +625,43 @@ export class VariableService { return { items, metadata } } + async getRevisionsOfVariable( + user: User, + variableId: Variable['id'], + environmentId: Environment['id'], + page: number, + limit: number, + order: 'asc' | 'desc' + ) { + await this.authorityCheckerService.checkAuthorityOverVariable({ + userId: user.id, + entity: { id: variableId }, + authority: Authority.READ_VARIABLE, + prisma: this.prisma + }) + + await this.authorityCheckerService.checkAuthorityOverEnvironment({ + userId: user.id, + entity: { id: environmentId }, + authority: Authority.READ_ENVIRONMENT, + prisma: this.prisma + }) + + const revisions = await this.prisma.variableVersion.findMany({ + where: { + variableId: variableId, + environmentId: environmentId + }, + skip: page * limit, + take: limit, + orderBy: { + version: order + } + }) + + return revisions + } + private async variableExists( variableName: Variable['name'], projectId: Project['id'] diff --git a/apps/api/src/variable/variable.e2e.spec.ts b/apps/api/src/variable/variable.e2e.spec.ts index eb215cd2..e999b58a 100644 --- a/apps/api/src/variable/variable.e2e.spec.ts +++ b/apps/api/src/variable/variable.e2e.spec.ts @@ -556,7 +556,7 @@ describe('Variable Controller Tests', () => { ) }) - it('should not create a secret version entity if value-environmentId is not provided during creation', async () => { + it('should not create a variable version entity if value-environmentId is not provided during creation', async () => { const variable = await variableService.createVariable( user1, { @@ -764,4 +764,108 @@ describe('Variable Controller Tests', () => { expect(event.workspaceId).toBe(workspace1.id) expect(event.itemId).toBeDefined() }) + + //revisions test + it('should be able to fetch all revisions of variables', async () => { + // create two more entries,totalling three versions + // checks if its able to fetch multiple revisions + await variableService.updateVariable(user1, variable1.id, { + entries: [ + { + value: 'Updated Variable 1 value', + environmentId: environment1.id + } + ] + }) + + await variableService.updateVariable(user1, variable1.id, { + entries: [ + { + value: 'Updated variable 1 value 2', + environmentId: environment1.id + } + ] + }) + + const response = await app.inject({ + method: 'GET', + url: `/variable/${variable1.id}/revisions/${environment1.id}`, + headers: { + 'x-e2e-user-email': user1.email + } + }) + + expect(response.statusCode).toBe(200) + expect(response.json().length).toBe(3) + }) + + it('should return [] if the variable has no revision', async () => { + //returns [] if variable has no revision + await prisma.variableVersion.deleteMany({ + where: { + variableId: variable1.id + } + }) + + const response = await app.inject({ + method: 'GET', + url: `/variable/${variable1.id}/revisions/${environment1.id}`, + headers: { + 'x-e2e-user-email': user1.email + } + }) + + expect(response.statusCode).toBe(200) + expect(response.json().length).toBe(0) + }) + + it('should return error if variable doesnt exist', async () => { + //return error if variable doesnt exist + const variableid = 'nonexistentvariable' + const response = await app.inject({ + method: 'GET', + url: `/variable/${variableid}/revisions/${environment1.id}`, + headers: { + 'x-e2e-user-email': user1.email + } + }) + + expect(response.statusCode).toBe(404) + expect(response.json().message).toEqual( + `Variable with id ${variableid} not found` + ) + }) + + it('should return error if environment doesnt exist', async () => { + //return error if environment doesnt exist + const environmentid = 'nonexistentenvironment' + const response = await app.inject({ + method: 'GET', + url: `/variable/${variable1.id}/revisions/${environmentid}`, + headers: { + 'x-e2e-user-email': user1.email + } + }) + + expect(response.statusCode).toBe(404) + expect(response.json().message).toEqual( + `Environment with id ${environmentid} not found` + ) + }) + + it('returns error if variable isnt accessible', async () => { + //return error if user has no access to variable + const response = await app.inject({ + method: 'GET', + url: `/variable/${variable1.id}/revisions/${environment1.id}`, + headers: { + 'x-e2e-user-email': user2.email + } + }) + + expect(response.statusCode).toBe(401) + expect(response.json().message).toEqual( + `User ${user2.id} does not have the required authorities` + ) + }) })