Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7277ea3d7a |
Generated
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.48",
|
"version": "2.2.47",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.48",
|
"version": "2.2.47",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
},
|
},
|
||||||
"../open-api/typescript-sdk": {
|
"../open-api/typescript-sdk": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.48",
|
"version": "2.2.47",
|
||||||
"description": "Command Line Interface (CLI) for Immich",
|
"description": "Command Line Interface (CLI) for Immich",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ services:
|
|||||||
vaapi-wsl: # use this for VAAPI if you're running Immich in WSL2
|
vaapi-wsl: # use this for VAAPI if you're running Immich in WSL2
|
||||||
devices:
|
devices:
|
||||||
- /dev/dri:/dev/dri
|
- /dev/dri:/dev/dri
|
||||||
- /dev/dxg:/dev/dxg
|
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/lib/wsl:/usr/lib/wsl
|
- /usr/lib/wsl:/usr/lib/wsl
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -8,23 +8,22 @@ For the full list, refer to the [Immich source code](https://github.com/immich-a
|
|||||||
|
|
||||||
## Image formats
|
## Image formats
|
||||||
|
|
||||||
| Format | Extension(s) | Supported? | Notes |
|
| Format | Extension(s) | Supported? | Notes |
|
||||||
| :---------- | :---------------------------- | :----------------: | :-------------- |
|
| :-------- | :---------------------------- | :----------------: | :-------------- |
|
||||||
| `AVIF` | `.avif` | :white_check_mark: | |
|
| `AVIF` | `.avif` | :white_check_mark: | |
|
||||||
| `BMP` | `.bmp` | :white_check_mark: | |
|
| `BMP` | `.bmp` | :white_check_mark: | |
|
||||||
| `GIF` | `.gif` | :white_check_mark: | |
|
| `GIF` | `.gif` | :white_check_mark: | |
|
||||||
| `HEIC` | `.heic` | :white_check_mark: | |
|
| `HEIC` | `.heic` | :white_check_mark: | |
|
||||||
| `HEIF` | `.heif` | :white_check_mark: | |
|
| `HEIF` | `.heif` | :white_check_mark: | |
|
||||||
| `JPEG 2000` | `.jp2` | :white_check_mark: | |
|
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
|
||||||
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
|
| `JPEG XL` | `.jxl` | :white_check_mark: | |
|
||||||
| `JPEG XL` | `.jxl` | :white_check_mark: | |
|
| `PNG` | `.webp` | :white_check_mark: | |
|
||||||
| `PNG` | `.webp` | :white_check_mark: | |
|
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
|
||||||
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
|
| `RAW` | `.raw` | :white_check_mark: | |
|
||||||
| `RAW` | `.raw` | :white_check_mark: | |
|
| `RW2` | `.rw2` | :white_check_mark: | |
|
||||||
| `RW2` | `.rw2` | :white_check_mark: | |
|
| `SVG` | `.svg` | :white_check_mark: | |
|
||||||
| `SVG` | `.svg` | :white_check_mark: | |
|
| `TIFF` | `.tif` `.tiff` | :white_check_mark: | |
|
||||||
| `TIFF` | `.tif` `.tiff` | :white_check_mark: | |
|
| `WEBP` | `.webp` | :white_check_mark: | |
|
||||||
| `WEBP` | `.webp` | :white_check_mark: | |
|
|
||||||
|
|
||||||
## Video formats
|
## Video formats
|
||||||
|
|
||||||
|
|||||||
Vendored
-4
@@ -1,8 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"label": "v1.125.7",
|
|
||||||
"url": "https://v1.125.7.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": "v1.125.6",
|
"label": "v1.125.6",
|
||||||
"url": "https://v1.125.6.archive.immich.app"
|
"url": "https://v1.125.6.archive.immich.app"
|
||||||
|
|||||||
Generated
+4
-4
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
"../cli": {
|
"../cli": {
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.48",
|
"version": "2.2.47",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
},
|
},
|
||||||
"../open-api/typescript-sdk": {
|
"../open-api/typescript-sdk": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -356,24 +356,5 @@ describe('/admin/users', () => {
|
|||||||
expect(status).toBe(403);
|
expect(status).toBe(403);
|
||||||
expect(body).toEqual(errorDto.forbidden);
|
expect(body).toEqual(errorDto.forbidden);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should restore a user', async () => {
|
|
||||||
const user = await utils.userSetup(admin.accessToken, createUserDto.create('restore'));
|
|
||||||
|
|
||||||
await deleteUserAdmin({ id: user.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) });
|
|
||||||
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.post(`/admin/users/${user.userId}/restore`)
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: user.userId,
|
|
||||||
email: user.userEmail,
|
|
||||||
status: 'active',
|
|
||||||
deletedAt: null,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "machine-learning"
|
name = "machine-learning"
|
||||||
version = "1.125.7"
|
version = "1.125.6"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ platform :android do
|
|||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 182,
|
"android.injected.version.code" => 182,
|
||||||
"android.injected.version.name" => "1.125.7",
|
"android.injected.version.name" => "1.125.6",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ platform :ios do
|
|||||||
desc "iOS Release"
|
desc "iOS Release"
|
||||||
lane :release do
|
lane :release do
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.125.7"
|
version_number: "1.125.6"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
Generated
+5
-5
@@ -3,7 +3,7 @@ Immich API
|
|||||||
|
|
||||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.125.7
|
- API version: 1.125.6
|
||||||
- Generator version: 7.8.0
|
- Generator version: 7.8.0
|
||||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||||
|
|
||||||
@@ -93,17 +93,17 @@ Class | Method | HTTP request | Description
|
|||||||
*AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} |
|
*AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} |
|
||||||
*AlbumsApi* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} |
|
*AlbumsApi* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} |
|
||||||
*AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} |
|
*AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} |
|
||||||
*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | checkBulkUpload
|
*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | Checks if assets exist by checksums
|
||||||
*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | checkExistingAssets
|
*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||||
*AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets |
|
*AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets |
|
||||||
*AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original |
|
*AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original |
|
||||||
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | getAllUserAssetsByDeviceId
|
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | Get all asset of a device that are in the database, ID only.
|
||||||
*AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} |
|
*AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} |
|
||||||
*AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics |
|
*AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics |
|
||||||
*AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane |
|
*AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane |
|
||||||
*AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random |
|
*AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random |
|
||||||
*AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback |
|
*AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback |
|
||||||
*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | replaceAsset
|
*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | Replace the asset with new file, without changing its id
|
||||||
*AssetsApi* | [**runAssetJobs**](doc//AssetsApi.md#runassetjobs) | **POST** /assets/jobs |
|
*AssetsApi* | [**runAssetJobs**](doc//AssetsApi.md#runassetjobs) | **POST** /assets/jobs |
|
||||||
*AssetsApi* | [**updateAsset**](doc//AssetsApi.md#updateasset) | **PUT** /assets/{id} |
|
*AssetsApi* | [**updateAsset**](doc//AssetsApi.md#updateasset) | **PUT** /assets/{id} |
|
||||||
*AssetsApi* | [**updateAssets**](doc//AssetsApi.md#updateassets) | **PUT** /assets |
|
*AssetsApi* | [**updateAssets**](doc//AssetsApi.md#updateassets) | **PUT** /assets |
|
||||||
|
|||||||
Generated
-16
@@ -16,8 +16,6 @@ class AssetsApi {
|
|||||||
|
|
||||||
final ApiClient apiClient;
|
final ApiClient apiClient;
|
||||||
|
|
||||||
/// checkBulkUpload
|
|
||||||
///
|
|
||||||
/// Checks if assets exist by checksums
|
/// Checks if assets exist by checksums
|
||||||
///
|
///
|
||||||
/// Note: This method returns the HTTP [Response].
|
/// Note: This method returns the HTTP [Response].
|
||||||
@@ -50,8 +48,6 @@ class AssetsApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// checkBulkUpload
|
|
||||||
///
|
|
||||||
/// Checks if assets exist by checksums
|
/// Checks if assets exist by checksums
|
||||||
///
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
@@ -72,8 +68,6 @@ class AssetsApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// checkExistingAssets
|
|
||||||
///
|
|
||||||
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
|
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||||
///
|
///
|
||||||
/// Note: This method returns the HTTP [Response].
|
/// Note: This method returns the HTTP [Response].
|
||||||
@@ -106,8 +100,6 @@ class AssetsApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// checkExistingAssets
|
|
||||||
///
|
|
||||||
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
|
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||||
///
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
@@ -223,8 +215,6 @@ class AssetsApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getAllUserAssetsByDeviceId
|
|
||||||
///
|
|
||||||
/// Get all asset of a device that are in the database, ID only.
|
/// Get all asset of a device that are in the database, ID only.
|
||||||
///
|
///
|
||||||
/// Note: This method returns the HTTP [Response].
|
/// Note: This method returns the HTTP [Response].
|
||||||
@@ -258,8 +248,6 @@ class AssetsApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getAllUserAssetsByDeviceId
|
|
||||||
///
|
|
||||||
/// Get all asset of a device that are in the database, ID only.
|
/// Get all asset of a device that are in the database, ID only.
|
||||||
///
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
@@ -576,8 +564,6 @@ class AssetsApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// replaceAsset
|
|
||||||
///
|
|
||||||
/// Replace the asset with new file, without changing its id
|
/// Replace the asset with new file, without changing its id
|
||||||
///
|
///
|
||||||
/// Note: This method returns the HTTP [Response].
|
/// Note: This method returns the HTTP [Response].
|
||||||
@@ -659,8 +645,6 @@ class AssetsApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// replaceAsset
|
|
||||||
///
|
|
||||||
/// Replace the asset with new file, without changing its id
|
/// Replace the asset with new file, without changing its id
|
||||||
///
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ name: immich_mobile
|
|||||||
description: Immich - selfhosted backup media file on mobile phone
|
description: Immich - selfhosted backup media file on mobile phone
|
||||||
|
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 1.125.7+182
|
version: 1.125.6+182
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.3.0 <4.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
|||||||
@@ -539,7 +539,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"201": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@@ -1424,7 +1424,6 @@
|
|||||||
},
|
},
|
||||||
"/assets/bulk-upload-check": {
|
"/assets/bulk-upload-check": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Checks if assets exist by checksums",
|
|
||||||
"operationId": "checkBulkUpload",
|
"operationId": "checkBulkUpload",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
@@ -1460,7 +1459,7 @@
|
|||||||
"api_key": []
|
"api_key": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"summary": "checkBulkUpload",
|
"summary": "Checks if assets exist by checksums",
|
||||||
"tags": [
|
"tags": [
|
||||||
"Assets"
|
"Assets"
|
||||||
]
|
]
|
||||||
@@ -1468,7 +1467,6 @@
|
|||||||
},
|
},
|
||||||
"/assets/device/{deviceId}": {
|
"/assets/device/{deviceId}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Get all asset of a device that are in the database, ID only.",
|
|
||||||
"operationId": "getAllUserAssetsByDeviceId",
|
"operationId": "getAllUserAssetsByDeviceId",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
@@ -1506,7 +1504,7 @@
|
|||||||
"api_key": []
|
"api_key": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"summary": "getAllUserAssetsByDeviceId",
|
"summary": "Get all asset of a device that are in the database, ID only.",
|
||||||
"tags": [
|
"tags": [
|
||||||
"Assets"
|
"Assets"
|
||||||
]
|
]
|
||||||
@@ -1514,7 +1512,6 @@
|
|||||||
},
|
},
|
||||||
"/assets/exist": {
|
"/assets/exist": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Checks if multiple assets exist on the server and returns all existing - used by background backup",
|
|
||||||
"operationId": "checkExistingAssets",
|
"operationId": "checkExistingAssets",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
@@ -1550,7 +1547,7 @@
|
|||||||
"api_key": []
|
"api_key": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"summary": "checkExistingAssets",
|
"summary": "Checks if multiple assets exist on the server and returns all existing - used by background backup",
|
||||||
"tags": [
|
"tags": [
|
||||||
"Assets"
|
"Assets"
|
||||||
]
|
]
|
||||||
@@ -1906,7 +1903,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"put": {
|
"put": {
|
||||||
"description": "Replace the asset with new file, without changing its id",
|
|
||||||
"operationId": "replaceAsset",
|
"operationId": "replaceAsset",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
@@ -1960,7 +1956,7 @@
|
|||||||
"api_key": []
|
"api_key": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"summary": "replaceAsset",
|
"summary": "Replace the asset with new file, without changing its id",
|
||||||
"tags": [
|
"tags": [
|
||||||
"Assets"
|
"Assets"
|
||||||
],
|
],
|
||||||
@@ -7458,7 +7454,7 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"title": "Immich",
|
"title": "Immich",
|
||||||
"description": "Immich API",
|
"description": "Immich API",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"contact": {}
|
"contact": {}
|
||||||
},
|
},
|
||||||
"tags": [],
|
"tags": [],
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./build/index.js",
|
"main": "./build/index.js",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Immich
|
* Immich
|
||||||
* 1.125.7
|
* 1.125.6
|
||||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||||
* See https://www.npmjs.com/package/oazapfts
|
* See https://www.npmjs.com/package/oazapfts
|
||||||
*/
|
*/
|
||||||
@@ -1475,7 +1475,7 @@ export function restoreUserAdmin({ id }: {
|
|||||||
id: string;
|
id: string;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
status: 200;
|
status: 201;
|
||||||
data: UserAdminResponseDto;
|
data: UserAdminResponseDto;
|
||||||
}>(`/admin/users/${encodeURIComponent(id)}/restore`, {
|
}>(`/admin/users/${encodeURIComponent(id)}/restore`, {
|
||||||
...opts,
|
...opts,
|
||||||
@@ -1703,7 +1703,7 @@ export function updateAssets({ assetBulkUpdateDto }: {
|
|||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* checkBulkUpload
|
* Checks if assets exist by checksums
|
||||||
*/
|
*/
|
||||||
export function checkBulkUpload({ assetBulkUploadCheckDto }: {
|
export function checkBulkUpload({ assetBulkUploadCheckDto }: {
|
||||||
assetBulkUploadCheckDto: AssetBulkUploadCheckDto;
|
assetBulkUploadCheckDto: AssetBulkUploadCheckDto;
|
||||||
@@ -1718,7 +1718,7 @@ export function checkBulkUpload({ assetBulkUploadCheckDto }: {
|
|||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* getAllUserAssetsByDeviceId
|
* Get all asset of a device that are in the database, ID only.
|
||||||
*/
|
*/
|
||||||
export function getAllUserAssetsByDeviceId({ deviceId }: {
|
export function getAllUserAssetsByDeviceId({ deviceId }: {
|
||||||
deviceId: string;
|
deviceId: string;
|
||||||
@@ -1731,7 +1731,7 @@ export function getAllUserAssetsByDeviceId({ deviceId }: {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* checkExistingAssets
|
* Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||||
*/
|
*/
|
||||||
export function checkExistingAssets({ checkExistingAssetsDto }: {
|
export function checkExistingAssets({ checkExistingAssetsDto }: {
|
||||||
checkExistingAssetsDto: CheckExistingAssetsDto;
|
checkExistingAssetsDto: CheckExistingAssetsDto;
|
||||||
@@ -1839,7 +1839,7 @@ export function downloadAsset({ id, key }: {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* replaceAsset
|
* Replace the asset with new file, without changing its id
|
||||||
*/
|
*/
|
||||||
export function replaceAsset({ id, key, assetMediaReplaceDto }: {
|
export function replaceAsset({ id, key, assetMediaReplaceDto }: {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/bullmq": "^11.0.0",
|
"@nestjs/bullmq": "^11.0.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
UploadedFiles,
|
UploadedFiles,
|
||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiBody, ApiConsumes, ApiHeader, ApiOperation, ApiTags } from '@nestjs/swagger';
|
import { ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger';
|
||||||
import { NextFunction, Response } from 'express';
|
import { NextFunction, Response } from 'express';
|
||||||
import { EndpointLifecycle } from 'src/decorators';
|
import { EndpointLifecycle } from 'src/decorators';
|
||||||
import {
|
import {
|
||||||
@@ -94,10 +94,6 @@ export class AssetMediaController {
|
|||||||
@UseInterceptors(FileUploadInterceptor)
|
@UseInterceptors(FileUploadInterceptor)
|
||||||
@ApiConsumes('multipart/form-data')
|
@ApiConsumes('multipart/form-data')
|
||||||
@EndpointLifecycle({ addedAt: 'v1.106.0' })
|
@EndpointLifecycle({ addedAt: 'v1.106.0' })
|
||||||
@ApiOperation({
|
|
||||||
summary: 'replaceAsset',
|
|
||||||
description: 'Replace the asset with new file, without changing its id',
|
|
||||||
})
|
|
||||||
@Authenticated({ sharedLink: true })
|
@Authenticated({ sharedLink: true })
|
||||||
async replaceAsset(
|
async replaceAsset(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@@ -145,10 +141,6 @@ export class AssetMediaController {
|
|||||||
*/
|
*/
|
||||||
@Post('exist')
|
@Post('exist')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@ApiOperation({
|
|
||||||
summary: 'checkExistingAssets',
|
|
||||||
description: 'Checks if multiple assets exist on the server and returns all existing - used by background backup',
|
|
||||||
})
|
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
checkExistingAssets(
|
checkExistingAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@@ -162,10 +154,6 @@ export class AssetMediaController {
|
|||||||
*/
|
*/
|
||||||
@Post('bulk-upload-check')
|
@Post('bulk-upload-check')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@ApiOperation({
|
|
||||||
summary: 'checkBulkUpload',
|
|
||||||
description: 'Checks if assets exist by checksums',
|
|
||||||
})
|
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
checkBulkUpload(
|
checkBulkUpload(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { EndpointLifecycle } from 'src/decorators';
|
import { EndpointLifecycle } from 'src/decorators';
|
||||||
import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import {
|
import {
|
||||||
@@ -41,10 +41,6 @@ export class AssetController {
|
|||||||
* Get all asset of a device that are in the database, ID only.
|
* Get all asset of a device that are in the database, ID only.
|
||||||
*/
|
*/
|
||||||
@Get('/device/:deviceId')
|
@Get('/device/:deviceId')
|
||||||
@ApiOperation({
|
|
||||||
summary: 'getAllUserAssetsByDeviceId',
|
|
||||||
description: 'Get all asset of a device that are in the database, ID only.',
|
|
||||||
})
|
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
getAllUserAssetsByDeviceId(@Auth() auth: AuthDto, @Param() { deviceId }: DeviceIdDto) {
|
getAllUserAssetsByDeviceId(@Auth() auth: AuthDto, @Param() { deviceId }: DeviceIdDto) {
|
||||||
return this.service.getUserAssetsByDeviceId(auth, deviceId);
|
return this.service.getUserAssetsByDeviceId(auth, deviceId);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import { UserPreferencesResponseDto, UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto';
|
import { UserPreferencesResponseDto, UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto';
|
||||||
@@ -75,7 +75,6 @@ export class UserAdminController {
|
|||||||
|
|
||||||
@Post(':id/restore')
|
@Post(':id/restore')
|
||||||
@Authenticated({ permission: Permission.ADMIN_USER_DELETE, admin: true })
|
@Authenticated({ permission: Permission.ADMIN_USER_DELETE, admin: true })
|
||||||
@HttpCode(HttpStatus.OK)
|
|
||||||
restoreUserAdmin(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<UserAdminResponseDto> {
|
restoreUserAdmin(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<UserAdminResponseDto> {
|
||||||
return this.service.restore(auth, id);
|
return this.service.restore(auth, id);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+15
-13
@@ -3,21 +3,16 @@
|
|||||||
* Please do not edit it manually.
|
* Please do not edit it manually.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ColumnType } from "kysely";
|
import type { ColumnType } from 'kysely';
|
||||||
|
|
||||||
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[]
|
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;
|
||||||
? U[]
|
|
||||||
: ArrayTypeImpl<T>;
|
|
||||||
|
|
||||||
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U>
|
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[];
|
||||||
? ColumnType<S[], I[], U[]>
|
|
||||||
: T[];
|
|
||||||
|
|
||||||
export type AssetsStatusEnum = "active" | "deleted" | "trashed";
|
export type AssetsStatusEnum = 'active' | 'deleted' | 'trashed';
|
||||||
|
|
||||||
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
export type Generated<T> =
|
||||||
? ColumnType<S, I | undefined, U>
|
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
|
||||||
: ColumnType<T, T | undefined, T>;
|
|
||||||
|
|
||||||
export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
|
export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
|
||||||
|
|
||||||
@@ -33,7 +28,7 @@ export type JsonPrimitive = boolean | number | string | null;
|
|||||||
|
|
||||||
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
||||||
|
|
||||||
export type Sourcetype = "exif" | "machine-learning";
|
export type Sourcetype = 'exif' | 'machine-learning';
|
||||||
|
|
||||||
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||||
|
|
||||||
@@ -154,6 +149,12 @@ export interface AssetStack {
|
|||||||
primaryAssetId: string;
|
primaryAssetId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AssetUser {
|
||||||
|
assetId: string;
|
||||||
|
createdAt: Timestamp;
|
||||||
|
userId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Audit {
|
export interface Audit {
|
||||||
action: string;
|
action: string;
|
||||||
createdAt: Generated<Timestamp>;
|
createdAt: Generated<Timestamp>;
|
||||||
@@ -413,6 +414,7 @@ export interface DB {
|
|||||||
asset_files: AssetFiles;
|
asset_files: AssetFiles;
|
||||||
asset_job_status: AssetJobStatus;
|
asset_job_status: AssetJobStatus;
|
||||||
asset_stack: AssetStack;
|
asset_stack: AssetStack;
|
||||||
|
asset_user: AssetUser;
|
||||||
assets: Assets;
|
assets: Assets;
|
||||||
audit: Audit;
|
audit: Audit;
|
||||||
exif: Exif;
|
exif: Exif;
|
||||||
@@ -438,6 +440,6 @@ export interface DB {
|
|||||||
tags_closure: TagsClosure;
|
tags_closure: TagsClosure;
|
||||||
user_metadata: UserMetadata;
|
user_metadata: UserMetadata;
|
||||||
users: Users;
|
users: Users;
|
||||||
"vectors.pg_vector_index_stat": VectorsPgVectorIndexStat;
|
'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
|
||||||
version_history: VersionHistory;
|
version_history: VersionHistory;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
|
import { Column, Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity('asset_user')
|
||||||
|
@Index('IDX_assetId_userId', ['assetId', 'userId'])
|
||||||
|
export class AssetUserEntity {
|
||||||
|
@PrimaryColumn()
|
||||||
|
assetId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||||
|
asset!: AssetEntity;
|
||||||
|
|
||||||
|
@PrimaryColumn()
|
||||||
|
userId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||||
|
user!: UserEntity;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
createdAt!: Date;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { APIKeyEntity } from 'src/entities/api-key.entity';
|
|||||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||||
import { AssetFileEntity } from 'src/entities/asset-files.entity';
|
import { AssetFileEntity } from 'src/entities/asset-files.entity';
|
||||||
import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity';
|
import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity';
|
||||||
|
import { AssetUserEntity } from 'src/entities/asset-user.entity';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { AuditEntity } from 'src/entities/audit.entity';
|
import { AuditEntity } from 'src/entities/audit.entity';
|
||||||
import { ExifEntity } from 'src/entities/exif.entity';
|
import { ExifEntity } from 'src/entities/exif.entity';
|
||||||
@@ -34,6 +35,7 @@ export const entities = [
|
|||||||
AssetEntity,
|
AssetEntity,
|
||||||
AssetFaceEntity,
|
AssetFaceEntity,
|
||||||
AssetFileEntity,
|
AssetFileEntity,
|
||||||
|
AssetUserEntity,
|
||||||
AssetJobStatusEntity,
|
AssetJobStatusEntity,
|
||||||
AuditEntity,
|
AuditEntity,
|
||||||
ExifEntity,
|
ExifEntity,
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export interface IUserRepository {
|
|||||||
getUserStats(): Promise<UserStatsQueryResponse[]>;
|
getUserStats(): Promise<UserStatsQueryResponse[]>;
|
||||||
create(user: Insertable<Users>): Promise<UserEntity>;
|
create(user: Insertable<Users>): Promise<UserEntity>;
|
||||||
update(id: string, user: Updateable<Users>): Promise<UserEntity>;
|
update(id: string, user: Updateable<Users>): Promise<UserEntity>;
|
||||||
restore(id: string): Promise<UserEntity>;
|
|
||||||
upsertMetadata<T extends keyof UserMetadata>(id: string, item: { key: T; value: UserMetadata[T] }): Promise<void>;
|
upsertMetadata<T extends keyof UserMetadata>(id: string, item: { key: T; value: UserMetadata[T] }): Promise<void>;
|
||||||
deleteMetadata<T extends keyof UserMetadata>(id: string, key: T): Promise<void>;
|
deleteMetadata<T extends keyof UserMetadata>(id: string, key: T): Promise<void>;
|
||||||
delete(user: UserEntity, hard?: boolean): Promise<UserEntity>;
|
delete(user: UserEntity, hard?: boolean): Promise<UserEntity>;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddAssetUserTable1738099775096 implements MigrationInterface {
|
||||||
|
name = 'AddAssetUserTable1738099775096'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "asset_user" ("assetId" uuid NOT NULL, "userId" uuid NOT NULL, "createdAt" TIMESTAMP NOT NULL, CONSTRAINT "PK_f3d7f17ab93d60e007282726058" PRIMARY KEY ("assetId", "userId"))`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_assetId_userId" ON "asset_user" ("assetId", "userId") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_user" ADD CONSTRAINT "FK_07c8478e0936e78b553aaeceedb" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_user" ADD CONSTRAINT "FK_85e2ef24493bdf649dfdfb769a2" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_user" DROP CONSTRAINT "FK_85e2ef24493bdf649dfdfb769a2"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_user" DROP CONSTRAINT "FK_07c8478e0936e78b553aaeceedb"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_assetId_userId"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "asset_user"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -81,7 +81,24 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create(asset: Insertable<Assets>): Promise<AssetEntity> {
|
create(asset: Insertable<Assets>): Promise<AssetEntity> {
|
||||||
return this.db.insertInto('assets').values(asset).returningAll().executeTakeFirst() as any as Promise<AssetEntity>;
|
return this.db.transaction().execute(async (tx) => {
|
||||||
|
const newAsset = (await tx
|
||||||
|
.insertInto('assets')
|
||||||
|
.values(asset)
|
||||||
|
.returningAll()
|
||||||
|
.executeTakeFirst()) as any as AssetEntity;
|
||||||
|
|
||||||
|
await tx
|
||||||
|
.insertInto('asset_user')
|
||||||
|
.values({
|
||||||
|
assetId: newAsset.id,
|
||||||
|
userId: newAsset.ownerId,
|
||||||
|
createdAt: new Date(),
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return newAsset;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
|
@GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { DB, UserMetadata as DbUserMetadata, Users } from 'src/db';
|
|||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { UserMetadata } from 'src/entities/user-metadata.entity';
|
import { UserMetadata } from 'src/entities/user-metadata.entity';
|
||||||
import { UserEntity, withMetadata } from 'src/entities/user.entity';
|
import { UserEntity, withMetadata } from 'src/entities/user.entity';
|
||||||
import { UserStatus } from 'src/enum';
|
|
||||||
import {
|
import {
|
||||||
IUserRepository,
|
IUserRepository,
|
||||||
UserFindOptions,
|
UserFindOptions,
|
||||||
@@ -141,16 +140,6 @@ export class UserRepository implements IUserRepository {
|
|||||||
.executeTakeFirst() as unknown as Promise<UserEntity>;
|
.executeTakeFirst() as unknown as Promise<UserEntity>;
|
||||||
}
|
}
|
||||||
|
|
||||||
restore(id: string): Promise<UserEntity> {
|
|
||||||
return this.db
|
|
||||||
.updateTable('users')
|
|
||||||
.set({ status: UserStatus.ACTIVE, deletedAt: null })
|
|
||||||
.where('users.id', '=', asUuid(id))
|
|
||||||
.returning(columns)
|
|
||||||
.returning(withMetadata)
|
|
||||||
.executeTakeFirst() as unknown as Promise<UserEntity>;
|
|
||||||
}
|
|
||||||
|
|
||||||
async upsertMetadata<T extends keyof UserMetadata>(id: string, { key, value }: { key: T; value: UserMetadata[T] }) {
|
async upsertMetadata<T extends keyof UserMetadata>(id: string, { key, value }: { key: T; value: UserMetadata[T] }) {
|
||||||
await this.db
|
await this.db
|
||||||
.insertInto('user_metadata')
|
.insertInto('user_metadata')
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ const validImages = [
|
|||||||
'.heic',
|
'.heic',
|
||||||
'.heif',
|
'.heif',
|
||||||
'.iiq',
|
'.iiq',
|
||||||
'.jp2',
|
|
||||||
'.jpeg',
|
'.jpeg',
|
||||||
'.jpg',
|
'.jpg',
|
||||||
'.jxl',
|
'.jxl',
|
||||||
|
|||||||
@@ -173,9 +173,9 @@ describe(UserAdminService.name, () => {
|
|||||||
|
|
||||||
it('should restore an user', async () => {
|
it('should restore an user', async () => {
|
||||||
userMock.get.mockResolvedValue(userStub.user1);
|
userMock.get.mockResolvedValue(userStub.user1);
|
||||||
userMock.restore.mockResolvedValue(userStub.user1);
|
userMock.update.mockResolvedValue(userStub.user1);
|
||||||
await expect(sut.restore(authStub.admin, userStub.user1.id)).resolves.toEqual(mapUserAdmin(userStub.user1));
|
await expect(sut.restore(authStub.admin, userStub.user1.id)).resolves.toEqual(mapUserAdmin(userStub.user1));
|
||||||
expect(userMock.restore).toHaveBeenCalledWith(userStub.user1.id);
|
expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { status: UserStatus.ACTIVE, deletedAt: null });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export class UserAdminService extends BaseService {
|
|||||||
async restore(auth: AuthDto, id: string): Promise<UserAdminResponseDto> {
|
async restore(auth: AuthDto, id: string): Promise<UserAdminResponseDto> {
|
||||||
await this.findOrFail(id, { withDeleted: true });
|
await this.findOrFail(id, { withDeleted: true });
|
||||||
await this.albumRepository.restoreAll(id);
|
await this.albumRepository.restoreAll(id);
|
||||||
const user = await this.userRepository.restore(id);
|
const user = await this.userRepository.update(id, { deletedAt: null, status: UserStatus.ACTIVE });
|
||||||
return mapUserAdmin(user);
|
return mapUserAdmin(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ describe('mimeTypes', () => {
|
|||||||
{ mimetype: 'image/heif', extension: '.heif' },
|
{ mimetype: 'image/heif', extension: '.heif' },
|
||||||
{ mimetype: 'image/hif', extension: '.hif' },
|
{ mimetype: 'image/hif', extension: '.hif' },
|
||||||
{ mimetype: 'image/iiq', extension: '.iiq' },
|
{ mimetype: 'image/iiq', extension: '.iiq' },
|
||||||
{ mimetype: 'image/jp2', extension: '.jp2' },
|
|
||||||
{ mimetype: 'image/jpeg', extension: '.jpe' },
|
{ mimetype: 'image/jpeg', extension: '.jpe' },
|
||||||
{ mimetype: 'image/jpeg', extension: '.jpeg' },
|
{ mimetype: 'image/jpeg', extension: '.jpeg' },
|
||||||
{ mimetype: 'image/jpeg', extension: '.jpg' },
|
{ mimetype: 'image/jpeg', extension: '.jpg' },
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ const image: Record<string, string[]> = {
|
|||||||
'.heif': ['image/heif'],
|
'.heif': ['image/heif'],
|
||||||
'.hif': ['image/hif'],
|
'.hif': ['image/hif'],
|
||||||
'.insp': ['image/jpeg'],
|
'.insp': ['image/jpeg'],
|
||||||
'.jp2': ['image/jp2'],
|
|
||||||
'.jpe': ['image/jpeg'],
|
'.jpe': ['image/jpeg'],
|
||||||
'.jpeg': ['image/jpeg'],
|
'.jpeg': ['image/jpeg'],
|
||||||
'.jpg': ['image/jpeg'],
|
'.jpg': ['image/jpeg'],
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export const newUserRepositoryMock = (): Mocked<IUserRepository> => {
|
|||||||
create: vitest.fn(),
|
create: vitest.fn(),
|
||||||
update: vitest.fn(),
|
update: vitest.fn(),
|
||||||
delete: vitest.fn(),
|
delete: vitest.fn(),
|
||||||
restore: vitest.fn(),
|
|
||||||
getDeletedUsers: vitest.fn(),
|
getDeletedUsers: vitest.fn(),
|
||||||
hasAdmin: vitest.fn(),
|
hasAdmin: vitest.fn(),
|
||||||
updateUsage: vitest.fn(),
|
updateUsage: vitest.fn(),
|
||||||
|
|||||||
Generated
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-web",
|
"name": "immich-web",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich-web",
|
"name": "immich-web",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formatjs/icu-messageformat-parser": "^2.9.8",
|
"@formatjs/icu-messageformat-parser": "^2.9.8",
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
},
|
},
|
||||||
"../open-api/typescript-sdk": {
|
"../open-api/typescript-sdk": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-web",
|
"name": "immich-web",
|
||||||
"version": "1.125.7",
|
"version": "1.125.6",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev --host 0.0.0.0 --port 3000",
|
"dev": "vite dev --host 0.0.0.0 --port 3000",
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
locale,
|
locale,
|
||||||
type AlbumViewSettings,
|
type AlbumViewSettings,
|
||||||
} from '$lib/stores/preferences.store';
|
} from '$lib/stores/preferences.store';
|
||||||
import { userInteraction } from '$lib/stores/user.svelte';
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
@@ -294,15 +293,6 @@
|
|||||||
sharedAlbums[sharedAlbums.findIndex(({ id }) => id === album.id)] = album;
|
sharedAlbums[sharedAlbums.findIndex(({ id }) => id === album.id)] = album;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRecentAlbumInfo = (album: AlbumResponseDto) => {
|
|
||||||
for (const cachedAlbum of userInteraction.recentAlbums || []) {
|
|
||||||
if (cachedAlbum.id === album.id) {
|
|
||||||
Object.assign(cachedAlbum, { ...cachedAlbum, ...album });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const successEditAlbumInfo = (album: AlbumResponseDto) => {
|
const successEditAlbumInfo = (album: AlbumResponseDto) => {
|
||||||
albumToEdit = null;
|
albumToEdit = null;
|
||||||
|
|
||||||
@@ -318,7 +308,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
updateAlbumInfo(album);
|
updateAlbumInfo(album);
|
||||||
updateRecentAlbumInfo(album);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddUsers = async (albumUsers: AlbumUserAddDto[]) => {
|
const handleAddUsers = async (albumUsers: AlbumUserAddDto[]) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user