Skip to content

Commit

Permalink
feat(cli): Added CLI (keyshade-xyz#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
rajdip-b authored and yogesh1801 committed Jun 29, 2024
1 parent 25fb4c9 commit 35e5279
Show file tree
Hide file tree
Showing 37 changed files with 1,648 additions and 288 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ Thumbs.db
.env.sentry-build-plugin

# turbo
.turbo
.turbo

keyshade.json
2 changes: 0 additions & 2 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@
"@nestjs/websockets": "^10.3.7",
"@socket.io/redis-adapter": "^8.3.0",
"@supabase/supabase-js": "^2.39.6",
"chalk": "^4.1.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"cookie-parser": "^1.4.6",
"eccrypto": "^1.1.6",
"minio": "^8.0.0",
"moment": "^2.30.1",
"nodemailer": "^6.9.9",
"passport-github2": "^0.1.12",
"passport-gitlab2": "^5.0.0",
Expand Down
38 changes: 37 additions & 1 deletion apps/api/src/api-key/api-key.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { MAIL_SERVICE } from '../mail/services/interface.service'
import { MockMailService } from '../mail/services/mock.service'
import { AppModule } from '../app/app.module'
import { Test } from '@nestjs/testing'
import { ApiKey, User } from '@prisma/client'
import { ApiKey, Authority, User } from '@prisma/client'
import { ApiKeyService } from './service/api-key.service'

describe('Api Key Role Controller Tests', () => {
Expand Down Expand Up @@ -252,6 +252,42 @@ describe('Api Key Role Controller Tests', () => {
expect(response.statusCode).toBe(401)
})

it('should be able to access live updates if API key has the required authorities', async () => {
// Create a new API key with the required authorities
const newApiKey = await apiKeyService.createApiKey(user, {
name: 'Test Key 2',
authorities: [
Authority.READ_SECRET,
Authority.READ_VARIABLE,
Authority.READ_ENVIRONMENT,
Authority.READ_PROJECT,
Authority.READ_WORKSPACE
]
})

const response = await app.inject({
method: 'GET',
url: '/api-key/access/live-updates',
headers: {
'x-keyshade-token': newApiKey.value
}
})

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

it('should not be able to access live updates if API key does not have the required authorities', async () => {
const response = await app.inject({
method: 'GET',
url: '/api-key/access/live-updates',
headers: {
'x-keyshade-token': apiKey.value
}
})

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

it('should be able to delete the api key', async () => {
const response = await app.inject({
method: 'DELETE',
Expand Down
14 changes: 14 additions & 0 deletions apps/api/src/api-key/controller/api-key.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,18 @@ export class ApiKeyController {
search
)
}

@Get('/access/live-updates')
@RequiredApiKeyAuthorities(
Authority.READ_SECRET,
Authority.READ_VARIABLE,
Authority.READ_ENVIRONMENT,
Authority.READ_PROJECT,
Authority.READ_WORKSPACE
)
async canAccessLiveUpdates() {
return {
canAccessLiveUpdates: true
}
}
}
23 changes: 18 additions & 5 deletions apps/api/src/api-key/service/api-key.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,31 @@ export class ApiKeyService {
}

async updateApiKey(user: User, apiKeyId: string, dto: UpdateApiKey) {
const apiKey = await this.prisma.apiKey.findUnique({
where: {
id: apiKeyId,
userId: user.id
}
})

if (!apiKey) {
throw new NotFoundException(`API key with id ${apiKeyId} not found`)
}

const existingAuthorities = new Set(apiKey.authorities)
dto.authorities &&
dto.authorities.forEach((auth) => existingAuthorities.add(auth))

const updatedApiKey = await this.prisma.apiKey.update({
where: {
id: apiKeyId,
userId: user.id
},
data: {
name: dto.name,
authorities: dto.authorities
? {
set: dto.authorities
}
: undefined,
authorities: {
set: Array.from(existingAuthorities)
},
expiresAt: dto.expiresAfter
? addHoursToDate(dto.expiresAfter)
: undefined
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/auth/guard/auth/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class AuthGuard implements CanActivate {
if (authType === 'API_KEY') {
const apiKeyValue = this.extractApiKeyFromHeader(request)
if (!apiKeyValue) {
throw new ForbiddenException()
throw new ForbiddenException('No API key provided')
}

const apiKey = await this.prisma.apiKey.findUnique({
Expand All @@ -88,7 +88,7 @@ export class AuthGuard implements CanActivate {
})

if (!apiKey) {
throw new ForbiddenException()
throw new ForbiddenException('Invalid API key')
}

user = apiKey.user
Expand Down

This file was deleted.

2 changes: 0 additions & 2 deletions apps/api/src/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ model Secret {
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 @@ -401,7 +400,6 @@ model 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
14 changes: 14 additions & 0 deletions apps/api/src/secret/controller/secret.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,18 @@ export class SecretController {
search
)
}

@Get('/all/:projectId/:environmentId')
@RequiredApiKeyAuthorities(Authority.READ_SECRET)
async getAllSecretsOfEnvironment(
@CurrentUser() user: User,
@Param('projectId') projectId: string,
@Param('environmentId') environmentId: string
) {
return await this.secretService.getAllSecretsOfProjectAndEnvironment(
user,
projectId,
environmentId
)
}
}
6 changes: 0 additions & 6 deletions apps/api/src/secret/dto/create.secret/create.secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
IsArray,
IsOptional,
IsString,
IsBoolean,
Length,
ValidateNested
} from 'class-validator'
Expand All @@ -22,11 +21,6 @@ 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
Loading

0 comments on commit 35e5279

Please sign in to comment.