mirror of
https://github.com/immich-app/immich.git
synced 2026-03-01 18:19:10 +03:00
refactor: enum casing (#19946)
This commit is contained in:
@@ -78,7 +78,7 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async reassignFaces(auth: AuthDto, personId: string, dto: AssetFaceUpdateDto): Promise<PersonResponseDto[]> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [personId] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonUpdate, ids: [personId] });
|
||||
const person = await this.findOrFail(personId);
|
||||
const result: PersonResponseDto[] = [];
|
||||
const changeFeaturePhoto: string[] = [];
|
||||
@@ -86,7 +86,7 @@ export class PersonService extends BaseService {
|
||||
const faces = await this.personRepository.getFacesByIds([{ personId: data.personId, assetId: data.assetId }]);
|
||||
|
||||
for (const face of faces) {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_CREATE, ids: [face.id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonCreate, ids: [face.id] });
|
||||
if (person.faceAssetId === null) {
|
||||
changeFeaturePhoto.push(person.id);
|
||||
}
|
||||
@@ -107,8 +107,8 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async reassignFacesById(auth: AuthDto, personId: string, dto: FaceDto): Promise<PersonResponseDto> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [personId] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_CREATE, ids: [dto.id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonUpdate, ids: [personId] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonCreate, ids: [dto.id] });
|
||||
const face = await this.personRepository.getFaceById(dto.id);
|
||||
const person = await this.findOrFail(personId);
|
||||
|
||||
@@ -124,7 +124,7 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async getFacesById(auth: AuthDto, dto: FaceDto): Promise<AssetFaceResponseDto[]> {
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_READ, ids: [dto.id] });
|
||||
await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [dto.id] });
|
||||
const faces = await this.personRepository.getFaces(dto.id);
|
||||
return faces.map((asset) => mapFaces(asset, auth));
|
||||
}
|
||||
@@ -140,7 +140,7 @@ export class PersonService extends BaseService {
|
||||
|
||||
if (assetFace) {
|
||||
await this.personRepository.update({ id: personId, faceAssetId: assetFace.id });
|
||||
jobs.push({ name: JobName.GENERATE_PERSON_THUMBNAIL, data: { id: personId } });
|
||||
jobs.push({ name: JobName.GeneratePersonThumbnail, data: { id: personId } });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,17 +148,17 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async getById(auth: AuthDto, id: string): Promise<PersonResponseDto> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonRead, ids: [id] });
|
||||
return this.findOrFail(id).then(mapPerson);
|
||||
}
|
||||
|
||||
async getStatistics(auth: AuthDto, id: string): Promise<PersonStatisticsResponseDto> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonRead, ids: [id] });
|
||||
return this.personRepository.getStatistics(id);
|
||||
}
|
||||
|
||||
async getThumbnail(auth: AuthDto, id: string): Promise<ImmichFileResponse> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonRead, ids: [id] });
|
||||
const person = await this.personRepository.getById(id);
|
||||
if (!person || !person.thumbnailPath) {
|
||||
throw new NotFoundException();
|
||||
@@ -167,7 +167,7 @@ export class PersonService extends BaseService {
|
||||
return new ImmichFileResponse({
|
||||
path: person.thumbnailPath,
|
||||
contentType: mimeTypes.lookup(person.thumbnailPath),
|
||||
cacheControl: CacheControl.PRIVATE_WITHOUT_CACHE,
|
||||
cacheControl: CacheControl.PrivateWithoutCache,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -185,13 +185,13 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: PersonUpdateDto): Promise<PersonResponseDto> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonUpdate, ids: [id] });
|
||||
|
||||
const { name, birthDate, isHidden, featureFaceAssetId: assetId, isFavorite, color } = dto;
|
||||
// TODO: set by faceId directly
|
||||
let faceId: string | undefined = undefined;
|
||||
if (assetId) {
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_READ, ids: [assetId] });
|
||||
await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [assetId] });
|
||||
const [face] = await this.personRepository.getFacesByIds([{ personId: id, assetId }]);
|
||||
if (!face) {
|
||||
throw new BadRequestException('Invalid assetId for feature face');
|
||||
@@ -211,7 +211,7 @@ export class PersonService extends BaseService {
|
||||
});
|
||||
|
||||
if (assetId) {
|
||||
await this.jobRepository.queue({ name: JobName.GENERATE_PERSON_THUMBNAIL, data: { id } });
|
||||
await this.jobRepository.queue({ name: JobName.GeneratePersonThumbnail, data: { id } });
|
||||
}
|
||||
|
||||
return mapPerson(person);
|
||||
@@ -242,7 +242,7 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async deleteAll(auth: AuthDto, { ids }: BulkIdsDto): Promise<void> {
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_DELETE, ids });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonDelete, ids });
|
||||
const people = await this.personRepository.getForPeopleDelete(ids);
|
||||
await this.removeAllPeople(people);
|
||||
}
|
||||
@@ -254,22 +254,22 @@ export class PersonService extends BaseService {
|
||||
this.logger.debug(`Deleted ${people.length} people`);
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.PERSON_CLEANUP, queue: QueueName.BACKGROUND_TASK })
|
||||
@OnJob({ name: JobName.PersonCleanup, queue: QueueName.BackgroundTask })
|
||||
async handlePersonCleanup(): Promise<JobStatus> {
|
||||
const people = await this.personRepository.getAllWithoutFaces();
|
||||
await this.removeAllPeople(people);
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.QUEUE_FACE_DETECTION, queue: QueueName.FACE_DETECTION })
|
||||
async handleQueueDetectFaces({ force }: JobOf<JobName.QUEUE_FACE_DETECTION>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.QueueFaceDetection, queue: QueueName.FaceDetection })
|
||||
async handleQueueDetectFaces({ force }: JobOf<JobName.QueueFaceDetection>): Promise<JobStatus> {
|
||||
const { machineLearning } = await this.getConfig({ withCache: false });
|
||||
if (!isFacialRecognitionEnabled(machineLearning)) {
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
if (force) {
|
||||
await this.personRepository.deleteFaces({ sourceType: SourceType.MACHINE_LEARNING });
|
||||
await this.personRepository.deleteFaces({ sourceType: SourceType.MachineLearning });
|
||||
await this.handlePersonCleanup();
|
||||
await this.personRepository.vacuum({ reindexVectors: true });
|
||||
}
|
||||
@@ -277,7 +277,7 @@ export class PersonService extends BaseService {
|
||||
let jobs: JobItem[] = [];
|
||||
const assets = this.assetJobRepository.streamForDetectFacesJob(force);
|
||||
for await (const asset of assets) {
|
||||
jobs.push({ name: JobName.FACE_DETECTION, data: { id: asset.id } });
|
||||
jobs.push({ name: JobName.FaceDetection, data: { id: asset.id } });
|
||||
|
||||
if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) {
|
||||
await this.jobRepository.queueAll(jobs);
|
||||
@@ -288,27 +288,27 @@ export class PersonService extends BaseService {
|
||||
await this.jobRepository.queueAll(jobs);
|
||||
|
||||
if (force === undefined) {
|
||||
await this.jobRepository.queue({ name: JobName.PERSON_CLEANUP });
|
||||
await this.jobRepository.queue({ name: JobName.PersonCleanup });
|
||||
}
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.FACE_DETECTION, queue: QueueName.FACE_DETECTION })
|
||||
async handleDetectFaces({ id }: JobOf<JobName.FACE_DETECTION>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.FaceDetection, queue: QueueName.FaceDetection })
|
||||
async handleDetectFaces({ id }: JobOf<JobName.FaceDetection>): Promise<JobStatus> {
|
||||
const { machineLearning } = await this.getConfig({ withCache: true });
|
||||
if (!isFacialRecognitionEnabled(machineLearning)) {
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
const asset = await this.assetJobRepository.getForDetectFacesJob(id);
|
||||
const previewFile = asset?.files[0];
|
||||
if (!asset || asset.files.length !== 1 || !previewFile) {
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
if (asset.visibility === AssetVisibility.HIDDEN) {
|
||||
return JobStatus.SKIPPED;
|
||||
if (asset.visibility === AssetVisibility.Hidden) {
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
const { imageHeight, imageWidth, faces } = await this.machineLearningRepository.detectFaces(
|
||||
@@ -323,7 +323,7 @@ export class PersonService extends BaseService {
|
||||
const mlFaceIds = new Set<string>();
|
||||
|
||||
for (const face of asset.faces) {
|
||||
if (face.sourceType === SourceType.MACHINE_LEARNING) {
|
||||
if (face.sourceType === SourceType.MachineLearning) {
|
||||
mlFaceIds.add(face.id);
|
||||
}
|
||||
}
|
||||
@@ -368,15 +368,15 @@ export class PersonService extends BaseService {
|
||||
|
||||
if (facesToAdd.length > 0) {
|
||||
this.logger.log(`Detected ${facesToAdd.length} new faces in asset ${id}`);
|
||||
const jobs = facesToAdd.map((face) => ({ name: JobName.FACIAL_RECOGNITION, data: { id: face.id } }) as const);
|
||||
await this.jobRepository.queueAll([{ name: JobName.QUEUE_FACIAL_RECOGNITION, data: { force: false } }, ...jobs]);
|
||||
const jobs = facesToAdd.map((face) => ({ name: JobName.FacialRecognition, data: { id: face.id } }) as const);
|
||||
await this.jobRepository.queueAll([{ name: JobName.QueueFacialRecognition, data: { force: false } }, ...jobs]);
|
||||
} else if (embeddings.length > 0) {
|
||||
this.logger.log(`Added ${embeddings.length} face embeddings for asset ${id}`);
|
||||
}
|
||||
|
||||
await this.assetRepository.upsertJobStatus({ assetId: asset.id, facesRecognizedAt: new Date() });
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
private iou(
|
||||
@@ -396,50 +396,50 @@ export class PersonService extends BaseService {
|
||||
return intersection / union;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.QUEUE_FACIAL_RECOGNITION, queue: QueueName.FACIAL_RECOGNITION })
|
||||
async handleQueueRecognizeFaces({ force, nightly }: JobOf<JobName.QUEUE_FACIAL_RECOGNITION>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.QueueFacialRecognition, queue: QueueName.FacialRecognition })
|
||||
async handleQueueRecognizeFaces({ force, nightly }: JobOf<JobName.QueueFacialRecognition>): Promise<JobStatus> {
|
||||
const { machineLearning } = await this.getConfig({ withCache: false });
|
||||
if (!isFacialRecognitionEnabled(machineLearning)) {
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
await this.jobRepository.waitForQueueCompletion(QueueName.THUMBNAIL_GENERATION, QueueName.FACE_DETECTION);
|
||||
await this.jobRepository.waitForQueueCompletion(QueueName.ThumbnailGeneration, QueueName.FaceDetection);
|
||||
|
||||
if (nightly) {
|
||||
const [state, latestFaceDate] = await Promise.all([
|
||||
this.systemMetadataRepository.get(SystemMetadataKey.FACIAL_RECOGNITION_STATE),
|
||||
this.systemMetadataRepository.get(SystemMetadataKey.FacialRecognitionState),
|
||||
this.personRepository.getLatestFaceDate(),
|
||||
]);
|
||||
|
||||
if (state?.lastRun && latestFaceDate && state.lastRun > latestFaceDate) {
|
||||
this.logger.debug('Skipping facial recognition nightly since no face has been added since the last run');
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
}
|
||||
|
||||
const { waiting } = await this.jobRepository.getJobCounts(QueueName.FACIAL_RECOGNITION);
|
||||
const { waiting } = await this.jobRepository.getJobCounts(QueueName.FacialRecognition);
|
||||
|
||||
if (force) {
|
||||
await this.personRepository.unassignFaces({ sourceType: SourceType.MACHINE_LEARNING });
|
||||
await this.personRepository.unassignFaces({ sourceType: SourceType.MachineLearning });
|
||||
await this.handlePersonCleanup();
|
||||
await this.personRepository.vacuum({ reindexVectors: false });
|
||||
} else if (waiting) {
|
||||
this.logger.debug(
|
||||
`Skipping facial recognition queueing because ${waiting} job${waiting > 1 ? 's are' : ' is'} already queued`,
|
||||
);
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
await this.databaseRepository.prewarm(VectorIndex.FACE);
|
||||
await this.databaseRepository.prewarm(VectorIndex.Face);
|
||||
|
||||
const lastRun = new Date().toISOString();
|
||||
const facePagination = this.personRepository.getAllFaces(
|
||||
force ? undefined : { personId: null, sourceType: SourceType.MACHINE_LEARNING },
|
||||
force ? undefined : { personId: null, sourceType: SourceType.MachineLearning },
|
||||
);
|
||||
|
||||
let jobs: { name: JobName.FACIAL_RECOGNITION; data: { id: string; deferred: false } }[] = [];
|
||||
let jobs: { name: JobName.FacialRecognition; data: { id: string; deferred: false } }[] = [];
|
||||
for await (const face of facePagination) {
|
||||
jobs.push({ name: JobName.FACIAL_RECOGNITION, data: { id: face.id, deferred: false } });
|
||||
jobs.push({ name: JobName.FacialRecognition, data: { id: face.id, deferred: false } });
|
||||
|
||||
if (jobs.length === JOBS_ASSET_PAGINATION_SIZE) {
|
||||
await this.jobRepository.queueAll(jobs);
|
||||
@@ -449,37 +449,37 @@ export class PersonService extends BaseService {
|
||||
|
||||
await this.jobRepository.queueAll(jobs);
|
||||
|
||||
await this.systemMetadataRepository.set(SystemMetadataKey.FACIAL_RECOGNITION_STATE, { lastRun });
|
||||
await this.systemMetadataRepository.set(SystemMetadataKey.FacialRecognitionState, { lastRun });
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.FACIAL_RECOGNITION, queue: QueueName.FACIAL_RECOGNITION })
|
||||
async handleRecognizeFaces({ id, deferred }: JobOf<JobName.FACIAL_RECOGNITION>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.FacialRecognition, queue: QueueName.FacialRecognition })
|
||||
async handleRecognizeFaces({ id, deferred }: JobOf<JobName.FacialRecognition>): Promise<JobStatus> {
|
||||
const { machineLearning } = await this.getConfig({ withCache: true });
|
||||
if (!isFacialRecognitionEnabled(machineLearning)) {
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
const face = await this.personRepository.getFaceForFacialRecognitionJob(id);
|
||||
if (!face || !face.asset) {
|
||||
this.logger.warn(`Face ${id} not found`);
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
if (face.sourceType !== SourceType.MACHINE_LEARNING) {
|
||||
if (face.sourceType !== SourceType.MachineLearning) {
|
||||
this.logger.warn(`Skipping face ${id} due to source ${face.sourceType}`);
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
if (!face.faceSearch?.embedding) {
|
||||
this.logger.warn(`Face ${id} does not have an embedding`);
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
if (face.personId) {
|
||||
this.logger.debug(`Face ${id} already has a person assigned`);
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
const matches = await this.searchRepository.searchFaces({
|
||||
@@ -493,18 +493,18 @@ export class PersonService extends BaseService {
|
||||
// `matches` also includes the face itself
|
||||
if (machineLearning.facialRecognition.minFaces > 1 && matches.length <= 1) {
|
||||
this.logger.debug(`Face ${id} only matched the face itself, skipping`);
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
this.logger.debug(`Face ${id} has ${matches.length} matches`);
|
||||
|
||||
const isCore =
|
||||
matches.length >= machineLearning.facialRecognition.minFaces &&
|
||||
face.asset.visibility === AssetVisibility.TIMELINE;
|
||||
face.asset.visibility === AssetVisibility.Timeline;
|
||||
if (!isCore && !deferred) {
|
||||
this.logger.debug(`Deferring non-core face ${id} for later processing`);
|
||||
await this.jobRepository.queue({ name: JobName.FACIAL_RECOGNITION, data: { id, deferred: true } });
|
||||
return JobStatus.SKIPPED;
|
||||
await this.jobRepository.queue({ name: JobName.FacialRecognition, data: { id, deferred: true } });
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
let personId = matches.find((match) => match.personId)?.personId;
|
||||
@@ -526,7 +526,7 @@ export class PersonService extends BaseService {
|
||||
if (isCore && !personId) {
|
||||
this.logger.log(`Creating new person for face ${id}`);
|
||||
const newPerson = await this.personRepository.create({ ownerId: face.asset.ownerId, faceAssetId: face.id });
|
||||
await this.jobRepository.queue({ name: JobName.GENERATE_PERSON_THUMBNAIL, data: { id: newPerson.id } });
|
||||
await this.jobRepository.queue({ name: JobName.GeneratePersonThumbnail, data: { id: newPerson.id } });
|
||||
personId = newPerson.id;
|
||||
}
|
||||
|
||||
@@ -535,19 +535,19 @@ export class PersonService extends BaseService {
|
||||
await this.personRepository.reassignFaces({ faceIds: [id], newPersonId: personId });
|
||||
}
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.MIGRATE_PERSON, queue: QueueName.MIGRATION })
|
||||
async handlePersonMigration({ id }: JobOf<JobName.MIGRATE_PERSON>): Promise<JobStatus> {
|
||||
@OnJob({ name: JobName.MigratePerson, queue: QueueName.Migration })
|
||||
async handlePersonMigration({ id }: JobOf<JobName.MigratePerson>): Promise<JobStatus> {
|
||||
const person = await this.personRepository.getById(id);
|
||||
if (!person) {
|
||||
return JobStatus.FAILED;
|
||||
return JobStatus.Failed;
|
||||
}
|
||||
|
||||
await this.storageCore.movePersonFile(person, PersonPathType.FACE);
|
||||
await this.storageCore.movePersonFile(person, PersonPathType.Face);
|
||||
|
||||
return JobStatus.SUCCESS;
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
async mergePerson(auth: AuthDto, id: string, dto: MergePersonDto): Promise<BulkIdResponseDto[]> {
|
||||
@@ -556,7 +556,7 @@ export class PersonService extends BaseService {
|
||||
throw new BadRequestException('Cannot merge a person into themselves');
|
||||
}
|
||||
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PersonUpdate, ids: [id] });
|
||||
let primaryPerson = await this.findOrFail(id);
|
||||
const primaryName = primaryPerson.name || primaryPerson.id;
|
||||
|
||||
@@ -564,7 +564,7 @@ export class PersonService extends BaseService {
|
||||
|
||||
const allowedIds = await this.checkAccess({
|
||||
auth,
|
||||
permission: Permission.PERSON_MERGE,
|
||||
permission: Permission.PersonMerge,
|
||||
ids: mergeIds,
|
||||
});
|
||||
|
||||
@@ -623,8 +623,8 @@ export class PersonService extends BaseService {
|
||||
// TODO return a asset face response
|
||||
async createFace(auth: AuthDto, dto: AssetFaceCreateDto): Promise<void> {
|
||||
await Promise.all([
|
||||
this.requireAccess({ auth, permission: Permission.ASSET_READ, ids: [dto.assetId] }),
|
||||
this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [dto.personId] }),
|
||||
this.requireAccess({ auth, permission: Permission.AssetRead, ids: [dto.assetId] }),
|
||||
this.requireAccess({ auth, permission: Permission.PersonRead, ids: [dto.personId] }),
|
||||
]);
|
||||
|
||||
await this.personRepository.createAssetFace({
|
||||
@@ -636,12 +636,12 @@ export class PersonService extends BaseService {
|
||||
boundingBoxX2: dto.x + dto.width,
|
||||
boundingBoxY1: dto.y,
|
||||
boundingBoxY2: dto.y + dto.height,
|
||||
sourceType: SourceType.MANUAL,
|
||||
sourceType: SourceType.Manual,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteFace(auth: AuthDto, id: string, dto: AssetFaceDeleteDto): Promise<void> {
|
||||
await this.requireAccess({ auth, permission: Permission.FACE_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.FaceDelete, ids: [id] });
|
||||
|
||||
return dto.force ? this.personRepository.deleteAssetFace(id) : this.personRepository.softDeleteAssetFaces(id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user