a bunch of changes here... allowing user profiles to be flagged, #5232

v1.18.x
Julian Lam 8 years ago
parent 57fcb92bbc
commit 5dd892bd01

@ -29,6 +29,9 @@
"start-new-chat": "Start New Chat",
"go-to-target": "View Flag Target",
"user-view": "View Profile",
"user-edit": "Edit Profile",
"notes": "Flag Notes",
"add-note": "Add Note",
"no-notes": "No shared notes.",
@ -43,5 +46,13 @@
"state-resolved": "Resolved",
"state-rejected": "Rejected",
"no-assignee": "Not Assigned",
"note-added": "Note Added"
"note-added": "Note Added",
"modal-title": "Report Inappropriate Content",
"modal-body": "Please specify your reason for flagging %1 %2 for review. Alternatively, use one of the quick report buttons if applicable.",
"modal-reason-spam": "Spam",
"modal-reason-offensive": "Offensive",
"modal-reason-custom": "Reason for reporting this content...",
"modal-submit": "Submit Report",
"modal-submit-success": "Content has been flagged for moderation."
}

@ -21,6 +21,9 @@
"user_flagged_post_in": "<strong>%1</strong> flagged a post in <strong>%2</strong>",
"user_flagged_post_in_dual": "<strong>%1</strong> and <strong>%2</strong> flagged a post in <strong>%3</strong>",
"user_flagged_post_in_multiple": "<strong>%1</strong> and %2 others flagged a post in <strong>%3</strong>",
"user_flagged_user": "<strong>%1</strong> flagged a user profile (%2)",
"user_flagged_user_dual": "<strong>%1</strong> and <strong>%2</strong> flagged a user profile (%3)",
"user_flagged_user_multiple": "<strong>%1</strong> and %2 others flagged a user profile (%3)",
"user_posted_to" : "<strong>%1</strong> has posted a reply to: <strong>%2</strong>",
"user_posted_to_dual" : "<strong>%1</strong> and <strong>%2</strong> have posted replies to: <strong>%3</strong>",
"user_posted_to_multiple" : "<strong>%1</strong> and %2 others have posted replies to: <strong>%3</strong>",

@ -28,7 +28,6 @@
"link": "Link",
"share": "Share",
"tools": "Tools",
"flag": "Flag",
"locked": "Locked",
"pinned": "Pinned",
"moved": "Moved",
@ -36,7 +35,6 @@
"bookmark_instructions" : "Click here to return to the last read post in this thread.",
"flag_title": "Flag this post for moderation",
"flag_success": "This post has been flagged for moderation.",
"deleted_message": "This topic has been deleted. Only users with topic management privileges can see it.",
@ -138,10 +136,5 @@
"stale.create": "Create a new topic",
"stale.reply_anyway": "Reply to this topic anyway",
"link_back": "Re: [%1](%2)\n\n",
"spam": "Spam",
"offensive": "Offensive",
"custom-flag-reason": "Enter a flagging reason"
"link_back": "Re: [%1](%2)\n\n"
}

@ -35,6 +35,7 @@
"chat": "Chat",
"chat_with": "Continue chat with %1",
"new_chat_with": "Start new chat with %1",
"flag-profile": "Flag Profile",
"follow": "Follow",
"unfollow": "Unfollow",
"more": "More",

@ -49,6 +49,7 @@ define('forum/account/header', [
components.get('account/ban').on('click', banAccount);
components.get('account/unban').on('click', unbanAccount);
components.get('account/delete').on('click', deleteAccount);
components.get('account/flag').on('click', flagAccount);
};
function hidePrivateLinks() {
@ -167,6 +168,15 @@ define('forum/account/header', [
});
}
function flagAccount() {
require(['flags'], function (flags) {
flags.showFlagModal({
type: 'user',
id: ajaxify.data.uid
});
});
}
function removeCover() {
socket.emit('user.removeCover', {
uid: ajaxify.data.uid

@ -23,6 +23,8 @@ define('forum/flags/list', ['components'], function (components) {
var qs = payload.map(function (filter) {
if (filter.value) {
return filter.name + '=' + filter.value;
} else {
return;
}
}).filter(Boolean).join('&');

@ -167,10 +167,11 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
postContainer.on('click', '[component="post/flag"]', function () {
var pid = getData($(this), 'data-pid');
var username = getData($(this), 'data-username');
var userslug = getData($(this), 'data-userslug');
require(['forum/topic/flag'], function (flag) {
flag.showFlagModal(pid, username, userslug);
require(['flags'], function (flags) {
flags.showFlagModal({
type: 'post',
id: pid
});
});
});

@ -2,18 +2,13 @@
/* globals define, app, socket, templates */
define('forum/topic/flag', [], function () {
define('flags', [], function () {
var Flag = {},
flagModal,
flagCommit;
Flag.showFlagModal = function (pid, username, userslug) {
parseModal({
pid: pid,
username: username,
userslug: userslug
}, function (html) {
Flag.showFlagModal = function (data) {
parseModal(data, function (html) {
flagModal = $(html);
flagModal.on('hidden.bs.modal', function () {
@ -23,11 +18,11 @@ define('forum/topic/flag', [], function () {
flagCommit = flagModal.find('#flag-post-commit');
flagModal.on('click', '.flag-reason', function () {
flagPost(pid, $(this).text());
createFlag(data.type, data.id, $(this).text());
});
flagCommit.on('click', function () {
flagPost(pid, flagModal.find('#flag-reason-custom').val());
createFlag(data.type, data.id, flagModal.find('#flag-reason-custom').val());
});
flagModal.modal('show');
@ -37,24 +32,24 @@ define('forum/topic/flag', [], function () {
};
function parseModal(tplData, callback) {
templates.parse('partials/modals/flag_post_modal', tplData, function (html) {
templates.parse('partials/modals/flag_modal', tplData, function (html) {
require(['translator'], function (translator) {
translator.translate(html, callback);
});
});
}
function flagPost(pid, reason) {
if (!pid || !reason) {
function createFlag(type, id, reason) {
if (!type || !id || !reason) {
return;
}
socket.emit('flags.create', {type: 'post', id: pid, reason: reason}, function (err) {
socket.emit('flags.create', {type: type, id: id, reason: reason}, function (err) {
if (err) {
return app.alertError(err.message);
}
flagModal.modal('hide');
app.alertSuccess('[[topic:flag_success]]');
app.alertSuccess('[[flags:modal-submit-success]]');
});
}

@ -63,7 +63,11 @@ modsController.flags.detail = function (req, res, next) {
}
res.render('flags/detail', Object.assign(results.flagData, {
assignees: results.assignees
assignees: results.assignees,
type_bool: ['post', 'user'].reduce(function (memo, cur) {
memo[cur] = results.flagData.type === cur;
return memo;
}, {})
}));
});
};

@ -167,20 +167,44 @@ Flags.validate = function (payload, callback) {
switch (payload.type) {
case 'post':
async.parallel({
privileges: async.apply(privileges.posts.get, [payload.id], payload.uid)
editable: async.apply(privileges.posts.canEdit, payload.id, payload.uid)
}, function (err, subdata) {
if (err) {
return callback(err);
}
var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1;
if (!subdata.privileges[0].isAdminOrMod && parseInt(data.reporter.reputation, 10) < minimumReputation) {
// Check if reporter meets rep threshold (or can edit the target post, in which case threshold does not apply)
if (!subdata.editable.flag && parseInt(data.reporter.reputation, 10) < minimumReputation) {
return callback(new Error('[[error:not-enough-reputation-to-flag]]'));
}
callback();
});
break;
case 'user':
async.parallel({
editable: async.apply(privileges.users.canEdit, payload.uid, payload.id)
}, function (err, subdata) {
if (err) {
return callback(err);
}
var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1;
// Check if reporter meets rep threshold (or can edit the target user, in which case threshold does not apply)
if (!subdata.editable && parseInt(data.reporter.reputation, 10) < minimumReputation) {
return callback(new Error('[[error:not-enough-reputation-to-flag]]'));
}
callback();
});
break;
default:
callback(new Error('[[error:invalid-data]]'));
break;
}
});
};
@ -369,13 +393,17 @@ Flags.exists = function (type, id, uid, callback) {
Flags.targetExists = function (type, id, callback) {
switch (type) {
case 'topic': // just an example...
topics.exists(id, callback);
break;
case 'post':
posts.exists(id, callback);
break;
case 'user':
user.exists(id, callback);
break;
default:
callback(new Error('[[error:invalid-data]]'));
break;
}
};
@ -384,6 +412,10 @@ Flags.getTargetUid = function (type, id, callback) {
case 'post':
posts.getPostField(id, 'uid', callback);
break;
case 'user':
setImmediate(callback, null, id);
break;
}
};
@ -553,7 +585,7 @@ Flags.notify = function (flagObj, uid, callback) {
notifications.create({
bodyShort: '[[notifications:user_flagged_post_in, ' + flagObj.reporter.username + ', ' + titleEscaped + ']]',
bodyLong: results.post.content,
bodyLong: flagObj.description,
pid: flagObj.targetId,
path: '/post/' + flagObj.targetId,
nid: 'flag:post:' + flagObj.targetId + ':uid:' + uid,
@ -570,6 +602,36 @@ Flags.notify = function (flagObj, uid, callback) {
});
});
break;
case 'user':
async.parallel({
admins: async.apply(groups.getMembers, 'administrators', 0, -1),
globalMods: async.apply(groups.getMembers, 'Global Moderators', 0, -1),
}, function (err, results) {
if (err) {
return callback(err);
}
notifications.create({
bodyShort: '[[notifications:user_flagged_user, ' + flagObj.reporter.username + ', ' + flagObj.target.username + ']]',
bodyLong: flagObj.description,
path: '/uid/' + flagObj.targetId,
nid: 'flag:user:' + flagObj.targetId + ':uid:' + uid,
from: uid,
mergeId: 'notifications:user_flagged_user|' + flagObj.targetId
}, function (err, notification) {
if (err || !notification) {
return callback(err);
}
notifications.push(notification, results.admins.concat(results.globalMods), callback);
});
});
break;
default:
callback(new Error('[[error:invalid-data]]'));
break;
}
};

@ -49,7 +49,6 @@ module.exports = function (Meta) {
'public/src/client/unread.js',
'public/src/client/topic.js',
'public/src/client/topic/events.js',
'public/src/client/topic/flag.js',
'public/src/client/topic/fork.js',
'public/src/client/topic/move.js',
'public/src/client/topic/posts.js',
@ -72,7 +71,8 @@ module.exports = function (Meta) {
'public/src/modules/taskbar.js',
'public/src/modules/helpers.js',
'public/src/modules/sounds.js',
'public/src/modules/string.js'
'public/src/modules/string.js',
'public/src/modules/flags.js'
],
// modules listed below are routed through express (/src/modules) so they can be defined anonymously

@ -415,6 +415,7 @@ var utils = require('../public/src/utils');
'notifications:user_started_following_you',
'notifications:user_posted_to',
'notifications:user_flagged_post_in',
'notifications:user_flagged_user',
'new_register'
],
isolated, differentiators, differentiator, modifyIndex, set;
@ -462,6 +463,7 @@ var utils = require('../public/src/utils');
case 'notifications:user_started_following_you':
case 'notifications:user_posted_to':
case 'notifications:user_flagged_post_in':
case 'notifications:user_flagged_user':
var usernames = set.map(function (notifObj) {
return notifObj && notifObj.user && notifObj.user.username;
}).filter(function (username, idx, array) {

@ -32,6 +32,11 @@ describe('Flags', function () {
content: 'This is flaggable content'
}, next);
});
},
function (topicData, next) {
User.create({
username: 'testUser2', password: 'abcdef', email: 'c@d.com'
}, next);
}
], done);
});
@ -212,7 +217,7 @@ describe('Flags', function () {
Flags.validate({
type: 'post',
id: 1,
uid: 1
uid: 2
}, function (err) {
assert.ok(err);
assert.strictEqual('[[error:not-enough-reputation-to-flag]]', err.message);
@ -305,6 +310,10 @@ describe('Flags', function () {
assert.ifError(err);
Flags.getHistory(1, function (err, history) {
if (err) {
throw err;
}
assert.strictEqual(entries + 1, history.length);
done();
});
@ -315,6 +324,7 @@ describe('Flags', function () {
describe('.getHistory()', function () {
it('should retrieve a flag\'s history', function (done) {
Flags.getHistory(1, function (err, history) {
assert.ifError(err);
assert.strictEqual(history[0].fields[0].value, '[[flags:state-rejected]]');
done();
});

Loading…
Cancel
Save