mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
@@ -1,4 +1,4 @@
|
||||
import { Controller, Post, Param, Get, Put } from '@nestjs/common';
|
||||
import { Controller, Post, Param, Get, Put, Body } from '@nestjs/common';
|
||||
import { GenerateApiKey } from './commands/GenerateApiKey.service';
|
||||
import { GetApiKeysService } from './queries/GetApiKeys.service';
|
||||
import {
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
ApiParam,
|
||||
ApiExtraModels,
|
||||
getSchemaPath,
|
||||
ApiBody,
|
||||
ApiProperty,
|
||||
} from '@nestjs/swagger';
|
||||
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
|
||||
import {
|
||||
@@ -16,6 +18,20 @@ import {
|
||||
ApiKeyListResponseDto,
|
||||
ApiKeyListItemDto,
|
||||
} from './dtos/ApiKey.dto';
|
||||
import { IsString, MaxLength } from 'class-validator';
|
||||
import { IsOptional } from '@/common/decorators/Validators';
|
||||
|
||||
class GenerateApiKeyDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
@ApiProperty({
|
||||
description: 'Optional name for the API key',
|
||||
required: false,
|
||||
example: 'My API Key',
|
||||
})
|
||||
name?: string;
|
||||
}
|
||||
|
||||
@Controller('api-keys')
|
||||
@ApiTags('Api keys')
|
||||
@@ -29,17 +45,18 @@ export class AuthApiKeysController {
|
||||
constructor(
|
||||
private readonly getApiKeysService: GetApiKeysService,
|
||||
private readonly generateApiKeyService: GenerateApiKey,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
@Post('generate')
|
||||
@ApiOperation({ summary: 'Generate a new API key' })
|
||||
@ApiBody({ type: GenerateApiKeyDto })
|
||||
@ApiResponse({
|
||||
status: 201,
|
||||
description: 'The generated API key',
|
||||
type: ApiKeyResponseDto,
|
||||
})
|
||||
async generate() {
|
||||
return this.generateApiKeyService.generate();
|
||||
async generate(@Body() body: GenerateApiKeyDto) {
|
||||
return this.generateApiKeyService.generate(body.name);
|
||||
}
|
||||
|
||||
@Put(':id/revoke')
|
||||
|
||||
@@ -10,14 +10,15 @@ export class GenerateApiKey {
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
@Inject(ApiKeyModel.name)
|
||||
private readonly apiKeyModel: typeof ApiKeyModel,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Generates a new secure API key for the current tenant and system user.
|
||||
* The key is saved in the database and returned (only the key and id for security).
|
||||
* @param {string} name - Optional name for the API key.
|
||||
* @returns {Promise<{ key: string; id: number }>} The generated API key and its database id.
|
||||
*/
|
||||
async generate() {
|
||||
async generate(name?: string) {
|
||||
const tenant = await this.tenancyContext.getTenant();
|
||||
const user = await this.tenancyContext.getSystemUser();
|
||||
|
||||
@@ -26,6 +27,7 @@ export class GenerateApiKey {
|
||||
// Save the API key to the database
|
||||
const apiKeyRecord = await this.apiKeyModel.query().insert({
|
||||
key,
|
||||
name,
|
||||
tenantId: tenant.id,
|
||||
userId: user.id,
|
||||
createdAt: new Date(),
|
||||
|
||||
@@ -29,6 +29,12 @@ export class ApiKeyListItemDto {
|
||||
@ApiProperty({ example: 'My API Key', description: 'API key name' })
|
||||
name?: string;
|
||||
|
||||
@ApiProperty({
|
||||
example: 'bc_1234...',
|
||||
description: 'First 8 characters of the API key token',
|
||||
})
|
||||
token: string;
|
||||
|
||||
@ApiProperty({
|
||||
example: '2024-01-01T00:00:00.000Z',
|
||||
description: 'Creation date',
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||
|
||||
export class GetApiKeysTransformer extends Transformer {
|
||||
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['token'];
|
||||
};
|
||||
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['tenantId'];
|
||||
};
|
||||
|
||||
public token(apiKey) {
|
||||
return apiKey.key ? `${apiKey.key.substring(0, 8)}...` : '';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user