mirror of
https://github.com/wassname/talk.git
synced 2026-07-20 12:40:47 +08:00
saving my place so i dont have too many threads
This commit is contained in:
@@ -38,6 +38,8 @@ class LayoutContainer extends Component {
|
||||
}
|
||||
if (roleUtils.canAccessAdmin(user) && loggedIn) {
|
||||
return <Layout handleLogout={handleLogout} toggleShortcutModal={toggleShortcutModal} {...this.props} />;
|
||||
} else if (loggedIn) {
|
||||
return <p>you do not have permission to see this page.</p>;
|
||||
}
|
||||
return <FullLoading />;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
import includes from 'lodash/includes';
|
||||
import intersection from 'lodash/intersection';
|
||||
|
||||
export default {
|
||||
canAccessConfig: (user) => includes(user.roles, 'ADMIN'),
|
||||
canChangeRoles: user => includes(user.roles, 'ADMIN'),
|
||||
hasStaffTag: user => includes(user.roles, 'ADMIN', 'MODERATOR', 'STAFF'),
|
||||
canViewUserEmails: user => includes(user.roles, 'ADMIN'),
|
||||
canModerate: user => includes(user.roles, 'ADMIN', 'MODERATOR'),
|
||||
canAccessAdmin: user => includes(user.roles, 'ADMIN', 'MODERATOR')
|
||||
const basicRoles = {
|
||||
hasStaffTag: ['ADMIN', 'MODERATOR', 'STAFF']
|
||||
};
|
||||
|
||||
const queryRoles = {
|
||||
canAccessConfig: ['ADMIN', 'MODERATOR'],
|
||||
canAccessAdmin: ['ADMIN', 'MODERATOR'],
|
||||
canViewUserEmails: ['ADMIN']
|
||||
};
|
||||
|
||||
const mutationRoles = {
|
||||
canChangeRoles: ['ADMIN'],
|
||||
canModerateComments: ['ADMIN', 'MODERATOR']
|
||||
};
|
||||
|
||||
const roles = {...basicRoles, ...queryRoles, ...mutationRoles};
|
||||
|
||||
export const can = (user, perms) => {
|
||||
for (let perm in perms) {
|
||||
const role = roles[perm];
|
||||
if (typeof role === 'undefined') {
|
||||
continue;
|
||||
}
|
||||
let grant = intersection(role, user.roles).length > 0;
|
||||
return grant;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ const Action = {
|
||||
// This will load the user for the specific action. We'll limit this to the
|
||||
// admin users only or the current logged in user.
|
||||
user({user_id}, _, {loaders: {Users}, user}) {
|
||||
if (user && (user.hasRole('ADMIN') || user_id === user.id)) {
|
||||
if (user && (user.canViewOtherUsers() || user_id === user.id)) {
|
||||
return Users.getByID.load(user_id);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-7
@@ -2,6 +2,7 @@ const mongoose = require('../services/mongoose');
|
||||
const bcrypt = require('bcrypt');
|
||||
const uuid = require('uuid');
|
||||
const intersection = require('lodash/intersection');
|
||||
const can = require('../perms');
|
||||
|
||||
// USER_ROLES is the array of roles that is permissible as a user role.
|
||||
const USER_ROLES = [
|
||||
@@ -269,13 +270,7 @@ const USER_GRAPH_OPERATIONS = [
|
||||
* operation.
|
||||
*/
|
||||
UserSchema.method('can', function(...actions) {
|
||||
if (actions.some((action) => USER_GRAPH_OPERATIONS.indexOf(action) === -1)) {
|
||||
throw new Error(`invalid actions: ${actions}`);
|
||||
}
|
||||
|
||||
if (this.status === 'BANNED') {
|
||||
return false;
|
||||
}
|
||||
return can(this, null, actions);
|
||||
|
||||
if (actions.some((action) => action === 'mutation:setUserStatus' || action === 'mutation:suspendUser' || action === 'mutation:setCommentStatus') && !this.canSetUserStatus()) {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
const root = require('./rootReducer');
|
||||
const queries = require('./queryReducer');
|
||||
const mutations = require('./mutationReducer');
|
||||
|
||||
const reducers = [
|
||||
root.reducer,
|
||||
queries.reducer,
|
||||
mutations.reducer
|
||||
];
|
||||
|
||||
const allPermissions = [...root.constants, ...queries.constants, ...mutations.constants];
|
||||
|
||||
const findGrant = (user, perms, context, initialState) => {
|
||||
return perms.every(perm => {
|
||||
|
||||
for (let reducer in reducers) {
|
||||
const grant = reducer(user, perm, context, initialState);
|
||||
|
||||
if (grant !== null && typeof grant !== 'undefined') {
|
||||
return grant;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* returns true, false, or null depending on whether the user has those permissions
|
||||
* throws an error if you pass a permission that's not known to the system
|
||||
* @param {User} user the user making the request for db operations
|
||||
* @param {[type]} context [description]
|
||||
* @param {String/Array} perms a string an array of strings which are the names of the permissions
|
||||
* @return {Boolean}
|
||||
*/
|
||||
module.exports = (user, context, ...perms) => {
|
||||
|
||||
// make sure all the passed permissions are not typos
|
||||
const missingPerms = perms.filter(perm => {
|
||||
return typeof allPermissions[perm] === 'undefined';
|
||||
});
|
||||
|
||||
if (missingPerms.length) {
|
||||
throw new Error(`${missingPerms.join(' ')} are not valid permissions.`);
|
||||
}
|
||||
|
||||
return findGrant(user, perms, context, null);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
const intersection = require('lodash/intersection');
|
||||
const check = (user, roles) => {
|
||||
return !!intersection(roles, user.roles).length;
|
||||
};
|
||||
|
||||
const CREATE_COMMENT = 'CREATE_COMMENT';
|
||||
const CREATE_ACTION = 'CREATE_ACTION';
|
||||
const DELETE_ACTION = 'DELETE_ACTION';
|
||||
const EDIT_NAME = 'EDIT_NAME';
|
||||
const SET_USER_STATUS = 'SET_USER_STATUS';
|
||||
const SUSPEND_USER = 'SUSPEND_USER';
|
||||
const SET_COMMENT_STATUS = 'SET_COMMENT_STATUS';
|
||||
const ADD_COMMENT_TAG = 'ADD_COMMENT_TAG';
|
||||
const REMOVE_COMMENT_TAG = 'REMOVE_COMMENT_TAG';
|
||||
const UPDATE_CONFIG = 'UPDATE_CONFIG';
|
||||
|
||||
module.exports = {
|
||||
constants: [
|
||||
CREATE_COMMENT, CREATE_ACTION, DELETE_ACTION, EDIT_NAME, SET_USER_STATUS,
|
||||
SUSPEND_USER, SET_COMMENT_STATUS, ADD_COMMENT_TAG, REMOVE_COMMENT_TAG, UPDATE_CONFIG
|
||||
],
|
||||
reducer: (user, perm, context, initialState) => {
|
||||
switch (perm) {
|
||||
case 'muation:createComment':
|
||||
return true;
|
||||
case 'mutation:createAction':
|
||||
return true;
|
||||
case 'mutation:deleteAction':
|
||||
return true;
|
||||
case 'mutation:editName':
|
||||
return true;
|
||||
case 'mutation:setUserStatus':
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case 'mutation:suspendUser':
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case 'mutation:setCommentStatus':
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case 'mutation:addCommentTag':
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case 'mutation:removeCommentTag':
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case 'mutation:updateConfig':
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
default:
|
||||
return initialState;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
const intersection = require('lodash/intersection');
|
||||
const check = (user, roles) => {
|
||||
return !!intersection(roles, user.roles).length;
|
||||
};
|
||||
|
||||
const SEARCH_ASSETS = 'SEARCH_ASSETS';
|
||||
const SEARCH_OTHER_USERS = 'SEARCH_OTHER_USERS';
|
||||
const SEARCH_ACTIONS = 'SEARCH_ACTIONS';
|
||||
const SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS = 'SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS';
|
||||
const SEARCH_OTHERS_COMMENTS = 'SEARCH_OTHERS_COMMENTS';
|
||||
const SEARCH_COMMENT_METRICS = 'SEARCH_COMMENT_METRICS';
|
||||
|
||||
module.exports = {
|
||||
constants: [
|
||||
SEARCH_ASSETS, SEARCH_OTHER_USERS, SEARCH_ACTIONS, SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS,
|
||||
SEARCH_OTHERS_COMMENTS, SEARCH_COMMENT_METRICS
|
||||
],
|
||||
reducer: (perm, user, context, initialState) => {
|
||||
switch (perm) {
|
||||
case SEARCH_ASSETS:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case SEARCH_OTHER_USERS:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case SEARCH_ACTIONS:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case SEARCH_NON_NULL_OR_ACCEPTED_COMMENTS:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case SEARCH_OTHERS_COMMENTS:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
case SEARCH_COMMENT_METRICS:
|
||||
return check(user, ['ADMIN', 'MODERATOR']);
|
||||
default:
|
||||
return initialState;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
constants: [],
|
||||
reducer: (perm, user, context, initialState) => {
|
||||
|
||||
// this runs before everything
|
||||
if (user.status === 'BANNED') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return initialState;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user