mirror of
https://github.com/immich-app/immich.git
synced 2025-03-11 02:23:09 -05:00
refactor: access repository (#15490)
This commit is contained in:
parent
318dd32363
commit
b0cdd8f475
9 changed files with 75 additions and 152 deletions
|
@ -1,53 +0,0 @@
|
|||
import { AlbumUserRole } from 'src/enum';
|
||||
|
||||
export const IAccessRepository = 'IAccessRepository';
|
||||
|
||||
export interface IAccessRepository {
|
||||
activity: {
|
||||
checkOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>>;
|
||||
checkAlbumOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>>;
|
||||
checkCreateAccess(userId: string, albumIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
asset: {
|
||||
checkOwnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>>;
|
||||
checkAlbumAccess(userId: string, assetIds: Set<string>): Promise<Set<string>>;
|
||||
checkPartnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>>;
|
||||
checkSharedLinkAccess(sharedLinkId: string, assetIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
authDevice: {
|
||||
checkOwnerAccess(userId: string, deviceIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
album: {
|
||||
checkOwnerAccess(userId: string, albumIds: Set<string>): Promise<Set<string>>;
|
||||
checkSharedAlbumAccess(userId: string, albumIds: Set<string>, access: AlbumUserRole): Promise<Set<string>>;
|
||||
checkSharedLinkAccess(sharedLinkId: string, albumIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
timeline: {
|
||||
checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
memory: {
|
||||
checkOwnerAccess(userId: string, memoryIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
person: {
|
||||
checkFaceOwnerAccess(userId: string, assetFaceId: Set<string>): Promise<Set<string>>;
|
||||
checkOwnerAccess(userId: string, personIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
partner: {
|
||||
checkUpdateAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
stack: {
|
||||
checkOwnerAccess(userId: string, stackIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
tag: {
|
||||
checkOwnerAccess(userId: string, tagIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
}
|
|
@ -1,33 +1,18 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Kysely, sql } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
|
||||
import { AlbumUserRole } from 'src/enum';
|
||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
type IActivityAccess = IAccessRepository['activity'];
|
||||
type IAlbumAccess = IAccessRepository['album'];
|
||||
type IAssetAccess = IAccessRepository['asset'];
|
||||
type IAuthDeviceAccess = IAccessRepository['authDevice'];
|
||||
type IMemoryAccess = IAccessRepository['memory'];
|
||||
type IPersonAccess = IAccessRepository['person'];
|
||||
type IPartnerAccess = IAccessRepository['partner'];
|
||||
type IStackAccess = IAccessRepository['stack'];
|
||||
type ITagAccess = IAccessRepository['tag'];
|
||||
type ITimelineAccess = IAccessRepository['timeline'];
|
||||
|
||||
@Injectable()
|
||||
class ActivityAccess implements IActivityAccess {
|
||||
class ActivityAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, activityIds: Set<string>) {
|
||||
if (activityIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -41,9 +26,9 @@ class ActivityAccess implements IActivityAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkAlbumOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>> {
|
||||
async checkAlbumOwnerAccess(userId: string, activityIds: Set<string>) {
|
||||
if (activityIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -58,9 +43,9 @@ class ActivityAccess implements IActivityAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkCreateAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
|
||||
async checkCreateAccess(userId: string, albumIds: Set<string>) {
|
||||
if (albumIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -77,14 +62,14 @@ class ActivityAccess implements IActivityAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class AlbumAccess implements IAlbumAccess {
|
||||
class AlbumAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, albumIds: Set<string>) {
|
||||
if (albumIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -99,9 +84,9 @@ class AlbumAccess implements IAlbumAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkSharedAlbumAccess(userId: string, albumIds: Set<string>, access: AlbumUserRole): Promise<Set<string>> {
|
||||
async checkSharedAlbumAccess(userId: string, albumIds: Set<string>, access: AlbumUserRole) {
|
||||
if (albumIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
const accessRole =
|
||||
|
@ -122,9 +107,9 @@ class AlbumAccess implements IAlbumAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkSharedLinkAccess(sharedLinkId: string, albumIds: Set<string>): Promise<Set<string>> {
|
||||
async checkSharedLinkAccess(sharedLinkId: string, albumIds: Set<string>) {
|
||||
if (albumIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -139,14 +124,14 @@ class AlbumAccess implements IAlbumAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class AssetAccess implements IAssetAccess {
|
||||
class AssetAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkAlbumAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
|
||||
async checkAlbumAccess(userId: string, assetIds: Set<string>) {
|
||||
if (assetIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -182,9 +167,9 @@ class AssetAccess implements IAssetAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, assetIds: Set<string>) {
|
||||
if (assetIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -198,9 +183,9 @@ class AssetAccess implements IAssetAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkPartnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
|
||||
async checkPartnerAccess(userId: string, assetIds: Set<string>) {
|
||||
if (assetIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -221,9 +206,9 @@ class AssetAccess implements IAssetAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkSharedLinkAccess(sharedLinkId: string, assetIds: Set<string>): Promise<Set<string>> {
|
||||
async checkSharedLinkAccess(sharedLinkId: string, assetIds: Set<string>) {
|
||||
if (assetIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -273,14 +258,14 @@ class AssetAccess implements IAssetAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class AuthDeviceAccess implements IAuthDeviceAccess {
|
||||
class AuthDeviceAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, deviceIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, deviceIds: Set<string>) {
|
||||
if (deviceIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -293,14 +278,14 @@ class AuthDeviceAccess implements IAuthDeviceAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class StackAccess implements IStackAccess {
|
||||
class StackAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, stackIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, stackIds: Set<string>) {
|
||||
if (stackIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -313,14 +298,14 @@ class StackAccess implements IStackAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class TimelineAccess implements ITimelineAccess {
|
||||
class TimelineAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
|
||||
async checkPartnerAccess(userId: string, partnerIds: Set<string>) {
|
||||
if (partnerIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -333,14 +318,14 @@ class TimelineAccess implements ITimelineAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class MemoryAccess implements IMemoryAccess {
|
||||
class MemoryAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, memoryIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, memoryIds: Set<string>) {
|
||||
if (memoryIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -354,14 +339,14 @@ class MemoryAccess implements IMemoryAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class PersonAccess implements IPersonAccess {
|
||||
class PersonAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, personIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, personIds: Set<string>) {
|
||||
if (personIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -375,9 +360,9 @@ class PersonAccess implements IPersonAccess {
|
|||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkFaceOwnerAccess(userId: string, assetFaceIds: Set<string>): Promise<Set<string>> {
|
||||
async checkFaceOwnerAccess(userId: string, assetFaceIds: Set<string>) {
|
||||
if (assetFaceIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -393,14 +378,14 @@ class PersonAccess implements IPersonAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class PartnerAccess implements IPartnerAccess {
|
||||
class PartnerAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkUpdateAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
|
||||
async checkUpdateAccess(userId: string, partnerIds: Set<string>) {
|
||||
if (partnerIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -413,14 +398,14 @@ class PartnerAccess implements IPartnerAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class TagAccess implements ITagAccess {
|
||||
class TagAccess {
|
||||
constructor(private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, tagIds: Set<string>): Promise<Set<string>> {
|
||||
async checkOwnerAccess(userId: string, tagIds: Set<string>) {
|
||||
if (tagIds.size === 0) {
|
||||
return new Set();
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
return this.db
|
||||
|
@ -433,17 +418,17 @@ class TagAccess implements ITagAccess {
|
|||
}
|
||||
}
|
||||
|
||||
export class AccessRepository implements IAccessRepository {
|
||||
activity: IActivityAccess;
|
||||
album: IAlbumAccess;
|
||||
asset: IAssetAccess;
|
||||
authDevice: IAuthDeviceAccess;
|
||||
memory: IMemoryAccess;
|
||||
person: IPersonAccess;
|
||||
partner: IPartnerAccess;
|
||||
stack: IStackAccess;
|
||||
tag: ITagAccess;
|
||||
timeline: ITimelineAccess;
|
||||
export class AccessRepository {
|
||||
activity: ActivityAccess;
|
||||
album: AlbumAccess;
|
||||
asset: AssetAccess;
|
||||
authDevice: AuthDeviceAccess;
|
||||
memory: MemoryAccess;
|
||||
person: PersonAccess;
|
||||
partner: PartnerAccess;
|
||||
stack: StackAccess;
|
||||
tag: TagAccess;
|
||||
timeline: TimelineAccess;
|
||||
|
||||
constructor(@InjectKysely() db: Kysely<DB>) {
|
||||
this.activity = new ActivityAccess(db);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||
import { IKeyRepository } from 'src/interfaces/api-key.interface';
|
||||
|
@ -78,11 +77,11 @@ import { ViewRepository } from 'src/repositories/view-repository';
|
|||
|
||||
export const repositories = [
|
||||
//
|
||||
AccessRepository,
|
||||
ActivityRepository,
|
||||
];
|
||||
|
||||
export const providers = [
|
||||
{ provide: IAccessRepository, useClass: AccessRepository },
|
||||
{ provide: IAlbumRepository, useClass: AlbumRepository },
|
||||
{ provide: IAlbumUserRepository, useClass: AlbumUserRepository },
|
||||
{ provide: IAssetRepository, useClass: AssetRepository },
|
||||
|
|
|
@ -6,7 +6,6 @@ import { SALT_ROUNDS } from 'src/constants';
|
|||
import { StorageCore } from 'src/cores/storage.core';
|
||||
import { Users } from 'src/db';
|
||||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||
import { IKeyRepository } from 'src/interfaces/api-key.interface';
|
||||
|
@ -44,6 +43,7 @@ import { ITrashRepository } from 'src/interfaces/trash.interface';
|
|||
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||
import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface';
|
||||
import { IViewRepository } from 'src/interfaces/view.interface';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { AccessRequest, checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { getConfig, updateConfig } from 'src/utils/config';
|
||||
|
@ -53,7 +53,7 @@ export class BaseService {
|
|||
|
||||
constructor(
|
||||
@Inject(ILoggerRepository) protected logger: ILoggerRepository,
|
||||
@Inject(IAccessRepository) protected accessRepository: IAccessRepository,
|
||||
protected accessRepository: AccessRepository,
|
||||
protected activityRepository: ActivityRepository,
|
||||
@Inject(IAuditRepository) protected auditRepository: IAuditRepository,
|
||||
@Inject(IAlbumRepository) protected albumRepository: IAlbumRepository,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
|
||||
export type AuthApiKey = {
|
||||
|
@ -12,6 +13,7 @@ export type AuthApiKey = {
|
|||
export type RepositoryInterface<T extends object> = Pick<T, keyof T>;
|
||||
|
||||
export type IActivityRepository = RepositoryInterface<ActivityRepository>;
|
||||
export type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface<AccessRepository[K]> };
|
||||
|
||||
export type ActivityItem =
|
||||
| Awaited<ReturnType<IActivityRepository['create']>>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common';
|
|||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { AlbumUserRole, Permission } from 'src/enum';
|
||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { setDifference, setIsEqual, setIsSuperset, setUnion } from 'src/utils/set';
|
||||
|
||||
export type GrantedRequest = {
|
||||
|
@ -34,7 +34,7 @@ export const requireUploadAccess = (auth: AuthDto | null): AuthDto => {
|
|||
return auth;
|
||||
};
|
||||
|
||||
export const requireAccess = async (access: IAccessRepository, request: AccessRequest) => {
|
||||
export const requireAccess = async (access: AccessRepository, request: AccessRequest) => {
|
||||
const allowedIds = await checkAccess(access, request);
|
||||
if (!setIsEqual(new Set(request.ids), allowedIds)) {
|
||||
throw new BadRequestException(`Not found or no ${request.permission} access`);
|
||||
|
@ -42,7 +42,7 @@ export const requireAccess = async (access: IAccessRepository, request: AccessRe
|
|||
};
|
||||
|
||||
export const checkAccess = async (
|
||||
access: IAccessRepository,
|
||||
access: AccessRepository,
|
||||
{ ids, auth, permission }: AccessRequest,
|
||||
): Promise<Set<string>> => {
|
||||
const idSet = Array.isArray(ids) ? new Set(ids) : ids;
|
||||
|
@ -56,7 +56,7 @@ export const checkAccess = async (
|
|||
};
|
||||
|
||||
const checkSharedLinkAccess = async (
|
||||
access: IAccessRepository,
|
||||
access: AccessRepository,
|
||||
request: SharedLinkAccessRequest,
|
||||
): Promise<Set<string>> => {
|
||||
const { sharedLink, permission, ids } = request;
|
||||
|
@ -102,7 +102,7 @@ const checkSharedLinkAccess = async (
|
|||
}
|
||||
};
|
||||
|
||||
const checkOtherAccess = async (access: IAccessRepository, request: OtherAccessRequest): Promise<Set<string>> => {
|
||||
const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRequest): Promise<Set<string>> => {
|
||||
const { auth, permission, ids } = request;
|
||||
|
||||
switch (permission) {
|
||||
|
|
|
@ -5,12 +5,12 @@ import { UploadFieldName } from 'src/dtos/asset-media.dto';
|
|||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AssetFileEntity } from 'src/entities/asset-files.entity';
|
||||
import { AssetFileType, AssetType, Permission } from 'src/enum';
|
||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||
import { AuthRequest } from 'src/middleware/auth.guard';
|
||||
import { ImmichFile } from 'src/middleware/file-upload.interceptor';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { UploadFile } from 'src/services/asset-media.service';
|
||||
import { checkAccess } from 'src/utils/access';
|
||||
|
||||
|
@ -31,7 +31,7 @@ export const getAssetFiles = (files?: AssetFileEntity[]) => ({
|
|||
|
||||
export const addAssets = async (
|
||||
auth: AuthDto,
|
||||
repositories: { access: IAccessRepository; bulk: IBulkAsset },
|
||||
repositories: { access: AccessRepository; bulk: IBulkAsset },
|
||||
dto: { parentId: string; assetIds: string[] },
|
||||
) => {
|
||||
const { access, bulk } = repositories;
|
||||
|
@ -71,7 +71,7 @@ export const addAssets = async (
|
|||
|
||||
export const removeAssets = async (
|
||||
auth: AuthDto,
|
||||
repositories: { access: IAccessRepository; bulk: IBulkAsset },
|
||||
repositories: { access: AccessRepository; bulk: IBulkAsset },
|
||||
dto: { parentId: string; assetIds: string[]; canAlwaysRemove: Permission },
|
||||
) => {
|
||||
const { access, bulk } = repositories;
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { IAccessRepository } from 'src/types';
|
||||
import { Mocked, vitest } from 'vitest';
|
||||
|
||||
export interface IAccessRepositoryMock {
|
||||
activity: Mocked<IAccessRepository['activity']>;
|
||||
asset: Mocked<IAccessRepository['asset']>;
|
||||
album: Mocked<IAccessRepository['album']>;
|
||||
authDevice: Mocked<IAccessRepository['authDevice']>;
|
||||
memory: Mocked<IAccessRepository['memory']>;
|
||||
person: Mocked<IAccessRepository['person']>;
|
||||
partner: Mocked<IAccessRepository['partner']>;
|
||||
stack: Mocked<IAccessRepository['stack']>;
|
||||
timeline: Mocked<IAccessRepository['timeline']>;
|
||||
tag: Mocked<IAccessRepository['tag']>;
|
||||
}
|
||||
export type IAccessRepositoryMock = { [K in keyof IAccessRepository]: Mocked<IAccessRepository[K]> };
|
||||
|
||||
export const newAccessRepositoryMock = (): IAccessRepositoryMock => {
|
||||
return {
|
||||
|
|
|
@ -3,9 +3,10 @@ import { Writable } from 'node:stream';
|
|||
import { PNG } from 'pngjs';
|
||||
import { ImmichWorker } from 'src/enum';
|
||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { IActivityRepository } from 'src/types';
|
||||
import { IAccessRepository, IActivityRepository } from 'src/types';
|
||||
import { newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
||||
import { newActivityRepositoryMock } from 'test/repositories/activity.repository.mock';
|
||||
import { newAlbumUserRepositoryMock } from 'test/repositories/album-user.repository.mock';
|
||||
|
@ -105,7 +106,7 @@ export const newTestService = <T extends BaseService>(
|
|||
|
||||
const sut = new Service(
|
||||
loggerMock,
|
||||
accessMock,
|
||||
accessMock as IAccessRepository as AccessRepository,
|
||||
activityMock as IActivityRepository as ActivityRepository,
|
||||
auditMock,
|
||||
albumMock,
|
||||
|
|
Loading…
Add table
Reference in a new issue