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

feat(api): Add requireRestart parameter #286

Merged
merged 5 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
yogesh1801 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "Secret" ADD COLUMN "requireRestart" BOOLEAN DEFAULT false;

-- AlterTable
ALTER TABLE "Variable" ADD COLUMN "requireRestart" BOOLEAN NOT NULL DEFAULT false;
28 changes: 15 additions & 13 deletions apps/api/src/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -358,13 +358,14 @@ model SecretVersion {
}

model Secret {
id String @id @default(cuid())
name String
versions SecretVersion[] // Stores the versions of the secret
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
rotateAt DateTime?
note String?
id String @id @default(cuid())
name String
versions SecretVersion[] // Stores the versions of the secret
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
rotateAt DateTime?
note String?
requireRestart Boolean @default(false)

lastUpdatedBy User? @relation(fields: [lastUpdatedById], references: [id], onUpdate: Cascade, onDelete: SetNull)
lastUpdatedById String?
Expand Down Expand Up @@ -394,12 +395,13 @@ model VariableVersion {
}

model Variable {
id String @id @default(cuid())
name String
versions VariableVersion[] // Stores the versions of the variable
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
note String?
id String @id @default(cuid())
name String
versions VariableVersion[] // Stores the versions of the variable
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
note String?
requireRestart Boolean @default(false)

lastUpdatedBy User? @relation(fields: [lastUpdatedById], references: [id], onUpdate: Cascade, onDelete: SetNull)
lastUpdatedById String?
Expand Down
6 changes: 6 additions & 0 deletions apps/api/src/secret/dto/create.secret/create.secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
IsArray,
IsOptional,
IsString,
IsBoolean,
Length,
ValidateNested
} from 'class-validator'
Expand All @@ -21,6 +22,11 @@ export class CreateSecret {
@IsOptional()
rotateAfter?: '24' | '168' | '720' | '8760' | 'never' = 'never'

@IsBoolean()
@IsOptional()
@Transform(({ value }) => value === 'true' || value === true)
requireRestart?: boolean

@IsOptional()
@IsArray()
@ValidateNested({ each: true })
Expand Down
58 changes: 58 additions & 0 deletions apps/api/src/secret/secret.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,40 @@ describe('Secret Controller Tests', () => {
expect(body.versions[0].value).not.toBe('Secret 2 value')
})

it('should be able to create a secret with requireRestart set to true', async () => {
const response = await app.inject({
method: 'POST',
url: `/secret/${project1.id}`,
payload: {
name: 'Secret 3',
note: 'Secret 3 note',
requireRestart: true,
entries: [
{
value: 'Secret 3 value',
environmentId: environment1.id
}
],
rotateAfter: '24'
},
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(201)

const body = response.json()

expect(body).toBeDefined()
expect(body.name).toBe('Secret 3')
expect(body.note).toBe('Secret 3 note')
expect(body.requireRestart).toBe(true)
expect(body.projectId).toBe(project1.id)
expect(body.versions.length).toBe(1)
expect(body.versions[0].value).not.toBe('Secret 3 value')
})

it('should have created a secret version', async () => {
const secretVersion = await prisma.secretVersion.findFirst({
where: {
Expand Down Expand Up @@ -343,6 +377,30 @@ describe('Secret Controller Tests', () => {
expect(secretVersion.length).toBe(1)
})

it('should be able to update the requireRestart Param without creating a new version', async () => {
const response = await app.inject({
method: 'PUT',
url: `/secret/${secret1.id}`,
payload: {
requireRestart: true
},
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(200)
expect(response.json().requireRestart).toEqual(true)

const secretVersion = await prisma.secretVersion.findMany({
where: {
secretId: secret1.id
}
})

expect(secretVersion.length).toBe(1)
})

it('should create a new version if the value is updated', async () => {
const response = await app.inject({
method: 'PUT',
Expand Down
4 changes: 4 additions & 0 deletions apps/api/src/secret/service/secret.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class SecretService {
name: dto.name,
note: dto.note,
rotateAt: addHoursToDate(dto.rotateAfter),
requireRestart: dto.requireRestart,
versions: shouldCreateRevisions && {
createMany: {
data: await Promise.all(
Expand Down Expand Up @@ -198,6 +199,7 @@ export class SecretService {
data: {
name: dto.name,
note: dto.note,
requireRestart: dto.requireRestart,
rotateAt: dto.rotateAfter
? addHoursToDate(dto.rotateAfter)
: undefined,
Expand Down Expand Up @@ -268,6 +270,7 @@ export class SecretService {
environmentId: entry.environmentId,
name: updatedSecret.name,
value: entry.value,
requireRestart: dto.requireRestart,
isSecret: true
})
)
Expand Down Expand Up @@ -352,6 +355,7 @@ export class SecretService {
environmentId,
name: secret.name,
value: secret.versions[rollbackVersion - 1].value,
requireRestart: secret.requireRestart,
isSecret: true
})
)
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/socket/socket.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface ChangeNotifierRegistration {
export interface ChangeNotification {
name: string
value: string
requireRestart: boolean
isSecret: boolean
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
IsArray,
IsOptional,
IsString,
IsBoolean,
Length,
ValidateNested
} from 'class-validator'
Expand All @@ -19,6 +20,11 @@ export class CreateVariable {
@Transform(({ value }) => (value ? value.trim() : null))
note?: string

@IsBoolean()
@IsOptional()
@Transform(({ value }) => value === 'true' || value === true)
requireRestart?: boolean

@IsOptional()
@IsArray()
@ValidateNested({ each: true })
Expand Down
4 changes: 4 additions & 0 deletions apps/api/src/variable/service/variable.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class VariableService {
data: {
name: dto.name,
note: dto.note,
requireRestart: dto.requireRestart,
versions: shouldCreateRevisions && {
createMany: {
data: dto.entries.map((entry) => ({
Expand Down Expand Up @@ -200,6 +201,7 @@ export class VariableService {
data: {
name: dto.name,
note: dto.note,
requireRestart: dto.requireRestart,
lastUpdatedById: user.id
},
include: {
Expand Down Expand Up @@ -266,6 +268,7 @@ export class VariableService {
environmentId: entry.environmentId,
name: updatedVariable.name,
value: entry.value,
requireRestart: dto.requireRestart,
isSecret: false
})
)
Expand Down Expand Up @@ -353,6 +356,7 @@ export class VariableService {
environmentId,
name: variable.name,
value: variable.versions[rollbackVersion - 1].value,
requireRestart: variable.requireRestart,
isSecret: false
})
)
Expand Down
66 changes: 66 additions & 0 deletions apps/api/src/variable/variable.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,48 @@ describe('Variable Controller Tests', () => {
expect(variable).toBeDefined()
})

it('should be able to create a variable with requireRestart set to true', async () => {
const response = await app.inject({
method: 'POST',
url: `/variable/${project1.id}`,
payload: {
name: 'Variable 4',
note: 'Variable 4 note',
requireRestart: true,
rotateAfter: '24',
entries: [
{
value: 'Variable 4 value',
environmentId: environment2.id
}
]
},
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(201)

const body = response.json()

expect(body).toBeDefined()
expect(body.name).toBe('Variable 4')
expect(body.note).toBe('Variable 4 note')
expect(body.requireRestart).toBe(true)
expect(body.projectId).toBe(project1.id)
expect(body.versions.length).toBe(1)
expect(body.versions[0].value).toBe('Variable 4 value')

const variable = await prisma.variable.findUnique({
where: {
id: body.id
}
})

expect(variable).toBeDefined()
})

it('should have created a variable version', async () => {
const variableVersion = await prisma.variableVersion.findFirst({
where: {
Expand Down Expand Up @@ -363,6 +405,30 @@ describe('Variable Controller Tests', () => {
expect(variableVersion.length).toBe(1)
})

it('should be able to update requireRestart param without creating a new version', async () => {
const response = await app.inject({
method: 'PUT',
url: `/variable/${variable1.id}`,
payload: {
requireRestart: true
},
headers: {
'x-e2e-user-email': user1.email
}
})

expect(response.statusCode).toBe(200)
expect(response.json().requireRestart).toEqual(true)

const variableVersion = await prisma.variableVersion.findMany({
where: {
variableId: variable1.id
}
})

expect(variableVersion.length).toBe(1)
})

it('should create a new version if the value is updated', async () => {
const response = await app.inject({
method: 'PUT',
Expand Down
2 changes: 1 addition & 1 deletion apps/platform/src/lib/workspace-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ export function getCurrentWorkspace(): Workspace | null {

export function setCurrentWorkspace(workspace: Workspace): void {
localStorage.setItem('currentWorkspace', JSON.stringify(workspace))
}
}