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:
parent
b3383f46ca
commit
ec1939c01d
11 changed files with 2128 additions and 780 deletions
|
@ -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
|
@ -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)
|
||||
|
|
1346
embed/bindata.go
1346
embed/bindata.go
File diff suppressed because one or more lines are too long
|
@ -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);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 — please be patient while the backup operation is in progress</p>
|
||||
<p>It can take <b>several minutes</b> to complete the backup process — 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 — 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 — 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 — 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 — SMTP, authentication, integrations and other settings
|
||||
{{/ui/ui-checkbox}}
|
||||
</div>
|
||||
|
||||
{{#if restoreFailed}}
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
{{else}}
|
||||
<i class="material-icons">radio_button_unchecked</i>
|
||||
{{/if}}
|
||||
{{yield}}
|
||||
<div class="text">{{yield}}</div>
|
||||
</div>
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue