Skip to content

Commit

Permalink
feat(api)!: update workspace role mechanism and added functionality t…
Browse files Browse the repository at this point in the history
…o create custom roles
  • Loading branch information
rajdip-b committed Feb 5, 2024
1 parent f2a8243 commit 6144aea
Show file tree
Hide file tree
Showing 54 changed files with 2,749 additions and 1,355 deletions.
3 changes: 2 additions & 1 deletion apps/api/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@
"outputs": ["{workspaceRoot}/coverage-e2e/{projectRoot}"],
"options": {
"devServerTarget": "api:serve",
"jestConfig": "apps/api/jest.e2e-config.ts"
"jestConfig": "apps/api/jest.e2e-config.ts",
"runInBand": true
},
"configurations": {
"development": {
Expand Down
158 changes: 158 additions & 0 deletions apps/api/src/api-key/api-key.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import {
FastifyAdapter,
NestFastifyApplication
} from '@nestjs/platform-fastify'
import { PrismaService } from '../prisma/prisma.service'
import { ApiKeyModule } from './api-key.module'
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'

describe('Api Key Role Controller Tests', () => {
let app: NestFastifyApplication
let prisma: PrismaService
let user: User
let apiKey: ApiKey

beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [AppModule, ApiKeyModule]
})
.overrideProvider(MAIL_SERVICE)
.useClass(MockMailService)
.compile()
app = moduleRef.createNestApplication<NestFastifyApplication>(
new FastifyAdapter()
)
prisma = moduleRef.get(PrismaService)

await app.init()
await app.getHttpAdapter().getInstance().ready()

await prisma.apiKey.deleteMany()
await prisma.user.deleteMany()

user = await prisma.user.create({
data: {
email: '[email protected]',
name: 'John',
isActive: true,
isAdmin: false,
isOnboardingFinished: true
}
})
})

it('should be able to create api key', async () => {
const response = await app.inject({
method: 'POST',
url: '/api-key',
payload: {
name: 'Test Key',
expiresAfter: '24'
},
headers: {
'x-e2e-user-email': user.email
}
})

expect(response.statusCode).toBe(201)
expect(response.json()).toEqual({
id: expect.any(String),
name: 'Test Key',
value: expect.stringMatching(/^ks_*/),
expiresAt: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String)
})

apiKey = response.json()
})

it('should be able to update the api key', async () => {
const response = await app.inject({
method: 'PUT',
url: `/api-key/${apiKey.id}`,
payload: {
name: 'Updated Test Key',
expiresAfter: '168'
},
headers: {
'x-e2e-user-email': user.email
}
})

expect(response.statusCode).toBe(200)
expect(response.json()).toEqual({
id: apiKey.id,
name: 'Updated Test Key',
expiresAt: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String)
})

apiKey = response.json()
})

it('should be able to get the api key', async () => {
const response = await app.inject({
method: 'GET',
url: `/api-key/${apiKey.id}`,
headers: {
'x-e2e-user-email': user.email
}
})

expect(response.statusCode).toBe(200)
expect(response.json()).toEqual({
id: apiKey.id,
name: 'Updated Test Key',
expiresAt: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String)
})
})

it('should be able to get all the api keys of the user', async () => {
const response = await app.inject({
method: 'GET',
url: '/api-key/all/as-user',
headers: {
'x-e2e-user-email': user.email
}
})

expect(response.statusCode).toBe(200)
expect(response.json()).toEqual([
{
id: apiKey.id,
name: 'Updated Test Key',
expiresAt: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String)
}
])
})

it('should be able to delete the api key', async () => {
const response = await app.inject({
method: 'DELETE',
url: `/api-key/${apiKey.id}`,
headers: {
'x-e2e-user-email': user.email
}
})

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

afterAll(async () => {
await prisma.apiKey.deleteMany()
await prisma.user.deleteMany()

await prisma.$disconnect()
await app.close()
})
})
25 changes: 17 additions & 8 deletions apps/api/src/api-key/controller/api-key.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,20 @@ import {
Param,
Post,
Put,
Query
Query,
UseGuards
} from '@nestjs/common'
import { ApiKeyService } from '../service/api-key.service'
import { User } from '@prisma/client'
import { CurrentUser } from '../../decorators/user.decorator'
import { CreateApiKey } from '../dto/create.api-key/create.api-key'
import { UpdateApiKey } from '../dto/update.api-key/update.api-key'
import { AdminGuard } from '../../auth/guard/admin.guard'

@Controller('api-key')
export class ApiKeyController {
constructor(private readonly apiKeyService: ApiKeyService) {}

@Get('permissable-scopes-of-workspaces')
async getPermissableScopesOfWorkspaces(@CurrentUser() user: User) {
return this.apiKeyService.getPermissableScopesOfWorkspaces(user)
}

@Post()
async createApiKey(@CurrentUser() user: User, @Body() dto: CreateApiKey) {
return this.apiKeyService.createApiKey(user, dto)
Expand All @@ -47,8 +44,8 @@ export class ApiKeyController {
return this.apiKeyService.getApiKeyById(user, id)
}

@Get()
async getApiKeys(
@Get('all/as-user')
async getApiKeysOfUser(
@CurrentUser() user: User,
@Query('page') page: number = 1,
@Query('limit') limit: number = 10,
Expand All @@ -65,4 +62,16 @@ export class ApiKeyController {
search
)
}

@Get('all/as-admin')
@UseGuards(AdminGuard)
async getApiKeys(
@Query('page') page: number = 1,
@Query('limit') limit: number = 10,
@Query('sort') sort: string = 'name',
@Query('order') order: string = 'asc',
@Query('search') search: string = ''
) {
return this.apiKeyService.getAllApiKeys(page, limit, sort, order, search)
}
}
11 changes: 2 additions & 9 deletions apps/api/src/api-key/dto/create.api-key/create.api-key.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import { ApiKey, ApiKeyGeneralRole, ApiKeyWorkspaceScope } from '@prisma/client'
import { IsArray, IsOptional, IsString } from 'class-validator'
import { ApiKey } from '@prisma/client'
import { IsString } from 'class-validator'

export class CreateApiKey {
@IsString()
name: ApiKey['name']

@IsString()
expiresAfter: '24' | '168' | '720' | '8760' | 'never' = 'never'

@IsArray()
generalRoles: ApiKeyGeneralRole[]

@IsArray()
@IsOptional()
scopes: ApiKeyWorkspaceScope[]
}
Loading

0 comments on commit 6144aea

Please sign in to comment.