feat: magic link to enable backups

This commit is contained in:
izzy 2026-06-19 13:06:57 +01:00
parent 5ded6f89b7
commit d18e09de30
No known key found for this signature in database
17 changed files with 225 additions and 35 deletions

View file

@ -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",

View file

@ -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,

View file

@ -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'),

View file

@ -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({

View file

@ -137,6 +137,7 @@ describe(ServerService.name, () => {
duplicateDetection: true,
facialRecognition: true,
importFaces: false,
backups: false,
map: true,
reverseGeocoding: true,
oauth: false,

View file

@ -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,

View file

@ -46,6 +46,7 @@ const updatedConfig = Object.freeze<SystemConfig>({
[QueueName.Editor]: { concurrency: 2 },
},
backup: {
beta: false,
database: {
enabled: true,
cronExpression: '0 02 * * *',