chore(server): Use access core for person permissions (#4138)

* use access core for all person methods

* minor fixes, feedback

* reorder assignments

* remove unnecessary permission requirement

* unify naming of tests

* reorder variables
This commit is contained in:
Daniel Dietzler
2023-09-18 23:22:44 +02:00
committed by GitHub
parent dda735ec51
commit 1a633f3fca
8 changed files with 171 additions and 29 deletions

View File

@@ -1,4 +1,5 @@
import { BadRequestException, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
import { AccessCore, IAccessRepository, Permission } from '../access';
import { AssetResponseDto, BulkIdErrorReason, BulkIdResponseDto, mapAsset } from '../asset';
import { AuthUserDto } from '../auth';
import { mimeTypes } from '../domain.constant';
@@ -18,15 +19,18 @@ import { IPersonRepository, UpdateFacesData } from './person.repository';
@Injectable()
export class PersonService {
private access: AccessCore;
private configCore: SystemConfigCore;
readonly logger = new Logger(PersonService.name);
constructor(
@Inject(IAccessRepository) private accessRepository: IAccessRepository,
@Inject(IPersonRepository) private repository: IPersonRepository,
@Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository,
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository,
) {
this.access = new AccessCore(accessRepository);
this.configCore = new SystemConfigCore(configRepository);
}
@@ -48,12 +52,14 @@ export class PersonService {
};
}
getById(authUser: AuthUserDto, id: string): Promise<PersonResponseDto> {
return this.findOrFail(authUser, id).then(mapPerson);
async getById(authUser: AuthUserDto, id: string): Promise<PersonResponseDto> {
await this.access.requirePermission(authUser, Permission.PERSON_READ, id);
return this.findOrFail(id).then(mapPerson);
}
async getThumbnail(authUser: AuthUserDto, id: string): Promise<ImmichReadStream> {
const person = await this.repository.getById(authUser.id, id);
await this.access.requirePermission(authUser, Permission.PERSON_READ, id);
const person = await this.repository.getById(id);
if (!person || !person.thumbnailPath) {
throw new NotFoundException();
}
@@ -62,17 +68,19 @@ export class PersonService {
}
async getAssets(authUser: AuthUserDto, id: string): Promise<AssetResponseDto[]> {
const assets = await this.repository.getAssets(authUser.id, id);
await this.access.requirePermission(authUser, Permission.PERSON_READ, id);
const assets = await this.repository.getAssets(id);
return assets.map(mapAsset);
}
async update(authUser: AuthUserDto, id: string, dto: PersonUpdateDto): Promise<PersonResponseDto> {
let person = await this.findOrFail(authUser, id);
await this.access.requirePermission(authUser, Permission.PERSON_WRITE, id);
let person = await this.findOrFail(id);
if (dto.name !== undefined || dto.birthDate !== undefined || dto.isHidden !== undefined) {
person = await this.repository.update({ id, name: dto.name, birthDate: dto.birthDate, isHidden: dto.isHidden });
if (this.needsSearchIndexUpdate(dto)) {
const assets = await this.repository.getAssets(authUser.id, id);
const assets = await this.repository.getAssets(id);
const ids = assets.map((asset) => asset.id);
await this.jobRepository.queue({ name: JobName.SEARCH_INDEX_ASSET, data: { ids } });
}
@@ -141,14 +149,22 @@ export class PersonService {
async mergePerson(authUser: AuthUserDto, id: string, dto: MergePersonDto): Promise<BulkIdResponseDto[]> {
const mergeIds = dto.ids;
const primaryPerson = await this.findOrFail(authUser, id);
await this.access.requirePermission(authUser, Permission.PERSON_WRITE, id);
const primaryPerson = await this.findOrFail(id);
const primaryName = primaryPerson.name || primaryPerson.id;
const results: BulkIdResponseDto[] = [];
for (const mergeId of mergeIds) {
const hasPermission = await this.access.hasPermission(authUser, Permission.PERSON_MERGE, mergeId);
if (!hasPermission) {
results.push({ id: mergeId, success: false, error: BulkIdErrorReason.NO_PERMISSION });
continue;
}
try {
const mergePerson = await this.repository.getById(authUser.id, mergeId);
const mergePerson = await this.repository.getById(mergeId);
if (!mergePerson) {
results.push({ id: mergeId, success: false, error: BulkIdErrorReason.NOT_FOUND });
continue;
@@ -188,8 +204,8 @@ export class PersonService {
return dto.name !== undefined || dto.isHidden !== undefined;
}
private async findOrFail(authUser: AuthUserDto, id: string) {
const person = await this.repository.getById(authUser.id, id);
private async findOrFail(id: string) {
const person = await this.repository.getById(id);
if (!person) {
throw new BadRequestException('Person not found');
}