mirror of
https://github.com/immich-app/immich.git
synced 2026-06-22 14:52:17 -07:00
feat: magic link to enable backups
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.0",
|
||||
"@faker-js/faker": "^10.1.0",
|
||||
"@futo-org/backups-orchestrator-ui": "0.3.1",
|
||||
"@futo-org/backups-orchestrator-ui": "0.4.0",
|
||||
"@immich/cli": "workspace:*",
|
||||
"@immich/e2e-auth-server": "workspace:*",
|
||||
"@immich/sdk": "workspace:*",
|
||||
|
||||
@@ -109,6 +109,7 @@ describe('/server', () => {
|
||||
configFile: false,
|
||||
duplicateDetection: false,
|
||||
facialRecognition: false,
|
||||
backups: false,
|
||||
map: true,
|
||||
reverseGeocoding: true,
|
||||
importFaces: false,
|
||||
|
||||
@@ -118,6 +118,7 @@ export const setupBaseMockApiRoutes = async (context: BrowserContext, adminUserI
|
||||
smartSearch: false,
|
||||
facialRecognition: false,
|
||||
duplicateDetection: false,
|
||||
backups: false,
|
||||
map: true,
|
||||
reverseGeocoding: true,
|
||||
importFaces: false,
|
||||
|
||||
@@ -16484,6 +16484,20 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/onboarding/report-error": {
|
||||
"post": {
|
||||
"operationId": "reportError",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Onboarding"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/onboarding/skip": {
|
||||
"post": {
|
||||
"operationId": "skipOnboardingExtraConfig",
|
||||
@@ -16498,6 +16512,20 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/onboarding/telemetry": {
|
||||
"post": {
|
||||
"operationId": "enableTelemetry",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Onboarding"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/repository": {
|
||||
"get": {
|
||||
"operationId": "getRepositories",
|
||||
@@ -16560,7 +16588,16 @@
|
||||
"/yucca/repository/inspect": {
|
||||
"get": {
|
||||
"operationId": "inspectRepositories",
|
||||
"parameters": [],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "backend",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
@@ -16675,6 +16712,46 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/repository/{id}/backend": {
|
||||
"put": {
|
||||
"operationId": "reconfigureRepositoryPrimaryBackend",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RepositoryPrimaryBackendReconfigureRequestDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RepositoryCreateResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Repository"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/repository/{id}/import": {
|
||||
"get": {
|
||||
"operationId": "checkImportRepository",
|
||||
@@ -19170,6 +19247,9 @@
|
||||
},
|
||||
"BackendDto": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -19188,6 +19268,7 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"isOnline",
|
||||
"type"
|
||||
@@ -19227,6 +19308,14 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"BootstrapStatus": {
|
||||
"enum": [
|
||||
"not-ready",
|
||||
"ready",
|
||||
"error"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"BulkIdErrorReason": {
|
||||
"description": "Error reason",
|
||||
"enum": [
|
||||
@@ -20444,6 +20533,9 @@
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"meter": {
|
||||
"$ref": "#/components/schemas/RepositoryMeterDto"
|
||||
},
|
||||
"metrics": {
|
||||
"$ref": "#/components/schemas/RepositoryMetricsDto"
|
||||
},
|
||||
@@ -20803,6 +20895,9 @@
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"meter": {
|
||||
"$ref": "#/components/schemas/RepositoryMeterDto"
|
||||
},
|
||||
"metrics": {
|
||||
"$ref": "#/components/schemas/RepositoryMetricsDto"
|
||||
},
|
||||
@@ -22018,6 +22113,9 @@
|
||||
},
|
||||
"OnboardingStatusResponseDto": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"hasBackend": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -22032,6 +22130,20 @@
|
||||
},
|
||||
"hasSkippedExtraConfig": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"hasTelemetry": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/TelemetryLevel"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/BootstrapStatus"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -22039,7 +22151,9 @@
|
||||
"hasBackup",
|
||||
"hasOnboardedKey",
|
||||
"hasSchedule",
|
||||
"hasSkippedExtraConfig"
|
||||
"hasSkippedExtraConfig",
|
||||
"hasTelemetry",
|
||||
"status"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
@@ -23610,6 +23724,24 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RepositoryMeterDto": {
|
||||
"properties": {
|
||||
"lastUpdated": {
|
||||
"type": "string"
|
||||
},
|
||||
"objectCount": {
|
||||
"type": "number"
|
||||
},
|
||||
"sizeBytes": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"objectCount",
|
||||
"sizeBytes"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RepositoryMetricsDto": {
|
||||
"properties": {
|
||||
"lastBackup": {
|
||||
@@ -23630,6 +23762,17 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RepositoryPrimaryBackendReconfigureRequestDto": {
|
||||
"properties": {
|
||||
"backendId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"backendId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RepositorySnapshotRestoreFromPointRequestDto": {
|
||||
"properties": {
|
||||
"include": {
|
||||
@@ -24383,6 +24526,10 @@
|
||||
},
|
||||
"ServerFeaturesDto": {
|
||||
"properties": {
|
||||
"backups": {
|
||||
"description": "Whether the backups feature is enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"configFile": {
|
||||
"description": "Whether config file is available",
|
||||
"type": "boolean"
|
||||
@@ -24449,6 +24596,7 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"backups",
|
||||
"configFile",
|
||||
"duplicateDetection",
|
||||
"email",
|
||||
@@ -27467,11 +27615,16 @@
|
||||
},
|
||||
"SystemConfigBackupsDto": {
|
||||
"properties": {
|
||||
"beta": {
|
||||
"description": "Whether the backups feature is enabled",
|
||||
"type": "boolean"
|
||||
},
|
||||
"database": {
|
||||
"$ref": "#/components/schemas/DatabaseBackupConfig"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"beta",
|
||||
"database"
|
||||
],
|
||||
"type": "object"
|
||||
@@ -28728,6 +28881,13 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TelemetryLevel": {
|
||||
"enum": [
|
||||
"full",
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TemplateDto": {
|
||||
"properties": {
|
||||
"template": {
|
||||
|
||||
@@ -2009,6 +2009,8 @@ export type ServerConfigDto = {
|
||||
userDeleteDelay: number;
|
||||
};
|
||||
export type ServerFeaturesDto = {
|
||||
/** Whether the backups feature is enabled */
|
||||
backups: boolean;
|
||||
/** Whether config file is available */
|
||||
configFile: boolean;
|
||||
/** Whether duplicate detection is enabled */
|
||||
@@ -2287,6 +2289,8 @@ export type DatabaseBackupConfig = {
|
||||
keepLastAmount: number;
|
||||
};
|
||||
export type SystemConfigBackupsDto = {
|
||||
/** Whether the backups feature is in beta */
|
||||
beta: boolean;
|
||||
database: DatabaseBackupConfig;
|
||||
};
|
||||
export type SystemConfigFFmpegRealtimeDto = {
|
||||
|
||||
Generated
+23
-23
@@ -118,8 +118,8 @@ importers:
|
||||
specifier: ^10.1.0
|
||||
version: 10.4.0
|
||||
'@futo-org/backups-orchestrator-ui':
|
||||
specifier: 0.3.1
|
||||
version: 0.3.1(svelte@5.56.2(@typescript-eslint/types@8.61.0))
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(svelte@5.56.2(@typescript-eslint/types@8.61.0))
|
||||
'@immich/cli':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/cli
|
||||
@@ -378,8 +378,8 @@ importers:
|
||||
specifier: 2.0.0-rc13
|
||||
version: 2.0.0-rc13
|
||||
'@futo-org/backups-orchestrator-api':
|
||||
specifier: 0.3.1
|
||||
version: 0.3.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)
|
||||
'@immich/plugin-sdk':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/plugin-sdk
|
||||
@@ -769,8 +769,8 @@ importers:
|
||||
specifier: ^3.0.0
|
||||
version: 3.5.11
|
||||
'@futo-org/backups-orchestrator-ui':
|
||||
specifier: 0.3.1
|
||||
version: 0.3.1(@sveltejs/kit@2.65.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.2(@typescript-eslint/types@8.61.0))(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(@sveltejs/kit@2.65.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.2(@typescript-eslint/types@8.61.0))(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))
|
||||
'@immich/justified-layout-wasm':
|
||||
specifier: ^0.4.3
|
||||
version: 0.4.3
|
||||
@@ -3030,11 +3030,11 @@ packages:
|
||||
resolution: {integrity: sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
'@futo-org/backups-api-client@0.3.1':
|
||||
resolution: {integrity: sha512-CO2kDerCTRk3fSEwYFR3HWU3A6SGzuu8IM4RI8OgGp/7TI4fGCi4wb5c3KjbZKtSHvUmN4Wy1WPD1GNWv30OIA==}
|
||||
'@futo-org/backups-api-client@0.4.0':
|
||||
resolution: {integrity: sha512-OaVhTSsesMOxzk1/I+pVh5Nbm/QzfjY1RDU6HZgNw5PWvaizq2Wv3o9UHzBn2vyH5+8LMs2xKreC+jGwEs6NJQ==}
|
||||
|
||||
'@futo-org/backups-orchestrator-api@0.3.1':
|
||||
resolution: {integrity: sha512-7AGByA1OshaaXHg50MxxnLtlJn8BZnOdpR43clG2DqJxMRps84KMAQlolT+lyL3l6RgT+0KU6Xc8FWd9Qlxr4A==}
|
||||
'@futo-org/backups-orchestrator-api@0.4.0':
|
||||
resolution: {integrity: sha512-IC4R0bxEA3YmJGfm3oj5KOb6XzfC8iEd5VPQ+SWlFrOdyrF/WHa0sTxTYa9ddMn1BtKkl4cUnig21hmj3ub/KQ==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^11.0.0
|
||||
'@nestjs/core': ^11.0.0
|
||||
@@ -3042,13 +3042,13 @@ packages:
|
||||
'@nestjs/schedule': ^6.0.0
|
||||
'@nestjs/websockets': ^11.0.0
|
||||
|
||||
'@futo-org/backups-orchestrator-ui@0.3.1':
|
||||
resolution: {integrity: sha512-5IO4EF6w5q7gkBQarDUYRqKWXuEVOxjzcPtVBUzg52PAVB+iEtPYKiTpBqEOWDcM1ooAMQcbqtkzD/D2LSVVgw==}
|
||||
'@futo-org/backups-orchestrator-ui@0.4.0':
|
||||
resolution: {integrity: sha512-OimxOvUWwmUpf8xGZRHoK1yWb35oPJHv0gD4u28fnL34nrqdoY8ZeUThqmnn6pT9hqJ3xsoa/qopMONWxkdA7g==}
|
||||
peerDependencies:
|
||||
svelte: ^5.0.0
|
||||
|
||||
'@futo-org/restic-wrapper@1.2.1':
|
||||
resolution: {integrity: sha512-shMx5f0/RTTYTvJ9Zryq7InWcmHm01kpIXy6wli/RIOx1Jjcx2j/Ab32WWhpYRTMxGhrKlOEmmen0qinMHFSNg==}
|
||||
'@futo-org/restic-wrapper@1.3.0':
|
||||
resolution: {integrity: sha512-RIKM2lhQIHpCdF3vTjf86UwGPfCkAvJ9vUquhn93WZaBeHwfVPuAQdiz6SuS4RDvAmyYgEkedREhfHvpEi4/dQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@golevelup/nestjs-discovery@5.0.0':
|
||||
@@ -15958,14 +15958,14 @@ snapshots:
|
||||
dependencies:
|
||||
'@fortawesome/fontawesome-common-types': 7.2.0
|
||||
|
||||
'@futo-org/backups-api-client@0.3.1':
|
||||
'@futo-org/backups-api-client@0.4.0':
|
||||
dependencies:
|
||||
'@oazapfts/runtime': 1.2.0
|
||||
|
||||
'@futo-org/backups-orchestrator-api@0.3.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)':
|
||||
'@futo-org/backups-orchestrator-api@0.4.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)(@nestjs/platform-socket.io@11.1.27)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27))(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)':
|
||||
dependencies:
|
||||
'@futo-org/backups-api-client': 0.3.1
|
||||
'@futo-org/restic-wrapper': 1.2.1
|
||||
'@futo-org/backups-api-client': 0.4.0
|
||||
'@futo-org/restic-wrapper': 1.3.0
|
||||
'@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
'@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.27)(@nestjs/websockets@11.1.27)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
'@nestjs/event-emitter': 3.1.0(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)
|
||||
@@ -15991,9 +15991,9 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@futo-org/backups-orchestrator-ui@0.3.1(@sveltejs/kit@2.65.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.2(@typescript-eslint/types@8.61.0))(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))':
|
||||
'@futo-org/backups-orchestrator-ui@0.4.0(@sveltejs/kit@2.65.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.2(@typescript-eslint/types@8.61.0))(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))':
|
||||
dependencies:
|
||||
'@futo-org/backups-api-client': 0.3.1
|
||||
'@futo-org/backups-api-client': 0.4.0
|
||||
'@immich/ui': 0.59.0(@sveltejs/kit@2.65.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.2(@typescript-eslint/types@8.61.0))(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.13.2)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.9.0)))(svelte@5.56.2(@typescript-eslint/types@8.61.0))
|
||||
'@mdi/js': 7.4.47
|
||||
'@oazapfts/runtime': 1.2.0
|
||||
@@ -16010,9 +16010,9 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@futo-org/backups-orchestrator-ui@0.3.1(svelte@5.56.2(@typescript-eslint/types@8.61.0))':
|
||||
'@futo-org/backups-orchestrator-ui@0.4.0(svelte@5.56.2(@typescript-eslint/types@8.61.0))':
|
||||
dependencies:
|
||||
'@futo-org/backups-api-client': 0.3.1
|
||||
'@futo-org/backups-api-client': 0.4.0
|
||||
'@immich/ui': 0.59.0(svelte@5.56.2(@typescript-eslint/types@8.61.0))
|
||||
'@mdi/js': 7.4.47
|
||||
'@oazapfts/runtime': 1.2.0
|
||||
@@ -16029,7 +16029,7 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@futo-org/restic-wrapper@1.2.1':
|
||||
'@futo-org/restic-wrapper@1.3.0':
|
||||
dependencies:
|
||||
zod: 4.3.6
|
||||
|
||||
|
||||
+4
-3
@@ -31,10 +31,11 @@ allowBuilds:
|
||||
dedupePeerDependents: false
|
||||
injectWorkspacePackages: true
|
||||
minimumReleaseAgeExclude:
|
||||
- '@futo-org/backups-api-client@0.3.1'
|
||||
- '@futo-org/backups-orchestrator-ui@0.3.1'
|
||||
- '@futo-org/backups-orchestrator-api@0.3.1'
|
||||
- '@immich/ui@0.81.1'
|
||||
- '@futo-org/backups-api-client@0.4.0'
|
||||
- '@futo-org/backups-orchestrator-ui@0.4.0'
|
||||
- '@futo-org/backups-orchestrator-api@0.4.0'
|
||||
- '@futo-org/restic-wrapper@1.3.0'
|
||||
overrides:
|
||||
canvas: 3.2.3
|
||||
sharp: ^0.34.5
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@extism/extism": "2.0.0-rc13",
|
||||
"@futo-org/backups-orchestrator-api": "0.3.1",
|
||||
"@futo-org/backups-orchestrator-api": "0.4.0",
|
||||
"@immich/plugin-sdk": "workspace:*",
|
||||
"@immich/sql-tools": "^0.5.1",
|
||||
"@nestjs/bullmq": "^11.0.1",
|
||||
|
||||
@@ -18,6 +18,7 @@ import { ConcurrentQueueName, FullsizeImageOptions, ImageOptions } from 'src/typ
|
||||
|
||||
export type SystemConfig = {
|
||||
backup: {
|
||||
beta: boolean;
|
||||
database: {
|
||||
enabled: boolean;
|
||||
cronExpression: string;
|
||||
@@ -217,6 +218,7 @@ export type MachineLearningConfig = SystemConfig['machineLearning'];
|
||||
|
||||
export const defaults = Object.freeze<SystemConfig>({
|
||||
backup: {
|
||||
beta: false,
|
||||
database: {
|
||||
enabled: true,
|
||||
cronExpression: CronExpression.EVERY_DAY_AT_2AM,
|
||||
|
||||
@@ -135,6 +135,7 @@ const ServerFeaturesSchema = z
|
||||
configFile: z.boolean().describe('Whether config file is available'),
|
||||
facialRecognition: z.boolean().describe('Whether facial recognition is enabled'),
|
||||
map: z.boolean().describe('Whether map feature is enabled'),
|
||||
backups: z.boolean().describe('Whether the backups feature is enabled'),
|
||||
trash: z.boolean().describe('Whether trash feature is enabled'),
|
||||
reverseGeocoding: z.boolean().describe('Whether reverse geocoding is enabled'),
|
||||
importFaces: z.boolean().describe('Whether face import is enabled'),
|
||||
|
||||
@@ -88,7 +88,9 @@ const SystemConfigIntegrityChecksSchema = z
|
||||
.describe('Integrity checks config')
|
||||
.meta({ id: 'SystemConfigIntegrityChecks' });
|
||||
|
||||
const SystemConfigBackupsSchema = z.object({ database: DatabaseBackupSchema }).meta({ id: 'SystemConfigBackupsDto' });
|
||||
const SystemConfigBackupsSchema = z
|
||||
.object({ beta: configBool.describe('Whether the backups feature is enabled'), database: DatabaseBackupSchema })
|
||||
.meta({ id: 'SystemConfigBackupsDto' });
|
||||
|
||||
const SystemConfigFFmpegSchema = z
|
||||
.object({
|
||||
|
||||
@@ -137,6 +137,7 @@ describe(ServerService.name, () => {
|
||||
duplicateDetection: true,
|
||||
facialRecognition: true,
|
||||
importFaces: false,
|
||||
backups: false,
|
||||
map: true,
|
||||
reverseGeocoding: true,
|
||||
oauth: false,
|
||||
|
||||
@@ -86,7 +86,7 @@ export class ServerService extends BaseService {
|
||||
}
|
||||
|
||||
async getFeatures(): Promise<ServerFeaturesDto> {
|
||||
const { reverseGeocoding, metadata, map, machineLearning, trash, oauth, passwordLogin, notifications, ffmpeg } =
|
||||
const { reverseGeocoding, metadata, map, backup, machineLearning, trash, oauth, passwordLogin, notifications, ffmpeg } =
|
||||
await this.getConfig({ withCache: false });
|
||||
const { configFile } = this.configRepository.getEnv();
|
||||
|
||||
@@ -95,6 +95,7 @@ export class ServerService extends BaseService {
|
||||
facialRecognition: isFacialRecognitionEnabled(machineLearning),
|
||||
duplicateDetection: isDuplicateDetectionEnabled(machineLearning),
|
||||
map: map.enabled,
|
||||
backups: backup.beta,
|
||||
reverseGeocoding: reverseGeocoding.enabled,
|
||||
importFaces: metadata.faces.import,
|
||||
sidecar: true,
|
||||
|
||||
@@ -46,6 +46,7 @@ const updatedConfig = Object.freeze<SystemConfig>({
|
||||
[QueueName.Editor]: { concurrency: 2 },
|
||||
},
|
||||
backup: {
|
||||
beta: false,
|
||||
database: {
|
||||
enabled: true,
|
||||
cronExpression: '0 02 * * *',
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^3.0.0",
|
||||
"@futo-org/backups-orchestrator-ui": "0.3.1",
|
||||
"@futo-org/backups-orchestrator-ui": "0.4.0",
|
||||
"@immich/justified-layout-wasm": "^0.4.3",
|
||||
"@immich/sdk": "workspace:*",
|
||||
"@immich/ui": "^0.81.1",
|
||||
|
||||
@@ -88,7 +88,9 @@
|
||||
<NavbarItem title={$t('folders')} href={Route.folders()} icon={{ icon: mdiFolderOutline, flipped: true }} />
|
||||
{/if}
|
||||
|
||||
<NavbarItem title="Backups" href={Route.backups()} icon={mdiBackupRestore} />
|
||||
{#if featureFlagsManager.value.backups && authManager.user.isAdmin}
|
||||
<NavbarItem title="Backups" href={Route.backups()} icon={mdiBackupRestore} />
|
||||
{/if}
|
||||
|
||||
<NavbarItem title={$t('utilities')} href={Route.utilities()} icon={mdiToolboxOutline} activeIcon={mdiToolbox} />
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { getConfig, updateConfig } from '@immich/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { OpenQueryParam } from '$lib/constants';
|
||||
import { Route } from '$lib/route';
|
||||
@@ -8,9 +9,10 @@ enum LinkTarget {
|
||||
UNSUBSCRIBE = 'unsubscribe',
|
||||
VIEW_ASSET = 'view_asset',
|
||||
ACTIVATE_LICENSE = 'activate_license',
|
||||
BACKUPS = 'backups',
|
||||
}
|
||||
|
||||
export const load = (({ url }) => {
|
||||
export const load = (async ({ url }) => {
|
||||
const queryParams = url.searchParams;
|
||||
const target = queryParams.get('target') as LinkTarget;
|
||||
switch (target) {
|
||||
@@ -22,6 +24,17 @@ export const load = (({ url }) => {
|
||||
return redirect(307, Route.userSettings({ isOpen: OpenQueryParam.NOTIFICATIONS }));
|
||||
}
|
||||
|
||||
case LinkTarget.BACKUPS: {
|
||||
const config = await getConfig().catch(() => undefined);
|
||||
if (config && !config.backup.beta) {
|
||||
await updateConfig({
|
||||
systemConfigDto: { ...config, backup: { ...config.backup, beta: true } },
|
||||
}).catch(() => undefined);
|
||||
}
|
||||
|
||||
return redirect(307, Route.backups());
|
||||
}
|
||||
|
||||
case LinkTarget.VIEW_ASSET: {
|
||||
const id = queryParams.get('id');
|
||||
if (id) {
|
||||
|
||||
Reference in New Issue
Block a user