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

Provide Backup/Restore for system and tenant

This commit is contained in:
sauls8t 2018-10-17 14:27:40 +01:00
parent b3383f46ca
commit ec1939c01d
11 changed files with 2128 additions and 780 deletions

View file

@ -49,7 +49,6 @@ import (
"github.com/documize/community/model/permission"
"github.com/documize/community/model/pin"
"github.com/documize/community/model/space"
"github.com/documize/community/model/user"
uuid "github.com/nu7hatch/gouuid"
"github.com/pkg/errors"
)
@ -304,7 +303,7 @@ func (b backerHandler) dmzUserAccount(files *[]backupItem) (err error) {
w = fmt.Sprintf(" , dmz_user_account a WHERE u.c_refid=a.c_userid AND a.c_orgid='%s' ", b.Spec.OrgID)
}
u := []user.User{}
u := []m.User{}
err = b.Runtime.Db.Select(&u, `SELECT u.id, u.c_refid AS refid,
u.c_firstname AS firstname, u.c_lastname AS lastname, u.c_email AS email,
u.c_initials AS initials, u.c_globaladmin AS globaladmin,
@ -740,13 +739,13 @@ func (b backerHandler) dmzDocument(files *[]backupItem) (err error) {
// Share
type share struct {
ID uint64 `json:"id"`
OrgID string `json:"-"`
OrgID string `json:"orgId"`
UserID string `json:"userId"`
DocumentID string `json:"documentId"`
Email string `json:"email"`
Message string `json:"message"`
Viewed string `json:"viewed"` // recording each view as |date-viewed|date-viewed|
Secret string `json:"-"` // secure token used to access document
Secret string `json:"secret"` // secure token used to access document
Expires string `json:"expires"` // number of days from creation, value of 0 means never
Active bool `json:"active"`
Created time.Time `json:"created"`
@ -756,7 +755,7 @@ func (b backerHandler) dmzDocument(files *[]backupItem) (err error) {
err = b.Runtime.Db.Select(&sh, `
SELECT id AS id, c_orgid AS orgid, c_docid AS documentid,
c_userid AS userid, c_email AS email, c_message AS message, c_viewed AS viewed,
c_expires AS expires, c_active AS active, c_created AS created
c_expires AS expires, c_active AS active, c_secret AS secret, c_created AS created
FROM dmz_doc_share`+w)
if err != nil {
return errors.Wrap(err, "select.docshare")

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,7 @@ type Store struct {
}
//**************************************************
// Page Revisions
// Page
//**************************************************
// Add inserts the given page into the page table, adds that page to the queue of pages to index and audits that the page has been added.
@ -157,7 +157,7 @@ func (s Store) Update(ctx domain.RequestContext, page page.Page, refID, userID s
c_name, c_body, c_rawbody, c_config, c_created, c_revised)
SELECT ? AS refid, a.c_orgid, a.c_docid, a.c_userid AS ownerid, a.c_refid AS sectionid,
? AS userid, a.c_contenttype, a.c_type, a.c_name, a.c_body,
b.c_rawbody, b.c_config, ? AS c_created, ? As c_revised
b.c_rawbody, b.c_config, ? AS c_created, ? AS c_revised
FROM dmz_section a, dmz_section_meta b
WHERE a.c_refid=? AND a.c_refid=b.c_sectionid`),
refID, userID, time.Now().UTC(), time.Now().UTC(), page.RefID)

File diff suppressed because one or more lines are too long

View file

@ -17,12 +17,15 @@ import Component from '@ember/component';
export default Component.extend(Notifier, Modal, {
appMeta: service(),
router: service(),
browserSvc: service('browser'),
buttonLabel: 'Start Backup',
backupLabel: 'Backup',
backupSystemLabel: 'System Backup',
backupSpec: null,
backupFilename: '',
backupError: false,
backupSuccess: false,
backupRunning: false,
restoreSpec: null,
restoreButtonLabel: 'Restore',
restoreUploadReady: false,
@ -43,6 +46,8 @@ export default Component.extend(Notifier, Modal, {
this.set('restoreFile', null);
this.set('confirmRestore', '');
this.set('backupType', { Tenant: true, System: false });
},
didInsertElement() {
@ -54,31 +59,42 @@ export default Component.extend(Notifier, Modal, {
});
},
doBackup() {
this.showWait();
this.set('backupFilename', '');
this.set('backupSuccess', false);
this.set('backupFailed', false);
this.set('backupRunning', true);
let spec = this.get('backupSpec');
this.get('onBackup')(spec).then((filename) => {
this.showDone();
this.set('backupLabel', 'Start Backup');
this.set('backupSuccess', true);
this.set('backupFilename', filename);
this.set('backupRunning', false);
}, ()=> {
this.showDone();
this.set('backupLabel', 'Run Backup');
this.set('backupFailed', true);
this.set('backupRunning', false);
});
},
actions: {
onBackup() {
this.showWait();
this.set('buttonLabel', 'Please wait, backup running...');
this.set('backupFilename', '');
this.set('backupSuccess', false);
this.set('backupFailed', false);
// We perform tenant level backup.
this.set('backupSpec.org', this.get('appMeta.orgId'));
// If Documize Global Admin we perform system-level backup.
// Otherwise it is current tenant backup.
let spec = this.get('backupSpec');
if (this.get('session.isGlobalAdmin')) {
spec.org = "*";
}
this.doBackup();
},
this.get('onBackup')(spec).then((filename) => {
this.showDone();
this.set('buttonLabel', 'Start Backup');
this.set('backupSuccess', true);
this.set('backupFilename', filename);
}, ()=> {
this.showDone();
this.set('buttonLabel', 'Run Backup');
this.set('backupFailed', true);
});
onSystemBackup() {
// We perform system-level backup.
this.set('backupSpec.org', '*');
this.doBackup();
},
onShowRestoreModal() {
@ -132,11 +148,12 @@ export default Component.extend(Notifier, Modal, {
this.get('onRestore')(spec, filedata).then(() => {
this.showDone();
this.set('buttonLabel', 'Restore');
this.set('restoreSuccess', true);
this.set('backupLabel', 'Restore');
this.set('restoreSuccess', true);
this.get('router').transitionTo('auth.logout');
}, ()=> {
this.showDone();
this.set('restorButtonLabel', 'Restore');
this.set('restorbackupLabel', 'Restore');
this.set('restoreFailed', true);
});
},

View file

@ -162,12 +162,7 @@
border: 1px solid $color-border;
padding: 20px 20px;
background-color: lighten($color-green, 60%);
> .explain {
color: $color-gray;
font-size: 1rem;
font-style: italic;
}
color: $color-off-black;
> .backup-fail {
margin: 10px 0;
@ -186,6 +181,7 @@
margin: 50px 0;
padding: 20px 20px;
background-color: lighten($color-red, 60%);
color: $color-off-black;
> .restore-fail {
margin: 10px 0;

View file

@ -7,21 +7,29 @@
margin: 0 0 5px 0;
> .material-icons {
font-size: 1.4rem;
font-size: 1.5rem;
color: $color-gray;
vertical-align: top;
margin-right: 5px;
}
> .selected {
color: $color-link;
color: $color-blue;
}
&:hover {
color: $color-link;
color: $color-blue;
}
> .text {
display: inline-block;
font-size: 1.1rem;
vertical-align: sub;
color: $color-off-black;
}
}
.ui-radio-selected {
color: $color-link;
color: $color-blue;
}

View file

@ -12,23 +12,35 @@
<div class="backup-restore">
<div class="backup-zone">
{{#if session.isGlobalAdmin}}
<div class="explain">
<p>
Documize is a multi-tenanted application enabling both "tech.mycompany.com" and "sales.mycompany.com" to run using the same executable/database.
As a Documize <b>Global</b> Administrator, you will be performing a complete system-wide backup across all tenants.
A regular Documize Administrator can login to perform just a tenant-level backup (e.g. marketing.mycompany.com).
</p>
</div>
<p>
Documize is a multi-tenanted application enabling both "tech.mycompany.com" and "sales.mycompany.com" to run using the same executable/database.
As a Documize <b>Global Administrator</b>, you will be performing a complete system-wide backup across all tenants.
A Documize <b>Tenant Administrator</b> can login to perform a tenant-level backup (e.g. marketing.mycompany.com).
</p>
{{else}}
<p>
Documize is a multi-tenanted application enabling both "tech.mycompany.com" and "sales.mycompany.com" to run using the same executable/database.
A Documize <b>Global Administrator</b>, you will be performing a complete system-wide backup across all tenants.
As a Documize <b>Tenant Administrator</b> you can perform a tenant-level backup (e.g. marketing.mycompany.com).
</p>
{{/if}}
<p class="font-weight-bold">It can take several minutes to complete the backup process &mdash; please be patient while the backup operation is in progress</p>
<p>It can take <b>several minutes</b> to complete the backup process &mdash; please be patient while the backup operation is in progress.</p>
<div class="margin-top-30 margin-bottom-20">
{{#ui/ui-checkbox selected=backupSpec.retain}}
Retain backup file on server
{{/ui/ui-checkbox}}
</div>
<button class="btn btn-success mb-3" {{action 'onBackup'}}>{{buttonLabel}}</button>
{{#if backupRunning}}
<h3 class="text-success">Backup running, please wait...</h3>
{{else}}
<button class="btn btn-success mb-3" {{action 'onBackup'}}>BACKUP TENANT</button>
{{#if session.isGlobalAdmin}}
<div class="button-gap" />
<button class="btn btn-success mb-3" {{action 'onSystemBackup'}}>BACKUP SYSTEM</button>
{{/if}}
{{/if}}
{{#if backupFailed}}
<div class="backup-fail">Backup failed &mdash; please check server logs</div>
{{/if}}
@ -41,13 +53,10 @@
<div class="backup-restore">
<div class="restore-zone">
{{#if session.isGlobalAdmin}}
<div class="explain">
<p class="font-weight-bold">
You should only perform a restore to an empty Documize instance.
</p>
</div>
<p class="text-danger">Restore from a <b>system backup</b> should only be performed on an <b>empty Documize database.</b></p>
{{/if}}
<p class="font-weight-bold">It can take up to an hour to complete the restore process &mdash; please be patient while the restore operation is in progress</p>
<p>Restore operation will <b>re-create</b> users, groups, permissions, spaces, categories and content.</p>
<p>It can take <b>several minutes</b> to complete the restore process &mdash; please be patient while the restore operation is in progress.</p>
<div class="margin-top-30 margin-bottom-20">
<div class="custom-file">
@ -55,9 +64,6 @@
<label class="custom-file-label" for="restore-file">Choose backup file</label>
</div>
<div class="margin-top-20"></div>
{{#ui/ui-checkbox selected=restoreSpec.overwriteOrg}}
Overwrite settings &mdash; SMTP, authentication, integrations and other settings
{{/ui/ui-checkbox}}
</div>
{{#if restoreFailed}}

View file

@ -4,5 +4,5 @@
{{else}}
<i class="material-icons">radio_button_unchecked</i>
{{/if}}
{{yield}}
<div class="text">{{yield}}</div>
</div>

View file

@ -13,10 +13,11 @@
package backup
import (
"github.com/documize/community/model/org"
"time"
"github.com/documize/community/core/env"
"github.com/documize/community/model"
"github.com/documize/community/model/org"
)
// Manifest contains backup meta information.
@ -74,4 +75,24 @@ type ImportSpec struct {
// Handle to the current organization being used for restore process.
Org org.Organization
// Was the backup file for a global system backup?
// TRUE if Manifest.Org = "*".
GlobalBackup bool
}
// User represents user object for backup/restore operations.
// We include user specific secrets in such operations.
type User struct {
model.BaseEntity
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Email string `json:"email"`
Initials string `json:"initials"`
Active bool `json:"active"`
GlobalAdmin bool `json:"global"`
Password string `json:"password"`
Salt string `json:"salt"`
Reset string `json:"reset"`
LastVersion string `json:"lastVersion"`
}

View file

@ -16,7 +16,7 @@ import "github.com/documize/community/model"
// Organization defines a company that uses this app.
type Organization struct {
model.BaseEntity
Company string `json:"-"`
Company string `json:"company"`
Title string `json:"title"`
Message string `json:"message"`
Domain string `json:"domain"`
@ -26,6 +26,6 @@ type Organization struct {
AuthConfig string `json:"authConfig"`
ConversionEndpoint string `json:"conversionEndpoint"`
MaxTags int `json:"maxTags"`
Serial string `json:"-"`
Active bool `json:"-"`
Serial string `json:"serial"`
Active bool `json:"active"`
}