diff --git a/backend/src/collections/apikey-db/apikey-db.service.ts b/backend/src/collections/apikey-db/apikey-db.service.ts index ff9b0e4..85d089b 100644 --- a/backend/src/collections/apikey-db/apikey-db.service.ts +++ b/backend/src/collections/apikey-db/apikey-db.service.ts @@ -20,6 +20,11 @@ export class ApiKeyDbService { const apikey = new EApiKeyBackend(); apikey.user = userid; apikey.created = new Date(); + // YYYY-MM-DD- followed by a random number + apikey.name = + new Date().toISOString().slice(0, 10) + + '_' + + Math.round(Math.random() * 100); apikey.key = generateRandomString(32); // Might collide, probably not /* @@ -36,7 +41,7 @@ export class ApiKeyDbService { } async findOne( - key: string, + id: string, userid: string | undefined, ): AsyncFailable> { try { @@ -47,7 +52,7 @@ export class ApiKeyDbService { ? // This is stupid, but typeorm do typeorm ({ id: userid } as any) : undefined, - key, + id, }, loadRelationIds: true, }); @@ -92,11 +97,28 @@ export class ApiKeyDbService { } } - async deleteApiKey( - key: string, + async updateApiKey( + id: string, + name: string, userid: string | undefined, ): AsyncFailable> { - const apikeyToDelete = await this.findOne(key, userid); + const apikey = await this.findOne(id, userid); + if (HasFailed(apikey)) return apikey; + + try { + apikey.name = name; + + return this.apikeyRepo.save(apikey); + } catch (e) { + return Fail(FT.Database, e); + } + } + + async deleteApiKey( + id: string, + userid: string | undefined, + ): AsyncFailable> { + const apikeyToDelete = await this.findOne(id, userid); if (HasFailed(apikeyToDelete)) return apikeyToDelete; const apiKeyCopy = { ...apikeyToDelete }; diff --git a/backend/src/database/entities/apikey.entity.ts b/backend/src/database/entities/apikey.entity.ts index 06fee42..449c44c 100644 --- a/backend/src/database/entities/apikey.entity.ts +++ b/backend/src/database/entities/apikey.entity.ts @@ -1,8 +1,8 @@ import { EApiKeySchema } from 'picsur-shared/dist/entities/apikey.entity'; import { Column, Entity, - ManyToOne, - PrimaryColumn + Index, + ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { z } from 'zod'; import { EUserBackend } from './user.entity'; @@ -19,7 +19,11 @@ export class EApiKeyBackend< T extends string | EUserBackend = string | EUserBackend, > implements OverriddenEApiKey { - @PrimaryColumn({ + @PrimaryGeneratedColumn('uuid') + id: string; + + @Index() + @Column({ nullable: false, unique: true, }) @@ -31,6 +35,9 @@ export class EApiKeyBackend< }) user: T; + @Column({ nullable: false }) + name: string; + @Column({ nullable: false, }) diff --git a/backend/src/routes/api/apikeys/apikeys.controller.ts b/backend/src/routes/api/apikeys/apikeys.controller.ts index 67caea5..0b69f0e 100644 --- a/backend/src/routes/api/apikeys/apikeys.controller.ts +++ b/backend/src/routes/api/apikeys/apikeys.controller.ts @@ -6,7 +6,9 @@ import { ApiKeyInfoRequest, ApiKeyInfoResponse, ApiKeyListRequest, - ApiKeyListResponse + ApiKeyListResponse, + ApiKeyUpdateRequest, + ApiKeyUpdateResponse } from 'picsur-shared/dist/dto/api/apikeys.dto'; import { Permission } from 'picsur-shared/dist/dto/permissions.enum'; import { ThrowIfFailed } from 'picsur-shared/dist/types'; @@ -31,7 +33,7 @@ export class ApiKeysController { @HasPermission(Permission.ApiKeyAdmin) isAdmin: boolean, ): Promise { return ThrowIfFailed( - await this.apikeyDB.findOne(body.key, isAdmin ? undefined : userid), + await this.apikeyDB.findOne(body.id, isAdmin ? undefined : userid), ); } @@ -57,6 +59,22 @@ export class ApiKeysController { return ThrowIfFailed(await this.apikeyDB.createApiKey(userID)); } + @Post('update') + @Returns(ApiKeyUpdateResponse) + async updateApiKey( + @ReqUserID() userID: string, + @Body() body: ApiKeyUpdateRequest, + @HasPermission(Permission.ApiKeyAdmin) isAdmin: boolean, + ): Promise { + return ThrowIfFailed( + await this.apikeyDB.updateApiKey( + body.id, + body.name, + isAdmin ? undefined : userID, + ), + ); + } + @Post('delete') @Returns(ApiKeyDeleteResponse) async deleteApiKey( @@ -65,7 +83,7 @@ export class ApiKeysController { @HasPermission(Permission.ApiKeyAdmin) isAdmin: boolean, ): Promise { return ThrowIfFailed( - await this.apikeyDB.deleteApiKey(body.key, isAdmin ? undefined : userID), + await this.apikeyDB.deleteApiKey(body.id, isAdmin ? undefined : userID), ); } } diff --git a/frontend/src/app/routes/settings/apikeys/settings-apikeys.component.html b/frontend/src/app/routes/settings/apikeys/settings-apikeys.component.html index a9f1a90..e6a4d04 100644 --- a/frontend/src/app/routes/settings/apikeys/settings-apikeys.component.html +++ b/frontend/src/app/routes/settings/apikeys/settings-apikeys.component.html @@ -1,15 +1,13 @@

Api Keys

- - Key + + Name - + + Name + + @@ -34,7 +32,12 @@ Actions - +