Skip to content

Commit

Permalink
feat: Variables listing revamp (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
rajdip-b authored Feb 10, 2025
1 parent f9b095c commit 38b42fa
Show file tree
Hide file tree
Showing 19 changed files with 319 additions and 388 deletions.

This file was deleted.

14 changes: 0 additions & 14 deletions apps/api/src/variable/controller/variable.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,6 @@ export class VariableController {
)
}

@Get('/:projectSlug/:environmentSlug')
@RequiredApiKeyAuthorities(Authority.READ_VARIABLE)
async getAllVariablesOfEnvironment(
@CurrentUser() user: User,
@Param('projectSlug') projectSlug: string,
@Param('environmentSlug') environmentSlug: string
) {
return await this.variableService.getAllVariablesOfProjectAndEnvironment(
user,
projectSlug,
environmentSlug
)
}

@Get('/:variableSlug/revisions/:environmentSlug')
@RequiredApiKeyAuthorities(Authority.READ_VARIABLE)
async getRevisionsOfVariable(
Expand Down
135 changes: 47 additions & 88 deletions apps/api/src/variable/service/variable.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ import { RedisClientType } from 'redis'
import { REDIS_CLIENT } from '@/provider/redis.provider'
import { CHANGE_NOTIFIER_RSC } from '@/socket/change-notifier.socket'
import { AuthorityCheckerService } from '@/common/authority-checker.service'
import {
ChangeNotification,
ChangeNotificationEvent
} from 'src/socket/socket.types'
import { ChangeNotificationEvent } from 'src/socket/socket.types'
import { paginate } from '@/common/paginate'
import { getEnvironmentIdToSlugMap } from '@/common/environment'
import generateEntitySlug from '@/common/slug-generator'
Expand Down Expand Up @@ -130,7 +127,14 @@ export class VariableService {
}
},
version: true,
value: true
value: true,
createdBy: {
select: {
id: true,
name: true,
profilePictureUrl: true
}
}
}
}
}
Expand Down Expand Up @@ -470,85 +474,6 @@ export class VariableService {
this.logger.log(`User ${user.id} deleted variable ${variable.id}`)
}

/**
* Gets all variables of a project and environment.
* @param user the user performing the action
* @param projectSlug the slug of the project to get the variables from
* @param environmentSlug the slug of the environment to get the variables from
* @returns an array of objects containing the name, value and whether the value is a plaintext
* @throws `NotFoundException` if the project or environment does not exist
* @throws `ForbiddenException` if the user does not have the required authority
*/
async getAllVariablesOfProjectAndEnvironment(
user: User,
projectSlug: Project['slug'],
environmentSlug: Environment['slug']
) {
// Check if the user has the required authorities in the project
const { id: projectId } =
await this.authorityCheckerService.checkAuthorityOverProject({
userId: user.id,
entity: { slug: projectSlug },
authorities: [Authority.READ_VARIABLE],
prisma: this.prisma
})

// Check if the user has the required authorities in the environment
const { id: environmentId } =
await this.authorityCheckerService.checkAuthorityOverEnvironment({
userId: user.id,
entity: { slug: environmentSlug },
authorities: [Authority.READ_ENVIRONMENT],
prisma: this.prisma
})

const variables = await this.prisma.variable.findMany({
where: {
projectId,
versions: {
some: {
environmentId
}
}
},
include: {
lastUpdatedBy: {
select: {
id: true,
name: true
}
},
versions: {
where: {
environmentId
},
select: {
value: true,
environment: {
select: {
id: true,
slug: true
}
}
},
orderBy: {
version: 'desc'
},
take: 1
}
}
})

return variables.map(
(variable) =>
({
name: variable.name,
value: variable.versions[0].value,
isPlaintext: true
}) as ChangeNotification
)
}

/**
* Gets all variables of a project, paginated, sorted and filtered by search query.
* @param user the user performing the action
Expand Down Expand Up @@ -591,7 +516,8 @@ export class VariableService {
lastUpdatedBy: {
select: {
id: true,
name: true
name: true,
profilePictureUrl: true
}
},
versions: {
Expand All @@ -604,7 +530,15 @@ export class VariableService {
id: true,
slug: true
}
}
},
createdBy: {
select: {
id: true,
name: true,
profilePictureUrl: true
}
},
createdOn: true
}
}
},
Expand All @@ -625,6 +559,12 @@ export class VariableService {
}
value: VariableVersion['value']
version: VariableVersion['version']
createdBy: {
id: User['id']
name: User['name']
profilePictureUrl: User['profilePictureUrl']
}
createdOn: VariableVersion['createdOn']
}[]
}>()

Expand All @@ -641,6 +581,11 @@ export class VariableService {
slug: Environment['slug']
name: Environment['name']
}
createdBy: {
id: User['id']
name: User['name']
profilePictureUrl: User['profilePictureUrl']
}
}
>()

Expand Down Expand Up @@ -672,7 +617,13 @@ export class VariableService {
slug: variableVersion.environment.slug
},
value: variableVersion.value,
version: variableVersion.version
version: variableVersion.version,
createdBy: {
id: variableVersion.createdBy.id,
name: variableVersion.createdBy.name,
profilePictureUrl: variableVersion.createdBy.profilePictureUrl
},
createdOn: variableVersion.createdOn
})
)
)
Expand Down Expand Up @@ -747,9 +698,17 @@ export class VariableService {
},
skip: page * limit,
take: limitMaxItemsPerPage(limit),

orderBy: {
version: order
},
include: {
createdBy: {
select: {
id: true,
name: true,
profilePictureUrl: true
}
}
}
})

Expand Down
65 changes: 4 additions & 61 deletions apps/api/src/variable/variable.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,8 @@ describe('Variable Controller Tests', () => {
lastUpdatedById: variable1.lastUpdatedById,
lastUpdatedBy: {
id: user1.id,
name: user1.name
name: user1.name,
profilePictureUrl: user1.profilePictureUrl
},
createdAt: variable1.createdAt.toISOString(),
updatedAt: variable1.updatedAt.toISOString()
Expand Down Expand Up @@ -682,7 +683,8 @@ describe('Variable Controller Tests', () => {
lastUpdatedById: variable1.lastUpdatedById,
lastUpdatedBy: {
id: user1.id,
name: user1.name
name: user1.name,
profilePictureUrl: user1.profilePictureUrl
},
createdAt: variable1.createdAt.toISOString(),
updatedAt: expect.any(String)
Expand Down Expand Up @@ -732,65 +734,6 @@ describe('Variable Controller Tests', () => {
})
})

describe('Get All Variables By Project And Environment Tests', () => {
it('should be able to fetch all variables by project and environment', async () => {
const response = await app.inject({
method: 'GET',
url: `/variable/${project1.slug}/${environment1.slug}`,
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(200)
expect(response.json().length).toBe(1)

const variable = response.json()[0]
expect(variable.name).toBe('Variable 1')
expect(variable.value).toBe('Variable 1 value')
expect(variable.isPlaintext).toBe(true)
})

it('should not be able to fetch all variables by project and environment if the user has no access to the project', async () => {
const response = await app.inject({
method: 'GET',
url: `/variable/${project1.slug}/${environment1.slug}`,
headers: {
'x-e2e-user-email': user2.email
}
})

expect(response.statusCode).toBe(401)
})

it('should not be able to fetch all variables by project and environment if the project does not exist', async () => {
const response = await app.inject({
method: 'GET',
url: `/variable/non-existing-project-slug/${environment1.slug}`,
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(404)
expect(response.json().message).toEqual(
'Project non-existing-project-slug not found'
)
})

it('should not be able to fetch all variables by project and environment if the environment does not exist', async () => {
const response = await app.inject({
method: 'GET',
url: `/variable/${project1.slug}/non-existing-environment-slug`,
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(404)
})
})

describe('Delete Variable Tests', () => {
it('should not be able to delete a non-existing variable', async () => {
const response = await app.inject({
Expand Down
5 changes: 5 additions & 0 deletions apps/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,8 @@
- Formatted outputs of `keyshade secret list` and `keyshade secret revisions` commands
- Update `keyshade secret rollback` to check for missing environment or version
- Added usage examples in secret commands
- Removed `keyshade variable get` command
- Updated `keyshade variable update` and `keyshade variable create` commands to include `-e/--entry` flag for specifying values to environments
- Formatted outputs of `keyshade variable list` and `keyshade variable revisions` commands
- Update `keyshade variable rollback` to check for missing environment or version
- Added usage examples in variable commands
Loading

0 comments on commit 38b42fa

Please sign in to comment.