1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-19 05:09:42 +02:00

Add the basis for in-app backup/restore process

Zip format output.
This commit is contained in:
Harvey Kandola 2018-10-04 21:04:31 +01:00
parent 391c143483
commit ab2cbd4ff7
9 changed files with 163 additions and 1 deletions

View file

@ -0,0 +1,32 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import { inject as service } from '@ember/service';
import Notifier from '../../mixins/notifier';
import Component from '@ember/component';
export default Component.extend(Notifier, {
appMeta: service(),
browserSvc: service('browser'),
buttonLabel: 'Run Backup',
actions: {
onBackup() {
this.showWait();
this.set('buttonLabel', 'Please wait, backup running...');
this.get('onBackup')({}).then(() => {
this.set('buttonLabel', 'Run Backup');
this.showDone();
});
}
}
});

View file

@ -0,0 +1,25 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import { inject as service } from '@ember/service';
import Controller from '@ember/controller';
export default Controller.extend({
global: service(),
actions: {
onBackup(spec) {
if(this.get('session.isAdmin')) {
return this.get('global').backup(spec);
}
}
}
});

View file

@ -0,0 +1,33 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import { inject as service } from '@ember/service';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import Route from '@ember/routing/route';
export default Route.extend(AuthenticatedRouteMixin, {
appMeta: service(),
session: service(),
global: service(),
beforeModel() {
if (!this.get("session.isAdmin")) {
this.transitionTo('auth.login');
}
},
model() {
},
activate() {
this.get('browser').setTitle('Backup/Restore');
}
});

View file

@ -0,0 +1 @@
{{customize/backup-restore onBackup=(action 'onBackup')}}

View file

@ -98,6 +98,9 @@ export default Router.map(function () {
this.route('integrations', {
path: 'integrations'
});
this.route('backup', {
path: 'backup'
});
}
);

View file

@ -9,12 +9,14 @@
//
// https://documize.com
import { Promise as EmberPromise } from 'rsvp';
import Service, { inject as service } from '@ember/service';
export default Service.extend({
sessionService: service('session'),
ajax: service(),
appMeta: service(),
browserSvc: service('browser'),
store: service(),
// Returns SMTP configuration.
@ -137,5 +139,50 @@ export default Service.extend({
method: 'POST',
});
}
},
// Run tenant level backup.
backup(spec) {
return new EmberPromise((resolve) => {
let url = this.get('appMeta.endpoint');
let token = this.get('sessionService.session.content.authenticated.token');
let uploadUrl = `${url}/global/backup?token=${token}`;
var xhr = new XMLHttpRequest();
xhr.open('POST', uploadUrl);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.responseType = 'blob';
xhr.onload = function() {
if (this.status == 200) {
// get binary data as a response
var blob = this.response;
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = xhr.getResponseHeader('x-documize-filename').replace('"', '');
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
resolve();
}
}
xhr.send(JSON.stringify(spec));
});
// return this.get('ajax').raw(`global/backup`, {
// method: 'post',
// data: JSON.stringify(spec),
// contentType: 'json',
// dataType: 'text'
// });
}
});

View file

@ -0,0 +1,18 @@
<div class="row">
<div class="col">
<div class="view-customize">
<h1 class="admin-heading">Backup & Restore</h1>
<h2 class="sub-heading">Export all documents and settings to a single ZIP file.</h2>
</div>
</div>
</div>
<div class="view-customize">
<form class="mt-5 ">
<div class="form-group">
<p>It can take several minutes to complete the backup process &mdash; please be patient while the backup is running.</p>
<div class="btn btn-success mt-3" {{action 'onBackup'}}>{{buttonLabel}}</div>
</div>
</form>
</div>

View file

@ -39,7 +39,7 @@ func (m *middleware) cors(w http.ResponseWriter, r *http.Request, next http.Hand
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS, PATCH")
w.Header().Set("Access-Control-Allow-Headers", "host, content-type, accept, authorization, origin, referer, user-agent, cache-control, x-requested-with")
w.Header().Set("Access-Control-Expose-Headers", "x-documize-version, x-documize-status")
w.Header().Set("Access-Control-Expose-Headers", "x-documize-version, x-documize-status, x-documize-filename, Content-Disposition, Content-Length")
if r.Method == "OPTIONS" {
w.Header().Add("X-Documize-Version", m.Runtime.Product.Version)

View file

@ -19,6 +19,7 @@ import (
"github.com/documize/community/domain/auth"
"github.com/documize/community/domain/auth/keycloak"
"github.com/documize/community/domain/auth/ldap"
"github.com/documize/community/domain/backup"
"github.com/documize/community/domain/block"
"github.com/documize/community/domain/category"
"github.com/documize/community/domain/conversion"
@ -57,6 +58,7 @@ func RegisterEndpoints(rt *env.Runtime, s *store.Store) {
space := space.Handler{Runtime: rt, Store: s}
block := block.Handler{Runtime: rt, Store: s}
group := group.Handler{Runtime: rt, Store: s}
backup := backup.Handler{Runtime: rt, Store: s}
section := section.Handler{Runtime: rt, Store: s}
setting := setting.Handler{Runtime: rt, Store: s}
category := category.Handler{Runtime: rt, Store: s}
@ -217,6 +219,7 @@ func RegisterEndpoints(rt *env.Runtime, s *store.Store) {
AddPrivate(rt, "global/sync/keycloak", []string{"GET", "OPTIONS"}, nil, keycloak.Sync)
AddPrivate(rt, "global/ldap/preview", []string{"POST", "OPTIONS"}, nil, ldap.Preview)
AddPrivate(rt, "global/ldap/sync", []string{"GET", "OPTIONS"}, nil, ldap.Sync)
AddPrivate(rt, "global/backup", []string{"POST", "OPTIONS"}, nil, backup.Backup)
Add(rt, RoutePrefixRoot, "robots.txt", []string{"GET", "OPTIONS"}, nil, meta.RobotsTxt)
Add(rt, RoutePrefixRoot, "sitemap.xml", []string{"GET", "OPTIONS"}, nil, meta.Sitemap)