Files
Immich/server/src/controllers/person.controller.ts
T
immich-push-o-matic[bot]andDaniel Dietzler 5a7e65fac3 chore: mark people users endpoints as beta (#32233)
chore: mark people users endpoints as beta (#32232)

(cherry picked from commit 481a7bf3ae0d2c2613100d74b028463117e44a39)

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
2026-10-08 17:02:27 +00:00

262 lines
8.6 KiB
TypeScript

import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Next,
Param,
Patch,
Post,
Put,
Query,
Res,
} from '@nestjs/common';
import { ApiExcludeEndpoint, ApiTags } from '@nestjs/swagger';
import type { NextFunction, Response } from 'express';
import type { AuthDto } from 'src/dtos/auth.dto.js';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto.js';
import {
AssetFaceUpdateDto,
MergePersonDto,
PeopleDeleteDto,
PeopleResponseDto,
PeopleUpdateDto,
PeopleUsersUpsertDto,
PersonCreateDto,
PersonDeleteDto,
PersonResponseDto,
PersonSearchDto,
PersonStatisticsResponseDto,
PersonUpdateDto,
PersonUsersDeleteDto,
PersonUsersResponseDto,
PersonUsersSearchDto,
} from 'src/dtos/person.dto.js';
import { ApiTag, Permission } from 'src/enum.js';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { PersonService } from 'src/services/person.service.js';
import { sendFile } from 'src/utils/file.js';
import { UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.People)
@Controller('people')
export class PersonController {
constructor(
private service: PersonService,
private logger: LoggingRepository,
) {
this.logger.setContext(PersonController.name);
}
@Get()
@Authenticated({ permission: Permission.PersonRead })
@Endpoint({
summary: 'Get all people',
description: 'Retrieve a list of all people.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
getAllPeople(@Auth() auth: AuthDto, @Query() options: PersonSearchDto): Promise<PeopleResponseDto> {
return this.service.getAll(auth, options);
}
@Post()
@Authenticated({ permission: Permission.PersonCreate })
@Endpoint({
summary: 'Create a person',
description: 'Create a new person that can have multiple faces assigned to them.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
createPerson(@Auth() auth: AuthDto, @Body() dto: PersonCreateDto): Promise<PersonResponseDto> {
return this.service.create(auth, dto);
}
@Put()
@Authenticated({ permission: Permission.PersonUpdate })
@Endpoint({
summary: 'Update people',
description: 'Bulk update multiple people at once.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
updatePeople(@Auth() auth: AuthDto, @Body() dto: PeopleUpdateDto): Promise<BulkIdResponseDto[]> {
return this.service.updateAll(auth, dto);
}
@Delete()
@Authenticated({ permission: Permission.PersonDelete })
@HttpCode(HttpStatus.NO_CONTENT)
@Endpoint({
summary: 'Delete people',
description: 'Bulk delete a list of people at once.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
deletePeople(@Auth() auth: AuthDto, @Body() dto: PeopleDeleteDto): Promise<void> {
return this.service.deleteAll(auth, dto);
}
@Get(':id')
@Authenticated({ permission: Permission.PersonRead })
@Endpoint({
summary: 'Get a person',
description: 'Retrieve a person by id.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
getPerson(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PersonResponseDto> {
return this.service.getById(auth, id);
}
@Put(':id')
@Authenticated({ permission: Permission.PersonUpdate })
@Endpoint({
summary: 'Update person',
description: 'Update an individual person.',
history: new HistoryBuilder()
.added('v1')
.beta('v1')
.stable('v2')
.deprecated('v3', { replacementId: 'updatePerson' }),
})
updatePerson(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: PersonUpdateDto,
): Promise<PersonResponseDto> {
return this.service.update(auth, id, dto);
}
@Patch(':id')
@ApiExcludeEndpoint()
@Authenticated({ permission: Permission.PersonUpdate })
updatePersonV3(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: PersonUpdateDto,
): Promise<PersonResponseDto> {
return this.service.update(auth, id, dto);
}
@Delete(':id')
@Authenticated({ permission: Permission.PersonDelete })
@HttpCode(HttpStatus.NO_CONTENT)
@Endpoint({
summary: 'Delete person',
description: 'Delete an individual person.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
deletePerson(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, @Body() dto: PersonDeleteDto): Promise<void> {
return this.service.delete(auth, id, dto);
}
@Get(':id/statistics')
@Authenticated({ permission: Permission.PersonStatistics })
@Endpoint({
summary: 'Get person statistics',
description: 'Retrieve statistics about a specific person.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
getPersonStatistics(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PersonStatisticsResponseDto> {
return this.service.getStatistics(auth, id);
}
@Get(':id/thumbnail')
@FileResponse()
@Authenticated({ permission: Permission.PersonRead })
@Endpoint({
summary: 'Get person thumbnail',
description: 'Retrieve the thumbnail file for a person.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
async getPersonThumbnail(
@Res() res: Response,
@Next() next: NextFunction,
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
) {
await sendFile(res, next, () => this.service.getThumbnail(auth, id), this.logger);
}
@Put(':id/reassign')
@Authenticated({ permission: Permission.PersonReassign })
@Endpoint({
summary: 'Reassign faces',
description: 'Bulk reassign a list of faces to a different person.',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
reassignFaces(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: AssetFaceUpdateDto,
): Promise<PersonResponseDto[]> {
return this.service.reassignFaces(auth, id, dto);
}
@Post('merge')
@Authenticated({ permission: Permission.PersonMerge })
@HttpCode(HttpStatus.OK)
@Endpoint({
summary: 'Merge people',
description:
'Merge an ordered list of people together into a single person. The final name and birth date are always the first defined value, following the order. Also automatically merges people for other users in the cluster group, skipping people that would result in overriding a previously set name or birth date.',
history: new HistoryBuilder().added('v3.2.1').stable('v3.2.1'),
})
mergePeople(@Auth() auth: AuthDto, @Body() dto: MergePersonDto): Promise<BulkIdResponseDto[]> {
return this.service.mergePeople(auth, dto);
}
@Post(':id/merge')
@Authenticated({ permission: Permission.PersonMerge })
@HttpCode(HttpStatus.OK)
@Endpoint({
summary: 'Merge people',
description: 'Merge a list of people into the person specified in the path parameter.',
history: new HistoryBuilder()
.added('v1')
.beta('v1')
.stable('v2')
.deprecated('v3.2.1', { replacementId: 'mergePeople' }),
})
mergePersonLegacy(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: MergePersonDto,
): Promise<BulkIdResponseDto[]> {
return this.service.mergePeople(auth, { ids: [id, ...dto.ids] });
}
@Get('users')
@Authenticated({ permission: Permission.PersonRead })
@Endpoint({
summary: 'Get people access',
description: 'Retrieve a list of users and the people to which they have been given access',
history: new HistoryBuilder().added('v3.3.0').beta('v3.3.0'),
})
getUsersForPeople(@Auth() auth: AuthDto, @Query() dto: PersonUsersSearchDto): Promise<PersonUsersResponseDto> {
return this.service.getUsersForPeople(auth, dto);
}
@Put('users')
@Authenticated({ permission: Permission.PersonUpdate })
@Endpoint({
summary: 'Upsert user access',
description: 'Give users access to people',
history: new HistoryBuilder().added('v3.3.0').beta('v3.3.0'),
})
upsertPeopleUsers(@Auth() auth: AuthDto, @Body() dto: PeopleUsersUpsertDto): Promise<void> {
return this.service.upsertPeopleUsers(auth, dto);
}
@Delete('users')
@Authenticated({ permission: Permission.PersonUpdate })
@Endpoint({
summary: 'Remove users from people',
description: 'Remove user access to people',
history: new HistoryBuilder().added('v3.3.0').beta('v3.3.0'),
})
removeUsersFromPeople(@Auth() auth: AuthDto, @Body() dto: PersonUsersDeleteDto): Promise<void> {
return this.service.removeUsersFromPeople(auth, dto);
}
}