diff --git a/config.js b/config.js index 4601683c1..3e167b294 100644 --- a/config.js +++ b/config.js @@ -175,7 +175,12 @@ const CONFIG = { DISABLE_AUTOFLAG_SUSPECT_WORDS: process.env.TALK_DISABLE_AUTOFLAG_SUSPECT_WORDS === 'TRUE', // TRUST_THRESHOLDS defines the thresholds used for automoderation. - TRUST_THRESHOLDS: process.env.TRUST_THRESHOLDS || 'comment:2,-1;flag:2,-1' + TRUST_THRESHOLDS: process.env.TRUST_THRESHOLDS || 'comment:2,-1;flag:2,-1', + + // IGNORE_FLAGS_AGAINST_STAFF disables staff members from entering the + // reported queue from comments after this was enabled and from reports + // against the staff members user account. + IGNORE_FLAGS_AGAINST_STAFF: process.env.TALK_DISABLE_IGNORE_FLAGS_AGAINST_STAFF === 'TRUE', }; //============================================================================== diff --git a/docs/_docs/02-02-advanced-configuration.md b/docs/_docs/02-02-advanced-configuration.md index 74099258d..94a6b402d 100644 --- a/docs/_docs/02-02-advanced-configuration.md +++ b/docs/_docs/02-02-advanced-configuration.md @@ -456,3 +456,8 @@ Could be read as: added back to the queue. - At the moment of writing, behavior is not attached to the flagging reliability, but it is recorded. + +## TALK_DISABLE_IGNORE_FLAGS_AGAINST_STAFF + +When `TRUE`, staff members will have their accounts and comments moderated the +same as any other user in the system. (Default `FALSE`) \ No newline at end of file diff --git a/graph/mutators/action.js b/graph/mutators/action.js index 1ef9014a8..29a6e67af 100644 --- a/graph/mutators/action.js +++ b/graph/mutators/action.js @@ -1,5 +1,8 @@ const errors = require('../../errors'); const {CREATE_ACTION, DELETE_ACTION} = require('../../perms/constants'); +const { + IGNORE_FLAGS_AGAINST_STAFF, +} = require('../../config'); /** * getActionItem will return the item that is associated with the given action. @@ -56,12 +59,16 @@ const createAction = async (ctx, {item_id, item_type, action_type, group_id, met // Gets the item referenced by the action. const item = await getActionItem(ctx, {item_id, item_type}); - if (action_type === 'FLAG' && item_type === 'USERS') { + // If we are ignoring flags against staff, ensure that the target isn't a + // staff member. + if (IGNORE_FLAGS_AGAINST_STAFF) { + if (action_type === 'FLAG') { - // The item is a user, and this is a flag. Check to see if they are staff, - // if they are, don't permit the flag. - if (item.isStaff()) { - throw errors.ErrNotAuthorized; + // If the item is a user, and this is a flag. Check to see if they are + // staff, if they are, don't permit the flag. + if (item_type === 'USERS' && item.isStaff()) { + return null; + } } } diff --git a/graph/mutators/comment.js b/graph/mutators/comment.js index de3345257..bd8ab18fd 100644 --- a/graph/mutators/comment.js +++ b/graph/mutators/comment.js @@ -19,7 +19,8 @@ const { } = require('../../perms/constants'); const { - DISABLE_AUTOFLAG_SUSPECT_WORDS + DISABLE_AUTOFLAG_SUSPECT_WORDS, + IGNORE_FLAGS_AGAINST_STAFF, } = require('../../config'); const debug = require('debug')('talk:graph:mutators:tags'); @@ -292,7 +293,7 @@ const moderationPhases = [ } }, - // This phase checks to see if the comment's length exeeds maximum. + // This phase checks to see if the comment's length exceeds maximum. (context, comment, {assetSettings: {charCountEnable, charCount}}) => { // Reject if the comment is too long @@ -313,6 +314,15 @@ const moderationPhases = [ } }, + // If a given user is a staff member, always approve their comment. + (context) => { + if (IGNORE_FLAGS_AGAINST_STAFF && context.user && context.user.isStaff()) { + return { + status: 'ACCEPTED', + }; + } + }, + // This phase checks the comment if it has any links in it if the check is // enabled. (context, comment, {assetSettings: {premodLinksEnable}}) => { @@ -362,7 +372,7 @@ const moderationPhases = [ } }, - // This phase checks to see if the comment was already perscribed a status. + // This phase checks to see if the comment was already prescribed a status. (context, comment) => { // If the status was already defined, don't redefine it. It's only defined diff --git a/plugin-api/beta/server/getReactionConfig.js b/plugin-api/beta/server/getReactionConfig.js index 481990c16..2fffb4d1c 100644 --- a/plugin-api/beta/server/getReactionConfig.js +++ b/plugin-api/beta/server/getReactionConfig.js @@ -157,10 +157,22 @@ function getReactionConfig(reaction) { RootMutation: { [`create${Reaction}Action`]: async (_, {input: {item_id}}, {mutators: {Action}, pubsub, loaders: {Comments}}) => { const comment = await Comments.get.load(item_id); + if (!comment) { + throw errors.ErrNotFound; + } - let action; try { - action = await Action.create({item_id, item_type: 'COMMENTS', action_type: REACTION}); + const action = await Action.create({item_id, item_type: 'COMMENTS', action_type: REACTION}); + + if (pubsub) { + + // The comment is needed to allow better filtering e.g. by asset_id. + pubsub.publish(`${reaction}ActionCreated`, {action, comment}); + } + + return { + [reaction]: action, + }; } catch (err) { if (err instanceof errors.ErrAlreadyExists) { return err.metadata.existing; @@ -168,16 +180,6 @@ function getReactionConfig(reaction) { throw err; } - - if (pubsub) { - - // The comment is needed to allow better filtering e.g. by asset_id. - pubsub.publish(`${reaction}ActionCreated`, {action, comment}); - } - - return { - [reaction]: action, - }; }, [`delete${Reaction}Action`]: async (_, {input: {id}}, {mutators: {Action}, pubsub, loaders: {Comments}}) => { const action = await Action.delete({id});