From 14b483d0894a07ca16b37da71158194f74e93be9 Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Thu, 11 May 2017 14:23:02 -0600 Subject: [PATCH] create roles helper --- client/coral-admin/src/actions/auth.js | 8 +++----- client/coral-admin/src/containers/LayoutContainer.js | 7 ++++--- client/coral-admin/src/reducers/auth.js | 2 -- client/coral-embed-stream/src/components/Embed.js | 5 +++-- client/coral-embed-stream/src/components/Stream.js | 5 +++-- client/coral-framework/actions/auth.js | 7 +++---- client/coral-framework/reducers/auth.js | 6 +----- client/coral-framework/utils/roles.js | 10 ++++++++++ services/users.js | 11 ++++------- 9 files changed, 31 insertions(+), 30 deletions(-) create mode 100644 client/coral-framework/utils/roles.js diff --git a/client/coral-admin/src/actions/auth.js b/client/coral-admin/src/actions/auth.js index 89b56d4dc..68da3577e 100644 --- a/client/coral-admin/src/actions/auth.js +++ b/client/coral-admin/src/actions/auth.js @@ -14,8 +14,7 @@ export const handleLogin = (email, password, recaptchaResponse) => dispatch => { return dispatch(checkLoginFailure('not logged in')); } - const isAdmin = !!user.roles.filter(i => i === 'ADMIN').length; - dispatch(checkLoginSuccess(user, isAdmin)); + dispatch(checkLoginSuccess(user)); }) .catch(error => { @@ -41,7 +40,7 @@ export const requestPasswordReset = email => dispatch => { // Check Login const checkLoginRequest = () => ({type: actions.CHECK_LOGIN_REQUEST}); -const checkLoginSuccess = (user, isAdmin) => ({type: actions.CHECK_LOGIN_SUCCESS, user, isAdmin}); +const checkLoginSuccess = (user) => ({type: actions.CHECK_LOGIN_SUCCESS, user}); const checkLoginFailure = error => ({type: actions.CHECK_LOGIN_FAILURE, error}); export const checkLogin = () => dispatch => { @@ -52,8 +51,7 @@ export const checkLogin = () => dispatch => { return dispatch(checkLoginFailure('not logged in')); } - const isAdmin = !!user.roles.filter(i => i === 'ADMIN').length; - dispatch(checkLoginSuccess(user, isAdmin)); + dispatch(checkLoginSuccess(user)); }) .catch(error => { console.error(error); diff --git a/client/coral-admin/src/containers/LayoutContainer.js b/client/coral-admin/src/containers/LayoutContainer.js index 42e2baade..fea730c98 100644 --- a/client/coral-admin/src/containers/LayoutContainer.js +++ b/client/coral-admin/src/containers/LayoutContainer.js @@ -6,6 +6,7 @@ import {toggleModal as toggleShortcutModal} from '../actions/moderation'; import {fetchConfig} from '../actions/config'; import {FullLoading} from '../components/FullLoading'; import AdminLogin from '../components/AdminLogin'; +import roleUtils from 'coral-framework/utils/roles'; class LayoutContainer extends Component { componentWillMount () { @@ -16,7 +17,7 @@ class LayoutContainer extends Component { } render () { const { - isAdmin, + user, loggedIn, loadingUser, loginError, @@ -26,7 +27,7 @@ class LayoutContainer extends Component { const {handleLogout, toggleShortcutModal, TALK_RECAPTCHA_PUBLIC} = this.props; if (loadingUser) { return ; } - if (!isAdmin) { + if (roleUtils.canAccessAdmin(user)) { return ; } - if (isAdmin && loggedIn) { + if (roleUtils.canAccessAdmin(user) && loggedIn) { return ; } return ; diff --git a/client/coral-admin/src/reducers/auth.js b/client/coral-admin/src/reducers/auth.js index a7054ddfa..2bd42d112 100644 --- a/client/coral-admin/src/reducers/auth.js +++ b/client/coral-admin/src/reducers/auth.js @@ -4,7 +4,6 @@ import * as actions from '../constants/auth'; const initialState = Map({ loggedIn: false, user: null, - isAdmin: false, loginError: null, loginMaxExceeded: false, passwordRequestSuccess: null @@ -24,7 +23,6 @@ export default function auth (state = initialState, action) { return state .set('loggedIn', true) .set('loadingUser', false) - .set('isAdmin', action.isAdmin) .set('user', action.user); case actions.LOGOUT_SUCCESS: return initialState; diff --git a/client/coral-embed-stream/src/components/Embed.js b/client/coral-embed-stream/src/components/Embed.js index 0d26cf740..908fd4a90 100644 --- a/client/coral-embed-stream/src/components/Embed.js +++ b/client/coral-embed-stream/src/components/Embed.js @@ -1,6 +1,7 @@ import React from 'react'; import I18n from 'coral-framework/modules/i18n/i18n'; import translations from 'coral-framework/translations'; +import rolesHelper from 'coral-framework/utils/roles'; const lang = new I18n(translations); import {TabBar, Tab, TabContent, Button} from 'coral-ui'; @@ -38,7 +39,7 @@ export default class Embed extends React.Component { render () { const {activeTab, logout, viewAllComments, commentId} = this.props; const {asset: {totalCommentCount}} = this.props.root; - const {loggedIn, isAdmin, user} = this.props.auth; + const {loggedIn, user} = this.props.auth; const userBox = ; @@ -48,7 +49,7 @@ export default class Embed extends React.Component { {lang.t('myProfile')} - Configure Stream + Configure Stream { commentId && diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js index 46ac75dca..7efadc921 100644 --- a/client/coral-embed-stream/src/components/Stream.js +++ b/client/coral-embed-stream/src/components/Stream.js @@ -11,6 +11,7 @@ import QuestionBox from 'coral-plugin-questionbox/QuestionBox'; import IgnoredCommentTombstone from './IgnoredCommentTombstone'; import SuspendedAccount from 'coral-framework/components/SuspendedAccount'; import RestrictedContent from 'coral-framework/components/RestrictedContent'; +import rolesHelper from 'coral-framework/utils/roles'; import ChangeUsernameContainer from 'coral-sign-in/containers/ChangeUsernameContainer'; @@ -37,7 +38,7 @@ class Stream extends React.Component { removeCommentTag, pluginProps, ignoreUser, - auth: {loggedIn, isAdmin, user}, + auth: {loggedIn, user}, commentCountCache, editName } = this.props; @@ -111,7 +112,7 @@ class Stream extends React.Component { {loggedIn && user && } - {loggedIn && } + {loggedIn && } {/* the highlightedComment is isolated after the user followed a permalink */} {highlightedComment diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index d689aeb63..527369b60 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -108,7 +108,7 @@ export const cleanState = () => ({type: actions.CLEAN_STATE}); const signInRequest = () => ({type: actions.FETCH_SIGNIN_REQUEST}); // TODO: revisit login redux flow. -// const signInSuccess = (user, isAdmin) => ({type: actions.FETCH_SIGNIN_SUCCESS, user, isAdmin}); +// const signInSuccess = (user) => ({type: actions.FETCH_SIGNIN_SUCCESS, user}); // const signInFailure = error => ({type: actions.FETCH_SIGNIN_FAILURE, error}); @@ -236,7 +236,7 @@ export const invalidForm = error => ({type: actions.INVALID_FORM, error}); // Check Login const checkLoginRequest = () => ({type: actions.CHECK_LOGIN_REQUEST}); -const checkLoginSuccess = (user, isAdmin) => ({type: actions.CHECK_LOGIN_SUCCESS, user, isAdmin}); +const checkLoginSuccess = (user) => ({type: actions.CHECK_LOGIN_SUCCESS, user}); const checkLoginFailure = error => ({type: actions.CHECK_LOGIN_FAILURE, error}); export const checkLogin = () => dispatch => { @@ -247,8 +247,7 @@ export const checkLogin = () => dispatch => { throw new Error('Not logged in'); } - const isAdmin = !!result.user.roles.filter(i => i === 'ADMIN').length; - dispatch(checkLoginSuccess(result.user, isAdmin)); + dispatch(checkLoginSuccess(result.user)); }) .catch(error => { console.error(error); diff --git a/client/coral-framework/reducers/auth.js b/client/coral-framework/reducers/auth.js index 83ea49ce5..5ac862431 100644 --- a/client/coral-framework/reducers/auth.js +++ b/client/coral-framework/reducers/auth.js @@ -4,7 +4,6 @@ import * as actions from '../constants/auth'; const initialState = Map({ isLoading: false, loggedIn: false, - isAdmin: false, user: null, showSignInDialog: false, showCreateUsernameDialog: false, @@ -79,12 +78,10 @@ export default function auth (state = initialState, action) { return state .set('checkedInitialLogin', true) .set('loggedIn', true) - .set('isAdmin', action.isAdmin) .set('user', purge(action.user)); case actions.FETCH_SIGNIN_SUCCESS: return state .set('loggedIn', true) - .set('isAdmin', action.isAdmin) .set('user', purge(action.user)); case actions.FETCH_SIGNIN_FAILURE: return state @@ -120,8 +117,7 @@ export default function auth (state = initialState, action) { return state .set('user', null) .set('isLoading', false) - .set('loggedIn', false) - .set('isAdmin', false); + .set('loggedIn', false); case actions.INVALID_FORM: return state .set('error', action.error); diff --git a/client/coral-framework/utils/roles.js b/client/coral-framework/utils/roles.js new file mode 100644 index 000000000..b457ff1b3 --- /dev/null +++ b/client/coral-framework/utils/roles.js @@ -0,0 +1,10 @@ +import includes from 'lodash/includes'; + +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') +}; diff --git a/services/users.js b/services/users.js index 14301ccf4..246d3fded 100644 --- a/services/users.js +++ b/services/users.js @@ -395,13 +395,10 @@ module.exports = class UsersService { return Promise.reject(new Error(`role ${role} is not supported`)); } - return UserModel.update({ - id: id - }, { - $addToSet: { - roles: role - } - }); + // 5.11.2017 - Restricting this to a hierarchical system like WordPress + // where you can only set one role at a time. + // I'm not changing the data structure here, because I don't want a migration + return UserModel.update({id}, {$set: {roles: [role]}}); } /**