mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 11:37:06 +02:00
refactor(server): add base methods for access checks (#13349)
This commit is contained in:
parent
97edf90889
commit
8daa8073ae
@ -14,12 +14,11 @@ import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { ActivityEntity } from 'src/entities/activity.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
|
||||
@Injectable()
|
||||
export class ActivityService extends BaseService {
|
||||
async getAll(auth: AuthDto, dto: ActivitySearchDto): Promise<ActivityResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||
const activities = await this.activityRepository.search({
|
||||
userId: dto.userId,
|
||||
albumId: dto.albumId,
|
||||
@ -31,12 +30,12 @@ export class ActivityService extends BaseService {
|
||||
}
|
||||
|
||||
async getStatistics(auth: AuthDto, dto: ActivityDto): Promise<ActivityStatisticsResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||
return { comments: await this.activityRepository.getStatistics(dto.assetId, dto.albumId) };
|
||||
}
|
||||
|
||||
async create(auth: AuthDto, dto: ActivityCreateDto): Promise<MaybeDuplicate<ActivityResponseDto>> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ACTIVITY_CREATE, ids: [dto.albumId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ACTIVITY_CREATE, ids: [dto.albumId] });
|
||||
|
||||
const common = {
|
||||
userId: auth.user.id,
|
||||
@ -70,7 +69,7 @@ export class ActivityService extends BaseService {
|
||||
}
|
||||
|
||||
async delete(auth: AuthDto, id: string): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ACTIVITY_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ACTIVITY_DELETE, ids: [id] });
|
||||
await this.activityRepository.delete(id);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { AlbumAssetCount, AlbumInfoOptions } from 'src/interfaces/album.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { addAssets, removeAssets } from 'src/utils/asset.util';
|
||||
|
||||
@Injectable()
|
||||
@ -82,7 +81,7 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string, dto: AlbumInfoDto): Promise<AlbumResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [id] });
|
||||
await this.albumRepository.updateThumbnails();
|
||||
const withAssets = dto.withoutAssets === undefined ? true : !dto.withoutAssets;
|
||||
const album = await this.findOrFail(id, { withAssets });
|
||||
@ -106,7 +105,7 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
const allowedAssetIdsSet = await checkAccess(this.accessRepository, {
|
||||
const allowedAssetIdsSet = await this.checkAccess({
|
||||
auth,
|
||||
permission: Permission.ASSET_SHARE,
|
||||
ids: dto.assetIds || [],
|
||||
@ -130,7 +129,7 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: UpdateAlbumDto): Promise<AlbumResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_UPDATE, ids: [id] });
|
||||
|
||||
const album = await this.findOrFail(id, { withAssets: true });
|
||||
|
||||
@ -153,13 +152,13 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
|
||||
async delete(auth: AuthDto, id: string): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_DELETE, ids: [id] });
|
||||
await this.albumRepository.delete(id);
|
||||
}
|
||||
|
||||
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
const album = await this.findOrFail(id, { withAssets: false });
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_ADD_ASSET, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_ADD_ASSET, ids: [id] });
|
||||
|
||||
const results = await addAssets(
|
||||
auth,
|
||||
@ -182,7 +181,7 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
|
||||
async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_REMOVE_ASSET, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_REMOVE_ASSET, ids: [id] });
|
||||
|
||||
const album = await this.findOrFail(id, { withAssets: false });
|
||||
const results = await removeAssets(
|
||||
@ -203,7 +202,7 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
|
||||
async addUsers(auth: AuthDto, id: string, { albumUsers }: AddUsersDto): Promise<AlbumResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_SHARE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] });
|
||||
|
||||
const album = await this.findOrFail(id, { withAssets: false });
|
||||
|
||||
@ -247,14 +246,14 @@ export class AlbumService extends BaseService {
|
||||
|
||||
// non-admin can remove themselves
|
||||
if (auth.user.id !== userId) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_SHARE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] });
|
||||
}
|
||||
|
||||
await this.albumUserRepository.delete({ albumId: id, userId });
|
||||
}
|
||||
|
||||
async updateUser(auth: AuthDto, id: string, userId: string, dto: Partial<AlbumUserEntity>): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_SHARE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] });
|
||||
await this.albumUserRepository.update({ albumId: id, userId }, { role: dto.role });
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity } from 'src/entities/asset.entit
|
||||
import { AssetStatus, AssetType, CacheControl, Permission, StorageFolder } from 'src/enum';
|
||||
import { JobName } from 'src/interfaces/job.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess, requireUploadAccess } from 'src/utils/access';
|
||||
import { requireUploadAccess } from 'src/utils/access';
|
||||
import { getAssetFiles, onBeforeLink } from 'src/utils/asset.util';
|
||||
import { ImmichFileResponse } from 'src/utils/file';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
@ -125,7 +125,7 @@ export class AssetMediaService extends BaseService {
|
||||
sidecarFile?: UploadFile,
|
||||
): Promise<AssetMediaResponseDto> {
|
||||
try {
|
||||
await requireAccess(this.accessRepository, {
|
||||
await this.requireAccess({
|
||||
auth,
|
||||
permission: Permission.ASSET_UPLOAD,
|
||||
// do not need an id here, but the interface requires it
|
||||
@ -159,7 +159,7 @@ export class AssetMediaService extends BaseService {
|
||||
sidecarFile?: UploadFile,
|
||||
): Promise<AssetMediaResponseDto> {
|
||||
try {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_UPDATE, ids: [id] });
|
||||
const asset = (await this.assetRepository.getById(id)) as AssetEntity;
|
||||
|
||||
this.requireQuota(auth, file.size);
|
||||
@ -182,7 +182,7 @@ export class AssetMediaService extends BaseService {
|
||||
}
|
||||
|
||||
async downloadOriginal(auth: AuthDto, id: string): Promise<ImmichFileResponse> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_DOWNLOAD, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_DOWNLOAD, ids: [id] });
|
||||
|
||||
const asset = await this.findOrFail(id);
|
||||
|
||||
@ -194,7 +194,7 @@ export class AssetMediaService extends BaseService {
|
||||
}
|
||||
|
||||
async viewThumbnail(auth: AuthDto, id: string, dto: AssetMediaOptionsDto): Promise<ImmichFileResponse> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_VIEW, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_VIEW, ids: [id] });
|
||||
|
||||
const asset = await this.findOrFail(id);
|
||||
const size = dto.size ?? AssetMediaSize.THUMBNAIL;
|
||||
@ -217,7 +217,7 @@ export class AssetMediaService extends BaseService {
|
||||
}
|
||||
|
||||
async playbackVideo(auth: AuthDto, id: string): Promise<ImmichFileResponse> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_VIEW, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_VIEW, ids: [id] });
|
||||
|
||||
const asset = await this.findOrFail(id);
|
||||
|
||||
|
@ -29,7 +29,6 @@ import {
|
||||
JobStatus,
|
||||
} from 'src/interfaces/job.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
import { getAssetFiles, getMyPartnerIds, onAfterUnlink, onBeforeLink, onBeforeUnlink } from 'src/utils/asset.util';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
|
||||
@ -86,7 +85,7 @@ export class AssetService extends BaseService {
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string): Promise<AssetResponseDto | SanitizedAssetResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_READ, ids: [id] });
|
||||
|
||||
const asset = await this.assetRepository.getById(
|
||||
id,
|
||||
@ -135,7 +134,7 @@ export class AssetService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: UpdateAssetDto): Promise<AssetResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_UPDATE, ids: [id] });
|
||||
|
||||
const { description, dateTimeOriginal, latitude, longitude, rating, ...rest } = dto;
|
||||
const repos = { asset: this.assetRepository, event: this.eventRepository };
|
||||
@ -178,7 +177,7 @@ export class AssetService extends BaseService {
|
||||
|
||||
async updateAll(auth: AuthDto, dto: AssetBulkUpdateDto): Promise<void> {
|
||||
const { ids, dateTimeOriginal, latitude, longitude, ...options } = dto;
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_UPDATE, ids });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_UPDATE, ids });
|
||||
|
||||
for (const id of ids) {
|
||||
await this.updateMetadata({ id, dateTimeOriginal, latitude, longitude });
|
||||
@ -275,7 +274,7 @@ export class AssetService extends BaseService {
|
||||
async deleteAll(auth: AuthDto, dto: AssetBulkDeleteDto): Promise<void> {
|
||||
const { ids, force } = dto;
|
||||
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_DELETE, ids });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_DELETE, ids });
|
||||
await this.assetRepository.updateAll(ids, {
|
||||
deletedAt: new Date(),
|
||||
status: force ? AssetStatus.DELETED : AssetStatus.TRASHED,
|
||||
@ -284,7 +283,7 @@ export class AssetService extends BaseService {
|
||||
}
|
||||
|
||||
async run(auth: AuthDto, dto: AssetJobsDto) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds });
|
||||
|
||||
const jobs: JobItem[] = [];
|
||||
|
||||
|
@ -23,7 +23,6 @@ import {
|
||||
} from 'src/enum';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE, JobStatus } from 'src/interfaces/job.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
import { getAssetFiles } from 'src/utils/asset.util';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
|
||||
@ -36,7 +35,7 @@ export class AuditService extends BaseService {
|
||||
|
||||
async getDeletes(auth: AuthDto, dto: AuditDeletesDto): Promise<AuditDeletesResponseDto> {
|
||||
const userId = dto.userId || auth.user.id;
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TIMELINE_READ, ids: [userId] });
|
||||
await this.requireAccess({ auth, permission: Permission.TIMELINE_READ, ids: [userId] });
|
||||
|
||||
const audits = await this.auditRepository.getAfter(dto.after, {
|
||||
userIds: [userId],
|
||||
|
@ -38,6 +38,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 { AccessRequest, checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { getConfig, updateConfig } from 'src/utils/config';
|
||||
|
||||
export class BaseService {
|
||||
@ -95,7 +96,7 @@ export class BaseService {
|
||||
);
|
||||
}
|
||||
|
||||
private get repos() {
|
||||
private get configRepos() {
|
||||
return {
|
||||
configRepo: this.configRepository,
|
||||
metadataRepo: this.systemMetadataRepository,
|
||||
@ -104,10 +105,18 @@ export class BaseService {
|
||||
}
|
||||
|
||||
getConfig(options: { withCache: boolean }) {
|
||||
return getConfig(this.repos, options);
|
||||
return getConfig(this.configRepos, options);
|
||||
}
|
||||
|
||||
updateConfig(newConfig: SystemConfig) {
|
||||
return updateConfig(this.repos, newConfig);
|
||||
return updateConfig(this.configRepos, newConfig);
|
||||
}
|
||||
|
||||
requireAccess(request: AccessRequest) {
|
||||
return requireAccess(this.accessRepository, request);
|
||||
}
|
||||
|
||||
checkAccess(request: AccessRequest) {
|
||||
return checkAccess(this.accessRepository, request);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { ImmichReadStream } from 'src/interfaces/storage.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
import { HumanReadableSize } from 'src/utils/bytes';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
import { getPreferences } from 'src/utils/preferences';
|
||||
@ -62,7 +61,7 @@ export class DownloadService extends BaseService {
|
||||
}
|
||||
|
||||
async downloadArchive(auth: AuthDto, dto: AssetIdsDto): Promise<ImmichReadStream> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_DOWNLOAD, ids: dto.assetIds });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_DOWNLOAD, ids: dto.assetIds });
|
||||
|
||||
const zip = this.storageRepository.createZipStream();
|
||||
const assets = await this.assetRepository.getByIds(dto.assetIds);
|
||||
@ -105,20 +104,20 @@ export class DownloadService extends BaseService {
|
||||
|
||||
if (dto.assetIds) {
|
||||
const assetIds = dto.assetIds;
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_DOWNLOAD, ids: assetIds });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_DOWNLOAD, ids: assetIds });
|
||||
const assets = await this.assetRepository.getByIds(assetIds, { exifInfo: true });
|
||||
return usePagination(PAGINATION_SIZE, () => ({ hasNextPage: false, items: assets }));
|
||||
}
|
||||
|
||||
if (dto.albumId) {
|
||||
const albumId = dto.albumId;
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_DOWNLOAD, ids: [albumId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_DOWNLOAD, ids: [albumId] });
|
||||
return usePagination(PAGINATION_SIZE, (pagination) => this.assetRepository.getByAlbumId(pagination, albumId));
|
||||
}
|
||||
|
||||
if (dto.userId) {
|
||||
const userId = dto.userId;
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TIMELINE_DOWNLOAD, ids: [userId] });
|
||||
await this.requireAccess({ auth, permission: Permission.TIMELINE_DOWNLOAD, ids: [userId] });
|
||||
return usePagination(PAGINATION_SIZE, (pagination) =>
|
||||
this.assetRepository.getByUserId(pagination, userId, { isVisible: true }),
|
||||
);
|
||||
|
@ -5,7 +5,6 @@ import { MemoryCreateDto, MemoryResponseDto, MemoryUpdateDto, mapMemory } from '
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { addAssets, removeAssets } from 'src/utils/asset.util';
|
||||
|
||||
@Injectable()
|
||||
@ -16,7 +15,7 @@ export class MemoryService extends BaseService {
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string): Promise<MemoryResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.MEMORY_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.MEMORY_READ, ids: [id] });
|
||||
const memory = await this.findOrFail(id);
|
||||
return mapMemory(memory);
|
||||
}
|
||||
@ -25,7 +24,7 @@ export class MemoryService extends BaseService {
|
||||
// TODO validate type/data combination
|
||||
|
||||
const assetIds = dto.assetIds || [];
|
||||
const allowedAssetIds = await checkAccess(this.accessRepository, {
|
||||
const allowedAssetIds = await this.checkAccess({
|
||||
auth,
|
||||
permission: Permission.ASSET_SHARE,
|
||||
ids: assetIds,
|
||||
@ -44,7 +43,7 @@ export class MemoryService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: MemoryUpdateDto): Promise<MemoryResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.MEMORY_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.MEMORY_UPDATE, ids: [id] });
|
||||
|
||||
const memory = await this.memoryRepository.update({
|
||||
id,
|
||||
@ -57,12 +56,12 @@ export class MemoryService extends BaseService {
|
||||
}
|
||||
|
||||
async remove(auth: AuthDto, id: string): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.MEMORY_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.MEMORY_DELETE, ids: [id] });
|
||||
await this.memoryRepository.delete(id);
|
||||
}
|
||||
|
||||
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.MEMORY_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.MEMORY_READ, ids: [id] });
|
||||
|
||||
const repos = { access: this.accessRepository, bulk: this.memoryRepository };
|
||||
const results = await addAssets(auth, repos, { parentId: id, assetIds: dto.ids });
|
||||
@ -76,7 +75,7 @@ export class MemoryService extends BaseService {
|
||||
}
|
||||
|
||||
async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.MEMORY_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.MEMORY_UPDATE, ids: [id] });
|
||||
|
||||
const repos = { access: this.accessRepository, bulk: this.memoryRepository };
|
||||
const results = await removeAssets(auth, repos, {
|
||||
|
@ -6,7 +6,6 @@ import { PartnerEntity } from 'src/entities/partner.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { PartnerDirection, PartnerIds } from 'src/interfaces/partner.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
|
||||
@Injectable()
|
||||
export class PartnerService extends BaseService {
|
||||
@ -41,7 +40,7 @@ export class PartnerService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, sharedById: string, dto: UpdatePartnerDto): Promise<PartnerResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PARTNER_UPDATE, ids: [sharedById] });
|
||||
await this.requireAccess({ auth, permission: Permission.PARTNER_UPDATE, ids: [sharedById] });
|
||||
const partnerId: PartnerIds = { sharedById, sharedWithId: auth.user.id };
|
||||
|
||||
const entity = await this.partnerRepository.update({ ...partnerId, inTimeline: dto.inTimeline });
|
||||
|
@ -47,7 +47,6 @@ import { BoundingBox } from 'src/interfaces/machine-learning.interface';
|
||||
import { CropOptions, ImageDimensions, InputDimensions } from 'src/interfaces/media.interface';
|
||||
import { UpdateFacesData } from 'src/interfaces/person.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { getAssetFiles } from 'src/utils/asset.util';
|
||||
import { ImmichFileResponse } from 'src/utils/file';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
@ -80,7 +79,7 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async reassignFaces(auth: AuthDto, personId: string, dto: AssetFaceUpdateDto): Promise<PersonResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_UPDATE, ids: [personId] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [personId] });
|
||||
const person = await this.findOrFail(personId);
|
||||
const result: PersonResponseDto[] = [];
|
||||
const changeFeaturePhoto: string[] = [];
|
||||
@ -88,7 +87,7 @@ export class PersonService extends BaseService {
|
||||
const faces = await this.personRepository.getFacesByIds([{ personId: data.personId, assetId: data.assetId }]);
|
||||
|
||||
for (const face of faces) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_CREATE, ids: [face.id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_CREATE, ids: [face.id] });
|
||||
if (person.faceAssetId === null) {
|
||||
changeFeaturePhoto.push(person.id);
|
||||
}
|
||||
@ -109,8 +108,8 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async reassignFacesById(auth: AuthDto, personId: string, dto: FaceDto): Promise<PersonResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_UPDATE, ids: [personId] });
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_CREATE, ids: [dto.id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [personId] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_CREATE, ids: [dto.id] });
|
||||
const face = await this.personRepository.getFaceById(dto.id);
|
||||
const person = await this.findOrFail(personId);
|
||||
|
||||
@ -126,7 +125,7 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async getFacesById(auth: AuthDto, dto: FaceDto): Promise<AssetFaceResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_READ, ids: [dto.id] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_READ, ids: [dto.id] });
|
||||
const faces = await this.personRepository.getFaces(dto.id);
|
||||
return faces.map((asset) => mapFaces(asset, auth));
|
||||
}
|
||||
@ -150,17 +149,17 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async getById(auth: AuthDto, id: string): Promise<PersonResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
return this.findOrFail(id).then(mapPerson);
|
||||
}
|
||||
|
||||
async getStatistics(auth: AuthDto, id: string): Promise<PersonStatisticsResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
return this.personRepository.getStatistics(id);
|
||||
}
|
||||
|
||||
async getThumbnail(auth: AuthDto, id: string): Promise<ImmichFileResponse> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_READ, ids: [id] });
|
||||
const person = await this.personRepository.getById(id);
|
||||
if (!person || !person.thumbnailPath) {
|
||||
throw new NotFoundException();
|
||||
@ -183,13 +182,13 @@ export class PersonService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: PersonUpdateDto): Promise<PersonResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||
|
||||
const { name, birthDate, isHidden, featureFaceAssetId: assetId } = dto;
|
||||
// TODO: set by faceId directly
|
||||
let faceId: string | undefined = undefined;
|
||||
if (assetId) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_READ, ids: [assetId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_READ, ids: [assetId] });
|
||||
const [face] = await this.personRepository.getFacesByIds([{ personId: id, assetId }]);
|
||||
if (!face) {
|
||||
throw new BadRequestException('Invalid assetId for feature face');
|
||||
@ -584,13 +583,13 @@ export class PersonService extends BaseService {
|
||||
throw new BadRequestException('Cannot merge a person into themselves');
|
||||
}
|
||||
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||
let primaryPerson = await this.findOrFail(id);
|
||||
const primaryName = primaryPerson.name || primaryPerson.id;
|
||||
|
||||
const results: BulkIdResponseDto[] = [];
|
||||
|
||||
const allowedIds = await checkAccess(this.accessRepository, {
|
||||
const allowedIds = await this.checkAccess({
|
||||
auth,
|
||||
permission: Permission.PERSON_MERGE,
|
||||
ids: mergeIds,
|
||||
|
@ -5,7 +5,6 @@ import { SessionResponseDto, mapSession } from 'src/dtos/session.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { JobStatus } from 'src/interfaces/job.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
|
||||
@Injectable()
|
||||
export class SessionService extends BaseService {
|
||||
@ -34,7 +33,7 @@ export class SessionService extends BaseService {
|
||||
}
|
||||
|
||||
async delete(auth: AuthDto, id: string): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.AUTH_DEVICE_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.AUTH_DEVICE_DELETE, ids: [id] });
|
||||
await this.sessionRepository.delete(id);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { Permission, SharedLinkType } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { OpenGraphTags } from 'src/utils/misc';
|
||||
|
||||
@Injectable()
|
||||
@ -49,7 +48,7 @@ export class SharedLinkService extends BaseService {
|
||||
if (!dto.albumId) {
|
||||
throw new BadRequestException('Invalid albumId');
|
||||
}
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_SHARE, ids: [dto.albumId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [dto.albumId] });
|
||||
break;
|
||||
}
|
||||
|
||||
@ -58,7 +57,7 @@ export class SharedLinkService extends BaseService {
|
||||
throw new BadRequestException('Invalid assetIds');
|
||||
}
|
||||
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_SHARE, ids: dto.assetIds });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_SHARE, ids: dto.assetIds });
|
||||
|
||||
break;
|
||||
}
|
||||
@ -119,7 +118,7 @@ export class SharedLinkService extends BaseService {
|
||||
|
||||
const existingAssetIds = new Set(sharedLink.assets.map((asset) => asset.id));
|
||||
const notPresentAssetIds = dto.assetIds.filter((assetId) => !existingAssetIds.has(assetId));
|
||||
const allowedAssetIds = await checkAccess(this.accessRepository, {
|
||||
const allowedAssetIds = await this.checkAccess({
|
||||
auth,
|
||||
permission: Permission.ASSET_SHARE,
|
||||
ids: notPresentAssetIds,
|
||||
|
@ -4,7 +4,6 @@ import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { StackCreateDto, StackResponseDto, StackSearchDto, StackUpdateDto, mapStack } from 'src/dtos/stack.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
|
||||
@Injectable()
|
||||
export class StackService extends BaseService {
|
||||
@ -18,7 +17,7 @@ export class StackService extends BaseService {
|
||||
}
|
||||
|
||||
async create(auth: AuthDto, dto: StackCreateDto): Promise<StackResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds });
|
||||
|
||||
const stack = await this.stackRepository.create({ ownerId: auth.user.id, assetIds: dto.assetIds });
|
||||
|
||||
@ -28,13 +27,13 @@ export class StackService extends BaseService {
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string): Promise<StackResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.STACK_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.STACK_READ, ids: [id] });
|
||||
const stack = await this.findOrFail(id);
|
||||
return mapStack(stack, { auth });
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: StackUpdateDto): Promise<StackResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.STACK_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.STACK_UPDATE, ids: [id] });
|
||||
const stack = await this.findOrFail(id);
|
||||
if (dto.primaryAssetId && !stack.assets.some(({ id }) => id === dto.primaryAssetId)) {
|
||||
throw new BadRequestException('Primary asset must be in the stack');
|
||||
@ -48,13 +47,13 @@ export class StackService extends BaseService {
|
||||
}
|
||||
|
||||
async delete(auth: AuthDto, id: string): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.STACK_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.STACK_DELETE, ids: [id] });
|
||||
await this.stackRepository.delete(id);
|
||||
await this.eventRepository.emit('stack.delete', { stackId: id, userId: auth.user.id });
|
||||
}
|
||||
|
||||
async deleteAll(auth: AuthDto, dto: BulkIdsDto): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.STACK_DELETE, ids: dto.ids });
|
||||
await this.requireAccess({ auth, permission: Permission.STACK_DELETE, ids: dto.ids });
|
||||
await this.stackRepository.deleteAll(dto.ids);
|
||||
await this.eventRepository.emit('stacks.delete', { stackIds: dto.ids, userId: auth.user.id });
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AssetDeltaSyncDto, AssetDeltaSyncResponseDto, AssetFullSyncDto } from 'src/dtos/sync.dto';
|
||||
import { DatabaseAction, EntityType, Permission } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
import { getMyPartnerIds } from 'src/utils/asset.util';
|
||||
import { setIsEqual } from 'src/utils/set';
|
||||
|
||||
@ -15,7 +14,7 @@ export class SyncService extends BaseService {
|
||||
async getFullSync(auth: AuthDto, dto: AssetFullSyncDto): Promise<AssetResponseDto[]> {
|
||||
// mobile implementation is faster if this is a single id
|
||||
const userId = dto.userId || auth.user.id;
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TIMELINE_READ, ids: [userId] });
|
||||
await this.requireAccess({ auth, permission: Permission.TIMELINE_READ, ids: [userId] });
|
||||
const assets = await this.assetRepository.getAllForUserFullSync({
|
||||
ownerId: userId,
|
||||
updatedUntil: dto.updatedUntil,
|
||||
@ -39,7 +38,7 @@ export class SyncService extends BaseService {
|
||||
return FULL_SYNC;
|
||||
}
|
||||
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TIMELINE_READ, ids: dto.userIds });
|
||||
await this.requireAccess({ auth, permission: Permission.TIMELINE_READ, ids: dto.userIds });
|
||||
|
||||
const limit = 10_000;
|
||||
const upserted = await this.assetRepository.getChangedDeltaSync({ limit, updatedAfter: dto.updatedAfter, userIds });
|
||||
|
@ -15,7 +15,6 @@ import { Permission } from 'src/enum';
|
||||
import { JobStatus } from 'src/interfaces/job.interface';
|
||||
import { AssetTagItem } from 'src/interfaces/tag.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { checkAccess, requireAccess } from 'src/utils/access';
|
||||
import { addAssets, removeAssets } from 'src/utils/asset.util';
|
||||
import { upsertTags } from 'src/utils/tag';
|
||||
|
||||
@ -27,7 +26,7 @@ export class TagService extends BaseService {
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string): Promise<TagResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_READ, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_READ, ids: [id] });
|
||||
const tag = await this.findOrFail(id);
|
||||
return mapTag(tag);
|
||||
}
|
||||
@ -35,7 +34,7 @@ export class TagService extends BaseService {
|
||||
async create(auth: AuthDto, dto: TagCreateDto) {
|
||||
let parent: TagEntity | undefined;
|
||||
if (dto.parentId) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_READ, ids: [dto.parentId] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_READ, ids: [dto.parentId] });
|
||||
parent = (await this.tagRepository.get(dto.parentId)) || undefined;
|
||||
if (!parent) {
|
||||
throw new BadRequestException('Tag not found');
|
||||
@ -55,7 +54,7 @@ export class TagService extends BaseService {
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: TagUpdateDto): Promise<TagResponseDto> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_UPDATE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_UPDATE, ids: [id] });
|
||||
|
||||
const { color } = dto;
|
||||
const tag = await this.tagRepository.update({ id, color });
|
||||
@ -68,7 +67,7 @@ export class TagService extends BaseService {
|
||||
}
|
||||
|
||||
async remove(auth: AuthDto, id: string): Promise<void> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_DELETE, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_DELETE, ids: [id] });
|
||||
|
||||
// TODO sync tag changes for affected assets
|
||||
|
||||
@ -77,8 +76,8 @@ export class TagService extends BaseService {
|
||||
|
||||
async bulkTagAssets(auth: AuthDto, dto: TagBulkAssetsDto): Promise<TagBulkAssetsResponseDto> {
|
||||
const [tagIds, assetIds] = await Promise.all([
|
||||
checkAccess(this.accessRepository, { auth, permission: Permission.TAG_ASSET, ids: dto.tagIds }),
|
||||
checkAccess(this.accessRepository, { auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds }),
|
||||
this.checkAccess({ auth, permission: Permission.TAG_ASSET, ids: dto.tagIds }),
|
||||
this.checkAccess({ auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds }),
|
||||
]);
|
||||
|
||||
const items: AssetTagItem[] = [];
|
||||
@ -97,7 +96,7 @@ export class TagService extends BaseService {
|
||||
}
|
||||
|
||||
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_ASSET, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_ASSET, ids: [id] });
|
||||
|
||||
const results = await addAssets(
|
||||
auth,
|
||||
@ -115,7 +114,7 @@ export class TagService extends BaseService {
|
||||
}
|
||||
|
||||
async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_ASSET, ids: [id] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_ASSET, ids: [id] });
|
||||
|
||||
const results = await removeAssets(
|
||||
auth,
|
||||
|
@ -5,7 +5,6 @@ import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dt
|
||||
import { Permission } from 'src/enum';
|
||||
import { TimeBucketOptions } from 'src/interfaces/asset.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
import { getMyPartnerIds } from 'src/utils/asset.util';
|
||||
|
||||
export class TimelineService extends BaseService {
|
||||
@ -48,20 +47,20 @@ export class TimelineService extends BaseService {
|
||||
|
||||
private async timeBucketChecks(auth: AuthDto, dto: TimeBucketDto) {
|
||||
if (dto.albumId) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
||||
} else {
|
||||
dto.userId = dto.userId || auth.user.id;
|
||||
}
|
||||
|
||||
if (dto.userId) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TIMELINE_READ, ids: [dto.userId] });
|
||||
await this.requireAccess({ auth, permission: Permission.TIMELINE_READ, ids: [dto.userId] });
|
||||
if (dto.isArchived !== false) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ARCHIVE_READ, ids: [dto.userId] });
|
||||
await this.requireAccess({ auth, permission: Permission.ARCHIVE_READ, ids: [dto.userId] });
|
||||
}
|
||||
}
|
||||
|
||||
if (dto.tagId) {
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.TAG_READ, ids: [dto.tagId] });
|
||||
await this.requireAccess({ auth, permission: Permission.TAG_READ, ids: [dto.tagId] });
|
||||
}
|
||||
|
||||
if (dto.withPartners) {
|
||||
|
@ -5,7 +5,6 @@ import { TrashResponseDto } from 'src/dtos/trash.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { requireAccess } from 'src/utils/access';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
|
||||
export class TrashService extends BaseService {
|
||||
@ -15,7 +14,7 @@ export class TrashService extends BaseService {
|
||||
return { count: 0 };
|
||||
}
|
||||
|
||||
await requireAccess(this.accessRepository, { auth, permission: Permission.ASSET_DELETE, ids });
|
||||
await this.requireAccess({ auth, permission: Permission.ASSET_DELETE, ids });
|
||||
await this.trashRepository.restoreAll(ids);
|
||||
await this.eventRepository.emit('assets.restore', { assetIds: ids, userId: auth.user.id });
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user