dev: create rule

This commit is contained in:
Alex Tran 2023-08-10 20:56:51 -05:00
parent 22e5c6ead2
commit 70cf100407
11 changed files with 128 additions and 9 deletions

View file

@ -390,6 +390,16 @@
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateRuleDto"
}
}
},
"required": true
},
"responses": {
"201": {
"description": ""
@ -423,6 +433,14 @@
"format": "uuid",
"type": "string"
}
},
{
"name": "ruleId",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"responses": {
@ -5436,6 +5454,21 @@
],
"type": "object"
},
"CreateRuleDto": {
"properties": {
"key": {
"$ref": "#/components/schemas/RuleKey"
},
"value": {
"type": "string"
}
},
"required": [
"key",
"value"
],
"type": "object"
},
"CreateTagDto": {
"properties": {
"name": {
@ -6169,6 +6202,14 @@
],
"type": "object"
},
"RuleKey": {
"enum": [
"personId",
"exifInfo.city",
"asset.fileCreatedAt"
],
"type": "string"
},
"SearchAlbumResponseDto": {
"properties": {
"count": {

View file

@ -1,4 +1,4 @@
import { AlbumEntity, AssetEntity, UserEntity } from '@app/infra/entities';
import { AlbumEntity, AssetEntity, RuleEntity, UserEntity } from '@app/infra/entities';
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { AccessCore, IAccessRepository, Permission } from '../access';
import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto, IAssetRepository, mapAsset } from '../asset';
@ -7,7 +7,8 @@ import { IJobRepository, JobName } from '../job';
import { IUserRepository } from '../user';
import { AlbumCountResponseDto, AlbumResponseDto, mapAlbum } from './album-response.dto';
import { IAlbumRepository } from './album.repository';
import { AddUsersDto, CreateAlbumDto, GetAlbumsDto, UpdateAlbumDto } from './dto';
import { AddUsersDto, CreateAlbumDto, CreateRuleDto, GetAlbumsDto, UpdateAlbumDto } from './dto';
import { IRuleRepository } from './rule.repository';
@Injectable()
export class AlbumService {
@ -18,6 +19,7 @@ export class AlbumService {
@Inject(IAssetRepository) private assetRepository: IAssetRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository,
@Inject(IUserRepository) private userRepository: IUserRepository,
@Inject(IRuleRepository) private ruleRepository: IRuleRepository,
) {
this.access = new AccessCore(accessRepository);
}
@ -98,6 +100,7 @@ export class AlbumService {
sharedUsers: dto.sharedWithUserIds?.map((value) => ({ id: value } as UserEntity)) ?? [],
assets: (dto.assetIds || []).map((id) => ({ id } as AssetEntity)),
albumThumbnailAssetId: dto.assetIds?.[0] || null,
rules: [],
});
await this.jobRepository.queue({ name: JobName.SEARCH_INDEX_ALBUM, data: { ids: [album.id] } });
@ -281,4 +284,29 @@ export class AlbumService {
}
return album;
}
async addRule(authUser: AuthUserDto, id: string, dto: CreateRuleDto) {
await this.access.requirePermission(authUser, Permission.ALBUM_READ, id);
const album = await this.findOrFail(id);
const user = await this.userRepository.get(authUser.id);
if (!user) {
throw new BadRequestException('User not found');
}
const rule = new RuleEntity();
rule.key = dto.key;
rule.value = dto.value;
rule.album = album;
rule.albumId = album.id;
rule.user = user;
rule.ownerId = user.id;
await this.ruleRepository.create(rule);
return await this.findOrFail(id);
}
async removeRule(authUser: AuthUserDto, ruleId: string) {}
}

View file

@ -2,3 +2,4 @@ export * from './album-add-users.dto';
export * from './album-create.dto';
export * from './album-update.dto';
export * from './get-albums.dto';
export * from './rule.dto';

View file

@ -0,0 +1,12 @@
import { RuleKey } from '@app/infra/entities';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty } from 'class-validator';
export class CreateRuleDto {
@ApiProperty({ enumName: 'RuleKey', enum: RuleKey })
@IsNotEmpty()
key!: RuleKey;
@IsNotEmpty()
value!: string;
}

View file

@ -2,3 +2,4 @@ export * from './album-response.dto';
export * from './album.repository';
export * from './album.service';
export * from './dto';
export * from './rule.repository';

View file

@ -0,0 +1,8 @@
import { RuleEntity } from '@app/infra/entities';
export const IRuleRepository = 'IRuleRepository';
export interface IRuleRepository {
create(rule: RuleEntity): Promise<RuleEntity>;
delete(rule: RuleEntity): Promise<void>;
}

View file

@ -6,6 +6,7 @@ import {
BulkIdResponseDto,
BulkIdsDto,
CreateAlbumDto as CreateDto,
CreateRuleDto,
UpdateAlbumDto as UpdateDto,
} from '@app/domain';
import { GetAlbumsDto } from '@app/domain/album/dto/get-albums.dto';
@ -88,12 +89,16 @@ export class AlbumController {
}
@Post(':id/rule')
addRule(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto) {
throw new Error('Not implemented');
addRule(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto, @Body() dto: CreateRuleDto) {
return this.service.addRule(authUser, id, dto);
}
@Delete(':id/rule/:ruleId')
removeRule(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto) {
removeRule(
@AuthUser() authUser: AuthUserDto,
@Param() { id }: UUIDParamDto,
@Param('ruleId', new ParseMeUUIDPipe({ version: '4' })) ruleId: string,
) {
throw new Error('Not implemented');
}
}

View file

@ -13,6 +13,7 @@ import {
immichAppConfig,
IPartnerRepository,
IPersonRepository,
IRuleRepository,
ISearchRepository,
ISharedLinkRepository,
ISmartInfoRepository,
@ -45,6 +46,7 @@ import {
MediaRepository,
PartnerRepository,
PersonRepository,
RuleRepository,
SharedLinkRepository,
SmartInfoRepository,
SystemConfigRepository,
@ -67,6 +69,7 @@ const providers: Provider[] = [
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
{ provide: IPartnerRepository, useClass: PartnerRepository },
{ provide: IPersonRepository, useClass: PersonRepository },
{ provide: IRuleRepository, useClass: RuleRepository },
{ provide: ISearchRepository, useClass: TypesenseRepository },
{ provide: ISharedLinkRepository, useClass: SharedLinkRepository },
{ provide: ISmartInfoRepository, useClass: SmartInfoRepository },

View file

@ -24,6 +24,7 @@ export class AlbumRepository implements IAlbumRepository {
exifInfo: true,
},
sharedLinks: true,
rules: true,
},
order: {
assets: {
@ -41,6 +42,7 @@ export class AlbumRepository implements IAlbumRepository {
relations: {
owner: true,
sharedUsers: true,
rules: true,
},
});
}
@ -48,7 +50,7 @@ export class AlbumRepository implements IAlbumRepository {
getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]> {
return this.repository.find({
where: { ownerId, assets: { id: assetId } },
relations: { owner: true, sharedUsers: true },
relations: { owner: true, sharedUsers: true, rules: true },
order: { createdAt: 'DESC' },
});
}
@ -104,7 +106,7 @@ export class AlbumRepository implements IAlbumRepository {
getOwned(ownerId: string): Promise<AlbumEntity[]> {
return this.repository.find({
relations: { sharedUsers: true, sharedLinks: true, owner: true },
relations: { sharedUsers: true, sharedLinks: true, owner: true, rules: true },
where: { ownerId },
order: { createdAt: 'DESC' },
});
@ -115,7 +117,7 @@ export class AlbumRepository implements IAlbumRepository {
*/
getShared(ownerId: string): Promise<AlbumEntity[]> {
return this.repository.find({
relations: { sharedUsers: true, sharedLinks: true, owner: true },
relations: { sharedUsers: true, sharedLinks: true, owner: true, rules: true },
where: [
{ sharedUsers: { id: ownerId } },
{ sharedLinks: { userId: ownerId } },
@ -130,7 +132,7 @@ export class AlbumRepository implements IAlbumRepository {
*/
getNotShared(ownerId: string): Promise<AlbumEntity[]> {
return this.repository.find({
relations: { sharedUsers: true, sharedLinks: true, owner: true },
relations: { sharedUsers: true, sharedLinks: true, owner: true, rules: true },
where: { ownerId, sharedUsers: { id: IsNull() }, sharedLinks: { id: IsNull() } },
order: { createdAt: 'DESC' },
});
@ -182,6 +184,7 @@ export class AlbumRepository implements IAlbumRepository {
owner: true,
sharedUsers: true,
assets: true,
rules: true,
},
});
}

View file

@ -12,6 +12,7 @@ export * from './machine-learning.repository';
export * from './media.repository';
export * from './partner.repository';
export * from './person.repository';
export * from './rule.repository';
export * from './shared-link.repository';
export * from './smart-info.repository';
export * from './system-config.repository';

View file

@ -0,0 +1,16 @@
import { IRuleRepository } from '@app/domain';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RuleEntity } from '../entities';
export class RuleRepository implements IRuleRepository {
constructor(@InjectRepository(RuleEntity) private assetRepository: Repository<RuleEntity>) {}
create(rule: RuleEntity): Promise<RuleEntity> {
return this.assetRepository.save(rule);
}
delete(rule: RuleEntity): Promise<void> {
throw new Error('Method not implemented.');
}
}