Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 43d66c7a36 |
Generated
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.49",
|
"version": "2.2.48",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.49",
|
"version": "2.2.48",
|
||||||
"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.126.0",
|
"version": "1.125.7",
|
||||||
"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.49",
|
"version": "2.2.48",
|
||||||
"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",
|
||||||
|
|||||||
+30
-30
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.52.0"
|
version = "4.50.0"
|
||||||
constraints = "4.52.0"
|
constraints = "4.50.0"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:2BEJyXJtYC4B4nda/WCYUmuJYDaYk88F8t1pwPzr0iQ=",
|
"h1:0qvD5ZKn2tMZ8cOjQrUSITIC9tKCZbrSaSswV9lOyiU=",
|
||||||
"h1:4IASk5SESeWKQ7JU0+M7KApuF5mZyklvwMXPBabim3c=",
|
"h1:4N0gplrZ0zOsJv3Kx1VfIx2FwrZHbYU0Un2yfiLZIGQ=",
|
||||||
"h1:5ImZxxALSnWfH/4EXw/wFirSmk5Tr0ACmcysy51AafE=",
|
"h1:81AMQq4kNKU/35U8ElQegUxG4E6xB0erIjG5xVmjIyo=",
|
||||||
"h1:6TJ3dxLSin4ZKBJLsZDn95H2ZYnGm8S7GGHvvXuuMQU=",
|
"h1:EEQNADUmV3IL6x00yzy04i7OCSLeOMgM9XQkV3w71gA=",
|
||||||
"h1:IzTUjg9kQ4N3qizP9CjYLeHwjsuGgtxwXvfUQWyOLcA=",
|
"h1:HD0KI7td6oiSSAnJNn8UPSGf+hKiTo4JVQYfAiU1SqM=",
|
||||||
"h1:NTaOQfYINA0YTG/V1/9+SYtgX1it63+cBugj4WK4FWc=",
|
"h1:Hl+o5LtcvZg2f3l1hh9vaG/DFK6k+dTIZSeM0lXyfpo=",
|
||||||
"h1:PXH48LuJn329sCfMXprdMDk51EZaWFyajVvS03qhQLs=",
|
"h1:ZUO2oIJ6jtZdvl816h0cEIiIeZ/fFCF64+abGEVxZZM=",
|
||||||
"h1:Pi5M+GeoMSN2eJ6QnIeXjBf19O+rby/74CfB2ocpv20=",
|
"h1:Zio80fnEeUKdlSOhTVskMEFSLUQ6TMsMKnXc+Dy2P2A=",
|
||||||
"h1:ShXZ2ZjBvm3thfoPPzPT8+OhyismnydQVkUAfI8X12w=",
|
"h1:aLLvg36evTyqjtXGV2MjAV8imktXFmry7p/xCu9GQC4=",
|
||||||
"h1:WQ9hu0Wge2msBbODfottCSKgu8oKUrw4Opz+fDPVVHk=",
|
"h1:azL05eWyy2V8SWkbZZImPWvv8ynG4eqmrbZhjXBDFug=",
|
||||||
"h1:Z5yXML2DE0uH9UU+M0ut9JMQAORcwVZz1CxBHzeBmao=",
|
"h1:ckMysHY4fJmr7o58XMi+DdgOTB/U/Mf1u1JA9ly3g/I=",
|
||||||
"h1:jqI2qKknpleS3JDSplyGYHMu0u9K/tor1ZOjFwDgEMk=",
|
"h1:jxOwjDNjt5WCb4YjjiMsman91O8Y+MAPz6UwJ4a6F+0=",
|
||||||
"h1:kgfutDh14Q5nw4eg6qGFamFxIiY8Ae0FPKRBLDOzpcI=",
|
"h1:u4OfnjSLa4Wk1IUFAzrvMnGgr8MvRHEWVDHEScPK2E8=",
|
||||||
"h1:zCAO7GZmfYhWb+i6TfqlqhMeDyPZWGio2IzEzAh3YTs=",
|
"h1:wQkR1oeSkzlHn3rnVuLJRJLBHlg4EHt7Y64DeTjfkjQ=",
|
||||||
"zh:19be1a91c982b902c42aba47766860dfa5dc151eed1e95fd39ca642229381ef0",
|
"zh:0ef99ed39472a94e6a0d6fa733cf0a46bce3bf66eba2873efae8846efdddc237",
|
||||||
"zh:1de451c4d1ecf7efbe67b6dace3426ba810711afdd644b0f1b870364c8ae91f8",
|
"zh:2929cbbffcead171d45c88e4a7a59e9c013ea775dafa68b10da8db7cd04b6140",
|
||||||
"zh:352b4a2120173298622e669258744554339d959ac3a95607b117a48ee4a83238",
|
"zh:462601c87118088e1a718842e367af7d8e7620598d426980a6d6b33de759865e",
|
||||||
"zh:3c6f1346d9154afbd2d558fabb4b0150fc8d559aa961254144fe1bc17fe6032f",
|
"zh:56766eb62a74a9d88d9efb8486dd3a0c5c9db873d0a980ae9ef1e8af27d74231",
|
||||||
"zh:4c4c92d53fb535b1e0eff26f222bbd627b97d3b4c891ec9c321268676d06152f",
|
"zh:6b4e8810d99498a5a20a5872982a0f1354e79cfc4a7dfe7cc656f1c7eaae47d8",
|
||||||
"zh:53276f68006c9ceb7cdb10a6ccf91a5c1eadd1407a28edb5741e84e88d7e29e8",
|
"zh:6d65bdb4ec94b6eecc8abe26d94e2ca09262dc1e7a9934db829f418be0119920",
|
||||||
"zh:7925a97773948171a63d4f65bb81ee92fd6d07a447e36012977313293a5435c9",
|
"zh:71adeaf31e41a358ec6095004062e43f56ee7d4b2504e5613ab351d511695641",
|
||||||
"zh:7dfb0a4496cfe032437386d0a2cd9229a1956e9c30bd920923c141b0f0440060",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:8d4aa79f0a414bb4163d771063c70cd991c8fac6c766e685bac2ee12903c5bd6",
|
"zh:89761c15908ccc2cf9c50bb5cb3be45d3ad0c45fc7c608c6b95f48c0288b7160",
|
||||||
"zh:a67540c13565616a7e7e51ee9366e88b0dc60046e1d75c72680e150bd02725bb",
|
"zh:8cc5d7c5939da89cfd01f3e51c84f3576564783acea9db86bd9e32049805ed96",
|
||||||
"zh:a936383a4767f5393f38f622e92bf2d0c03fe04b69c284951f27345766c7b31b",
|
"zh:987cff8225b1dd436cdcb4fc6228689ae7e4281de6896412a2a9a3325c49f05e",
|
||||||
"zh:d4887d73c466ff036eecf50ad6404ba38fd82ea4855296b1846d244b0f13c380",
|
"zh:991e83ebb89867d71e01a1c215ed159efb425683b0a44707be8579eb0a337f06",
|
||||||
"zh:e9093c8bd5b6cd99c81666e315197791781b8f93afa14fc2e0f732d1bb2a44b7",
|
"zh:ab8177ae2d8f5cfa90043a6f867435012cae115f6061b832a7e2462e0ae87a67",
|
||||||
"zh:efd3b3f1ec59a37f635aa1d4efcf178734c2fcf8ddb0d56ea690bec342da8672",
|
"zh:d1ca34df1398f201274a6a18102975148c10ca15aa43cfc56cc9897620929509",
|
||||||
|
"zh:d34946f70201baf6dda03e3b294c6bbe40d95d0278e97b9f636ded94822b24ac",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.52.0"
|
version = "4.50.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-30
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.52.0"
|
version = "4.50.0"
|
||||||
constraints = "4.52.0"
|
constraints = "4.50.0"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:2BEJyXJtYC4B4nda/WCYUmuJYDaYk88F8t1pwPzr0iQ=",
|
"h1:0qvD5ZKn2tMZ8cOjQrUSITIC9tKCZbrSaSswV9lOyiU=",
|
||||||
"h1:4IASk5SESeWKQ7JU0+M7KApuF5mZyklvwMXPBabim3c=",
|
"h1:4N0gplrZ0zOsJv3Kx1VfIx2FwrZHbYU0Un2yfiLZIGQ=",
|
||||||
"h1:5ImZxxALSnWfH/4EXw/wFirSmk5Tr0ACmcysy51AafE=",
|
"h1:81AMQq4kNKU/35U8ElQegUxG4E6xB0erIjG5xVmjIyo=",
|
||||||
"h1:6TJ3dxLSin4ZKBJLsZDn95H2ZYnGm8S7GGHvvXuuMQU=",
|
"h1:EEQNADUmV3IL6x00yzy04i7OCSLeOMgM9XQkV3w71gA=",
|
||||||
"h1:IzTUjg9kQ4N3qizP9CjYLeHwjsuGgtxwXvfUQWyOLcA=",
|
"h1:HD0KI7td6oiSSAnJNn8UPSGf+hKiTo4JVQYfAiU1SqM=",
|
||||||
"h1:NTaOQfYINA0YTG/V1/9+SYtgX1it63+cBugj4WK4FWc=",
|
"h1:Hl+o5LtcvZg2f3l1hh9vaG/DFK6k+dTIZSeM0lXyfpo=",
|
||||||
"h1:PXH48LuJn329sCfMXprdMDk51EZaWFyajVvS03qhQLs=",
|
"h1:ZUO2oIJ6jtZdvl816h0cEIiIeZ/fFCF64+abGEVxZZM=",
|
||||||
"h1:Pi5M+GeoMSN2eJ6QnIeXjBf19O+rby/74CfB2ocpv20=",
|
"h1:Zio80fnEeUKdlSOhTVskMEFSLUQ6TMsMKnXc+Dy2P2A=",
|
||||||
"h1:ShXZ2ZjBvm3thfoPPzPT8+OhyismnydQVkUAfI8X12w=",
|
"h1:aLLvg36evTyqjtXGV2MjAV8imktXFmry7p/xCu9GQC4=",
|
||||||
"h1:WQ9hu0Wge2msBbODfottCSKgu8oKUrw4Opz+fDPVVHk=",
|
"h1:azL05eWyy2V8SWkbZZImPWvv8ynG4eqmrbZhjXBDFug=",
|
||||||
"h1:Z5yXML2DE0uH9UU+M0ut9JMQAORcwVZz1CxBHzeBmao=",
|
"h1:ckMysHY4fJmr7o58XMi+DdgOTB/U/Mf1u1JA9ly3g/I=",
|
||||||
"h1:jqI2qKknpleS3JDSplyGYHMu0u9K/tor1ZOjFwDgEMk=",
|
"h1:jxOwjDNjt5WCb4YjjiMsman91O8Y+MAPz6UwJ4a6F+0=",
|
||||||
"h1:kgfutDh14Q5nw4eg6qGFamFxIiY8Ae0FPKRBLDOzpcI=",
|
"h1:u4OfnjSLa4Wk1IUFAzrvMnGgr8MvRHEWVDHEScPK2E8=",
|
||||||
"h1:zCAO7GZmfYhWb+i6TfqlqhMeDyPZWGio2IzEzAh3YTs=",
|
"h1:wQkR1oeSkzlHn3rnVuLJRJLBHlg4EHt7Y64DeTjfkjQ=",
|
||||||
"zh:19be1a91c982b902c42aba47766860dfa5dc151eed1e95fd39ca642229381ef0",
|
"zh:0ef99ed39472a94e6a0d6fa733cf0a46bce3bf66eba2873efae8846efdddc237",
|
||||||
"zh:1de451c4d1ecf7efbe67b6dace3426ba810711afdd644b0f1b870364c8ae91f8",
|
"zh:2929cbbffcead171d45c88e4a7a59e9c013ea775dafa68b10da8db7cd04b6140",
|
||||||
"zh:352b4a2120173298622e669258744554339d959ac3a95607b117a48ee4a83238",
|
"zh:462601c87118088e1a718842e367af7d8e7620598d426980a6d6b33de759865e",
|
||||||
"zh:3c6f1346d9154afbd2d558fabb4b0150fc8d559aa961254144fe1bc17fe6032f",
|
"zh:56766eb62a74a9d88d9efb8486dd3a0c5c9db873d0a980ae9ef1e8af27d74231",
|
||||||
"zh:4c4c92d53fb535b1e0eff26f222bbd627b97d3b4c891ec9c321268676d06152f",
|
"zh:6b4e8810d99498a5a20a5872982a0f1354e79cfc4a7dfe7cc656f1c7eaae47d8",
|
||||||
"zh:53276f68006c9ceb7cdb10a6ccf91a5c1eadd1407a28edb5741e84e88d7e29e8",
|
"zh:6d65bdb4ec94b6eecc8abe26d94e2ca09262dc1e7a9934db829f418be0119920",
|
||||||
"zh:7925a97773948171a63d4f65bb81ee92fd6d07a447e36012977313293a5435c9",
|
"zh:71adeaf31e41a358ec6095004062e43f56ee7d4b2504e5613ab351d511695641",
|
||||||
"zh:7dfb0a4496cfe032437386d0a2cd9229a1956e9c30bd920923c141b0f0440060",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:8d4aa79f0a414bb4163d771063c70cd991c8fac6c766e685bac2ee12903c5bd6",
|
"zh:89761c15908ccc2cf9c50bb5cb3be45d3ad0c45fc7c608c6b95f48c0288b7160",
|
||||||
"zh:a67540c13565616a7e7e51ee9366e88b0dc60046e1d75c72680e150bd02725bb",
|
"zh:8cc5d7c5939da89cfd01f3e51c84f3576564783acea9db86bd9e32049805ed96",
|
||||||
"zh:a936383a4767f5393f38f622e92bf2d0c03fe04b69c284951f27345766c7b31b",
|
"zh:987cff8225b1dd436cdcb4fc6228689ae7e4281de6896412a2a9a3325c49f05e",
|
||||||
"zh:d4887d73c466ff036eecf50ad6404ba38fd82ea4855296b1846d244b0f13c380",
|
"zh:991e83ebb89867d71e01a1c215ed159efb425683b0a44707be8579eb0a337f06",
|
||||||
"zh:e9093c8bd5b6cd99c81666e315197791781b8f93afa14fc2e0f732d1bb2a44b7",
|
"zh:ab8177ae2d8f5cfa90043a6f867435012cae115f6061b832a7e2462e0ae87a67",
|
||||||
"zh:efd3b3f1ec59a37f635aa1d4efcf178734c2fcf8ddb0d56ea690bec342da8672",
|
"zh:d1ca34df1398f201274a6a18102975148c10ca15aa43cfc56cc9897620929509",
|
||||||
|
"zh:d34946f70201baf6dda03e3b294c6bbe40d95d0278e97b9f636ded94822b24ac",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.52.0"
|
version = "4.50.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ services:
|
|||||||
command: ['./run.sh', '-disable-reporting']
|
command: ['./run.sh', '-disable-reporting']
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:11.5.1-ubuntu@sha256:9a4ab78cec1a2ec7d1ca5dfd5aacec6412706a1bc9e971fc7184e2f6696a63f5
|
image: grafana/grafana:11.4.0-ubuntu@sha256:afccec22ba0e4815cca1d2bf3836e414322390dc78d77f1851976ffa8d61051c
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ To see local changes to `@immich/ui` in Immich, do the following:
|
|||||||
|
|
||||||
### Mobile app
|
### Mobile app
|
||||||
|
|
||||||
The mobile app `(/mobile)` will required Flutter toolchain 3.13.x and FVM to be installed on your system.
|
The mobile app `(/mobile)` will required Flutter toolchain 3.13.x to be installed on your system.
|
||||||
|
|
||||||
Please refer to the [Flutter's official documentation](https://flutter.dev/docs/get-started/install) for more information on setting up the toolchain on your machine.
|
Please refer to the [Flutter's official documentation](https://flutter.dev/docs/get-started/install) for more information on setting up the toolchain on your machine.
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
|
|
||||||
- ARM NN (Mali)
|
- ARM NN (Mali)
|
||||||
- CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher)
|
- CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher)
|
||||||
- OpenVINO (Intel GPUs such as Iris Xe and Arc)
|
- OpenVINO (Intel discrete GPUs such as Iris Xe and Arc)
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
@@ -43,9 +43,8 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
|
|
||||||
#### OpenVINO
|
#### OpenVINO
|
||||||
|
|
||||||
- Integrated GPUs are more likely to experience issues than discrete GPUs, especially for older processors or servers with low RAM.
|
- The server must have a discrete GPU, i.e. Iris Xe or Arc. Expect issues when attempting to use integrated graphics.
|
||||||
- Ensure the server's kernel version is new enough to use the device for hardware accceleration.
|
- Ensure the server's kernel version is new enough to use the device for hardware accceleration.
|
||||||
- Expect higher RAM usage when using OpenVINO compared to CPU processing.
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default function VersionSwitcher(): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
versions.length > 0 && (
|
versions.length > 0 && (
|
||||||
<DropdownNavbarItem
|
<DropdownNavbarItem
|
||||||
className="version-switcher-34ab39"
|
className="navbar__item"
|
||||||
label={label}
|
label={label}
|
||||||
mobile={windowSize === 'mobile'}
|
mobile={windowSize === 'mobile'}
|
||||||
items={versions.map(({ label, url }) => ({
|
items={versions.map(({ label, url }) => ({
|
||||||
|
|||||||
@@ -75,11 +75,6 @@ div[class^='announcementBar_'] {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* workaround for version switcher PR 15894 */
|
|
||||||
div[class*='navbar__items'] > li:has(a[class*='version-switcher-34ab39']) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-4
@@ -1,8 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"label": "v1.126.0",
|
|
||||||
"url": "https://v1.126.0.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": "v1.125.7",
|
"label": "v1.125.7",
|
||||||
"url": "https://v1.125.7.archive.immich.app"
|
"url": "https://v1.125.7.archive.immich.app"
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ services:
|
|||||||
- database
|
- database
|
||||||
ports:
|
ports:
|
||||||
- 2285:2285
|
- 2285:2285
|
||||||
|
cap_drop:
|
||||||
|
# We need this to perform testing on permission errors
|
||||||
|
- DAC_OVERRIDE
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:6.2-alpine@sha256:905c4ee67b8e0aa955331960d2aa745781e6bd89afc44a8584bfd13bc890f0ae
|
image: redis:6.2-alpine@sha256:905c4ee67b8e0aa955331960d2aa745781e6bd89afc44a8584bfd13bc890f0ae
|
||||||
|
|||||||
Generated
+4
-4
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"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.49",
|
"version": "2.2.48",
|
||||||
"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.126.0",
|
"version": "1.125.7",
|
||||||
"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.126.0",
|
"version": "1.125.7",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { LibraryResponseDto, LoginResponseDto, getAllLibraries, scanLibrary } from '@immich/sdk';
|
import { LibraryResponseDto, LoginResponseDto, getAllLibraries, scanLibrary } from '@immich/sdk';
|
||||||
import { cpSync, existsSync, rmSync, unlinkSync } from 'node:fs';
|
import { chmodSync, cpSync, existsSync, promises, rmSync, unlinkSync } from 'node:fs';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
import { userDto, uuidDto } from 'src/fixtures';
|
import { userDto, uuidDto } from 'src/fixtures';
|
||||||
import { errorDto } from 'src/responses';
|
import { errorDto } from 'src/responses';
|
||||||
@@ -492,6 +492,34 @@ describe('/libraries', () => {
|
|||||||
utils.removeImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`);
|
utils.removeImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle permission errors on import paths without error', async () => {
|
||||||
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
|
ownerId: admin.userId,
|
||||||
|
importPaths: [`${testAssetDirInternal}/temp/`],
|
||||||
|
});
|
||||||
|
|
||||||
|
const stat = await promises.stat(`${testAssetDir}/temp/directoryA`);
|
||||||
|
const mode = stat.mode;
|
||||||
|
|
||||||
|
chmodSync(`${testAssetDir}/temp/directoryB`, 0o000);
|
||||||
|
|
||||||
|
const { status } = await request(app)
|
||||||
|
.post(`/libraries/${library.id}/scan`)
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
|
.send();
|
||||||
|
expect(status).toBe(204);
|
||||||
|
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
|
||||||
|
chmodSync(`${testAssetDir}/temp/directoryB`, mode);
|
||||||
|
|
||||||
|
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
||||||
|
|
||||||
|
expect(assets.count).toBe(1);
|
||||||
|
expect(assets.items.find((asset) => asset.originalPath.includes('directoryA'))).toBeDefined();
|
||||||
|
expect(assets.items.find((asset) => asset.originalPath.includes('directoryB'))).not.toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
it('should reimport a modified file', async () => {
|
it('should reimport a modified file', async () => {
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
|
|||||||
@@ -195,7 +195,6 @@ describe('/people', () => {
|
|||||||
.send({
|
.send({
|
||||||
name: 'New Person',
|
name: 'New Person',
|
||||||
birthDate: '1990-01-01',
|
birthDate: '1990-01-01',
|
||||||
color: '#333',
|
|
||||||
});
|
});
|
||||||
expect(status).toBe(201);
|
expect(status).toBe(201);
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
@@ -274,24 +273,6 @@ describe('/people', () => {
|
|||||||
expect(body).toMatchObject({ birthDate: null });
|
expect(body).toMatchObject({ birthDate: null });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set a color', async () => {
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.put(`/people/${visiblePerson.id}`)
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
|
||||||
.send({ color: '#555' });
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toMatchObject({ color: '#555' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clear a color', async () => {
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.put(`/people/${visiblePerson.id}`)
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
|
||||||
.send({ color: null });
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body.color).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should mark a person as favorite', async () => {
|
it('should mark a person as favorite', async () => {
|
||||||
const person = await utils.createPerson(admin.accessToken, {
|
const person = await utils.createPerson(admin.accessToken, {
|
||||||
name: 'visible_person',
|
name: 'visible_person',
|
||||||
|
|||||||
@@ -150,30 +150,6 @@ describe('/shared-links', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter on albumId', async () => {
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.get(`/shared-links?albumId=${album.id}`)
|
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
|
||||||
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toHaveLength(2);
|
|
||||||
expect(body).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ id: linkWithAlbum.id }),
|
|
||||||
expect.objectContaining({ id: linkWithPassword.id }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should find 0 albums', async () => {
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.get(`/shared-links?albumId=${uuidDto.notFound}`)
|
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
|
||||||
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toHaveLength(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not get shared links created by other users', async () => {
|
it('should not get shared links created by other users', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get('/shared-links')
|
.get('/shared-links')
|
||||||
|
|||||||
@@ -436,7 +436,6 @@
|
|||||||
"back_close_deselect": "Back, close, or deselect",
|
"back_close_deselect": "Back, close, or deselect",
|
||||||
"backward": "Backward",
|
"backward": "Backward",
|
||||||
"birthdate_saved": "Date of birth saved successfully",
|
"birthdate_saved": "Date of birth saved successfully",
|
||||||
"show_shared_links": "Show shared links",
|
|
||||||
"birthdate_set_description": "Date of birth is used to calculate the age of this person at the time of a photo.",
|
"birthdate_set_description": "Date of birth is used to calculate the age of this person at the time of a photo.",
|
||||||
"blurred_background": "Blurred background",
|
"blurred_background": "Blurred background",
|
||||||
"bugs_and_feature_requests": "Bugs & Feature Requests",
|
"bugs_and_feature_requests": "Bugs & Feature Requests",
|
||||||
@@ -769,10 +768,8 @@
|
|||||||
"go_to_search": "Go to search",
|
"go_to_search": "Go to search",
|
||||||
"go_to_folder": "Go to folder",
|
"go_to_folder": "Go to folder",
|
||||||
"group_albums_by": "Group albums by...",
|
"group_albums_by": "Group albums by...",
|
||||||
"group_country": "Group by country",
|
|
||||||
"group_no": "No grouping",
|
"group_no": "No grouping",
|
||||||
"group_owner": "Group by owner",
|
"group_owner": "Group by owner",
|
||||||
"group_places_by": "Group places by...",
|
|
||||||
"group_year": "Group by year",
|
"group_year": "Group by year",
|
||||||
"has_quota": "Has quota",
|
"has_quota": "Has quota",
|
||||||
"hi_user": "Hi {name} ({email})",
|
"hi_user": "Hi {name} ({email})",
|
||||||
@@ -805,7 +802,6 @@
|
|||||||
"include_shared_albums": "Include shared albums",
|
"include_shared_albums": "Include shared albums",
|
||||||
"include_shared_partner_assets": "Include shared partner assets",
|
"include_shared_partner_assets": "Include shared partner assets",
|
||||||
"individual_share": "Individual share",
|
"individual_share": "Individual share",
|
||||||
"individual_shares": "Individual shares",
|
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
"interval": {
|
"interval": {
|
||||||
"day_at_onepm": "Every day at 1pm",
|
"day_at_onepm": "Every day at 1pm",
|
||||||
@@ -991,7 +987,6 @@
|
|||||||
"pick_a_location": "Pick a location",
|
"pick_a_location": "Pick a location",
|
||||||
"place": "Place",
|
"place": "Place",
|
||||||
"places": "Places",
|
"places": "Places",
|
||||||
"places_count": "{count, plural, one {{count, number} Place} other {{count, number} Places}}",
|
|
||||||
"play": "Play",
|
"play": "Play",
|
||||||
"play_memories": "Play memories",
|
"play_memories": "Play memories",
|
||||||
"play_motion_photo": "Play Motion Photo",
|
"play_motion_photo": "Play Motion Photo",
|
||||||
@@ -1174,7 +1169,6 @@
|
|||||||
"shared_from_partner": "Photos from {partner}",
|
"shared_from_partner": "Photos from {partner}",
|
||||||
"shared_link_options": "Shared link options",
|
"shared_link_options": "Shared link options",
|
||||||
"shared_links": "Shared links",
|
"shared_links": "Shared links",
|
||||||
"shared_links_description": "Share photos and videos with a link",
|
|
||||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# shared photos & videos.}}",
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# shared photos & videos.}}",
|
||||||
"shared_with_partner": "Shared with {partner}",
|
"shared_with_partner": "Shared with {partner}",
|
||||||
"sharing": "Sharing",
|
"sharing": "Sharing",
|
||||||
@@ -1284,7 +1278,6 @@
|
|||||||
"unfavorite": "Unfavorite",
|
"unfavorite": "Unfavorite",
|
||||||
"unhide_person": "Unhide person",
|
"unhide_person": "Unhide person",
|
||||||
"unknown": "Unknown",
|
"unknown": "Unknown",
|
||||||
"unknown_country": "Unknown Country",
|
|
||||||
"unknown_year": "Unknown Year",
|
"unknown_year": "Unknown Year",
|
||||||
"unlimited": "Unlimited",
|
"unlimited": "Unlimited",
|
||||||
"unlink_motion_video": "Unlink motion video",
|
"unlink_motion_video": "Unlink motion video",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "machine-learning"
|
name = "machine-learning"
|
||||||
version = "1.126.0"
|
version = "1.125.7"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ platform :android do
|
|||||||
task: 'bundle',
|
task: 'bundle',
|
||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 183,
|
"android.injected.version.code" => 182,
|
||||||
"android.injected.version.name" => "1.126.0",
|
"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')
|
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.126.0"
|
version_number: "1.125.7"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
Generated
+1
-3
@@ -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.126.0
|
- API version: 1.125.7
|
||||||
- Generator version: 7.8.0
|
- Generator version: 7.8.0
|
||||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||||
|
|
||||||
@@ -408,8 +408,6 @@ Class | Method | HTTP request | Description
|
|||||||
- [SharedLinkEditDto](doc//SharedLinkEditDto.md)
|
- [SharedLinkEditDto](doc//SharedLinkEditDto.md)
|
||||||
- [SharedLinkResponseDto](doc//SharedLinkResponseDto.md)
|
- [SharedLinkResponseDto](doc//SharedLinkResponseDto.md)
|
||||||
- [SharedLinkType](doc//SharedLinkType.md)
|
- [SharedLinkType](doc//SharedLinkType.md)
|
||||||
- [SharedLinksResponse](doc//SharedLinksResponse.md)
|
|
||||||
- [SharedLinksUpdate](doc//SharedLinksUpdate.md)
|
|
||||||
- [SignUpDto](doc//SignUpDto.md)
|
- [SignUpDto](doc//SignUpDto.md)
|
||||||
- [SmartSearchDto](doc//SmartSearchDto.md)
|
- [SmartSearchDto](doc//SmartSearchDto.md)
|
||||||
- [SourceType](doc//SourceType.md)
|
- [SourceType](doc//SourceType.md)
|
||||||
|
|||||||
Generated
-2
@@ -221,8 +221,6 @@ part 'model/shared_link_create_dto.dart';
|
|||||||
part 'model/shared_link_edit_dto.dart';
|
part 'model/shared_link_edit_dto.dart';
|
||||||
part 'model/shared_link_response_dto.dart';
|
part 'model/shared_link_response_dto.dart';
|
||||||
part 'model/shared_link_type.dart';
|
part 'model/shared_link_type.dart';
|
||||||
part 'model/shared_links_response.dart';
|
|
||||||
part 'model/shared_links_update.dart';
|
|
||||||
part 'model/sign_up_dto.dart';
|
part 'model/sign_up_dto.dart';
|
||||||
part 'model/smart_search_dto.dart';
|
part 'model/smart_search_dto.dart';
|
||||||
part 'model/source_type.dart';
|
part 'model/source_type.dart';
|
||||||
|
|||||||
+3
-13
@@ -127,10 +127,7 @@ class SharedLinksApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /shared-links' operation and returns the [Response].
|
/// Performs an HTTP 'GET /shared-links' operation and returns the [Response].
|
||||||
/// Parameters:
|
Future<Response> getAllSharedLinksWithHttpInfo() async {
|
||||||
///
|
|
||||||
/// * [String] albumId:
|
|
||||||
Future<Response> getAllSharedLinksWithHttpInfo({ String? albumId, }) async {
|
|
||||||
// ignore: prefer_const_declarations
|
// ignore: prefer_const_declarations
|
||||||
final path = r'/shared-links';
|
final path = r'/shared-links';
|
||||||
|
|
||||||
@@ -141,10 +138,6 @@ class SharedLinksApi {
|
|||||||
final headerParams = <String, String>{};
|
final headerParams = <String, String>{};
|
||||||
final formParams = <String, String>{};
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
if (albumId != null) {
|
|
||||||
queryParams.addAll(_queryParams('', 'albumId', albumId));
|
|
||||||
}
|
|
||||||
|
|
||||||
const contentTypes = <String>[];
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
@@ -159,11 +152,8 @@ class SharedLinksApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameters:
|
Future<List<SharedLinkResponseDto>?> getAllSharedLinks() async {
|
||||||
///
|
final response = await getAllSharedLinksWithHttpInfo();
|
||||||
/// * [String] albumId:
|
|
||||||
Future<List<SharedLinkResponseDto>?> getAllSharedLinks({ String? albumId, }) async {
|
|
||||||
final response = await getAllSharedLinksWithHttpInfo( albumId: albumId, );
|
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
-4
@@ -496,10 +496,6 @@ class ApiClient {
|
|||||||
return SharedLinkResponseDto.fromJson(value);
|
return SharedLinkResponseDto.fromJson(value);
|
||||||
case 'SharedLinkType':
|
case 'SharedLinkType':
|
||||||
return SharedLinkTypeTypeTransformer().decode(value);
|
return SharedLinkTypeTypeTransformer().decode(value);
|
||||||
case 'SharedLinksResponse':
|
|
||||||
return SharedLinksResponse.fromJson(value);
|
|
||||||
case 'SharedLinksUpdate':
|
|
||||||
return SharedLinksUpdate.fromJson(value);
|
|
||||||
case 'SignUpDto':
|
case 'SignUpDto':
|
||||||
return SignUpDto.fromJson(value);
|
return SignUpDto.fromJson(value);
|
||||||
case 'SmartSearchDto':
|
case 'SmartSearchDto':
|
||||||
|
|||||||
+1
-12
@@ -14,7 +14,6 @@ class PeopleUpdateItem {
|
|||||||
/// Returns a new [PeopleUpdateItem] instance.
|
/// Returns a new [PeopleUpdateItem] instance.
|
||||||
PeopleUpdateItem({
|
PeopleUpdateItem({
|
||||||
this.birthDate,
|
this.birthDate,
|
||||||
this.color,
|
|
||||||
this.featureFaceAssetId,
|
this.featureFaceAssetId,
|
||||||
required this.id,
|
required this.id,
|
||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
@@ -25,8 +24,6 @@ class PeopleUpdateItem {
|
|||||||
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
String? color;
|
|
||||||
|
|
||||||
/// Asset is used to get the feature face thumbnail.
|
/// Asset is used to get the feature face thumbnail.
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@@ -68,7 +65,6 @@ class PeopleUpdateItem {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is PeopleUpdateItem &&
|
bool operator ==(Object other) => identical(this, other) || other is PeopleUpdateItem &&
|
||||||
other.birthDate == birthDate &&
|
other.birthDate == birthDate &&
|
||||||
other.color == color &&
|
|
||||||
other.featureFaceAssetId == featureFaceAssetId &&
|
other.featureFaceAssetId == featureFaceAssetId &&
|
||||||
other.id == id &&
|
other.id == id &&
|
||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
@@ -79,7 +75,6 @@ class PeopleUpdateItem {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(birthDate == null ? 0 : birthDate!.hashCode) +
|
(birthDate == null ? 0 : birthDate!.hashCode) +
|
||||||
(color == null ? 0 : color!.hashCode) +
|
|
||||||
(featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
|
(featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
|
||||||
(id.hashCode) +
|
(id.hashCode) +
|
||||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
@@ -87,7 +82,7 @@ class PeopleUpdateItem {
|
|||||||
(name == null ? 0 : name!.hashCode);
|
(name == null ? 0 : name!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'PeopleUpdateItem[birthDate=$birthDate, color=$color, featureFaceAssetId=$featureFaceAssetId, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]';
|
String toString() => 'PeopleUpdateItem[birthDate=$birthDate, featureFaceAssetId=$featureFaceAssetId, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -96,11 +91,6 @@ class PeopleUpdateItem {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'birthDate'] = null;
|
// json[r'birthDate'] = null;
|
||||||
}
|
}
|
||||||
if (this.color != null) {
|
|
||||||
json[r'color'] = this.color;
|
|
||||||
} else {
|
|
||||||
// json[r'color'] = null;
|
|
||||||
}
|
|
||||||
if (this.featureFaceAssetId != null) {
|
if (this.featureFaceAssetId != null) {
|
||||||
json[r'featureFaceAssetId'] = this.featureFaceAssetId;
|
json[r'featureFaceAssetId'] = this.featureFaceAssetId;
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +125,6 @@ class PeopleUpdateItem {
|
|||||||
|
|
||||||
return PeopleUpdateItem(
|
return PeopleUpdateItem(
|
||||||
birthDate: mapDateTime(json, r'birthDate', r''),
|
birthDate: mapDateTime(json, r'birthDate', r''),
|
||||||
color: mapValueOfType<String>(json, r'color'),
|
|
||||||
featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
|
featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
|
||||||
id: mapValueOfType<String>(json, r'id')!,
|
id: mapValueOfType<String>(json, r'id')!,
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
|
|||||||
+1
-12
@@ -14,7 +14,6 @@ class PersonCreateDto {
|
|||||||
/// Returns a new [PersonCreateDto] instance.
|
/// Returns a new [PersonCreateDto] instance.
|
||||||
PersonCreateDto({
|
PersonCreateDto({
|
||||||
this.birthDate,
|
this.birthDate,
|
||||||
this.color,
|
|
||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
this.isHidden,
|
this.isHidden,
|
||||||
this.name,
|
this.name,
|
||||||
@@ -23,8 +22,6 @@ class PersonCreateDto {
|
|||||||
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
String? color;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
@@ -54,7 +51,6 @@ class PersonCreateDto {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is PersonCreateDto &&
|
bool operator ==(Object other) => identical(this, other) || other is PersonCreateDto &&
|
||||||
other.birthDate == birthDate &&
|
other.birthDate == birthDate &&
|
||||||
other.color == color &&
|
|
||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
other.isHidden == isHidden &&
|
other.isHidden == isHidden &&
|
||||||
other.name == name;
|
other.name == name;
|
||||||
@@ -63,13 +59,12 @@ class PersonCreateDto {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(birthDate == null ? 0 : birthDate!.hashCode) +
|
(birthDate == null ? 0 : birthDate!.hashCode) +
|
||||||
(color == null ? 0 : color!.hashCode) +
|
|
||||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
(isHidden == null ? 0 : isHidden!.hashCode) +
|
(isHidden == null ? 0 : isHidden!.hashCode) +
|
||||||
(name == null ? 0 : name!.hashCode);
|
(name == null ? 0 : name!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'PersonCreateDto[birthDate=$birthDate, color=$color, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]';
|
String toString() => 'PersonCreateDto[birthDate=$birthDate, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -78,11 +73,6 @@ class PersonCreateDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'birthDate'] = null;
|
// json[r'birthDate'] = null;
|
||||||
}
|
}
|
||||||
if (this.color != null) {
|
|
||||||
json[r'color'] = this.color;
|
|
||||||
} else {
|
|
||||||
// json[r'color'] = null;
|
|
||||||
}
|
|
||||||
if (this.isFavorite != null) {
|
if (this.isFavorite != null) {
|
||||||
json[r'isFavorite'] = this.isFavorite;
|
json[r'isFavorite'] = this.isFavorite;
|
||||||
} else {
|
} else {
|
||||||
@@ -111,7 +101,6 @@ class PersonCreateDto {
|
|||||||
|
|
||||||
return PersonCreateDto(
|
return PersonCreateDto(
|
||||||
birthDate: mapDateTime(json, r'birthDate', r''),
|
birthDate: mapDateTime(json, r'birthDate', r''),
|
||||||
color: mapValueOfType<String>(json, r'color'),
|
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
isHidden: mapValueOfType<bool>(json, r'isHidden'),
|
isHidden: mapValueOfType<bool>(json, r'isHidden'),
|
||||||
name: mapValueOfType<String>(json, r'name'),
|
name: mapValueOfType<String>(json, r'name'),
|
||||||
|
|||||||
+1
-19
@@ -14,7 +14,6 @@ class PersonResponseDto {
|
|||||||
/// Returns a new [PersonResponseDto] instance.
|
/// Returns a new [PersonResponseDto] instance.
|
||||||
PersonResponseDto({
|
PersonResponseDto({
|
||||||
required this.birthDate,
|
required this.birthDate,
|
||||||
this.color,
|
|
||||||
required this.id,
|
required this.id,
|
||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
required this.isHidden,
|
required this.isHidden,
|
||||||
@@ -25,15 +24,6 @@ class PersonResponseDto {
|
|||||||
|
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
/// This property was added in v1.126.0
|
|
||||||
///
|
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
|
||||||
/// source code must fall back to having a nullable type.
|
|
||||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
|
||||||
///
|
|
||||||
String? color;
|
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
|
|
||||||
/// This property was added in v1.126.0
|
/// This property was added in v1.126.0
|
||||||
@@ -63,7 +53,6 @@ class PersonResponseDto {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is PersonResponseDto &&
|
bool operator ==(Object other) => identical(this, other) || other is PersonResponseDto &&
|
||||||
other.birthDate == birthDate &&
|
other.birthDate == birthDate &&
|
||||||
other.color == color &&
|
|
||||||
other.id == id &&
|
other.id == id &&
|
||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
other.isHidden == isHidden &&
|
other.isHidden == isHidden &&
|
||||||
@@ -75,7 +64,6 @@ class PersonResponseDto {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(birthDate == null ? 0 : birthDate!.hashCode) +
|
(birthDate == null ? 0 : birthDate!.hashCode) +
|
||||||
(color == null ? 0 : color!.hashCode) +
|
|
||||||
(id.hashCode) +
|
(id.hashCode) +
|
||||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
(isHidden.hashCode) +
|
(isHidden.hashCode) +
|
||||||
@@ -84,7 +72,7 @@ class PersonResponseDto {
|
|||||||
(updatedAt == null ? 0 : updatedAt!.hashCode);
|
(updatedAt == null ? 0 : updatedAt!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'PersonResponseDto[birthDate=$birthDate, color=$color, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]';
|
String toString() => 'PersonResponseDto[birthDate=$birthDate, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -92,11 +80,6 @@ class PersonResponseDto {
|
|||||||
json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc());
|
json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc());
|
||||||
} else {
|
} else {
|
||||||
// json[r'birthDate'] = null;
|
// json[r'birthDate'] = null;
|
||||||
}
|
|
||||||
if (this.color != null) {
|
|
||||||
json[r'color'] = this.color;
|
|
||||||
} else {
|
|
||||||
// json[r'color'] = null;
|
|
||||||
}
|
}
|
||||||
json[r'id'] = this.id;
|
json[r'id'] = this.id;
|
||||||
if (this.isFavorite != null) {
|
if (this.isFavorite != null) {
|
||||||
@@ -125,7 +108,6 @@ class PersonResponseDto {
|
|||||||
|
|
||||||
return PersonResponseDto(
|
return PersonResponseDto(
|
||||||
birthDate: mapDateTime(json, r'birthDate', r''),
|
birthDate: mapDateTime(json, r'birthDate', r''),
|
||||||
color: mapValueOfType<String>(json, r'color'),
|
|
||||||
id: mapValueOfType<String>(json, r'id')!,
|
id: mapValueOfType<String>(json, r'id')!,
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
isHidden: mapValueOfType<bool>(json, r'isHidden')!,
|
isHidden: mapValueOfType<bool>(json, r'isHidden')!,
|
||||||
|
|||||||
+1
-12
@@ -14,7 +14,6 @@ class PersonUpdateDto {
|
|||||||
/// Returns a new [PersonUpdateDto] instance.
|
/// Returns a new [PersonUpdateDto] instance.
|
||||||
PersonUpdateDto({
|
PersonUpdateDto({
|
||||||
this.birthDate,
|
this.birthDate,
|
||||||
this.color,
|
|
||||||
this.featureFaceAssetId,
|
this.featureFaceAssetId,
|
||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
this.isHidden,
|
this.isHidden,
|
||||||
@@ -24,8 +23,6 @@ class PersonUpdateDto {
|
|||||||
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
String? color;
|
|
||||||
|
|
||||||
/// Asset is used to get the feature face thumbnail.
|
/// Asset is used to get the feature face thumbnail.
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@@ -64,7 +61,6 @@ class PersonUpdateDto {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is PersonUpdateDto &&
|
bool operator ==(Object other) => identical(this, other) || other is PersonUpdateDto &&
|
||||||
other.birthDate == birthDate &&
|
other.birthDate == birthDate &&
|
||||||
other.color == color &&
|
|
||||||
other.featureFaceAssetId == featureFaceAssetId &&
|
other.featureFaceAssetId == featureFaceAssetId &&
|
||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
other.isHidden == isHidden &&
|
other.isHidden == isHidden &&
|
||||||
@@ -74,14 +70,13 @@ class PersonUpdateDto {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(birthDate == null ? 0 : birthDate!.hashCode) +
|
(birthDate == null ? 0 : birthDate!.hashCode) +
|
||||||
(color == null ? 0 : color!.hashCode) +
|
|
||||||
(featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
|
(featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
|
||||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
(isHidden == null ? 0 : isHidden!.hashCode) +
|
(isHidden == null ? 0 : isHidden!.hashCode) +
|
||||||
(name == null ? 0 : name!.hashCode);
|
(name == null ? 0 : name!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'PersonUpdateDto[birthDate=$birthDate, color=$color, featureFaceAssetId=$featureFaceAssetId, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]';
|
String toString() => 'PersonUpdateDto[birthDate=$birthDate, featureFaceAssetId=$featureFaceAssetId, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -90,11 +85,6 @@ class PersonUpdateDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'birthDate'] = null;
|
// json[r'birthDate'] = null;
|
||||||
}
|
}
|
||||||
if (this.color != null) {
|
|
||||||
json[r'color'] = this.color;
|
|
||||||
} else {
|
|
||||||
// json[r'color'] = null;
|
|
||||||
}
|
|
||||||
if (this.featureFaceAssetId != null) {
|
if (this.featureFaceAssetId != null) {
|
||||||
json[r'featureFaceAssetId'] = this.featureFaceAssetId;
|
json[r'featureFaceAssetId'] = this.featureFaceAssetId;
|
||||||
} else {
|
} else {
|
||||||
@@ -128,7 +118,6 @@ class PersonUpdateDto {
|
|||||||
|
|
||||||
return PersonUpdateDto(
|
return PersonUpdateDto(
|
||||||
birthDate: mapDateTime(json, r'birthDate', r''),
|
birthDate: mapDateTime(json, r'birthDate', r''),
|
||||||
color: mapValueOfType<String>(json, r'color'),
|
|
||||||
featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
|
featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
isHidden: mapValueOfType<bool>(json, r'isHidden'),
|
isHidden: mapValueOfType<bool>(json, r'isHidden'),
|
||||||
|
|||||||
+1
-19
@@ -14,7 +14,6 @@ class PersonWithFacesResponseDto {
|
|||||||
/// Returns a new [PersonWithFacesResponseDto] instance.
|
/// Returns a new [PersonWithFacesResponseDto] instance.
|
||||||
PersonWithFacesResponseDto({
|
PersonWithFacesResponseDto({
|
||||||
required this.birthDate,
|
required this.birthDate,
|
||||||
this.color,
|
|
||||||
this.faces = const [],
|
this.faces = const [],
|
||||||
required this.id,
|
required this.id,
|
||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
@@ -26,15 +25,6 @@ class PersonWithFacesResponseDto {
|
|||||||
|
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
/// This property was added in v1.126.0
|
|
||||||
///
|
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
|
||||||
/// source code must fall back to having a nullable type.
|
|
||||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
|
||||||
///
|
|
||||||
String? color;
|
|
||||||
|
|
||||||
List<AssetFaceWithoutPersonResponseDto> faces;
|
List<AssetFaceWithoutPersonResponseDto> faces;
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
@@ -66,7 +56,6 @@ class PersonWithFacesResponseDto {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is PersonWithFacesResponseDto &&
|
bool operator ==(Object other) => identical(this, other) || other is PersonWithFacesResponseDto &&
|
||||||
other.birthDate == birthDate &&
|
other.birthDate == birthDate &&
|
||||||
other.color == color &&
|
|
||||||
_deepEquality.equals(other.faces, faces) &&
|
_deepEquality.equals(other.faces, faces) &&
|
||||||
other.id == id &&
|
other.id == id &&
|
||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
@@ -79,7 +68,6 @@ class PersonWithFacesResponseDto {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(birthDate == null ? 0 : birthDate!.hashCode) +
|
(birthDate == null ? 0 : birthDate!.hashCode) +
|
||||||
(color == null ? 0 : color!.hashCode) +
|
|
||||||
(faces.hashCode) +
|
(faces.hashCode) +
|
||||||
(id.hashCode) +
|
(id.hashCode) +
|
||||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
@@ -89,7 +77,7 @@ class PersonWithFacesResponseDto {
|
|||||||
(updatedAt == null ? 0 : updatedAt!.hashCode);
|
(updatedAt == null ? 0 : updatedAt!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'PersonWithFacesResponseDto[birthDate=$birthDate, color=$color, faces=$faces, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]';
|
String toString() => 'PersonWithFacesResponseDto[birthDate=$birthDate, faces=$faces, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -97,11 +85,6 @@ class PersonWithFacesResponseDto {
|
|||||||
json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc());
|
json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc());
|
||||||
} else {
|
} else {
|
||||||
// json[r'birthDate'] = null;
|
// json[r'birthDate'] = null;
|
||||||
}
|
|
||||||
if (this.color != null) {
|
|
||||||
json[r'color'] = this.color;
|
|
||||||
} else {
|
|
||||||
// json[r'color'] = null;
|
|
||||||
}
|
}
|
||||||
json[r'faces'] = this.faces;
|
json[r'faces'] = this.faces;
|
||||||
json[r'id'] = this.id;
|
json[r'id'] = this.id;
|
||||||
@@ -131,7 +114,6 @@ class PersonWithFacesResponseDto {
|
|||||||
|
|
||||||
return PersonWithFacesResponseDto(
|
return PersonWithFacesResponseDto(
|
||||||
birthDate: mapDateTime(json, r'birthDate', r''),
|
birthDate: mapDateTime(json, r'birthDate', r''),
|
||||||
color: mapValueOfType<String>(json, r'color'),
|
|
||||||
faces: AssetFaceWithoutPersonResponseDto.listFromJson(json[r'faces']),
|
faces: AssetFaceWithoutPersonResponseDto.listFromJson(json[r'faces']),
|
||||||
id: mapValueOfType<String>(json, r'id')!,
|
id: mapValueOfType<String>(json, r'id')!,
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
|
|||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
//
|
|
||||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
|
||||||
//
|
|
||||||
// @dart=2.18
|
|
||||||
|
|
||||||
// ignore_for_file: unused_element, unused_import
|
|
||||||
// ignore_for_file: always_put_required_named_parameters_first
|
|
||||||
// ignore_for_file: constant_identifier_names
|
|
||||||
// ignore_for_file: lines_longer_than_80_chars
|
|
||||||
|
|
||||||
part of openapi.api;
|
|
||||||
|
|
||||||
class SharedLinksResponse {
|
|
||||||
/// Returns a new [SharedLinksResponse] instance.
|
|
||||||
SharedLinksResponse({
|
|
||||||
this.enabled = true,
|
|
||||||
this.sidebarWeb = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
bool enabled;
|
|
||||||
|
|
||||||
bool sidebarWeb;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) => identical(this, other) || other is SharedLinksResponse &&
|
|
||||||
other.enabled == enabled &&
|
|
||||||
other.sidebarWeb == sidebarWeb;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode =>
|
|
||||||
// ignore: unnecessary_parenthesis
|
|
||||||
(enabled.hashCode) +
|
|
||||||
(sidebarWeb.hashCode);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => 'SharedLinksResponse[enabled=$enabled, sidebarWeb=$sidebarWeb]';
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
final json = <String, dynamic>{};
|
|
||||||
json[r'enabled'] = this.enabled;
|
|
||||||
json[r'sidebarWeb'] = this.sidebarWeb;
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new [SharedLinksResponse] instance and imports its values from
|
|
||||||
/// [value] if it's a [Map], null otherwise.
|
|
||||||
// ignore: prefer_constructors_over_static_methods
|
|
||||||
static SharedLinksResponse? fromJson(dynamic value) {
|
|
||||||
upgradeDto(value, "SharedLinksResponse");
|
|
||||||
if (value is Map) {
|
|
||||||
final json = value.cast<String, dynamic>();
|
|
||||||
|
|
||||||
return SharedLinksResponse(
|
|
||||||
enabled: mapValueOfType<bool>(json, r'enabled')!,
|
|
||||||
sidebarWeb: mapValueOfType<bool>(json, r'sidebarWeb')!,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<SharedLinksResponse> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <SharedLinksResponse>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = SharedLinksResponse.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Map<String, SharedLinksResponse> mapFromJson(dynamic json) {
|
|
||||||
final map = <String, SharedLinksResponse>{};
|
|
||||||
if (json is Map && json.isNotEmpty) {
|
|
||||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
final value = SharedLinksResponse.fromJson(entry.value);
|
|
||||||
if (value != null) {
|
|
||||||
map[entry.key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
// maps a json object with a list of SharedLinksResponse-objects as value to a dart map
|
|
||||||
static Map<String, List<SharedLinksResponse>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final map = <String, List<SharedLinksResponse>>{};
|
|
||||||
if (json is Map && json.isNotEmpty) {
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
json = json.cast<String, dynamic>();
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
map[entry.key] = SharedLinksResponse.listFromJson(entry.value, growable: growable,);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The list of required keys that must be present in a JSON.
|
|
||||||
static const requiredKeys = <String>{
|
|
||||||
'enabled',
|
|
||||||
'sidebarWeb',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
-125
@@ -1,125 +0,0 @@
|
|||||||
//
|
|
||||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
|
||||||
//
|
|
||||||
// @dart=2.18
|
|
||||||
|
|
||||||
// ignore_for_file: unused_element, unused_import
|
|
||||||
// ignore_for_file: always_put_required_named_parameters_first
|
|
||||||
// ignore_for_file: constant_identifier_names
|
|
||||||
// ignore_for_file: lines_longer_than_80_chars
|
|
||||||
|
|
||||||
part of openapi.api;
|
|
||||||
|
|
||||||
class SharedLinksUpdate {
|
|
||||||
/// Returns a new [SharedLinksUpdate] instance.
|
|
||||||
SharedLinksUpdate({
|
|
||||||
this.enabled,
|
|
||||||
this.sidebarWeb,
|
|
||||||
});
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
|
||||||
/// source code must fall back to having a nullable type.
|
|
||||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
|
||||||
///
|
|
||||||
bool? enabled;
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
|
||||||
/// source code must fall back to having a nullable type.
|
|
||||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
|
||||||
///
|
|
||||||
bool? sidebarWeb;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) => identical(this, other) || other is SharedLinksUpdate &&
|
|
||||||
other.enabled == enabled &&
|
|
||||||
other.sidebarWeb == sidebarWeb;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode =>
|
|
||||||
// ignore: unnecessary_parenthesis
|
|
||||||
(enabled == null ? 0 : enabled!.hashCode) +
|
|
||||||
(sidebarWeb == null ? 0 : sidebarWeb!.hashCode);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => 'SharedLinksUpdate[enabled=$enabled, sidebarWeb=$sidebarWeb]';
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
final json = <String, dynamic>{};
|
|
||||||
if (this.enabled != null) {
|
|
||||||
json[r'enabled'] = this.enabled;
|
|
||||||
} else {
|
|
||||||
// json[r'enabled'] = null;
|
|
||||||
}
|
|
||||||
if (this.sidebarWeb != null) {
|
|
||||||
json[r'sidebarWeb'] = this.sidebarWeb;
|
|
||||||
} else {
|
|
||||||
// json[r'sidebarWeb'] = null;
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new [SharedLinksUpdate] instance and imports its values from
|
|
||||||
/// [value] if it's a [Map], null otherwise.
|
|
||||||
// ignore: prefer_constructors_over_static_methods
|
|
||||||
static SharedLinksUpdate? fromJson(dynamic value) {
|
|
||||||
upgradeDto(value, "SharedLinksUpdate");
|
|
||||||
if (value is Map) {
|
|
||||||
final json = value.cast<String, dynamic>();
|
|
||||||
|
|
||||||
return SharedLinksUpdate(
|
|
||||||
enabled: mapValueOfType<bool>(json, r'enabled'),
|
|
||||||
sidebarWeb: mapValueOfType<bool>(json, r'sidebarWeb'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<SharedLinksUpdate> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <SharedLinksUpdate>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = SharedLinksUpdate.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Map<String, SharedLinksUpdate> mapFromJson(dynamic json) {
|
|
||||||
final map = <String, SharedLinksUpdate>{};
|
|
||||||
if (json is Map && json.isNotEmpty) {
|
|
||||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
final value = SharedLinksUpdate.fromJson(entry.value);
|
|
||||||
if (value != null) {
|
|
||||||
map[entry.key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
// maps a json object with a list of SharedLinksUpdate-objects as value to a dart map
|
|
||||||
static Map<String, List<SharedLinksUpdate>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final map = <String, List<SharedLinksUpdate>>{};
|
|
||||||
if (json is Map && json.isNotEmpty) {
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
json = json.cast<String, dynamic>();
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
map[entry.key] = SharedLinksUpdate.listFromJson(entry.value, growable: growable,);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The list of required keys that must be present in a JSON.
|
|
||||||
static const requiredKeys = <String>{
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
+1
-9
@@ -21,7 +21,6 @@ class UserPreferencesResponseDto {
|
|||||||
required this.people,
|
required this.people,
|
||||||
required this.purchase,
|
required this.purchase,
|
||||||
required this.ratings,
|
required this.ratings,
|
||||||
required this.sharedLinks,
|
|
||||||
required this.tags,
|
required this.tags,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,8 +40,6 @@ class UserPreferencesResponseDto {
|
|||||||
|
|
||||||
RatingsResponse ratings;
|
RatingsResponse ratings;
|
||||||
|
|
||||||
SharedLinksResponse sharedLinks;
|
|
||||||
|
|
||||||
TagsResponse tags;
|
TagsResponse tags;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -55,7 +52,6 @@ class UserPreferencesResponseDto {
|
|||||||
other.people == people &&
|
other.people == people &&
|
||||||
other.purchase == purchase &&
|
other.purchase == purchase &&
|
||||||
other.ratings == ratings &&
|
other.ratings == ratings &&
|
||||||
other.sharedLinks == sharedLinks &&
|
|
||||||
other.tags == tags;
|
other.tags == tags;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -69,11 +65,10 @@ class UserPreferencesResponseDto {
|
|||||||
(people.hashCode) +
|
(people.hashCode) +
|
||||||
(purchase.hashCode) +
|
(purchase.hashCode) +
|
||||||
(ratings.hashCode) +
|
(ratings.hashCode) +
|
||||||
(sharedLinks.hashCode) +
|
|
||||||
(tags.hashCode);
|
(tags.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UserPreferencesResponseDto[avatar=$avatar, download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, sharedLinks=$sharedLinks, tags=$tags]';
|
String toString() => 'UserPreferencesResponseDto[avatar=$avatar, download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, tags=$tags]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -85,7 +80,6 @@ class UserPreferencesResponseDto {
|
|||||||
json[r'people'] = this.people;
|
json[r'people'] = this.people;
|
||||||
json[r'purchase'] = this.purchase;
|
json[r'purchase'] = this.purchase;
|
||||||
json[r'ratings'] = this.ratings;
|
json[r'ratings'] = this.ratings;
|
||||||
json[r'sharedLinks'] = this.sharedLinks;
|
|
||||||
json[r'tags'] = this.tags;
|
json[r'tags'] = this.tags;
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
@@ -107,7 +101,6 @@ class UserPreferencesResponseDto {
|
|||||||
people: PeopleResponse.fromJson(json[r'people'])!,
|
people: PeopleResponse.fromJson(json[r'people'])!,
|
||||||
purchase: PurchaseResponse.fromJson(json[r'purchase'])!,
|
purchase: PurchaseResponse.fromJson(json[r'purchase'])!,
|
||||||
ratings: RatingsResponse.fromJson(json[r'ratings'])!,
|
ratings: RatingsResponse.fromJson(json[r'ratings'])!,
|
||||||
sharedLinks: SharedLinksResponse.fromJson(json[r'sharedLinks'])!,
|
|
||||||
tags: TagsResponse.fromJson(json[r'tags'])!,
|
tags: TagsResponse.fromJson(json[r'tags'])!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -164,7 +157,6 @@ class UserPreferencesResponseDto {
|
|||||||
'people',
|
'people',
|
||||||
'purchase',
|
'purchase',
|
||||||
'ratings',
|
'ratings',
|
||||||
'sharedLinks',
|
|
||||||
'tags',
|
'tags',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-18
@@ -21,7 +21,6 @@ class UserPreferencesUpdateDto {
|
|||||||
this.people,
|
this.people,
|
||||||
this.purchase,
|
this.purchase,
|
||||||
this.ratings,
|
this.ratings,
|
||||||
this.sharedLinks,
|
|
||||||
this.tags,
|
this.tags,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -89,14 +88,6 @@ class UserPreferencesUpdateDto {
|
|||||||
///
|
///
|
||||||
RatingsUpdate? ratings;
|
RatingsUpdate? ratings;
|
||||||
|
|
||||||
///
|
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
|
||||||
/// source code must fall back to having a nullable type.
|
|
||||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
|
||||||
///
|
|
||||||
SharedLinksUpdate? sharedLinks;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
@@ -115,7 +106,6 @@ class UserPreferencesUpdateDto {
|
|||||||
other.people == people &&
|
other.people == people &&
|
||||||
other.purchase == purchase &&
|
other.purchase == purchase &&
|
||||||
other.ratings == ratings &&
|
other.ratings == ratings &&
|
||||||
other.sharedLinks == sharedLinks &&
|
|
||||||
other.tags == tags;
|
other.tags == tags;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -129,11 +119,10 @@ class UserPreferencesUpdateDto {
|
|||||||
(people == null ? 0 : people!.hashCode) +
|
(people == null ? 0 : people!.hashCode) +
|
||||||
(purchase == null ? 0 : purchase!.hashCode) +
|
(purchase == null ? 0 : purchase!.hashCode) +
|
||||||
(ratings == null ? 0 : ratings!.hashCode) +
|
(ratings == null ? 0 : ratings!.hashCode) +
|
||||||
(sharedLinks == null ? 0 : sharedLinks!.hashCode) +
|
|
||||||
(tags == null ? 0 : tags!.hashCode);
|
(tags == null ? 0 : tags!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UserPreferencesUpdateDto[avatar=$avatar, download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, sharedLinks=$sharedLinks, tags=$tags]';
|
String toString() => 'UserPreferencesUpdateDto[avatar=$avatar, download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, tags=$tags]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -177,11 +166,6 @@ class UserPreferencesUpdateDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'ratings'] = null;
|
// json[r'ratings'] = null;
|
||||||
}
|
}
|
||||||
if (this.sharedLinks != null) {
|
|
||||||
json[r'sharedLinks'] = this.sharedLinks;
|
|
||||||
} else {
|
|
||||||
// json[r'sharedLinks'] = null;
|
|
||||||
}
|
|
||||||
if (this.tags != null) {
|
if (this.tags != null) {
|
||||||
json[r'tags'] = this.tags;
|
json[r'tags'] = this.tags;
|
||||||
} else {
|
} else {
|
||||||
@@ -207,7 +191,6 @@ class UserPreferencesUpdateDto {
|
|||||||
people: PeopleUpdate.fromJson(json[r'people']),
|
people: PeopleUpdate.fromJson(json[r'people']),
|
||||||
purchase: PurchaseUpdate.fromJson(json[r'purchase']),
|
purchase: PurchaseUpdate.fromJson(json[r'purchase']),
|
||||||
ratings: RatingsUpdate.fromJson(json[r'ratings']),
|
ratings: RatingsUpdate.fromJson(json[r'ratings']),
|
||||||
sharedLinks: SharedLinksUpdate.fromJson(json[r'sharedLinks']),
|
|
||||||
tags: TagsUpdate.fromJson(json[r'tags']),
|
tags: TagsUpdate.fromJson(json[r'tags']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+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.126.0+183
|
version: 1.125.7+182
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.3.0 <4.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
|||||||
@@ -5230,17 +5230,7 @@
|
|||||||
"/shared-links": {
|
"/shared-links": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getAllSharedLinks",
|
"operationId": "getAllSharedLinks",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "albumId",
|
|
||||||
"required": false,
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "uuid",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
@@ -7468,7 +7458,7 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"title": "Immich",
|
"title": "Immich",
|
||||||
"description": "Immich API",
|
"description": "Immich API",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"contact": {}
|
"contact": {}
|
||||||
},
|
},
|
||||||
"tags": [],
|
"tags": [],
|
||||||
@@ -10296,10 +10286,6 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"color": {
|
|
||||||
"nullable": true,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"featureFaceAssetId": {
|
"featureFaceAssetId": {
|
||||||
"description": "Asset is used to get the feature face thumbnail.",
|
"description": "Asset is used to get the feature face thumbnail.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -10416,10 +10402,6 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"color": {
|
|
||||||
"nullable": true,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"isFavorite": {
|
"isFavorite": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
@@ -10441,10 +10423,6 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"color": {
|
|
||||||
"description": "This property was added in v1.126.0",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -10495,10 +10473,6 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"color": {
|
|
||||||
"nullable": true,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"featureFaceAssetId": {
|
"featureFaceAssetId": {
|
||||||
"description": "Asset is used to get the feature face thumbnail.",
|
"description": "Asset is used to get the feature face thumbnail.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -10524,10 +10498,6 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"color": {
|
|
||||||
"description": "This property was added in v1.126.0",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"faces": {
|
"faces": {
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/components/schemas/AssetFaceWithoutPersonResponseDto"
|
"$ref": "#/components/schemas/AssetFaceWithoutPersonResponseDto"
|
||||||
@@ -11524,34 +11494,6 @@
|
|||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"SharedLinksResponse": {
|
|
||||||
"properties": {
|
|
||||||
"enabled": {
|
|
||||||
"default": true,
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"sidebarWeb": {
|
|
||||||
"default": false,
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"enabled",
|
|
||||||
"sidebarWeb"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"SharedLinksUpdate": {
|
|
||||||
"properties": {
|
|
||||||
"enabled": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"sidebarWeb": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"SignUpDto": {
|
"SignUpDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"email": {
|
"email": {
|
||||||
@@ -12669,6 +12611,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"color": {
|
"color": {
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
|
"pattern": "^#?([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -13198,9 +13141,6 @@
|
|||||||
"ratings": {
|
"ratings": {
|
||||||
"$ref": "#/components/schemas/RatingsResponse"
|
"$ref": "#/components/schemas/RatingsResponse"
|
||||||
},
|
},
|
||||||
"sharedLinks": {
|
|
||||||
"$ref": "#/components/schemas/SharedLinksResponse"
|
|
||||||
},
|
|
||||||
"tags": {
|
"tags": {
|
||||||
"$ref": "#/components/schemas/TagsResponse"
|
"$ref": "#/components/schemas/TagsResponse"
|
||||||
}
|
}
|
||||||
@@ -13214,7 +13154,6 @@
|
|||||||
"people",
|
"people",
|
||||||
"purchase",
|
"purchase",
|
||||||
"ratings",
|
"ratings",
|
||||||
"sharedLinks",
|
|
||||||
"tags"
|
"tags"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -13245,9 +13184,6 @@
|
|||||||
"ratings": {
|
"ratings": {
|
||||||
"$ref": "#/components/schemas/RatingsUpdate"
|
"$ref": "#/components/schemas/RatingsUpdate"
|
||||||
},
|
},
|
||||||
"sharedLinks": {
|
|
||||||
"$ref": "#/components/schemas/SharedLinksUpdate"
|
|
||||||
},
|
|
||||||
"tags": {
|
"tags": {
|
||||||
"$ref": "#/components/schemas/TagsUpdate"
|
"$ref": "#/components/schemas/TagsUpdate"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"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.126.0",
|
"version": "1.125.7",
|
||||||
"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.126.0
|
* 1.125.7
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@@ -113,10 +113,6 @@ export type PurchaseResponse = {
|
|||||||
export type RatingsResponse = {
|
export type RatingsResponse = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
export type SharedLinksResponse = {
|
|
||||||
enabled: boolean;
|
|
||||||
sidebarWeb: boolean;
|
|
||||||
};
|
|
||||||
export type TagsResponse = {
|
export type TagsResponse = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
sidebarWeb: boolean;
|
sidebarWeb: boolean;
|
||||||
@@ -130,7 +126,6 @@ export type UserPreferencesResponseDto = {
|
|||||||
people: PeopleResponse;
|
people: PeopleResponse;
|
||||||
purchase: PurchaseResponse;
|
purchase: PurchaseResponse;
|
||||||
ratings: RatingsResponse;
|
ratings: RatingsResponse;
|
||||||
sharedLinks: SharedLinksResponse;
|
|
||||||
tags: TagsResponse;
|
tags: TagsResponse;
|
||||||
};
|
};
|
||||||
export type AvatarUpdate = {
|
export type AvatarUpdate = {
|
||||||
@@ -163,10 +158,6 @@ export type PurchaseUpdate = {
|
|||||||
export type RatingsUpdate = {
|
export type RatingsUpdate = {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
};
|
};
|
||||||
export type SharedLinksUpdate = {
|
|
||||||
enabled?: boolean;
|
|
||||||
sidebarWeb?: boolean;
|
|
||||||
};
|
|
||||||
export type TagsUpdate = {
|
export type TagsUpdate = {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
sidebarWeb?: boolean;
|
sidebarWeb?: boolean;
|
||||||
@@ -180,7 +171,6 @@ export type UserPreferencesUpdateDto = {
|
|||||||
people?: PeopleUpdate;
|
people?: PeopleUpdate;
|
||||||
purchase?: PurchaseUpdate;
|
purchase?: PurchaseUpdate;
|
||||||
ratings?: RatingsUpdate;
|
ratings?: RatingsUpdate;
|
||||||
sharedLinks?: SharedLinksUpdate;
|
|
||||||
tags?: TagsUpdate;
|
tags?: TagsUpdate;
|
||||||
};
|
};
|
||||||
export type AlbumUserResponseDto = {
|
export type AlbumUserResponseDto = {
|
||||||
@@ -223,8 +213,6 @@ export type AssetFaceWithoutPersonResponseDto = {
|
|||||||
};
|
};
|
||||||
export type PersonWithFacesResponseDto = {
|
export type PersonWithFacesResponseDto = {
|
||||||
birthDate: string | null;
|
birthDate: string | null;
|
||||||
/** This property was added in v1.126.0 */
|
|
||||||
color?: string;
|
|
||||||
faces: AssetFaceWithoutPersonResponseDto[];
|
faces: AssetFaceWithoutPersonResponseDto[];
|
||||||
id: string;
|
id: string;
|
||||||
/** This property was added in v1.126.0 */
|
/** This property was added in v1.126.0 */
|
||||||
@@ -505,8 +493,6 @@ export type DuplicateResponseDto = {
|
|||||||
};
|
};
|
||||||
export type PersonResponseDto = {
|
export type PersonResponseDto = {
|
||||||
birthDate: string | null;
|
birthDate: string | null;
|
||||||
/** This property was added in v1.126.0 */
|
|
||||||
color?: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
/** This property was added in v1.126.0 */
|
/** This property was added in v1.126.0 */
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
@@ -707,7 +693,6 @@ export type PersonCreateDto = {
|
|||||||
/** Person date of birth.
|
/** Person date of birth.
|
||||||
Note: the mobile app cannot currently set the birth date to null. */
|
Note: the mobile app cannot currently set the birth date to null. */
|
||||||
birthDate?: string | null;
|
birthDate?: string | null;
|
||||||
color?: string | null;
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
/** Person visibility */
|
/** Person visibility */
|
||||||
isHidden?: boolean;
|
isHidden?: boolean;
|
||||||
@@ -718,7 +703,6 @@ export type PeopleUpdateItem = {
|
|||||||
/** Person date of birth.
|
/** Person date of birth.
|
||||||
Note: the mobile app cannot currently set the birth date to null. */
|
Note: the mobile app cannot currently set the birth date to null. */
|
||||||
birthDate?: string | null;
|
birthDate?: string | null;
|
||||||
color?: string | null;
|
|
||||||
/** Asset is used to get the feature face thumbnail. */
|
/** Asset is used to get the feature face thumbnail. */
|
||||||
featureFaceAssetId?: string;
|
featureFaceAssetId?: string;
|
||||||
/** Person id. */
|
/** Person id. */
|
||||||
@@ -736,7 +720,6 @@ export type PersonUpdateDto = {
|
|||||||
/** Person date of birth.
|
/** Person date of birth.
|
||||||
Note: the mobile app cannot currently set the birth date to null. */
|
Note: the mobile app cannot currently set the birth date to null. */
|
||||||
birthDate?: string | null;
|
birthDate?: string | null;
|
||||||
color?: string | null;
|
|
||||||
/** Asset is used to get the feature face thumbnail. */
|
/** Asset is used to get the feature face thumbnail. */
|
||||||
featureFaceAssetId?: string;
|
featureFaceAssetId?: string;
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
@@ -2762,15 +2745,11 @@ export function deleteSession({ id }: {
|
|||||||
method: "DELETE"
|
method: "DELETE"
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
export function getAllSharedLinks({ albumId }: {
|
export function getAllSharedLinks(opts?: Oazapfts.RequestOpts) {
|
||||||
albumId?: string;
|
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
status: 200;
|
status: 200;
|
||||||
data: SharedLinkResponseDto[];
|
data: SharedLinkResponseDto[];
|
||||||
}>(`/shared-links${QS.query(QS.explode({
|
}>("/shared-links", {
|
||||||
albumId
|
|
||||||
}))}`, {
|
|
||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# dev build
|
# dev build
|
||||||
FROM ghcr.io/immich-app/base-server-dev:20250204@sha256:8b203f19f4d5cf4619b60ee5f50d6d4b5ea3745747f5e5170d1b7404ebeb0792 AS dev
|
FROM ghcr.io/immich-app/base-server-dev:20250123@sha256:04eba5cd87d61bc3d20a3915b2302f04d08fbc329c55ee0cde103c502f59f412 AS dev
|
||||||
|
|
||||||
RUN apt-get install --no-install-recommends -yqq tini
|
RUN apt-get install --no-install-recommends -yqq tini
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
@@ -42,7 +42,7 @@ RUN npm run build
|
|||||||
|
|
||||||
|
|
||||||
# prod build
|
# prod build
|
||||||
FROM ghcr.io/immich-app/base-server-prod:20250204@sha256:2af3da713d5ab3ccca23b216b747557ea6016117e72deac101e35069ccaf9b5e
|
FROM ghcr.io/immich-app/base-server-prod:20250123@sha256:591739983913f82672d8191258f3a1a24c123db0d619ff91fca8fef431ee1338
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
|
|||||||
Generated
+726
-1316
File diff suppressed because it is too large
Load Diff
+16
-16
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -35,16 +35,16 @@
|
|||||||
"email:dev": "email dev -p 3050 --dir src/emails"
|
"email:dev": "email dev -p 3050 --dir src/emails"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/bullmq": "^11.0.1",
|
"@nestjs/bullmq": "^11.0.0",
|
||||||
"@nestjs/common": "^11.0.4",
|
"@nestjs/common": "^10.2.2",
|
||||||
"@nestjs/core": "^11.0.4",
|
"@nestjs/core": "^10.2.2",
|
||||||
"@nestjs/event-emitter": "^3.0.0",
|
"@nestjs/event-emitter": "^3.0.0",
|
||||||
"@nestjs/platform-express": "^11.0.4",
|
"@nestjs/platform-express": "^10.2.2",
|
||||||
"@nestjs/platform-socket.io": "^11.0.4",
|
"@nestjs/platform-socket.io": "^10.2.2",
|
||||||
"@nestjs/schedule": "^5.0.0",
|
"@nestjs/schedule": "^5.0.0",
|
||||||
"@nestjs/swagger": "^11.0.2",
|
"@nestjs/swagger": "^8.0.0",
|
||||||
"@nestjs/typeorm": "^11.0.0",
|
"@nestjs/typeorm": "^10.0.0",
|
||||||
"@nestjs/websockets": "^11.0.4",
|
"@nestjs/websockets": "^10.2.2",
|
||||||
"@opentelemetry/auto-instrumentations-node": "^0.55.0",
|
"@opentelemetry/auto-instrumentations-node": "^0.55.0",
|
||||||
"@opentelemetry/context-async-hooks": "^1.24.0",
|
"@opentelemetry/context-async-hooks": "^1.24.0",
|
||||||
"@opentelemetry/exporter-prometheus": "^0.57.0",
|
"@opentelemetry/exporter-prometheus": "^0.57.0",
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"exiftool-vendored": "^28.3.1",
|
"exiftool-vendored": "^28.3.1",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "github:etnoy/fast-glob#built",
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"geo-tz": "^8.0.0",
|
"geo-tz": "^8.0.0",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
@@ -72,9 +72,9 @@
|
|||||||
"kysely-postgres-js": "^2.0.0",
|
"kysely-postgres-js": "^2.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"luxon": "^3.4.2",
|
"luxon": "^3.4.2",
|
||||||
"nest-commander": "^3.16.0",
|
"nest-commander": "^3.11.1",
|
||||||
"nestjs-cls": "^5.0.0",
|
"nestjs-cls": "^4.3.0",
|
||||||
"nestjs-kysely": "^1.1.0",
|
"nestjs-kysely": "^1.0.0",
|
||||||
"nestjs-otel": "^6.0.0",
|
"nestjs-otel": "^6.0.0",
|
||||||
"nodemailer": "^6.9.13",
|
"nodemailer": "^6.9.13",
|
||||||
"openid-client": "^5.4.3",
|
"openid-client": "^5.4.3",
|
||||||
@@ -97,9 +97,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@nestjs/cli": "^11.0.2",
|
"@nestjs/cli": "^10.1.16",
|
||||||
"@nestjs/schematics": "^11.0.0",
|
"@nestjs/schematics": "^10.0.2",
|
||||||
"@nestjs/testing": "^11.0.4",
|
"@nestjs/testing": "^10.2.2",
|
||||||
"@swc/core": "^1.4.14",
|
"@swc/core": "^1.4.14",
|
||||||
"@testcontainers/postgresql": "^10.2.1",
|
"@testcontainers/postgresql": "^10.2.1",
|
||||||
"@types/archiver": "^6.0.0",
|
"@types/archiver": "^6.0.0",
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
SharedLinkEditDto,
|
SharedLinkEditDto,
|
||||||
SharedLinkPasswordDto,
|
SharedLinkPasswordDto,
|
||||||
SharedLinkResponseDto,
|
SharedLinkResponseDto,
|
||||||
SharedLinkSearchDto,
|
|
||||||
} from 'src/dtos/shared-link.dto';
|
} from 'src/dtos/shared-link.dto';
|
||||||
import { ImmichCookie, Permission } from 'src/enum';
|
import { ImmichCookie, Permission } from 'src/enum';
|
||||||
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
|
||||||
@@ -25,8 +24,8 @@ export class SharedLinkController {
|
|||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@Authenticated({ permission: Permission.SHARED_LINK_READ })
|
@Authenticated({ permission: Permission.SHARED_LINK_READ })
|
||||||
getAllSharedLinks(@Auth() auth: AuthDto, @Query() dto: SharedLinkSearchDto): Promise<SharedLinkResponseDto[]> {
|
getAllSharedLinks(@Auth() auth: AuthDto): Promise<SharedLinkResponseDto[]> {
|
||||||
return this.service.getAll(auth, dto);
|
return this.service.getAll(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('me')
|
@Get('me')
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
|||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
import { IConfigRepository, ILoggingRepository, ISystemMetadataRepository } from 'src/types';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
|
import { IConfigRepository, ILoggingRepository } from 'src/types';
|
||||||
import { getAssetFiles } from 'src/utils/asset.util';
|
import { getAssetFiles } from 'src/utils/asset.util';
|
||||||
import { getConfig } from 'src/utils/config';
|
import { getConfig } from 'src/utils/config';
|
||||||
|
|
||||||
|
|||||||
Vendored
-1
@@ -276,7 +276,6 @@ export interface Partners {
|
|||||||
|
|
||||||
export interface Person {
|
export interface Person {
|
||||||
birthDate: Timestamp | null;
|
birthDate: Timestamp | null;
|
||||||
color: string | null;
|
|
||||||
createdAt: Generated<Timestamp>;
|
createdAt: Generated<Timestamp>;
|
||||||
faceAssetId: string | null;
|
faceAssetId: string | null;
|
||||||
id: Generated<string>;
|
id: Generated<string>;
|
||||||
|
|||||||
@@ -7,14 +7,7 @@ import { AuthDto } from 'src/dtos/auth.dto';
|
|||||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
import { PersonEntity } from 'src/entities/person.entity';
|
||||||
import { SourceType } from 'src/enum';
|
import { SourceType } from 'src/enum';
|
||||||
import {
|
import { IsDateStringFormat, MaxDateString, Optional, ValidateBoolean, ValidateUUID } from 'src/validation';
|
||||||
IsDateStringFormat,
|
|
||||||
MaxDateString,
|
|
||||||
Optional,
|
|
||||||
ValidateBoolean,
|
|
||||||
ValidateHexColor,
|
|
||||||
ValidateUUID,
|
|
||||||
} from 'src/validation';
|
|
||||||
|
|
||||||
export class PersonCreateDto {
|
export class PersonCreateDto {
|
||||||
/**
|
/**
|
||||||
@@ -42,10 +35,6 @@ export class PersonCreateDto {
|
|||||||
|
|
||||||
@ValidateBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@Optional({ emptyToNull: true, nullable: true })
|
|
||||||
@ValidateHexColor()
|
|
||||||
color?: string | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PersonUpdateDto extends PersonCreateDto {
|
export class PersonUpdateDto extends PersonCreateDto {
|
||||||
@@ -113,8 +102,6 @@ export class PersonResponseDto {
|
|||||||
updatedAt?: Date;
|
updatedAt?: Date;
|
||||||
@PropertyLifecycle({ addedAt: 'v1.126.0' })
|
@PropertyLifecycle({ addedAt: 'v1.126.0' })
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
@PropertyLifecycle({ addedAt: 'v1.126.0' })
|
|
||||||
color?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PersonWithFacesResponseDto extends PersonResponseDto {
|
export class PersonWithFacesResponseDto extends PersonResponseDto {
|
||||||
@@ -189,7 +176,6 @@ export function mapPerson(person: PersonEntity): PersonResponseDto {
|
|||||||
thumbnailPath: person.thumbnailPath,
|
thumbnailPath: person.thumbnailPath,
|
||||||
isHidden: person.isHidden,
|
isHidden: person.isHidden,
|
||||||
isFavorite: person.isFavorite,
|
isFavorite: person.isFavorite,
|
||||||
color: person.color ?? undefined,
|
|
||||||
updatedAt: person.updatedAt,
|
updatedAt: person.updatedAt,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { SessionItem } from 'src/types';
|
import { SessionEntity } from 'src/entities/session.entity';
|
||||||
|
|
||||||
export class SessionResponseDto {
|
export class SessionResponseDto {
|
||||||
id!: string;
|
id!: string;
|
||||||
@@ -9,7 +9,7 @@ export class SessionResponseDto {
|
|||||||
deviceOS!: string;
|
deviceOS!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapSession = (entity: SessionItem, currentId?: string): SessionResponseDto => ({
|
export const mapSession = (entity: SessionEntity, currentId?: string): SessionResponseDto => ({
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
createdAt: entity.createdAt.toISOString(),
|
createdAt: entity.createdAt.toISOString(),
|
||||||
updatedAt: entity.updatedAt.toISOString(),
|
updatedAt: entity.updatedAt.toISOString(),
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
|||||||
import { SharedLinkType } from 'src/enum';
|
import { SharedLinkType } from 'src/enum';
|
||||||
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
|
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
export class SharedLinkSearchDto {
|
|
||||||
@ValidateUUID({ optional: true })
|
|
||||||
albumId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SharedLinkCreateDto {
|
export class SharedLinkCreateDto {
|
||||||
@IsEnum(SharedLinkType)
|
@IsEnum(SharedLinkType)
|
||||||
@ApiProperty({ enum: SharedLinkType, enumName: 'SharedLinkType' })
|
@ApiProperty({ enum: SharedLinkType, enumName: 'SharedLinkType' })
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { Transform } from 'class-transformer';
|
||||||
import { IsHexColor, IsNotEmpty, IsString } from 'class-validator';
|
import { IsHexColor, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { TagEntity } from 'src/entities/tag.entity';
|
import { TagEntity } from 'src/entities/tag.entity';
|
||||||
import { Optional, ValidateHexColor, ValidateUUID } from 'src/validation';
|
import { Optional, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
export class TagCreateDto {
|
export class TagCreateDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -17,8 +18,9 @@ export class TagCreateDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TagUpdateDto {
|
export class TagUpdateDto {
|
||||||
@Optional({ emptyToNull: true, nullable: true })
|
@Optional({ nullable: true, emptyToNull: true })
|
||||||
@ValidateHexColor()
|
@IsHexColor()
|
||||||
|
@Transform(({ value }) => (typeof value === 'string' && value[0] !== '#' ? `#${value}` : value))
|
||||||
color?: string | null;
|
color?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,14 +38,6 @@ class PeopleUpdate {
|
|||||||
sidebarWeb?: boolean;
|
sidebarWeb?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SharedLinksUpdate {
|
|
||||||
@ValidateBoolean({ optional: true })
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
@ValidateBoolean({ optional: true })
|
|
||||||
sidebarWeb?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TagsUpdate {
|
class TagsUpdate {
|
||||||
@ValidateBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
@@ -106,11 +98,6 @@ export class UserPreferencesUpdateDto {
|
|||||||
@Type(() => RatingsUpdate)
|
@Type(() => RatingsUpdate)
|
||||||
ratings?: RatingsUpdate;
|
ratings?: RatingsUpdate;
|
||||||
|
|
||||||
@Optional()
|
|
||||||
@ValidateNested()
|
|
||||||
@Type(() => SharedLinksUpdate)
|
|
||||||
sharedLinks?: SharedLinksUpdate;
|
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => TagsUpdate)
|
@Type(() => TagsUpdate)
|
||||||
@@ -165,11 +152,6 @@ class TagsResponse {
|
|||||||
sidebarWeb: boolean = true;
|
sidebarWeb: boolean = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SharedLinksResponse {
|
|
||||||
enabled: boolean = true;
|
|
||||||
sidebarWeb: boolean = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmailNotificationsResponse {
|
class EmailNotificationsResponse {
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
albumInvite!: boolean;
|
albumInvite!: boolean;
|
||||||
@@ -193,7 +175,6 @@ export class UserPreferencesResponseDto implements UserPreferences {
|
|||||||
memories!: MemoriesResponse;
|
memories!: MemoriesResponse;
|
||||||
people!: PeopleResponse;
|
people!: PeopleResponse;
|
||||||
ratings!: RatingsResponse;
|
ratings!: RatingsResponse;
|
||||||
sharedLinks!: SharedLinksResponse;
|
|
||||||
tags!: TagsResponse;
|
tags!: TagsResponse;
|
||||||
avatar!: AvatarResponse;
|
avatar!: AvatarResponse;
|
||||||
emailNotifications!: EmailNotificationsResponse;
|
emailNotifications!: EmailNotificationsResponse;
|
||||||
|
|||||||
@@ -52,7 +52,4 @@ export class PersonEntity {
|
|||||||
|
|
||||||
@Column({ default: false })
|
@Column({ default: false })
|
||||||
isFavorite!: boolean;
|
isFavorite!: boolean;
|
||||||
|
|
||||||
@Column({ type: 'varchar', nullable: true, default: null })
|
|
||||||
color?: string | null;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ export interface UserPreferences {
|
|||||||
ratings: {
|
ratings: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
sharedLinks: {
|
|
||||||
enabled: boolean;
|
|
||||||
sidebarWeb: boolean;
|
|
||||||
};
|
|
||||||
tags: {
|
tags: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
sidebarWeb: boolean;
|
sidebarWeb: boolean;
|
||||||
@@ -78,10 +74,6 @@ export const getDefaultPreferences = (user: { email: string }): UserPreferences
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
sidebarWeb: false,
|
sidebarWeb: false,
|
||||||
},
|
},
|
||||||
sharedLinks: {
|
|
||||||
enabled: true,
|
|
||||||
sidebarWeb: false,
|
|
||||||
},
|
|
||||||
ratings: {
|
ratings: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio } from 'node:child_process';
|
||||||
|
import { Readable } from 'node:stream';
|
||||||
|
|
||||||
|
export interface ImmichReadStream {
|
||||||
|
stream: Readable;
|
||||||
|
type?: string;
|
||||||
|
length?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImmichZipStream extends ImmichReadStream {
|
||||||
|
addFile: (inputPath: string, filename: string) => void;
|
||||||
|
finalize: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DiskUsage {
|
||||||
|
available: number;
|
||||||
|
free: number;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IProcessRepository = 'IProcessRepository';
|
||||||
|
|
||||||
|
export interface IProcessRepository {
|
||||||
|
spawn(command: string, args?: readonly string[], options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Insertable, Updateable } from 'kysely';
|
||||||
|
import { Sessions } from 'src/db';
|
||||||
|
import { SessionEntity } from 'src/entities/session.entity';
|
||||||
|
|
||||||
|
export const ISessionRepository = 'ISessionRepository';
|
||||||
|
|
||||||
|
type E = SessionEntity;
|
||||||
|
export type SessionSearchOptions = { updatedBefore: Date };
|
||||||
|
|
||||||
|
export interface ISessionRepository {
|
||||||
|
search(options: SessionSearchOptions): Promise<SessionEntity[]>;
|
||||||
|
create(dto: Insertable<Sessions>): Promise<SessionEntity>;
|
||||||
|
update(id: string, dto: Updateable<Sessions>): Promise<SessionEntity>;
|
||||||
|
delete(id: string): Promise<void>;
|
||||||
|
getByToken(token: string): Promise<E | undefined>;
|
||||||
|
getByUserId(userId: string): Promise<E[]>;
|
||||||
|
}
|
||||||
@@ -4,13 +4,8 @@ import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
|||||||
|
|
||||||
export const ISharedLinkRepository = 'ISharedLinkRepository';
|
export const ISharedLinkRepository = 'ISharedLinkRepository';
|
||||||
|
|
||||||
export type SharedLinkSearchOptions = {
|
|
||||||
userId: string;
|
|
||||||
albumId?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ISharedLinkRepository {
|
export interface ISharedLinkRepository {
|
||||||
getAll(options: SharedLinkSearchOptions): Promise<SharedLinkEntity[]>;
|
getAll(userId: string): Promise<SharedLinkEntity[]>;
|
||||||
get(userId: string, id: string): Promise<SharedLinkEntity | undefined>;
|
get(userId: string, id: string): Promise<SharedLinkEntity | undefined>;
|
||||||
getByKey(key: Buffer): Promise<SharedLinkEntity | undefined>;
|
getByKey(key: Buffer): Promise<SharedLinkEntity | undefined>;
|
||||||
create(entity: Insertable<SharedLinks> & { assetIds?: string[] }): Promise<SharedLinkEntity>;
|
create(entity: Insertable<SharedLinks> & { assetIds?: string[] }): Promise<SharedLinkEntity>;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { SystemMetadata } from 'src/entities/system-metadata.entity';
|
||||||
|
|
||||||
|
export const ISystemMetadataRepository = 'ISystemMetadataRepository';
|
||||||
|
|
||||||
|
export interface ISystemMetadataRepository {
|
||||||
|
get<T extends keyof SystemMetadata>(key: T): Promise<SystemMetadata[T] | null>;
|
||||||
|
set<T extends keyof SystemMetadata>(key: T, value: SystemMetadata[T]): Promise<void>;
|
||||||
|
delete<T extends keyof SystemMetadata>(key: T): Promise<void>;
|
||||||
|
readFile(filename: string): Promise<string>;
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
||||||
|
|
||||||
export class AddPersonColor1738889177573 implements MigrationInterface {
|
|
||||||
name = 'AddPersonColor1738889177573'
|
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`ALTER TABLE "person" ADD "color" character varying`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`ALTER TABLE "person" DROP COLUMN "color"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,10 +9,13 @@ import { IMachineLearningRepository } from 'src/interfaces/machine-learning.inte
|
|||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
import { IStackRepository } from 'src/interfaces/stack.interface';
|
import { IStackRepository } from 'src/interfaces/stack.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
@@ -70,10 +73,7 @@ export const repositories = [
|
|||||||
MetadataRepository,
|
MetadataRepository,
|
||||||
NotificationRepository,
|
NotificationRepository,
|
||||||
OAuthRepository,
|
OAuthRepository,
|
||||||
ProcessRepository,
|
|
||||||
SessionRepository,
|
|
||||||
ServerInfoRepository,
|
ServerInfoRepository,
|
||||||
SystemMetadataRepository,
|
|
||||||
TelemetryRepository,
|
TelemetryRepository,
|
||||||
TrashRepository,
|
TrashRepository,
|
||||||
ViewRepository,
|
ViewRepository,
|
||||||
@@ -92,10 +92,13 @@ export const providers = [
|
|||||||
{ provide: IMoveRepository, useClass: MoveRepository },
|
{ provide: IMoveRepository, useClass: MoveRepository },
|
||||||
{ provide: IPartnerRepository, useClass: PartnerRepository },
|
{ provide: IPartnerRepository, useClass: PartnerRepository },
|
||||||
{ provide: IPersonRepository, useClass: PersonRepository },
|
{ provide: IPersonRepository, useClass: PersonRepository },
|
||||||
|
{ provide: IProcessRepository, useClass: ProcessRepository },
|
||||||
{ provide: ISearchRepository, useClass: SearchRepository },
|
{ provide: ISearchRepository, useClass: SearchRepository },
|
||||||
|
{ provide: ISessionRepository, useClass: SessionRepository },
|
||||||
{ provide: ISharedLinkRepository, useClass: SharedLinkRepository },
|
{ provide: ISharedLinkRepository, useClass: SharedLinkRepository },
|
||||||
{ provide: IStackRepository, useClass: StackRepository },
|
{ provide: IStackRepository, useClass: StackRepository },
|
||||||
{ provide: IStorageRepository, useClass: StorageRepository },
|
{ provide: IStorageRepository, useClass: StorageRepository },
|
||||||
|
{ provide: ISystemMetadataRepository, useClass: SystemMetadataRepository },
|
||||||
{ provide: ITagRepository, useClass: TagRepository },
|
{ provide: ITagRepository, useClass: TagRepository },
|
||||||
{ provide: IUserRepository, useClass: UserRepository },
|
{ provide: IUserRepository, useClass: UserRepository },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { getName } from 'i18n-iso-countries';
|
import { getName } from 'i18n-iso-countries';
|
||||||
import { Expression, Kysely, sql, SqlBool } from 'kysely';
|
import { Expression, Kysely, sql, SqlBool } from 'kysely';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
@@ -11,9 +11,9 @@ import { DB, GeodataPlaces, NaturalearthCountries } from 'src/db';
|
|||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { NaturalEarthCountriesTempEntity } from 'src/entities/natural-earth-countries.entity';
|
import { NaturalEarthCountriesTempEntity } from 'src/entities/natural-earth-countries.entity';
|
||||||
import { LogLevel, SystemMetadataKey } from 'src/enum';
|
import { LogLevel, SystemMetadataKey } from 'src/enum';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
|
||||||
|
|
||||||
export interface MapMarkerSearchOptions {
|
export interface MapMarkerSearchOptions {
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
@@ -48,7 +48,7 @@ interface MapDB extends DB {
|
|||||||
export class MapRepository {
|
export class MapRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private configRepository: ConfigRepository,
|
private configRepository: ConfigRepository,
|
||||||
private metadataRepository: SystemMetadataRepository,
|
@Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository,
|
||||||
private logger: LoggingRepository,
|
private logger: LoggingRepository,
|
||||||
@InjectKysely() private db: Kysely<MapDB>,
|
@InjectKysely() private db: Kysely<MapDB>,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -43,12 +43,7 @@ export class OAuthRepository {
|
|||||||
const params = client.callbackParams(url);
|
const params = client.callbackParams(url);
|
||||||
try {
|
try {
|
||||||
const tokens = await client.callback(redirectUrl, params, { state: params.state });
|
const tokens = await client.callback(redirectUrl, params, { state: params.state });
|
||||||
const profile = await client.userinfo<OAuthProfile>(tokens.access_token || '');
|
return await client.userinfo<OAuthProfile>(tokens.access_token || '');
|
||||||
if (!profile.sub) {
|
|
||||||
throw new Error('Unexpected profile response, no `sub`');
|
|
||||||
}
|
|
||||||
|
|
||||||
return profile;
|
|
||||||
} catch (error: Error | any) {
|
} catch (error: Error | any) {
|
||||||
if (error.message.includes('unexpected JWT alg received')) {
|
if (error.message.includes('unexpected JWT alg received')) {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ChildProcessWithoutNullStreams, spawn, SpawnOptionsWithoutStdio } from 'node:child_process';
|
import { ChildProcessWithoutNullStreams, spawn, SpawnOptionsWithoutStdio } from 'node:child_process';
|
||||||
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { StorageRepository } from 'src/repositories/storage.repository';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProcessRepository {
|
export class ProcessRepository implements IProcessRepository {
|
||||||
constructor(private logger: LoggingRepository) {
|
constructor(private logger: LoggingRepository) {
|
||||||
this.logger.setContext(ProcessRepository.name);
|
this.logger.setContext(StorageRepository.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
spawn(command: string, args: readonly string[], options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams {
|
spawn(command: string, args: readonly string[], options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams {
|
||||||
|
|||||||
@@ -3,37 +3,36 @@ import { Insertable, Kysely, Updateable } from 'kysely';
|
|||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { DB, Sessions } from 'src/db';
|
import { DB, Sessions } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { withUser } from 'src/entities/session.entity';
|
import { SessionEntity, withUser } from 'src/entities/session.entity';
|
||||||
|
import { ISessionRepository, SessionSearchOptions } from 'src/interfaces/session.interface';
|
||||||
import { asUuid } from 'src/utils/database';
|
import { asUuid } from 'src/utils/database';
|
||||||
|
|
||||||
export type SessionSearchOptions = { updatedBefore: Date };
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SessionRepository {
|
export class SessionRepository implements ISessionRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ updatedBefore: DummyValue.DATE }] })
|
@GenerateSql({ params: [{ updatedBefore: DummyValue.DATE }] })
|
||||||
search(options: SessionSearchOptions) {
|
search(options: SessionSearchOptions): Promise<SessionEntity[]> {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('sessions')
|
.selectFrom('sessions')
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.where('sessions.updatedAt', '<=', options.updatedBefore)
|
.where('sessions.updatedAt', '<=', options.updatedBefore)
|
||||||
.execute();
|
.execute() as Promise<SessionEntity[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.STRING] })
|
@GenerateSql({ params: [DummyValue.STRING] })
|
||||||
getByToken(token: string) {
|
getByToken(token: string): Promise<SessionEntity | undefined> {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('sessions')
|
.selectFrom('sessions')
|
||||||
.innerJoinLateral(withUser, (join) => join.onTrue())
|
.innerJoinLateral(withUser, (join) => join.onTrue())
|
||||||
.selectAll('sessions')
|
.selectAll('sessions')
|
||||||
.select((eb) => eb.fn.toJson('user').as('user'))
|
.select((eb) => eb.fn.toJson('user').as('user'))
|
||||||
.where('sessions.token', '=', token)
|
.where('sessions.token', '=', token)
|
||||||
.executeTakeFirst();
|
.executeTakeFirst() as Promise<SessionEntity | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
getByUserId(userId: string) {
|
getByUserId(userId: string): Promise<SessionEntity[]> {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('sessions')
|
.selectFrom('sessions')
|
||||||
.innerJoinLateral(withUser, (join) => join.onTrue())
|
.innerJoinLateral(withUser, (join) => join.onTrue())
|
||||||
@@ -42,24 +41,30 @@ export class SessionRepository {
|
|||||||
.where('sessions.userId', '=', userId)
|
.where('sessions.userId', '=', userId)
|
||||||
.orderBy('sessions.updatedAt', 'desc')
|
.orderBy('sessions.updatedAt', 'desc')
|
||||||
.orderBy('sessions.createdAt', 'desc')
|
.orderBy('sessions.createdAt', 'desc')
|
||||||
.execute();
|
.execute() as unknown as Promise<SessionEntity[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
create(dto: Insertable<Sessions>) {
|
async create(dto: Insertable<Sessions>): Promise<SessionEntity> {
|
||||||
return this.db.insertInto('sessions').values(dto).returningAll().executeTakeFirstOrThrow();
|
const { id, token, userId, createdAt, updatedAt, deviceType, deviceOS } = await this.db
|
||||||
|
.insertInto('sessions')
|
||||||
|
.values(dto)
|
||||||
|
.returningAll()
|
||||||
|
.executeTakeFirstOrThrow();
|
||||||
|
|
||||||
|
return { id, token, userId, createdAt, updatedAt, deviceType, deviceOS } as SessionEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
update(id: string, dto: Updateable<Sessions>) {
|
update(id: string, dto: Updateable<Sessions>): Promise<SessionEntity> {
|
||||||
return this.db
|
return this.db
|
||||||
.updateTable('sessions')
|
.updateTable('sessions')
|
||||||
.set(dto)
|
.set(dto)
|
||||||
.where('sessions.id', '=', asUuid(id))
|
.where('sessions.id', '=', asUuid(id))
|
||||||
.returningAll()
|
.returningAll()
|
||||||
.executeTakeFirstOrThrow();
|
.executeTakeFirstOrThrow() as Promise<SessionEntity>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
async delete(id: string) {
|
async delete(id: string): Promise<void> {
|
||||||
await this.db.deleteFrom('sessions').where('id', '=', asUuid(id)).execute();
|
await this.db.deleteFrom('sessions').where('id', '=', asUuid(id)).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { DB, SharedLinks } from 'src/db';
|
|||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||||
import { SharedLinkType } from 'src/enum';
|
import { SharedLinkType } from 'src/enum';
|
||||||
import { ISharedLinkRepository, SharedLinkSearchOptions } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SharedLinkRepository implements ISharedLinkRepository {
|
export class SharedLinkRepository implements ISharedLinkRepository {
|
||||||
@@ -93,7 +93,7 @@ export class SharedLinkRepository implements ISharedLinkRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
getAll({ userId, albumId }: SharedLinkSearchOptions): Promise<SharedLinkEntity[]> {
|
getAll(userId: string): Promise<SharedLinkEntity[]> {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('shared_links')
|
.selectFrom('shared_links')
|
||||||
.selectAll('shared_links')
|
.selectAll('shared_links')
|
||||||
@@ -149,7 +149,6 @@ export class SharedLinkRepository implements ISharedLinkRepository {
|
|||||||
)
|
)
|
||||||
.select((eb) => eb.fn.toJson('album').as('album'))
|
.select((eb) => eb.fn.toJson('album').as('album'))
|
||||||
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
|
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
|
||||||
.$if(!!albumId, (eb) => eb.where('shared_links.albumId', '=', albumId!))
|
|
||||||
.orderBy('shared_links.createdAt', 'desc')
|
.orderBy('shared_links.createdAt', 'desc')
|
||||||
.distinctOn(['shared_links.createdAt'])
|
.distinctOn(['shared_links.createdAt'])
|
||||||
.execute() as unknown as Promise<SharedLinkEntity[]>;
|
.execute() as unknown as Promise<SharedLinkEntity[]>;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import archiver from 'archiver';
|
import archiver from 'archiver';
|
||||||
import chokidar, { WatchOptions } from 'chokidar';
|
import chokidar, { WatchOptions } from 'chokidar';
|
||||||
import { escapePath, glob, globStream } from 'fast-glob';
|
import { escapePath, glob, globStream } from 'fast-glob';
|
||||||
|
import { ErrnoException } from 'fast-glob/out/types';
|
||||||
import { constants, createReadStream, createWriteStream, existsSync, mkdirSync } from 'node:fs';
|
import { constants, createReadStream, createWriteStream, existsSync, mkdirSync } from 'node:fs';
|
||||||
import fs from 'node:fs/promises';
|
import fs from 'node:fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
@@ -170,6 +171,19 @@ export class StorageRepository implements IStorageRepository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private errorHandler = (error: ErrnoException) => {
|
||||||
|
if (error.code === 'ENOENT') {
|
||||||
|
this.logger.warn(`Path ${error.path} does not exist, ignoring.`);
|
||||||
|
return true;
|
||||||
|
} else if (error.code === 'EACCES') {
|
||||||
|
this.logger.warn(`Permission denied for path ${error.path}, ignoring.`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.error(`Error while walking path ${error.path}: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
async *walk(walkOptions: WalkOptionsDto): AsyncGenerator<string[]> {
|
async *walk(walkOptions: WalkOptionsDto): AsyncGenerator<string[]> {
|
||||||
const { pathsToCrawl, exclusionPatterns, includeHidden } = walkOptions;
|
const { pathsToCrawl, exclusionPatterns, includeHidden } = walkOptions;
|
||||||
if (pathsToCrawl.length === 0) {
|
if (pathsToCrawl.length === 0) {
|
||||||
@@ -185,6 +199,7 @@ export class StorageRepository implements IStorageRepository {
|
|||||||
onlyFiles: true,
|
onlyFiles: true,
|
||||||
dot: includeHidden,
|
dot: includeHidden,
|
||||||
ignore: exclusionPatterns,
|
ignore: exclusionPatterns,
|
||||||
|
errorHandler: this.errorHandler,
|
||||||
});
|
});
|
||||||
|
|
||||||
let batch: string[] = [];
|
let batch: string[] = [];
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import { readFile } from 'node:fs/promises';
|
|||||||
import { DB, SystemMetadata as DbSystemMetadata } from 'src/db';
|
import { DB, SystemMetadata as DbSystemMetadata } from 'src/db';
|
||||||
import { GenerateSql } from 'src/decorators';
|
import { GenerateSql } from 'src/decorators';
|
||||||
import { SystemMetadata } from 'src/entities/system-metadata.entity';
|
import { SystemMetadata } from 'src/entities/system-metadata.entity';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
|
|
||||||
type Upsert = Insertable<DbSystemMetadata>;
|
type Upsert = Insertable<DbSystemMetadata>;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SystemMetadataRepository {
|
export class SystemMetadataRepository implements ISystemMetadataRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: ['metadata_key'] })
|
@GenerateSql({ params: ['metadata_key'] })
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import { IEventRepository } from 'src/interfaces/event.interface';
|
|||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||||
import { IStackRepository } from 'src/interfaces/stack.interface';
|
import { IStackRepository } from 'src/interfaces/stack.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { AssetService } from 'src/services/asset.service';
|
import { AssetService } from 'src/services/asset.service';
|
||||||
import { ISystemMetadataRepository } from 'src/types';
|
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { faceStub } from 'test/fixtures/face.stub';
|
import { faceStub } from 'test/fixtures/face.stub';
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import { UserEntity } from 'src/entities/user.entity';
|
|||||||
import { AuthType, Permission } from 'src/enum';
|
import { AuthType, Permission } from 'src/enum';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { AuthService } from 'src/services/auth.service';
|
import { AuthService } from 'src/services/auth.service';
|
||||||
import { IApiKeyRepository, IOAuthRepository, ISessionRepository, ISystemMetadataRepository } from 'src/types';
|
import { IApiKeyRepository, IOAuthRepository } from 'src/types';
|
||||||
import { keyStub } from 'test/fixtures/api-key.stub';
|
import { keyStub } from 'test/fixtures/api-key.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { sessionStub } from 'test/fixtures/session.stub';
|
import { sessionStub } from 'test/fixtures/session.stub';
|
||||||
@@ -256,7 +258,7 @@ describe('AuthService', () => {
|
|||||||
|
|
||||||
it('should validate using authorization header', async () => {
|
it('should validate using authorization header', async () => {
|
||||||
userMock.get.mockResolvedValue(userStub.user1);
|
userMock.get.mockResolvedValue(userStub.user1);
|
||||||
sessionMock.getByToken.mockResolvedValue(sessionStub.valid as any);
|
sessionMock.getByToken.mockResolvedValue(sessionStub.valid);
|
||||||
await expect(
|
await expect(
|
||||||
sut.authenticate({
|
sut.authenticate({
|
||||||
headers: { authorization: 'Bearer auth_token' },
|
headers: { authorization: 'Bearer auth_token' },
|
||||||
@@ -361,7 +363,7 @@ describe('AuthService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return an auth dto', async () => {
|
it('should return an auth dto', async () => {
|
||||||
sessionMock.getByToken.mockResolvedValue(sessionStub.valid as any);
|
sessionMock.getByToken.mockResolvedValue(sessionStub.valid);
|
||||||
await expect(
|
await expect(
|
||||||
sut.authenticate({
|
sut.authenticate({
|
||||||
headers: { cookie: 'immich_access_token=auth_token' },
|
headers: { cookie: 'immich_access_token=auth_token' },
|
||||||
@@ -375,7 +377,7 @@ describe('AuthService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if admin route and not an admin', async () => {
|
it('should throw if admin route and not an admin', async () => {
|
||||||
sessionMock.getByToken.mockResolvedValue(sessionStub.valid as any);
|
sessionMock.getByToken.mockResolvedValue(sessionStub.valid);
|
||||||
await expect(
|
await expect(
|
||||||
sut.authenticate({
|
sut.authenticate({
|
||||||
headers: { cookie: 'immich_access_token=auth_token' },
|
headers: { cookie: 'immich_access_token=auth_token' },
|
||||||
@@ -386,7 +388,7 @@ describe('AuthService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should update when access time exceeds an hour', async () => {
|
it('should update when access time exceeds an hour', async () => {
|
||||||
sessionMock.getByToken.mockResolvedValue(sessionStub.inactive as any);
|
sessionMock.getByToken.mockResolvedValue(sessionStub.inactive);
|
||||||
sessionMock.update.mockResolvedValue(sessionStub.valid);
|
sessionMock.update.mockResolvedValue(sessionStub.valid);
|
||||||
await expect(
|
await expect(
|
||||||
sut.authenticate({
|
sut.authenticate({
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
mapLoginResponse,
|
mapLoginResponse,
|
||||||
} from 'src/dtos/auth.dto';
|
} from 'src/dtos/auth.dto';
|
||||||
import { UserAdminResponseDto, mapUserAdmin } from 'src/dtos/user.dto';
|
import { UserAdminResponseDto, mapUserAdmin } from 'src/dtos/user.dto';
|
||||||
import { SessionEntity } from 'src/entities/session.entity';
|
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { AuthType, ImmichCookie, ImmichHeader, ImmichQuery, Permission } from 'src/enum';
|
import { AuthType, ImmichCookie, ImmichHeader, ImmichQuery, Permission } from 'src/enum';
|
||||||
import { OAuthProfile } from 'src/repositories/oauth.repository';
|
import { OAuthProfile } from 'src/repositories/oauth.repository';
|
||||||
@@ -339,7 +338,7 @@ export class AuthService extends BaseService {
|
|||||||
await this.sessionRepository.update(session.id, { id: session.id, updatedAt: new Date() });
|
await this.sessionRepository.update(session.id, { id: session.id, updatedAt: new Date() });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { user: session.user as unknown as UserEntity, session: session as unknown as SessionEntity };
|
return { user: session.user, session };
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnauthorizedException('Invalid user token');
|
throw new UnauthorizedException('Invalid user token');
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import { StorageCore } from 'src/cores/storage.core';
|
|||||||
import { ImmichWorker, StorageFolder } from 'src/enum';
|
import { ImmichWorker, StorageFolder } from 'src/enum';
|
||||||
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
||||||
import { JobStatus } from 'src/interfaces/job.interface';
|
import { JobStatus } from 'src/interfaces/job.interface';
|
||||||
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { BackupService } from 'src/services/backup.service';
|
import { BackupService } from 'src/services/backup.service';
|
||||||
import { IConfigRepository, ICronRepository, IProcessRepository, ISystemMetadataRepository } from 'src/types';
|
import { IConfigRepository, ICronRepository } from 'src/types';
|
||||||
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
||||||
import { mockSpawn, newTestService } from 'test/utils';
|
import { mockSpawn, newTestService } from 'test/utils';
|
||||||
import { describe, Mocked } from 'vitest';
|
import { describe, Mocked } from 'vitest';
|
||||||
|
|||||||
@@ -17,10 +17,13 @@ import { IMachineLearningRepository } from 'src/interfaces/machine-learning.inte
|
|||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
import { IStackRepository } from 'src/interfaces/stack.interface';
|
import { IStackRepository } from 'src/interfaces/stack.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
@@ -37,10 +40,7 @@ import { MemoryRepository } from 'src/repositories/memory.repository';
|
|||||||
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||||
import { NotificationRepository } from 'src/repositories/notification.repository';
|
import { NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
||||||
import { ProcessRepository } from 'src/repositories/process.repository';
|
|
||||||
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
||||||
import { SessionRepository } from 'src/repositories/session.repository';
|
|
||||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
|
||||||
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
|
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
import { TrashRepository } from 'src/repositories/trash.repository';
|
import { TrashRepository } from 'src/repositories/trash.repository';
|
||||||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||||
@@ -77,14 +77,14 @@ export class BaseService {
|
|||||||
protected oauthRepository: OAuthRepository,
|
protected oauthRepository: OAuthRepository,
|
||||||
@Inject(IPartnerRepository) protected partnerRepository: IPartnerRepository,
|
@Inject(IPartnerRepository) protected partnerRepository: IPartnerRepository,
|
||||||
@Inject(IPersonRepository) protected personRepository: IPersonRepository,
|
@Inject(IPersonRepository) protected personRepository: IPersonRepository,
|
||||||
protected processRepository: ProcessRepository,
|
@Inject(IProcessRepository) protected processRepository: IProcessRepository,
|
||||||
@Inject(ISearchRepository) protected searchRepository: ISearchRepository,
|
@Inject(ISearchRepository) protected searchRepository: ISearchRepository,
|
||||||
protected serverInfoRepository: ServerInfoRepository,
|
protected serverInfoRepository: ServerInfoRepository,
|
||||||
protected sessionRepository: SessionRepository,
|
@Inject(ISessionRepository) protected sessionRepository: ISessionRepository,
|
||||||
@Inject(ISharedLinkRepository) protected sharedLinkRepository: ISharedLinkRepository,
|
@Inject(ISharedLinkRepository) protected sharedLinkRepository: ISharedLinkRepository,
|
||||||
@Inject(IStackRepository) protected stackRepository: IStackRepository,
|
@Inject(IStackRepository) protected stackRepository: IStackRepository,
|
||||||
@Inject(IStorageRepository) protected storageRepository: IStorageRepository,
|
@Inject(IStorageRepository) protected storageRepository: IStorageRepository,
|
||||||
protected systemMetadataRepository: SystemMetadataRepository,
|
@Inject(ISystemMetadataRepository) protected systemMetadataRepository: ISystemMetadataRepository,
|
||||||
@Inject(ITagRepository) protected tagRepository: ITagRepository,
|
@Inject(ITagRepository) protected tagRepository: ITagRepository,
|
||||||
protected telemetryRepository: TelemetryRepository,
|
protected telemetryRepository: TelemetryRepository,
|
||||||
protected trashRepository: TrashRepository,
|
protected trashRepository: TrashRepository,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { CliService } from 'src/services/cli.service';
|
import { CliService } from 'src/services/cli.service';
|
||||||
import { ISystemMetadataRepository } from 'src/types';
|
|
||||||
import { userStub } from 'test/fixtures/user.stub';
|
import { userStub } from 'test/fixtures/user.stub';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked, describe, it } from 'vitest';
|
import { Mocked, describe, it } from 'vitest';
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
|
import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { DuplicateService } from 'src/services/duplicate.service';
|
import { DuplicateService } from 'src/services/duplicate.service';
|
||||||
import { SearchService } from 'src/services/search.service';
|
import { SearchService } from 'src/services/search.service';
|
||||||
import { ILoggingRepository, ISystemMetadataRepository } from 'src/types';
|
import { ILoggingRepository } from 'src/types';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ import { IJobRepository, JobCounts, JobName, JobStatus } from 'src/interfaces/jo
|
|||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { MediaService } from 'src/services/media.service';
|
import { MediaService } from 'src/services/media.service';
|
||||||
import { ILoggingRepository, IMediaRepository, ISystemMetadataRepository, RawImageInfo } from 'src/types';
|
import { ILoggingRepository, IMediaRepository, RawImageInfo } from 'src/types';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { faceStub } from 'test/fixtures/face.stub';
|
import { faceStub } from 'test/fixtures/face.stub';
|
||||||
import { probeStub } from 'test/fixtures/media.stub';
|
import { probeStub } from 'test/fixtures/media.stub';
|
||||||
|
|||||||
@@ -12,17 +12,12 @@ import { IEventRepository } from 'src/interfaces/event.interface';
|
|||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { ImmichTags } from 'src/repositories/metadata.repository';
|
import { ImmichTags } from 'src/repositories/metadata.repository';
|
||||||
import { MetadataService } from 'src/services/metadata.service';
|
import { MetadataService } from 'src/services/metadata.service';
|
||||||
import {
|
import { IConfigRepository, IMapRepository, IMediaRepository, IMetadataRepository } from 'src/types';
|
||||||
IConfigRepository,
|
|
||||||
IMapRepository,
|
|
||||||
IMediaRepository,
|
|
||||||
IMetadataRepository,
|
|
||||||
ISystemMetadataRepository,
|
|
||||||
} from 'src/types';
|
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { fileStub } from 'test/fixtures/file.stub';
|
import { fileStub } from 'test/fixtures/file.stub';
|
||||||
import { probeStub } from 'test/fixtures/media.stub';
|
import { probeStub } from 'test/fixtures/media.stub';
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import { IAlbumRepository } from 'src/interfaces/album.interface';
|
|||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, INotifyAlbumUpdateJob, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, INotifyAlbumUpdateJob, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { EmailTemplate } from 'src/repositories/notification.repository';
|
import { EmailTemplate } from 'src/repositories/notification.repository';
|
||||||
import { NotificationService } from 'src/services/notification.service';
|
import { NotificationService } from 'src/services/notification.service';
|
||||||
import { INotificationRepository, ISystemMetadataRepository } from 'src/types';
|
import { INotificationRepository } from 'src/types';
|
||||||
import { albumStub } from 'test/fixtures/album.stub';
|
import { albumStub } from 'test/fixtures/album.stub';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { userStub } from 'test/fixtures/user.stub';
|
import { userStub } from 'test/fixtures/user.stub';
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import { DetectedFaces, IMachineLearningRepository } from 'src/interfaces/machin
|
|||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { FaceSearchResult, ISearchRepository } from 'src/interfaces/search.interface';
|
import { FaceSearchResult, ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { PersonService } from 'src/services/person.service';
|
import { PersonService } from 'src/services/person.service';
|
||||||
import { IMediaRepository, ISystemMetadataRepository } from 'src/types';
|
import { IMediaRepository } from 'src/types';
|
||||||
import { ImmichFileResponse } from 'src/utils/file';
|
import { ImmichFileResponse } from 'src/utils/file';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
@@ -354,7 +355,7 @@ describe(PersonService.name, () => {
|
|||||||
sut.reassignFaces(authStub.admin, personStub.noName.id, {
|
sut.reassignFaces(authStub.admin, personStub.noName.id, {
|
||||||
data: [{ personId: personStub.withName.id, assetId: assetStub.image.id }],
|
data: [{ personId: personStub.withName.id, assetId: assetStub.image.id }],
|
||||||
}),
|
}),
|
||||||
).resolves.toBeDefined();
|
).resolves.toEqual([personStub.noName]);
|
||||||
|
|
||||||
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
@@ -447,7 +448,7 @@ describe(PersonService.name, () => {
|
|||||||
it('should create a new person', async () => {
|
it('should create a new person', async () => {
|
||||||
personMock.create.mockResolvedValue(personStub.primaryPerson);
|
personMock.create.mockResolvedValue(personStub.primaryPerson);
|
||||||
|
|
||||||
await expect(sut.create(authStub.admin, {})).resolves.toBeDefined();
|
await expect(sut.create(authStub.admin, {})).resolves.toBe(personStub.primaryPerson);
|
||||||
|
|
||||||
expect(personMock.create).toHaveBeenCalledWith({ ownerId: authStub.admin.user.id });
|
expect(personMock.create).toHaveBeenCalledWith({ ownerId: authStub.admin.user.id });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export class PersonService extends BaseService {
|
|||||||
await this.personRepository.reassignFace(face.id, personId);
|
await this.personRepository.reassignFace(face.id, personId);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(mapPerson(person));
|
result.push(person);
|
||||||
}
|
}
|
||||||
if (changeFeaturePhoto.length > 0) {
|
if (changeFeaturePhoto.length > 0) {
|
||||||
// Remove duplicates
|
// Remove duplicates
|
||||||
@@ -178,23 +178,20 @@ export class PersonService extends BaseService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(auth: AuthDto, dto: PersonCreateDto): Promise<PersonResponseDto> {
|
create(auth: AuthDto, dto: PersonCreateDto): Promise<PersonResponseDto> {
|
||||||
const person = await this.personRepository.create({
|
return this.personRepository.create({
|
||||||
ownerId: auth.user.id,
|
ownerId: auth.user.id,
|
||||||
name: dto.name,
|
name: dto.name,
|
||||||
birthDate: dto.birthDate,
|
birthDate: dto.birthDate,
|
||||||
isHidden: dto.isHidden,
|
isHidden: dto.isHidden,
|
||||||
isFavorite: dto.isFavorite,
|
isFavorite: dto.isFavorite,
|
||||||
color: dto.color,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return mapPerson(person);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(auth: AuthDto, id: string, dto: PersonUpdateDto): Promise<PersonResponseDto> {
|
async update(auth: AuthDto, id: string, dto: PersonUpdateDto): Promise<PersonResponseDto> {
|
||||||
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
await this.requireAccess({ auth, permission: Permission.PERSON_UPDATE, ids: [id] });
|
||||||
|
|
||||||
const { name, birthDate, isHidden, featureFaceAssetId: assetId, isFavorite, color } = dto;
|
const { name, birthDate, isHidden, featureFaceAssetId: assetId, isFavorite } = dto;
|
||||||
// TODO: set by faceId directly
|
// TODO: set by faceId directly
|
||||||
let faceId: string | undefined = undefined;
|
let faceId: string | undefined = undefined;
|
||||||
if (assetId) {
|
if (assetId) {
|
||||||
@@ -214,7 +211,6 @@ export class PersonService extends BaseService {
|
|||||||
birthDate,
|
birthDate,
|
||||||
isHidden,
|
isHidden,
|
||||||
isFavorite,
|
isFavorite,
|
||||||
color,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (assetId) {
|
if (assetId) {
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ describe(SearchService.name, () => {
|
|||||||
it('should pass options to search', async () => {
|
it('should pass options to search', async () => {
|
||||||
const { name } = personStub.withName;
|
const { name } = personStub.withName;
|
||||||
|
|
||||||
personMock.getByName.mockResolvedValue([]);
|
|
||||||
|
|
||||||
await sut.searchPerson(authStub.user1, { name, withHidden: false });
|
await sut.searchPerson(authStub.user1, { name, withHidden: false });
|
||||||
|
|
||||||
expect(personMock.getByName).toHaveBeenCalledWith(authStub.user1.user.id, name, { withHidden: false });
|
expect(personMock.getByName).toHaveBeenCalledWith(authStub.user1.user.id, name, { withHidden: false });
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||||
import { AssetMapOptions, AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
import { AssetMapOptions, AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import { mapPerson, PersonResponseDto } from 'src/dtos/person.dto';
|
import { PersonResponseDto } from 'src/dtos/person.dto';
|
||||||
import {
|
import {
|
||||||
mapPlaces,
|
|
||||||
MetadataSearchDto,
|
MetadataSearchDto,
|
||||||
PlacesResponseDto,
|
PlacesResponseDto,
|
||||||
RandomSearchDto,
|
RandomSearchDto,
|
||||||
@@ -13,6 +12,7 @@ import {
|
|||||||
SearchSuggestionRequestDto,
|
SearchSuggestionRequestDto,
|
||||||
SearchSuggestionType,
|
SearchSuggestionType,
|
||||||
SmartSearchDto,
|
SmartSearchDto,
|
||||||
|
mapPlaces,
|
||||||
} from 'src/dtos/search.dto';
|
} from 'src/dtos/search.dto';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { AssetOrder } from 'src/enum';
|
import { AssetOrder } from 'src/enum';
|
||||||
@@ -24,8 +24,7 @@ import { isSmartSearchEnabled } from 'src/utils/misc';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class SearchService extends BaseService {
|
export class SearchService extends BaseService {
|
||||||
async searchPerson(auth: AuthDto, dto: SearchPeopleDto): Promise<PersonResponseDto[]> {
|
async searchPerson(auth: AuthDto, dto: SearchPeopleDto): Promise<PersonResponseDto[]> {
|
||||||
const people = await this.personRepository.getByName(auth.user.id, dto.name, { withHidden: dto.withHidden });
|
return this.personRepository.getByName(auth.user.id, dto.name, { withHidden: dto.withHidden });
|
||||||
return people.map((person) => mapPerson(person));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchPlaces(dto: SearchPlacesDto): Promise<PlacesResponseDto[]> {
|
async searchPlaces(dto: SearchPlacesDto): Promise<PlacesResponseDto[]> {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { SystemMetadataKey } from 'src/enum';
|
import { SystemMetadataKey } from 'src/enum';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { ServerService } from 'src/services/server.service';
|
import { ServerService } from 'src/services/server.service';
|
||||||
import { ISystemMetadataRepository } from 'src/types';
|
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { JobStatus } from 'src/interfaces/job.interface';
|
import { JobStatus } from 'src/interfaces/job.interface';
|
||||||
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { SessionService } from 'src/services/session.service';
|
import { SessionService } from 'src/services/session.service';
|
||||||
import { ISessionRepository } from 'src/types';
|
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { sessionStub } from 'test/fixtures/session.stub';
|
import { sessionStub } from 'test/fixtures/session.stub';
|
||||||
import { IAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
import { IAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
||||||
@@ -37,6 +38,7 @@ describe('SessionService', () => {
|
|||||||
deviceType: '',
|
deviceType: '',
|
||||||
id: '123',
|
id: '123',
|
||||||
token: '420',
|
token: '420',
|
||||||
|
user: {} as UserEntity,
|
||||||
userId: '42',
|
userId: '42',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -48,7 +50,7 @@ describe('SessionService', () => {
|
|||||||
|
|
||||||
describe('getAll', () => {
|
describe('getAll', () => {
|
||||||
it('should get the devices', async () => {
|
it('should get the devices', async () => {
|
||||||
sessionMock.getByUserId.mockResolvedValue([sessionStub.valid as any, sessionStub.inactive]);
|
sessionMock.getByUserId.mockResolvedValue([sessionStub.valid, sessionStub.inactive]);
|
||||||
await expect(sut.getAll(authStub.user1)).resolves.toEqual([
|
await expect(sut.getAll(authStub.user1)).resolves.toEqual([
|
||||||
{
|
{
|
||||||
createdAt: '2021-01-01T00:00:00.000Z',
|
createdAt: '2021-01-01T00:00:00.000Z',
|
||||||
@@ -74,7 +76,7 @@ describe('SessionService', () => {
|
|||||||
|
|
||||||
describe('logoutDevices', () => {
|
describe('logoutDevices', () => {
|
||||||
it('should logout all devices', async () => {
|
it('should logout all devices', async () => {
|
||||||
sessionMock.getByUserId.mockResolvedValue([sessionStub.inactive, sessionStub.valid] as any[]);
|
sessionMock.getByUserId.mockResolvedValue([sessionStub.inactive, sessionStub.valid]);
|
||||||
|
|
||||||
await sut.deleteAll(authStub.user1);
|
await sut.deleteAll(authStub.user1);
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ describe(SharedLinkService.name, () => {
|
|||||||
describe('getAll', () => {
|
describe('getAll', () => {
|
||||||
it('should return all shared links for a user', async () => {
|
it('should return all shared links for a user', async () => {
|
||||||
sharedLinkMock.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]);
|
sharedLinkMock.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]);
|
||||||
await expect(sut.getAll(authStub.user1, {})).resolves.toEqual([
|
await expect(sut.getAll(authStub.user1)).resolves.toEqual([
|
||||||
sharedLinkResponseStub.expired,
|
sharedLinkResponseStub.expired,
|
||||||
sharedLinkResponseStub.valid,
|
sharedLinkResponseStub.valid,
|
||||||
]);
|
]);
|
||||||
expect(sharedLinkMock.getAll).toHaveBeenCalledWith({ userId: authStub.user1.user.id });
|
expect(sharedLinkMock.getAll).toHaveBeenCalledWith(authStub.user1.user.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
SharedLinkEditDto,
|
SharedLinkEditDto,
|
||||||
SharedLinkPasswordDto,
|
SharedLinkPasswordDto,
|
||||||
SharedLinkResponseDto,
|
SharedLinkResponseDto,
|
||||||
SharedLinkSearchDto,
|
|
||||||
} from 'src/dtos/shared-link.dto';
|
} from 'src/dtos/shared-link.dto';
|
||||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||||
import { Permission, SharedLinkType } from 'src/enum';
|
import { Permission, SharedLinkType } from 'src/enum';
|
||||||
@@ -18,10 +17,8 @@ import { getExternalDomain, OpenGraphTags } from 'src/utils/misc';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SharedLinkService extends BaseService {
|
export class SharedLinkService extends BaseService {
|
||||||
async getAll(auth: AuthDto, { albumId }: SharedLinkSearchDto): Promise<SharedLinkResponseDto[]> {
|
async getAll(auth: AuthDto): Promise<SharedLinkResponseDto[]> {
|
||||||
return this.sharedLinkRepository
|
return this.sharedLinkRepository.getAll(auth.user.id).then((links) => links.map((link) => mapSharedLink(link)));
|
||||||
.getAll({ userId: auth.user.id, albumId })
|
|
||||||
.then((links) => links.map((link) => mapSharedLink(link)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMine(auth: AuthDto, dto: SharedLinkPasswordDto): Promise<SharedLinkResponseDto> {
|
async getMine(auth: AuthDto, dto: SharedLinkPasswordDto): Promise<SharedLinkResponseDto> {
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
|||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { SmartInfoService } from 'src/services/smart-info.service';
|
import { SmartInfoService } from 'src/services/smart-info.service';
|
||||||
import { IConfigRepository, ISystemMetadataRepository } from 'src/types';
|
import { IConfigRepository } from 'src/types';
|
||||||
import { getCLIPModelInfo } from 'src/utils/misc';
|
import { getCLIPModelInfo } from 'src/utils/misc';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
|||||||
import { JobStatus } from 'src/interfaces/job.interface';
|
import { JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { StorageTemplateService } from 'src/services/storage-template.service';
|
import { StorageTemplateService } from 'src/services/storage-template.service';
|
||||||
import { ISystemMetadataRepository } from 'src/types';
|
|
||||||
import { albumStub } from 'test/fixtures/album.stub';
|
import { albumStub } from 'test/fixtures/album.stub';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { userStub } from 'test/fixtures/user.stub';
|
import { userStub } from 'test/fixtures/user.stub';
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { SystemMetadataKey } from 'src/enum';
|
import { SystemMetadataKey } from 'src/enum';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { StorageService } from 'src/services/storage.service';
|
import { StorageService } from 'src/services/storage.service';
|
||||||
import { IConfigRepository, ILoggingRepository, ISystemMetadataRepository } from 'src/types';
|
import { IConfigRepository, ILoggingRepository } from 'src/types';
|
||||||
import { ImmichStartupError } from 'src/utils/misc';
|
import { ImmichStartupError } from 'src/utils/misc';
|
||||||
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ import {
|
|||||||
} from 'src/enum';
|
} from 'src/enum';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { QueueName } from 'src/interfaces/job.interface';
|
import { QueueName } from 'src/interfaces/job.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { SystemConfigService } from 'src/services/system-config.service';
|
import { SystemConfigService } from 'src/services/system-config.service';
|
||||||
import { DeepPartial, IConfigRepository, ILoggingRepository, ISystemMetadataRepository } from 'src/types';
|
import { DeepPartial, IConfigRepository, ILoggingRepository } from 'src/types';
|
||||||
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { SystemMetadataKey } from 'src/enum';
|
import { SystemMetadataKey } from 'src/enum';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||||
import { ISystemMetadataRepository } from 'src/types';
|
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { CacheControl, UserMetadataKey } from 'src/enum';
|
|||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IJobRepository, JobName } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName } from 'src/interfaces/job.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { UserService } from 'src/services/user.service';
|
import { UserService } from 'src/services/user.service';
|
||||||
import { ISystemMetadataRepository } from 'src/types';
|
|
||||||
import { ImmichFileResponse } from 'src/utils/file';
|
import { ImmichFileResponse } from 'src/utils/file';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
||||||
|
|||||||
@@ -4,14 +4,9 @@ import { serverVersion } from 'src/constants';
|
|||||||
import { ImmichEnvironment, SystemMetadataKey } from 'src/enum';
|
import { ImmichEnvironment, SystemMetadataKey } from 'src/enum';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { VersionService } from 'src/services/version.service';
|
import { VersionService } from 'src/services/version.service';
|
||||||
import {
|
import { IConfigRepository, ILoggingRepository, IServerInfoRepository, IVersionHistoryRepository } from 'src/types';
|
||||||
IConfigRepository,
|
|
||||||
ILoggingRepository,
|
|
||||||
IServerInfoRepository,
|
|
||||||
ISystemMetadataRepository,
|
|
||||||
IVersionHistoryRepository,
|
|
||||||
} from 'src/types';
|
|
||||||
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import { MemoryRepository } from 'src/repositories/memory.repository';
|
|||||||
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||||
import { NotificationRepository } from 'src/repositories/notification.repository';
|
import { NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
||||||
import { ProcessRepository } from 'src/repositories/process.repository';
|
|
||||||
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
||||||
import { SessionRepository } from 'src/repositories/session.repository';
|
|
||||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
|
||||||
import { MetricGroupRepository, TelemetryRepository } from 'src/repositories/telemetry.repository';
|
import { MetricGroupRepository, TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
import { TrashRepository } from 'src/repositories/trash.repository';
|
import { TrashRepository } from 'src/repositories/trash.repository';
|
||||||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||||
@@ -61,10 +58,7 @@ export type IMetadataRepository = RepositoryInterface<MetadataRepository>;
|
|||||||
export type IMetricGroupRepository = RepositoryInterface<MetricGroupRepository>;
|
export type IMetricGroupRepository = RepositoryInterface<MetricGroupRepository>;
|
||||||
export type INotificationRepository = RepositoryInterface<NotificationRepository>;
|
export type INotificationRepository = RepositoryInterface<NotificationRepository>;
|
||||||
export type IOAuthRepository = RepositoryInterface<OAuthRepository>;
|
export type IOAuthRepository = RepositoryInterface<OAuthRepository>;
|
||||||
export type IProcessRepository = RepositoryInterface<ProcessRepository>;
|
|
||||||
export type ISessionRepository = RepositoryInterface<SessionRepository>;
|
|
||||||
export type IServerInfoRepository = RepositoryInterface<ServerInfoRepository>;
|
export type IServerInfoRepository = RepositoryInterface<ServerInfoRepository>;
|
||||||
export type ISystemMetadataRepository = RepositoryInterface<SystemMetadataRepository>;
|
|
||||||
export type ITelemetryRepository = RepositoryInterface<TelemetryRepository>;
|
export type ITelemetryRepository = RepositoryInterface<TelemetryRepository>;
|
||||||
export type ITrashRepository = RepositoryInterface<TrashRepository>;
|
export type ITrashRepository = RepositoryInterface<TrashRepository>;
|
||||||
export type IViewRepository = RepositoryInterface<ViewRepository>;
|
export type IViewRepository = RepositoryInterface<ViewRepository>;
|
||||||
@@ -83,8 +77,6 @@ export type MemoryItem =
|
|||||||
| Awaited<ReturnType<IMemoryRepository['create']>>
|
| Awaited<ReturnType<IMemoryRepository['create']>>
|
||||||
| Awaited<ReturnType<IMemoryRepository['search']>>[0];
|
| Awaited<ReturnType<IMemoryRepository['search']>>[0];
|
||||||
|
|
||||||
export type SessionItem = Awaited<ReturnType<ISessionRepository['getByUserId']>>[0];
|
|
||||||
|
|
||||||
export interface CropOptions {
|
export interface CropOptions {
|
||||||
top: number;
|
top: number;
|
||||||
left: number;
|
left: number;
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { SystemConfig, defaults } from 'src/config';
|
|||||||
import { SystemConfigDto } from 'src/dtos/system-config.dto';
|
import { SystemConfigDto } from 'src/dtos/system-config.dto';
|
||||||
import { SystemMetadataKey } from 'src/enum';
|
import { SystemMetadataKey } from 'src/enum';
|
||||||
import { DatabaseLock } from 'src/interfaces/database.interface';
|
import { DatabaseLock } from 'src/interfaces/database.interface';
|
||||||
import { DeepPartial, IConfigRepository, ILoggingRepository, ISystemMetadataRepository } from 'src/types';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
|
import { DeepPartial, IConfigRepository, ILoggingRepository } from 'src/types';
|
||||||
import { getKeysDeep, unsetDeep } from 'src/utils/misc';
|
import { getKeysDeep, unsetDeep } from 'src/utils/misc';
|
||||||
|
|
||||||
export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise<void>;
|
export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise<void>;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
IsArray,
|
IsArray,
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
IsDate,
|
IsDate,
|
||||||
IsHexColor,
|
|
||||||
IsNotEmpty,
|
IsNotEmpty,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
IsString,
|
IsString,
|
||||||
@@ -98,15 +97,6 @@ export function Optional({ nullable, emptyToNull, ...validationOptions }: Option
|
|||||||
return applyDecorators(...decorators);
|
return applyDecorators(...decorators);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ValidateHexColor = () => {
|
|
||||||
const decorators = [
|
|
||||||
IsHexColor(),
|
|
||||||
Transform(({ value }) => (typeof value === 'string' && value[0] !== '#' ? `#${value}` : value)),
|
|
||||||
];
|
|
||||||
|
|
||||||
return applyDecorators(...decorators);
|
|
||||||
};
|
|
||||||
|
|
||||||
type UUIDOptions = { optional?: boolean; each?: boolean; nullable?: boolean };
|
type UUIDOptions = { optional?: boolean; each?: boolean; nullable?: boolean };
|
||||||
export const ValidateUUID = (options?: UUIDOptions) => {
|
export const ValidateUUID = (options?: UUIDOptions) => {
|
||||||
const { optional, each, nullable } = { optional: false, each: false, nullable: false, ...options };
|
const { optional, each, nullable } = { optional: false, each: false, nullable: false, ...options };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IProcessRepository } from 'src/types';
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newProcessRepositoryMock = (): Mocked<IProcessRepository> => {
|
export const newProcessRepositoryMock = (): Mocked<IProcessRepository> => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ISessionRepository } from 'src/types';
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newSessionRepositoryMock = (): Mocked<ISessionRepository> => {
|
export const newSessionRepositoryMock = (): Mocked<ISessionRepository> => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ISystemMetadataRepository } from 'src/types';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { clearConfigCache } from 'src/utils/config';
|
import { clearConfigCache } from 'src/utils/config';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ import { MemoryRepository } from 'src/repositories/memory.repository';
|
|||||||
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||||
import { NotificationRepository } from 'src/repositories/notification.repository';
|
import { NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
||||||
import { ProcessRepository } from 'src/repositories/process.repository';
|
|
||||||
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
||||||
import { SessionRepository } from 'src/repositories/session.repository';
|
|
||||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
|
||||||
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
|
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
import { TrashRepository } from 'src/repositories/trash.repository';
|
import { TrashRepository } from 'src/repositories/trash.repository';
|
||||||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||||
@@ -38,10 +35,7 @@ import {
|
|||||||
IMetadataRepository,
|
IMetadataRepository,
|
||||||
INotificationRepository,
|
INotificationRepository,
|
||||||
IOAuthRepository,
|
IOAuthRepository,
|
||||||
IProcessRepository,
|
|
||||||
IServerInfoRepository,
|
IServerInfoRepository,
|
||||||
ISessionRepository,
|
|
||||||
ISystemMetadataRepository,
|
|
||||||
ITrashRepository,
|
ITrashRepository,
|
||||||
IVersionHistoryRepository,
|
IVersionHistoryRepository,
|
||||||
IViewRepository,
|
IViewRepository,
|
||||||
@@ -169,14 +163,14 @@ export const newTestService = <T extends BaseService>(
|
|||||||
oauthMock as IOAuthRepository as OAuthRepository,
|
oauthMock as IOAuthRepository as OAuthRepository,
|
||||||
partnerMock,
|
partnerMock,
|
||||||
personMock,
|
personMock,
|
||||||
processMock as IProcessRepository as ProcessRepository,
|
processMock,
|
||||||
searchMock,
|
searchMock,
|
||||||
serverInfoMock as IServerInfoRepository as ServerInfoRepository,
|
serverInfoMock as IServerInfoRepository as ServerInfoRepository,
|
||||||
sessionMock as ISessionRepository as SessionRepository,
|
sessionMock,
|
||||||
sharedLinkMock,
|
sharedLinkMock,
|
||||||
stackMock,
|
stackMock,
|
||||||
storageMock,
|
storageMock,
|
||||||
systemMock as ISystemMetadataRepository as SystemMetadataRepository,
|
systemMock,
|
||||||
tagMock,
|
tagMock,
|
||||||
telemetryMock as unknown as TelemetryRepository,
|
telemetryMock as unknown as TelemetryRepository,
|
||||||
trashMock as ITrashRepository as TrashRepository,
|
trashMock as ITrashRepository as TrashRepository,
|
||||||
|
|||||||
Generated
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-web",
|
"name": "immich-web",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich-web",
|
"name": "immich-web",
|
||||||
"version": "1.126.0",
|
"version": "1.125.7",
|
||||||
"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.126.0",
|
"version": "1.125.7",
|
||||||
"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.126.0",
|
"version": "1.125.7",
|
||||||
"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",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user