Compare commits
6 Commits
asset-user
...
v1.125.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fd8c1b3c1 | ||
|
|
f3ba994186 | ||
|
|
b4a4abbf51 | ||
|
|
a0aea021a1 | ||
|
|
9033a99587 | ||
|
|
cc0cbd705e |
6
cli/package-lock.json
generated
6
cli/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.47",
|
||||
"version": "2.2.48",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.47",
|
||||
"version": "2.2.48",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"fast-glob": "^3.3.2",
|
||||
@@ -52,7 +52,7 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.47",
|
||||
"version": "2.2.48",
|
||||
"description": "Command Line Interface (CLI) for Immich",
|
||||
"type": "module",
|
||||
"exports": "./dist/index.js",
|
||||
|
||||
@@ -48,6 +48,7 @@ services:
|
||||
vaapi-wsl: # use this for VAAPI if you're running Immich in WSL2
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
- /dev/dxg:/dev/dxg
|
||||
volumes:
|
||||
- /usr/lib/wsl:/usr/lib/wsl
|
||||
environment:
|
||||
|
||||
@@ -8,22 +8,23 @@ For the full list, refer to the [Immich source code](https://github.com/immich-a
|
||||
|
||||
## Image formats
|
||||
|
||||
| Format | Extension(s) | Supported? | Notes |
|
||||
| :-------- | :---------------------------- | :----------------: | :-------------- |
|
||||
| `AVIF` | `.avif` | :white_check_mark: | |
|
||||
| `BMP` | `.bmp` | :white_check_mark: | |
|
||||
| `GIF` | `.gif` | :white_check_mark: | |
|
||||
| `HEIC` | `.heic` | :white_check_mark: | |
|
||||
| `HEIF` | `.heif` | :white_check_mark: | |
|
||||
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
|
||||
| `JPEG XL` | `.jxl` | :white_check_mark: | |
|
||||
| `PNG` | `.webp` | :white_check_mark: | |
|
||||
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
|
||||
| `RAW` | `.raw` | :white_check_mark: | |
|
||||
| `RW2` | `.rw2` | :white_check_mark: | |
|
||||
| `SVG` | `.svg` | :white_check_mark: | |
|
||||
| `TIFF` | `.tif` `.tiff` | :white_check_mark: | |
|
||||
| `WEBP` | `.webp` | :white_check_mark: | |
|
||||
| Format | Extension(s) | Supported? | Notes |
|
||||
| :---------- | :---------------------------- | :----------------: | :-------------- |
|
||||
| `AVIF` | `.avif` | :white_check_mark: | |
|
||||
| `BMP` | `.bmp` | :white_check_mark: | |
|
||||
| `GIF` | `.gif` | :white_check_mark: | |
|
||||
| `HEIC` | `.heic` | :white_check_mark: | |
|
||||
| `HEIF` | `.heif` | :white_check_mark: | |
|
||||
| `JPEG 2000` | `.jp2` | :white_check_mark: | |
|
||||
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
|
||||
| `JPEG XL` | `.jxl` | :white_check_mark: | |
|
||||
| `PNG` | `.webp` | :white_check_mark: | |
|
||||
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
|
||||
| `RAW` | `.raw` | :white_check_mark: | |
|
||||
| `RW2` | `.rw2` | :white_check_mark: | |
|
||||
| `SVG` | `.svg` | :white_check_mark: | |
|
||||
| `TIFF` | `.tif` `.tiff` | :white_check_mark: | |
|
||||
| `WEBP` | `.webp` | :white_check_mark: | |
|
||||
|
||||
## Video formats
|
||||
|
||||
|
||||
4
docs/static/archived-versions.json
vendored
4
docs/static/archived-versions.json
vendored
@@ -1,4 +1,8 @@
|
||||
[
|
||||
{
|
||||
"label": "v1.125.7",
|
||||
"url": "https://v1.125.7.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.125.6",
|
||||
"url": "https://v1.125.6.archive.immich.app"
|
||||
|
||||
8
e2e/package-lock.json
generated
8
e2e/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich-e2e",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
},
|
||||
"../cli": {
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.47",
|
||||
"version": "2.2.48",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
@@ -92,7 +92,7 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
||||
@@ -356,5 +356,24 @@ describe('/admin/users', () => {
|
||||
expect(status).toBe(403);
|
||||
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]
|
||||
name = "machine-learning"
|
||||
version = "1.125.6"
|
||||
version = "1.125.7"
|
||||
description = ""
|
||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||
readme = "README.md"
|
||||
|
||||
@@ -36,7 +36,7 @@ platform :android do
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 182,
|
||||
"android.injected.version.name" => "1.125.6",
|
||||
"android.injected.version.name" => "1.125.7",
|
||||
}
|
||||
)
|
||||
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"
|
||||
lane :release do
|
||||
increment_version_number(
|
||||
version_number: "1.125.6"
|
||||
version_number: "1.125.7"
|
||||
)
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
|
||||
10
mobile/openapi/README.md
generated
10
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.125.6
|
||||
- API version: 1.125.7
|
||||
- Generator version: 7.8.0
|
||||
- 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* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} |
|
||||
*AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} |
|
||||
*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 | Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||
*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | checkBulkUpload
|
||||
*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | checkExistingAssets
|
||||
*AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets |
|
||||
*AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original |
|
||||
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | Get all asset of a device that are in the database, ID only.
|
||||
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | getAllUserAssetsByDeviceId
|
||||
*AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} |
|
||||
*AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics |
|
||||
*AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane |
|
||||
*AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random |
|
||||
*AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback |
|
||||
*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | Replace the asset with new file, without changing its id
|
||||
*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | replaceAsset
|
||||
*AssetsApi* | [**runAssetJobs**](doc//AssetsApi.md#runassetjobs) | **POST** /assets/jobs |
|
||||
*AssetsApi* | [**updateAsset**](doc//AssetsApi.md#updateasset) | **PUT** /assets/{id} |
|
||||
*AssetsApi* | [**updateAssets**](doc//AssetsApi.md#updateassets) | **PUT** /assets |
|
||||
|
||||
16
mobile/openapi/lib/api/assets_api.dart
generated
16
mobile/openapi/lib/api/assets_api.dart
generated
@@ -16,6 +16,8 @@ class AssetsApi {
|
||||
|
||||
final ApiClient apiClient;
|
||||
|
||||
/// checkBulkUpload
|
||||
///
|
||||
/// Checks if assets exist by checksums
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
@@ -48,6 +50,8 @@ class AssetsApi {
|
||||
);
|
||||
}
|
||||
|
||||
/// checkBulkUpload
|
||||
///
|
||||
/// Checks if assets exist by checksums
|
||||
///
|
||||
/// Parameters:
|
||||
@@ -68,6 +72,8 @@ class AssetsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// checkExistingAssets
|
||||
///
|
||||
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
@@ -100,6 +106,8 @@ class AssetsApi {
|
||||
);
|
||||
}
|
||||
|
||||
/// checkExistingAssets
|
||||
///
|
||||
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||
///
|
||||
/// Parameters:
|
||||
@@ -215,6 +223,8 @@ class AssetsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// getAllUserAssetsByDeviceId
|
||||
///
|
||||
/// Get all asset of a device that are in the database, ID only.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
@@ -248,6 +258,8 @@ class AssetsApi {
|
||||
);
|
||||
}
|
||||
|
||||
/// getAllUserAssetsByDeviceId
|
||||
///
|
||||
/// Get all asset of a device that are in the database, ID only.
|
||||
///
|
||||
/// Parameters:
|
||||
@@ -564,6 +576,8 @@ class AssetsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// replaceAsset
|
||||
///
|
||||
/// Replace the asset with new file, without changing its id
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
@@ -645,6 +659,8 @@ class AssetsApi {
|
||||
);
|
||||
}
|
||||
|
||||
/// replaceAsset
|
||||
///
|
||||
/// Replace the asset with new file, without changing its id
|
||||
///
|
||||
/// Parameters:
|
||||
|
||||
@@ -2,7 +2,7 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: 'none'
|
||||
version: 1.125.6+182
|
||||
version: 1.125.7+182
|
||||
|
||||
environment:
|
||||
sdk: '>=3.3.0 <4.0.0'
|
||||
|
||||
@@ -539,7 +539,7 @@
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@@ -1424,6 +1424,7 @@
|
||||
},
|
||||
"/assets/bulk-upload-check": {
|
||||
"post": {
|
||||
"description": "Checks if assets exist by checksums",
|
||||
"operationId": "checkBulkUpload",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
@@ -1459,7 +1460,7 @@
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"summary": "Checks if assets exist by checksums",
|
||||
"summary": "checkBulkUpload",
|
||||
"tags": [
|
||||
"Assets"
|
||||
]
|
||||
@@ -1467,6 +1468,7 @@
|
||||
},
|
||||
"/assets/device/{deviceId}": {
|
||||
"get": {
|
||||
"description": "Get all asset of a device that are in the database, ID only.",
|
||||
"operationId": "getAllUserAssetsByDeviceId",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -1504,7 +1506,7 @@
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"summary": "Get all asset of a device that are in the database, ID only.",
|
||||
"summary": "getAllUserAssetsByDeviceId",
|
||||
"tags": [
|
||||
"Assets"
|
||||
]
|
||||
@@ -1512,6 +1514,7 @@
|
||||
},
|
||||
"/assets/exist": {
|
||||
"post": {
|
||||
"description": "Checks if multiple assets exist on the server and returns all existing - used by background backup",
|
||||
"operationId": "checkExistingAssets",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
@@ -1547,7 +1550,7 @@
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"summary": "Checks if multiple assets exist on the server and returns all existing - used by background backup",
|
||||
"summary": "checkExistingAssets",
|
||||
"tags": [
|
||||
"Assets"
|
||||
]
|
||||
@@ -1903,6 +1906,7 @@
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"description": "Replace the asset with new file, without changing its id",
|
||||
"operationId": "replaceAsset",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -1956,7 +1960,7 @@
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"summary": "Replace the asset with new file, without changing its id",
|
||||
"summary": "replaceAsset",
|
||||
"tags": [
|
||||
"Assets"
|
||||
],
|
||||
@@ -7454,7 +7458,7 @@
|
||||
"info": {
|
||||
"title": "Immich",
|
||||
"description": "Immich API",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"contact": {}
|
||||
},
|
||||
"tags": [],
|
||||
|
||||
4
open-api/typescript-sdk/package-lock.json
generated
4
open-api/typescript-sdk/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||
"type": "module",
|
||||
"main": "./build/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Immich
|
||||
* 1.125.6
|
||||
* 1.125.7
|
||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||
* See https://www.npmjs.com/package/oazapfts
|
||||
*/
|
||||
@@ -1475,7 +1475,7 @@ export function restoreUserAdmin({ id }: {
|
||||
id: string;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 201;
|
||||
status: 200;
|
||||
data: UserAdminResponseDto;
|
||||
}>(`/admin/users/${encodeURIComponent(id)}/restore`, {
|
||||
...opts,
|
||||
@@ -1703,7 +1703,7 @@ export function updateAssets({ assetBulkUpdateDto }: {
|
||||
})));
|
||||
}
|
||||
/**
|
||||
* Checks if assets exist by checksums
|
||||
* checkBulkUpload
|
||||
*/
|
||||
export function checkBulkUpload({ assetBulkUploadCheckDto }: {
|
||||
assetBulkUploadCheckDto: AssetBulkUploadCheckDto;
|
||||
@@ -1718,7 +1718,7 @@ export function checkBulkUpload({ assetBulkUploadCheckDto }: {
|
||||
})));
|
||||
}
|
||||
/**
|
||||
* Get all asset of a device that are in the database, ID only.
|
||||
* getAllUserAssetsByDeviceId
|
||||
*/
|
||||
export function getAllUserAssetsByDeviceId({ deviceId }: {
|
||||
deviceId: string;
|
||||
@@ -1731,7 +1731,7 @@ export function getAllUserAssetsByDeviceId({ deviceId }: {
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||
* checkExistingAssets
|
||||
*/
|
||||
export function checkExistingAssets({ checkExistingAssetsDto }: {
|
||||
checkExistingAssetsDto: CheckExistingAssetsDto;
|
||||
@@ -1839,7 +1839,7 @@ export function downloadAsset({ id, key }: {
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Replace the asset with new file, without changing its id
|
||||
* replaceAsset
|
||||
*/
|
||||
export function replaceAsset({ id, key, assetMediaReplaceDto }: {
|
||||
id: string;
|
||||
|
||||
4
server/package-lock.json
generated
4
server/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@nestjs/bullmq": "^11.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
UploadedFiles,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger';
|
||||
import { ApiBody, ApiConsumes, ApiHeader, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { NextFunction, Response } from 'express';
|
||||
import { EndpointLifecycle } from 'src/decorators';
|
||||
import {
|
||||
@@ -94,6 +94,10 @@ export class AssetMediaController {
|
||||
@UseInterceptors(FileUploadInterceptor)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@EndpointLifecycle({ addedAt: 'v1.106.0' })
|
||||
@ApiOperation({
|
||||
summary: 'replaceAsset',
|
||||
description: 'Replace the asset with new file, without changing its id',
|
||||
})
|
||||
@Authenticated({ sharedLink: true })
|
||||
async replaceAsset(
|
||||
@Auth() auth: AuthDto,
|
||||
@@ -141,6 +145,10 @@ export class AssetMediaController {
|
||||
*/
|
||||
@Post('exist')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({
|
||||
summary: 'checkExistingAssets',
|
||||
description: 'Checks if multiple assets exist on the server and returns all existing - used by background backup',
|
||||
})
|
||||
@Authenticated()
|
||||
checkExistingAssets(
|
||||
@Auth() auth: AuthDto,
|
||||
@@ -154,6 +162,10 @@ export class AssetMediaController {
|
||||
*/
|
||||
@Post('bulk-upload-check')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({
|
||||
summary: 'checkBulkUpload',
|
||||
description: 'Checks if assets exist by checksums',
|
||||
})
|
||||
@Authenticated()
|
||||
checkBulkUpload(
|
||||
@Auth() auth: AuthDto,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { EndpointLifecycle } from 'src/decorators';
|
||||
import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto';
|
||||
import {
|
||||
@@ -41,6 +41,10 @@ export class AssetController {
|
||||
* Get all asset of a device that are in the database, ID only.
|
||||
*/
|
||||
@Get('/device/:deviceId')
|
||||
@ApiOperation({
|
||||
summary: 'getAllUserAssetsByDeviceId',
|
||||
description: 'Get all asset of a device that are in the database, ID only.',
|
||||
})
|
||||
@Authenticated()
|
||||
getAllUserAssetsByDeviceId(@Auth() auth: AuthDto, @Param() { deviceId }: DeviceIdDto) {
|
||||
return this.service.getUserAssetsByDeviceId(auth, deviceId);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { UserPreferencesResponseDto, UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto';
|
||||
@@ -75,6 +75,7 @@ export class UserAdminController {
|
||||
|
||||
@Post(':id/restore')
|
||||
@Authenticated({ permission: Permission.ADMIN_USER_DELETE, admin: true })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
restoreUserAdmin(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<UserAdminResponseDto> {
|
||||
return this.service.restore(auth, id);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface IUserRepository {
|
||||
getUserStats(): Promise<UserStatsQueryResponse[]>;
|
||||
create(user: Insertable<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>;
|
||||
deleteMetadata<T extends keyof UserMetadata>(id: string, key: T): Promise<void>;
|
||||
delete(user: UserEntity, hard?: boolean): Promise<UserEntity>;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { DB, UserMetadata as DbUserMetadata, Users } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { UserMetadata } from 'src/entities/user-metadata.entity';
|
||||
import { UserEntity, withMetadata } from 'src/entities/user.entity';
|
||||
import { UserStatus } from 'src/enum';
|
||||
import {
|
||||
IUserRepository,
|
||||
UserFindOptions,
|
||||
@@ -140,6 +141,16 @@ export class UserRepository implements IUserRepository {
|
||||
.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] }) {
|
||||
await this.db
|
||||
.insertInto('user_metadata')
|
||||
|
||||
@@ -73,6 +73,7 @@ const validImages = [
|
||||
'.heic',
|
||||
'.heif',
|
||||
'.iiq',
|
||||
'.jp2',
|
||||
'.jpeg',
|
||||
'.jpg',
|
||||
'.jxl',
|
||||
|
||||
@@ -173,9 +173,9 @@ describe(UserAdminService.name, () => {
|
||||
|
||||
it('should restore an user', async () => {
|
||||
userMock.get.mockResolvedValue(userStub.user1);
|
||||
userMock.update.mockResolvedValue(userStub.user1);
|
||||
userMock.restore.mockResolvedValue(userStub.user1);
|
||||
await expect(sut.restore(authStub.admin, userStub.user1.id)).resolves.toEqual(mapUserAdmin(userStub.user1));
|
||||
expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { status: UserStatus.ACTIVE, deletedAt: null });
|
||||
expect(userMock.restore).toHaveBeenCalledWith(userStub.user1.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@ export class UserAdminService extends BaseService {
|
||||
async restore(auth: AuthDto, id: string): Promise<UserAdminResponseDto> {
|
||||
await this.findOrFail(id, { withDeleted: true });
|
||||
await this.albumRepository.restoreAll(id);
|
||||
const user = await this.userRepository.update(id, { deletedAt: null, status: UserStatus.ACTIVE });
|
||||
const user = await this.userRepository.restore(id);
|
||||
return mapUserAdmin(user);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ describe('mimeTypes', () => {
|
||||
{ mimetype: 'image/heif', extension: '.heif' },
|
||||
{ mimetype: 'image/hif', extension: '.hif' },
|
||||
{ mimetype: 'image/iiq', extension: '.iiq' },
|
||||
{ mimetype: 'image/jp2', extension: '.jp2' },
|
||||
{ mimetype: 'image/jpeg', extension: '.jpe' },
|
||||
{ mimetype: 'image/jpeg', extension: '.jpeg' },
|
||||
{ mimetype: 'image/jpeg', extension: '.jpg' },
|
||||
|
||||
@@ -43,6 +43,7 @@ const image: Record<string, string[]> = {
|
||||
'.heif': ['image/heif'],
|
||||
'.hif': ['image/hif'],
|
||||
'.insp': ['image/jpeg'],
|
||||
'.jp2': ['image/jp2'],
|
||||
'.jpe': ['image/jpeg'],
|
||||
'.jpeg': ['image/jpeg'],
|
||||
'.jpg': ['image/jpeg'],
|
||||
|
||||
@@ -13,6 +13,7 @@ export const newUserRepositoryMock = (): Mocked<IUserRepository> => {
|
||||
create: vitest.fn(),
|
||||
update: vitest.fn(),
|
||||
delete: vitest.fn(),
|
||||
restore: vitest.fn(),
|
||||
getDeletedUsers: vitest.fn(),
|
||||
hasAdmin: vitest.fn(),
|
||||
updateUsage: vitest.fn(),
|
||||
|
||||
6
web/package-lock.json
generated
6
web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich-web",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich-web",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^2.9.8",
|
||||
@@ -77,7 +77,7 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-web",
|
||||
"version": "1.125.6",
|
||||
"version": "1.125.7",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"scripts": {
|
||||
"dev": "vite dev --host 0.0.0.0 --port 3000",
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
locale,
|
||||
type AlbumViewSettings,
|
||||
} from '$lib/stores/preferences.store';
|
||||
import { userInteraction } from '$lib/stores/user.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { t } from 'svelte-i18n';
|
||||
@@ -293,6 +294,15 @@
|
||||
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) => {
|
||||
albumToEdit = null;
|
||||
|
||||
@@ -308,6 +318,7 @@
|
||||
});
|
||||
|
||||
updateAlbumInfo(album);
|
||||
updateRecentAlbumInfo(album);
|
||||
};
|
||||
|
||||
const handleAddUsers = async (albumUsers: AlbumUserAddDto[]) => {
|
||||
|
||||
Reference in New Issue
Block a user