user queries

This commit is contained in:
Wyatt Johnson
2017-11-08 13:40:46 -07:00
parent 9e84c72148
commit 1b7f78b562
6 changed files with 163 additions and 130 deletions
+49 -16
View File
@@ -10,6 +10,47 @@ const {
const UsersService = require('../../services/users');
const UserModel = require('../../models/user');
const mergeState = (query, state) => {
const {status} = state;
if (status) {
const {username, banned, suspended} = status;
if (typeof username !== 'undefined' && username && username.length > 0) {
query.merge({
'status.username.status': {
$in: username
}
});
}
if (typeof banned !== 'undefined' && banned !== null) {
query.merge({
'status.banned.status': banned
});
}
if (typeof suspended !== 'undefined' && suspended !== null) {
if (suspended) {
query.merge({
'status.suspension.until': {
$gte: Date.now()
}
});
} else {
query.merge({
$or: [
{'status.suspension.until': null},
{'status.suspension.until': {
$lt: Date.now()
}}
]
});
}
}
}
};
const genUserByIDs = async (context, ids) => {
if (!ids || ids.length === 0) {
return [];
@@ -31,20 +72,16 @@ const genUserByIDs = async (context, ids) => {
* @param {Object} context graph context
* @param {Object} query query terms to apply to the users query
*/
const getUsersByQuery = async ({user, loaders: {Actions}}, {ids, limit, cursor, statuses, action_type, sortOrder}) => {
const getUsersByQuery = async ({user, loaders: {Actions}}, {ids, limit, cursor, state, action_type, sortOrder}) => {
let query = UserModel.find();
if (action_type || statuses) {
if (action_type || state) {
if (!user || !user.can(SEARCH_OTHER_USERS)) {
return null;
}
if (statuses) {
query = query.where({
status: {
$in: statuses
}
});
if (state) {
mergeState(query, state);
} else {
const userIds = await Actions.getByTypes({action_type, item_type: 'USERS'});
ids = ids ? union(ids, userIds) : userIds;
@@ -115,25 +152,21 @@ const getUsersByQuery = async ({user, loaders: {Actions}}, {ids, limit, cursor,
* @return {Promise} resolves to the counts of the users from the
* query
*/
const getCountByQuery = async ({loaders: {Actions}}, {action_type, statuses}) => {
const getCountByQuery = async ({loaders: {Actions}}, {action_type, state}) => {
let query = UserModel.find();
if (action_type) {
const userIds = await Actions.getByTypes({action_type, item_type: 'USERS'});
query = query.find({
query.merge({
id: {
$in: userIds
}
});
}
if (statuses) {
query = query.where({
status: {
$in: statuses
}
});
if (state) {
mergeState(query, state);
}
return UserModel
+2
View File
@@ -13,6 +13,8 @@ const setUserUsernameStatus = async (ctx, id, status) => {
const user = await UsersService.setUsernameStatus(id, status, ctx.user.id);
if (status === 'REJECTED') {
ctx.pubsub.publish('usernameRejected', user);
} else if (status === 'APPROVED') {
ctx.pubsub.publish('usernameApproved', user);
}
};
+106 -114
View File
@@ -7,131 +7,123 @@ const {
SUBSCRIBE_ALL_USER_SUSPENDED,
SUBSCRIBE_ALL_USER_BANNED,
SUBSCRIBE_ALL_USERNAME_REJECTED,
SUBSCRIBE_ALL_USERNAME_APPROVED,
} = require('../perms/constants');
const merge = require('lodash/merge');
const debug = require('debug')('talk:graph:setupFunctions');
const plugins = require('../services/plugins');
const setupFunctions = {
commentAdded: (options, args, comment, context) => {
// Only privileged users can subscribe to all assets.
if (!args.asset_id && (!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_ADDED))) {
return false;
}
// If user subscribes for statuses other than NONE and/or ACCEPTED statuses, it needs
// special privileges.
if (
(!args.statuses || args.statuses.some((status) => !['NONE', 'ACCEPTED'].includes(status))) &&
(!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_ADDED))
) {
return false;
}
if (args.asset_id && comment.asset_id !== args.asset_id) {
return false;
}
if (args.statuses && !args.statuses.includes(comment.status)) {
return false;
}
return true;
},
commentEdited: (options, args, comment, context) => {
if (!args.asset_id && (!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_EDITED))) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
},
commentFlagged: (options, args, comment, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_FLAGGED)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
},
commentAccepted: (options, args, comment, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_ACCEPTED)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
},
commentRejected: (options, args) => (comment, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_REJECTED)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
},
userSuspended: (options, args, user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USER_SUSPENDED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
},
userBanned: (options, args, user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USER_BANNED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
},
usernameRejected: (options, args, user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USERNAME_REJECTED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
},
usernameApproved: (options, args, user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USERNAME_APPROVED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
},
};
/**
* Plugin support requires that we merge in existing setupFunctions with our new
* plugin based ones. This allows plugins to extend existing setupFunctions as well
* as provide new ones.
* plugin based ones. This allows plugins to extend existing setupFunctions as
* well as provide new ones. We'll remap our internal representation of the
* setupFunctions into the format needed by Apollo.
*/
const setupFunctions = plugins.get('server', 'setupFunctions').reduce((acc, {plugin, setupFunctions}) => {
module.exports = plugins.get('server', 'setupFunctions').reduce((acc, {plugin, setupFunctions}) => {
debug(`added plugin '${plugin.name}'`);
return merge(acc, setupFunctions);
}, {
commentAdded: (options, args) => ({
commentAdded: {
filter: (comment, context) => {
}, Object.keys(setupFunctions).map((key) => {
const filter = setupFunctions[key];
// Only privileged users can subscribe to all assets.
if (!args.asset_id && (!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_ADDED))) {
return false;
}
// If user subscribes for statuses other than NONE and/or ACCEPTED statuses, it needs
// special privileges.
if (
(!args.statuses || args.statuses.some((status) => !['NONE', 'ACCEPTED'].includes(status))) &&
(!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_ADDED))
) {
return false;
}
if (args.asset_id && comment.asset_id !== args.asset_id) {
return false;
}
if (args.statuses && !args.statuses.includes(comment.status)) {
return false;
}
return true;
return {
[key]: (options, args) => ({
[key]: {
filter: (user, ctx) => filter(options, args, user, ctx)
}
},
}),
commentEdited: (options, args) => ({
commentEdited: {
filter: (comment, context) => {
if (!args.asset_id && (!context.user || !context.user.can(SUBSCRIBE_ALL_COMMENT_EDITED))) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
}
},
}),
commentFlagged: (options, args) => ({
commentFlagged: {
filter: (comment, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_FLAGGED)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
}
},
}),
commentAccepted: (options, args) => ({
commentAccepted: {
filter: (comment, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_ACCEPTED)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
}
},
}),
commentRejected: (options, args) => ({
commentRejected: {
filter: (comment, context) => {
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_REJECTED)) {
return false;
}
return !args.asset_id || comment.asset_id === args.asset_id;
}
},
}),
userSuspended: (options, args) => ({
userSuspended: {
filter: (user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USER_SUSPENDED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
}
},
}),
userBanned: (options, args) => ({
userBanned: {
filter: (user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USER_BANNED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
}
},
}),
usernameRejected: (options, args) => ({
usernameRejected: {
filter: (user, context) => {
if (
!context.user
|| args.user_id !== user.id && !context.user.can(SUBSCRIBE_ALL_USERNAME_REJECTED)
) {
return false;
}
return !args.user_id || user.id === args.user_id;
}
},
}),
});
module.exports = setupFunctions;
})
};
})
.reduce((setupFunction, setupFunctions) => {
return merge(setupFunctions, setupFunction);
}, {}));
+4
View File
@@ -1492,6 +1492,10 @@ type Subscription {
# `user_id` must match id of current user except for
# users with the `ADMIN` or `MODERATOR` role.
usernameRejected(user_id: ID): User
# Gen an update whenever a username has been approved. `user_id` must match id
# of current user except for users with the `ADMIN` or `MODERATOR` role.
usernameApproved(user_id: ID): User
}
################################################################################
+1
View File
@@ -7,4 +7,5 @@ module.exports = {
SUBSCRIBE_ALL_USER_SUSPENDED: 'SUBSCRIBE_ALL_USER_SUSPENDED',
SUBSCRIBE_ALL_USER_BANNED: 'SUBSCRIBE_ALL_USER_BANNED',
SUBSCRIBE_ALL_USERNAME_REJECTED: 'SUBSCRIBE_ALL_USERNAME_REJECTED',
SUBSCRIBE_ALL_USERNAME_APPROVED: 'SUBSCRIBE_ALL_USERNAME_APPROVED'
};
+1
View File
@@ -11,6 +11,7 @@ module.exports = (user, perm) => {
case types.SUBSCRIBE_ALL_USER_SUSPENDED:
case types.SUBSCRIBE_ALL_USER_BANNED:
case types.SUBSCRIBE_ALL_USERNAME_REJECTED:
case types.SUBSCRIBE_ALL_USERNAME_APPROVED:
return check(user, ['ADMIN', 'MODERATOR']);
default: