chg: run account export as job

This commit is contained in:
Tobi Schäfer 2018-05-05 11:04:17 +02:00
parent c388e71203
commit 5a2af525e1
10 changed files with 541 additions and 389 deletions

View file

@ -31,7 +31,19 @@ var Exporter = {}
* @param {Site} site The site to export.
* @param {User} user The user whose content will be exported.
*/
Exporter.run = function(site, user) {
Exporter.run = function(target, user) {
switch (target.constructor) {
case Site:
Exporter.saveSite(target, user);
break;
case User:
Exporter.saveAccount(target);
break;
}
};
Exporter.saveSite = function(site, user) {
try {
var file;
if (site.export_id && (file = File.getById(site.export_id))) {
@ -102,7 +114,7 @@ Exporter.run = function(site, user) {
return;
};
Exporter.getArchive = account => {
Exporter.saveAccount = account => {
const zip = new helma.Zip();
const sql = new Sql();
const FileUtils = Packages.org.apache.commons.io.FileUtils;
@ -140,7 +152,6 @@ Exporter.getArchive = account => {
files: [],
images: [],
members: [],
memberships: [],
polls: [],
sites: [],
stories: []
@ -154,16 +165,6 @@ Exporter.getArchive = account => {
index.accounts.push(this);
});
/*sql.retrieve('select * from site s, membership m where m.creator_id = $0 and s.id = m.site_id order by lower(s.name)', account._id);
sql.traverse(function() {
const site = Site.getById(this.id);
this.href = site.href();
addMetadata(this, Site);
addAssets(site);
index.sites.push(this);
});*/
sql.retrieve('select * from site s, membership m where m.creator_id = $0 and s.id = m.site_id order by lower(s.name)', account._id);
sql.traverse(function() {
@ -238,6 +239,16 @@ Exporter.getArchive = account => {
const data = new java.lang.String(json).getBytes('UTF-8');
zip.addData(data, 'index.json');
zip.close();
const dirName = app.appsProperties['static'] + '/export';
const fileName = 'antville-account-' + java.util.UUID.randomUUID() + '.zip';
const dir = new java.io.File(dirName);
const file = new java.io.File(dir, fileName);
if (!dir.exists()) dir.makeDirectory();
zip.save(file);
account.export = app.appsProperties.staticMountpoint + '/export/' + fileName;
account.job = null;
return zip;
};

View file

@ -55,6 +55,7 @@ Members.prototype.getPermission = function(action) {
switch (action) {
case 'edit':
case 'export':
case 'subscriptions':
case 'updates':
return !!session.user;
@ -211,9 +212,15 @@ Members.prototype.logout_action = function() {
}
Members.prototype.edit_action = function() {
res.handlers.context = this;
return void User.prototype.edit_action.call(session.user);
};
Members.prototype.export_action = function() {
res.handlers.context = this;
return void User.prototype.export_action.call(session.user);
};
Members.prototype.salt_txt_action = function() {
res.contentType = 'text/plain';
var user;

View file

@ -50,6 +50,9 @@
<% gettext 'Last modified by {0} on {1}' <% user.name %> <% this.modified short %> prefix=<br> %>
%>
</div>
<div class='uk-margin-top uk-margin-bottom'>
<% context.link export <% gettext Export %> %>
</div>
<form id='edit' class='uk-form uk-form-stacked uk-margin-top' method="post">
<input type="hidden" name="digest" id="digest">
<input type="hidden" name="hash" id="hash">
@ -99,9 +102,6 @@
<button class='uk-button uk-button-primary' type="submit" id="submit" name="save" value="1">
<% gettext Save %>
</button>
<button class='uk-button uk-button-secondary' type="submit" name="export" value="1">
<% gettext Export %>
</button>
<% user.link delete <% gettext 'Delete' %> class='uk-button' %>
<a href='<% site.href %>' class="uk-button uk-button-link"><% gettext Cancel %></a>
</div>
@ -150,6 +150,17 @@
</div>
</fieldset>
<% #export %>
<h1><% gettext "Export Account Data" %></h1>
<p>
<% if <% param.status %> is null then <% if <% this.export %> is null then '' else <% gettext "{0}Download the archive{1} or click “Export” to create a new one." <% this.export prefix="<a href='" suffix="'>" %> "</a>" %> %> else <% param.status %> %>
</p>
<form action="<% context.href export %>" method="post">
<button type="submit" name="submit" value="<% if <% param.status %> is null then export else cancel %>" class='uk-button uk-button-primary'>
<% if <% param.status %> is null then <% gettext Export %> else <% gettext Cancel %> %>
</button>
<a href='<% context.href edit %>' class='uk-button uk-button-link'><% gettext Account %></a>
</form>
<% #notify_reset %>
<% gettext 'Hello {0}.' <% user.name %> %>

View file

@ -24,7 +24,9 @@ markgettext('account');
markgettext('a account // accusative');
this.handleMetadata('accepted');
this.handleMetadata('export');
this.handleMetadata('hash');
this.handleMetadata('job');
this.handleMetadata('notes');
this.handleMetadata('salt');
this.handleMetadata('url');
@ -386,18 +388,16 @@ User.prototype.getPermission = function(action) {
}
User.prototype.edit_action = function () {
if (!res.handlers.context) res.handlers.context = this;
if (req.postParams.save) {
try {
this.update(req.postParams);
res.message = gettext('The changes were saved successfully.');
res.redirect(this.href(req.action));
res.redirect(res.handlers.context.href(req.action));
} catch (err) {
res.message = err.toString();
}
} else if (req.postParams.export) {
var zip = Exporter.getArchive(this);
res.setHeader('Content-Disposition', 'attachment; filename=antville-' + this.name + '.zip');
res.writeBinary(zip.getData());
}
session.data.token = User.getSalt();
session.data.salt = this.salt;
@ -411,9 +411,42 @@ User.prototype.block_action = function () {
res.redirect(req.data.http_referer);
};
User.prototype.export_action = function() {
if (!res.handlers.context) res.handlers.context = this;
const data = req.postParams;
const param = {};
const href = res.handlers.context.href(req.action);
let job = new Admin.Job(this.job || {});
if (data.submit === 'export') {
try {
if (job.method && job.method !== 'export') {
throw Error(gettext('There is already another job queued for this account: {0}', job.method));
}
this.job = Admin.queue(this, 'export');
res.message = gettext('The account is queued for export.');
} catch (ex) {
res.message = ex.toString();
app.log(res.message);
}
res.redirect(href);
} else if (data.submit === 'cancel') {
this.job = job.remove();
res.redirect(href);
}
if (job.method === 'export') {
param.status = gettext('The account data will be available for download from here within the next days.');
}
res.data.title = 'Export Account ' + this.name;
res.data.body = this.renderSkinAsString('$User#export', param);
res.handlers.site.renderSkin('Site#page');
};
User.prototype.getConfirmText = function () {
return gettext('You are about to delete the account {0}.',
this.getTitle());
return gettext('You are about to delete the account {0}.', this.getTitle());
};
/**