added support for user assigned_by fields to get resolved

This commit is contained in:
Wyatt Johnson
2017-11-23 10:53:20 -07:00
parent 6e6ddbf378
commit 6119503057
9 changed files with 117 additions and 37 deletions
+2 -2
View File
@@ -40,11 +40,11 @@ const stopIgnoringUser = ({user}, userToStopIgnoring) => {
};
const changeUsername = async (ctx, id, username) => {
return UsersService.changeUsername(id, username);
return UsersService.changeUsername(id, username, ctx.user.id);
};
const setUsername = async (ctx, id, username) => {
return UsersService.setUsername(id, username);
return UsersService.setUsername(id, username, ctx.user.id);
};
module.exports = (ctx) => {
+7
View File
@@ -0,0 +1,7 @@
const {decorateUserField} = require('./util');
const BannedStatusHistory = {};
decorateUserField(BannedStatusHistory, 'assigned_by');
module.exports = BannedStatusHistory;
+3 -9
View File
@@ -1,13 +1,7 @@
const {SEARCH_OTHER_USERS} = require('../../perms/constants');
const {decorateUserField} = require('./util');
const CommentStatusHistory = {
assigned_by({assigned_by}, _, {user, loaders: {Users}}) {
if (!user || !user.can(SEARCH_OTHER_USERS) || assigned_by == null) {
return null;
}
const CommentStatusHistory = {};
return Users.getByID.load(assigned_by);
}
};
decorateUserField(CommentStatusHistory, 'assigned_by');
module.exports = CommentStatusHistory;
+18 -14
View File
@@ -1,56 +1,60 @@
const _ = require('lodash');
const debug = require('debug')('talk:graph:resolvers');
const ActionSummary = require('./action_summary');
const Action = require('./action');
const AssetActionSummary = require('./asset_action_summary');
const ActionSummary = require('./action_summary');
const Asset = require('./asset');
const CommentStatusHistory = require('./comment_status_history');
const AssetActionSummary = require('./asset_action_summary');
const BannedStatusHistory = require('./banned_status_history');
const Comment = require('./comment');
const CommentStatusHistory = require('./comment_status_history');
const Cursor = require('./cursor');
const Date = require('./date');
const FlagActionSummary = require('./flag_action_summary');
const FlagAction = require('./flag_action');
const DontAgreeAction = require('./dont_agree_action');
const DontAgreeActionSummary = require('./dont_agree_action_summary');
const FlagAction = require('./flag_action');
const FlagActionSummary = require('./flag_action_summary');
const GenericUserError = require('./generic_user_error');
const RootMutation = require('./root_mutation');
const RootQuery = require('./root_query');
const Settings = require('./settings');
const Subscription = require('./subscription');
const TagLink = require('./tag_link');
const Tag = require('./tag');
const UserError = require('./user_error');
const TagLink = require('./tag_link');
const User = require('./user');
const UserError = require('./user_error');
const UserState = require('./user_state');
const UsernameStatusHistory = require('./username_status_history');
const ValidationUserError = require('./validation_user_error');
const plugins = require('../../services/plugins');
// Provide the core resolvers.
let resolvers = {
ActionSummary,
Action,
AssetActionSummary,
ActionSummary,
Asset,
CommentStatusHistory,
AssetActionSummary,
BannedStatusHistory,
Comment,
CommentStatusHistory,
Cursor,
Date,
FlagActionSummary,
FlagAction,
DontAgreeAction,
DontAgreeActionSummary,
FlagAction,
FlagActionSummary,
GenericUserError,
RootMutation,
RootQuery,
Settings,
Subscription,
TagLink,
Tag,
UserError,
TagLink,
User,
UserError,
UserState,
UsernameStatusHistory,
ValidationUserError,
};
@@ -0,0 +1,7 @@
const {decorateUserField} = require('./util');
const SuspensionStatusHistory = {};
decorateUserField(SuspensionStatusHistory, 'assigned_by');
module.exports = SuspensionStatusHistory;
@@ -0,0 +1,7 @@
const {decorateUserField} = require('./util');
const UsernameStatusHistory = {};
decorateUserField(UsernameStatusHistory, 'assigned_by');
module.exports = UsernameStatusHistory;
+39 -2
View File
@@ -1,4 +1,8 @@
const {ADD_COMMENT_TAG} = require('../../perms/constants');
const {
ADD_COMMENT_TAG,
SEARCH_OTHER_USERS,
} = require('../../perms/constants');
const property = require('lodash/property');
/**
* Decorates the typeResolver with the tags field.
@@ -22,7 +26,7 @@ const decorateWithTags = (typeResolver) => {
*/
const decorateWithPermissionCheck = (typeResolver, protect) => {
for (const [field, permissions] of Object.entries(protect)) {
let fieldResolver = (obj) => obj[field];
let fieldResolver = property(field);
if (field in typeResolver) {
fieldResolver = typeResolver[field];
}
@@ -37,7 +41,40 @@ const decorateWithPermissionCheck = (typeResolver, protect) => {
}
};
/**
* decorateUserField will decorate the user field accesses with correct
* permission checks.
*
* @param {Object} typeResolver the type resolver
* @param {String} field the field to decorate
*/
const decorateUserField = (typeResolver, field) => {
// The default resolver for the user decorator is loading the user by id.
let fieldResolver = (obj, args, ctx) =>
ctx.loaders.Users.getByID.get(obj[field]);
// The resolver can be overridden however. This decorator will simply wrap the
// field with a permission check.
if (field in typeResolver) {
fieldResolver = typeResolver[field];
}
typeResolver[field] = (obj, args, ctx, info) => {
if (
!ctx.user ||
obj[field] === null ||
(ctx.user.id !== obj[field] && !ctx.user.can(SEARCH_OTHER_USERS))
) {
return null;
}
return fieldResolver(obj, args, ctx, info);
};
};
module.exports = {
decorateUserField,
decorateWithTags,
decorateWithPermissionCheck,
};
+6 -6
View File
@@ -209,7 +209,7 @@ class UsersService {
return user;
}
static async _setUsername(id, username, fromStatus, toStatus, resetAllowed = false) {
static async _setUsername(id, username, fromStatus, toStatus, assignedBy, resetAllowed = false) {
try {
const query = {
id,
@@ -228,7 +228,7 @@ class UsersService {
$push: {
'status.username.history': {
status: toStatus,
assigned_by: id,
assigned_by: assignedBy,
created_at: Date.now()
}
}
@@ -265,12 +265,12 @@ class UsersService {
}
}
static async setUsername(id, username) {
return UsersService._setUsername(id, username, 'UNSET', 'SET', true);
static async setUsername(id, username, assignedBy) {
return UsersService._setUsername(id, username, 'UNSET', 'SET', assignedBy, true);
}
static async changeUsername(id, username) {
return UsersService._setUsername(id, username, 'REJECTED', 'CHANGED');
static async changeUsername(id, username, assignedBy) {
return UsersService._setUsername(id, username, 'REJECTED', 'CHANGED', assignedBy);
}
/**
+28 -4
View File
@@ -26,6 +26,24 @@ describe('graph.mutations.changeUsername', () => {
}
}
}
query User {
me {
state {
status {
username {
history {
status
assigned_by {
username
}
created_at
}
}
}
}
}
}
`;
[
@@ -44,7 +62,7 @@ describe('graph.mutations.changeUsername', () => {
let res = await graphql(schema, changeUsernameMutation, {}, ctx, {
user_id: user.id,
username,
});
}, 'ChangeUsername');
if (res.errors && res.errors.length > 0) {
console.error(res.errors);
@@ -65,7 +83,7 @@ describe('graph.mutations.changeUsername', () => {
res = await graphql(schema, changeUsernameMutation, {}, ctx, {
user_id: user.id,
username,
});
}, 'ChangeUsername');
if (res.errors && res.errors.length > 0) {
console.error(res.errors);
@@ -74,9 +92,15 @@ describe('graph.mutations.changeUsername', () => {
expect(res.errors).to.be.undefined;
expect(res.data.changeUsername).to.be.null;
user = await UsersService.findById(user.id);
res = await graphql(schema, changeUsernameMutation, {}, ctx, {}, 'User');
expect(user.status.username.status, 'CHANGED');
if (res.errors && res.errors.length > 0) {
console.error(res.errors);
}
expect(res.errors).to.be.undefined;
expect(res.data.me.state.status.username.status, 'CHANGED');
});
});
});