martabal 1 tahun lalu
induk
melakukan
40c1bfa27b
75 mengubah file dengan 1405 tambahan dan 1445 penghapusan
  1. 310 345
      cli/src/api/open-api/api.ts
  2. 2 1
      mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
  3. 2 2
      mobile/lib/modules/login/services/oauth.service.dart
  4. 1 1
      mobile/lib/modules/login/ui/login_form.dart
  5. 2 2
      mobile/lib/shared/providers/server_info.provider.dart
  6. 20 20
      mobile/openapi/README.md
  7. 25 25
      mobile/openapi/doc/APIKeyApi.md
  8. 84 84
      mobile/openapi/doc/AssetApi.md
  9. 42 42
      mobile/openapi/doc/AuthenticationApi.md
  10. 5 5
      mobile/openapi/doc/LibraryApi.md
  11. 67 67
      mobile/openapi/doc/OAuthApi.md
  12. 27 27
      mobile/openapi/doc/ServerInfoApi.md
  13. 5 5
      mobile/openapi/doc/SystemConfigApi.md
  14. 15 15
      mobile/openapi/lib/api/api_key_api.dart
  15. 119 119
      mobile/openapi/lib/api/asset_api.dart
  16. 47 47
      mobile/openapi/lib/api/authentication_api.dart
  17. 3 3
      mobile/openapi/lib/api/library_api.dart
  18. 62 62
      mobile/openapi/lib/api/o_auth_api.dart
  19. 12 12
      mobile/openapi/lib/api/server_info_api.dart
  20. 3 3
      mobile/openapi/lib/api/system_config_api.dart
  21. 10 10
      mobile/openapi/test/api_key_api_test.dart
  22. 9 9
      mobile/openapi/test/asset_api_test.dart
  23. 5 5
      mobile/openapi/test/authentication_api_test.dart
  24. 2 2
      mobile/openapi/test/library_api_test.dart
  25. 14 14
      mobile/openapi/test/o_auth_api_test.dart
  26. 4 4
      mobile/openapi/test/server_info_api_test.dart
  27. 2 2
      mobile/openapi/test/system_config_api_test.dart
  28. 19 19
      server/immich-openapi-specs.json
  29. 10 10
      server/src/domain/asset/asset.service.spec.ts
  30. 2 2
      server/src/domain/asset/asset.service.ts
  31. 2 7
      server/src/domain/auth/auth.service.ts
  32. 1 1
      server/src/domain/repositories/asset.repository.ts
  33. 1 1
      server/src/domain/server-info/server-info.service.spec.ts
  34. 1 1
      server/src/domain/server-info/server-info.service.ts
  35. 32 42
      server/src/domain/user/user.core.ts
  36. 2 2
      server/src/immich/api-v1/asset/asset.controller.ts
  37. 4 5
      server/src/immich/app.module.ts
  38. 7 0
      server/src/immich/app.utils.ts
  39. 5 5
      server/src/immich/controllers/api-key.controller.ts
  40. 5 4
      server/src/immich/controllers/asset.controller.ts
  41. 1 1
      server/src/immich/controllers/auth.controller.ts
  42. 1 1
      server/src/immich/controllers/library.controller.ts
  43. 6 6
      server/src/immich/controllers/oauth.controller.ts
  44. 3 3
      server/src/immich/controllers/server-info.controller.ts
  45. 1 1
      server/src/immich/controllers/system-config.controller.ts
  46. 1 1
      server/src/immich/controllers/user.controller.ts
  47. 32 0
      server/src/immich/interceptors/error.interceptor.ts
  48. 1 1
      server/src/immich/interceptors/file.interceptor.ts
  49. 2 0
      server/src/immich/interceptors/index.ts
  50. 1 1
      server/src/infra/repositories/asset.repository.ts
  51. 4 4
      server/test/e2e/server-info.e2e-spec.ts
  52. 1 1
      server/test/repositories/asset.repository.mock.ts
  53. 310 345
      web/src/api/open-api/api.ts
  54. 4 8
      web/src/api/utils.ts
  55. 2 2
      web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte
  56. 2 2
      web/src/lib/components/admin-page/settings/job-settings/job-settings.svelte
  57. 2 2
      web/src/lib/components/admin-page/settings/library-settings/library-settings.svelte
  58. 1 1
      web/src/lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte
  59. 2 2
      web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte
  60. 2 2
      web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte
  61. 2 2
      web/src/lib/components/admin-page/settings/oauth/oauth-settings.svelte
  62. 2 2
      web/src/lib/components/admin-page/settings/password-login/password-login-settings.svelte
  63. 2 2
      web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte
  64. 2 2
      web/src/lib/components/admin-page/settings/theme/theme-settings.svelte
  65. 2 2
      web/src/lib/components/admin-page/settings/thumbnail/thumbnail-settings.svelte
  66. 2 2
      web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte
  67. 2 3
      web/src/lib/components/asset-viewer/asset-viewer.svelte
  68. 1 1
      web/src/lib/components/forms/admin-registration-form.svelte
  69. 3 3
      web/src/lib/components/shared-components/side-bar/side-bar.svelte
  70. 1 1
      web/src/lib/components/user-settings-page/library-list.svelte
  71. 4 4
      web/src/lib/components/user-settings-page/user-api-key-list.svelte
  72. 10 2
      web/src/lib/stores/assets.store.ts
  73. 1 1
      web/src/routes/(user)/user-settings/+page.server.ts
  74. 1 1
      web/src/routes/admin/server-status/+page.server.ts
  75. 1 1
      web/src/routes/admin/server-status/+page.svelte

File diff ditekan karena terlalu besar
+ 310 - 345
cli/src/api/open-api/api.ts


+ 2 - 1
mobile/lib/modules/asset_viewer/views/gallery_viewer.dart

@@ -443,7 +443,8 @@ class GalleryViewerPage extends HookConsumerWidget {
                 decoration: BoxDecoration(
                   color: Colors.white,
                   borderRadius: BorderRadius.circular(6),
-                  border: index == stackIndex.value
+                  border: (stackIndex.value == -1 && index == 0) ||
+                          index == stackIndex.value
                       ? Border.all(
                           color: Colors.white,
                           width: 2,

+ 2 - 2
mobile/lib/modules/login/services/oauth.service.dart

@@ -17,7 +17,7 @@ class OAuthService {
     // Resolve API server endpoint from user provided serverUrl
     await _apiService.resolveAndSetEndpoint(serverUrl);
 
-    return await _apiService.oAuthApi.generateConfig(
+    return await _apiService.oAuthApi.generateOAuthConfig(
       OAuthConfigDto(redirectUri: '$callbackUrlScheme:/'),
     );
   }
@@ -29,7 +29,7 @@ class OAuthService {
         callbackUrlScheme: callbackUrlScheme,
       );
 
-      return await _apiService.oAuthApi.callback(
+      return await _apiService.oAuthApi.finishOAuth(
         OAuthCallbackDto(
           url: result,
         ),

+ 1 - 1
mobile/lib/modules/login/ui/login_form.dart

@@ -65,7 +65,7 @@ class LoginForm extends HookConsumerWidget {
         isLoadingServer.value = true;
         final endpoint = await apiService.resolveAndSetEndpoint(serverUrl);
 
-        final loginConfig = await apiService.oAuthApi.generateConfig(
+        final loginConfig = await apiService.oAuthApi.generateOAuthConfig(
           OAuthConfigDto(redirectUri: serverUrl),
         );
 

+ 2 - 2
mobile/lib/shared/providers/server_info.provider.dart

@@ -66,7 +66,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
       state = state.copyWith(
         isVersionMismatch: true,
         versionMismatchErrorMessage:
-            "Server is out of date in major version. Some functionalities might not work correctly. Download and rebuild server",
+            "Server is out of date. Please update to the latest major version.",
       );
 
       return;
@@ -76,7 +76,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
       state = state.copyWith(
         isVersionMismatch: true,
         versionMismatchErrorMessage:
-            "Server is out of date in minor version. Some functionalities might not work correctly. Consider download and rebuild server",
+            "Server is out of date. Consider updating to the latest minor version.",
       );
 
       return;

+ 20 - 20
mobile/openapi/README.md

@@ -58,10 +58,10 @@ final api_instance = APIKeyApi();
 final aPIKeyCreateDto = APIKeyCreateDto(); // APIKeyCreateDto | 
 
 try {
-    final result = api_instance.createKey(aPIKeyCreateDto);
+    final result = api_instance.createApiKey(aPIKeyCreateDto);
     print(result);
 } catch (e) {
-    print('Exception when calling APIKeyApi->createKey: $e\n');
+    print('Exception when calling APIKeyApi->createApiKey: $e\n');
 }
 
 ```
@@ -72,11 +72,11 @@ All URIs are relative to */api*
 
 Class | Method | HTTP request | Description
 ------------ | ------------- | ------------- | -------------
-*APIKeyApi* | [**createKey**](doc//APIKeyApi.md#createkey) | **POST** /api-key | 
-*APIKeyApi* | [**deleteKey**](doc//APIKeyApi.md#deletekey) | **DELETE** /api-key/{id} | 
-*APIKeyApi* | [**getKey**](doc//APIKeyApi.md#getkey) | **GET** /api-key/{id} | 
-*APIKeyApi* | [**getKeys**](doc//APIKeyApi.md#getkeys) | **GET** /api-key | 
-*APIKeyApi* | [**updateKey**](doc//APIKeyApi.md#updatekey) | **PUT** /api-key/{id} | 
+*APIKeyApi* | [**createApiKey**](doc//APIKeyApi.md#createapikey) | **POST** /api-key | 
+*APIKeyApi* | [**deleteApiKey**](doc//APIKeyApi.md#deleteapikey) | **DELETE** /api-key/{id} | 
+*APIKeyApi* | [**getApiKey**](doc//APIKeyApi.md#getapikey) | **GET** /api-key/{id} | 
+*APIKeyApi* | [**getApiKeys**](doc//APIKeyApi.md#getapikeys) | **GET** /api-key | 
+*APIKeyApi* | [**updateApiKey**](doc//APIKeyApi.md#updateapikey) | **PUT** /api-key/{id} | 
 *ActivityApi* | [**createActivity**](doc//ActivityApi.md#createactivity) | **POST** /activity | 
 *ActivityApi* | [**deleteActivity**](doc//ActivityApi.md#deleteactivity) | **DELETE** /activity/{id} | 
 *ActivityApi* | [**getActivities**](doc//ActivityApi.md#getactivities) | **GET** /activity | 
@@ -91,7 +91,7 @@ Class | Method | HTTP request | Description
 *AlbumApi* | [**removeAssetFromAlbum**](doc//AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{id}/assets | 
 *AlbumApi* | [**removeUserFromAlbum**](doc//AlbumApi.md#removeuserfromalbum) | **DELETE** /album/{id}/user/{userId} | 
 *AlbumApi* | [**updateAlbumInfo**](doc//AlbumApi.md#updatealbuminfo) | **PATCH** /album/{id} | 
-*AssetApi* | [**bulkUploadCheck**](doc//AssetApi.md#bulkuploadcheck) | **POST** /asset/bulk-upload-check | 
+*AssetApi* | [**checkBulkUpload**](doc//AssetApi.md#checkbulkupload) | **POST** /asset/bulk-upload-check | 
 *AssetApi* | [**checkExistingAssets**](doc//AssetApi.md#checkexistingassets) | **POST** /asset/exist | 
 *AssetApi* | [**deleteAssets**](doc//AssetApi.md#deleteassets) | **DELETE** /asset | 
 *AssetApi* | [**downloadArchive**](doc//AssetApi.md#downloadarchive) | **POST** /asset/download/archive | 
@@ -100,15 +100,15 @@ Class | Method | HTTP request | Description
 *AssetApi* | [**getAllAssets**](doc//AssetApi.md#getallassets) | **GET** /asset | 
 *AssetApi* | [**getAssetById**](doc//AssetApi.md#getassetbyid) | **GET** /asset/assetById/{id} | 
 *AssetApi* | [**getAssetSearchTerms**](doc//AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms | 
-*AssetApi* | [**getAssetStats**](doc//AssetApi.md#getassetstats) | **GET** /asset/statistics | 
+*AssetApi* | [**getAssetStatistics**](doc//AssetApi.md#getassetstatistics) | **GET** /asset/statistics | 
 *AssetApi* | [**getAssetThumbnail**](doc//AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{id} | 
-*AssetApi* | [**getByTimeBucket**](doc//AssetApi.md#getbytimebucket) | **GET** /asset/time-bucket | 
 *AssetApi* | [**getCuratedLocations**](doc//AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations | 
 *AssetApi* | [**getCuratedObjects**](doc//AssetApi.md#getcuratedobjects) | **GET** /asset/curated-objects | 
 *AssetApi* | [**getDownloadInfo**](doc//AssetApi.md#getdownloadinfo) | **POST** /asset/download/info | 
 *AssetApi* | [**getMapMarkers**](doc//AssetApi.md#getmapmarkers) | **GET** /asset/map-marker | 
 *AssetApi* | [**getMemoryLane**](doc//AssetApi.md#getmemorylane) | **GET** /asset/memory-lane | 
 *AssetApi* | [**getRandom**](doc//AssetApi.md#getrandom) | **GET** /asset/random | 
+*AssetApi* | [**getTimeBucket**](doc//AssetApi.md#gettimebucket) | **GET** /asset/time-bucket | 
 *AssetApi* | [**getTimeBuckets**](doc//AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets | 
 *AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | 
 *AssetApi* | [**importFile**](doc//AssetApi.md#importfile) | **POST** /asset/import | 
@@ -125,30 +125,30 @@ Class | Method | HTTP request | Description
 *AuditApi* | [**getAuditDeletes**](doc//AuditApi.md#getauditdeletes) | **GET** /audit/deletes | 
 *AuditApi* | [**getAuditFiles**](doc//AuditApi.md#getauditfiles) | **GET** /audit/file-report | 
 *AuditApi* | [**getFileChecksums**](doc//AuditApi.md#getfilechecksums) | **POST** /audit/file-report/checksum | 
-*AuthenticationApi* | [**adminSignUp**](doc//AuthenticationApi.md#adminsignup) | **POST** /auth/admin-sign-up | 
 *AuthenticationApi* | [**changePassword**](doc//AuthenticationApi.md#changepassword) | **POST** /auth/change-password | 
 *AuthenticationApi* | [**getAuthDevices**](doc//AuthenticationApi.md#getauthdevices) | **GET** /auth/devices | 
 *AuthenticationApi* | [**login**](doc//AuthenticationApi.md#login) | **POST** /auth/login | 
 *AuthenticationApi* | [**logout**](doc//AuthenticationApi.md#logout) | **POST** /auth/logout | 
 *AuthenticationApi* | [**logoutAuthDevice**](doc//AuthenticationApi.md#logoutauthdevice) | **DELETE** /auth/devices/{id} | 
 *AuthenticationApi* | [**logoutAuthDevices**](doc//AuthenticationApi.md#logoutauthdevices) | **DELETE** /auth/devices | 
+*AuthenticationApi* | [**signUpAdmin**](doc//AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up | 
 *AuthenticationApi* | [**validateAccessToken**](doc//AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken | 
 *JobApi* | [**getAllJobsStatus**](doc//JobApi.md#getalljobsstatus) | **GET** /jobs | 
 *JobApi* | [**sendJobCommand**](doc//JobApi.md#sendjobcommand) | **PUT** /jobs/{id} | 
 *LibraryApi* | [**createLibrary**](doc//LibraryApi.md#createlibrary) | **POST** /library | 
 *LibraryApi* | [**deleteLibrary**](doc//LibraryApi.md#deletelibrary) | **DELETE** /library/{id} | 
-*LibraryApi* | [**getAllForUser**](doc//LibraryApi.md#getallforuser) | **GET** /library | 
+*LibraryApi* | [**getLibraries**](doc//LibraryApi.md#getlibraries) | **GET** /library | 
 *LibraryApi* | [**getLibraryInfo**](doc//LibraryApi.md#getlibraryinfo) | **GET** /library/{id} | 
 *LibraryApi* | [**getLibraryStatistics**](doc//LibraryApi.md#getlibrarystatistics) | **GET** /library/{id}/statistics | 
 *LibraryApi* | [**removeOfflineFiles**](doc//LibraryApi.md#removeofflinefiles) | **POST** /library/{id}/removeOffline | 
 *LibraryApi* | [**scanLibrary**](doc//LibraryApi.md#scanlibrary) | **POST** /library/{id}/scan | 
 *LibraryApi* | [**updateLibrary**](doc//LibraryApi.md#updatelibrary) | **PUT** /library/{id} | 
-*OAuthApi* | [**authorizeOAuth**](doc//OAuthApi.md#authorizeoauth) | **POST** /oauth/authorize | 
-*OAuthApi* | [**callback**](doc//OAuthApi.md#callback) | **POST** /oauth/callback | 
-*OAuthApi* | [**generateConfig**](doc//OAuthApi.md#generateconfig) | **POST** /oauth/config | 
-*OAuthApi* | [**link**](doc//OAuthApi.md#link) | **POST** /oauth/link | 
-*OAuthApi* | [**mobileRedirect**](doc//OAuthApi.md#mobileredirect) | **GET** /oauth/mobile-redirect | 
-*OAuthApi* | [**unlink**](doc//OAuthApi.md#unlink) | **POST** /oauth/unlink | 
+*OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback | 
+*OAuthApi* | [**generateOAuthConfig**](doc//OAuthApi.md#generateoauthconfig) | **POST** /oauth/config | 
+*OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link | 
+*OAuthApi* | [**redirectOAuthToMobile**](doc//OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect | 
+*OAuthApi* | [**startOAuth**](doc//OAuthApi.md#startoauth) | **POST** /oauth/authorize | 
+*OAuthApi* | [**unlinkOAuthAccount**](doc//OAuthApi.md#unlinkoauthaccount) | **POST** /oauth/unlink | 
 *PartnerApi* | [**createPartner**](doc//PartnerApi.md#createpartner) | **POST** /partner/{id} | 
 *PartnerApi* | [**getPartners**](doc//PartnerApi.md#getpartners) | **GET** /partner | 
 *PartnerApi* | [**removePartner**](doc//PartnerApi.md#removepartner) | **DELETE** /partner/{id} | 
@@ -166,8 +166,8 @@ Class | Method | HTTP request | Description
 *ServerInfoApi* | [**getServerConfig**](doc//ServerInfoApi.md#getserverconfig) | **GET** /server-info/config | 
 *ServerInfoApi* | [**getServerFeatures**](doc//ServerInfoApi.md#getserverfeatures) | **GET** /server-info/features | 
 *ServerInfoApi* | [**getServerInfo**](doc//ServerInfoApi.md#getserverinfo) | **GET** /server-info | 
+*ServerInfoApi* | [**getServerStatistics**](doc//ServerInfoApi.md#getserverstatistics) | **GET** /server-info/statistics | 
 *ServerInfoApi* | [**getServerVersion**](doc//ServerInfoApi.md#getserverversion) | **GET** /server-info/version | 
-*ServerInfoApi* | [**getStats**](doc//ServerInfoApi.md#getstats) | **GET** /server-info/stats | 
 *ServerInfoApi* | [**getSupportedMediaTypes**](doc//ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types | 
 *ServerInfoApi* | [**getTheme**](doc//ServerInfoApi.md#gettheme) | **GET** /server-info/theme | 
 *ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping | 
@@ -180,7 +180,7 @@ Class | Method | HTTP request | Description
 *SharedLinkApi* | [**removeSharedLinkAssets**](doc//SharedLinkApi.md#removesharedlinkassets) | **DELETE** /shared-link/{id}/assets | 
 *SharedLinkApi* | [**updateSharedLink**](doc//SharedLinkApi.md#updatesharedlink) | **PATCH** /shared-link/{id} | 
 *SystemConfigApi* | [**getConfig**](doc//SystemConfigApi.md#getconfig) | **GET** /system-config | 
-*SystemConfigApi* | [**getDefaults**](doc//SystemConfigApi.md#getdefaults) | **GET** /system-config/defaults | 
+*SystemConfigApi* | [**getConfigDefaults**](doc//SystemConfigApi.md#getconfigdefaults) | **GET** /system-config/defaults | 
 *SystemConfigApi* | [**getStorageTemplateOptions**](doc//SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options | 
 *SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config | 
 *TagApi* | [**createTag**](doc//TagApi.md#createtag) | **POST** /tag | 

+ 25 - 25
mobile/openapi/doc/APIKeyApi.md

@@ -9,15 +9,15 @@ All URIs are relative to */api*
 
 Method | HTTP request | Description
 ------------- | ------------- | -------------
-[**createKey**](APIKeyApi.md#createkey) | **POST** /api-key | 
-[**deleteKey**](APIKeyApi.md#deletekey) | **DELETE** /api-key/{id} | 
-[**getKey**](APIKeyApi.md#getkey) | **GET** /api-key/{id} | 
-[**getKeys**](APIKeyApi.md#getkeys) | **GET** /api-key | 
-[**updateKey**](APIKeyApi.md#updatekey) | **PUT** /api-key/{id} | 
+[**createApiKey**](APIKeyApi.md#createapikey) | **POST** /api-key | 
+[**deleteApiKey**](APIKeyApi.md#deleteapikey) | **DELETE** /api-key/{id} | 
+[**getApiKey**](APIKeyApi.md#getapikey) | **GET** /api-key/{id} | 
+[**getApiKeys**](APIKeyApi.md#getapikeys) | **GET** /api-key | 
+[**updateApiKey**](APIKeyApi.md#updateapikey) | **PUT** /api-key/{id} | 
 
 
-# **createKey**
-> APIKeyCreateResponseDto createKey(aPIKeyCreateDto)
+# **createApiKey**
+> APIKeyCreateResponseDto createApiKey(aPIKeyCreateDto)
 
 
 
@@ -43,10 +43,10 @@ final api_instance = APIKeyApi();
 final aPIKeyCreateDto = APIKeyCreateDto(); // APIKeyCreateDto | 
 
 try {
-    final result = api_instance.createKey(aPIKeyCreateDto);
+    final result = api_instance.createApiKey(aPIKeyCreateDto);
     print(result);
 } catch (e) {
-    print('Exception when calling APIKeyApi->createKey: $e\n');
+    print('Exception when calling APIKeyApi->createApiKey: $e\n');
 }
 ```
 
@@ -71,8 +71,8 @@ Name | Type | Description  | Notes
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **deleteKey**
-> deleteKey(id)
+# **deleteApiKey**
+> deleteApiKey(id)
 
 
 
@@ -98,9 +98,9 @@ final api_instance = APIKeyApi();
 final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
 
 try {
-    api_instance.deleteKey(id);
+    api_instance.deleteApiKey(id);
 } catch (e) {
-    print('Exception when calling APIKeyApi->deleteKey: $e\n');
+    print('Exception when calling APIKeyApi->deleteApiKey: $e\n');
 }
 ```
 
@@ -125,8 +125,8 @@ void (empty response body)
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getKey**
-> APIKeyResponseDto getKey(id)
+# **getApiKey**
+> APIKeyResponseDto getApiKey(id)
 
 
 
@@ -152,10 +152,10 @@ final api_instance = APIKeyApi();
 final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
 
 try {
-    final result = api_instance.getKey(id);
+    final result = api_instance.getApiKey(id);
     print(result);
 } catch (e) {
-    print('Exception when calling APIKeyApi->getKey: $e\n');
+    print('Exception when calling APIKeyApi->getApiKey: $e\n');
 }
 ```
 
@@ -180,8 +180,8 @@ Name | Type | Description  | Notes
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getKeys**
-> List<APIKeyResponseDto> getKeys()
+# **getApiKeys**
+> List<APIKeyResponseDto> getApiKeys()
 
 
 
@@ -206,10 +206,10 @@ import 'package:openapi/api.dart';
 final api_instance = APIKeyApi();
 
 try {
-    final result = api_instance.getKeys();
+    final result = api_instance.getApiKeys();
     print(result);
 } catch (e) {
-    print('Exception when calling APIKeyApi->getKeys: $e\n');
+    print('Exception when calling APIKeyApi->getApiKeys: $e\n');
 }
 ```
 
@@ -231,8 +231,8 @@ This endpoint does not need any parameter.
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **updateKey**
-> APIKeyResponseDto updateKey(id, aPIKeyUpdateDto)
+# **updateApiKey**
+> APIKeyResponseDto updateApiKey(id, aPIKeyUpdateDto)
 
 
 
@@ -259,10 +259,10 @@ final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
 final aPIKeyUpdateDto = APIKeyUpdateDto(); // APIKeyUpdateDto | 
 
 try {
-    final result = api_instance.updateKey(id, aPIKeyUpdateDto);
+    final result = api_instance.updateApiKey(id, aPIKeyUpdateDto);
     print(result);
 } catch (e) {
-    print('Exception when calling APIKeyApi->updateKey: $e\n');
+    print('Exception when calling APIKeyApi->updateApiKey: $e\n');
 }
 ```
 

+ 84 - 84
mobile/openapi/doc/AssetApi.md

@@ -9,7 +9,7 @@ All URIs are relative to */api*
 
 Method | HTTP request | Description
 ------------- | ------------- | -------------
-[**bulkUploadCheck**](AssetApi.md#bulkuploadcheck) | **POST** /asset/bulk-upload-check | 
+[**checkBulkUpload**](AssetApi.md#checkbulkupload) | **POST** /asset/bulk-upload-check | 
 [**checkExistingAssets**](AssetApi.md#checkexistingassets) | **POST** /asset/exist | 
 [**deleteAssets**](AssetApi.md#deleteassets) | **DELETE** /asset | 
 [**downloadArchive**](AssetApi.md#downloadarchive) | **POST** /asset/download/archive | 
@@ -18,15 +18,15 @@ Method | HTTP request | Description
 [**getAllAssets**](AssetApi.md#getallassets) | **GET** /asset | 
 [**getAssetById**](AssetApi.md#getassetbyid) | **GET** /asset/assetById/{id} | 
 [**getAssetSearchTerms**](AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms | 
-[**getAssetStats**](AssetApi.md#getassetstats) | **GET** /asset/statistics | 
+[**getAssetStatistics**](AssetApi.md#getassetstatistics) | **GET** /asset/statistics | 
 [**getAssetThumbnail**](AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{id} | 
-[**getByTimeBucket**](AssetApi.md#getbytimebucket) | **GET** /asset/time-bucket | 
 [**getCuratedLocations**](AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations | 
 [**getCuratedObjects**](AssetApi.md#getcuratedobjects) | **GET** /asset/curated-objects | 
 [**getDownloadInfo**](AssetApi.md#getdownloadinfo) | **POST** /asset/download/info | 
 [**getMapMarkers**](AssetApi.md#getmapmarkers) | **GET** /asset/map-marker | 
 [**getMemoryLane**](AssetApi.md#getmemorylane) | **GET** /asset/memory-lane | 
 [**getRandom**](AssetApi.md#getrandom) | **GET** /asset/random | 
+[**getTimeBucket**](AssetApi.md#gettimebucket) | **GET** /asset/time-bucket | 
 [**getTimeBuckets**](AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets | 
 [**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | 
 [**importFile**](AssetApi.md#importfile) | **POST** /asset/import | 
@@ -41,8 +41,8 @@ Method | HTTP request | Description
 [**uploadFile**](AssetApi.md#uploadfile) | **POST** /asset/upload | 
 
 
-# **bulkUploadCheck**
-> AssetBulkUploadCheckResponseDto bulkUploadCheck(assetBulkUploadCheckDto)
+# **checkBulkUpload**
+> AssetBulkUploadCheckResponseDto checkBulkUpload(assetBulkUploadCheckDto)
 
 
 
@@ -70,10 +70,10 @@ final api_instance = AssetApi();
 final assetBulkUploadCheckDto = AssetBulkUploadCheckDto(); // AssetBulkUploadCheckDto | 
 
 try {
-    final result = api_instance.bulkUploadCheck(assetBulkUploadCheckDto);
+    final result = api_instance.checkBulkUpload(assetBulkUploadCheckDto);
     print(result);
 } catch (e) {
-    print('Exception when calling AssetApi->bulkUploadCheck: $e\n');
+    print('Exception when calling AssetApi->checkBulkUpload: $e\n');
 }
 ```
 
@@ -550,8 +550,8 @@ This endpoint does not need any parameter.
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getAssetStats**
-> AssetStatsResponseDto getAssetStats(isArchived, isFavorite, isTrashed)
+# **getAssetStatistics**
+> AssetStatsResponseDto getAssetStatistics(isArchived, isFavorite, isTrashed)
 
 
 
@@ -579,10 +579,10 @@ final isFavorite = true; // bool |
 final isTrashed = true; // bool | 
 
 try {
-    final result = api_instance.getAssetStats(isArchived, isFavorite, isTrashed);
+    final result = api_instance.getAssetStatistics(isArchived, isFavorite, isTrashed);
     print(result);
 } catch (e) {
-    print('Exception when calling AssetApi->getAssetStats: $e\n');
+    print('Exception when calling AssetApi->getAssetStatistics: $e\n');
 }
 ```
 
@@ -668,79 +668,6 @@ Name | Type | Description  | Notes
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getByTimeBucket**
-> List<AssetResponseDto> getByTimeBucket(size, timeBucket, userId, albumId, personId, isArchived, isFavorite, isTrashed, withStacked, key)
-
-
-
-### Example
-```dart
-import 'package:openapi/api.dart';
-// TODO Configure API key authorization: cookie
-//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
-// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
-//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
-// TODO Configure API key authorization: api_key
-//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
-// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
-//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
-// TODO Configure HTTP Bearer authorization: bearer
-// Case 1. Use String Token
-//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
-// Case 2. Use Function which generate token.
-// String yourTokenGeneratorFunction() { ... }
-//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
-
-final api_instance = AssetApi();
-final size = ; // TimeBucketSize | 
-final timeBucket = timeBucket_example; // String | 
-final userId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
-final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
-final personId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
-final isArchived = true; // bool | 
-final isFavorite = true; // bool | 
-final isTrashed = true; // bool | 
-final withStacked = true; // bool | 
-final key = key_example; // String | 
-
-try {
-    final result = api_instance.getByTimeBucket(size, timeBucket, userId, albumId, personId, isArchived, isFavorite, isTrashed, withStacked, key);
-    print(result);
-} catch (e) {
-    print('Exception when calling AssetApi->getByTimeBucket: $e\n');
-}
-```
-
-### Parameters
-
-Name | Type | Description  | Notes
-------------- | ------------- | ------------- | -------------
- **size** | [**TimeBucketSize**](.md)|  | 
- **timeBucket** | **String**|  | 
- **userId** | **String**|  | [optional] 
- **albumId** | **String**|  | [optional] 
- **personId** | **String**|  | [optional] 
- **isArchived** | **bool**|  | [optional] 
- **isFavorite** | **bool**|  | [optional] 
- **isTrashed** | **bool**|  | [optional] 
- **withStacked** | **bool**|  | [optional] 
- **key** | **String**|  | [optional] 
-
-### Return type
-
-[**List<AssetResponseDto>**](AssetResponseDto.md)
-
-### Authorization
-
-[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
-
-### HTTP request headers
-
- - **Content-Type**: Not defined
- - **Accept**: application/json
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
 # **getCuratedLocations**
 > List<CuratedLocationsResponseDto> getCuratedLocations()
 
@@ -1073,6 +1000,79 @@ Name | Type | Description  | Notes
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
+# **getTimeBucket**
+> List<AssetResponseDto> getTimeBucket(size, timeBucket, userId, albumId, personId, isArchived, isFavorite, isTrashed, withStacked, key)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure API key authorization: cookie
+//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
+// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
+//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
+// TODO Configure API key authorization: api_key
+//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
+// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
+//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
+// TODO Configure HTTP Bearer authorization: bearer
+// Case 1. Use String Token
+//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
+// Case 2. Use Function which generate token.
+// String yourTokenGeneratorFunction() { ... }
+//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
+
+final api_instance = AssetApi();
+final size = ; // TimeBucketSize | 
+final timeBucket = timeBucket_example; // String | 
+final userId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
+final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
+final personId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | 
+final isArchived = true; // bool | 
+final isFavorite = true; // bool | 
+final isTrashed = true; // bool | 
+final withStacked = true; // bool | 
+final key = key_example; // String | 
+
+try {
+    final result = api_instance.getTimeBucket(size, timeBucket, userId, albumId, personId, isArchived, isFavorite, isTrashed, withStacked, key);
+    print(result);
+} catch (e) {
+    print('Exception when calling AssetApi->getTimeBucket: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+ **size** | [**TimeBucketSize**](.md)|  | 
+ **timeBucket** | **String**|  | 
+ **userId** | **String**|  | [optional] 
+ **albumId** | **String**|  | [optional] 
+ **personId** | **String**|  | [optional] 
+ **isArchived** | **bool**|  | [optional] 
+ **isFavorite** | **bool**|  | [optional] 
+ **isTrashed** | **bool**|  | [optional] 
+ **withStacked** | **bool**|  | [optional] 
+ **key** | **String**|  | [optional] 
+
+### Return type
+
+[**List<AssetResponseDto>**](AssetResponseDto.md)
+
+### Authorization
+
+[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
 # **getTimeBuckets**
 > List<TimeBucketResponseDto> getTimeBuckets(size, userId, albumId, personId, isArchived, isFavorite, isTrashed, withStacked, key)
 

+ 42 - 42
mobile/openapi/doc/AuthenticationApi.md

@@ -9,57 +9,16 @@ All URIs are relative to */api*
 
 Method | HTTP request | Description
 ------------- | ------------- | -------------
-[**adminSignUp**](AuthenticationApi.md#adminsignup) | **POST** /auth/admin-sign-up | 
 [**changePassword**](AuthenticationApi.md#changepassword) | **POST** /auth/change-password | 
 [**getAuthDevices**](AuthenticationApi.md#getauthdevices) | **GET** /auth/devices | 
 [**login**](AuthenticationApi.md#login) | **POST** /auth/login | 
 [**logout**](AuthenticationApi.md#logout) | **POST** /auth/logout | 
 [**logoutAuthDevice**](AuthenticationApi.md#logoutauthdevice) | **DELETE** /auth/devices/{id} | 
 [**logoutAuthDevices**](AuthenticationApi.md#logoutauthdevices) | **DELETE** /auth/devices | 
+[**signUpAdmin**](AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up | 
 [**validateAccessToken**](AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken | 
 
 
-# **adminSignUp**
-> AdminSignupResponseDto adminSignUp(signUpDto)
-
-
-
-### Example
-```dart
-import 'package:openapi/api.dart';
-
-final api_instance = AuthenticationApi();
-final signUpDto = SignUpDto(); // SignUpDto | 
-
-try {
-    final result = api_instance.adminSignUp(signUpDto);
-    print(result);
-} catch (e) {
-    print('Exception when calling AuthenticationApi->adminSignUp: $e\n');
-}
-```
-
-### Parameters
-
-Name | Type | Description  | Notes
-------------- | ------------- | ------------- | -------------
- **signUpDto** | [**SignUpDto**](SignUpDto.md)|  | 
-
-### Return type
-
-[**AdminSignupResponseDto**](AdminSignupResponseDto.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
- - **Content-Type**: application/json
- - **Accept**: application/json
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
 # **changePassword**
 > UserResponseDto changePassword(changePasswordDto)
 
@@ -362,6 +321,47 @@ void (empty response body)
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
+# **signUpAdmin**
+> AdminSignupResponseDto signUpAdmin(signUpDto)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+
+final api_instance = AuthenticationApi();
+final signUpDto = SignUpDto(); // SignUpDto | 
+
+try {
+    final result = api_instance.signUpAdmin(signUpDto);
+    print(result);
+} catch (e) {
+    print('Exception when calling AuthenticationApi->signUpAdmin: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+ **signUpDto** | [**SignUpDto**](SignUpDto.md)|  | 
+
+### Return type
+
+[**AdminSignupResponseDto**](AdminSignupResponseDto.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
 # **validateAccessToken**
 > ValidateAccessTokenResponseDto validateAccessToken()
 

+ 5 - 5
mobile/openapi/doc/LibraryApi.md

@@ -11,7 +11,7 @@ Method | HTTP request | Description
 ------------- | ------------- | -------------
 [**createLibrary**](LibraryApi.md#createlibrary) | **POST** /library | 
 [**deleteLibrary**](LibraryApi.md#deletelibrary) | **DELETE** /library/{id} | 
-[**getAllForUser**](LibraryApi.md#getallforuser) | **GET** /library | 
+[**getLibraries**](LibraryApi.md#getlibraries) | **GET** /library | 
 [**getLibraryInfo**](LibraryApi.md#getlibraryinfo) | **GET** /library/{id} | 
 [**getLibraryStatistics**](LibraryApi.md#getlibrarystatistics) | **GET** /library/{id}/statistics | 
 [**removeOfflineFiles**](LibraryApi.md#removeofflinefiles) | **POST** /library/{id}/removeOffline | 
@@ -128,8 +128,8 @@ void (empty response body)
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getAllForUser**
-> List<LibraryResponseDto> getAllForUser()
+# **getLibraries**
+> List<LibraryResponseDto> getLibraries()
 
 
 
@@ -154,10 +154,10 @@ import 'package:openapi/api.dart';
 final api_instance = LibraryApi();
 
 try {
-    final result = api_instance.getAllForUser();
+    final result = api_instance.getLibraries();
     print(result);
 } catch (e) {
-    print('Exception when calling LibraryApi->getAllForUser: $e\n');
+    print('Exception when calling LibraryApi->getLibraries: $e\n');
 }
 ```
 

+ 67 - 67
mobile/openapi/doc/OAuthApi.md

@@ -9,57 +9,16 @@ All URIs are relative to */api*
 
 Method | HTTP request | Description
 ------------- | ------------- | -------------
-[**authorizeOAuth**](OAuthApi.md#authorizeoauth) | **POST** /oauth/authorize | 
-[**callback**](OAuthApi.md#callback) | **POST** /oauth/callback | 
-[**generateConfig**](OAuthApi.md#generateconfig) | **POST** /oauth/config | 
-[**link**](OAuthApi.md#link) | **POST** /oauth/link | 
-[**mobileRedirect**](OAuthApi.md#mobileredirect) | **GET** /oauth/mobile-redirect | 
-[**unlink**](OAuthApi.md#unlink) | **POST** /oauth/unlink | 
+[**finishOAuth**](OAuthApi.md#finishoauth) | **POST** /oauth/callback | 
+[**generateOAuthConfig**](OAuthApi.md#generateoauthconfig) | **POST** /oauth/config | 
+[**linkOAuthAccount**](OAuthApi.md#linkoauthaccount) | **POST** /oauth/link | 
+[**redirectOAuthToMobile**](OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect | 
+[**startOAuth**](OAuthApi.md#startoauth) | **POST** /oauth/authorize | 
+[**unlinkOAuthAccount**](OAuthApi.md#unlinkoauthaccount) | **POST** /oauth/unlink | 
 
 
-# **authorizeOAuth**
-> OAuthAuthorizeResponseDto authorizeOAuth(oAuthConfigDto)
-
-
-
-### Example
-```dart
-import 'package:openapi/api.dart';
-
-final api_instance = OAuthApi();
-final oAuthConfigDto = OAuthConfigDto(); // OAuthConfigDto | 
-
-try {
-    final result = api_instance.authorizeOAuth(oAuthConfigDto);
-    print(result);
-} catch (e) {
-    print('Exception when calling OAuthApi->authorizeOAuth: $e\n');
-}
-```
-
-### Parameters
-
-Name | Type | Description  | Notes
-------------- | ------------- | ------------- | -------------
- **oAuthConfigDto** | [**OAuthConfigDto**](OAuthConfigDto.md)|  | 
-
-### Return type
-
-[**OAuthAuthorizeResponseDto**](OAuthAuthorizeResponseDto.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
- - **Content-Type**: application/json
- - **Accept**: application/json
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **callback**
-> LoginResponseDto callback(oAuthCallbackDto)
+# **finishOAuth**
+> LoginResponseDto finishOAuth(oAuthCallbackDto)
 
 
 
@@ -71,10 +30,10 @@ final api_instance = OAuthApi();
 final oAuthCallbackDto = OAuthCallbackDto(); // OAuthCallbackDto | 
 
 try {
-    final result = api_instance.callback(oAuthCallbackDto);
+    final result = api_instance.finishOAuth(oAuthCallbackDto);
     print(result);
 } catch (e) {
-    print('Exception when calling OAuthApi->callback: $e\n');
+    print('Exception when calling OAuthApi->finishOAuth: $e\n');
 }
 ```
 
@@ -99,8 +58,8 @@ No authorization required
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **generateConfig**
-> OAuthConfigResponseDto generateConfig(oAuthConfigDto)
+# **generateOAuthConfig**
+> OAuthConfigResponseDto generateOAuthConfig(oAuthConfigDto)
 
 
 
@@ -114,10 +73,10 @@ final api_instance = OAuthApi();
 final oAuthConfigDto = OAuthConfigDto(); // OAuthConfigDto | 
 
 try {
-    final result = api_instance.generateConfig(oAuthConfigDto);
+    final result = api_instance.generateOAuthConfig(oAuthConfigDto);
     print(result);
 } catch (e) {
-    print('Exception when calling OAuthApi->generateConfig: $e\n');
+    print('Exception when calling OAuthApi->generateOAuthConfig: $e\n');
 }
 ```
 
@@ -142,8 +101,8 @@ No authorization required
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **link**
-> UserResponseDto link(oAuthCallbackDto)
+# **linkOAuthAccount**
+> UserResponseDto linkOAuthAccount(oAuthCallbackDto)
 
 
 
@@ -169,10 +128,10 @@ final api_instance = OAuthApi();
 final oAuthCallbackDto = OAuthCallbackDto(); // OAuthCallbackDto | 
 
 try {
-    final result = api_instance.link(oAuthCallbackDto);
+    final result = api_instance.linkOAuthAccount(oAuthCallbackDto);
     print(result);
 } catch (e) {
-    print('Exception when calling OAuthApi->link: $e\n');
+    print('Exception when calling OAuthApi->linkOAuthAccount: $e\n');
 }
 ```
 
@@ -197,8 +156,8 @@ Name | Type | Description  | Notes
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **mobileRedirect**
-> mobileRedirect()
+# **redirectOAuthToMobile**
+> redirectOAuthToMobile()
 
 
 
@@ -209,9 +168,9 @@ import 'package:openapi/api.dart';
 final api_instance = OAuthApi();
 
 try {
-    api_instance.mobileRedirect();
+    api_instance.redirectOAuthToMobile();
 } catch (e) {
-    print('Exception when calling OAuthApi->mobileRedirect: $e\n');
+    print('Exception when calling OAuthApi->redirectOAuthToMobile: $e\n');
 }
 ```
 
@@ -233,8 +192,49 @@ No authorization required
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **unlink**
-> UserResponseDto unlink()
+# **startOAuth**
+> OAuthAuthorizeResponseDto startOAuth(oAuthConfigDto)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+
+final api_instance = OAuthApi();
+final oAuthConfigDto = OAuthConfigDto(); // OAuthConfigDto | 
+
+try {
+    final result = api_instance.startOAuth(oAuthConfigDto);
+    print(result);
+} catch (e) {
+    print('Exception when calling OAuthApi->startOAuth: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+ **oAuthConfigDto** | [**OAuthConfigDto**](OAuthConfigDto.md)|  | 
+
+### Return type
+
+[**OAuthAuthorizeResponseDto**](OAuthAuthorizeResponseDto.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **unlinkOAuthAccount**
+> UserResponseDto unlinkOAuthAccount()
 
 
 
@@ -259,10 +259,10 @@ import 'package:openapi/api.dart';
 final api_instance = OAuthApi();
 
 try {
-    final result = api_instance.unlink();
+    final result = api_instance.unlinkOAuthAccount();
     print(result);
 } catch (e) {
-    print('Exception when calling OAuthApi->unlink: $e\n');
+    print('Exception when calling OAuthApi->unlinkOAuthAccount: $e\n');
 }
 ```
 

+ 27 - 27
mobile/openapi/doc/ServerInfoApi.md

@@ -12,8 +12,8 @@ Method | HTTP request | Description
 [**getServerConfig**](ServerInfoApi.md#getserverconfig) | **GET** /server-info/config | 
 [**getServerFeatures**](ServerInfoApi.md#getserverfeatures) | **GET** /server-info/features | 
 [**getServerInfo**](ServerInfoApi.md#getserverinfo) | **GET** /server-info | 
+[**getServerStatistics**](ServerInfoApi.md#getserverstatistics) | **GET** /server-info/statistics | 
 [**getServerVersion**](ServerInfoApi.md#getserverversion) | **GET** /server-info/version | 
-[**getStats**](ServerInfoApi.md#getstats) | **GET** /server-info/stats | 
 [**getSupportedMediaTypes**](ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types | 
 [**getTheme**](ServerInfoApi.md#gettheme) | **GET** /server-info/theme | 
 [**pingServer**](ServerInfoApi.md#pingserver) | **GET** /server-info/ping | 
@@ -144,22 +144,36 @@ This endpoint does not need any parameter.
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getServerVersion**
-> ServerVersionResponseDto getServerVersion()
+# **getServerStatistics**
+> ServerStatsResponseDto getServerStatistics()
 
 
 
 ### Example
 ```dart
 import 'package:openapi/api.dart';
+// TODO Configure API key authorization: cookie
+//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
+// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
+//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
+// TODO Configure API key authorization: api_key
+//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
+// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
+//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
+// TODO Configure HTTP Bearer authorization: bearer
+// Case 1. Use String Token
+//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
+// Case 2. Use Function which generate token.
+// String yourTokenGeneratorFunction() { ... }
+//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
 
 final api_instance = ServerInfoApi();
 
 try {
-    final result = api_instance.getServerVersion();
+    final result = api_instance.getServerStatistics();
     print(result);
 } catch (e) {
-    print('Exception when calling ServerInfoApi->getServerVersion: $e\n');
+    print('Exception when calling ServerInfoApi->getServerStatistics: $e\n');
 }
 ```
 
@@ -168,11 +182,11 @@ This endpoint does not need any parameter.
 
 ### Return type
 
-[**ServerVersionResponseDto**](ServerVersionResponseDto.md)
+[**ServerStatsResponseDto**](ServerStatsResponseDto.md)
 
 ### Authorization
 
-No authorization required
+[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
 
 ### HTTP request headers
 
@@ -181,36 +195,22 @@ No authorization required
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getStats**
-> ServerStatsResponseDto getStats()
+# **getServerVersion**
+> ServerVersionResponseDto getServerVersion()
 
 
 
 ### Example
 ```dart
 import 'package:openapi/api.dart';
-// TODO Configure API key authorization: cookie
-//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
-// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
-//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
-// TODO Configure API key authorization: api_key
-//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
-// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
-//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
-// TODO Configure HTTP Bearer authorization: bearer
-// Case 1. Use String Token
-//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
-// Case 2. Use Function which generate token.
-// String yourTokenGeneratorFunction() { ... }
-//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
 
 final api_instance = ServerInfoApi();
 
 try {
-    final result = api_instance.getStats();
+    final result = api_instance.getServerVersion();
     print(result);
 } catch (e) {
-    print('Exception when calling ServerInfoApi->getStats: $e\n');
+    print('Exception when calling ServerInfoApi->getServerVersion: $e\n');
 }
 ```
 
@@ -219,11 +219,11 @@ This endpoint does not need any parameter.
 
 ### Return type
 
-[**ServerStatsResponseDto**](ServerStatsResponseDto.md)
+[**ServerVersionResponseDto**](ServerVersionResponseDto.md)
 
 ### Authorization
 
-[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
+No authorization required
 
 ### HTTP request headers
 

+ 5 - 5
mobile/openapi/doc/SystemConfigApi.md

@@ -10,7 +10,7 @@ All URIs are relative to */api*
 Method | HTTP request | Description
 ------------- | ------------- | -------------
 [**getConfig**](SystemConfigApi.md#getconfig) | **GET** /system-config | 
-[**getDefaults**](SystemConfigApi.md#getdefaults) | **GET** /system-config/defaults | 
+[**getConfigDefaults**](SystemConfigApi.md#getconfigdefaults) | **GET** /system-config/defaults | 
 [**getStorageTemplateOptions**](SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options | 
 [**updateConfig**](SystemConfigApi.md#updateconfig) | **PUT** /system-config | 
 
@@ -66,8 +66,8 @@ This endpoint does not need any parameter.
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
-# **getDefaults**
-> SystemConfigDto getDefaults()
+# **getConfigDefaults**
+> SystemConfigDto getConfigDefaults()
 
 
 
@@ -92,10 +92,10 @@ import 'package:openapi/api.dart';
 final api_instance = SystemConfigApi();
 
 try {
-    final result = api_instance.getDefaults();
+    final result = api_instance.getConfigDefaults();
     print(result);
 } catch (e) {
-    print('Exception when calling SystemConfigApi->getDefaults: $e\n');
+    print('Exception when calling SystemConfigApi->getConfigDefaults: $e\n');
 }
 ```
 

+ 15 - 15
mobile/openapi/lib/api/api_key_api.dart

@@ -20,7 +20,7 @@ class APIKeyApi {
   /// Parameters:
   ///
   /// * [APIKeyCreateDto] aPIKeyCreateDto (required):
-  Future<Response> createKeyWithHttpInfo(APIKeyCreateDto aPIKeyCreateDto,) async {
+  Future<Response> createApiKeyWithHttpInfo(APIKeyCreateDto aPIKeyCreateDto,) async {
     // ignore: prefer_const_declarations
     final path = r'/api-key';
 
@@ -48,8 +48,8 @@ class APIKeyApi {
   /// Parameters:
   ///
   /// * [APIKeyCreateDto] aPIKeyCreateDto (required):
-  Future<APIKeyCreateResponseDto?> createKey(APIKeyCreateDto aPIKeyCreateDto,) async {
-    final response = await createKeyWithHttpInfo(aPIKeyCreateDto,);
+  Future<APIKeyCreateResponseDto?> createApiKey(APIKeyCreateDto aPIKeyCreateDto,) async {
+    final response = await createApiKeyWithHttpInfo(aPIKeyCreateDto,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -67,7 +67,7 @@ class APIKeyApi {
   /// Parameters:
   ///
   /// * [String] id (required):
-  Future<Response> deleteKeyWithHttpInfo(String id,) async {
+  Future<Response> deleteApiKeyWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
     final path = r'/api-key/{id}'
       .replaceAll('{id}', id);
@@ -96,8 +96,8 @@ class APIKeyApi {
   /// Parameters:
   ///
   /// * [String] id (required):
-  Future<void> deleteKey(String id,) async {
-    final response = await deleteKeyWithHttpInfo(id,);
+  Future<void> deleteApiKey(String id,) async {
+    final response = await deleteApiKeyWithHttpInfo(id,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -107,7 +107,7 @@ class APIKeyApi {
   /// Parameters:
   ///
   /// * [String] id (required):
-  Future<Response> getKeyWithHttpInfo(String id,) async {
+  Future<Response> getApiKeyWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
     final path = r'/api-key/{id}'
       .replaceAll('{id}', id);
@@ -136,8 +136,8 @@ class APIKeyApi {
   /// Parameters:
   ///
   /// * [String] id (required):
-  Future<APIKeyResponseDto?> getKey(String id,) async {
-    final response = await getKeyWithHttpInfo(id,);
+  Future<APIKeyResponseDto?> getApiKey(String id,) async {
+    final response = await getApiKeyWithHttpInfo(id,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -152,7 +152,7 @@ class APIKeyApi {
   }
 
   /// Performs an HTTP 'GET /api-key' operation and returns the [Response].
-  Future<Response> getKeysWithHttpInfo() async {
+  Future<Response> getApiKeysWithHttpInfo() async {
     // ignore: prefer_const_declarations
     final path = r'/api-key';
 
@@ -177,8 +177,8 @@ class APIKeyApi {
     );
   }
 
-  Future<List<APIKeyResponseDto>?> getKeys() async {
-    final response = await getKeysWithHttpInfo();
+  Future<List<APIKeyResponseDto>?> getApiKeys() async {
+    final response = await getApiKeysWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -201,7 +201,7 @@ class APIKeyApi {
   /// * [String] id (required):
   ///
   /// * [APIKeyUpdateDto] aPIKeyUpdateDto (required):
-  Future<Response> updateKeyWithHttpInfo(String id, APIKeyUpdateDto aPIKeyUpdateDto,) async {
+  Future<Response> updateApiKeyWithHttpInfo(String id, APIKeyUpdateDto aPIKeyUpdateDto,) async {
     // ignore: prefer_const_declarations
     final path = r'/api-key/{id}'
       .replaceAll('{id}', id);
@@ -232,8 +232,8 @@ class APIKeyApi {
   /// * [String] id (required):
   ///
   /// * [APIKeyUpdateDto] aPIKeyUpdateDto (required):
-  Future<APIKeyResponseDto?> updateKey(String id, APIKeyUpdateDto aPIKeyUpdateDto,) async {
-    final response = await updateKeyWithHttpInfo(id, aPIKeyUpdateDto,);
+  Future<APIKeyResponseDto?> updateApiKey(String id, APIKeyUpdateDto aPIKeyUpdateDto,) async {
+    final response = await updateApiKeyWithHttpInfo(id, aPIKeyUpdateDto,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }

+ 119 - 119
mobile/openapi/lib/api/asset_api.dart

@@ -23,7 +23,7 @@ class AssetApi {
   /// Parameters:
   ///
   /// * [AssetBulkUploadCheckDto] assetBulkUploadCheckDto (required):
-  Future<Response> bulkUploadCheckWithHttpInfo(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
+  Future<Response> checkBulkUploadWithHttpInfo(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
     // ignore: prefer_const_declarations
     final path = r'/asset/bulk-upload-check';
 
@@ -53,8 +53,8 @@ class AssetApi {
   /// Parameters:
   ///
   /// * [AssetBulkUploadCheckDto] assetBulkUploadCheckDto (required):
-  Future<AssetBulkUploadCheckResponseDto?> bulkUploadCheck(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
-    final response = await bulkUploadCheckWithHttpInfo(assetBulkUploadCheckDto,);
+  Future<AssetBulkUploadCheckResponseDto?> checkBulkUpload(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
+    final response = await checkBulkUploadWithHttpInfo(assetBulkUploadCheckDto,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -513,7 +513,7 @@ class AssetApi {
   /// * [bool] isFavorite:
   ///
   /// * [bool] isTrashed:
-  Future<Response> getAssetStatsWithHttpInfo({ bool? isArchived, bool? isFavorite, bool? isTrashed, }) async {
+  Future<Response> getAssetStatisticsWithHttpInfo({ bool? isArchived, bool? isFavorite, bool? isTrashed, }) async {
     // ignore: prefer_const_declarations
     final path = r'/asset/statistics';
 
@@ -555,8 +555,8 @@ class AssetApi {
   /// * [bool] isFavorite:
   ///
   /// * [bool] isTrashed:
-  Future<AssetStatsResponseDto?> getAssetStats({ bool? isArchived, bool? isFavorite, bool? isTrashed, }) async {
-    final response = await getAssetStatsWithHttpInfo( isArchived: isArchived, isFavorite: isFavorite, isTrashed: isTrashed, );
+  Future<AssetStatsResponseDto?> getAssetStatistics({ bool? isArchived, bool? isFavorite, bool? isTrashed, }) async {
+    final response = await getAssetStatisticsWithHttpInfo( isArchived: isArchived, isFavorite: isFavorite, isTrashed: isTrashed, );
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -633,119 +633,6 @@ class AssetApi {
     return null;
   }
 
-  /// Performs an HTTP 'GET /asset/time-bucket' operation and returns the [Response].
-  /// Parameters:
-  ///
-  /// * [TimeBucketSize] size (required):
-  ///
-  /// * [String] timeBucket (required):
-  ///
-  /// * [String] userId:
-  ///
-  /// * [String] albumId:
-  ///
-  /// * [String] personId:
-  ///
-  /// * [bool] isArchived:
-  ///
-  /// * [bool] isFavorite:
-  ///
-  /// * [bool] isTrashed:
-  ///
-  /// * [bool] withStacked:
-  ///
-  /// * [String] key:
-  Future<Response> getByTimeBucketWithHttpInfo(TimeBucketSize size, String timeBucket, { String? userId, String? albumId, String? personId, bool? isArchived, bool? isFavorite, bool? isTrashed, bool? withStacked, String? key, }) async {
-    // ignore: prefer_const_declarations
-    final path = r'/asset/time-bucket';
-
-    // ignore: prefer_final_locals
-    Object? postBody;
-
-    final queryParams = <QueryParam>[];
-    final headerParams = <String, String>{};
-    final formParams = <String, String>{};
-
-      queryParams.addAll(_queryParams('', 'size', size));
-    if (userId != null) {
-      queryParams.addAll(_queryParams('', 'userId', userId));
-    }
-    if (albumId != null) {
-      queryParams.addAll(_queryParams('', 'albumId', albumId));
-    }
-    if (personId != null) {
-      queryParams.addAll(_queryParams('', 'personId', personId));
-    }
-    if (isArchived != null) {
-      queryParams.addAll(_queryParams('', 'isArchived', isArchived));
-    }
-    if (isFavorite != null) {
-      queryParams.addAll(_queryParams('', 'isFavorite', isFavorite));
-    }
-    if (isTrashed != null) {
-      queryParams.addAll(_queryParams('', 'isTrashed', isTrashed));
-    }
-    if (withStacked != null) {
-      queryParams.addAll(_queryParams('', 'withStacked', withStacked));
-    }
-      queryParams.addAll(_queryParams('', 'timeBucket', timeBucket));
-    if (key != null) {
-      queryParams.addAll(_queryParams('', 'key', key));
-    }
-
-    const contentTypes = <String>[];
-
-
-    return apiClient.invokeAPI(
-      path,
-      'GET',
-      queryParams,
-      postBody,
-      headerParams,
-      formParams,
-      contentTypes.isEmpty ? null : contentTypes.first,
-    );
-  }
-
-  /// Parameters:
-  ///
-  /// * [TimeBucketSize] size (required):
-  ///
-  /// * [String] timeBucket (required):
-  ///
-  /// * [String] userId:
-  ///
-  /// * [String] albumId:
-  ///
-  /// * [String] personId:
-  ///
-  /// * [bool] isArchived:
-  ///
-  /// * [bool] isFavorite:
-  ///
-  /// * [bool] isTrashed:
-  ///
-  /// * [bool] withStacked:
-  ///
-  /// * [String] key:
-  Future<List<AssetResponseDto>?> getByTimeBucket(TimeBucketSize size, String timeBucket, { String? userId, String? albumId, String? personId, bool? isArchived, bool? isFavorite, bool? isTrashed, bool? withStacked, String? key, }) async {
-    final response = await getByTimeBucketWithHttpInfo(size, timeBucket,  userId: userId, albumId: albumId, personId: personId, isArchived: isArchived, isFavorite: isFavorite, isTrashed: isTrashed, withStacked: withStacked, key: key, );
-    if (response.statusCode >= HttpStatus.badRequest) {
-      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
-    }
-    // When a remote server returns no body with a status of 204, we shall not decode it.
-    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
-    // FormatException when trying to decode an empty string.
-    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
-      final responseBody = await _decodeBodyBytes(response);
-      return (await apiClient.deserializeAsync(responseBody, 'List<AssetResponseDto>') as List)
-        .cast<AssetResponseDto>()
-        .toList();
-
-    }
-    return null;
-  }
-
   /// Performs an HTTP 'GET /asset/curated-locations' operation and returns the [Response].
   Future<Response> getCuratedLocationsWithHttpInfo() async {
     // ignore: prefer_const_declarations
@@ -1075,6 +962,119 @@ class AssetApi {
     return null;
   }
 
+  /// Performs an HTTP 'GET /asset/time-bucket' operation and returns the [Response].
+  /// Parameters:
+  ///
+  /// * [TimeBucketSize] size (required):
+  ///
+  /// * [String] timeBucket (required):
+  ///
+  /// * [String] userId:
+  ///
+  /// * [String] albumId:
+  ///
+  /// * [String] personId:
+  ///
+  /// * [bool] isArchived:
+  ///
+  /// * [bool] isFavorite:
+  ///
+  /// * [bool] isTrashed:
+  ///
+  /// * [bool] withStacked:
+  ///
+  /// * [String] key:
+  Future<Response> getTimeBucketWithHttpInfo(TimeBucketSize size, String timeBucket, { String? userId, String? albumId, String? personId, bool? isArchived, bool? isFavorite, bool? isTrashed, bool? withStacked, String? key, }) async {
+    // ignore: prefer_const_declarations
+    final path = r'/asset/time-bucket';
+
+    // ignore: prefer_final_locals
+    Object? postBody;
+
+    final queryParams = <QueryParam>[];
+    final headerParams = <String, String>{};
+    final formParams = <String, String>{};
+
+      queryParams.addAll(_queryParams('', 'size', size));
+    if (userId != null) {
+      queryParams.addAll(_queryParams('', 'userId', userId));
+    }
+    if (albumId != null) {
+      queryParams.addAll(_queryParams('', 'albumId', albumId));
+    }
+    if (personId != null) {
+      queryParams.addAll(_queryParams('', 'personId', personId));
+    }
+    if (isArchived != null) {
+      queryParams.addAll(_queryParams('', 'isArchived', isArchived));
+    }
+    if (isFavorite != null) {
+      queryParams.addAll(_queryParams('', 'isFavorite', isFavorite));
+    }
+    if (isTrashed != null) {
+      queryParams.addAll(_queryParams('', 'isTrashed', isTrashed));
+    }
+    if (withStacked != null) {
+      queryParams.addAll(_queryParams('', 'withStacked', withStacked));
+    }
+      queryParams.addAll(_queryParams('', 'timeBucket', timeBucket));
+    if (key != null) {
+      queryParams.addAll(_queryParams('', 'key', key));
+    }
+
+    const contentTypes = <String>[];
+
+
+    return apiClient.invokeAPI(
+      path,
+      'GET',
+      queryParams,
+      postBody,
+      headerParams,
+      formParams,
+      contentTypes.isEmpty ? null : contentTypes.first,
+    );
+  }
+
+  /// Parameters:
+  ///
+  /// * [TimeBucketSize] size (required):
+  ///
+  /// * [String] timeBucket (required):
+  ///
+  /// * [String] userId:
+  ///
+  /// * [String] albumId:
+  ///
+  /// * [String] personId:
+  ///
+  /// * [bool] isArchived:
+  ///
+  /// * [bool] isFavorite:
+  ///
+  /// * [bool] isTrashed:
+  ///
+  /// * [bool] withStacked:
+  ///
+  /// * [String] key:
+  Future<List<AssetResponseDto>?> getTimeBucket(TimeBucketSize size, String timeBucket, { String? userId, String? albumId, String? personId, bool? isArchived, bool? isFavorite, bool? isTrashed, bool? withStacked, String? key, }) async {
+    final response = await getTimeBucketWithHttpInfo(size, timeBucket,  userId: userId, albumId: albumId, personId: personId, isArchived: isArchived, isFavorite: isFavorite, isTrashed: isTrashed, withStacked: withStacked, key: key, );
+    if (response.statusCode >= HttpStatus.badRequest) {
+      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
+    }
+    // When a remote server returns no body with a status of 204, we shall not decode it.
+    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+    // FormatException when trying to decode an empty string.
+    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+      final responseBody = await _decodeBodyBytes(response);
+      return (await apiClient.deserializeAsync(responseBody, 'List<AssetResponseDto>') as List)
+        .cast<AssetResponseDto>()
+        .toList();
+
+    }
+    return null;
+  }
+
   /// Performs an HTTP 'GET /asset/time-buckets' operation and returns the [Response].
   /// Parameters:
   ///

+ 47 - 47
mobile/openapi/lib/api/authentication_api.dart

@@ -16,53 +16,6 @@ class AuthenticationApi {
 
   final ApiClient apiClient;
 
-  /// Performs an HTTP 'POST /auth/admin-sign-up' operation and returns the [Response].
-  /// Parameters:
-  ///
-  /// * [SignUpDto] signUpDto (required):
-  Future<Response> adminSignUpWithHttpInfo(SignUpDto signUpDto,) async {
-    // ignore: prefer_const_declarations
-    final path = r'/auth/admin-sign-up';
-
-    // ignore: prefer_final_locals
-    Object? postBody = signUpDto;
-
-    final queryParams = <QueryParam>[];
-    final headerParams = <String, String>{};
-    final formParams = <String, String>{};
-
-    const contentTypes = <String>['application/json'];
-
-
-    return apiClient.invokeAPI(
-      path,
-      'POST',
-      queryParams,
-      postBody,
-      headerParams,
-      formParams,
-      contentTypes.isEmpty ? null : contentTypes.first,
-    );
-  }
-
-  /// Parameters:
-  ///
-  /// * [SignUpDto] signUpDto (required):
-  Future<AdminSignupResponseDto?> adminSignUp(SignUpDto signUpDto,) async {
-    final response = await adminSignUpWithHttpInfo(signUpDto,);
-    if (response.statusCode >= HttpStatus.badRequest) {
-      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
-    }
-    // When a remote server returns no body with a status of 204, we shall not decode it.
-    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
-    // FormatException when trying to decode an empty string.
-    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
-      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AdminSignupResponseDto',) as AdminSignupResponseDto;
-    
-    }
-    return null;
-  }
-
   /// Performs an HTTP 'POST /auth/change-password' operation and returns the [Response].
   /// Parameters:
   ///
@@ -315,6 +268,53 @@ class AuthenticationApi {
     }
   }
 
+  /// Performs an HTTP 'POST /auth/admin-sign-up' operation and returns the [Response].
+  /// Parameters:
+  ///
+  /// * [SignUpDto] signUpDto (required):
+  Future<Response> signUpAdminWithHttpInfo(SignUpDto signUpDto,) async {
+    // ignore: prefer_const_declarations
+    final path = r'/auth/admin-sign-up';
+
+    // ignore: prefer_final_locals
+    Object? postBody = signUpDto;
+
+    final queryParams = <QueryParam>[];
+    final headerParams = <String, String>{};
+    final formParams = <String, String>{};
+
+    const contentTypes = <String>['application/json'];
+
+
+    return apiClient.invokeAPI(
+      path,
+      'POST',
+      queryParams,
+      postBody,
+      headerParams,
+      formParams,
+      contentTypes.isEmpty ? null : contentTypes.first,
+    );
+  }
+
+  /// Parameters:
+  ///
+  /// * [SignUpDto] signUpDto (required):
+  Future<AdminSignupResponseDto?> signUpAdmin(SignUpDto signUpDto,) async {
+    final response = await signUpAdminWithHttpInfo(signUpDto,);
+    if (response.statusCode >= HttpStatus.badRequest) {
+      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
+    }
+    // When a remote server returns no body with a status of 204, we shall not decode it.
+    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+    // FormatException when trying to decode an empty string.
+    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AdminSignupResponseDto',) as AdminSignupResponseDto;
+    
+    }
+    return null;
+  }
+
   /// Performs an HTTP 'POST /auth/validateToken' operation and returns the [Response].
   Future<Response> validateAccessTokenWithHttpInfo() async {
     // ignore: prefer_const_declarations

+ 3 - 3
mobile/openapi/lib/api/library_api.dart

@@ -104,7 +104,7 @@ class LibraryApi {
   }
 
   /// Performs an HTTP 'GET /library' operation and returns the [Response].
-  Future<Response> getAllForUserWithHttpInfo() async {
+  Future<Response> getLibrariesWithHttpInfo() async {
     // ignore: prefer_const_declarations
     final path = r'/library';
 
@@ -129,8 +129,8 @@ class LibraryApi {
     );
   }
 
-  Future<List<LibraryResponseDto>?> getAllForUser() async {
-    final response = await getAllForUserWithHttpInfo();
+  Future<List<LibraryResponseDto>?> getLibraries() async {
+    final response = await getLibrariesWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }

+ 62 - 62
mobile/openapi/lib/api/o_auth_api.dart

@@ -16,58 +16,11 @@ class OAuthApi {
 
   final ApiClient apiClient;
 
-  /// Performs an HTTP 'POST /oauth/authorize' operation and returns the [Response].
-  /// Parameters:
-  ///
-  /// * [OAuthConfigDto] oAuthConfigDto (required):
-  Future<Response> authorizeOAuthWithHttpInfo(OAuthConfigDto oAuthConfigDto,) async {
-    // ignore: prefer_const_declarations
-    final path = r'/oauth/authorize';
-
-    // ignore: prefer_final_locals
-    Object? postBody = oAuthConfigDto;
-
-    final queryParams = <QueryParam>[];
-    final headerParams = <String, String>{};
-    final formParams = <String, String>{};
-
-    const contentTypes = <String>['application/json'];
-
-
-    return apiClient.invokeAPI(
-      path,
-      'POST',
-      queryParams,
-      postBody,
-      headerParams,
-      formParams,
-      contentTypes.isEmpty ? null : contentTypes.first,
-    );
-  }
-
-  /// Parameters:
-  ///
-  /// * [OAuthConfigDto] oAuthConfigDto (required):
-  Future<OAuthAuthorizeResponseDto?> authorizeOAuth(OAuthConfigDto oAuthConfigDto,) async {
-    final response = await authorizeOAuthWithHttpInfo(oAuthConfigDto,);
-    if (response.statusCode >= HttpStatus.badRequest) {
-      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
-    }
-    // When a remote server returns no body with a status of 204, we shall not decode it.
-    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
-    // FormatException when trying to decode an empty string.
-    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
-      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'OAuthAuthorizeResponseDto',) as OAuthAuthorizeResponseDto;
-    
-    }
-    return null;
-  }
-
   /// Performs an HTTP 'POST /oauth/callback' operation and returns the [Response].
   /// Parameters:
   ///
   /// * [OAuthCallbackDto] oAuthCallbackDto (required):
-  Future<Response> callbackWithHttpInfo(OAuthCallbackDto oAuthCallbackDto,) async {
+  Future<Response> finishOAuthWithHttpInfo(OAuthCallbackDto oAuthCallbackDto,) async {
     // ignore: prefer_const_declarations
     final path = r'/oauth/callback';
 
@@ -95,8 +48,8 @@ class OAuthApi {
   /// Parameters:
   ///
   /// * [OAuthCallbackDto] oAuthCallbackDto (required):
-  Future<LoginResponseDto?> callback(OAuthCallbackDto oAuthCallbackDto,) async {
-    final response = await callbackWithHttpInfo(oAuthCallbackDto,);
+  Future<LoginResponseDto?> finishOAuth(OAuthCallbackDto oAuthCallbackDto,) async {
+    final response = await finishOAuthWithHttpInfo(oAuthCallbackDto,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -117,7 +70,7 @@ class OAuthApi {
   /// Parameters:
   ///
   /// * [OAuthConfigDto] oAuthConfigDto (required):
-  Future<Response> generateConfigWithHttpInfo(OAuthConfigDto oAuthConfigDto,) async {
+  Future<Response> generateOAuthConfigWithHttpInfo(OAuthConfigDto oAuthConfigDto,) async {
     // ignore: prefer_const_declarations
     final path = r'/oauth/config';
 
@@ -147,8 +100,8 @@ class OAuthApi {
   /// Parameters:
   ///
   /// * [OAuthConfigDto] oAuthConfigDto (required):
-  Future<OAuthConfigResponseDto?> generateConfig(OAuthConfigDto oAuthConfigDto,) async {
-    final response = await generateConfigWithHttpInfo(oAuthConfigDto,);
+  Future<OAuthConfigResponseDto?> generateOAuthConfig(OAuthConfigDto oAuthConfigDto,) async {
+    final response = await generateOAuthConfigWithHttpInfo(oAuthConfigDto,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -166,7 +119,7 @@ class OAuthApi {
   /// Parameters:
   ///
   /// * [OAuthCallbackDto] oAuthCallbackDto (required):
-  Future<Response> linkWithHttpInfo(OAuthCallbackDto oAuthCallbackDto,) async {
+  Future<Response> linkOAuthAccountWithHttpInfo(OAuthCallbackDto oAuthCallbackDto,) async {
     // ignore: prefer_const_declarations
     final path = r'/oauth/link';
 
@@ -194,8 +147,8 @@ class OAuthApi {
   /// Parameters:
   ///
   /// * [OAuthCallbackDto] oAuthCallbackDto (required):
-  Future<UserResponseDto?> link(OAuthCallbackDto oAuthCallbackDto,) async {
-    final response = await linkWithHttpInfo(oAuthCallbackDto,);
+  Future<UserResponseDto?> linkOAuthAccount(OAuthCallbackDto oAuthCallbackDto,) async {
+    final response = await linkOAuthAccountWithHttpInfo(oAuthCallbackDto,);
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -210,7 +163,7 @@ class OAuthApi {
   }
 
   /// Performs an HTTP 'GET /oauth/mobile-redirect' operation and returns the [Response].
-  Future<Response> mobileRedirectWithHttpInfo() async {
+  Future<Response> redirectOAuthToMobileWithHttpInfo() async {
     // ignore: prefer_const_declarations
     final path = r'/oauth/mobile-redirect';
 
@@ -235,15 +188,62 @@ class OAuthApi {
     );
   }
 
-  Future<void> mobileRedirect() async {
-    final response = await mobileRedirectWithHttpInfo();
+  Future<void> redirectOAuthToMobile() async {
+    final response = await redirectOAuthToMobileWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
   }
 
+  /// Performs an HTTP 'POST /oauth/authorize' operation and returns the [Response].
+  /// Parameters:
+  ///
+  /// * [OAuthConfigDto] oAuthConfigDto (required):
+  Future<Response> startOAuthWithHttpInfo(OAuthConfigDto oAuthConfigDto,) async {
+    // ignore: prefer_const_declarations
+    final path = r'/oauth/authorize';
+
+    // ignore: prefer_final_locals
+    Object? postBody = oAuthConfigDto;
+
+    final queryParams = <QueryParam>[];
+    final headerParams = <String, String>{};
+    final formParams = <String, String>{};
+
+    const contentTypes = <String>['application/json'];
+
+
+    return apiClient.invokeAPI(
+      path,
+      'POST',
+      queryParams,
+      postBody,
+      headerParams,
+      formParams,
+      contentTypes.isEmpty ? null : contentTypes.first,
+    );
+  }
+
+  /// Parameters:
+  ///
+  /// * [OAuthConfigDto] oAuthConfigDto (required):
+  Future<OAuthAuthorizeResponseDto?> startOAuth(OAuthConfigDto oAuthConfigDto,) async {
+    final response = await startOAuthWithHttpInfo(oAuthConfigDto,);
+    if (response.statusCode >= HttpStatus.badRequest) {
+      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
+    }
+    // When a remote server returns no body with a status of 204, we shall not decode it.
+    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+    // FormatException when trying to decode an empty string.
+    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'OAuthAuthorizeResponseDto',) as OAuthAuthorizeResponseDto;
+    
+    }
+    return null;
+  }
+
   /// Performs an HTTP 'POST /oauth/unlink' operation and returns the [Response].
-  Future<Response> unlinkWithHttpInfo() async {
+  Future<Response> unlinkOAuthAccountWithHttpInfo() async {
     // ignore: prefer_const_declarations
     final path = r'/oauth/unlink';
 
@@ -268,8 +268,8 @@ class OAuthApi {
     );
   }
 
-  Future<UserResponseDto?> unlink() async {
-    final response = await unlinkWithHttpInfo();
+  Future<UserResponseDto?> unlinkOAuthAccount() async {
+    final response = await unlinkOAuthAccountWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }

+ 12 - 12
mobile/openapi/lib/api/server_info_api.dart

@@ -139,10 +139,10 @@ class ServerInfoApi {
     return null;
   }
 
-  /// Performs an HTTP 'GET /server-info/version' operation and returns the [Response].
-  Future<Response> getServerVersionWithHttpInfo() async {
+  /// Performs an HTTP 'GET /server-info/statistics' operation and returns the [Response].
+  Future<Response> getServerStatisticsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server-info/version';
+    final path = r'/server-info/statistics';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -165,8 +165,8 @@ class ServerInfoApi {
     );
   }
 
-  Future<ServerVersionResponseDto?> getServerVersion() async {
-    final response = await getServerVersionWithHttpInfo();
+  Future<ServerStatsResponseDto?> getServerStatistics() async {
+    final response = await getServerStatisticsWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -174,16 +174,16 @@ class ServerInfoApi {
     // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
     // FormatException when trying to decode an empty string.
     if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
-      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'ServerVersionResponseDto',) as ServerVersionResponseDto;
+      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'ServerStatsResponseDto',) as ServerStatsResponseDto;
     
     }
     return null;
   }
 
-  /// Performs an HTTP 'GET /server-info/stats' operation and returns the [Response].
-  Future<Response> getStatsWithHttpInfo() async {
+  /// Performs an HTTP 'GET /server-info/version' operation and returns the [Response].
+  Future<Response> getServerVersionWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server-info/stats';
+    final path = r'/server-info/version';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -206,8 +206,8 @@ class ServerInfoApi {
     );
   }
 
-  Future<ServerStatsResponseDto?> getStats() async {
-    final response = await getStatsWithHttpInfo();
+  Future<ServerVersionResponseDto?> getServerVersion() async {
+    final response = await getServerVersionWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
@@ -215,7 +215,7 @@ class ServerInfoApi {
     // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
     // FormatException when trying to decode an empty string.
     if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
-      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'ServerStatsResponseDto',) as ServerStatsResponseDto;
+      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'ServerVersionResponseDto',) as ServerVersionResponseDto;
     
     }
     return null;

+ 3 - 3
mobile/openapi/lib/api/system_config_api.dart

@@ -58,7 +58,7 @@ class SystemConfigApi {
   }
 
   /// Performs an HTTP 'GET /system-config/defaults' operation and returns the [Response].
-  Future<Response> getDefaultsWithHttpInfo() async {
+  Future<Response> getConfigDefaultsWithHttpInfo() async {
     // ignore: prefer_const_declarations
     final path = r'/system-config/defaults';
 
@@ -83,8 +83,8 @@ class SystemConfigApi {
     );
   }
 
-  Future<SystemConfigDto?> getDefaults() async {
-    final response = await getDefaultsWithHttpInfo();
+  Future<SystemConfigDto?> getConfigDefaults() async {
+    final response = await getConfigDefaultsWithHttpInfo();
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }

+ 10 - 10
mobile/openapi/test/api_key_api_test.dart

@@ -17,28 +17,28 @@ void main() {
   // final instance = APIKeyApi();
 
   group('tests for APIKeyApi', () {
-    //Future<APIKeyCreateResponseDto> createKey(APIKeyCreateDto aPIKeyCreateDto) async
-    test('test createKey', () async {
+    //Future<APIKeyCreateResponseDto> createApiKey(APIKeyCreateDto aPIKeyCreateDto) async
+    test('test createApiKey', () async {
       // TODO
     });
 
-    //Future deleteKey(String id) async
-    test('test deleteKey', () async {
+    //Future deleteApiKey(String id) async
+    test('test deleteApiKey', () async {
       // TODO
     });
 
-    //Future<APIKeyResponseDto> getKey(String id) async
-    test('test getKey', () async {
+    //Future<APIKeyResponseDto> getApiKey(String id) async
+    test('test getApiKey', () async {
       // TODO
     });
 
-    //Future<List<APIKeyResponseDto>> getKeys() async
-    test('test getKeys', () async {
+    //Future<List<APIKeyResponseDto>> getApiKeys() async
+    test('test getApiKeys', () async {
       // TODO
     });
 
-    //Future<APIKeyResponseDto> updateKey(String id, APIKeyUpdateDto aPIKeyUpdateDto) async
-    test('test updateKey', () async {
+    //Future<APIKeyResponseDto> updateApiKey(String id, APIKeyUpdateDto aPIKeyUpdateDto) async
+    test('test updateApiKey', () async {
       // TODO
     });
 

+ 9 - 9
mobile/openapi/test/asset_api_test.dart

@@ -19,8 +19,8 @@ void main() {
   group('tests for AssetApi', () {
     // Checks if assets exist by checksums
     //
-    //Future<AssetBulkUploadCheckResponseDto> bulkUploadCheck(AssetBulkUploadCheckDto assetBulkUploadCheckDto) async
-    test('test bulkUploadCheck', () async {
+    //Future<AssetBulkUploadCheckResponseDto> checkBulkUpload(AssetBulkUploadCheckDto assetBulkUploadCheckDto) async
+    test('test checkBulkUpload', () async {
       // TODO
     });
 
@@ -70,8 +70,8 @@ void main() {
       // TODO
     });
 
-    //Future<AssetStatsResponseDto> getAssetStats({ bool isArchived, bool isFavorite, bool isTrashed }) async
-    test('test getAssetStats', () async {
+    //Future<AssetStatsResponseDto> getAssetStatistics({ bool isArchived, bool isFavorite, bool isTrashed }) async
+    test('test getAssetStatistics', () async {
       // TODO
     });
 
@@ -80,11 +80,6 @@ void main() {
       // TODO
     });
 
-    //Future<List<AssetResponseDto>> getByTimeBucket(TimeBucketSize size, String timeBucket, { String userId, String albumId, String personId, bool isArchived, bool isFavorite, bool isTrashed, bool withStacked, String key }) async
-    test('test getByTimeBucket', () async {
-      // TODO
-    });
-
     //Future<List<CuratedLocationsResponseDto>> getCuratedLocations() async
     test('test getCuratedLocations', () async {
       // TODO
@@ -115,6 +110,11 @@ void main() {
       // TODO
     });
 
+    //Future<List<AssetResponseDto>> getTimeBucket(TimeBucketSize size, String timeBucket, { String userId, String albumId, String personId, bool isArchived, bool isFavorite, bool isTrashed, bool withStacked, String key }) async
+    test('test getTimeBucket', () async {
+      // TODO
+    });
+
     //Future<List<TimeBucketResponseDto>> getTimeBuckets(TimeBucketSize size, { String userId, String albumId, String personId, bool isArchived, bool isFavorite, bool isTrashed, bool withStacked, String key }) async
     test('test getTimeBuckets', () async {
       // TODO

+ 5 - 5
mobile/openapi/test/authentication_api_test.dart

@@ -17,11 +17,6 @@ void main() {
   // final instance = AuthenticationApi();
 
   group('tests for AuthenticationApi', () {
-    //Future<AdminSignupResponseDto> adminSignUp(SignUpDto signUpDto) async
-    test('test adminSignUp', () async {
-      // TODO
-    });
-
     //Future<UserResponseDto> changePassword(ChangePasswordDto changePasswordDto) async
     test('test changePassword', () async {
       // TODO
@@ -52,6 +47,11 @@ void main() {
       // TODO
     });
 
+    //Future<AdminSignupResponseDto> signUpAdmin(SignUpDto signUpDto) async
+    test('test signUpAdmin', () async {
+      // TODO
+    });
+
     //Future<ValidateAccessTokenResponseDto> validateAccessToken() async
     test('test validateAccessToken', () async {
       // TODO

+ 2 - 2
mobile/openapi/test/library_api_test.dart

@@ -27,8 +27,8 @@ void main() {
       // TODO
     });
 
-    //Future<List<LibraryResponseDto>> getAllForUser() async
-    test('test getAllForUser', () async {
+    //Future<List<LibraryResponseDto>> getLibraries() async
+    test('test getLibraries', () async {
       // TODO
     });
 

+ 14 - 14
mobile/openapi/test/o_auth_api_test.dart

@@ -17,35 +17,35 @@ void main() {
   // final instance = OAuthApi();
 
   group('tests for OAuthApi', () {
-    //Future<OAuthAuthorizeResponseDto> authorizeOAuth(OAuthConfigDto oAuthConfigDto) async
-    test('test authorizeOAuth', () async {
+    //Future<LoginResponseDto> finishOAuth(OAuthCallbackDto oAuthCallbackDto) async
+    test('test finishOAuth', () async {
       // TODO
     });
 
-    //Future<LoginResponseDto> callback(OAuthCallbackDto oAuthCallbackDto) async
-    test('test callback', () async {
+    // @deprecated use feature flags and /oauth/authorize
+    //
+    //Future<OAuthConfigResponseDto> generateOAuthConfig(OAuthConfigDto oAuthConfigDto) async
+    test('test generateOAuthConfig', () async {
       // TODO
     });
 
-    // @deprecated use feature flags and /oauth/authorize
-    //
-    //Future<OAuthConfigResponseDto> generateConfig(OAuthConfigDto oAuthConfigDto) async
-    test('test generateConfig', () async {
+    //Future<UserResponseDto> linkOAuthAccount(OAuthCallbackDto oAuthCallbackDto) async
+    test('test linkOAuthAccount', () async {
       // TODO
     });
 
-    //Future<UserResponseDto> link(OAuthCallbackDto oAuthCallbackDto) async
-    test('test link', () async {
+    //Future redirectOAuthToMobile() async
+    test('test redirectOAuthToMobile', () async {
       // TODO
     });
 
-    //Future mobileRedirect() async
-    test('test mobileRedirect', () async {
+    //Future<OAuthAuthorizeResponseDto> startOAuth(OAuthConfigDto oAuthConfigDto) async
+    test('test startOAuth', () async {
       // TODO
     });
 
-    //Future<UserResponseDto> unlink() async
-    test('test unlink', () async {
+    //Future<UserResponseDto> unlinkOAuthAccount() async
+    test('test unlinkOAuthAccount', () async {
       // TODO
     });
 

+ 4 - 4
mobile/openapi/test/server_info_api_test.dart

@@ -32,13 +32,13 @@ void main() {
       // TODO
     });
 
-    //Future<ServerVersionResponseDto> getServerVersion() async
-    test('test getServerVersion', () async {
+    //Future<ServerStatsResponseDto> getServerStatistics() async
+    test('test getServerStatistics', () async {
       // TODO
     });
 
-    //Future<ServerStatsResponseDto> getStats() async
-    test('test getStats', () async {
+    //Future<ServerVersionResponseDto> getServerVersion() async
+    test('test getServerVersion', () async {
       // TODO
     });
 

+ 2 - 2
mobile/openapi/test/system_config_api_test.dart

@@ -22,8 +22,8 @@ void main() {
       // TODO
     });
 
-    //Future<SystemConfigDto> getDefaults() async
-    test('test getDefaults', () async {
+    //Future<SystemConfigDto> getConfigDefaults() async
+    test('test getConfigDefaults', () async {
       // TODO
     });
 

+ 19 - 19
server/immich-openapi-specs.json

@@ -678,7 +678,7 @@
     },
     "/api-key": {
       "get": {
-        "operationId": "getKeys",
+        "operationId": "getApiKeys",
         "parameters": [],
         "responses": {
           "200": {
@@ -711,7 +711,7 @@
         ]
       },
       "post": {
-        "operationId": "createKey",
+        "operationId": "createApiKey",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -753,7 +753,7 @@
     },
     "/api-key/{id}": {
       "delete": {
-        "operationId": "deleteKey",
+        "operationId": "deleteApiKey",
         "parameters": [
           {
             "name": "id",
@@ -786,7 +786,7 @@
         ]
       },
       "get": {
-        "operationId": "getKey",
+        "operationId": "getApiKey",
         "parameters": [
           {
             "name": "id",
@@ -826,7 +826,7 @@
         ]
       },
       "put": {
-        "operationId": "updateKey",
+        "operationId": "updateApiKey",
         "parameters": [
           {
             "name": "id",
@@ -1084,7 +1084,7 @@
     "/asset/bulk-upload-check": {
       "post": {
         "description": "Checks if assets exist by checksums",
-        "operationId": "bulkUploadCheck",
+        "operationId": "checkBulkUpload",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -1855,7 +1855,7 @@
     },
     "/asset/statistics": {
       "get": {
-        "operationId": "getAssetStats",
+        "operationId": "getAssetStatistics",
         "parameters": [
           {
             "name": "isArchived",
@@ -1977,7 +1977,7 @@
     },
     "/asset/time-bucket": {
       "get": {
-        "operationId": "getByTimeBucket",
+        "operationId": "getTimeBucket",
         "parameters": [
           {
             "name": "size",
@@ -2596,7 +2596,7 @@
     },
     "/auth/admin-sign-up": {
       "post": {
-        "operationId": "adminSignUp",
+        "operationId": "signUpAdmin",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -2943,7 +2943,7 @@
     },
     "/library": {
       "get": {
-        "operationId": "getAllForUser",
+        "operationId": "getLibraries",
         "parameters": [],
         "responses": {
           "200": {
@@ -3265,7 +3265,7 @@
     },
     "/oauth/authorize": {
       "post": {
-        "operationId": "authorizeOAuth",
+        "operationId": "startOAuth",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -3296,7 +3296,7 @@
     },
     "/oauth/callback": {
       "post": {
-        "operationId": "callback",
+        "operationId": "finishOAuth",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -3329,7 +3329,7 @@
       "post": {
         "deprecated": true,
         "description": "@deprecated use feature flags and /oauth/authorize",
-        "operationId": "generateConfig",
+        "operationId": "generateOAuthConfig",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -3360,7 +3360,7 @@
     },
     "/oauth/link": {
       "post": {
-        "operationId": "link",
+        "operationId": "linkOAuthAccount",
         "parameters": [],
         "requestBody": {
           "content": {
@@ -3402,7 +3402,7 @@
     },
     "/oauth/mobile-redirect": {
       "get": {
-        "operationId": "mobileRedirect",
+        "operationId": "redirectOAuthToMobile",
         "parameters": [],
         "responses": {
           "200": {
@@ -3416,7 +3416,7 @@
     },
     "/oauth/unlink": {
       "post": {
-        "operationId": "unlink",
+        "operationId": "unlinkOAuthAccount",
         "parameters": [],
         "responses": {
           "201": {
@@ -4307,9 +4307,9 @@
         ]
       }
     },
-    "/server-info/stats": {
+    "/server-info/statistics": {
       "get": {
-        "operationId": "getStats",
+        "operationId": "getServerStatistics",
         "parameters": [],
         "responses": {
           "200": {
@@ -4837,7 +4837,7 @@
     },
     "/system-config/defaults": {
       "get": {
-        "operationId": "getDefaults",
+        "operationId": "getConfigDefaults",
         "parameters": [],
         "responses": {
           "200": {

+ 10 - 10
server/src/domain/asset/asset.service.spec.ts

@@ -331,17 +331,17 @@ describe(AssetService.name, () => {
     });
   });
 
-  describe('getByTimeBucket', () => {
+  describe('getTimeBucket', () => {
     it('should return the assets for a album time bucket if user has album.read', async () => {
       accessMock.album.hasOwnerAccess.mockResolvedValue(true);
-      assetMock.getByTimeBucket.mockResolvedValue([assetStub.image]);
+      assetMock.getTimeBucket.mockResolvedValue([assetStub.image]);
 
       await expect(
-        sut.getByTimeBucket(authStub.admin, { size: TimeBucketSize.DAY, timeBucket: 'bucket', albumId: 'album-id' }),
+        sut.getTimeBucket(authStub.admin, { size: TimeBucketSize.DAY, timeBucket: 'bucket', albumId: 'album-id' }),
       ).resolves.toEqual(expect.arrayContaining([expect.objectContaining({ id: 'asset-id' })]));
 
       expect(accessMock.album.hasOwnerAccess).toHaveBeenCalledWith(authStub.admin.id, 'album-id');
-      expect(assetMock.getByTimeBucket).toBeCalledWith('bucket', {
+      expect(assetMock.getTimeBucket).toBeCalledWith('bucket', {
         size: TimeBucketSize.DAY,
         timeBucket: 'bucket',
         albumId: 'album-id',
@@ -349,17 +349,17 @@ describe(AssetService.name, () => {
     });
 
     it('should return the assets for a archive time bucket if user has archive.read', async () => {
-      assetMock.getByTimeBucket.mockResolvedValue([assetStub.image]);
+      assetMock.getTimeBucket.mockResolvedValue([assetStub.image]);
 
       await expect(
-        sut.getByTimeBucket(authStub.admin, {
+        sut.getTimeBucket(authStub.admin, {
           size: TimeBucketSize.DAY,
           timeBucket: 'bucket',
           isArchived: true,
           userId: authStub.admin.id,
         }),
       ).resolves.toEqual(expect.arrayContaining([expect.objectContaining({ id: 'asset-id' })]));
-      expect(assetMock.getByTimeBucket).toBeCalledWith('bucket', {
+      expect(assetMock.getTimeBucket).toBeCalledWith('bucket', {
         size: TimeBucketSize.DAY,
         timeBucket: 'bucket',
         isArchived: true,
@@ -368,16 +368,16 @@ describe(AssetService.name, () => {
     });
 
     it('should return the assets for a library time bucket if user has library.read', async () => {
-      assetMock.getByTimeBucket.mockResolvedValue([assetStub.image]);
+      assetMock.getTimeBucket.mockResolvedValue([assetStub.image]);
 
       await expect(
-        sut.getByTimeBucket(authStub.admin, {
+        sut.getTimeBucket(authStub.admin, {
           size: TimeBucketSize.DAY,
           timeBucket: 'bucket',
           userId: authStub.admin.id,
         }),
       ).resolves.toEqual(expect.arrayContaining([expect.objectContaining({ id: 'asset-id' })]));
-      expect(assetMock.getByTimeBucket).toBeCalledWith('bucket', {
+      expect(assetMock.getTimeBucket).toBeCalledWith('bucket', {
         size: TimeBucketSize.DAY,
         timeBucket: 'bucket',
         userId: authStub.admin.id,

+ 2 - 2
server/src/domain/asset/asset.service.ts

@@ -194,12 +194,12 @@ export class AssetService {
     return this.assetRepository.getTimeBuckets(dto);
   }
 
-  async getByTimeBucket(
+  async getTimeBucket(
     authUser: AuthUserDto,
     dto: TimeBucketAssetDto,
   ): Promise<AssetResponseDto[] | SanitizedAssetResponseDto[]> {
     await this.timeBucketChecks(authUser, dto);
-    const assets = await this.assetRepository.getByTimeBucket(dto.timeBucket, dto);
+    const assets = await this.assetRepository.getTimeBucket(dto.timeBucket, dto);
     if (authUser.isShowMetadata) {
       return assets.map((asset) => mapAsset(asset, { withStack: true }));
     } else {

+ 2 - 7
server/src/domain/auth/auth.service.ts

@@ -315,13 +315,8 @@ export class AuthService {
     const redirectUri = this.normalize(config, url.split('?')[0]);
     const client = await this.getOAuthClient(config);
     const params = client.callbackParams(url);
-    try {
-      const tokens = await client.callback(redirectUri, params, { state: params.state });
-      return client.userinfo<OAuthProfile>(tokens.access_token || '');
-    } catch (error: Error | any) {
-      this.logger.error(`Unable to complete OAuth login: ${error}`, error?.stack);
-      throw new InternalServerErrorException(`Unable to complete OAuth login: ${error}`, { cause: error });
-    }
+    const tokens = await client.callback(redirectUri, params, { state: params.state });
+    return client.userinfo<OAuthProfile>(tokens.access_token || '');
   }
 
   private async getOAuthClient(config: SystemConfig) {

+ 1 - 1
server/src/domain/repositories/asset.repository.ts

@@ -123,6 +123,6 @@ export interface IAssetRepository {
   getMapMarkers(ownerId: string, options?: MapMarkerSearchOptions): Promise<MapMarker[]>;
   getStatistics(ownerId: string, options: AssetStatsOptions): Promise<AssetStats>;
   getTimeBuckets(options: TimeBucketOptions): Promise<TimeBucketItem[]>;
-  getByTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]>;
+  getTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]>;
   upsertExif(exif: Partial<ExifEntity>): Promise<void>;
 }

+ 1 - 1
server/src/domain/server-info/server-info.service.spec.ts

@@ -220,7 +220,7 @@ describe(ServerInfoService.name, () => {
         },
       ]);
 
-      await expect(sut.getStats()).resolves.toEqual({
+      await expect(sut.getStatistics()).resolves.toEqual({
         photos: 120,
         videos: 31,
         usage: 1123455,

+ 1 - 1
server/src/domain/server-info/server-info.service.ts

@@ -92,7 +92,7 @@ export class ServerInfoService {
     };
   }
 
-  async getStats(): Promise<ServerStatsResponseDto> {
+  async getStatistics(): Promise<ServerStatsResponseDto> {
     const userStats: UserStatsQueryResponse[] = await this.userRepository.getUserStats();
     const serverStats = new ServerStatsResponseDto();
 

+ 32 - 42
server/src/domain/user/user.core.ts

@@ -1,5 +1,5 @@
 import { LibraryType, UserEntity } from '@app/infra/entities';
-import { BadRequestException, ForbiddenException, InternalServerErrorException, Logger } from '@nestjs/common';
+import { BadRequestException, ForbiddenException } from '@nestjs/common';
 import path from 'path';
 import sanitize from 'sanitize-filename';
 import { AuthUserDto } from '../auth';
@@ -62,26 +62,21 @@ export class UserCore {
       }
     }
 
-    try {
-      if (dto.password) {
-        dto.password = await this.cryptoRepository.hashBcrypt(dto.password, SALT_ROUNDS);
-      }
-
-      if (dto.storageLabel === '') {
-        dto.storageLabel = null;
-      }
+    if (dto.password) {
+      dto.password = await this.cryptoRepository.hashBcrypt(dto.password, SALT_ROUNDS);
+    }
 
-      if (dto.externalPath === '') {
-        dto.externalPath = null;
-      } else if (dto.externalPath) {
-        dto.externalPath = path.normalize(dto.externalPath);
-      }
+    if (dto.storageLabel === '') {
+      dto.storageLabel = null;
+    }
 
-      return this.userRepository.update(id, dto);
-    } catch (e) {
-      Logger.error(e, 'Failed to update user info');
-      throw new InternalServerErrorException('Failed to update user info');
+    if (dto.externalPath === '') {
+      dto.externalPath = null;
+    } else if (dto.externalPath) {
+      dto.externalPath = path.normalize(dto.externalPath);
     }
+
+    return this.userRepository.update(id, dto);
   }
 
   async createUser(dto: Partial<UserEntity> & { email: string }): Promise<UserEntity> {
@@ -97,30 +92,25 @@ export class UserCore {
       }
     }
 
-    try {
-      const payload: Partial<UserEntity> = { ...dto };
-      if (payload.password) {
-        payload.password = await this.cryptoRepository.hashBcrypt(payload.password, SALT_ROUNDS);
-      }
-      if (payload.storageLabel) {
-        payload.storageLabel = sanitize(payload.storageLabel);
-      }
-      payload.avatarColor = getRandomAvatarColor();
-      const userEntity = await this.userRepository.create(payload);
-      await this.libraryRepository.create({
-        owner: { id: userEntity.id } as UserEntity,
-        name: 'Default Library',
-        assets: [],
-        type: LibraryType.UPLOAD,
-        importPaths: [],
-        exclusionPatterns: [],
-        isVisible: true,
-      });
-
-      return userEntity;
-    } catch (e) {
-      Logger.error(e, 'Create new user');
-      throw new InternalServerErrorException('Failed to register new user');
+    const payload: Partial<UserEntity> = { ...dto };
+    if (payload.password) {
+      payload.password = await this.cryptoRepository.hashBcrypt(payload.password, SALT_ROUNDS);
+    }
+    if (payload.storageLabel) {
+      payload.storageLabel = sanitize(payload.storageLabel);
     }
+    payload.avatarColor = getRandomAvatarColor();
+    const userEntity = await this.userRepository.create(payload);
+    await this.libraryRepository.create({
+      owner: { id: userEntity.id } as UserEntity,
+      name: 'Default Library',
+      assets: [],
+      type: LibraryType.UPLOAD,
+      importPaths: [],
+      exclusionPatterns: [],
+      isVisible: true,
+    });
+
+    return userEntity;
   }
 }

+ 2 - 2
server/src/immich/api-v1/asset/asset.controller.ts

@@ -17,8 +17,8 @@ import {
 import { ApiBody, ApiConsumes, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger';
 import { Response as Res } from 'express';
 import { AuthUser, Authenticated, SharedLinkRoute } from '../../app.guard';
-import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from '../../app.interceptor';
 import { UUIDParamDto } from '../../controllers/dto/uuid-param.dto';
+import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from '../../interceptors';
 import FileNotEmptyValidator from '../validation/file-not-empty-validator';
 import { AssetService } from './asset.service';
 import { AssetBulkUploadCheckDto } from './dto/asset-check.dto';
@@ -204,7 +204,7 @@ export class AssetController {
    */
   @Post('/bulk-upload-check')
   @HttpCode(HttpStatus.OK)
-  bulkUploadCheck(
+  checkBulkUpload(
     @AuthUser() authUser: AuthUserDto,
     @Body(ValidationPipe) dto: AssetBulkUploadCheckDto,
   ): Promise<AssetBulkUploadCheckResponseDto> {

+ 4 - 5
server/src/immich/app.module.ts

@@ -2,14 +2,13 @@ import { DomainModule } from '@app/domain';
 import { InfraModule } from '@app/infra';
 import { AssetEntity } from '@app/infra/entities';
 import { Module, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
-import { APP_GUARD } from '@nestjs/core';
+import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
 import { ScheduleModule } from '@nestjs/schedule';
 import { TypeOrmModule } from '@nestjs/typeorm';
 import { AssetRepository, IAssetRepository } from './api-v1/asset/asset-repository';
 import { AssetController as AssetControllerV1 } from './api-v1/asset/asset.controller';
 import { AssetService } from './api-v1/asset/asset.service';
 import { AppGuard } from './app.guard';
-import { FileUploadInterceptor } from './app.interceptor';
 import { AppService } from './app.service';
 import {
   APIKeyController,
@@ -31,6 +30,7 @@ import {
   TagController,
   UserController,
 } from './controllers';
+import { ErrorInterceptor, FileUploadInterceptor } from './interceptors';
 
 @Module({
   imports: [
@@ -61,10 +61,9 @@ import {
     PersonController,
   ],
   providers: [
-    //
-    { provide: APP_GUARD, useExisting: AppGuard },
+    { provide: APP_INTERCEPTOR, useClass: ErrorInterceptor },
+    { provide: APP_GUARD, useClass: AppGuard },
     { provide: IAssetRepository, useClass: AssetRepository },
-    AppGuard,
     AppService,
     AssetService,
     FileUploadInterceptor,

+ 7 - 0
server/src/immich/app.utils.ts

@@ -47,6 +47,9 @@ function sortKeys<T>(obj: T): T {
   return result as T;
 }
 
+export const routeToErrorMessage = (methodName: string) =>
+  'Failed to ' + methodName.replace(/[A-Z]+/g, (letter) => ` ${letter.toLowerCase()}`);
+
 const patchOpenAPI = (document: OpenAPIObject) => {
   document.paths = sortKeys(document.paths);
   if (document.components?.schemas) {
@@ -78,6 +81,10 @@ const patchOpenAPI = (document: OpenAPIObject) => {
         delete operation.summary;
       }
 
+      if (operation.operationId) {
+        // console.log(`${routeToErrorMessage(operation.operationId).padEnd(40)} (${operation.operationId})`);
+      }
+
       if (operation.description === '') {
         delete operation.description;
       }

+ 5 - 5
server/src/immich/controllers/api-key.controller.ts

@@ -20,22 +20,22 @@ export class APIKeyController {
   constructor(private service: APIKeyService) {}
 
   @Post()
-  createKey(@AuthUser() authUser: AuthUserDto, @Body() dto: APIKeyCreateDto): Promise<APIKeyCreateResponseDto> {
+  createApiKey(@AuthUser() authUser: AuthUserDto, @Body() dto: APIKeyCreateDto): Promise<APIKeyCreateResponseDto> {
     return this.service.create(authUser, dto);
   }
 
   @Get()
-  getKeys(@AuthUser() authUser: AuthUserDto): Promise<APIKeyResponseDto[]> {
+  getApiKeys(@AuthUser() authUser: AuthUserDto): Promise<APIKeyResponseDto[]> {
     return this.service.getAll(authUser);
   }
 
   @Get(':id')
-  getKey(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<APIKeyResponseDto> {
+  getApiKey(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<APIKeyResponseDto> {
     return this.service.getById(authUser, id);
   }
 
   @Put(':id')
-  updateKey(
+  updateApiKey(
     @AuthUser() authUser: AuthUserDto,
     @Param() { id }: UUIDParamDto,
     @Body() dto: APIKeyUpdateDto,
@@ -44,7 +44,7 @@ export class APIKeyController {
   }
 
   @Delete(':id')
-  deleteKey(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
+  deleteApiKey(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
     return this.service.delete(authUser, id);
   }
 }

+ 5 - 4
server/src/immich/controllers/asset.controller.ts

@@ -39,10 +39,11 @@ import {
 import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
 import { AuthUser, Authenticated, SharedLinkRoute } from '../app.guard';
 import { UseValidation, asStreamableFile } from '../app.utils';
+import { Route } from '../interceptors';
 import { UUIDParamDto } from './dto/uuid-param.dto';
 
 @ApiTags('Asset')
-@Controller('asset')
+@Controller(Route.ASSET)
 @Authenticated()
 @UseValidation()
 export class AssetController {
@@ -86,7 +87,7 @@ export class AssetController {
   }
 
   @Get('statistics')
-  getAssetStats(@AuthUser() authUser: AuthUserDto, @Query() dto: AssetStatsDto): Promise<AssetStatsResponseDto> {
+  getAssetStatistics(@AuthUser() authUser: AuthUserDto, @Query() dto: AssetStatsDto): Promise<AssetStatsResponseDto> {
     return this.service.getStatistics(authUser, dto);
   }
 
@@ -98,8 +99,8 @@ export class AssetController {
 
   @Authenticated({ isShared: true })
   @Get('time-bucket')
-  getByTimeBucket(@AuthUser() authUser: AuthUserDto, @Query() dto: TimeBucketAssetDto): Promise<AssetResponseDto[]> {
-    return this.service.getByTimeBucket(authUser, dto) as Promise<AssetResponseDto[]>;
+  getTimeBucket(@AuthUser() authUser: AuthUserDto, @Query() dto: TimeBucketAssetDto): Promise<AssetResponseDto[]> {
+    return this.service.getTimeBucket(authUser, dto) as Promise<AssetResponseDto[]>;
   }
 
   @Post('jobs')

+ 1 - 1
server/src/immich/controllers/auth.controller.ts

@@ -43,7 +43,7 @@ export class AuthController {
   @PublicRoute()
   @Post('admin-sign-up')
   @ApiBadRequestResponse({ description: 'The server already has an admin' })
-  adminSignUp(@Body() signUpCredential: SignUpDto): Promise<AdminSignupResponseDto> {
+  signUpAdmin(@Body() signUpCredential: SignUpDto): Promise<AdminSignupResponseDto> {
     return this.service.adminSignUp(signUpCredential);
   }
 

+ 1 - 1
server/src/immich/controllers/library.controller.ts

@@ -21,7 +21,7 @@ export class LibraryController {
   constructor(private service: LibraryService) {}
 
   @Get()
-  getAllForUser(@AuthUser() authUser: AuthUserDto): Promise<ResponseDto[]> {
+  getLibraries(@AuthUser() authUser: AuthUserDto): Promise<ResponseDto[]> {
     return this.service.getAllForUser(authUser);
   }
 

+ 6 - 6
server/src/immich/controllers/oauth.controller.ts

@@ -25,7 +25,7 @@ export class OAuthController {
   @PublicRoute()
   @Get('mobile-redirect')
   @Redirect()
-  mobileRedirect(@Req() req: Request) {
+  redirectOAuthToMobile(@Req() req: Request) {
     return {
       url: this.service.getMobileRedirect(req.url),
       statusCode: HttpStatus.TEMPORARY_REDIRECT,
@@ -35,19 +35,19 @@ export class OAuthController {
   /** @deprecated use feature flags and /oauth/authorize */
   @PublicRoute()
   @Post('config')
-  generateConfig(@Body() dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
+  generateOAuthConfig(@Body() dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
     return this.service.generateConfig(dto);
   }
 
   @PublicRoute()
   @Post('authorize')
-  authorizeOAuth(@Body() dto: OAuthConfigDto): Promise<OAuthAuthorizeResponseDto> {
+  startOAuth(@Body() dto: OAuthConfigDto): Promise<OAuthAuthorizeResponseDto> {
     return this.service.authorize(dto);
   }
 
   @PublicRoute()
   @Post('callback')
-  async callback(
+  async finishOAuth(
     @Res({ passthrough: true }) res: Response,
     @Body() dto: OAuthCallbackDto,
     @GetLoginDetails() loginDetails: LoginDetails,
@@ -58,12 +58,12 @@ export class OAuthController {
   }
 
   @Post('link')
-  link(@AuthUser() authUser: AuthUserDto, @Body() dto: OAuthCallbackDto): Promise<UserResponseDto> {
+  linkOAuthAccount(@AuthUser() authUser: AuthUserDto, @Body() dto: OAuthCallbackDto): Promise<UserResponseDto> {
     return this.service.link(authUser, dto);
   }
 
   @Post('unlink')
-  unlink(@AuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
+  unlinkOAuthAccount(@AuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
     return this.service.unlink(authUser);
   }
 }

+ 3 - 3
server/src/immich/controllers/server-info.controller.ts

@@ -57,9 +57,9 @@ export class ServerInfoController {
   }
 
   @AdminRoute()
-  @Get('stats')
-  getStats(): Promise<ServerStatsResponseDto> {
-    return this.service.getStats();
+  @Get('statistics')
+  getServerStatistics(): Promise<ServerStatsResponseDto> {
+    return this.service.getStatistics();
   }
 
   @PublicRoute()

+ 1 - 1
server/src/immich/controllers/system-config.controller.ts

@@ -17,7 +17,7 @@ export class SystemConfigController {
   }
 
   @Get('defaults')
-  getDefaults(): SystemConfigDto {
+  getConfigDefaults(): SystemConfigDto {
     return this.service.getDefaults();
   }
 

+ 1 - 1
server/src/immich/controllers/user.controller.ts

@@ -24,8 +24,8 @@ import {
 } from '@nestjs/common';
 import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
 import { AdminRoute, AuthUser, Authenticated } from '../app.guard';
-import { FileUploadInterceptor, Route } from '../app.interceptor';
 import { UseValidation, asStreamableFile } from '../app.utils';
+import { FileUploadInterceptor, Route } from '../interceptors';
 import { UUIDParamDto } from './dto/uuid-param.dto';
 
 @ApiTags('User')

+ 32 - 0
server/src/immich/interceptors/error.interceptor.ts

@@ -0,0 +1,32 @@
+import {
+  CallHandler,
+  ExecutionContext,
+  HttpException,
+  Injectable,
+  InternalServerErrorException,
+  Logger,
+  NestInterceptor,
+} from '@nestjs/common';
+import { Observable, catchError, throwError } from 'rxjs';
+import { routeToErrorMessage } from '../app.utils';
+
+@Injectable()
+export class ErrorInterceptor implements NestInterceptor {
+  private logger = new Logger(ErrorInterceptor.name);
+
+  async intercept(context: ExecutionContext, next: CallHandler<any>): Promise<Observable<any>> {
+    return next.handle().pipe(
+      catchError((error) =>
+        throwError(() => {
+          if (error instanceof HttpException === false) {
+            const errorMessage = routeToErrorMessage(context.getHandler().name);
+            this.logger.error(errorMessage, error, error?.errors);
+            return new InternalServerErrorException(errorMessage);
+          } else {
+            return error;
+          }
+        }),
+      ),
+    );
+  }
+}

+ 1 - 1
server/src/immich/app.interceptor.ts → server/src/immich/interceptors/file.interceptor.ts

@@ -7,7 +7,7 @@ import { createHash } from 'crypto';
 import { NextFunction, RequestHandler } from 'express';
 import multer, { StorageEngine, diskStorage } from 'multer';
 import { Observable } from 'rxjs';
-import { AuthRequest } from './app.guard';
+import { AuthRequest } from '../app.guard';
 
 export enum Route {
   ASSET = 'asset',

+ 2 - 0
server/src/immich/interceptors/index.ts

@@ -0,0 +1,2 @@
+export * from './error.interceptor';
+export * from './file.interceptor';

+ 1 - 1
server/src/infra/repositories/asset.repository.ts

@@ -493,7 +493,7 @@ export class AssetRepository implements IAssetRepository {
       .getRawMany();
   }
 
-  getByTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]> {
+  getTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]> {
     const truncated = dateTrunc(options);
     return (
       this.getBuilder(options)

+ 4 - 4
server/test/e2e/server-info.e2e-spec.ts

@@ -103,9 +103,9 @@ describe(`${ServerInfoController.name} (e2e)`, () => {
     });
   });
 
-  describe('GET /server-info/stats', () => {
+  describe('GET /server-info/statistics', () => {
     it('should require authentication', async () => {
-      const { status, body } = await request(server).get('/server-info/stats');
+      const { status, body } = await request(server).get('/server-info/statistics');
       expect(status).toBe(401);
       expect(body).toEqual(errorStub.unauthorized);
     });
@@ -115,7 +115,7 @@ describe(`${ServerInfoController.name} (e2e)`, () => {
       await api.userApi.create(server, accessToken, { ...loginDto, firstName: 'test', lastName: 'test' });
       const { accessToken: userAccessToken } = await api.authApi.login(server, loginDto);
       const { status, body } = await request(server)
-        .get('/server-info/stats')
+        .get('/server-info/statistics')
         .set('Authorization', `Bearer ${userAccessToken}`);
       expect(status).toBe(403);
       expect(body).toEqual(errorStub.forbidden);
@@ -123,7 +123,7 @@ describe(`${ServerInfoController.name} (e2e)`, () => {
 
     it('should return the server stats', async () => {
       const { status, body } = await request(server)
-        .get('/server-info/stats')
+        .get('/server-info/statistics')
         .set('Authorization', `Bearer ${accessToken}`);
       expect(status).toBe(200);
       expect(body).toEqual({

+ 1 - 1
server/test/repositories/asset.repository.mock.ts

@@ -26,7 +26,7 @@ export const newAssetRepositoryMock = (): jest.Mocked<IAssetRepository> => {
     findLivePhotoMatch: jest.fn(),
     getMapMarkers: jest.fn(),
     getStatistics: jest.fn(),
-    getByTimeBucket: jest.fn(),
+    getTimeBucket: jest.fn(),
     getTimeBuckets: jest.fn(),
     restoreAll: jest.fn(),
     softDeleteAll: jest.fn(),

File diff ditekan karena terlalu besar
+ 310 - 345
web/src/api/open-api/api.ts


+ 4 - 8
web/src/api/utils.ts

@@ -36,23 +36,19 @@ export const oauth = {
   authorize: async (location: Location) => {
     try {
       const redirectUri = location.href.split('?')[0];
-      const { data } = await api.oauthApi.authorizeOAuth({ oAuthConfigDto: { redirectUri } });
+      const { data } = await api.oauthApi.startOAuth({ oAuthConfigDto: { redirectUri } });
       goto(data.url);
     } catch (error) {
       handleError(error, 'Unable to login with OAuth');
     }
   },
-  getConfig: (location: Location) => {
-    const redirectUri = location.href.split('?')[0];
-    return api.oauthApi.generateConfig({ oAuthConfigDto: { redirectUri } });
-  },
   login: (location: Location) => {
-    return api.oauthApi.callback({ oAuthCallbackDto: { url: location.href } });
+    return api.oauthApi.finishOAuth({ oAuthCallbackDto: { url: location.href } });
   },
   link: (location: Location): AxiosPromise<UserResponseDto> => {
-    return api.oauthApi.link({ oAuthCallbackDto: { url: location.href } });
+    return api.oauthApi.linkOAuthAccount({ oAuthCallbackDto: { url: location.href } });
   },
   unlink: () => {
-    return api.oauthApi.unlink();
+    return api.oauthApi.unlinkOAuthAccount();
   },
 };

+ 2 - 2
web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte

@@ -32,7 +32,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.ffmpeg),
-      api.systemConfigApi.getDefaults().then((res) => res.data.ffmpeg),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.ffmpeg),
     ]);
   }
 
@@ -76,7 +76,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     ffmpegConfig = { ...configs.ffmpeg };
     defaultConfig = { ...configs.ffmpeg };

+ 2 - 2
web/src/lib/components/admin-page/settings/job-settings/job-settings.svelte

@@ -22,7 +22,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.job),
-      api.systemConfigApi.getDefaults().then((res) => res.data.job),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.job),
     ]);
   }
 
@@ -59,7 +59,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     jobConfig = { ...configs.job };
     defaultConfig = { ...configs.job };

+ 2 - 2
web/src/lib/components/admin-page/settings/library-settings/library-settings.svelte

@@ -28,7 +28,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.library),
-      api.systemConfigApi.getDefaults().then((res) => res.data.library),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.library),
     ]);
   }
 
@@ -68,7 +68,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     libraryConfig = { ...configs.library };
     defaultConfig = { ...configs.library };

+ 1 - 1
web/src/lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte

@@ -22,7 +22,7 @@
   async function refreshConfig() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.machineLearning),
-      api.systemConfigApi.getDefaults().then((res) => res.data.machineLearning),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.machineLearning),
     ]);
   }
 

+ 2 - 2
web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte

@@ -22,7 +22,7 @@
   async function refreshConfig() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data),
-      api.systemConfigApi.getDefaults().then((res) => res.data),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data),
     ]);
   }
 
@@ -65,7 +65,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     config = cloneDeep(configs);
     defaultConfig = cloneDeep(configs);

+ 2 - 2
web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte

@@ -18,7 +18,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.newVersionCheck),
-      api.systemConfigApi.getDefaults().then((res) => res.data.newVersionCheck),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.newVersionCheck),
     ]);
   }
 
@@ -55,7 +55,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     newVersionCheckConfig = { ...configs.newVersionCheck };
     defaultConfig = { ...configs.newVersionCheck };

+ 2 - 2
web/src/lib/components/admin-page/settings/oauth/oauth-settings.svelte

@@ -29,7 +29,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.oauth),
-      api.systemConfigApi.getDefaults().then((res) => res.data.oauth),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.oauth),
     ]);
   }
 
@@ -90,7 +90,7 @@
   }
 
   async function resetToDefault() {
-    const { data: defaultConfig } = await api.systemConfigApi.getDefaults();
+    const { data: defaultConfig } = await api.systemConfigApi.getConfigDefaults();
 
     oauthConfig = { ...defaultConfig.oauth };
 

+ 2 - 2
web/src/lib/components/admin-page/settings/password-login/password-login-settings.svelte

@@ -20,7 +20,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.passwordLogin),
-      api.systemConfigApi.getDefaults().then((res) => res.data.passwordLogin),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.passwordLogin),
     ]);
   }
 
@@ -77,7 +77,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     passwordLoginConfig = { ...configs.passwordLogin };
     defaultConfig = { ...configs.passwordLogin };

+ 2 - 2
web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte

@@ -26,7 +26,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig, templateOptions] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.storageTemplate),
-      api.systemConfigApi.getDefaults().then((res) => res.data.storageTemplate),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.storageTemplate),
       api.systemConfigApi.getStorageTemplateOptions().then((res) => res.data),
     ]);
 
@@ -119,7 +119,7 @@
   }
 
   async function resetToDefault() {
-    const { data: defaultConfig } = await api.systemConfigApi.getDefaults();
+    const { data: defaultConfig } = await api.systemConfigApi.getConfigDefaults();
 
     storageConfig.template = defaultConfig.storageTemplate.template;
 

+ 2 - 2
web/src/lib/components/admin-page/settings/theme/theme-settings.svelte

@@ -19,7 +19,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.theme),
-      api.systemConfigApi.getDefaults().then((res) => res.data.theme),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.theme),
     ]);
   }
 
@@ -56,7 +56,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     themeConfig = { ...configs.theme };
     defaultConfig = { ...configs.theme };

+ 2 - 2
web/src/lib/components/admin-page/settings/thumbnail/thumbnail-settings.svelte

@@ -20,7 +20,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.thumbnail),
-      api.systemConfigApi.getDefaults().then((res) => res.data.thumbnail),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.thumbnail),
     ]);
   }
 
@@ -37,7 +37,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     thumbnailConfig = { ...configs.thumbnail };
     defaultConfig = { ...configs.thumbnail };

+ 2 - 2
web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte

@@ -20,7 +20,7 @@
   async function getConfigs() {
     [savedConfig, defaultConfig] = await Promise.all([
       api.systemConfigApi.getConfig().then((res) => res.data.trash),
-      api.systemConfigApi.getDefaults().then((res) => res.data.trash),
+      api.systemConfigApi.getConfigDefaults().then((res) => res.data.trash),
     ]);
   }
 
@@ -53,7 +53,7 @@
   }
 
   async function resetToDefault() {
-    const { data: configs } = await api.systemConfigApi.getDefaults();
+    const { data: configs } = await api.systemConfigApi.getConfigDefaults();
 
     trashConfig = { ...configs.trash };
     defaultConfig = { ...configs.trash };

+ 2 - 3
web/src/lib/components/asset-viewer/asset-viewer.svelte

@@ -545,11 +545,10 @@
       await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids, removeParent: true } });
       for (const child of $stackAssetsStore) {
         child.stackParentId = null;
+        child.stackCount = 0;
+        child.stack = [];
         assetStore?.addAsset(child);
       }
-      asset.stackCount = 0;
-      asset.stack = [];
-      assetStore?.updateAsset(asset, true);
 
       dispatch('unstack');
       notificationController.show({ type: NotificationType.Info, message: 'Un-stacked', timeout: 1500 });

+ 1 - 1
web/src/lib/components/forms/admin-registration-form.svelte

@@ -30,7 +30,7 @@
       const firstName = form.get('firstName');
       const lastName = form.get('lastName');
 
-      const { status } = await api.authenticationApi.adminSignUp({
+      const { status } = await api.authenticationApi.signUpAdmin({
         signUpDto: {
           email: String(email),
           password: String(password),

+ 3 - 3
web/src/lib/components/shared-components/side-bar/side-bar.svelte

@@ -2,7 +2,7 @@
   import { page } from '$app/stores';
   import { locale, sidebarSettings } from '$lib/stores/preferences.store';
   import { featureFlags } from '$lib/stores/server-config.store';
-  import { AssetApiGetAssetStatsRequest, api } from '@api';
+  import { AssetApiGetAssetStatisticsRequest, api } from '@api';
   import {
     mdiAccount,
     mdiAccountMultiple,
@@ -23,8 +23,8 @@
   import SideBarButton from './side-bar-button.svelte';
   import SideBarSection from './side-bar-section.svelte';
 
-  const getStats = async (dto: AssetApiGetAssetStatsRequest) => {
-    const { data: stats } = await api.assetApi.getAssetStats(dto);
+  const getStats = async (dto: AssetApiGetAssetStatisticsRequest) => {
+    const { data: stats } = await api.assetApi.getAssetStatistics(dto);
     return stats;
   };
 

+ 1 - 1
web/src/lib/components/user-settings-page/library-list.svelte

@@ -82,7 +82,7 @@
   };
 
   async function readLibraryList() {
-    const { data } = await api.libraryApi.getAllForUser();
+    const { data } = await api.libraryApi.getLibraries();
     libraries = data;
 
     dropdownOpen.length = libraries.length;

+ 4 - 4
web/src/lib/components/user-settings-page/user-api-key-list.svelte

@@ -25,14 +25,14 @@
   };
 
   async function refreshKeys() {
-    const { data } = await api.keyApi.getKeys();
+    const { data } = await api.keyApi.getApiKeys();
     keys = data;
   }
 
   const handleCreate = async (event: CustomEvent<APIKeyResponseDto>) => {
     try {
       const dto = event.detail;
-      const { data } = await api.keyApi.createKey({ aPIKeyCreateDto: dto });
+      const { data } = await api.keyApi.createApiKey({ aPIKeyCreateDto: dto });
       secret = data.secret;
     } catch (error) {
       handleError(error, 'Unable to create a new API Key');
@@ -50,7 +50,7 @@
     const dto = event.detail;
 
     try {
-      await api.keyApi.updateKey({ id: editKey.id, aPIKeyUpdateDto: { name: dto.name } });
+      await api.keyApi.updateApiKey({ id: editKey.id, aPIKeyUpdateDto: { name: dto.name } });
       notificationController.show({
         message: `Saved API Key`,
         type: NotificationType.Info,
@@ -69,7 +69,7 @@
     }
 
     try {
-      await api.keyApi.deleteKey({ id: deleteKey.id });
+      await api.keyApi.deleteApiKey({ id: deleteKey.id });
       notificationController.show({
         message: `Removed API Key: ${deleteKey.name}`,
         type: NotificationType.Info,

+ 10 - 2
web/src/lib/stores/assets.store.ts

@@ -196,7 +196,7 @@ export class AssetStore {
 
       bucket.cancelToken = new AbortController();
 
-      const { data: assets } = await api.assetApi.getByTimeBucket(
+      const { data: assets } = await api.assetApi.getTimeBucket(
         {
           ...this.options,
           timeBucket: bucketDate,
@@ -206,7 +206,7 @@ export class AssetStore {
       );
 
       if (this.albumId) {
-        const { data: albumAssets } = await api.assetApi.getByTimeBucket(
+        const { data: albumAssets } = await api.assetApi.getTimeBucket(
           {
             albumId: this.albumId,
             timeBucket: bucketDate,
@@ -261,6 +261,9 @@ export class AssetStore {
       isMismatched(this.options.isArchived, asset.isArchived) ||
       isMismatched(this.options.isFavorite, asset.isFavorite)
     ) {
+      // If asset is already in the bucket we don't need to recalculate
+      // asset store containers
+      this.updateAsset(asset);
       return;
     }
 
@@ -290,6 +293,11 @@ export class AssetStore {
       const bDate = DateTime.fromISO(b.fileCreatedAt).toUTC();
       return bDate.diff(aDate).milliseconds;
     });
+
+    // If we added an asset to the store, we need to recalculate
+    // asset store containers
+    this.assets.push(asset);
+    this.updateAsset(asset, true);
   }
 
   getBucketByDate(bucketDate: string): AssetBucket | null {

+ 1 - 1
web/src/routes/(user)/user-settings/+page.server.ts

@@ -8,7 +8,7 @@ export const load = (async ({ parent, locals }) => {
     throw redirect(302, AppRoute.AUTH_LOGIN);
   }
 
-  const { data: keys } = await locals.api.keyApi.getKeys();
+  const { data: keys } = await locals.api.keyApi.getApiKeys();
   const { data: devices } = await locals.api.authenticationApi.getAuthDevices();
   const { data: partners } = await locals.api.partnerApi.getPartners({ direction: 'shared-by' });
 

+ 1 - 1
web/src/routes/admin/server-status/+page.server.ts

@@ -11,7 +11,7 @@ export const load = (async ({ parent, locals: { api } }) => {
     throw redirect(302, AppRoute.PHOTOS);
   }
 
-  const { data: stats } = await api.serverInfoApi.getStats();
+  const { data: stats } = await api.serverInfoApi.getServerStatistics();
 
   return {
     user,

+ 1 - 1
web/src/routes/admin/server-status/+page.svelte

@@ -11,7 +11,7 @@
 
   onMount(async () => {
     setIntervalHandler = setInterval(async () => {
-      const { data: stats } = await api.serverInfoApi.getStats();
+      const { data: stats } = await api.serverInfoApi.getServerStatistics();
       data.stats = stats;
     }, 5000);
   });

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini