1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-10 23:22:22 +02:00

feat(server,web): remove external path nonsense and make libraries admin-only (#7237)

* remove external path

* open-api

* make sql

* move library settings to admin panel

* Add documentation

* show external libraries only

* fix library list

* make user library settings look good

* fix test

* fix tests

* fix tests

* can pick user for library

* fix tests

* fix e2e

* chore: make sql

* Use unauth exception

* delete user library list

* cleanup

* fix e2e

* fix await lint

* chore: remove unused code

* chore: cleanup

* revert docs

* fix: is admin stuff

* table alignment

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jonathan Jogenfors
2024-02-29 19:35:37 +01:00
committed by GitHub
parent 369acc7bea
commit efa6efd200
63 changed files with 783 additions and 1111 deletions

View File

@@ -104,7 +104,10 @@ class LibraryApi {
}
/// Performs an HTTP 'GET /library' operation and returns the [Response].
Future<Response> getLibrariesWithHttpInfo() async {
/// Parameters:
///
/// * [LibraryType] type:
Future<Response> getAllLibrariesWithHttpInfo({ LibraryType? type, }) async {
// ignore: prefer_const_declarations
final path = r'/library';
@@ -115,6 +118,10 @@ class LibraryApi {
final headerParams = <String, String>{};
final formParams = <String, String>{};
if (type != null) {
queryParams.addAll(_queryParams('', 'type', type));
}
const contentTypes = <String>[];
@@ -129,8 +136,11 @@ class LibraryApi {
);
}
Future<List<LibraryResponseDto>?> getLibraries() async {
final response = await getLibrariesWithHttpInfo();
/// Parameters:
///
/// * [LibraryType] type:
Future<List<LibraryResponseDto>?> getAllLibraries({ LibraryType? type, }) async {
final response = await getAllLibrariesWithHttpInfo( type: type, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -151,7 +161,7 @@ class LibraryApi {
/// Parameters:
///
/// * [String] id (required):
Future<Response> getLibraryInfoWithHttpInfo(String id,) async {
Future<Response> getLibraryWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/library/{id}'
.replaceAll('{id}', id);
@@ -180,8 +190,8 @@ class LibraryApi {
/// Parameters:
///
/// * [String] id (required):
Future<LibraryResponseDto?> getLibraryInfo(String id,) async {
final response = await getLibraryInfoWithHttpInfo(id,);
Future<LibraryResponseDto?> getLibrary(String id,) async {
final response = await getLibraryWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@@ -18,6 +18,7 @@ class CreateLibraryDto {
this.isVisible,
this.isWatched,
this.name,
this.ownerId,
required this.type,
});
@@ -49,6 +50,14 @@ class CreateLibraryDto {
///
String? name;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? ownerId;
LibraryType type;
@override
@@ -58,6 +67,7 @@ class CreateLibraryDto {
other.isVisible == isVisible &&
other.isWatched == isWatched &&
other.name == name &&
other.ownerId == ownerId &&
other.type == type;
@override
@@ -68,10 +78,11 @@ class CreateLibraryDto {
(isVisible == null ? 0 : isVisible!.hashCode) +
(isWatched == null ? 0 : isWatched!.hashCode) +
(name == null ? 0 : name!.hashCode) +
(ownerId == null ? 0 : ownerId!.hashCode) +
(type.hashCode);
@override
String toString() => 'CreateLibraryDto[exclusionPatterns=$exclusionPatterns, importPaths=$importPaths, isVisible=$isVisible, isWatched=$isWatched, name=$name, type=$type]';
String toString() => 'CreateLibraryDto[exclusionPatterns=$exclusionPatterns, importPaths=$importPaths, isVisible=$isVisible, isWatched=$isWatched, name=$name, ownerId=$ownerId, type=$type]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -91,6 +102,11 @@ class CreateLibraryDto {
json[r'name'] = this.name;
} else {
// json[r'name'] = null;
}
if (this.ownerId != null) {
json[r'ownerId'] = this.ownerId;
} else {
// json[r'ownerId'] = null;
}
json[r'type'] = this.type;
return json;
@@ -113,6 +129,7 @@ class CreateLibraryDto {
isVisible: mapValueOfType<bool>(json, r'isVisible'),
isWatched: mapValueOfType<bool>(json, r'isWatched'),
name: mapValueOfType<String>(json, r'name'),
ownerId: mapValueOfType<String>(json, r'ownerId'),
type: LibraryType.fromJson(json[r'type'])!,
);
}

View File

@@ -14,7 +14,6 @@ class CreateUserDto {
/// Returns a new [CreateUserDto] instance.
CreateUserDto({
required this.email,
this.externalPath,
this.memoriesEnabled,
required this.name,
required this.password,
@@ -24,8 +23,6 @@ class CreateUserDto {
String email;
String? externalPath;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
@@ -45,7 +42,6 @@ class CreateUserDto {
@override
bool operator ==(Object other) => identical(this, other) || other is CreateUserDto &&
other.email == email &&
other.externalPath == externalPath &&
other.memoriesEnabled == memoriesEnabled &&
other.name == name &&
other.password == password &&
@@ -56,7 +52,6 @@ class CreateUserDto {
int get hashCode =>
// ignore: unnecessary_parenthesis
(email.hashCode) +
(externalPath == null ? 0 : externalPath!.hashCode) +
(memoriesEnabled == null ? 0 : memoriesEnabled!.hashCode) +
(name.hashCode) +
(password.hashCode) +
@@ -64,16 +59,11 @@ class CreateUserDto {
(storageLabel == null ? 0 : storageLabel!.hashCode);
@override
String toString() => 'CreateUserDto[email=$email, externalPath=$externalPath, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, storageLabel=$storageLabel]';
String toString() => 'CreateUserDto[email=$email, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, storageLabel=$storageLabel]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'email'] = this.email;
if (this.externalPath != null) {
json[r'externalPath'] = this.externalPath;
} else {
// json[r'externalPath'] = null;
}
if (this.memoriesEnabled != null) {
json[r'memoriesEnabled'] = this.memoriesEnabled;
} else {
@@ -103,7 +93,6 @@ class CreateUserDto {
return CreateUserDto(
email: mapValueOfType<String>(json, r'email')!,
externalPath: mapValueOfType<String>(json, r'externalPath'),
memoriesEnabled: mapValueOfType<bool>(json, r'memoriesEnabled'),
name: mapValueOfType<String>(json, r'name')!,
password: mapValueOfType<String>(json, r'password')!,

View File

@@ -17,7 +17,6 @@ class PartnerResponseDto {
required this.createdAt,
required this.deletedAt,
required this.email,
required this.externalPath,
required this.id,
this.inTimeline,
required this.isAdmin,
@@ -40,8 +39,6 @@ class PartnerResponseDto {
String email;
String? externalPath;
String id;
///
@@ -84,7 +81,6 @@ class PartnerResponseDto {
other.createdAt == createdAt &&
other.deletedAt == deletedAt &&
other.email == email &&
other.externalPath == externalPath &&
other.id == id &&
other.inTimeline == inTimeline &&
other.isAdmin == isAdmin &&
@@ -105,7 +101,6 @@ class PartnerResponseDto {
(createdAt.hashCode) +
(deletedAt == null ? 0 : deletedAt!.hashCode) +
(email.hashCode) +
(externalPath == null ? 0 : externalPath!.hashCode) +
(id.hashCode) +
(inTimeline == null ? 0 : inTimeline!.hashCode) +
(isAdmin.hashCode) +
@@ -120,7 +115,7 @@ class PartnerResponseDto {
(updatedAt.hashCode);
@override
String toString() => 'PartnerResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, externalPath=$externalPath, id=$id, inTimeline=$inTimeline, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
String toString() => 'PartnerResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, id=$id, inTimeline=$inTimeline, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -132,11 +127,6 @@ class PartnerResponseDto {
// json[r'deletedAt'] = null;
}
json[r'email'] = this.email;
if (this.externalPath != null) {
json[r'externalPath'] = this.externalPath;
} else {
// json[r'externalPath'] = null;
}
json[r'id'] = this.id;
if (this.inTimeline != null) {
json[r'inTimeline'] = this.inTimeline;
@@ -184,7 +174,6 @@ class PartnerResponseDto {
createdAt: mapDateTime(json, r'createdAt', r'')!,
deletedAt: mapDateTime(json, r'deletedAt', r''),
email: mapValueOfType<String>(json, r'email')!,
externalPath: mapValueOfType<String>(json, r'externalPath'),
id: mapValueOfType<String>(json, r'id')!,
inTimeline: mapValueOfType<bool>(json, r'inTimeline'),
isAdmin: mapValueOfType<bool>(json, r'isAdmin')!,
@@ -248,7 +237,6 @@ class PartnerResponseDto {
'createdAt',
'deletedAt',
'email',
'externalPath',
'id',
'isAdmin',
'name',

View File

@@ -15,7 +15,6 @@ class UpdateUserDto {
UpdateUserDto({
this.avatarColor,
this.email,
this.externalPath,
required this.id,
this.isAdmin,
this.memoriesEnabled,
@@ -42,14 +41,6 @@ class UpdateUserDto {
///
String? email;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? externalPath;
String id;
///
@@ -106,7 +97,6 @@ class UpdateUserDto {
bool operator ==(Object other) => identical(this, other) || other is UpdateUserDto &&
other.avatarColor == avatarColor &&
other.email == email &&
other.externalPath == externalPath &&
other.id == id &&
other.isAdmin == isAdmin &&
other.memoriesEnabled == memoriesEnabled &&
@@ -121,7 +111,6 @@ class UpdateUserDto {
// ignore: unnecessary_parenthesis
(avatarColor == null ? 0 : avatarColor!.hashCode) +
(email == null ? 0 : email!.hashCode) +
(externalPath == null ? 0 : externalPath!.hashCode) +
(id.hashCode) +
(isAdmin == null ? 0 : isAdmin!.hashCode) +
(memoriesEnabled == null ? 0 : memoriesEnabled!.hashCode) +
@@ -132,7 +121,7 @@ class UpdateUserDto {
(storageLabel == null ? 0 : storageLabel!.hashCode);
@override
String toString() => 'UpdateUserDto[avatarColor=$avatarColor, email=$email, externalPath=$externalPath, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
String toString() => 'UpdateUserDto[avatarColor=$avatarColor, email=$email, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -145,11 +134,6 @@ class UpdateUserDto {
json[r'email'] = this.email;
} else {
// json[r'email'] = null;
}
if (this.externalPath != null) {
json[r'externalPath'] = this.externalPath;
} else {
// json[r'externalPath'] = null;
}
json[r'id'] = this.id;
if (this.isAdmin != null) {
@@ -200,7 +184,6 @@ class UpdateUserDto {
return UpdateUserDto(
avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']),
email: mapValueOfType<String>(json, r'email'),
externalPath: mapValueOfType<String>(json, r'externalPath'),
id: mapValueOfType<String>(json, r'id')!,
isAdmin: mapValueOfType<bool>(json, r'isAdmin'),
memoriesEnabled: mapValueOfType<bool>(json, r'memoriesEnabled'),

View File

@@ -17,7 +17,6 @@ class UserResponseDto {
required this.createdAt,
required this.deletedAt,
required this.email,
required this.externalPath,
required this.id,
required this.isAdmin,
this.memoriesEnabled,
@@ -39,8 +38,6 @@ class UserResponseDto {
String email;
String? externalPath;
String id;
bool isAdmin;
@@ -75,7 +72,6 @@ class UserResponseDto {
other.createdAt == createdAt &&
other.deletedAt == deletedAt &&
other.email == email &&
other.externalPath == externalPath &&
other.id == id &&
other.isAdmin == isAdmin &&
other.memoriesEnabled == memoriesEnabled &&
@@ -95,7 +91,6 @@ class UserResponseDto {
(createdAt.hashCode) +
(deletedAt == null ? 0 : deletedAt!.hashCode) +
(email.hashCode) +
(externalPath == null ? 0 : externalPath!.hashCode) +
(id.hashCode) +
(isAdmin.hashCode) +
(memoriesEnabled == null ? 0 : memoriesEnabled!.hashCode) +
@@ -109,7 +104,7 @@ class UserResponseDto {
(updatedAt.hashCode);
@override
String toString() => 'UserResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, externalPath=$externalPath, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
String toString() => 'UserResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -121,11 +116,6 @@ class UserResponseDto {
// json[r'deletedAt'] = null;
}
json[r'email'] = this.email;
if (this.externalPath != null) {
json[r'externalPath'] = this.externalPath;
} else {
// json[r'externalPath'] = null;
}
json[r'id'] = this.id;
json[r'isAdmin'] = this.isAdmin;
if (this.memoriesEnabled != null) {
@@ -168,7 +158,6 @@ class UserResponseDto {
createdAt: mapDateTime(json, r'createdAt', r'')!,
deletedAt: mapDateTime(json, r'deletedAt', r''),
email: mapValueOfType<String>(json, r'email')!,
externalPath: mapValueOfType<String>(json, r'externalPath'),
id: mapValueOfType<String>(json, r'id')!,
isAdmin: mapValueOfType<bool>(json, r'isAdmin')!,
memoriesEnabled: mapValueOfType<bool>(json, r'memoriesEnabled'),
@@ -231,7 +220,6 @@ class UserResponseDto {
'createdAt',
'deletedAt',
'email',
'externalPath',
'id',
'isAdmin',
'name',