zerobyte/app/server/modules/backends/backend.ts
Jakub Trávník 92ba5f9706 feat: add deep secret resolution for all config fields
- Add resolveSecretsDeep() to recursively resolve secret placeholders
  (env://, file://, encv1:) in any config field
- Refactor restic operations to resolve secrets once via resolveAndBuild()
- Refactor volume backend dispatcher to resolve secrets at mount time
- Remove redundant per-field resolveSecret() calls from SMB, WebDAV, SFTP backends
- Simplify notifications service by replacing switch-based decryption
- Update backend-compatibility to use deep resolution for credential comparison

This allows users to use secret references in any configuration field,
not just the designated sensitive fields.
2026-01-05 17:35:56 +01:00

52 lines
1.6 KiB
TypeScript

import type { BackendConfig, BackendStatus } from "~/schemas/volumes";
import type { Volume } from "../../db/schema";
import { cryptoUtils } from "../../utils/crypto";
import { getVolumePath } from "../volumes/helpers";
import { makeDirectoryBackend } from "./directory/directory-backend";
import { makeNfsBackend } from "./nfs/nfs-backend";
import { makeRcloneBackend } from "./rclone/rclone-backend";
import { makeSmbBackend } from "./smb/smb-backend";
import { makeWebdavBackend } from "./webdav/webdav-backend";
import { makeSftpBackend } from "./sftp/sftp-backend";
type OperationResult = {
error?: string;
status: BackendStatus;
};
export type VolumeBackend = {
mount: () => Promise<OperationResult>;
unmount: () => Promise<OperationResult>;
checkHealth: () => Promise<OperationResult>;
};
const getBackendFactory = (backendType: BackendConfig["backend"]) => {
switch (backendType) {
case "nfs":
return makeNfsBackend;
case "smb":
return makeSmbBackend;
case "directory":
return makeDirectoryBackend;
case "webdav":
return makeWebdavBackend;
case "rclone":
return makeRcloneBackend;
case "sftp":
return makeSftpBackend;
}
};
export const createVolumeBackend = (volume: Volume): VolumeBackend => {
const path = getVolumePath(volume);
const makeBackend = getBackendFactory(volume.config.backend);
return {
mount: async () => {
const resolvedConfig = await cryptoUtils.resolveSecretsDeep(volume.config);
return makeBackend(resolvedConfig, path).mount();
},
unmount: () => makeBackend(volume.config, path).unmount(),
checkHealth: () => makeBackend(volume.config, path).checkHealth(),
};
};