You've already forked immich
mirror of
https://github.com/immich-app/immich.git
synced 2025-08-09 23:17:29 +02:00
feat(server): granular permissions for api keys (#11824)
feat(server): api auth permissions
This commit is contained in:
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
@@ -175,6 +175,7 @@ part 'model/path_type.dart';
|
||||
part 'model/people_response_dto.dart';
|
||||
part 'model/people_update_dto.dart';
|
||||
part 'model/people_update_item.dart';
|
||||
part 'model/permission.dart';
|
||||
part 'model/person_create_dto.dart';
|
||||
part 'model/person_response_dto.dart';
|
||||
part 'model/person_statistics_response_dto.dart';
|
||||
|
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
@@ -407,6 +407,8 @@ class ApiClient {
|
||||
return PeopleUpdateDto.fromJson(value);
|
||||
case 'PeopleUpdateItem':
|
||||
return PeopleUpdateItem.fromJson(value);
|
||||
case 'Permission':
|
||||
return PermissionTypeTransformer().decode(value);
|
||||
case 'PersonCreateDto':
|
||||
return PersonCreateDto.fromJson(value);
|
||||
case 'PersonResponseDto':
|
||||
|
3
mobile/openapi/lib/api_helper.dart
generated
3
mobile/openapi/lib/api_helper.dart
generated
@@ -112,6 +112,9 @@ String parameterToString(dynamic value) {
|
||||
if (value is PathType) {
|
||||
return PathTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is Permission) {
|
||||
return PermissionTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is ReactionLevel) {
|
||||
return ReactionLevelTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
14
mobile/openapi/lib/model/api_key_create_dto.dart
generated
14
mobile/openapi/lib/model/api_key_create_dto.dart
generated
@@ -14,6 +14,7 @@ class APIKeyCreateDto {
|
||||
/// Returns a new [APIKeyCreateDto] instance.
|
||||
APIKeyCreateDto({
|
||||
this.name,
|
||||
this.permissions = const [],
|
||||
});
|
||||
|
||||
///
|
||||
@@ -24,17 +25,21 @@ class APIKeyCreateDto {
|
||||
///
|
||||
String? name;
|
||||
|
||||
List<Permission> permissions;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is APIKeyCreateDto &&
|
||||
other.name == name;
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.permissions, permissions);
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(name == null ? 0 : name!.hashCode);
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(permissions.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'APIKeyCreateDto[name=$name]';
|
||||
String toString() => 'APIKeyCreateDto[name=$name, permissions=$permissions]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
@@ -43,6 +48,7 @@ class APIKeyCreateDto {
|
||||
} else {
|
||||
// json[r'name'] = null;
|
||||
}
|
||||
json[r'permissions'] = this.permissions;
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -55,6 +61,7 @@ class APIKeyCreateDto {
|
||||
|
||||
return APIKeyCreateDto(
|
||||
name: mapValueOfType<String>(json, r'name'),
|
||||
permissions: Permission.listFromJson(json[r'permissions']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -102,6 +109,7 @@ class APIKeyCreateDto {
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'permissions',
|
||||
};
|
||||
}
|
||||
|
||||
|
10
mobile/openapi/lib/model/api_key_response_dto.dart
generated
10
mobile/openapi/lib/model/api_key_response_dto.dart
generated
@@ -16,6 +16,7 @@ class APIKeyResponseDto {
|
||||
required this.createdAt,
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.permissions = const [],
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
@@ -25,6 +26,8 @@ class APIKeyResponseDto {
|
||||
|
||||
String name;
|
||||
|
||||
List<Permission> permissions;
|
||||
|
||||
DateTime updatedAt;
|
||||
|
||||
@override
|
||||
@@ -32,6 +35,7 @@ class APIKeyResponseDto {
|
||||
other.createdAt == createdAt &&
|
||||
other.id == id &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.permissions, permissions) &&
|
||||
other.updatedAt == updatedAt;
|
||||
|
||||
@override
|
||||
@@ -40,16 +44,18 @@ class APIKeyResponseDto {
|
||||
(createdAt.hashCode) +
|
||||
(id.hashCode) +
|
||||
(name.hashCode) +
|
||||
(permissions.hashCode) +
|
||||
(updatedAt.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'APIKeyResponseDto[createdAt=$createdAt, id=$id, name=$name, updatedAt=$updatedAt]';
|
||||
String toString() => 'APIKeyResponseDto[createdAt=$createdAt, id=$id, name=$name, permissions=$permissions, updatedAt=$updatedAt]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
|
||||
json[r'id'] = this.id;
|
||||
json[r'name'] = this.name;
|
||||
json[r'permissions'] = this.permissions;
|
||||
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
|
||||
return json;
|
||||
}
|
||||
@@ -65,6 +71,7 @@ class APIKeyResponseDto {
|
||||
createdAt: mapDateTime(json, r'createdAt', r'')!,
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
name: mapValueOfType<String>(json, r'name')!,
|
||||
permissions: Permission.listFromJson(json[r'permissions']),
|
||||
updatedAt: mapDateTime(json, r'updatedAt', r'')!,
|
||||
);
|
||||
}
|
||||
@@ -116,6 +123,7 @@ class APIKeyResponseDto {
|
||||
'createdAt',
|
||||
'id',
|
||||
'name',
|
||||
'permissions',
|
||||
'updatedAt',
|
||||
};
|
||||
}
|
||||
|
292
mobile/openapi/lib/model/permission.dart
generated
Normal file
292
mobile/openapi/lib/model/permission.dart
generated
Normal file
@@ -0,0 +1,292 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class Permission {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const Permission._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const all = Permission._(r'all');
|
||||
static const activityPeriodCreate = Permission._(r'activity.create');
|
||||
static const activityPeriodRead = Permission._(r'activity.read');
|
||||
static const activityPeriodUpdate = Permission._(r'activity.update');
|
||||
static const activityPeriodDelete = Permission._(r'activity.delete');
|
||||
static const activityPeriodStatistics = Permission._(r'activity.statistics');
|
||||
static const apiKeyPeriodCreate = Permission._(r'apiKey.create');
|
||||
static const apiKeyPeriodRead = Permission._(r'apiKey.read');
|
||||
static const apiKeyPeriodUpdate = Permission._(r'apiKey.update');
|
||||
static const apiKeyPeriodDelete = Permission._(r'apiKey.delete');
|
||||
static const assetPeriodRead = Permission._(r'asset.read');
|
||||
static const assetPeriodUpdate = Permission._(r'asset.update');
|
||||
static const assetPeriodDelete = Permission._(r'asset.delete');
|
||||
static const assetPeriodRestore = Permission._(r'asset.restore');
|
||||
static const assetPeriodShare = Permission._(r'asset.share');
|
||||
static const assetPeriodView = Permission._(r'asset.view');
|
||||
static const assetPeriodDownload = Permission._(r'asset.download');
|
||||
static const assetPeriodUpload = Permission._(r'asset.upload');
|
||||
static const albumPeriodCreate = Permission._(r'album.create');
|
||||
static const albumPeriodRead = Permission._(r'album.read');
|
||||
static const albumPeriodUpdate = Permission._(r'album.update');
|
||||
static const albumPeriodDelete = Permission._(r'album.delete');
|
||||
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 albumPeriodDownload = Permission._(r'album.download');
|
||||
static const authDevicePeriodDelete = Permission._(r'authDevice.delete');
|
||||
static const archivePeriodRead = Permission._(r'archive.read');
|
||||
static const facePeriodCreate = Permission._(r'face.create');
|
||||
static const facePeriodRead = Permission._(r'face.read');
|
||||
static const facePeriodUpdate = Permission._(r'face.update');
|
||||
static const facePeriodDelete = Permission._(r'face.delete');
|
||||
static const libraryPeriodCreate = Permission._(r'library.create');
|
||||
static const libraryPeriodRead = Permission._(r'library.read');
|
||||
static const libraryPeriodUpdate = Permission._(r'library.update');
|
||||
static const libraryPeriodDelete = Permission._(r'library.delete');
|
||||
static const libraryPeriodStatistics = Permission._(r'library.statistics');
|
||||
static const timelinePeriodRead = Permission._(r'timeline.read');
|
||||
static const timelinePeriodDownload = Permission._(r'timeline.download');
|
||||
static const memoryPeriodCreate = Permission._(r'memory.create');
|
||||
static const memoryPeriodRead = Permission._(r'memory.read');
|
||||
static const memoryPeriodUpdate = Permission._(r'memory.update');
|
||||
static const memoryPeriodDelete = Permission._(r'memory.delete');
|
||||
static const partnerPeriodCreate = Permission._(r'partner.create');
|
||||
static const partnerPeriodRead = Permission._(r'partner.read');
|
||||
static const partnerPeriodUpdate = Permission._(r'partner.update');
|
||||
static const partnerPeriodDelete = Permission._(r'partner.delete');
|
||||
static const personPeriodCreate = Permission._(r'person.create');
|
||||
static const personPeriodRead = Permission._(r'person.read');
|
||||
static const personPeriodUpdate = Permission._(r'person.update');
|
||||
static const personPeriodDelete = Permission._(r'person.delete');
|
||||
static const personPeriodStatistics = Permission._(r'person.statistics');
|
||||
static const personPeriodMerge = Permission._(r'person.merge');
|
||||
static const personPeriodReassign = Permission._(r'person.reassign');
|
||||
static const sharedLinkPeriodCreate = Permission._(r'sharedLink.create');
|
||||
static const sharedLinkPeriodRead = Permission._(r'sharedLink.read');
|
||||
static const sharedLinkPeriodUpdate = Permission._(r'sharedLink.update');
|
||||
static const sharedLinkPeriodDelete = Permission._(r'sharedLink.delete');
|
||||
static const systemConfigPeriodRead = Permission._(r'systemConfig.read');
|
||||
static const systemConfigPeriodUpdate = Permission._(r'systemConfig.update');
|
||||
static const systemMetadataPeriodRead = Permission._(r'systemMetadata.read');
|
||||
static const systemMetadataPeriodUpdate = Permission._(r'systemMetadata.update');
|
||||
static const tagPeriodCreate = Permission._(r'tag.create');
|
||||
static const tagPeriodRead = Permission._(r'tag.read');
|
||||
static const tagPeriodUpdate = Permission._(r'tag.update');
|
||||
static const tagPeriodDelete = Permission._(r'tag.delete');
|
||||
static const adminPeriodUserPeriodCreate = Permission._(r'admin.user.create');
|
||||
static const adminPeriodUserPeriodRead = Permission._(r'admin.user.read');
|
||||
static const adminPeriodUserPeriodUpdate = Permission._(r'admin.user.update');
|
||||
static const adminPeriodUserPeriodDelete = Permission._(r'admin.user.delete');
|
||||
|
||||
/// List of all possible values in this [enum][Permission].
|
||||
static const values = <Permission>[
|
||||
all,
|
||||
activityPeriodCreate,
|
||||
activityPeriodRead,
|
||||
activityPeriodUpdate,
|
||||
activityPeriodDelete,
|
||||
activityPeriodStatistics,
|
||||
apiKeyPeriodCreate,
|
||||
apiKeyPeriodRead,
|
||||
apiKeyPeriodUpdate,
|
||||
apiKeyPeriodDelete,
|
||||
assetPeriodRead,
|
||||
assetPeriodUpdate,
|
||||
assetPeriodDelete,
|
||||
assetPeriodRestore,
|
||||
assetPeriodShare,
|
||||
assetPeriodView,
|
||||
assetPeriodDownload,
|
||||
assetPeriodUpload,
|
||||
albumPeriodCreate,
|
||||
albumPeriodRead,
|
||||
albumPeriodUpdate,
|
||||
albumPeriodDelete,
|
||||
albumPeriodStatistics,
|
||||
albumPeriodAddAsset,
|
||||
albumPeriodRemoveAsset,
|
||||
albumPeriodShare,
|
||||
albumPeriodDownload,
|
||||
authDevicePeriodDelete,
|
||||
archivePeriodRead,
|
||||
facePeriodCreate,
|
||||
facePeriodRead,
|
||||
facePeriodUpdate,
|
||||
facePeriodDelete,
|
||||
libraryPeriodCreate,
|
||||
libraryPeriodRead,
|
||||
libraryPeriodUpdate,
|
||||
libraryPeriodDelete,
|
||||
libraryPeriodStatistics,
|
||||
timelinePeriodRead,
|
||||
timelinePeriodDownload,
|
||||
memoryPeriodCreate,
|
||||
memoryPeriodRead,
|
||||
memoryPeriodUpdate,
|
||||
memoryPeriodDelete,
|
||||
partnerPeriodCreate,
|
||||
partnerPeriodRead,
|
||||
partnerPeriodUpdate,
|
||||
partnerPeriodDelete,
|
||||
personPeriodCreate,
|
||||
personPeriodRead,
|
||||
personPeriodUpdate,
|
||||
personPeriodDelete,
|
||||
personPeriodStatistics,
|
||||
personPeriodMerge,
|
||||
personPeriodReassign,
|
||||
sharedLinkPeriodCreate,
|
||||
sharedLinkPeriodRead,
|
||||
sharedLinkPeriodUpdate,
|
||||
sharedLinkPeriodDelete,
|
||||
systemConfigPeriodRead,
|
||||
systemConfigPeriodUpdate,
|
||||
systemMetadataPeriodRead,
|
||||
systemMetadataPeriodUpdate,
|
||||
tagPeriodCreate,
|
||||
tagPeriodRead,
|
||||
tagPeriodUpdate,
|
||||
tagPeriodDelete,
|
||||
adminPeriodUserPeriodCreate,
|
||||
adminPeriodUserPeriodRead,
|
||||
adminPeriodUserPeriodUpdate,
|
||||
adminPeriodUserPeriodDelete,
|
||||
];
|
||||
|
||||
static Permission? fromJson(dynamic value) => PermissionTypeTransformer().decode(value);
|
||||
|
||||
static List<Permission> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <Permission>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = Permission.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [Permission] to String,
|
||||
/// and [decode] dynamic data back to [Permission].
|
||||
class PermissionTypeTransformer {
|
||||
factory PermissionTypeTransformer() => _instance ??= const PermissionTypeTransformer._();
|
||||
|
||||
const PermissionTypeTransformer._();
|
||||
|
||||
String encode(Permission data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a Permission.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
Permission? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'all': return Permission.all;
|
||||
case r'activity.create': return Permission.activityPeriodCreate;
|
||||
case r'activity.read': return Permission.activityPeriodRead;
|
||||
case r'activity.update': return Permission.activityPeriodUpdate;
|
||||
case r'activity.delete': return Permission.activityPeriodDelete;
|
||||
case r'activity.statistics': return Permission.activityPeriodStatistics;
|
||||
case r'apiKey.create': return Permission.apiKeyPeriodCreate;
|
||||
case r'apiKey.read': return Permission.apiKeyPeriodRead;
|
||||
case r'apiKey.update': return Permission.apiKeyPeriodUpdate;
|
||||
case r'apiKey.delete': return Permission.apiKeyPeriodDelete;
|
||||
case r'asset.read': return Permission.assetPeriodRead;
|
||||
case r'asset.update': return Permission.assetPeriodUpdate;
|
||||
case r'asset.delete': return Permission.assetPeriodDelete;
|
||||
case r'asset.restore': return Permission.assetPeriodRestore;
|
||||
case r'asset.share': return Permission.assetPeriodShare;
|
||||
case r'asset.view': return Permission.assetPeriodView;
|
||||
case r'asset.download': return Permission.assetPeriodDownload;
|
||||
case r'asset.upload': return Permission.assetPeriodUpload;
|
||||
case r'album.create': return Permission.albumPeriodCreate;
|
||||
case r'album.read': return Permission.albumPeriodRead;
|
||||
case r'album.update': return Permission.albumPeriodUpdate;
|
||||
case r'album.delete': return Permission.albumPeriodDelete;
|
||||
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.download': return Permission.albumPeriodDownload;
|
||||
case r'authDevice.delete': return Permission.authDevicePeriodDelete;
|
||||
case r'archive.read': return Permission.archivePeriodRead;
|
||||
case r'face.create': return Permission.facePeriodCreate;
|
||||
case r'face.read': return Permission.facePeriodRead;
|
||||
case r'face.update': return Permission.facePeriodUpdate;
|
||||
case r'face.delete': return Permission.facePeriodDelete;
|
||||
case r'library.create': return Permission.libraryPeriodCreate;
|
||||
case r'library.read': return Permission.libraryPeriodRead;
|
||||
case r'library.update': return Permission.libraryPeriodUpdate;
|
||||
case r'library.delete': return Permission.libraryPeriodDelete;
|
||||
case r'library.statistics': return Permission.libraryPeriodStatistics;
|
||||
case r'timeline.read': return Permission.timelinePeriodRead;
|
||||
case r'timeline.download': return Permission.timelinePeriodDownload;
|
||||
case r'memory.create': return Permission.memoryPeriodCreate;
|
||||
case r'memory.read': return Permission.memoryPeriodRead;
|
||||
case r'memory.update': return Permission.memoryPeriodUpdate;
|
||||
case r'memory.delete': return Permission.memoryPeriodDelete;
|
||||
case r'partner.create': return Permission.partnerPeriodCreate;
|
||||
case r'partner.read': return Permission.partnerPeriodRead;
|
||||
case r'partner.update': return Permission.partnerPeriodUpdate;
|
||||
case r'partner.delete': return Permission.partnerPeriodDelete;
|
||||
case r'person.create': return Permission.personPeriodCreate;
|
||||
case r'person.read': return Permission.personPeriodRead;
|
||||
case r'person.update': return Permission.personPeriodUpdate;
|
||||
case r'person.delete': return Permission.personPeriodDelete;
|
||||
case r'person.statistics': return Permission.personPeriodStatistics;
|
||||
case r'person.merge': return Permission.personPeriodMerge;
|
||||
case r'person.reassign': return Permission.personPeriodReassign;
|
||||
case r'sharedLink.create': return Permission.sharedLinkPeriodCreate;
|
||||
case r'sharedLink.read': return Permission.sharedLinkPeriodRead;
|
||||
case r'sharedLink.update': return Permission.sharedLinkPeriodUpdate;
|
||||
case r'sharedLink.delete': return Permission.sharedLinkPeriodDelete;
|
||||
case r'systemConfig.read': return Permission.systemConfigPeriodRead;
|
||||
case r'systemConfig.update': return Permission.systemConfigPeriodUpdate;
|
||||
case r'systemMetadata.read': return Permission.systemMetadataPeriodRead;
|
||||
case r'systemMetadata.update': return Permission.systemMetadataPeriodUpdate;
|
||||
case r'tag.create': return Permission.tagPeriodCreate;
|
||||
case r'tag.read': return Permission.tagPeriodRead;
|
||||
case r'tag.update': return Permission.tagPeriodUpdate;
|
||||
case r'tag.delete': return Permission.tagPeriodDelete;
|
||||
case r'admin.user.create': return Permission.adminPeriodUserPeriodCreate;
|
||||
case r'admin.user.read': return Permission.adminPeriodUserPeriodRead;
|
||||
case r'admin.user.update': return Permission.adminPeriodUserPeriodUpdate;
|
||||
case r'admin.user.delete': return Permission.adminPeriodUserPeriodDelete;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [PermissionTypeTransformer] instance.
|
||||
static PermissionTypeTransformer? _instance;
|
||||
}
|
||||
|
Reference in New Issue
Block a user