mirror of
https://github.com/wassname/talk.git
synced 2026-06-29 19:01:47 +08:00
Addressing CSRF and user status issues.
This commit is contained in:
@@ -6,10 +6,9 @@ import * as userTypes from '../constants/users';
|
||||
*/
|
||||
// change status of a user
|
||||
export const userStatusUpdate = (status, userId, commentId) => {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch) => {
|
||||
dispatch({type: userTypes.UPDATE_STATUS_REQUEST});
|
||||
const _csrf = getState().auth.get('_csrf');
|
||||
return coralApi(`/users/${userId}/status`, {method: 'POST', body: {status: status, comment_id: commentId}, _csrf})
|
||||
return coralApi(`/users/${userId}/status`, {method: 'POST', body: {status: status, comment_id: commentId}})
|
||||
.then(res => dispatch({type: userTypes.UPDATE_STATUS_SUCCESS, res}))
|
||||
.catch(error => dispatch({type: userTypes.UPDATE_STATUS_FAILURE, error}));
|
||||
};
|
||||
@@ -17,9 +16,8 @@ export const userStatusUpdate = (status, userId, commentId) => {
|
||||
|
||||
// change status of a user
|
||||
export const sendNotificationEmail = (userId, subject, body) => {
|
||||
return (dispatch, getState) => {
|
||||
const _csrf = getState().auth.get('_csrf');
|
||||
return coralApi(`/users/${userId}/email`, {method: 'POST', body: {subject, body}, _csrf})
|
||||
return (dispatch) => {
|
||||
return coralApi(`/users/${userId}/email`, {method: 'POST', body: {subject, body}})
|
||||
.catch(error => dispatch({type: userTypes.USER_EMAIL_FAILURE, error}));
|
||||
};
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ const BanUserDialog = ({open, handleClose, onClickBanUser, user = {}}) => (
|
||||
<Button cStyle="cancel" className={styles.cancel} onClick={() => handleClose()} full>
|
||||
{lang.t('bandialog.cancel')}
|
||||
</Button>
|
||||
<Button cStyle="black" onClick={() => onClickBanUser(user.userId, user.commentId)} full>
|
||||
<Button cStyle="black" onClick={() => onClickBanUser('banned', user.userId, user.commentId)} full>
|
||||
{lang.t('bandialog.yes_ban_user')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -55,7 +55,7 @@ const Comment = props => {
|
||||
|
||||
// Get the button of the action performed over a comment if any
|
||||
const getActionButton = (option, i, props) => {
|
||||
const {comment, author, menuOptionsMap, action} = props;
|
||||
const {comment, author, menuOptionsMap} = props;
|
||||
const status = comment.status;
|
||||
const flagged = comment.flagged;
|
||||
const banned = (author.status === 'banned');
|
||||
@@ -83,7 +83,7 @@ const getActionButton = (option, i, props) => {
|
||||
cStyle={option}
|
||||
icon={menuOption.icon}
|
||||
key={i}
|
||||
onClick={() => props.onClickAction(menuOption.status, comment, action)}
|
||||
onClick={() => props.onClickAction(menuOption.status, comment, {item_type: 'comment'})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -137,8 +137,8 @@ export default class ModerationList extends React.Component {
|
||||
// If a user bio or name is rejected, bring up a dialog before suspending them.
|
||||
if (menuOption === 'rejected') {
|
||||
this.setState({suspendUserModal: action});
|
||||
} else {
|
||||
this.props.userStatusUpdate(menuOption, action.item_id);
|
||||
} else if (menuOption === 'accepted') {
|
||||
this.props.userStatusUpdate('active', action.item_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ const UserAction = props => {
|
||||
let userStatus = user.status;
|
||||
const links = user.settings.bio ? linkify.getMatches(user.settings.bio) : [];
|
||||
|
||||
return (
|
||||
//Do not display if the user status is 'active'. This means that they have already been reviewed and approved.
|
||||
|
||||
return userStatus !== 'active' &&
|
||||
<li tabIndex={props.index} className={`${styles.listItem} ${props.isActive && !props.hideActive ? styles.activeItem : ''}`}>
|
||||
<div className={styles.itemHeader}>
|
||||
<div className={styles.author}>
|
||||
@@ -55,8 +57,7 @@ const UserAction = props => {
|
||||
<div className={styles.flagCount}>
|
||||
{`${action.count} ${action.action_type === 'flag_bio' ? lang.t('user.bio_flags') : lang.t('user.username_flags')}`}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
</li>;
|
||||
};
|
||||
|
||||
export default UserAction;
|
||||
@@ -71,17 +72,14 @@ const getActionButton = (option, i, props) => {
|
||||
return null;
|
||||
}
|
||||
if (option === 'ban') {
|
||||
return (
|
||||
<Button
|
||||
return <Button
|
||||
className='ban'
|
||||
cStyle='black'
|
||||
disabled={banned ? 'disabled' : ''}
|
||||
onClick={() => onClickShowBanDialog(user.id, user.displayName)}
|
||||
key={i}
|
||||
>
|
||||
key={i}>
|
||||
{lang.t('comment.ban_user')}
|
||||
</Button>
|
||||
);
|
||||
</Button>;
|
||||
}
|
||||
const menuOption = menuOptionsMap[option];
|
||||
return (
|
||||
|
||||
@@ -96,10 +96,9 @@ const mapDispatchToProps = dispatch => {
|
||||
fetchModerationQueueComments: () => dispatch(fetchModerationQueueComments()),
|
||||
showBanUserDialog: (userId, userName, commentId) => dispatch(showBanUserDialog(userId, userName, commentId)),
|
||||
hideBanUserDialog: () => dispatch(hideBanUserDialog(false)),
|
||||
banUser: (userId, commentId) => dispatch(userStatusUpdate('banned', userId, commentId)).then(() => {
|
||||
userStatusUpdate: (status, userId, commentId) => dispatch(userStatusUpdate(status, userId, commentId)).then(() => {
|
||||
dispatch(fetchModerationQueueComments());
|
||||
}),
|
||||
userStatusUpdate: (status, userId, commentId) => dispatch(userStatusUpdate(status, userId, commentId)),
|
||||
suspendUser: (userId, subject, text) => dispatch(userStatusUpdate('suspended', userId))
|
||||
.then(() => dispatch(sendNotificationEmail(userId, subject, text)))
|
||||
.then(() => dispatch(fetchModerationQueueComments()))
|
||||
|
||||
@@ -42,7 +42,7 @@ export default (props) => (
|
||||
<BanUserDialog
|
||||
open={props.comments.showBanUserDialog}
|
||||
handleClose={props.hideBanUserDialog}
|
||||
onClickBanUser={props.banUser}
|
||||
onClickBanUser={props.userStatusUpdate}
|
||||
user={props.comments.banUser}
|
||||
/>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@ export default (props) => (
|
||||
<BanUserDialog
|
||||
open={props.comments.showBanUserDialog}
|
||||
handleClose={props.hideBanUserDialog}
|
||||
onClickBanUser={props.banUser}
|
||||
onClickBanUser={props.userStatusUpdate}
|
||||
user={props.comments.banUser}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +125,6 @@ router.post('/', (req, res, next) => {
|
||||
});
|
||||
|
||||
router.post('/:user_id/actions', authorization.needed(), (req, res, next) => {
|
||||
|
||||
const {
|
||||
action_type,
|
||||
metadata
|
||||
@@ -133,6 +132,16 @@ router.post('/:user_id/actions', authorization.needed(), (req, res, next) => {
|
||||
|
||||
User
|
||||
.addAction(req.params.user_id, req.user.id, action_type, metadata)
|
||||
.then((action) => {
|
||||
|
||||
// Set the user status to "pending" for review by moderators
|
||||
if (action_type.slice(0, 4) === 'flag') {
|
||||
return User.setStatus(req.user.id, 'pending')
|
||||
.then(() => action);
|
||||
} else {
|
||||
return action;
|
||||
}
|
||||
})
|
||||
.then((action) => {
|
||||
res.status(201).json(action);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user