Skip to content

Commit

Permalink
chg: refactored deletion of accounts and sites
Browse files Browse the repository at this point in the history
  • Loading branch information
p3k committed May 21, 2018
1 parent a978ad7 commit c36302a
Show file tree
Hide file tree
Showing 21 changed files with 1,250 additions and 1,389 deletions.
6 changes: 3 additions & 3 deletions code/Admin/$Admin.skin
Expand Up @@ -207,7 +207,7 @@
</div> </div>
<div> <div>
<% gettext '{0} sites sorted by {1} in {2} order.' <% gettext '{0} sites sorted by {1} in {2} order.'
<% admin.dropdown name="display" <% markgettext all %> <% markgettext blocked %> <% markgettext trusted %> <% markgettext open %> <% markgettext restricted %> <% markgettext public %> <% markgettext closed %> <% markgettext deleted %> %> <% admin.dropdown name="display" <% markgettext all %> <% markgettext deleted %> <% markgettext blocked %> <% markgettext trusted %> <% markgettext open %> <% markgettext restricted %> <% markgettext public %> <% markgettext closed %> %>
<% admin.dropdown name="sorting" <% markgettext modified %> <% markgettext created %> <% markgettext name %> %> <% admin.dropdown name="sorting" <% markgettext modified %> <% markgettext created %> <% markgettext name %> %>
<% admin.dropdown name="order" <% markgettext descending %> <% markgettext ascending %> %> <% admin.dropdown name="order" <% markgettext descending %> <% markgettext ascending %> %>
%> %>
Expand Down Expand Up @@ -411,7 +411,7 @@
<div class='uk-badge uk-badge-success'><% gettext Trusted %></div> <div class='uk-badge uk-badge-success'><% gettext Trusted %></div>


<% #deletedSite %> <% #deletedSite %>
<i class='uk-icon-ban'></i> <div class='uk-badge'><% gettext Deleted %></div>


<% #closedSite %> <% #closedSite %>
<i class='uk-icon-lock'></i> <i class='uk-icon-lock'></i>
Expand All @@ -423,7 +423,7 @@
<i class='uk-icon-globe'></i> <i class='uk-icon-globe'></i>


<% #deletedUser %> <% #deletedUser %>
<div class='uk-badge'><% gettext Deleted %></div> <div class='uk-badge uk-badge-warning'><% gettext Deleted %></div>


<% #blockedUser %> <% #blockedUser %>
<div class='uk-badge uk-badge-danger'><% gettext Blocked %></div> <div class='uk-badge uk-badge-danger'><% gettext Blocked %></div>
Expand Down
38 changes: 16 additions & 22 deletions code/Admin/Admin.js
Expand Up @@ -146,10 +146,8 @@ Admin.dequeue = function() {
app.log('Processing queued job ' + (i + 1) + ' of ' + max); app.log('Processing queued job ' + (i + 1) + ' of ' + max);
switch (job.method) { switch (job.method) {
case 'remove': case 'remove':
if (job.target.deleted) { if (job.target.constructor === Site) Site.remove.call(job.target);
if (job.target.constructor === Site) Site.remove.call(job.target); if (job.target.constructor === User) User.remove.call(job.target);
if (job.target.constructor === User) User.remove.call(job.target);
}
break; break;
case 'import': case 'import':
Importer.run(job.target, job.user); Importer.run(job.target, job.user);
Expand Down Expand Up @@ -179,21 +177,17 @@ Admin.purgeAccounts = function() {
var now = Date.now(); var now = Date.now();


root.admin.deletedUsers.forEach(function() { root.admin.deletedUsers.forEach(function() {
if (!this.deleted) return; // already gone if (this.job || this.deleted) return; // already gone
if (now - this.deleted > 0 && !this.job) { this.job = Admin.queue(this, 'remove', this);
this.job = Admin.queue(this, 'remove', this);
}
}); });
}; };


Admin.purgeSites = function() { Admin.purgeSites = function() {
var now = new Date; var now = new Date;


root.admin.deletedSites.forEach(function() { root.admin.deletedSites.forEach(function() {
if (!this.deleted) return; if (this.job) return;
if (now > this.deleted > 0 && !this.job) { this.job = Admin.queue(this, 'remove', this.modifier);
this.job = Admin.queue(this, 'remove', this.modifier);
}
}); });


var notificationPeriod = root.phaseOutNotificationPeriod * Date.ONEDAY; var notificationPeriod = root.phaseOutNotificationPeriod * Date.ONEDAY;
Expand All @@ -217,7 +211,7 @@ Admin.purgeSites = function() {
}); });
this.notified = now; this.notified = now;
} else if (now - this.notified > gracePeriod) { } else if (now - this.notified > gracePeriod) {
this.mode = Site.DELETED; this.status = Site.DELETED;
this.deleted = now; this.deleted = now;
this.notified = null; this.notified = null;
} }
Expand Down Expand Up @@ -639,12 +633,12 @@ Admin.prototype.filterSites = function(data) {


var displays = { var displays = {
1: "status = 'blocked'", 1: "status = 'blocked'",
2: "status = 'trusted'", 2: "status = 'deleted'",
3: "mode = 'open'", 3: "status = 'trusted'",
4: "mode = 'restricted'", 4: "mode = 'open'",
5: "mode = 'public'", 5: "mode = 'restricted'",
6: "mode = 'closed'", 6: "mode = 'public'",
7: "mode = 'deleted'" 7: "mode = 'closed'"
}; };


var sortings = { var sortings = {
Expand Down Expand Up @@ -812,7 +806,7 @@ Admin.prototype.renderActivity = function (item, skin) {
case User: case User:
return item.status !== User.BLOCKED && item.status !== User.DELETED && item.created - item.modified < 1; return item.status !== User.BLOCKED && item.status !== User.DELETED && item.created - item.modified < 1;
case Site: case Site:
return item.mode !== Site.DELETED && item.created - item.modified < 1; return item.status !== Site.DELETED && item.created - item.modified < 1;
} }
return false; return false;
} }
Expand Down Expand Up @@ -905,15 +899,15 @@ Admin.prototype.link_macro = function (param, action, text, target) {
switch (action) { switch (action) {
case 'block': case 'block':
var user = target.creator || target; var user = target.creator || target;
if (user.status !== User.PRIVILEGED && user.status !== User.BLOCKED && (user.status !== User.DELETED || user.deleted)) { if (user.status !== User.PRIVILEGED && user.status !== User.BLOCKED && user.status !== User.DELETED) {
var url = user.href('block'); var url = user.href('block');
return renderLink.call(global, param, url, text || String.EMPTY, this); return renderLink.call(global, param, url, text || String.EMPTY, this);
} }
break; break;


case 'delete': case 'delete':
var site = target.constructor === Site ? target : target.site; var site = target.constructor === Site ? target : target.site;
if (site && site.getPermission(action) && site.mode !== Site.DELETED) { if (site && site.getPermission(action) && site.status !== Site.DELETED) {
var url = site.href('delete') + '?safemode'; var url = site.href('delete') + '?safemode';
return renderLink.call(global, param, url, text || String.EMPTY, this); return renderLink.call(global, param, url, text || String.EMPTY, this);
} }
Expand Down
2 changes: 1 addition & 1 deletion code/Admin/Admin.properties
Expand Up @@ -28,7 +28,7 @@ restrictedSites = collection(Site)
restrictedSites.filter = mode = 'restricted' and status <> 'blocked' restrictedSites.filter = mode = 'restricted' and status <> 'blocked'


deletedSites = collection(Site) deletedSites = collection(Site)
deletedSites.filter = mode = 'deleted' deletedSites.filter = status = 'deleted'
deletedSites.order = modified desc deletedSites.order = modified desc


users = collection(User) users = collection(User)
Expand Down
2 changes: 1 addition & 1 deletion code/Comment/Comment.js
Expand Up @@ -235,7 +235,7 @@ Comment.prototype.getConfirmText = function() {
if (this.status === Comment.DELETED && size > 1) { if (this.status === Comment.DELETED && size > 1) {
return gettext('You are about to delete a comment thread consisting of {0} postings.', size); return gettext('You are about to delete a comment thread consisting of {0} postings.', size);
} }
return gettext('You are about to delete a comment by user {0}.', this.creator.name); return gettext('You are about to delete a comment by {0}.', this.creator.name);
}; };


Comment.prototype.getConfirmExtra = function () { Comment.prototype.getConfirmExtra = function () {
Expand Down
2 changes: 1 addition & 1 deletion code/Global/$Global.skin
Expand Up @@ -36,7 +36,7 @@
<div class="uk-width-1-1 av-upload-controls"> <div class="uk-width-1-1 av-upload-controls">
<input class='uk-width-1-2' type="text" value="<% param.value %>"> <input class='uk-width-1-2' type="text" value="<% param.value %>">
<button class='uk-button' id="<% param.name %>_control" name="<% param.name %>_control" type="button"> <button class='uk-button' id="<% param.name %>_control" name="<% param.name %>_control" type="button">
<% gettext "Browse" suffix=… %> <% gettext "Select" suffix=… %>
</button> </button>
</div> </div>
</div> </div>
Expand Down
6 changes: 3 additions & 3 deletions code/HopObject/HopObject.js
Expand Up @@ -109,7 +109,7 @@ HopObject.prototype.onRequest = function() {
res.handlers.membership = User.getMembership(); res.handlers.membership = User.getMembership();


// Logout persisting session if account has been deleted // Logout persisting session if account has been deleted
if (User.getCurrentStatus() === User.DELETED && !session.user.deleted) { if (User.getCurrentStatus() === User.DELETED) {
User.logout(); User.logout();
} }


Expand All @@ -124,7 +124,7 @@ HopObject.prototype.onRequest = function() {


if (!User.require(User.PRIVILEGED)) { if (!User.require(User.PRIVILEGED)) {
// Simulate 404 for sites which are due for deletion by cronjob // Simulate 404 for sites which are due for deletion by cronjob
if (res.handlers.site.mode === Site.DELETED) { if (res.handlers.site.status === Site.DELETED) {
res.handlers.site = root; res.handlers.site = root;
root.notfound_action(); root.notfound_action();
res.stop(); res.stop();
Expand All @@ -143,7 +143,6 @@ HopObject.prototype.onRequest = function() {
HopObject.confirmConstructor(Layout); HopObject.confirmConstructor(Layout);
res.handlers.layout = res.handlers.site.layout || new Layout; res.handlers.layout = res.handlers.site.layout || new Layout;
res.skinpath = res.handlers.layout.getSkinPath(); res.skinpath = res.handlers.layout.getSkinPath();
//res.skinpath = [app.dir];


if (!this.getPermission(req.action)) { if (!this.getPermission(req.action)) {
if (!session.user) { if (!session.user) {
Expand Down Expand Up @@ -177,6 +176,7 @@ markgettext('Image');
markgettext('Membership'); markgettext('Membership');
markgettext('Poll'); markgettext('Poll');
markgettext('Story'); markgettext('Story');
markgettext('User');


HopObject.prototype.delete_action = function() { HopObject.prototype.delete_action = function() {
if (req.postParams.proceed) { if (req.postParams.proceed) {
Expand Down
6 changes: 3 additions & 3 deletions code/Members/Members.js
Expand Up @@ -118,11 +118,11 @@ Members.prototype.reset_action = function() {
if (req.postParams.reset) { if (req.postParams.reset) {
try { try {
if (!req.postParams.name || !req.postParams.email) { if (!req.postParams.name || !req.postParams.email) {
throw Error(gettext('Please enter a user name and e-mail address.')); throw Error(gettext('Please enter a username and e-mail address.'));
} }
var user = User.getByName(req.postParams.name); var user = User.getByName(req.postParams.name);
if (!user || user.email !== req.postParams.email) { if (!user || user.email !== req.postParams.email) {
throw Error(gettext('User name and e-mail address do not match.')) throw Error(gettext('Username and e-mail address do not match.'))
} }
var token = User.getSalt(); var token = User.getSalt();
user.setMetadata('resetToken', token); user.setMetadata('resetToken', token);
Expand Down Expand Up @@ -409,7 +409,7 @@ Members.prototype.search = function(searchString, limit) {
Members.prototype.addMembership = function(data) { Members.prototype.addMembership = function(data) {
var user = root.users.get(data.name); var user = root.users.get(data.name);
if (!user) { if (!user) {
throw Error(gettext('Sorry, your input did not match any registered user.')); throw Error(gettext('Sorry, your input did not match any registered account.'));
/*} else if (this.get(data.name)) { /*} else if (this.get(data.name)) {
throw Error(gettext('This user is already a member of this site.'));*/ throw Error(gettext('This user is already a member of this site.'));*/
} }
Expand Down
6 changes: 3 additions & 3 deletions code/Membership/Membership.js
Expand Up @@ -194,8 +194,8 @@ Membership.prototype.contact_action = function() {
} }
Recaptcha.verify(req.postParams); Recaptcha.verify(req.postParams);
this.notify(req.action, this.creator.email, session.user ? this.notify(req.action, this.creator.email, session.user ?
gettext('[{0}] Message from user {1}', root.title, session.user.name) : gettext('[{0}] Message from {1}', root.title, session.user.name) :
gettext('[{0}] Message from anonymous user', root.title)); gettext('[{0}] Message from anonymous', root.title));
res.message = gettext('Your message was sent successfully.'); res.message = gettext('Your message was sent successfully.');
res.redirect(this._parent.getPermission() ? res.redirect(this._parent.getPermission() ?
this._parent.href() : this.site.href()); this._parent.href() : this.site.href());
Expand Down Expand Up @@ -274,7 +274,7 @@ Membership.prototype.notify = function(action, recipient, subject) {
* @returns {String} * @returns {String}
*/ */
Membership.prototype.getConfirmText = function() { Membership.prototype.getConfirmText = function() {
return gettext('You are about to delete the membership of user {0}.', return gettext('You are about to delete the membership of {0}.',
this.creator.name); this.creator.name);
} }


Expand Down
9 changes: 0 additions & 9 deletions code/Site/$Site.skin
Expand Up @@ -1185,15 +1185,6 @@ a.gs-title:hover {
</td> </td>
</tr> </tr>


<% #deleted %>
<h1><% gettext 'Deleted Site' %></h1>
<p>
<% gettext "This site is scheduled for deletion." %>
</p>
<div class='uk-alert'>
<% gettext 'You still can revert the request for deletion in the {0}site settings{1}.' <% site.href edit prefix='<a href="' suffix='">' %> '</a>' %>
</div>

<% #export %> <% #export %>
<h1><% gettext "Export Site Data" %></h1> <h1><% gettext "Export Site Data" %></h1>
<p> <p>
Expand Down
36 changes: 13 additions & 23 deletions code/Site/Site.js
Expand Up @@ -29,7 +29,6 @@ this.handleMetadata('callbackUrl');
this.handleMetadata('closed'); this.handleMetadata('closed');
this.handleMetadata('commentMode'); this.handleMetadata('commentMode');
this.handleMetadata('configured'); this.handleMetadata('configured');
this.handleMetadata('deleted');
this.handleMetadata('export'); this.handleMetadata('export');
this.handleMetadata('imageDimensionLimits'); this.handleMetadata('imageDimensionLimits');
this.handleMetadata('import_id'); this.handleMetadata('import_id');
Expand All @@ -51,23 +50,21 @@ this.handleMetadata('trollFilter');
* @returns {String[]} * @returns {String[]}
* @see defineConstants * @see defineConstants
*/ */
Site.getStatus = defineConstants(Site, markgettext('Blocked'), Site.getStatus = defineConstants(Site, markgettext('Deleted'), markgettext('Blocked'),
markgettext('Regular'), markgettext('Trusted')); markgettext('Regular'), markgettext('Trusted'));
/** /**
* @function * @function
* @returns {String[]} * @returns {String[]}
* @see defineConstants * @see defineConstants
*/ */
Site.getModes = defineConstants(Site, markgettext('Deleted'), Site.getModes = defineConstants(Site, markgettext('Closed'), markgettext('Restricted'),
markgettext('Closed'), markgettext('Restricted'),
markgettext('Public'), markgettext('Open')); markgettext('Public'), markgettext('Open'));
/** /**
* @function * @function
* @returns {String[]} * @returns {String[]}
* @see defineConstants * @see defineConstants
*/ */
Site.getPageModes = defineConstants(Site, markgettext('days') /* , Site.getPageModes = defineConstants(Site, markgettext('days')/*, markgettext('stories') */ );
markgettext('stories') */ );
/** /**
* @function * @function
* @returns {String[]} * @returns {String[]}
Expand Down Expand Up @@ -98,13 +95,6 @@ Site.getNotificationModes = defineConstants(Site, markgettext('Nobody'),
Site.getCallbackModes = defineConstants(Site, markgettext('disabled'), Site.getCallbackModes = defineConstants(Site, markgettext('disabled'),
markgettext('enabled')); markgettext('enabled'));


/**
*
*/
Site.getDeletionDate = function() {
return new Date(Date.now() + Date.ONEDAY * 0);
};

/** /**
* @param {String} name A unique identifier also used in the URL of a site * @param {String} name A unique identifier also used in the URL of a site
* @param {String} title An arbitrary string branding a site * @param {String} title An arbitrary string branding a site
Expand Down Expand Up @@ -225,7 +215,6 @@ Site.require = function(mode) {
* @property {String} commentMode The way comments of a site are displayed * @property {String} commentMode The way comments of a site are displayed
* @property {Date} created The date and time of site creation * @property {Date} created The date and time of site creation
* @property {User} creator A reference to a user who created a site * @property {User} creator A reference to a user who created a site
* @property {Date} deleted
* @property {String} export * @property {String} export
* @property {Files} files * @property {Files} files
* @property {Tags} galleries * @property {Tags} galleries
Expand Down Expand Up @@ -292,7 +281,7 @@ Site.prototype.getPermission = function(action) {
User.require(User.PRIVILEGED); User.require(User.PRIVILEGED);


case 'delete': case 'delete':
return this !== root && this.getPermission('edit'); return this !== root && this.status !== Site.DELETED && this.getPermission('edit');


case 'edit': case 'edit':
case 'export': case 'export':
Expand Down Expand Up @@ -321,7 +310,7 @@ Site.prototype.main_action = function() {
schema: 'http://schema.org/WebSite', schema: 'http://schema.org/WebSite',
title: this.getTitle(), title: this.getTitle(),
description: this.tagline || String.EMPTY, description: this.tagline || String.EMPTY,
body: this.renderSkinAsString(this.mode === Site.DELETED ? '$Site#deleted' : 'Site#main'), body: this.renderSkinAsString('Site#main'),
images: [(this.layout.images.get('favicon') || Images.Default['favicon.png']).getUrl()], images: [(this.layout.images.get('favicon') || Images.Default['favicon.png']).getUrl()],
links: this.renderSkinAsString('$Site#links') links: this.renderSkinAsString('$Site#links')
}); });
Expand Down Expand Up @@ -355,16 +344,15 @@ Site.prototype.delete_action = function () {
HopObject.prototype.delete_action.call(this); HopObject.prototype.delete_action.call(this);
} else { } else {
// Otherwise, queue for deletion // Otherwise, queue for deletion
this.deleted = Site.getDeletionDate(); this.status = Site.DELETED;
this.mode = Site.DELETED; res.message = gettext('The site {0} is being deleted.', this.name);
res.message = gettext('The site {0} is queued for deletion.', this.name);
} }
this.log(root, 'Deleted site ' + this.name); this.log(root, 'Deleted site ' + this.name);
res.redirect(this.href()); res.redirect(root.href());
} else { } else {
HopObject.prototype.delete_action.call(this); HopObject.prototype.delete_action.call(this);
} }
} };


/** /**
* *
Expand Down Expand Up @@ -428,8 +416,10 @@ Site.prototype.getConfirmExtra = function () {
* @param {Object} data * @param {Object} data
*/ */
Site.prototype.update = function(data) { Site.prototype.update = function(data) {
if (this.mode !== data.mode) { // Remove the corresponding job if site deletion is cancelled
this.deleted = data.mode === Site.DELETED ? new Date() : null; if (this.job && this.status === Site.DELETED && this.status !== data.status) {
let job = new Admin.Job(this.job);
if (job.method === 'remove') job.remove();
} }


data.maxImageWidth = Math.abs(data.maxImageWidth) || Infinity; data.maxImageWidth = Math.abs(data.maxImageWidth) || Infinity;
Expand Down
2 changes: 1 addition & 1 deletion code/Story/Story.js
Expand Up @@ -788,6 +788,6 @@ Story.prototype.markdown_filter = function (value, param) {
* @returns {String} * @returns {String}
*/ */
Story.prototype.getConfirmText = function() { Story.prototype.getConfirmText = function() {
return gettext("You are about to delete a story by user {0}.", return gettext("You are about to delete a story by {0}.",
this.creator ? this.creator.name : 'null'); this.creator ? this.creator.name : 'null');
} }
10 changes: 4 additions & 6 deletions code/User/$User.skin
Expand Up @@ -45,7 +45,7 @@
<% #edit %> <% #edit %>
<h1><% response.title %></h1> <h1><% response.title %></h1>
<div class='uk-article-meta'> <div class='uk-article-meta'>
<% if <% user.status %> is 'deleted' then <% user.skin $User#deleted %> else <% user.skin $User#meta %> %> <% if <% user.status %> is deleted then <% user.skin $User#deleted %> else <% user.skin $User#meta %> %>
</div> </div>
<div class='uk-margin-top uk-margin-bottom'> <div class='uk-margin-top uk-margin-bottom'>
<% context.link timeline <% gettext Timeline %> %> | <% context.link timeline <% gettext Timeline %> %> |
Expand Down Expand Up @@ -75,7 +75,7 @@
<div class='uk-form-row'> <div class='uk-form-row'>
<label class='uk-form-label' for='url'> <label class='uk-form-label' for='url'>
<% gettext "Personal URL" %> <% gettext "Personal URL" %>
<i class='uk-icon-info-circle uk-text-muted' title='<% gettext "If you enter a URL here your user name will appear as link next to your posted items." %>' data-uk-tooltip="{pos: 'right'}"></i> <i class='uk-icon-info-circle uk-text-muted' title='<% gettext "If you enter a URL here your username will appear as link next to your posted items." %>' data-uk-tooltip="{pos: 'right'}"></i>
</label> </label>
<div class='uk-form-controls'> <div class='uk-form-controls'>
<% user.input url type=url class='uk-form uk-width-2-3' %> <% user.input url type=url class='uk-form uk-width-2-3' %>
Expand Down Expand Up @@ -199,11 +199,9 @@


<% #deleted %> <% #deleted %>
<% if <% user.deleted %> is null then <% if <% user.deleted %> is null then
<% gettext 'Deleted on {0}' <% user.created short %> %> <% gettext 'Account is being deleted' %>
else else
<% gettext 'Scheduled for deletion {0}' <% user.deleted | format expiry %> <% gettext 'Deleted on {0}' <% user.created short %> %>
suffix=<% context.link 'edit?undelete=1' <% gettext "Click to cancel deletion" prefix="<i class='uk-icon-times-circle uk-margin-small-left' data-uk-tooltip=\"{pos: 'right'}\" title='" suffix="'></i>" %> %>
%>
%> %>


<% #notify_reset %> <% #notify_reset %>
Expand Down

0 comments on commit c36302a

Please sign in to comment.