flag updating and note appending, #5232
parent
709a7ff7f0
commit
d9d60c20bd
@ -0,0 +1,60 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* globals define */
|
||||||
|
|
||||||
|
define('forum/flags/detail', ['components'], function (components) {
|
||||||
|
var Flags = {};
|
||||||
|
|
||||||
|
Flags.init = function () {
|
||||||
|
// Update attributes
|
||||||
|
$('#state').val(ajaxify.data.state).removeAttr('disabled');
|
||||||
|
$('#assignee').val(ajaxify.data.assignee).removeAttr('disabled');
|
||||||
|
|
||||||
|
$('[data-action]').on('click', function () {
|
||||||
|
var action = this.getAttribute('data-action');
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'update':
|
||||||
|
socket.emit('flags.update', {
|
||||||
|
flagId: ajaxify.data.flagId,
|
||||||
|
data: $('#attributes').serializeArray()
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
} else {
|
||||||
|
app.alertSuccess('[[flags:updated]]');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'appendNote':
|
||||||
|
socket.emit('flags.appendNote', {
|
||||||
|
flagId: ajaxify.data.flagId,
|
||||||
|
note: document.getElementById('note').value
|
||||||
|
}, function (err, notes) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
} else {
|
||||||
|
app.alertSuccess('[[flags:note-added]]');
|
||||||
|
Flags.reloadNotes(notes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Flags.reloadNotes = function (notes) {
|
||||||
|
templates.parse('flags/detail', 'notes', {
|
||||||
|
notes: notes
|
||||||
|
}, function (html) {
|
||||||
|
var wrapperEl = components.get('flag/notes');
|
||||||
|
wrapperEl.empty();
|
||||||
|
wrapperEl.html(html);
|
||||||
|
wrapperEl.find('span.timeago').timeago();
|
||||||
|
document.getElementById('note').value = '';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Flags;
|
||||||
|
});
|
@ -0,0 +1,167 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var S = require('string');
|
||||||
|
|
||||||
|
var user = require('../user');
|
||||||
|
var groups = require('../groups');
|
||||||
|
var posts = require('../posts');
|
||||||
|
var topics = require('../topics');
|
||||||
|
var privileges = require('../privileges');
|
||||||
|
var notifications = require('../notifications');
|
||||||
|
var plugins = require('../plugins');
|
||||||
|
var meta = require('../meta');
|
||||||
|
var utils = require('../../public/src/utils');
|
||||||
|
var flags = require('../flags');
|
||||||
|
|
||||||
|
var SocketFlags = {};
|
||||||
|
|
||||||
|
SocketFlags.create = function (socket, data, callback) {
|
||||||
|
if (!socket.uid) {
|
||||||
|
return callback(new Error('[[error:not-logged-in]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data || !data.pid || !data.reason) {
|
||||||
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var flaggingUser = {};
|
||||||
|
var post;
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
posts.getPostFields(data.pid, ['pid', 'tid', 'uid', 'content', 'deleted'], next);
|
||||||
|
},
|
||||||
|
function (postData, next) {
|
||||||
|
if (parseInt(postData.deleted, 10) === 1) {
|
||||||
|
return next(new Error('[[error:post-deleted]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
post = postData;
|
||||||
|
topics.getTopicFields(post.tid, ['title', 'cid'], next);
|
||||||
|
},
|
||||||
|
function (topicData, next) {
|
||||||
|
post.topic = topicData;
|
||||||
|
|
||||||
|
async.parallel({
|
||||||
|
isAdminOrMod: function (next) {
|
||||||
|
privileges.categories.isAdminOrMod(post.topic.cid, socket.uid, next);
|
||||||
|
},
|
||||||
|
userData: function (next) {
|
||||||
|
user.getUserFields(socket.uid, ['username', 'reputation', 'banned'], next);
|
||||||
|
}
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (user, next) {
|
||||||
|
var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1;
|
||||||
|
if (!user.isAdminOrMod && parseInt(user.userData.reputation, 10) < minimumReputation) {
|
||||||
|
return next(new Error('[[error:not-enough-reputation-to-flag]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseInt(user.banned, 10) === 1) {
|
||||||
|
return next(new Error('[[error:user-banned]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
flaggingUser = user.userData;
|
||||||
|
flaggingUser.uid = socket.uid;
|
||||||
|
|
||||||
|
flags.create('post', post.pid, socket.uid, data.reason, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
post: function (next) {
|
||||||
|
posts.parsePost(post, next);
|
||||||
|
},
|
||||||
|
admins: function (next) {
|
||||||
|
groups.getMembers('administrators', 0, -1, next);
|
||||||
|
},
|
||||||
|
globalMods: function (next) {
|
||||||
|
groups.getMembers('Global Moderators', 0, -1, next);
|
||||||
|
},
|
||||||
|
moderators: function (next) {
|
||||||
|
groups.getMembers('cid:' + post.topic.cid + ':privileges:mods', 0, -1, next);
|
||||||
|
}
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
var title = S(post.topic.title).decodeHTMLEntities().s;
|
||||||
|
var titleEscaped = title.replace(/%/g, '%').replace(/,/g, ',');
|
||||||
|
|
||||||
|
notifications.create({
|
||||||
|
bodyShort: '[[notifications:user_flagged_post_in, ' + flaggingUser.username + ', ' + titleEscaped + ']]',
|
||||||
|
bodyLong: post.content,
|
||||||
|
pid: data.pid,
|
||||||
|
path: '/post/' + data.pid,
|
||||||
|
nid: 'post_flag:' + data.pid + ':uid:' + socket.uid,
|
||||||
|
from: socket.uid,
|
||||||
|
mergeId: 'notifications:user_flagged_post_in|' + data.pid,
|
||||||
|
topicTitle: post.topic.title
|
||||||
|
}, function (err, notification) {
|
||||||
|
if (err || !notification) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.fireHook('action:post.flag', {post: post, reason: data.reason, flaggingUser: flaggingUser});
|
||||||
|
notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), next);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketFlags.update = function (socket, data, callback) {
|
||||||
|
if (!data || !(data.flagId && data.data)) {
|
||||||
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload = {};
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel([
|
||||||
|
async.apply(user.isAdminOrGlobalMod, socket.uid),
|
||||||
|
async.apply(user.isModeratorOfAnyCategory, socket.uid)
|
||||||
|
], function (err, results) {
|
||||||
|
next(err, results[0] || results[1]);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (allowed, next) {
|
||||||
|
if (!allowed) {
|
||||||
|
return next(new Error('[[no-privileges]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate form data into object
|
||||||
|
payload = data.data.reduce(function (memo, cur) {
|
||||||
|
memo[cur.name] = cur.value;
|
||||||
|
return memo;
|
||||||
|
}, payload);
|
||||||
|
|
||||||
|
flags.update(data.flagId, socket.uid, payload, next);
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketFlags.appendNote = function (socket, data, callback) {
|
||||||
|
if (!data || !(data.flagId && data.note)) {
|
||||||
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel([
|
||||||
|
async.apply(user.isAdminOrGlobalMod, socket.uid),
|
||||||
|
async.apply(user.isModeratorOfAnyCategory, socket.uid)
|
||||||
|
], function (err, results) {
|
||||||
|
next(err, results[0] || results[1]);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (allowed, next) {
|
||||||
|
if (!allowed) {
|
||||||
|
return next(new Error('[[no-privileges]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.appendNote(data.flagId, socket.uid, data.note, next);
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = SocketFlags;
|
@ -1,173 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var async = require('async');
|
|
||||||
var S = require('string');
|
|
||||||
|
|
||||||
var user = require('../../user');
|
|
||||||
var groups = require('../../groups');
|
|
||||||
var posts = require('../../posts');
|
|
||||||
var topics = require('../../topics');
|
|
||||||
var privileges = require('../../privileges');
|
|
||||||
var notifications = require('../../notifications');
|
|
||||||
var plugins = require('../../plugins');
|
|
||||||
var meta = require('../../meta');
|
|
||||||
var utils = require('../../../public/src/utils');
|
|
||||||
var flags = require('../../flags');
|
|
||||||
|
|
||||||
module.exports = function (SocketPosts) {
|
|
||||||
|
|
||||||
SocketPosts.flag = function (socket, data, callback) {
|
|
||||||
if (!socket.uid) {
|
|
||||||
return callback(new Error('[[error:not-logged-in]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data || !data.pid || !data.reason) {
|
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
var flaggingUser = {};
|
|
||||||
var post;
|
|
||||||
|
|
||||||
async.waterfall([
|
|
||||||
function (next) {
|
|
||||||
posts.getPostFields(data.pid, ['pid', 'tid', 'uid', 'content', 'deleted'], next);
|
|
||||||
},
|
|
||||||
function (postData, next) {
|
|
||||||
if (parseInt(postData.deleted, 10) === 1) {
|
|
||||||
return next(new Error('[[error:post-deleted]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
post = postData;
|
|
||||||
topics.getTopicFields(post.tid, ['title', 'cid'], next);
|
|
||||||
},
|
|
||||||
function (topicData, next) {
|
|
||||||
post.topic = topicData;
|
|
||||||
|
|
||||||
async.parallel({
|
|
||||||
isAdminOrMod: function (next) {
|
|
||||||
privileges.categories.isAdminOrMod(post.topic.cid, socket.uid, next);
|
|
||||||
},
|
|
||||||
userData: function (next) {
|
|
||||||
user.getUserFields(socket.uid, ['username', 'reputation', 'banned'], next);
|
|
||||||
}
|
|
||||||
}, next);
|
|
||||||
},
|
|
||||||
function (user, next) {
|
|
||||||
var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1;
|
|
||||||
if (!user.isAdminOrMod && parseInt(user.userData.reputation, 10) < minimumReputation) {
|
|
||||||
return next(new Error('[[error:not-enough-reputation-to-flag]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseInt(user.banned, 10) === 1) {
|
|
||||||
return next(new Error('[[error:user-banned]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
flaggingUser = user.userData;
|
|
||||||
flaggingUser.uid = socket.uid;
|
|
||||||
|
|
||||||
flags.create('post', post.pid, socket.uid, data.reason, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
async.parallel({
|
|
||||||
post: function (next) {
|
|
||||||
posts.parsePost(post, next);
|
|
||||||
},
|
|
||||||
admins: function (next) {
|
|
||||||
groups.getMembers('administrators', 0, -1, next);
|
|
||||||
},
|
|
||||||
globalMods: function (next) {
|
|
||||||
groups.getMembers('Global Moderators', 0, -1, next);
|
|
||||||
},
|
|
||||||
moderators: function (next) {
|
|
||||||
groups.getMembers('cid:' + post.topic.cid + ':privileges:mods', 0, -1, next);
|
|
||||||
}
|
|
||||||
}, next);
|
|
||||||
},
|
|
||||||
function (results, next) {
|
|
||||||
var title = S(post.topic.title).decodeHTMLEntities().s;
|
|
||||||
var titleEscaped = title.replace(/%/g, '%').replace(/,/g, ',');
|
|
||||||
|
|
||||||
notifications.create({
|
|
||||||
bodyShort: '[[notifications:user_flagged_post_in, ' + flaggingUser.username + ', ' + titleEscaped + ']]',
|
|
||||||
bodyLong: post.content,
|
|
||||||
pid: data.pid,
|
|
||||||
path: '/post/' + data.pid,
|
|
||||||
nid: 'post_flag:' + data.pid + ':uid:' + socket.uid,
|
|
||||||
from: socket.uid,
|
|
||||||
mergeId: 'notifications:user_flagged_post_in|' + data.pid,
|
|
||||||
topicTitle: post.topic.title
|
|
||||||
}, function (err, notification) {
|
|
||||||
if (err || !notification) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.fireHook('action:post.flag', {post: post, reason: data.reason, flaggingUser: flaggingUser});
|
|
||||||
notifications.push(notification, results.admins.concat(results.moderators).concat(results.globalMods), next);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
SocketPosts.dismissFlag = function (socket, pid, callback) {
|
|
||||||
if (!pid || !socket.uid) {
|
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
|
||||||
}
|
|
||||||
async.waterfall([
|
|
||||||
function (next) {
|
|
||||||
user.isAdminOrGlobalMod(socket.uid, next);
|
|
||||||
},
|
|
||||||
function (isAdminOrGlobalModerator, next) {
|
|
||||||
if (!isAdminOrGlobalModerator) {
|
|
||||||
return next(new Error('[[no-privileges]]'));
|
|
||||||
}
|
|
||||||
flags.dismiss(pid, next);
|
|
||||||
}
|
|
||||||
], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
SocketPosts.dismissAllFlags = function (socket, data, callback) {
|
|
||||||
async.waterfall([
|
|
||||||
function (next) {
|
|
||||||
user.isAdminOrGlobalMod(socket.uid, next);
|
|
||||||
},
|
|
||||||
function (isAdminOrGlobalModerator, next) {
|
|
||||||
if (!isAdminOrGlobalModerator) {
|
|
||||||
return next(new Error('[[no-privileges]]'));
|
|
||||||
}
|
|
||||||
flags.dismissAll(next);
|
|
||||||
}
|
|
||||||
], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
SocketPosts.updateFlag = function (socket, data, callback) {
|
|
||||||
if (!data || !(data.pid && data.data)) {
|
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
var payload = {};
|
|
||||||
|
|
||||||
async.waterfall([
|
|
||||||
function (next) {
|
|
||||||
async.parallel([
|
|
||||||
async.apply(user.isAdminOrGlobalMod, socket.uid),
|
|
||||||
async.apply(user.isModeratorOfAnyCategory, socket.uid)
|
|
||||||
], function (err, results) {
|
|
||||||
next(err, results[0] || results[1]);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function (allowed, next) {
|
|
||||||
if (!allowed) {
|
|
||||||
return next(new Error('[[no-privileges]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translate form data into object
|
|
||||||
payload = data.data.reduce(function (memo, cur) {
|
|
||||||
memo[cur.name] = cur.value;
|
|
||||||
return memo;
|
|
||||||
}, payload);
|
|
||||||
|
|
||||||
flags.update(socket.uid, data.pid, payload, next);
|
|
||||||
}
|
|
||||||
], callback);
|
|
||||||
};
|
|
||||||
};
|
|
Loading…
Reference in New Issue