mirror of
https://github.com/immich-app/immich.git
synced 2025-12-21 09:15:44 +03:00
refactor(server): api key auth (#3054)
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
import { APIKeyEntity } from '@app/infra/entities';
|
||||
|
||||
export class APIKeyCreateResponseDto {
|
||||
secret!: string;
|
||||
apiKey!: APIKeyResponseDto;
|
||||
}
|
||||
|
||||
export class APIKeyResponseDto {
|
||||
id!: string;
|
||||
name!: string;
|
||||
createdAt!: Date;
|
||||
updatedAt!: Date;
|
||||
}
|
||||
|
||||
export function mapKey(entity: APIKeyEntity): APIKeyResponseDto {
|
||||
return {
|
||||
id: entity.id,
|
||||
name: entity.name,
|
||||
createdAt: entity.createdAt,
|
||||
updatedAt: entity.updatedAt,
|
||||
};
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { AuthUserDto } from '../auth';
|
||||
import { ICryptoRepository } from '../crypto';
|
||||
import { IKeyRepository } from './api-key.repository';
|
||||
|
||||
@Injectable()
|
||||
export class APIKeyCore {
|
||||
constructor(private crypto: ICryptoRepository, private repository: IKeyRepository) {}
|
||||
|
||||
async validate(token: string): Promise<AuthUserDto | null> {
|
||||
const hashedToken = this.crypto.hashSha256(token);
|
||||
const keyEntity = await this.repository.getKey(hashedToken);
|
||||
if (keyEntity?.user) {
|
||||
const user = keyEntity.user;
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
isAdmin: user.isAdmin,
|
||||
isPublicUser: false,
|
||||
isAllowUpload: true,
|
||||
externalPath: user.externalPath,
|
||||
};
|
||||
}
|
||||
|
||||
throw new UnauthorizedException('Invalid API key');
|
||||
}
|
||||
}
|
||||
@@ -12,3 +12,15 @@ export class APIKeyUpdateDto {
|
||||
@IsNotEmpty()
|
||||
name!: string;
|
||||
}
|
||||
|
||||
export class APIKeyCreateResponseDto {
|
||||
secret!: string;
|
||||
apiKey!: APIKeyResponseDto;
|
||||
}
|
||||
|
||||
export class APIKeyResponseDto {
|
||||
id!: string;
|
||||
name!: string;
|
||||
createdAt!: Date;
|
||||
updatedAt!: Date;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ describe(APIKeyService.name, () => {
|
||||
|
||||
it('should update a key', async () => {
|
||||
keyMock.getById.mockResolvedValue(keyStub.admin);
|
||||
keyMock.update.mockResolvedValue(keyStub.admin);
|
||||
|
||||
await sut.update(authStub.admin, 'random-guid', { name: 'New Name' });
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { APIKeyEntity } from '@app/infra/entities';
|
||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { AuthUserDto } from '../auth';
|
||||
import { ICryptoRepository } from '../crypto';
|
||||
import { APIKeyCreateResponseDto, APIKeyResponseDto, mapKey } from './api-key-response.dto';
|
||||
import { APIKeyCreateDto } from './api-key.dto';
|
||||
import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from './api-key.dto';
|
||||
import { IKeyRepository } from './api-key.repository';
|
||||
|
||||
@Injectable()
|
||||
@@ -20,7 +20,7 @@ export class APIKeyService {
|
||||
userId: authUser.id,
|
||||
});
|
||||
|
||||
return { secret, apiKey: mapKey(entity) };
|
||||
return { secret, apiKey: this.map(entity) };
|
||||
}
|
||||
|
||||
async update(authUser: AuthUserDto, id: string, dto: APIKeyCreateDto): Promise<APIKeyResponseDto> {
|
||||
@@ -29,9 +29,9 @@ export class APIKeyService {
|
||||
throw new BadRequestException('API Key not found');
|
||||
}
|
||||
|
||||
return this.repository.update(authUser.id, id, {
|
||||
name: dto.name,
|
||||
});
|
||||
const key = await this.repository.update(authUser.id, id, { name: dto.name });
|
||||
|
||||
return this.map(key);
|
||||
}
|
||||
|
||||
async delete(authUser: AuthUserDto, id: string): Promise<void> {
|
||||
@@ -48,11 +48,20 @@ export class APIKeyService {
|
||||
if (!key) {
|
||||
throw new BadRequestException('API Key not found');
|
||||
}
|
||||
return mapKey(key);
|
||||
return this.map(key);
|
||||
}
|
||||
|
||||
async getAll(authUser: AuthUserDto): Promise<APIKeyResponseDto[]> {
|
||||
const keys = await this.repository.getByUserId(authUser.id);
|
||||
return keys.map(mapKey);
|
||||
return keys.map((key) => this.map(key));
|
||||
}
|
||||
|
||||
private map(entity: APIKeyEntity): APIKeyResponseDto {
|
||||
return {
|
||||
id: entity.id,
|
||||
name: entity.name,
|
||||
createdAt: entity.createdAt,
|
||||
updatedAt: entity.updatedAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './api-key-response.dto';
|
||||
export * from './api-key.dto';
|
||||
export * from './api-key.repository';
|
||||
export * from './api-key.service';
|
||||
|
||||
Reference in New Issue
Block a user