feat!: more permissions (#20250)

feat: more api key permissions
This commit is contained in:
Jason Rasmussen 2025-07-25 15:25:23 -04:00 committed by GitHub
parent 153bb70f6e
commit 0fdeac0417
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 414 additions and 120 deletions

View File

@ -470,7 +470,7 @@ describe('/albums', () => {
.send({ ids: [asset.id] }); .send({ ids: [asset.id] });
expect(status).toBe(400); expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('Not found or no album.addAsset access')); expect(body).toEqual(errorDto.badRequest('Not found or no albumAsset.create access'));
}); });
it('should add duplicate assets only once', async () => { it('should add duplicate assets only once', async () => {
@ -599,7 +599,7 @@ describe('/albums', () => {
.send({ ids: [user1Asset1.id] }); .send({ ids: [user1Asset1.id] });
expect(status).toBe(400); expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('Not found or no album.removeAsset access')); expect(body).toEqual(errorDto.badRequest('Not found or no albumAsset.delete access'));
}); });
it('should remove duplicate assets only once', async () => { it('should remove duplicate assets only once', async () => {

View File

@ -36,25 +36,35 @@ class Permission {
static const assetPeriodRead = Permission._(r'asset.read'); static const assetPeriodRead = Permission._(r'asset.read');
static const assetPeriodUpdate = Permission._(r'asset.update'); static const assetPeriodUpdate = Permission._(r'asset.update');
static const assetPeriodDelete = Permission._(r'asset.delete'); static const assetPeriodDelete = Permission._(r'asset.delete');
static const assetPeriodStatistics = Permission._(r'asset.statistics');
static const assetPeriodShare = Permission._(r'asset.share'); static const assetPeriodShare = Permission._(r'asset.share');
static const assetPeriodView = Permission._(r'asset.view'); static const assetPeriodView = Permission._(r'asset.view');
static const assetPeriodDownload = Permission._(r'asset.download'); static const assetPeriodDownload = Permission._(r'asset.download');
static const assetPeriodUpload = Permission._(r'asset.upload'); static const assetPeriodUpload = Permission._(r'asset.upload');
static const assetPeriodReplace = Permission._(r'asset.replace');
static const albumPeriodCreate = Permission._(r'album.create'); static const albumPeriodCreate = Permission._(r'album.create');
static const albumPeriodRead = Permission._(r'album.read'); static const albumPeriodRead = Permission._(r'album.read');
static const albumPeriodUpdate = Permission._(r'album.update'); static const albumPeriodUpdate = Permission._(r'album.update');
static const albumPeriodDelete = Permission._(r'album.delete'); static const albumPeriodDelete = Permission._(r'album.delete');
static const albumPeriodStatistics = Permission._(r'album.statistics'); static const albumPeriodStatistics = Permission._(r'album.statistics');
static const albumPeriodAddAsset = Permission._(r'album.addAsset');
static const albumPeriodRemoveAsset = Permission._(r'album.removeAsset');
static const albumPeriodShare = Permission._(r'album.share'); static const albumPeriodShare = Permission._(r'album.share');
static const albumPeriodDownload = Permission._(r'album.download'); static const albumPeriodDownload = Permission._(r'album.download');
static const albumAssetPeriodCreate = Permission._(r'albumAsset.create');
static const albumAssetPeriodDelete = Permission._(r'albumAsset.delete');
static const albumUserPeriodCreate = Permission._(r'albumUser.create');
static const albumUserPeriodUpdate = Permission._(r'albumUser.update');
static const albumUserPeriodDelete = Permission._(r'albumUser.delete');
static const authPeriodChangePassword = Permission._(r'auth.changePassword');
static const authDevicePeriodDelete = Permission._(r'authDevice.delete'); static const authDevicePeriodDelete = Permission._(r'authDevice.delete');
static const archivePeriodRead = Permission._(r'archive.read'); static const archivePeriodRead = Permission._(r'archive.read');
static const duplicatePeriodRead = Permission._(r'duplicate.read');
static const duplicatePeriodDelete = Permission._(r'duplicate.delete');
static const facePeriodCreate = Permission._(r'face.create'); static const facePeriodCreate = Permission._(r'face.create');
static const facePeriodRead = Permission._(r'face.read'); static const facePeriodRead = Permission._(r'face.read');
static const facePeriodUpdate = Permission._(r'face.update'); static const facePeriodUpdate = Permission._(r'face.update');
static const facePeriodDelete = Permission._(r'face.delete'); static const facePeriodDelete = Permission._(r'face.delete');
static const jobPeriodCreate = Permission._(r'job.create');
static const jobPeriodRead = Permission._(r'job.read');
static const libraryPeriodCreate = Permission._(r'library.create'); static const libraryPeriodCreate = Permission._(r'library.create');
static const libraryPeriodRead = Permission._(r'library.read'); static const libraryPeriodRead = Permission._(r'library.read');
static const libraryPeriodUpdate = Permission._(r'library.update'); static const libraryPeriodUpdate = Permission._(r'library.update');
@ -66,6 +76,9 @@ class Permission {
static const memoryPeriodRead = Permission._(r'memory.read'); static const memoryPeriodRead = Permission._(r'memory.read');
static const memoryPeriodUpdate = Permission._(r'memory.update'); static const memoryPeriodUpdate = Permission._(r'memory.update');
static const memoryPeriodDelete = Permission._(r'memory.delete'); static const memoryPeriodDelete = Permission._(r'memory.delete');
static const memoryPeriodStatistics = Permission._(r'memory.statistics');
static const memoryAssetPeriodCreate = Permission._(r'memoryAsset.create');
static const memoryAssetPeriodDelete = Permission._(r'memoryAsset.delete');
static const notificationPeriodCreate = Permission._(r'notification.create'); static const notificationPeriodCreate = Permission._(r'notification.create');
static const notificationPeriodRead = Permission._(r'notification.read'); static const notificationPeriodRead = Permission._(r'notification.read');
static const notificationPeriodUpdate = Permission._(r'notification.update'); static const notificationPeriodUpdate = Permission._(r'notification.update');
@ -81,6 +94,16 @@ class Permission {
static const personPeriodStatistics = Permission._(r'person.statistics'); static const personPeriodStatistics = Permission._(r'person.statistics');
static const personPeriodMerge = Permission._(r'person.merge'); static const personPeriodMerge = Permission._(r'person.merge');
static const personPeriodReassign = Permission._(r'person.reassign'); static const personPeriodReassign = Permission._(r'person.reassign');
static const pinCodePeriodCreate = Permission._(r'pinCode.create');
static const pinCodePeriodUpdate = Permission._(r'pinCode.update');
static const pinCodePeriodDelete = Permission._(r'pinCode.delete');
static const serverPeriodAbout = Permission._(r'server.about');
static const serverPeriodApkLinks = Permission._(r'server.apkLinks');
static const serverPeriodStorage = Permission._(r'server.storage');
static const serverPeriodStatistics = Permission._(r'server.statistics');
static const serverLicensePeriodRead = Permission._(r'serverLicense.read');
static const serverLicensePeriodUpdate = Permission._(r'serverLicense.update');
static const serverLicensePeriodDelete = Permission._(r'serverLicense.delete');
static const sessionPeriodCreate = Permission._(r'session.create'); static const sessionPeriodCreate = Permission._(r'session.create');
static const sessionPeriodRead = Permission._(r'session.read'); static const sessionPeriodRead = Permission._(r'session.read');
static const sessionPeriodUpdate = Permission._(r'session.update'); static const sessionPeriodUpdate = Permission._(r'session.update');
@ -94,6 +117,10 @@ class Permission {
static const stackPeriodRead = Permission._(r'stack.read'); static const stackPeriodRead = Permission._(r'stack.read');
static const stackPeriodUpdate = Permission._(r'stack.update'); static const stackPeriodUpdate = Permission._(r'stack.update');
static const stackPeriodDelete = Permission._(r'stack.delete'); static const stackPeriodDelete = Permission._(r'stack.delete');
static const syncPeriodStream = Permission._(r'sync.stream');
static const syncCheckpointPeriodRead = Permission._(r'syncCheckpoint.read');
static const syncCheckpointPeriodUpdate = Permission._(r'syncCheckpoint.update');
static const syncCheckpointPeriodDelete = Permission._(r'syncCheckpoint.delete');
static const systemConfigPeriodRead = Permission._(r'systemConfig.read'); static const systemConfigPeriodRead = Permission._(r'systemConfig.read');
static const systemConfigPeriodUpdate = Permission._(r'systemConfig.update'); static const systemConfigPeriodUpdate = Permission._(r'systemConfig.update');
static const systemMetadataPeriodRead = Permission._(r'systemMetadata.read'); static const systemMetadataPeriodRead = Permission._(r'systemMetadata.read');
@ -103,10 +130,25 @@ class Permission {
static const tagPeriodUpdate = Permission._(r'tag.update'); static const tagPeriodUpdate = Permission._(r'tag.update');
static const tagPeriodDelete = Permission._(r'tag.delete'); static const tagPeriodDelete = Permission._(r'tag.delete');
static const tagPeriodAsset = Permission._(r'tag.asset'); static const tagPeriodAsset = Permission._(r'tag.asset');
static const adminPeriodUserPeriodCreate = Permission._(r'admin.user.create'); static const userPeriodRead = Permission._(r'user.read');
static const adminPeriodUserPeriodRead = Permission._(r'admin.user.read'); static const userPeriodUpdate = Permission._(r'user.update');
static const adminPeriodUserPeriodUpdate = Permission._(r'admin.user.update'); static const userLicensePeriodCreate = Permission._(r'userLicense.create');
static const adminPeriodUserPeriodDelete = Permission._(r'admin.user.delete'); static const userLicensePeriodRead = Permission._(r'userLicense.read');
static const userLicensePeriodUpdate = Permission._(r'userLicense.update');
static const userLicensePeriodDelete = Permission._(r'userLicense.delete');
static const userOnboardingPeriodRead = Permission._(r'userOnboarding.read');
static const userOnboardingPeriodUpdate = Permission._(r'userOnboarding.update');
static const userOnboardingPeriodDelete = Permission._(r'userOnboarding.delete');
static const userPreferencePeriodRead = Permission._(r'userPreference.read');
static const userPreferencePeriodUpdate = Permission._(r'userPreference.update');
static const userProfileImagePeriodCreate = Permission._(r'userProfileImage.create');
static const userProfileImagePeriodRead = Permission._(r'userProfileImage.read');
static const userProfileImagePeriodUpdate = Permission._(r'userProfileImage.update');
static const userProfileImagePeriodDelete = Permission._(r'userProfileImage.delete');
static const adminUserPeriodCreate = Permission._(r'adminUser.create');
static const adminUserPeriodRead = Permission._(r'adminUser.read');
static const adminUserPeriodUpdate = Permission._(r'adminUser.update');
static const adminUserPeriodDelete = Permission._(r'adminUser.delete');
/// List of all possible values in this [enum][Permission]. /// List of all possible values in this [enum][Permission].
static const values = <Permission>[ static const values = <Permission>[
@ -123,25 +165,35 @@ class Permission {
assetPeriodRead, assetPeriodRead,
assetPeriodUpdate, assetPeriodUpdate,
assetPeriodDelete, assetPeriodDelete,
assetPeriodStatistics,
assetPeriodShare, assetPeriodShare,
assetPeriodView, assetPeriodView,
assetPeriodDownload, assetPeriodDownload,
assetPeriodUpload, assetPeriodUpload,
assetPeriodReplace,
albumPeriodCreate, albumPeriodCreate,
albumPeriodRead, albumPeriodRead,
albumPeriodUpdate, albumPeriodUpdate,
albumPeriodDelete, albumPeriodDelete,
albumPeriodStatistics, albumPeriodStatistics,
albumPeriodAddAsset,
albumPeriodRemoveAsset,
albumPeriodShare, albumPeriodShare,
albumPeriodDownload, albumPeriodDownload,
albumAssetPeriodCreate,
albumAssetPeriodDelete,
albumUserPeriodCreate,
albumUserPeriodUpdate,
albumUserPeriodDelete,
authPeriodChangePassword,
authDevicePeriodDelete, authDevicePeriodDelete,
archivePeriodRead, archivePeriodRead,
duplicatePeriodRead,
duplicatePeriodDelete,
facePeriodCreate, facePeriodCreate,
facePeriodRead, facePeriodRead,
facePeriodUpdate, facePeriodUpdate,
facePeriodDelete, facePeriodDelete,
jobPeriodCreate,
jobPeriodRead,
libraryPeriodCreate, libraryPeriodCreate,
libraryPeriodRead, libraryPeriodRead,
libraryPeriodUpdate, libraryPeriodUpdate,
@ -153,6 +205,9 @@ class Permission {
memoryPeriodRead, memoryPeriodRead,
memoryPeriodUpdate, memoryPeriodUpdate,
memoryPeriodDelete, memoryPeriodDelete,
memoryPeriodStatistics,
memoryAssetPeriodCreate,
memoryAssetPeriodDelete,
notificationPeriodCreate, notificationPeriodCreate,
notificationPeriodRead, notificationPeriodRead,
notificationPeriodUpdate, notificationPeriodUpdate,
@ -168,6 +223,16 @@ class Permission {
personPeriodStatistics, personPeriodStatistics,
personPeriodMerge, personPeriodMerge,
personPeriodReassign, personPeriodReassign,
pinCodePeriodCreate,
pinCodePeriodUpdate,
pinCodePeriodDelete,
serverPeriodAbout,
serverPeriodApkLinks,
serverPeriodStorage,
serverPeriodStatistics,
serverLicensePeriodRead,
serverLicensePeriodUpdate,
serverLicensePeriodDelete,
sessionPeriodCreate, sessionPeriodCreate,
sessionPeriodRead, sessionPeriodRead,
sessionPeriodUpdate, sessionPeriodUpdate,
@ -181,6 +246,10 @@ class Permission {
stackPeriodRead, stackPeriodRead,
stackPeriodUpdate, stackPeriodUpdate,
stackPeriodDelete, stackPeriodDelete,
syncPeriodStream,
syncCheckpointPeriodRead,
syncCheckpointPeriodUpdate,
syncCheckpointPeriodDelete,
systemConfigPeriodRead, systemConfigPeriodRead,
systemConfigPeriodUpdate, systemConfigPeriodUpdate,
systemMetadataPeriodRead, systemMetadataPeriodRead,
@ -190,10 +259,25 @@ class Permission {
tagPeriodUpdate, tagPeriodUpdate,
tagPeriodDelete, tagPeriodDelete,
tagPeriodAsset, tagPeriodAsset,
adminPeriodUserPeriodCreate, userPeriodRead,
adminPeriodUserPeriodRead, userPeriodUpdate,
adminPeriodUserPeriodUpdate, userLicensePeriodCreate,
adminPeriodUserPeriodDelete, userLicensePeriodRead,
userLicensePeriodUpdate,
userLicensePeriodDelete,
userOnboardingPeriodRead,
userOnboardingPeriodUpdate,
userOnboardingPeriodDelete,
userPreferencePeriodRead,
userPreferencePeriodUpdate,
userProfileImagePeriodCreate,
userProfileImagePeriodRead,
userProfileImagePeriodUpdate,
userProfileImagePeriodDelete,
adminUserPeriodCreate,
adminUserPeriodRead,
adminUserPeriodUpdate,
adminUserPeriodDelete,
]; ];
static Permission? fromJson(dynamic value) => PermissionTypeTransformer().decode(value); static Permission? fromJson(dynamic value) => PermissionTypeTransformer().decode(value);
@ -245,25 +329,35 @@ class PermissionTypeTransformer {
case r'asset.read': return Permission.assetPeriodRead; case r'asset.read': return Permission.assetPeriodRead;
case r'asset.update': return Permission.assetPeriodUpdate; case r'asset.update': return Permission.assetPeriodUpdate;
case r'asset.delete': return Permission.assetPeriodDelete; case r'asset.delete': return Permission.assetPeriodDelete;
case r'asset.statistics': return Permission.assetPeriodStatistics;
case r'asset.share': return Permission.assetPeriodShare; case r'asset.share': return Permission.assetPeriodShare;
case r'asset.view': return Permission.assetPeriodView; case r'asset.view': return Permission.assetPeriodView;
case r'asset.download': return Permission.assetPeriodDownload; case r'asset.download': return Permission.assetPeriodDownload;
case r'asset.upload': return Permission.assetPeriodUpload; case r'asset.upload': return Permission.assetPeriodUpload;
case r'asset.replace': return Permission.assetPeriodReplace;
case r'album.create': return Permission.albumPeriodCreate; case r'album.create': return Permission.albumPeriodCreate;
case r'album.read': return Permission.albumPeriodRead; case r'album.read': return Permission.albumPeriodRead;
case r'album.update': return Permission.albumPeriodUpdate; case r'album.update': return Permission.albumPeriodUpdate;
case r'album.delete': return Permission.albumPeriodDelete; case r'album.delete': return Permission.albumPeriodDelete;
case r'album.statistics': return Permission.albumPeriodStatistics; case r'album.statistics': return Permission.albumPeriodStatistics;
case r'album.addAsset': return Permission.albumPeriodAddAsset;
case r'album.removeAsset': return Permission.albumPeriodRemoveAsset;
case r'album.share': return Permission.albumPeriodShare; case r'album.share': return Permission.albumPeriodShare;
case r'album.download': return Permission.albumPeriodDownload; case r'album.download': return Permission.albumPeriodDownload;
case r'albumAsset.create': return Permission.albumAssetPeriodCreate;
case r'albumAsset.delete': return Permission.albumAssetPeriodDelete;
case r'albumUser.create': return Permission.albumUserPeriodCreate;
case r'albumUser.update': return Permission.albumUserPeriodUpdate;
case r'albumUser.delete': return Permission.albumUserPeriodDelete;
case r'auth.changePassword': return Permission.authPeriodChangePassword;
case r'authDevice.delete': return Permission.authDevicePeriodDelete; case r'authDevice.delete': return Permission.authDevicePeriodDelete;
case r'archive.read': return Permission.archivePeriodRead; case r'archive.read': return Permission.archivePeriodRead;
case r'duplicate.read': return Permission.duplicatePeriodRead;
case r'duplicate.delete': return Permission.duplicatePeriodDelete;
case r'face.create': return Permission.facePeriodCreate; case r'face.create': return Permission.facePeriodCreate;
case r'face.read': return Permission.facePeriodRead; case r'face.read': return Permission.facePeriodRead;
case r'face.update': return Permission.facePeriodUpdate; case r'face.update': return Permission.facePeriodUpdate;
case r'face.delete': return Permission.facePeriodDelete; case r'face.delete': return Permission.facePeriodDelete;
case r'job.create': return Permission.jobPeriodCreate;
case r'job.read': return Permission.jobPeriodRead;
case r'library.create': return Permission.libraryPeriodCreate; case r'library.create': return Permission.libraryPeriodCreate;
case r'library.read': return Permission.libraryPeriodRead; case r'library.read': return Permission.libraryPeriodRead;
case r'library.update': return Permission.libraryPeriodUpdate; case r'library.update': return Permission.libraryPeriodUpdate;
@ -275,6 +369,9 @@ class PermissionTypeTransformer {
case r'memory.read': return Permission.memoryPeriodRead; case r'memory.read': return Permission.memoryPeriodRead;
case r'memory.update': return Permission.memoryPeriodUpdate; case r'memory.update': return Permission.memoryPeriodUpdate;
case r'memory.delete': return Permission.memoryPeriodDelete; case r'memory.delete': return Permission.memoryPeriodDelete;
case r'memory.statistics': return Permission.memoryPeriodStatistics;
case r'memoryAsset.create': return Permission.memoryAssetPeriodCreate;
case r'memoryAsset.delete': return Permission.memoryAssetPeriodDelete;
case r'notification.create': return Permission.notificationPeriodCreate; case r'notification.create': return Permission.notificationPeriodCreate;
case r'notification.read': return Permission.notificationPeriodRead; case r'notification.read': return Permission.notificationPeriodRead;
case r'notification.update': return Permission.notificationPeriodUpdate; case r'notification.update': return Permission.notificationPeriodUpdate;
@ -290,6 +387,16 @@ class PermissionTypeTransformer {
case r'person.statistics': return Permission.personPeriodStatistics; case r'person.statistics': return Permission.personPeriodStatistics;
case r'person.merge': return Permission.personPeriodMerge; case r'person.merge': return Permission.personPeriodMerge;
case r'person.reassign': return Permission.personPeriodReassign; case r'person.reassign': return Permission.personPeriodReassign;
case r'pinCode.create': return Permission.pinCodePeriodCreate;
case r'pinCode.update': return Permission.pinCodePeriodUpdate;
case r'pinCode.delete': return Permission.pinCodePeriodDelete;
case r'server.about': return Permission.serverPeriodAbout;
case r'server.apkLinks': return Permission.serverPeriodApkLinks;
case r'server.storage': return Permission.serverPeriodStorage;
case r'server.statistics': return Permission.serverPeriodStatistics;
case r'serverLicense.read': return Permission.serverLicensePeriodRead;
case r'serverLicense.update': return Permission.serverLicensePeriodUpdate;
case r'serverLicense.delete': return Permission.serverLicensePeriodDelete;
case r'session.create': return Permission.sessionPeriodCreate; case r'session.create': return Permission.sessionPeriodCreate;
case r'session.read': return Permission.sessionPeriodRead; case r'session.read': return Permission.sessionPeriodRead;
case r'session.update': return Permission.sessionPeriodUpdate; case r'session.update': return Permission.sessionPeriodUpdate;
@ -303,6 +410,10 @@ class PermissionTypeTransformer {
case r'stack.read': return Permission.stackPeriodRead; case r'stack.read': return Permission.stackPeriodRead;
case r'stack.update': return Permission.stackPeriodUpdate; case r'stack.update': return Permission.stackPeriodUpdate;
case r'stack.delete': return Permission.stackPeriodDelete; case r'stack.delete': return Permission.stackPeriodDelete;
case r'sync.stream': return Permission.syncPeriodStream;
case r'syncCheckpoint.read': return Permission.syncCheckpointPeriodRead;
case r'syncCheckpoint.update': return Permission.syncCheckpointPeriodUpdate;
case r'syncCheckpoint.delete': return Permission.syncCheckpointPeriodDelete;
case r'systemConfig.read': return Permission.systemConfigPeriodRead; case r'systemConfig.read': return Permission.systemConfigPeriodRead;
case r'systemConfig.update': return Permission.systemConfigPeriodUpdate; case r'systemConfig.update': return Permission.systemConfigPeriodUpdate;
case r'systemMetadata.read': return Permission.systemMetadataPeriodRead; case r'systemMetadata.read': return Permission.systemMetadataPeriodRead;
@ -312,10 +423,25 @@ class PermissionTypeTransformer {
case r'tag.update': return Permission.tagPeriodUpdate; case r'tag.update': return Permission.tagPeriodUpdate;
case r'tag.delete': return Permission.tagPeriodDelete; case r'tag.delete': return Permission.tagPeriodDelete;
case r'tag.asset': return Permission.tagPeriodAsset; case r'tag.asset': return Permission.tagPeriodAsset;
case r'admin.user.create': return Permission.adminPeriodUserPeriodCreate; case r'user.read': return Permission.userPeriodRead;
case r'admin.user.read': return Permission.adminPeriodUserPeriodRead; case r'user.update': return Permission.userPeriodUpdate;
case r'admin.user.update': return Permission.adminPeriodUserPeriodUpdate; case r'userLicense.create': return Permission.userLicensePeriodCreate;
case r'admin.user.delete': return Permission.adminPeriodUserPeriodDelete; case r'userLicense.read': return Permission.userLicensePeriodRead;
case r'userLicense.update': return Permission.userLicensePeriodUpdate;
case r'userLicense.delete': return Permission.userLicensePeriodDelete;
case r'userOnboarding.read': return Permission.userOnboardingPeriodRead;
case r'userOnboarding.update': return Permission.userOnboardingPeriodUpdate;
case r'userOnboarding.delete': return Permission.userOnboardingPeriodDelete;
case r'userPreference.read': return Permission.userPreferencePeriodRead;
case r'userPreference.update': return Permission.userPreferencePeriodUpdate;
case r'userProfileImage.create': return Permission.userProfileImagePeriodCreate;
case r'userProfileImage.read': return Permission.userProfileImagePeriodRead;
case r'userProfileImage.update': return Permission.userProfileImagePeriodUpdate;
case r'userProfileImage.delete': return Permission.userProfileImagePeriodDelete;
case r'adminUser.create': return Permission.adminUserPeriodCreate;
case r'adminUser.read': return Permission.adminUserPeriodRead;
case r'adminUser.update': return Permission.adminUserPeriodUpdate;
case r'adminUser.delete': return Permission.adminUserPeriodDelete;
default: default:
if (!allowNull) { if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data'); throw ArgumentError('Unknown enum value to decode: $data');

View File

@ -11760,25 +11760,35 @@
"asset.read", "asset.read",
"asset.update", "asset.update",
"asset.delete", "asset.delete",
"asset.statistics",
"asset.share", "asset.share",
"asset.view", "asset.view",
"asset.download", "asset.download",
"asset.upload", "asset.upload",
"asset.replace",
"album.create", "album.create",
"album.read", "album.read",
"album.update", "album.update",
"album.delete", "album.delete",
"album.statistics", "album.statistics",
"album.addAsset",
"album.removeAsset",
"album.share", "album.share",
"album.download", "album.download",
"albumAsset.create",
"albumAsset.delete",
"albumUser.create",
"albumUser.update",
"albumUser.delete",
"auth.changePassword",
"authDevice.delete", "authDevice.delete",
"archive.read", "archive.read",
"duplicate.read",
"duplicate.delete",
"face.create", "face.create",
"face.read", "face.read",
"face.update", "face.update",
"face.delete", "face.delete",
"job.create",
"job.read",
"library.create", "library.create",
"library.read", "library.read",
"library.update", "library.update",
@ -11790,6 +11800,9 @@
"memory.read", "memory.read",
"memory.update", "memory.update",
"memory.delete", "memory.delete",
"memory.statistics",
"memoryAsset.create",
"memoryAsset.delete",
"notification.create", "notification.create",
"notification.read", "notification.read",
"notification.update", "notification.update",
@ -11805,6 +11818,16 @@
"person.statistics", "person.statistics",
"person.merge", "person.merge",
"person.reassign", "person.reassign",
"pinCode.create",
"pinCode.update",
"pinCode.delete",
"server.about",
"server.apkLinks",
"server.storage",
"server.statistics",
"serverLicense.read",
"serverLicense.update",
"serverLicense.delete",
"session.create", "session.create",
"session.read", "session.read",
"session.update", "session.update",
@ -11818,6 +11841,10 @@
"stack.read", "stack.read",
"stack.update", "stack.update",
"stack.delete", "stack.delete",
"sync.stream",
"syncCheckpoint.read",
"syncCheckpoint.update",
"syncCheckpoint.delete",
"systemConfig.read", "systemConfig.read",
"systemConfig.update", "systemConfig.update",
"systemMetadata.read", "systemMetadata.read",
@ -11827,10 +11854,25 @@
"tag.update", "tag.update",
"tag.delete", "tag.delete",
"tag.asset", "tag.asset",
"admin.user.create", "user.read",
"admin.user.read", "user.update",
"admin.user.update", "userLicense.create",
"admin.user.delete" "userLicense.read",
"userLicense.update",
"userLicense.delete",
"userOnboarding.read",
"userOnboarding.update",
"userOnboarding.delete",
"userPreference.read",
"userPreference.update",
"userProfileImage.create",
"userProfileImage.read",
"userProfileImage.update",
"userProfileImage.delete",
"adminUser.create",
"adminUser.read",
"adminUser.update",
"adminUser.delete"
], ],
"type": "string" "type": "string"
}, },

View File

@ -3947,25 +3947,35 @@ export enum Permission {
AssetRead = "asset.read", AssetRead = "asset.read",
AssetUpdate = "asset.update", AssetUpdate = "asset.update",
AssetDelete = "asset.delete", AssetDelete = "asset.delete",
AssetStatistics = "asset.statistics",
AssetShare = "asset.share", AssetShare = "asset.share",
AssetView = "asset.view", AssetView = "asset.view",
AssetDownload = "asset.download", AssetDownload = "asset.download",
AssetUpload = "asset.upload", AssetUpload = "asset.upload",
AssetReplace = "asset.replace",
AlbumCreate = "album.create", AlbumCreate = "album.create",
AlbumRead = "album.read", AlbumRead = "album.read",
AlbumUpdate = "album.update", AlbumUpdate = "album.update",
AlbumDelete = "album.delete", AlbumDelete = "album.delete",
AlbumStatistics = "album.statistics", AlbumStatistics = "album.statistics",
AlbumAddAsset = "album.addAsset",
AlbumRemoveAsset = "album.removeAsset",
AlbumShare = "album.share", AlbumShare = "album.share",
AlbumDownload = "album.download", AlbumDownload = "album.download",
AlbumAssetCreate = "albumAsset.create",
AlbumAssetDelete = "albumAsset.delete",
AlbumUserCreate = "albumUser.create",
AlbumUserUpdate = "albumUser.update",
AlbumUserDelete = "albumUser.delete",
AuthChangePassword = "auth.changePassword",
AuthDeviceDelete = "authDevice.delete", AuthDeviceDelete = "authDevice.delete",
ArchiveRead = "archive.read", ArchiveRead = "archive.read",
DuplicateRead = "duplicate.read",
DuplicateDelete = "duplicate.delete",
FaceCreate = "face.create", FaceCreate = "face.create",
FaceRead = "face.read", FaceRead = "face.read",
FaceUpdate = "face.update", FaceUpdate = "face.update",
FaceDelete = "face.delete", FaceDelete = "face.delete",
JobCreate = "job.create",
JobRead = "job.read",
LibraryCreate = "library.create", LibraryCreate = "library.create",
LibraryRead = "library.read", LibraryRead = "library.read",
LibraryUpdate = "library.update", LibraryUpdate = "library.update",
@ -3977,6 +3987,9 @@ export enum Permission {
MemoryRead = "memory.read", MemoryRead = "memory.read",
MemoryUpdate = "memory.update", MemoryUpdate = "memory.update",
MemoryDelete = "memory.delete", MemoryDelete = "memory.delete",
MemoryStatistics = "memory.statistics",
MemoryAssetCreate = "memoryAsset.create",
MemoryAssetDelete = "memoryAsset.delete",
NotificationCreate = "notification.create", NotificationCreate = "notification.create",
NotificationRead = "notification.read", NotificationRead = "notification.read",
NotificationUpdate = "notification.update", NotificationUpdate = "notification.update",
@ -3992,6 +4005,16 @@ export enum Permission {
PersonStatistics = "person.statistics", PersonStatistics = "person.statistics",
PersonMerge = "person.merge", PersonMerge = "person.merge",
PersonReassign = "person.reassign", PersonReassign = "person.reassign",
PinCodeCreate = "pinCode.create",
PinCodeUpdate = "pinCode.update",
PinCodeDelete = "pinCode.delete",
ServerAbout = "server.about",
ServerApkLinks = "server.apkLinks",
ServerStorage = "server.storage",
ServerStatistics = "server.statistics",
ServerLicenseRead = "serverLicense.read",
ServerLicenseUpdate = "serverLicense.update",
ServerLicenseDelete = "serverLicense.delete",
SessionCreate = "session.create", SessionCreate = "session.create",
SessionRead = "session.read", SessionRead = "session.read",
SessionUpdate = "session.update", SessionUpdate = "session.update",
@ -4005,6 +4028,10 @@ export enum Permission {
StackRead = "stack.read", StackRead = "stack.read",
StackUpdate = "stack.update", StackUpdate = "stack.update",
StackDelete = "stack.delete", StackDelete = "stack.delete",
SyncStream = "sync.stream",
SyncCheckpointRead = "syncCheckpoint.read",
SyncCheckpointUpdate = "syncCheckpoint.update",
SyncCheckpointDelete = "syncCheckpoint.delete",
SystemConfigRead = "systemConfig.read", SystemConfigRead = "systemConfig.read",
SystemConfigUpdate = "systemConfig.update", SystemConfigUpdate = "systemConfig.update",
SystemMetadataRead = "systemMetadata.read", SystemMetadataRead = "systemMetadata.read",
@ -4014,10 +4041,25 @@ export enum Permission {
TagUpdate = "tag.update", TagUpdate = "tag.update",
TagDelete = "tag.delete", TagDelete = "tag.delete",
TagAsset = "tag.asset", TagAsset = "tag.asset",
AdminUserCreate = "admin.user.create", UserRead = "user.read",
AdminUserRead = "admin.user.read", UserUpdate = "user.update",
AdminUserUpdate = "admin.user.update", UserLicenseCreate = "userLicense.create",
AdminUserDelete = "admin.user.delete" UserLicenseRead = "userLicense.read",
UserLicenseUpdate = "userLicense.update",
UserLicenseDelete = "userLicense.delete",
UserOnboardingRead = "userOnboarding.read",
UserOnboardingUpdate = "userOnboarding.update",
UserOnboardingDelete = "userOnboarding.delete",
UserPreferenceRead = "userPreference.read",
UserPreferenceUpdate = "userPreference.update",
UserProfileImageCreate = "userProfileImage.create",
UserProfileImageRead = "userProfileImage.read",
UserProfileImageUpdate = "userProfileImage.update",
UserProfileImageDelete = "userProfileImage.delete",
AdminUserCreate = "adminUser.create",
AdminUserRead = "adminUser.read",
AdminUserUpdate = "adminUser.update",
AdminUserDelete = "adminUser.delete"
} }
export enum AssetMediaStatus { export enum AssetMediaStatus {
Created = "created", Created = "created",

View File

@ -67,7 +67,7 @@ export class AlbumController {
} }
@Put(':id/assets') @Put(':id/assets')
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AlbumAssetCreate, sharedLink: true })
addAssetsToAlbum( addAssetsToAlbum(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -77,7 +77,7 @@ export class AlbumController {
} }
@Delete(':id/assets') @Delete(':id/assets')
@Authenticated() @Authenticated({ permission: Permission.AlbumAssetDelete })
removeAssetFromAlbum( removeAssetFromAlbum(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Body() dto: BulkIdsDto, @Body() dto: BulkIdsDto,
@ -87,7 +87,7 @@ export class AlbumController {
} }
@Put(':id/users') @Put(':id/users')
@Authenticated() @Authenticated({ permission: Permission.AlbumUserCreate })
addUsersToAlbum( addUsersToAlbum(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -97,7 +97,7 @@ export class AlbumController {
} }
@Put(':id/user/:userId') @Put(':id/user/:userId')
@Authenticated() @Authenticated({ permission: Permission.AlbumUserUpdate })
updateAlbumUser( updateAlbumUser(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -108,7 +108,7 @@ export class AlbumController {
} }
@Delete(':id/user/:userId') @Delete(':id/user/:userId')
@Authenticated() @Authenticated({ permission: Permission.AlbumUserDelete })
removeUserFromAlbum( removeUserFromAlbum(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,

View File

@ -34,7 +34,7 @@ import {
UploadFieldName, UploadFieldName,
} from 'src/dtos/asset-media.dto'; } from 'src/dtos/asset-media.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { ImmichHeader, RouteKey } from 'src/enum'; import { ImmichHeader, Permission, RouteKey } from 'src/enum';
import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor'; import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
import { FileUploadInterceptor, getFiles } from 'src/middleware/file-upload.interceptor'; import { FileUploadInterceptor, getFiles } from 'src/middleware/file-upload.interceptor';
@ -61,7 +61,7 @@ export class AssetMediaController {
required: false, required: false,
}) })
@ApiBody({ description: 'Asset Upload Information', type: AssetMediaCreateDto }) @ApiBody({ description: 'Asset Upload Information', type: AssetMediaCreateDto })
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetUpload, sharedLink: true })
async uploadAsset( async uploadAsset(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@UploadedFiles(new ParseFilePipe({ validators: [new FileNotEmptyValidator(['assetData'])] })) files: UploadFiles, @UploadedFiles(new ParseFilePipe({ validators: [new FileNotEmptyValidator(['assetData'])] })) files: UploadFiles,
@ -80,7 +80,7 @@ export class AssetMediaController {
@Get(':id/original') @Get(':id/original')
@FileResponse() @FileResponse()
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetDownload, sharedLink: true })
async downloadAsset( async downloadAsset(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -101,7 +101,7 @@ export class AssetMediaController {
summary: 'replaceAsset', summary: 'replaceAsset',
description: 'Replace the asset with new file, without changing its id', description: 'Replace the asset with new file, without changing its id',
}) })
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetReplace, sharedLink: true })
async replaceAsset( async replaceAsset(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -120,7 +120,7 @@ export class AssetMediaController {
@Get(':id/thumbnail') @Get(':id/thumbnail')
@FileResponse() @FileResponse()
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetView, sharedLink: true })
async viewAsset( async viewAsset(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -157,7 +157,7 @@ export class AssetMediaController {
@Get(':id/video/playback') @Get(':id/video/playback')
@FileResponse() @FileResponse()
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetView, sharedLink: true })
async playAssetVideo( async playAssetVideo(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,

View File

@ -13,7 +13,7 @@ import {
UpdateAssetDto, UpdateAssetDto,
} from 'src/dtos/asset.dto'; } from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { RouteKey } from 'src/enum'; import { Permission, RouteKey } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { AssetService } from 'src/services/asset.service'; import { AssetService } from 'src/services/asset.service';
import { UUIDParamDto } from 'src/validation'; import { UUIDParamDto } from 'src/validation';
@ -24,7 +24,7 @@ export class AssetController {
constructor(private service: AssetService) {} constructor(private service: AssetService) {}
@Get('random') @Get('random')
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
@EndpointLifecycle({ deprecatedAt: 'v1.116.0' }) @EndpointLifecycle({ deprecatedAt: 'v1.116.0' })
getRandom(@Auth() auth: AuthDto, @Query() dto: RandomAssetsDto): Promise<AssetResponseDto[]> { getRandom(@Auth() auth: AuthDto, @Query() dto: RandomAssetsDto): Promise<AssetResponseDto[]> {
return this.service.getRandom(auth, dto.count ?? 1); return this.service.getRandom(auth, dto.count ?? 1);
@ -44,7 +44,7 @@ export class AssetController {
} }
@Get('statistics') @Get('statistics')
@Authenticated() @Authenticated({ permission: Permission.AssetStatistics })
getAssetStatistics(@Auth() auth: AuthDto, @Query() dto: AssetStatsDto): Promise<AssetStatsResponseDto> { getAssetStatistics(@Auth() auth: AuthDto, @Query() dto: AssetStatsDto): Promise<AssetStatsResponseDto> {
return this.service.getStatistics(auth, dto); return this.service.getStatistics(auth, dto);
} }
@ -58,26 +58,26 @@ export class AssetController {
@Put() @Put()
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@Authenticated() @Authenticated({ permission: Permission.AssetUpdate })
updateAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkUpdateDto): Promise<void> { updateAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkUpdateDto): Promise<void> {
return this.service.updateAll(auth, dto); return this.service.updateAll(auth, dto);
} }
@Delete() @Delete()
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@Authenticated() @Authenticated({ permission: Permission.AssetDelete })
deleteAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkDeleteDto): Promise<void> { deleteAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkDeleteDto): Promise<void> {
return this.service.deleteAll(auth, dto); return this.service.deleteAll(auth, dto);
} }
@Get(':id') @Get(':id')
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetRead, sharedLink: true })
getAssetInfo(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto> { getAssetInfo(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto> {
return this.service.get(auth, id) as Promise<AssetResponseDto>; return this.service.get(auth, id) as Promise<AssetResponseDto>;
} }
@Put(':id') @Put(':id')
@Authenticated() @Authenticated({ permission: Permission.AssetUpdate })
updateAsset( updateAsset(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,

View File

@ -16,7 +16,7 @@ import {
ValidateAccessTokenResponseDto, ValidateAccessTokenResponseDto,
} from 'src/dtos/auth.dto'; } from 'src/dtos/auth.dto';
import { UserAdminResponseDto } from 'src/dtos/user.dto'; import { UserAdminResponseDto } from 'src/dtos/user.dto';
import { AuthType, ImmichCookie } from 'src/enum'; import { AuthType, ImmichCookie, Permission } from 'src/enum';
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard'; import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
import { AuthService, LoginDetails } from 'src/services/auth.service'; import { AuthService, LoginDetails } from 'src/services/auth.service';
import { respondWithCookie, respondWithoutCookie } from 'src/utils/response'; import { respondWithCookie, respondWithoutCookie } from 'src/utils/response';
@ -57,7 +57,7 @@ export class AuthController {
@Post('change-password') @Post('change-password')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.AuthChangePassword })
changePassword(@Auth() auth: AuthDto, @Body() dto: ChangePasswordDto): Promise<UserAdminResponseDto> { changePassword(@Auth() auth: AuthDto, @Body() dto: ChangePasswordDto): Promise<UserAdminResponseDto> {
return this.service.changePassword(auth, dto); return this.service.changePassword(auth, dto);
} }
@ -87,19 +87,19 @@ export class AuthController {
} }
@Post('pin-code') @Post('pin-code')
@Authenticated() @Authenticated({ permission: Permission.PinCodeCreate })
setupPinCode(@Auth() auth: AuthDto, @Body() dto: PinCodeSetupDto): Promise<void> { setupPinCode(@Auth() auth: AuthDto, @Body() dto: PinCodeSetupDto): Promise<void> {
return this.service.setupPinCode(auth, dto); return this.service.setupPinCode(auth, dto);
} }
@Put('pin-code') @Put('pin-code')
@Authenticated() @Authenticated({ permission: Permission.PinCodeUpdate })
async changePinCode(@Auth() auth: AuthDto, @Body() dto: PinCodeChangeDto): Promise<void> { async changePinCode(@Auth() auth: AuthDto, @Body() dto: PinCodeChangeDto): Promise<void> {
return this.service.changePinCode(auth, dto); return this.service.changePinCode(auth, dto);
} }
@Delete('pin-code') @Delete('pin-code')
@Authenticated() @Authenticated({ permission: Permission.PinCodeDelete })
async resetPinCode(@Auth() auth: AuthDto, @Body() dto: PinCodeResetDto): Promise<void> { async resetPinCode(@Auth() auth: AuthDto, @Body() dto: PinCodeResetDto): Promise<void> {
return this.service.resetPinCode(auth, dto); return this.service.resetPinCode(auth, dto);
} }

View File

@ -3,6 +3,7 @@ import { ApiTags } from '@nestjs/swagger';
import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AssetIdsDto } from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto';
import { Permission } from 'src/enum';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
import { DownloadService } from 'src/services/download.service'; import { DownloadService } from 'src/services/download.service';
import { asStreamableFile } from 'src/utils/file'; import { asStreamableFile } from 'src/utils/file';
@ -13,7 +14,7 @@ export class DownloadController {
constructor(private service: DownloadService) {} constructor(private service: DownloadService) {}
@Post('info') @Post('info')
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetDownload, sharedLink: true })
getDownloadInfo(@Auth() auth: AuthDto, @Body() dto: DownloadInfoDto): Promise<DownloadResponseDto> { getDownloadInfo(@Auth() auth: AuthDto, @Body() dto: DownloadInfoDto): Promise<DownloadResponseDto> {
return this.service.getDownloadInfo(auth, dto); return this.service.getDownloadInfo(auth, dto);
} }
@ -21,7 +22,7 @@ export class DownloadController {
@Post('archive') @Post('archive')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@FileResponse() @FileResponse()
@Authenticated({ sharedLink: true }) @Authenticated({ permission: Permission.AssetDownload, sharedLink: true })
downloadArchive(@Auth() auth: AuthDto, @Body() dto: AssetIdsDto): Promise<StreamableFile> { downloadArchive(@Auth() auth: AuthDto, @Body() dto: AssetIdsDto): Promise<StreamableFile> {
return this.service.downloadArchive(auth, dto).then(asStreamableFile); return this.service.downloadArchive(auth, dto).then(asStreamableFile);
} }

View File

@ -3,6 +3,7 @@ import { ApiTags } from '@nestjs/swagger';
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { DuplicateResponseDto } from 'src/dtos/duplicate.dto'; import { DuplicateResponseDto } from 'src/dtos/duplicate.dto';
import { Permission } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { DuplicateService } from 'src/services/duplicate.service'; import { DuplicateService } from 'src/services/duplicate.service';
import { UUIDParamDto } from 'src/validation'; import { UUIDParamDto } from 'src/validation';
@ -13,19 +14,19 @@ export class DuplicateController {
constructor(private service: DuplicateService) {} constructor(private service: DuplicateService) {}
@Get() @Get()
@Authenticated() @Authenticated({ permission: Permission.DuplicateRead })
getAssetDuplicates(@Auth() auth: AuthDto): Promise<DuplicateResponseDto[]> { getAssetDuplicates(@Auth() auth: AuthDto): Promise<DuplicateResponseDto[]> {
return this.service.getDuplicates(auth); return this.service.getDuplicates(auth);
} }
@Delete() @Delete()
@Authenticated() @Authenticated({ permission: Permission.DuplicateDelete })
deleteDuplicates(@Auth() auth: AuthDto, @Body() dto: BulkIdsDto): Promise<void> { deleteDuplicates(@Auth() auth: AuthDto, @Body() dto: BulkIdsDto): Promise<void> {
return this.service.deleteAll(auth, dto); return this.service.deleteAll(auth, dto);
} }
@Delete(':id') @Delete(':id')
@Authenticated() @Authenticated({ permission: Permission.DuplicateDelete })
deleteDuplicate(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> { deleteDuplicate(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
return this.service.delete(auth, id); return this.service.delete(auth, id);
} }

View File

@ -1,6 +1,7 @@
import { Body, Controller, Get, Param, Post, Put } from '@nestjs/common'; import { Body, Controller, Get, Param, Post, Put } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto'; import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto';
import { Permission } from 'src/enum';
import { Authenticated } from 'src/middleware/auth.guard'; import { Authenticated } from 'src/middleware/auth.guard';
import { JobService } from 'src/services/job.service'; import { JobService } from 'src/services/job.service';
@ -10,19 +11,19 @@ export class JobController {
constructor(private service: JobService) {} constructor(private service: JobService) {}
@Get() @Get()
@Authenticated({ admin: true }) @Authenticated({ permission: Permission.JobRead, admin: true })
getAllJobsStatus(): Promise<AllJobStatusResponseDto> { getAllJobsStatus(): Promise<AllJobStatusResponseDto> {
return this.service.getAllJobsStatus(); return this.service.getAllJobsStatus();
} }
@Post() @Post()
@Authenticated({ admin: true }) @Authenticated({ permission: Permission.JobCreate, admin: true })
createJob(@Body() dto: JobCreateDto): Promise<void> { createJob(@Body() dto: JobCreateDto): Promise<void> {
return this.service.create(dto); return this.service.create(dto);
} }
@Put(':id') @Put(':id')
@Authenticated({ admin: true }) @Authenticated({ permission: Permission.JobCreate, admin: true })
sendJobCommand(@Param() { id }: JobIdParamDto, @Body() dto: JobCommandDto): Promise<JobStatusDto> { sendJobCommand(@Param() { id }: JobIdParamDto, @Body() dto: JobCommandDto): Promise<JobStatusDto> {
return this.service.handleCommand(id, dto); return this.service.handleCommand(id, dto);
} }

View File

@ -32,7 +32,7 @@ export class MemoryController {
} }
@Get('statistics') @Get('statistics')
@Authenticated({ permission: Permission.MemoryRead }) @Authenticated({ permission: Permission.MemoryStatistics })
memoriesStatistics(@Auth() auth: AuthDto, @Query() dto: MemorySearchDto): Promise<MemoryStatisticsResponseDto> { memoriesStatistics(@Auth() auth: AuthDto, @Query() dto: MemorySearchDto): Promise<MemoryStatisticsResponseDto> {
return this.service.statistics(auth, dto); return this.service.statistics(auth, dto);
} }
@ -61,7 +61,7 @@ export class MemoryController {
} }
@Put(':id/assets') @Put(':id/assets')
@Authenticated() @Authenticated({ permission: Permission.MemoryAssetCreate })
addMemoryAssets( addMemoryAssets(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto, @Param() { id }: UUIDParamDto,
@ -72,7 +72,7 @@ export class MemoryController {
@Delete(':id/assets') @Delete(':id/assets')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.MemoryAssetDelete })
removeMemoryAssets( removeMemoryAssets(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Body() dto: BulkIdsDto, @Body() dto: BulkIdsDto,

View File

@ -16,6 +16,7 @@ import {
SmartSearchDto, SmartSearchDto,
StatisticsSearchDto, StatisticsSearchDto,
} from 'src/dtos/search.dto'; } from 'src/dtos/search.dto';
import { Permission } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { SearchService } from 'src/services/search.service'; import { SearchService } from 'src/services/search.service';
@ -26,58 +27,58 @@ export class SearchController {
@Post('metadata') @Post('metadata')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
searchAssets(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise<SearchResponseDto> { searchAssets(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise<SearchResponseDto> {
return this.service.searchMetadata(auth, dto); return this.service.searchMetadata(auth, dto);
} }
@Post('statistics') @Post('statistics')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.AssetStatistics })
searchAssetStatistics(@Auth() auth: AuthDto, @Body() dto: StatisticsSearchDto): Promise<SearchStatisticsResponseDto> { searchAssetStatistics(@Auth() auth: AuthDto, @Body() dto: StatisticsSearchDto): Promise<SearchStatisticsResponseDto> {
return this.service.searchStatistics(auth, dto); return this.service.searchStatistics(auth, dto);
} }
@Post('random') @Post('random')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
searchRandom(@Auth() auth: AuthDto, @Body() dto: RandomSearchDto): Promise<AssetResponseDto[]> { searchRandom(@Auth() auth: AuthDto, @Body() dto: RandomSearchDto): Promise<AssetResponseDto[]> {
return this.service.searchRandom(auth, dto); return this.service.searchRandom(auth, dto);
} }
@Post('smart') @Post('smart')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
searchSmart(@Auth() auth: AuthDto, @Body() dto: SmartSearchDto): Promise<SearchResponseDto> { searchSmart(@Auth() auth: AuthDto, @Body() dto: SmartSearchDto): Promise<SearchResponseDto> {
return this.service.searchSmart(auth, dto); return this.service.searchSmart(auth, dto);
} }
@Get('explore') @Get('explore')
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
getExploreData(@Auth() auth: AuthDto): Promise<SearchExploreResponseDto[]> { getExploreData(@Auth() auth: AuthDto): Promise<SearchExploreResponseDto[]> {
return this.service.getExploreData(auth); return this.service.getExploreData(auth);
} }
@Get('person') @Get('person')
@Authenticated() @Authenticated({ permission: Permission.PersonRead })
searchPerson(@Auth() auth: AuthDto, @Query() dto: SearchPeopleDto): Promise<PersonResponseDto[]> { searchPerson(@Auth() auth: AuthDto, @Query() dto: SearchPeopleDto): Promise<PersonResponseDto[]> {
return this.service.searchPerson(auth, dto); return this.service.searchPerson(auth, dto);
} }
@Get('places') @Get('places')
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
searchPlaces(@Query() dto: SearchPlacesDto): Promise<PlacesResponseDto[]> { searchPlaces(@Query() dto: SearchPlacesDto): Promise<PlacesResponseDto[]> {
return this.service.searchPlaces(dto); return this.service.searchPlaces(dto);
} }
@Get('cities') @Get('cities')
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
getAssetsByCity(@Auth() auth: AuthDto): Promise<AssetResponseDto[]> { getAssetsByCity(@Auth() auth: AuthDto): Promise<AssetResponseDto[]> {
return this.service.getAssetsByCity(auth); return this.service.getAssetsByCity(auth);
} }
@Get('suggestions') @Get('suggestions')
@Authenticated() @Authenticated({ permission: Permission.AssetRead })
getSearchSuggestions(@Auth() auth: AuthDto, @Query() dto: SearchSuggestionRequestDto): Promise<string[]> { getSearchSuggestions(@Auth() auth: AuthDto, @Query() dto: SearchSuggestionRequestDto): Promise<string[]> {
// TODO fix open api generation to indicate that results can be nullable // TODO fix open api generation to indicate that results can be nullable
return this.service.getSearchSuggestions(auth, dto) as Promise<string[]>; return this.service.getSearchSuggestions(auth, dto) as Promise<string[]>;

View File

@ -15,6 +15,7 @@ import {
ServerVersionResponseDto, ServerVersionResponseDto,
} from 'src/dtos/server.dto'; } from 'src/dtos/server.dto';
import { VersionCheckStateResponseDto } from 'src/dtos/system-metadata.dto'; import { VersionCheckStateResponseDto } from 'src/dtos/system-metadata.dto';
import { Permission } from 'src/enum';
import { Authenticated } from 'src/middleware/auth.guard'; import { Authenticated } from 'src/middleware/auth.guard';
import { ServerService } from 'src/services/server.service'; import { ServerService } from 'src/services/server.service';
import { SystemMetadataService } from 'src/services/system-metadata.service'; import { SystemMetadataService } from 'src/services/system-metadata.service';
@ -30,19 +31,19 @@ export class ServerController {
) {} ) {}
@Get('about') @Get('about')
@Authenticated() @Authenticated({ permission: Permission.ServerAbout })
getAboutInfo(): Promise<ServerAboutResponseDto> { getAboutInfo(): Promise<ServerAboutResponseDto> {
return this.service.getAboutInfo(); return this.service.getAboutInfo();
} }
@Get('apk-links') @Get('apk-links')
@Authenticated() @Authenticated({ permission: Permission.ServerApkLinks })
getApkLinks(): ServerApkLinksDto { getApkLinks(): ServerApkLinksDto {
return this.service.getApkLinks(); return this.service.getApkLinks();
} }
@Get('storage') @Get('storage')
@Authenticated() @Authenticated({ permission: Permission.ServerStorage })
getStorage(): Promise<ServerStorageResponseDto> { getStorage(): Promise<ServerStorageResponseDto> {
return this.service.getStorage(); return this.service.getStorage();
} }
@ -78,7 +79,7 @@ export class ServerController {
} }
@Get('statistics') @Get('statistics')
@Authenticated({ admin: true }) @Authenticated({ permission: Permission.ServerStatistics, admin: true })
getServerStatistics(): Promise<ServerStatsResponseDto> { getServerStatistics(): Promise<ServerStatsResponseDto> {
return this.service.getStatistics(); return this.service.getStatistics();
} }
@ -88,25 +89,25 @@ export class ServerController {
return this.service.getSupportedMediaTypes(); return this.service.getSupportedMediaTypes();
} }
@Get('license')
@Authenticated({ permission: Permission.ServerLicenseRead, admin: true })
@ApiNotFoundResponse()
getServerLicense(): Promise<LicenseResponseDto> {
return this.service.getLicense();
}
@Put('license') @Put('license')
@Authenticated({ admin: true }) @Authenticated({ permission: Permission.ServerLicenseUpdate, admin: true })
setServerLicense(@Body() license: LicenseKeyDto): Promise<LicenseResponseDto> { setServerLicense(@Body() license: LicenseKeyDto): Promise<LicenseResponseDto> {
return this.service.setLicense(license); return this.service.setLicense(license);
} }
@Delete('license') @Delete('license')
@Authenticated({ admin: true }) @Authenticated({ permission: Permission.ServerLicenseDelete, admin: true })
deleteServerLicense(): Promise<void> { deleteServerLicense(): Promise<void> {
return this.service.deleteLicense(); return this.service.deleteLicense();
} }
@Get('license')
@Authenticated({ admin: true })
@ApiNotFoundResponse()
getServerLicense(): Promise<LicenseResponseDto> {
return this.service.getLicense();
}
@Get('version-check') @Get('version-check')
@Authenticated() @Authenticated()
getVersionCheck(): Promise<VersionCheckStateResponseDto> { getVersionCheck(): Promise<VersionCheckStateResponseDto> {

View File

@ -12,6 +12,7 @@ import {
SyncAckSetDto, SyncAckSetDto,
SyncStreamDto, SyncStreamDto,
} from 'src/dtos/sync.dto'; } from 'src/dtos/sync.dto';
import { Permission } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter'; import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter';
import { SyncService } from 'src/services/sync.service'; import { SyncService } from 'src/services/sync.service';
@ -41,7 +42,7 @@ export class SyncController {
@Post('stream') @Post('stream')
@Header('Content-Type', 'application/jsonlines+json') @Header('Content-Type', 'application/jsonlines+json')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Authenticated() @Authenticated({ permission: Permission.SyncStream })
async getSyncStream(@Auth() auth: AuthDto, @Res() res: Response, @Body() dto: SyncStreamDto) { async getSyncStream(@Auth() auth: AuthDto, @Res() res: Response, @Body() dto: SyncStreamDto) {
try { try {
await this.service.stream(auth, res, dto); await this.service.stream(auth, res, dto);
@ -52,21 +53,21 @@ export class SyncController {
} }
@Get('ack') @Get('ack')
@Authenticated() @Authenticated({ permission: Permission.SyncCheckpointRead })
getSyncAck(@Auth() auth: AuthDto): Promise<SyncAckDto[]> { getSyncAck(@Auth() auth: AuthDto): Promise<SyncAckDto[]> {
return this.service.getAcks(auth); return this.service.getAcks(auth);
} }
@Post('ack') @Post('ack')
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@Authenticated() @Authenticated({ permission: Permission.SyncCheckpointUpdate })
sendSyncAck(@Auth() auth: AuthDto, @Body() dto: SyncAckSetDto) { sendSyncAck(@Auth() auth: AuthDto, @Body() dto: SyncAckSetDto) {
return this.service.setAcks(auth, dto); return this.service.setAcks(auth, dto);
} }
@Delete('ack') @Delete('ack')
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@Authenticated() @Authenticated({ permission: Permission.SyncCheckpointDelete })
deleteSyncAck(@Auth() auth: AuthDto, @Body() dto: SyncAckDeleteDto) { deleteSyncAck(@Auth() auth: AuthDto, @Body() dto: SyncAckDeleteDto) {
return this.service.deleteAcks(auth, dto); return this.service.deleteAcks(auth, dto);
} }

View File

@ -21,7 +21,7 @@ import { OnboardingDto, OnboardingResponseDto } from 'src/dtos/onboarding.dto';
import { UserPreferencesResponseDto, UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto'; import { UserPreferencesResponseDto, UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto';
import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto';
import { UserAdminResponseDto, UserResponseDto, UserUpdateMeDto } from 'src/dtos/user.dto'; import { UserAdminResponseDto, UserResponseDto, UserUpdateMeDto } from 'src/dtos/user.dto';
import { RouteKey } from 'src/enum'; import { Permission, RouteKey } from 'src/enum';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
import { LoggingRepository } from 'src/repositories/logging.repository'; import { LoggingRepository } from 'src/repositories/logging.repository';
@ -38,31 +38,31 @@ export class UserController {
) {} ) {}
@Get() @Get()
@Authenticated() @Authenticated({ permission: Permission.UserRead })
searchUsers(@Auth() auth: AuthDto): Promise<UserResponseDto[]> { searchUsers(@Auth() auth: AuthDto): Promise<UserResponseDto[]> {
return this.service.search(auth); return this.service.search(auth);
} }
@Get('me') @Get('me')
@Authenticated() @Authenticated({ permission: Permission.UserRead })
getMyUser(@Auth() auth: AuthDto): Promise<UserAdminResponseDto> { getMyUser(@Auth() auth: AuthDto): Promise<UserAdminResponseDto> {
return this.service.getMe(auth); return this.service.getMe(auth);
} }
@Put('me') @Put('me')
@Authenticated() @Authenticated({ permission: Permission.UserUpdate })
updateMyUser(@Auth() auth: AuthDto, @Body() dto: UserUpdateMeDto): Promise<UserAdminResponseDto> { updateMyUser(@Auth() auth: AuthDto, @Body() dto: UserUpdateMeDto): Promise<UserAdminResponseDto> {
return this.service.updateMe(auth, dto); return this.service.updateMe(auth, dto);
} }
@Get('me/preferences') @Get('me/preferences')
@Authenticated() @Authenticated({ permission: Permission.UserPreferenceRead })
getMyPreferences(@Auth() auth: AuthDto): Promise<UserPreferencesResponseDto> { getMyPreferences(@Auth() auth: AuthDto): Promise<UserPreferencesResponseDto> {
return this.service.getMyPreferences(auth); return this.service.getMyPreferences(auth);
} }
@Put('me/preferences') @Put('me/preferences')
@Authenticated() @Authenticated({ permission: Permission.UserPreferenceUpdate })
updateMyPreferences( updateMyPreferences(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@Body() dto: UserPreferencesUpdateDto, @Body() dto: UserPreferencesUpdateDto,
@ -71,43 +71,43 @@ export class UserController {
} }
@Get('me/license') @Get('me/license')
@Authenticated() @Authenticated({ permission: Permission.UserLicenseRead })
getUserLicense(@Auth() auth: AuthDto): Promise<LicenseResponseDto> { getUserLicense(@Auth() auth: AuthDto): Promise<LicenseResponseDto> {
return this.service.getLicense(auth); return this.service.getLicense(auth);
} }
@Put('me/license') @Put('me/license')
@Authenticated() @Authenticated({ permission: Permission.UserLicenseUpdate })
async setUserLicense(@Auth() auth: AuthDto, @Body() license: LicenseKeyDto): Promise<LicenseResponseDto> { async setUserLicense(@Auth() auth: AuthDto, @Body() license: LicenseKeyDto): Promise<LicenseResponseDto> {
return this.service.setLicense(auth, license); return this.service.setLicense(auth, license);
} }
@Delete('me/license') @Delete('me/license')
@Authenticated() @Authenticated({ permission: Permission.UserLicenseDelete })
async deleteUserLicense(@Auth() auth: AuthDto): Promise<void> { async deleteUserLicense(@Auth() auth: AuthDto): Promise<void> {
await this.service.deleteLicense(auth); await this.service.deleteLicense(auth);
} }
@Get('me/onboarding') @Get('me/onboarding')
@Authenticated() @Authenticated({ permission: Permission.UserOnboardingRead })
getUserOnboarding(@Auth() auth: AuthDto): Promise<OnboardingResponseDto> { getUserOnboarding(@Auth() auth: AuthDto): Promise<OnboardingResponseDto> {
return this.service.getOnboarding(auth); return this.service.getOnboarding(auth);
} }
@Put('me/onboarding') @Put('me/onboarding')
@Authenticated() @Authenticated({ permission: Permission.UserOnboardingUpdate })
async setUserOnboarding(@Auth() auth: AuthDto, @Body() Onboarding: OnboardingDto): Promise<OnboardingResponseDto> { async setUserOnboarding(@Auth() auth: AuthDto, @Body() Onboarding: OnboardingDto): Promise<OnboardingResponseDto> {
return this.service.setOnboarding(auth, Onboarding); return this.service.setOnboarding(auth, Onboarding);
} }
@Delete('me/onboarding') @Delete('me/onboarding')
@Authenticated() @Authenticated({ permission: Permission.UserOnboardingDelete })
async deleteUserOnboarding(@Auth() auth: AuthDto): Promise<void> { async deleteUserOnboarding(@Auth() auth: AuthDto): Promise<void> {
await this.service.deleteOnboarding(auth); await this.service.deleteOnboarding(auth);
} }
@Get(':id') @Get(':id')
@Authenticated() @Authenticated({ permission: Permission.UserRead })
getUser(@Param() { id }: UUIDParamDto): Promise<UserResponseDto> { getUser(@Param() { id }: UUIDParamDto): Promise<UserResponseDto> {
return this.service.get(id); return this.service.get(id);
} }
@ -116,7 +116,7 @@ export class UserController {
@ApiConsumes('multipart/form-data') @ApiConsumes('multipart/form-data')
@ApiBody({ description: 'A new avatar for the user', type: CreateProfileImageDto }) @ApiBody({ description: 'A new avatar for the user', type: CreateProfileImageDto })
@Post('profile-image') @Post('profile-image')
@Authenticated() @Authenticated({ permission: Permission.UserProfileImageUpdate })
createProfileImage( createProfileImage(
@Auth() auth: AuthDto, @Auth() auth: AuthDto,
@UploadedFile() fileInfo: Express.Multer.File, @UploadedFile() fileInfo: Express.Multer.File,
@ -126,14 +126,14 @@ export class UserController {
@Delete('profile-image') @Delete('profile-image')
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@Authenticated() @Authenticated({ permission: Permission.UserProfileImageDelete })
deleteProfileImage(@Auth() auth: AuthDto): Promise<void> { deleteProfileImage(@Auth() auth: AuthDto): Promise<void> {
return this.service.deleteProfileImage(auth); return this.service.deleteProfileImage(auth);
} }
@Get(':id/profile-image') @Get(':id/profile-image')
@FileResponse() @FileResponse()
@Authenticated() @Authenticated({ permission: Permission.UserProfileImageRead })
async getProfileImage(@Res() res: Response, @Next() next: NextFunction, @Param() { id }: UUIDParamDto) { async getProfileImage(@Res() res: Response, @Next() next: NextFunction, @Param() { id }: UUIDParamDto) {
await sendFile(res, next, () => this.service.getProfileImage(id), this.logger); await sendFile(res, next, () => this.service.getProfileImage(id), this.logger);
} }

View File

@ -87,31 +87,45 @@ export enum Permission {
AssetRead = 'asset.read', AssetRead = 'asset.read',
AssetUpdate = 'asset.update', AssetUpdate = 'asset.update',
AssetDelete = 'asset.delete', AssetDelete = 'asset.delete',
AssetStatistics = 'asset.statistics',
AssetShare = 'asset.share', AssetShare = 'asset.share',
AssetView = 'asset.view', AssetView = 'asset.view',
AssetDownload = 'asset.download', AssetDownload = 'asset.download',
AssetUpload = 'asset.upload', AssetUpload = 'asset.upload',
AssetReplace = 'asset.replace',
AlbumCreate = 'album.create', AlbumCreate = 'album.create',
AlbumRead = 'album.read', AlbumRead = 'album.read',
AlbumUpdate = 'album.update', AlbumUpdate = 'album.update',
AlbumDelete = 'album.delete', AlbumDelete = 'album.delete',
AlbumStatistics = 'album.statistics', AlbumStatistics = 'album.statistics',
AlbumAddAsset = 'album.addAsset',
AlbumRemoveAsset = 'album.removeAsset',
AlbumShare = 'album.share', AlbumShare = 'album.share',
AlbumDownload = 'album.download', AlbumDownload = 'album.download',
AlbumAssetCreate = 'albumAsset.create',
AlbumAssetDelete = 'albumAsset.delete',
AlbumUserCreate = 'albumUser.create',
AlbumUserUpdate = 'albumUser.update',
AlbumUserDelete = 'albumUser.delete',
AuthChangePassword = 'auth.changePassword',
AuthDeviceDelete = 'authDevice.delete', AuthDeviceDelete = 'authDevice.delete',
ArchiveRead = 'archive.read', ArchiveRead = 'archive.read',
DuplicateRead = 'duplicate.read',
DuplicateDelete = 'duplicate.delete',
FaceCreate = 'face.create', FaceCreate = 'face.create',
FaceRead = 'face.read', FaceRead = 'face.read',
FaceUpdate = 'face.update', FaceUpdate = 'face.update',
FaceDelete = 'face.delete', FaceDelete = 'face.delete',
JobCreate = 'job.create',
JobRead = 'job.read',
LibraryCreate = 'library.create', LibraryCreate = 'library.create',
LibraryRead = 'library.read', LibraryRead = 'library.read',
LibraryUpdate = 'library.update', LibraryUpdate = 'library.update',
@ -125,6 +139,10 @@ export enum Permission {
MemoryRead = 'memory.read', MemoryRead = 'memory.read',
MemoryUpdate = 'memory.update', MemoryUpdate = 'memory.update',
MemoryDelete = 'memory.delete', MemoryDelete = 'memory.delete',
MemoryStatistics = 'memory.statistics',
MemoryAssetCreate = 'memoryAsset.create',
MemoryAssetDelete = 'memoryAsset.delete',
NotificationCreate = 'notification.create', NotificationCreate = 'notification.create',
NotificationRead = 'notification.read', NotificationRead = 'notification.read',
@ -144,6 +162,19 @@ export enum Permission {
PersonMerge = 'person.merge', PersonMerge = 'person.merge',
PersonReassign = 'person.reassign', PersonReassign = 'person.reassign',
PinCodeCreate = 'pinCode.create',
PinCodeUpdate = 'pinCode.update',
PinCodeDelete = 'pinCode.delete',
ServerAbout = 'server.about',
ServerApkLinks = 'server.apkLinks',
ServerStorage = 'server.storage',
ServerStatistics = 'server.statistics',
ServerLicenseRead = 'serverLicense.read',
ServerLicenseUpdate = 'serverLicense.update',
ServerLicenseDelete = 'serverLicense.delete',
SessionCreate = 'session.create', SessionCreate = 'session.create',
SessionRead = 'session.read', SessionRead = 'session.read',
SessionUpdate = 'session.update', SessionUpdate = 'session.update',
@ -160,6 +191,11 @@ export enum Permission {
StackUpdate = 'stack.update', StackUpdate = 'stack.update',
StackDelete = 'stack.delete', StackDelete = 'stack.delete',
SyncStream = 'sync.stream',
SyncCheckpointRead = 'syncCheckpoint.read',
SyncCheckpointUpdate = 'syncCheckpoint.update',
SyncCheckpointDelete = 'syncCheckpoint.delete',
SystemConfigRead = 'systemConfig.read', SystemConfigRead = 'systemConfig.read',
SystemConfigUpdate = 'systemConfig.update', SystemConfigUpdate = 'systemConfig.update',
@ -172,10 +208,30 @@ export enum Permission {
TagDelete = 'tag.delete', TagDelete = 'tag.delete',
TagAsset = 'tag.asset', TagAsset = 'tag.asset',
AdminUserCreate = 'admin.user.create', UserRead = 'user.read',
AdminUserRead = 'admin.user.read', UserUpdate = 'user.update',
AdminUserUpdate = 'admin.user.update',
AdminUserDelete = 'admin.user.delete', UserLicenseCreate = 'userLicense.create',
UserLicenseRead = 'userLicense.read',
UserLicenseUpdate = 'userLicense.update',
UserLicenseDelete = 'userLicense.delete',
UserOnboardingRead = 'userOnboarding.read',
UserOnboardingUpdate = 'userOnboarding.update',
UserOnboardingDelete = 'userOnboarding.delete',
UserPreferenceRead = 'userPreference.read',
UserPreferenceUpdate = 'userPreference.update',
UserProfileImageCreate = 'userProfileImage.create',
UserProfileImageRead = 'userProfileImage.read',
UserProfileImageUpdate = 'userProfileImage.update',
UserProfileImageDelete = 'userProfileImage.delete',
AdminUserCreate = 'adminUser.create',
AdminUserRead = 'adminUser.read',
AdminUserUpdate = 'adminUser.update',
AdminUserDelete = 'adminUser.delete',
} }
export enum SharedLinkType { export enum SharedLinkType {

View File

@ -0,0 +1,22 @@
import { Kysely, sql } from 'kysely';
const items = [
{ oldName: 'album.addAsset', newName: 'albumAsset.create' },
{ oldName: 'album.removeAsset', newName: 'albumAsset.delete' },
{ oldName: 'admin.user.create', newName: 'adminUser.create' },
{ oldName: 'admin.user.read', newName: 'adminUser.read' },
{ oldName: 'admin.user.update', newName: 'adminUser.update' },
{ oldName: 'admin.user.delete', newName: 'adminUser.delete' },
];
export async function up(db: Kysely<any>): Promise<void> {
for (const { oldName, newName } of items) {
await sql`UPDATE "api_key" SET "permissions" = array_replace("permissions", ${oldName}, ${newName})`.execute(db);
}
}
export async function down(db: Kysely<any>): Promise<void> {
for (const { oldName, newName } of items) {
await sql`UPDATE "api_key" SET "permissions" = array_replace("permissions", ${newName}, ${oldName})`.execute(db);
}
}

View File

@ -158,7 +158,7 @@ export class AlbumService extends BaseService {
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> { async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
const album = await this.findOrFail(id, { withAssets: false }); const album = await this.findOrFail(id, { withAssets: false });
await this.requireAccess({ auth, permission: Permission.AlbumAddAsset, ids: [id] }); await this.requireAccess({ auth, permission: Permission.AlbumAssetCreate, ids: [id] });
const results = await addAssets( const results = await addAssets(
auth, auth,
@ -187,7 +187,7 @@ export class AlbumService extends BaseService {
} }
async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> { async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
await this.requireAccess({ auth, permission: Permission.AlbumRemoveAsset, ids: [id] }); await this.requireAccess({ auth, permission: Permission.AlbumAssetDelete, ids: [id] });
const album = await this.findOrFail(id, { withAssets: false }); const album = await this.findOrFail(id, { withAssets: false });
const results = await removeAssets( const results = await removeAssets(

View File

@ -92,7 +92,7 @@ const checkSharedLinkAccess = async (
return sharedLink.allowDownload ? await access.album.checkSharedLinkAccess(sharedLinkId, ids) : new Set(); return sharedLink.allowDownload ? await access.album.checkSharedLinkAccess(sharedLinkId, ids) : new Set();
} }
case Permission.AlbumAddAsset: { case Permission.AlbumAssetCreate: {
return sharedLink.allowUpload ? await access.album.checkSharedLinkAccess(sharedLinkId, ids) : new Set(); return sharedLink.allowUpload ? await access.album.checkSharedLinkAccess(sharedLinkId, ids) : new Set();
} }
@ -163,7 +163,7 @@ const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRe
return setUnion(isOwner, isShared); return setUnion(isOwner, isShared);
} }
case Permission.AlbumAddAsset: { case Permission.AlbumAssetCreate: {
const isOwner = await access.album.checkOwnerAccess(auth.user.id, ids); const isOwner = await access.album.checkOwnerAccess(auth.user.id, ids);
const isShared = await access.album.checkSharedAlbumAccess( const isShared = await access.album.checkSharedAlbumAccess(
auth.user.id, auth.user.id,
@ -195,7 +195,7 @@ const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRe
return setUnion(isOwner, isShared); return setUnion(isOwner, isShared);
} }
case Permission.AlbumRemoveAsset: { case Permission.AlbumAssetDelete: {
const isOwner = await access.album.checkOwnerAccess(auth.user.id, ids); const isOwner = await access.album.checkOwnerAccess(auth.user.id, ids);
const isShared = await access.album.checkSharedAlbumAccess( const isShared = await access.album.checkSharedAlbumAccess(
auth.user.id, auth.user.id,