WIP(members): basic report a user API
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
} from '../../models/message';
|
||||
import highlightMentions from '../../libs/highlightMentions';
|
||||
import { handleGetMembersForChallenge } from '../../libs/challenges/handleGetMembersForChallenge';
|
||||
import { chatReporterFactory } from '../../libs/chatReporting/chatReporterFactory';
|
||||
|
||||
const { achievements } = common;
|
||||
|
||||
@@ -777,4 +778,39 @@ api.transferGems = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {post} /api/v3/members/:memberId/flag Flag (report) a user
|
||||
* @apiDescription Sends an email to staff about another user or their profile
|
||||
* @apiName FlagUser
|
||||
* @apiGroup Members
|
||||
*
|
||||
* @apiParam (Path) {UUID} memberId The unique ID of the user being flagged
|
||||
* @apiParam (Body) {String} [comment] explain why the user was flagged
|
||||
*
|
||||
* @apiSuccess {Object} data The flagged user
|
||||
* @apiSuccess {UUID} data.id The id of the flagged user
|
||||
* @apiSuccess {String} data.username The username of the flagged user
|
||||
* @apiSuccess {Object} data.profile The flagged user's profile information
|
||||
* @apiSuccess {String} data.profile.blurb Text of the flagged user's profile bio
|
||||
* @apiSuccess {String} data.profile.imageUrl URL of the flagged user's profile image
|
||||
* @apiSuccess {String} data.profile.name The flagged user's display name
|
||||
*
|
||||
* @apiError (400) {BadRequest} AlreadyFlagged A profile cannot be flagged
|
||||
* more than once by the same user.
|
||||
* @apiError (400) {BadRequest} MemberIdRequired The `memberId` param is required
|
||||
* and must be a valid `UUID`.
|
||||
* @apiError (404) {NotFound} UserWithIdNotFound The `memberId` param did not
|
||||
* belong to an existing user.
|
||||
*/
|
||||
api.flagUser = {
|
||||
method: 'POST',
|
||||
url: '/members/:memberId/flag',
|
||||
middlewares: [authWithHeaders()],
|
||||
async handler (req, res) {
|
||||
const chatReporter = chatReporterFactory('User', req, res);
|
||||
const flaggedUser = await chatReporter.flag();
|
||||
res.respond(200, flaggedUser);
|
||||
},
|
||||
};
|
||||
|
||||
export default api;
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import GroupChatReporter from './groupChatReporter';
|
||||
import InboxChatReporter from './inboxChatReporter';
|
||||
import ProfileReporter from './profileReporter';
|
||||
|
||||
export function chatReporterFactory (type, req, res) { // eslint-disable-line import/prefer-default-export, max-len
|
||||
if (type === 'Group') {
|
||||
return new GroupChatReporter(req, res);
|
||||
} if (type === 'Inbox') {
|
||||
return new InboxChatReporter(req, res);
|
||||
} if (type === 'Profile' || type === 'User') {
|
||||
return new ProfileReporter(req, res);
|
||||
}
|
||||
|
||||
throw new Error('Invalid chat reporter type.');
|
||||
|
||||
@@ -34,7 +34,8 @@ export default class ProfileReporter extends ChatReporter {
|
||||
throw new NotFound(this.res.t('userWithIDNotFound'));
|
||||
}
|
||||
|
||||
if (flaggedUser.profile.flags.indexOf(this.user._id) !== -1 && !this.user.hasPermission('moderator')) {
|
||||
if (flaggedUser.profile.flags && flaggedUser.profile.flags.indexOf(this.user._id) !== -1
|
||||
&& !this.user.hasPermission('moderator')) {
|
||||
throw new BadRequest('A profile can not be flagged more than once by the same user.');
|
||||
}
|
||||
|
||||
@@ -64,6 +65,17 @@ export default class ProfileReporter extends ChatReporter {
|
||||
];
|
||||
}
|
||||
|
||||
flagProfile (flaggedUser) {
|
||||
// Log user ids that have flagged the account
|
||||
if (!flaggedUser.profile.flags) {
|
||||
flaggedUser.profile.flags = [];
|
||||
}
|
||||
|
||||
flaggedUser.profile.flags.push(this.user._id);
|
||||
|
||||
return flaggedUser.save();
|
||||
}
|
||||
|
||||
async notify (flaggedUser, userComment) {
|
||||
let emailVariables = await this.getEmailVariables(flaggedUser);
|
||||
emailVariables = emailVariables.concat([
|
||||
@@ -78,4 +90,14 @@ export default class ProfileReporter extends ChatReporter {
|
||||
userComment,
|
||||
});
|
||||
}
|
||||
|
||||
async flag () {
|
||||
const { flaggedUser, userComment } = await this.validate();
|
||||
await this.flagProfile(flaggedUser);
|
||||
await this.notify(flaggedUser, userComment);
|
||||
if (!this.user.hasPermission('moderator')) {
|
||||
flaggedUser.profile.flags = [this.user._id];
|
||||
}
|
||||
return flaggedUser;
|
||||
}
|
||||
}
|
||||
@@ -176,6 +176,39 @@ function sendInboxFlagNotification ({
|
||||
.catch(err => logger.error(err, 'Error while sending flag data to Slack.'));
|
||||
}
|
||||
|
||||
function sendProfileFlagNotification ({
|
||||
reporter,
|
||||
flaggedUser,
|
||||
userComment,
|
||||
}) {
|
||||
const title = 'User Profile Report';
|
||||
const titleLink = `${BASE_URL}/static/front/#?memberId=${flaggedUser._id}`;
|
||||
const text = `@${reporter.auth.local.username} (${reporter._id}; language: ${reporter.preferences.language}) flagged @${flaggedUser.auth.local.username}'s profile`;
|
||||
if (userComment) {
|
||||
text += ` and commented: ${userComment}`;
|
||||
}
|
||||
const profileData = `Bio: ${flaggedUser.profile.blurb}`;
|
||||
if (flaggedUser.profile.imageUrl) {
|
||||
profileData += `\n\nImage URL: ${flaggedUser.profile.imageUrl}`;
|
||||
}
|
||||
|
||||
flagSlack
|
||||
.send({
|
||||
text,
|
||||
attachments: [{
|
||||
fallback: 'Flag Profile',
|
||||
color: 'danger',
|
||||
title,
|
||||
title_link: titleLink,
|
||||
text: profileData,
|
||||
mrkdwn_in: [
|
||||
'text',
|
||||
],
|
||||
}],
|
||||
})
|
||||
.catch(err => logger.error(err, 'Error while sending flag data to Slack.'));
|
||||
}
|
||||
|
||||
function sendSubscriptionNotification ({
|
||||
buyer,
|
||||
recipient,
|
||||
@@ -302,6 +335,7 @@ function sendSlurNotification ({
|
||||
export {
|
||||
sendFlagNotification,
|
||||
sendInboxFlagNotification,
|
||||
sendProfileFlagNotification,
|
||||
sendSubscriptionNotification,
|
||||
sendShadowMutedPostNotification,
|
||||
sendSlurNotification,
|
||||
|
||||
@@ -621,6 +621,9 @@ export default new Schema({
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
flags: [
|
||||
{ $type: String, validate: [v => validator.isUUID(v), 'Invalid user UUID.'], ref: 'User' },
|
||||
],
|
||||
},
|
||||
stats: {
|
||||
hp: { $type: Number, default: shared.maxHealth },
|
||||
|
||||
Reference in New Issue
Block a user