Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(api): Update return type while fetching secrets and variables #264

Merged
merged 4 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/api/src/secret/secret.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -840,8 +840,9 @@ describe('Secret Controller Tests', () => {

expect(response.statusCode).toBe(200)
expect(response.json().length).toBe(1)
const secret = response.json()[0]
expect(secret.secrets[0].versions[0].value).toEqual('Secret 1 value')
const envsecret = response.json()[0]
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
expect(envsecret.environment).toHaveProperty('id')
expect(envsecret.environment).toHaveProperty('name')
})

it('should not be able to fetch all secrets decrypted if the project does not store the private key', async () => {
Expand Down
6 changes: 6 additions & 0 deletions apps/api/src/secret/secret.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ export interface SecretWithEnvironment extends Secret {
environment: Environment
}

export type SecretsByEnvironment = {
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
environment: { id: string; name: string }
secrets: any[]
}
export type SecretWithProjectAndVersion = SecretWithProject & SecretWithVersion
export type SecretWithVersionAndEnvironment = SecretWithVersion &
SecretWithEnvironment
63 changes: 16 additions & 47 deletions apps/api/src/secret/service/secret.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
import { addHoursToDate } from '../../common/add-hours-to-date'
import { encrypt } from '../../common/encrypt'
import {
SecretWithEnvironment,

Check warning on line 29 in apps/api/src/secret/service/secret.service.ts

View workflow job for this annotation

GitHub Actions / Validate API

'SecretWithEnvironment' is defined but never used
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
SecretWithProject,
SecretWithProjectAndVersion,
SecretWithVersion
SecretWithVersion,

Check warning on line 32 in apps/api/src/secret/service/secret.service.ts

View workflow job for this annotation

GitHub Actions / Validate API

'SecretWithVersion' is defined but never used
SecretWithVersionAndEnvironment,
SecretsByEnvironment
} from '../secret.types'
import createEvent from '../../common/create-event'
import getDefaultEnvironmentOfProject from '../../common/get-default-project-environment'
Expand Down Expand Up @@ -488,7 +491,7 @@
orderBy: {
[sort]: order
}
})) as SecretWithVersion[]
})) as unknown as SecretWithVersionAndEnvironment[]
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved

if (decryptValue) {
for (const secret of secrets) {
Expand All @@ -502,62 +505,28 @@
}
}
}

// Group secrets by environment
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
const secretsByEnvironment = await secrets.reduce(
async (accPromise, secret) => {
const acc = await accPromise
const environmentName = await this.getEnvironmentName(
secret.environmentId
)

if (!acc[secret.environmentId]) {
acc[secret.environmentId] = {
environmentName: environmentName,
environmentId: secret.environmentId,
const secretsByEnvironment = secrets.reduce((acc, secret) => {
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
const { environment } = secret
if (environment) {
const { id, name } = environment
if (!acc[id]) {
acc[id] = {
environment: { id, name },
secrets: []
}
}

acc[secret.environmentId].secrets.push(secret)
return acc
},
Promise.resolve({})
)
acc[id].secrets.push(secret)
}
return acc
}, {} as SecretsByEnvironment)

// Convert the result to an array
const clusteredSecrets = Object.values(secretsByEnvironment)

console.log(clusteredSecrets)

return clusteredSecrets
}

private async getEnvironmentName(
environmentId: string
): Promise<string | null> {
try {
// Fetch the environment using its unique ID
const environment = await this.prisma.environment.findUnique({
where: {
id: environmentId
}
})

// Check if the environment exists
if (environment) {
// Access and return the name property
return environment.name
} else {
console.log('Environment not found')
return null
}
} catch (error) {
console.error('Error fetching environment:', error)
return null
}
}

private async secretExists(
secretName: Secret['name'],
environmentId: Environment['id']
Expand Down
122 changes: 57 additions & 65 deletions apps/api/src/variable/service/variable.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import createApproval from '../../common/create-approval'
import { UpdateVariableMetadata } from '../../approval/approval.types'
import {
VariableWithProject,
VariableWithProjectAndVersion
VariableWithProjectAndVersion,
VariablesByEnvironment
} from '../variable.types'
import { RedisClientType } from 'redis'
import { REDIS_CLIENT } from '../../provider/redis.provider'
Expand Down Expand Up @@ -413,79 +414,70 @@ export class VariableService {
sort: string,
order: string,
search: string
): Promise<
{ environmentName: string; environmentId: string; variables: any[] }[]
> {
try {
// Check if the user has the required authorities in the project
await this.authorityCheckerService.checkAuthorityOverProject({
userId: user.id,
entity: { id: projectId },
authority: Authority.READ_VARIABLE,
prisma: this.prisma
})
): Promise<VariablesByEnvironment[]> {
// Check if the user has the required authorities in the project
await this.authorityCheckerService.checkAuthorityOverProject({
userId: user.id,
entity: { id: projectId },
authority: Authority.READ_VARIABLE,
prisma: this.prisma
})

const variables = await this.prisma.variable.findMany({
where: {
projectId,
pendingCreation: false,
name: {
contains: search
}
},
include: {
versions: {
orderBy: {
version: 'desc'
},
take: 1
},
lastUpdatedBy: {
select: {
id: true,
name: true
}
const variables = await this.prisma.variable.findMany({
where: {
projectId,
pendingCreation: false,
name: {
contains: search
}
},
include: {
versions: {
orderBy: {
version: 'desc'
},
environment: {
select: {
id: true,
name: true
}
take: 1
},
lastUpdatedBy: {
select: {
id: true,
name: true
}
},
skip: page * limit,
take: limit,
orderBy: {
[sort]: order
}
})

// Group variables by environment
const variablesByEnvironment: {
[key: string]: {
environmentName: string
environmentId: string
variables: any[]
}
} = {}
for (const variable of variables) {
const { id, name } = variable.environment
if (!variablesByEnvironment[id]) {
variablesByEnvironment[id] = {
environmentName: name,
environmentId: id,
variables: []
environment: {
select: {
id: true,
name: true
}
}
variablesByEnvironment[id].variables.push(variable)
},
skip: page * limit,
take: limit,
orderBy: {
[sort]: order
}
})

// Convert the object to an array and return
return Object.values(variablesByEnvironment)
} catch (error) {
console.error('Error fetching variables:', error)
throw error // Or handle the error as per your application's requirement
// Group variables by environment
const variablesByEnvironment: {
[key: string]: {
environment: { id: string; name: string }
variables: any[]
}
} = {}
for (const variable of variables) {
const { id, name } = variable.environment
if (!variablesByEnvironment[id]) {
variablesByEnvironment[id] = {
environment: { id, name },
variables: []
}
}
variablesByEnvironment[id].variables.push(variable)
}

// Convert the object to an array and return
return Object.values(variablesByEnvironment)
}

private async variableExists(
Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/variable/variable.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,9 @@ describe('Variable Controller Tests', () => {

expect(response.statusCode).toBe(200)
expect(response.json().length).toBe(1)
const envvariable = response.json()[0]
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
expect(envvariable.environment).toHaveProperty('id')
expect(envvariable.environment).toHaveProperty('name')
})

it('should not be able to fetch all variables if the user has no access to the project', async () => {
Expand Down
5 changes: 5 additions & 0 deletions apps/api/src/variable/variable.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@ export interface VariableWithEnvironment extends Variable {
environment: Environment
}

export type VariablesByEnvironment = {
rajdip-b marked this conversation as resolved.
Show resolved Hide resolved
environment: { id: string; name: string }
variables: any[]
}

export type VariableWithProjectAndVersion = VariableWithProject &
VariableWithVersion
Loading