mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
backups: upload and restore backup in-app
This commit is contained in:
parent
eff313be41
commit
ade032241a
26
api.go
26
api.go
@ -611,8 +611,7 @@ func (app *appContext) GetBackups(gc *gin.Context) {
|
||||
|
||||
// @Summary Restore a backup file stored locally to the server.
|
||||
// @Param fname path string true "backup filename"
|
||||
// @Router /backups/restore/{fname} [get]
|
||||
// @Produce octet-stream
|
||||
// @Router /backups/restore/{fname} [post]
|
||||
// @Produce json
|
||||
// @Failure 400 {object} boolResponse
|
||||
// @Security Bearer
|
||||
@ -632,3 +631,26 @@ func (app *appContext) RestoreLocalBackup(gc *gin.Context) {
|
||||
LOADBAK = fullpath
|
||||
app.restart(gc)
|
||||
}
|
||||
|
||||
// @Summary Restore a backup file uploaded by the user.
|
||||
// @Param file formData file true ".bak file"
|
||||
// @Router /backups/restore [post]
|
||||
// @Produce json
|
||||
// @Failure 400 {object} boolResponse
|
||||
// @Security Bearer
|
||||
// @tags Other
|
||||
func (app *appContext) RestoreBackup(gc *gin.Context) {
|
||||
file, err := gc.FormFile("backups-file")
|
||||
if err != nil {
|
||||
app.err.Printf("Failed to get file from form data: %v\n", err)
|
||||
respondBool(400, false, gc)
|
||||
return
|
||||
}
|
||||
app.debug.Printf("Got uploaded file \"%s\"\n", file.Filename)
|
||||
path := app.config.Section("backups").Key("path").String()
|
||||
fullpath := filepath.Join(path, "jfa-go-upload-bak-"+time.Now().Local().Format(BACKUP_DATEFMT)+BACKUP_SUFFIX)
|
||||
gc.SaveUploadedFile(file, fullpath)
|
||||
app.debug.Printf("Saved to \"%s\"\n", fullpath)
|
||||
LOADBAK = fullpath
|
||||
app.restart(gc)
|
||||
}
|
||||
|
@ -336,6 +336,7 @@
|
||||
<div class="row col flex">
|
||||
<button class="button ~info @low mr-2 mt-4 mb-4" id="settings-backups-backup">{{ .strings.backupNow }}</button>
|
||||
<button class="button ~neutral @low mr-2 mt-4 mb-4" id="settings-backups-upload">{{ .strings.backupUpload }}</button>
|
||||
<input id="backups-file" name="backups-file" type="file" hidden>
|
||||
<button class="button ~neutral @low mr-2 mt-4 mb-4" id="settings-backups-sort-direction">{{ .strings.sortDirection }}</button>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
|
@ -212,6 +212,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
||||
api.GET(p+"/backups/:fname", app.GetBackup)
|
||||
api.GET(p+"/backups", app.GetBackups)
|
||||
api.POST(p+"/backups/restore/:fname", app.RestoreLocalBackup)
|
||||
api.POST(p+"/backups/restore", app.RestoreBackup)
|
||||
if telegramEnabled || discordEnabled || matrixEnabled {
|
||||
api.GET(p+"/telegram/pin", app.TelegramGetPin)
|
||||
api.GET(p+"/telegram/verified/:pin", app.TelegramVerified)
|
||||
|
@ -56,6 +56,15 @@ export const _download = (url: string, fname: string): void => {
|
||||
req.send();
|
||||
};
|
||||
|
||||
export const _upload = (url: string, formData: FormData): void => {
|
||||
let req = new XMLHttpRequest();
|
||||
if (window.URLBase) { url = window.URLBase + url; }
|
||||
req.open("POST", url, true);
|
||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||
// req.setRequestHeader('Content-Type', 'multipart/form-data');
|
||||
req.send(formData);
|
||||
};
|
||||
|
||||
export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, response?: boolean, statusHandler?: (req: XMLHttpRequest) => void): void => {
|
||||
let req = new XMLHttpRequest();
|
||||
req.open("POST", window.URLBase + url, true);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { _get, _post, _delete, _download, toggleLoader, addLoader, removeLoader, insertText, toClipboard, toDateString } from "../modules/common.js";
|
||||
import { _get, _post, _delete, _download, _upload, toggleLoader, addLoader, removeLoader, insertText, toClipboard, toDateString } from "../modules/common.js";
|
||||
import { Marked } from "@ts-stack/markdown";
|
||||
import { stripMarkdown } from "../modules/stripmd.js";
|
||||
|
||||
@ -830,6 +830,21 @@ export class settingsList {
|
||||
};
|
||||
this._backupSortDirection.onclick = () => this.setBackupSort(!(this._backupSortAscending));
|
||||
const advancedEnableToggle = document.getElementById("settings-advanced-enabled") as HTMLInputElement;
|
||||
|
||||
const filedlg = document.getElementById("backups-file") as HTMLInputElement;
|
||||
document.getElementById("settings-backups-upload").onclick = () => {
|
||||
filedlg.click();
|
||||
};
|
||||
filedlg.addEventListener("change", () => {
|
||||
if (filedlg.files.length == 0) return;
|
||||
const form = new FormData();
|
||||
form.append("backups-file", filedlg.files[0], filedlg.files[0].name);
|
||||
_upload("/backups/restore", form);
|
||||
window.modals.backups.close();
|
||||
window.modals.settingsRefresh.modal.querySelector("span.heading").textContent = window.lang.strings("settingsRestarting");
|
||||
window.modals.settingsRefresh.show();
|
||||
});
|
||||
|
||||
advancedEnableToggle.onchange = () => {
|
||||
document.dispatchEvent(new CustomEvent("settings-advancedState", { detail: advancedEnableToggle.checked }));
|
||||
const parent = advancedEnableToggle.parentElement;
|
||||
|
Loading…
Reference in New Issue
Block a user