fix(backups): сохранять расписание и хранилище независимо

This commit is contained in:
Denozordec committed 2026-10-01 15:25:48 +07:00
1 parent 5ce21e9a47
commit 8e01666e0e
12 files changed
+286 -104

No files matched your search

+9
View File
@@ -81,3 +81,12 @@ test("restore, S3 test and sync do not accept empty or malformed success", async
globalThis.fetch = async () => json({ imported: -1, skipped: 0 }); await assert.rejects(() => syncBackupsFromStorage(base))
} finally { globalThis.fetch = original }
})
test("settings acknowledgment must match submitted fields and confirm a new secret", async () => {
const original = globalThis.fetch
try {
globalThis.fetch = async () => json(schedule); await assert.rejects(() => putBackupScheduleSettings(base, { hour: 7 }), /не подтверждено/)
globalThis.fetch = async () => json(storage); await assert.rejects(() => putBackupStorageSettings(base, { provider: "s3" }), /не подтверждено/)
await assert.rejects(() => putBackupStorageSettings(base, { s3SecretAccessKey: "new-test-secret" }), /ключа/)
} finally { globalThis.fetch = original }
})
+14 -2
View File
@@ -46,16 +46,28 @@ export async function restoreBackup(baseUrl: string, id: string, options?: Reque
export async function getBackupScheduleSettings(baseUrl: string, options?: RequestInit) {
return backupScheduleSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/schedule", { ...options, method: "GET" }))
}
function confirmSettings(result: Record<string, unknown>, payload: Record<string, unknown>) {
for (const [key, value] of Object.entries(payload)) {
if (value === undefined) continue
if (key === "s3SecretAccessKey") {
if (value && result.secretConfigured !== true) throw new Error("Сохранение ключа хранилища не подтверждено")
} else if (JSON.stringify(result[key]) !== JSON.stringify(value)) throw new Error("Сохранение настроек не подтверждено: ответ отличается от отправленных данных")
}
}
export async function putBackupScheduleSettings(baseUrl: string, payload: Partial<BackupScheduleSettingsDto>, options?: RequestInit) {
const body = putBackupScheduleSettingsSchema.parse(payload)
return backupScheduleSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/schedule", { ...options, method: "PUT", body: JSON.stringify(body) }))
const result = backupScheduleSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/schedule", { ...options, method: "PUT", body: JSON.stringify(body) }))
confirmSettings(result, body)
return result
}
export async function getBackupStorageSettings(baseUrl: string, options?: RequestInit) {
return backupStorageSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/storage", { ...options, method: "GET" }))
}
export async function putBackupStorageSettings(baseUrl: string, payload: PutBackupStorageSettings, options?: RequestInit) {
const body = putBackupStorageSettingsSchema.parse(payload)
return backupStorageSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/storage", { ...options, method: "PUT", body: JSON.stringify(body) }))
const result = backupStorageSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/storage", { ...options, method: "PUT", body: JSON.stringify(body) }))
confirmSettings(result, body)
return result
}
export async function testBackupStorage(baseUrl: string, options?: RequestInit) {
return backupStorageSettingsDtoSchema.parse(await backupJson(baseUrl, "/api/backups/storage/test", { ...options, method: "POST" }))