Skip to content

Commit

Permalink
Prune allow users to ignore threads during prune messages
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Jun 10, 2020
1 parent de8ad66 commit 4efcc5b
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 15 deletions.
5 changes: 3 additions & 2 deletions app/api/server/v1/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ API.v1.addRoute('rooms.cleanHistory', { authRequired: true }, {
oldest,
inclusive,
limit: this.bodyParams.limit,
excludePinned: this.bodyParams.excludePinned,
filesOnly: this.bodyParams.filesOnly,
excludePinned: [true, 'true', 1, '1'].includes(this.bodyParams.excludePinned),
filesOnly: [true, 'true', 1, '1'].includes(this.bodyParams.filesOnly),
ignoreThreads: [true, 'true', 1, '1'].includes(this.bodyParams.ignoreThreads),
fromUsers: this.bodyParams.users,
}));

Expand Down
15 changes: 15 additions & 0 deletions app/channel-settings/client/views/channelSettings.html
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,21 @@
</div>
</div>
{{/with}}
{{#with settings.retentionKeepThreads}}
<div class="rc-user-info__row">
<div class="rc-switch rc-switch--blue">
<label class="rc-switch__label">
<span class="rc-switch__text">
{{_ label}}{{equal default value '*'}}
</span>
<input type="checkbox" class="rc-switch__input js-input-check" name="retentionKeepThreads" checked="{{checked}}" disabled="{{./disabled}}">
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
</label>
</div>
</div>
{{/with}}
{{/if}}
{{/if}}
</div>
Expand Down
12 changes: 11 additions & 1 deletion app/channel-settings/server/methods/saveRoomSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { saveRoomTokenpass } from '../functions/saveRoomTokens';
import { saveStreamingOptions } from '../functions/saveStreamingOptions';
import { RoomSettingsEnum, roomTypes } from '../../../utils';

const fields = ['featured', 'roomName', 'roomTopic', 'roomAnnouncement', 'roomCustomFields', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode', 'tokenpass', 'streamingOptions', 'retentionEnabled', 'retentionMaxAge', 'retentionExcludePinned', 'retentionFilesOnly', 'retentionOverrideGlobal', 'encrypted', 'favorite'];
const fields = ['featured', 'roomName', 'roomTopic', 'roomAnnouncement', 'roomCustomFields', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode', 'tokenpass', 'streamingOptions', 'retentionEnabled', 'retentionMaxAge', 'retentionExcludePinned', 'retentionFilesOnly', 'retentionIgnoreThreads', 'retentionOverrideGlobal', 'encrypted', 'favorite'];
Meteor.methods({
saveRoomSettings(rid, settings, value) {
const userId = Meteor.userId();
Expand Down Expand Up @@ -128,10 +128,17 @@ Meteor.methods({
action: 'Editing_room',
});
}
if (setting === 'retentionIgnoreThreads' && !hasPermission(userId, 'edit-room-retention-policy', rid) && value !== room.retention.ignoreThreads) {
throw new Meteor.Error('error-action-not-allowed', 'Editing room retention policy is not allowed', {
method: 'saveRoomSettings',
action: 'Editing_room',
});
}
if (setting === 'retentionOverrideGlobal') {
delete settings.retentionMaxAge;
delete settings.retentionExcludePinned;
delete settings.retentionFilesOnly;
delete settings.retentionIgnoreThreads;
}
});

Expand Down Expand Up @@ -215,6 +222,9 @@ Meteor.methods({
case 'retentionFilesOnly':
Rooms.saveRetentionFilesOnlyById(rid, value);
break;
case 'retentionIgnoreThreads':
Rooms.saveRetentionIgnoreThreadsById(rid, value);
break;
case 'retentionOverrideGlobal':
Rooms.saveRetentionOverrideGlobalById(rid, value);
break;
Expand Down
10 changes: 10 additions & 0 deletions app/discussion/server/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,14 @@ Meteor.startup(() => {
i18nDescription: 'RetentionPolicy_DoNotExcludeDiscussion_Description',
enableQuery: globalQuery,
});

settings.add('RetentionPolicy_DoNotExcludeThreads', true, {
group: 'RetentionPolicy',
section: 'Global Policy',
type: 'boolean',
public: true,
i18nLabel: 'RetentionPolicy_DoNotExcludeThreads',
i18nDescription: 'RetentionPolicy_DoNotExcludeThreads_Description',
enableQuery: globalQuery,
});
});
6 changes: 4 additions & 2 deletions app/lib/server/functions/cleanRoomHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FileUpload } from '../../../file-upload';
import { Messages, Rooms } from '../../../models';
import { Notifications } from '../../../notifications';

export const cleanRoomHistory = function({ rid, latest = new Date(), oldest = new Date('0001-01-01T00:00:00Z'), inclusive = true, limit = 0, excludePinned = true, ignoreDiscussion = true, filesOnly = false, fromUsers = [] }) {
export const cleanRoomHistory = function({ rid, latest = new Date(), oldest = new Date('0001-01-01T00:00:00Z'), inclusive = true, limit = 0, excludePinned = true, ignoreDiscussion = true, filesOnly = false, fromUsers = [] }, ignoreThreads = true) {
const gt = inclusive ? '$gte' : '$gt';
const lt = inclusive ? '$lte' : '$lt';

Expand All @@ -21,19 +21,21 @@ export const cleanRoomHistory = function({ rid, latest = new Date(), oldest = ne
ts,
fromUsers,
{ fields: { 'file._id': 1, pinned: 1 }, limit },
ignoreThreads,
).forEach((document) => {
FileUpload.getStore('Uploads').deleteById(document.file._id);
fileCount++;
if (filesOnly) {
Messages.update({ _id: document._id }, { $unset: { file: 1 }, $set: { attachments: [{ color: '#FD745E', text }] } });
}
});

if (filesOnly) {
return fileCount;
}

if (!ignoreDiscussion) {
Messages.findDiscussionByRoomIdPinnedTimestampAndUsers(rid, excludePinned, ts, fromUsers, { fields: { drid: 1 }, ...limit && { limit } }).fetch()
Messages.findDiscussionByRoomIdPinnedTimestampAndUsers(rid, excludePinned, ts, fromUsers, { fields: { drid: 1 }, ...limit && { limit } }, ignoreThreads).fetch()
.forEach(({ drid }) => deleteRoom(drid));
}

Expand Down
5 changes: 3 additions & 2 deletions app/lib/server/methods/cleanRoomHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import { hasPermission } from '../../../authorization';
import { cleanRoomHistory } from '../functions';

Meteor.methods({
cleanRoomHistory({ roomId, latest, oldest, inclusive = true, limit, excludePinned = false, ignoreDiscussion = true, filesOnly = false, fromUsers = [] }) {
cleanRoomHistory({ roomId, latest, oldest, inclusive = true, limit, excludePinned = false, ignoreDiscussion = true, filesOnly = false, fromUsers = [], ignoreThreads }) {
check(roomId, String);
check(latest, Date);
check(oldest, Date);
check(inclusive, Boolean);
check(limit, Match.Maybe(Number));
check(excludePinned, Match.Maybe(Boolean));
check(filesOnly, Match.Maybe(Boolean));
check(ignoreThreads, Match.Maybe(Boolean));
check(fromUsers, Match.Maybe([String]));

const userId = Meteor.userId();
Expand All @@ -25,6 +26,6 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'cleanRoomHistory' });
}

return cleanRoomHistory({ rid: roomId, latest, oldest, inclusive, limit, excludePinned, ignoreDiscussion, filesOnly, fromUsers });
return cleanRoomHistory({ rid: roomId, latest, oldest, inclusive, limit, excludePinned, ignoreDiscussion, filesOnly, fromUsers, ignoreThreads });
},
});
14 changes: 12 additions & 2 deletions app/models/server/models/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class Messages extends Base {
return this.find(query, { fields: { 'file._id': 1 }, ...options });
}

findFilesByRoomIdPinnedTimestampAndUsers(rid, excludePinned, ignoreDiscussion = true, ts, users = [], options = {}) {
findFilesByRoomIdPinnedTimestampAndUsers(rid, excludePinned, ignoreDiscussion = true, ts, users = [], options = {}, ignoreThreads = true) {
const query = {
rid,
ts,
Expand All @@ -183,6 +183,11 @@ export class Messages extends Base {
query.pinned = { $ne: true };
}

if (ignoreThreads) {
query.tmid = { $exists: 0 };
query.tcount = { $exists: 0 };
}

if (ignoreDiscussion) {
query.drid = { $exists: 0 };
}
Expand Down Expand Up @@ -900,7 +905,7 @@ export class Messages extends Base {
return this.remove({ rid: { $in: rids } });
}

removeByIdPinnedTimestampLimitAndUsers(rid, pinned, ignoreDiscussion = true, ts, limit, users = []) {
removeByIdPinnedTimestampLimitAndUsers(rid, pinned, ignoreDiscussion = true, ts, limit, users = [], ignoreThreads = true) {
const query = {
rid,
ts,
Expand All @@ -914,6 +919,11 @@ export class Messages extends Base {
query.drid = { $exists: 0 };
}

if (ignoreThreads) {
query.tmid = { $exists: 0 };
query.tcount = { $exists: 0 };
}

if (users.length) {
query['u.username'] = { $in: users };
}
Expand Down
12 changes: 12 additions & 0 deletions app/models/server/models/Rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,18 @@ export class Rooms extends Base {
return this.update(query, update);
}

saveRetentionIgnoreThreadsById(_id, value) {
const query = { _id };

const update = {
[value === true ? '$set' : '$unset']: {
'retention.ignoreThreads': true,
},
};

return this.update(query, update);
}

saveRetentionFilesOnlyById(_id, value) {
const query = { _id };

Expand Down
7 changes: 4 additions & 3 deletions app/retention-policy/server/cronPruneMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function job() {
const filesOnly = settings.get('RetentionPolicy_FilesOnly');
const excludePinned = settings.get('RetentionPolicy_ExcludePinned');
const ignoreDiscussion = settings.get('RetentionPolicy_DoNotExcludeDiscussion');
const ignoreThreads = settings.get('RetentionPolicy_DoNotExcludeThreads');

// get all rooms with default values
types.forEach((type) => {
Expand All @@ -37,7 +38,7 @@ function job() {
],
'retention.overrideGlobal': { $ne: true },
}, { fields: { _id: 1 } }).forEach(({ _id: rid }) => {
cleanRoomHistory({ rid, latest, oldest, filesOnly, excludePinned, ignoreDiscussion });
cleanRoomHistory({ rid, latest, oldest, filesOnly, excludePinned, ignoreDiscussion, ignoreThreads });
});
});

Expand All @@ -46,9 +47,9 @@ function job() {
'retention.overrideGlobal': { $eq: true },
'retention.maxAge': { $gte: 0 },
}).forEach((room) => {
const { maxAge = 30, filesOnly, excludePinned } = room.retention;
const { maxAge = 30, filesOnly, excludePinned, ignoreThreads } = room.retention;
const latest = new Date(now.getTime() - toDays(maxAge));
cleanRoomHistory({ rid: room._id, latest, oldest, filesOnly, excludePinned, ignoreDiscussion });
cleanRoomHistory({ rid: room._id, latest, oldest, filesOnly, excludePinned, ignoreDiscussion, ignoreThreads });
});
}

Expand Down
5 changes: 5 additions & 0 deletions app/ui-clean-history/client/views/cleanHistory.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
{{> icon icon="check" block="rc-checkbox__icon"}}
<span class="rc-checkbox__text rc-text__small">{{_ "RetentionPolicy_DoNotExcludeDiscussion"}}</span>
</label>
<label class="rc-checkbox">
<input type="checkbox" name="ignoreThreads" class="rc-checkbox__input">
{{> icon icon="check" block="rc-checkbox__icon"}}
<span class="rc-checkbox__text rc-text__small">{{_ "RetentionPolicy_DoNotExcludeThreads"}}</span>
</label>
<label class="rc-checkbox">
<input type="checkbox" name="filesOnly" class="rc-checkbox__input">
{{> icon icon="check" block="rc-checkbox__icon"}}
Expand Down
11 changes: 8 additions & 3 deletions app/ui-clean-history/client/views/cleanHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const getRoomName = function() {
return t('conversation_with_s', roomTypes.getRoomName(room.t, room));
};

const purgeWorker = function(roomId, oldest, latest, inclusive, limit, excludePinned, ignoreDiscussion, filesOnly, fromUsers) {
const purgeWorker = function(roomId, oldest, latest, inclusive, limit, excludePinned, ignoreDiscussion, filesOnly, fromUsers, ignoreThreads) {
return call('cleanRoomHistory', {
roomId,
latest,
Expand All @@ -34,6 +34,7 @@ const purgeWorker = function(roomId, oldest, latest, inclusive, limit, excludePi
ignoreDiscussion,
filesOnly,
fromUsers,
ignoreThreads,
});
};

Expand Down Expand Up @@ -121,7 +122,7 @@ Template.cleanHistory.onCreated(function() {
this.cleanHistoryFilesOnly = new ReactiveVar(false);

this.ignoreDiscussion = new ReactiveVar(false);

this.ignoreThreads = new ReactiveVar(false);

this.cleanHistoryBusy = new ReactiveVar(false);
this.cleanHistoryFinished = new ReactiveVar(false);
Expand Down Expand Up @@ -257,6 +258,9 @@ Template.cleanHistory.events({
'change [name=ignoreDiscussion]'(e, instance) {
instance.ignoreDiscussion.set(e.target.checked);
},
'change [name=ignoreThreads]'(e, instance) {
instance.ignoreThreads.set(e.target.checked);
},
'click .js-prune'(e, instance) {
modal.open({
title: t('Are_you_sure'),
Expand All @@ -279,6 +283,7 @@ Template.cleanHistory.events({
const metaCleanHistoryExcludePinned = instance.cleanHistoryExcludePinned.get();
const metaCleanHistoryFilesOnly = instance.cleanHistoryFilesOnly.get();
const ignoreDiscussion = instance.ignoreDiscussion.get();
const ignoreThreads = instance.ignoreThreads.get();

let fromDate = new Date('0001-01-01T00:00:00Z');
let toDate = new Date('9999-12-31T23:59:59Z');
Expand All @@ -297,7 +302,7 @@ Template.cleanHistory.events({
let count = 0;
let result;
do {
result = await purgeWorker(roomId, fromDate, toDate, metaCleanHistoryInclusive, limit, metaCleanHistoryExcludePinned, ignoreDiscussion, metaCleanHistoryFilesOnly, users); // eslint-disable-line no-await-in-loop
result = await purgeWorker(roomId, fromDate, toDate, metaCleanHistoryInclusive, limit, metaCleanHistoryExcludePinned, ignoreDiscussion, metaCleanHistoryFilesOnly, users, ignoreThreads); // eslint-disable-line no-await-in-loop
count += result;
} while (result === limit);

Expand Down
1 change: 1 addition & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2911,6 +2911,7 @@
"Retention_setting_changed_successfully": "Retention policy setting changed successfully",
"RetentionPolicy": "Retention Policy",
"RetentionPolicy_DoNotExcludeDiscussion": "Do not exclude discussion messages",
"RetentionPolicy_DoNotExcludeThreads": "Do not exclude Threads",
"RetentionPolicy_RoomWarning": "Messages older than __time__ are automatically pruned here",
"RetentionPolicy_RoomWarning_Unpinned": "Unpinned messages older than __time__ are automatically pruned here",
"RetentionPolicy_RoomWarning_FilesOnly": "Files older than __time__ are automatically pruned here (messages stay intact)",
Expand Down

0 comments on commit 4efcc5b

Please sign in to comment.