mirror of
https://github.com/wassname/talk.git
synced 2026-08-13 12:40:11 +08:00
Extend backend to support new suspend feature
This commit is contained in:
@@ -52,7 +52,7 @@ class SuspendUserDialog extends Component {
|
||||
const cancel = this.props.handleClose;
|
||||
const next = () => this.setState({stage: stage + 1});
|
||||
const suspend = () => {
|
||||
suspendUser({userId: user.user.id, message: this.state.email})
|
||||
suspendUser({id: user.user.id, message: this.state.email, mustChangeUsername: true})
|
||||
.then(() => {
|
||||
this.props.handleClose();
|
||||
});
|
||||
@@ -79,7 +79,7 @@ class SuspendUserDialog extends Component {
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
onCancel={handleClose}
|
||||
title={lang.t('suspenduser.title')}>
|
||||
title={lang.t('suspenduser.suspend_user')}>
|
||||
<div className={styles.title}>
|
||||
{lang.t(stages[stage].title, lang.t('suspenduser.username'))}
|
||||
</div>
|
||||
|
||||
@@ -32,11 +32,10 @@ export const setUserStatus = graphql(SET_USER_STATUS, {
|
||||
|
||||
export const suspendUser = graphql(SUSPEND_USER, {
|
||||
props: ({mutate}) => ({
|
||||
suspendUser: ({userId, message}) => {
|
||||
suspendUser: (input) => {
|
||||
return mutate({
|
||||
variables: {
|
||||
userId,
|
||||
message
|
||||
input,
|
||||
},
|
||||
refetchQueries: ['Users']
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mutation suspendUser($userId: ID!, $message: String) {
|
||||
suspendUser(id: $userId, message: $message) {
|
||||
mutation suspendUser($input: SuspendUserInput!) {
|
||||
suspendUser(input: $input) {
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ export const fetchSignUpFacebook = () => (dispatch) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const facebookCallback = (err, data) => (dispatch) => {
|
||||
export const facebookCallback = (err, data) => (dispatch, getState) => {
|
||||
if (err) {
|
||||
dispatch(signInFacebookFailure(err));
|
||||
return;
|
||||
@@ -196,8 +196,10 @@ export const facebookCallback = (err, data) => (dispatch) => {
|
||||
dispatch(handleAuthToken(data.token));
|
||||
dispatch(signInFacebookSuccess(data.user));
|
||||
dispatch(hideSignInDialog());
|
||||
dispatch(showCreateUsernameDialog());
|
||||
dispatch(hideSignInDialog());
|
||||
const {user: {canEditName, suspension}} = getState().auth.toJS();
|
||||
if (canEditName && !suspension.mustChangeUsername) {
|
||||
dispatch(showCreateUsernameDialog());
|
||||
}
|
||||
} catch (err) {
|
||||
dispatch(signInFacebookFailure(err));
|
||||
return;
|
||||
|
||||
@@ -104,7 +104,7 @@ class ChangeUsernameContainer extends Component {
|
||||
return (
|
||||
<div>
|
||||
<CreateUsernameDialog
|
||||
open={auth.showCreateUsernameDialog && auth.user.canEditName}
|
||||
open={auth.showCreateUsernameDialog}
|
||||
handleClose={this.handleClose}
|
||||
loggedIn={loggedIn}
|
||||
handleSubmitUsername={this.handleSubmitUsername}
|
||||
|
||||
@@ -5,8 +5,8 @@ const setUserStatus = ({user}, {id, status}) => {
|
||||
return UsersService.setStatus(id, status);
|
||||
};
|
||||
|
||||
const suspendUser = ({user}, {id, message}) => {
|
||||
return UsersService.suspendUser(id, message);
|
||||
const suspendUser = ({user}, {id, message, mustChangeUsername, until}) => {
|
||||
return UsersService.suspendUser(id, message, mustChangeUsername, until);
|
||||
};
|
||||
|
||||
const ignoreUser = ({user}, userToIgnore) => {
|
||||
|
||||
@@ -25,9 +25,9 @@ const Comment = {
|
||||
|
||||
// TODO: remove
|
||||
if (user && excludeIgnored) {
|
||||
return Comments.countByParentIDPersonalized({id, excludeIgnored});
|
||||
return Comments.countByParentIDPersonalized({id, excludeIgnored});
|
||||
}
|
||||
return Comments.countByParentID.load(id);
|
||||
return Comments.countByParentID.load(id);
|
||||
},
|
||||
actions({id}, _, {user, loaders: {Actions}}) {
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ const RootMutation = {
|
||||
setUserStatus(_, {id, status}, {mutators: {User}}) {
|
||||
return wrapResponse(null)(User.setUserStatus({id, status}));
|
||||
},
|
||||
suspendUser(_, {id, message}, {mutators: {User}}) {
|
||||
return wrapResponse(null)(User.suspendUser({id, message}));
|
||||
suspendUser(_, {input: {id, message, mustChangeUsername, until}}, {mutators: {User}}) {
|
||||
return wrapResponse(null)(User.suspendUser({id, message, mustChangeUsername, until}));
|
||||
},
|
||||
ignoreUser(_, {id}, {mutators: {User}}) {
|
||||
return wrapResponse(null)(User.ignoreUser({id}));
|
||||
|
||||
+20
-3
@@ -669,6 +669,23 @@ input CreateDontAgreeInput {
|
||||
message: String
|
||||
}
|
||||
|
||||
# Input for suspendUser mutation.
|
||||
input SuspendUserInput {
|
||||
|
||||
# id of target user.
|
||||
id: ID!
|
||||
|
||||
# message to be sent to the user.
|
||||
# TODO: should this be required?
|
||||
message: String
|
||||
|
||||
# If set, the user is requested to change its username.
|
||||
mustChangeUsername: Boolean
|
||||
|
||||
# If set, the suspension lasts at least until specified date.
|
||||
until: Date
|
||||
}
|
||||
|
||||
# DeleteActionResponse is the response returned with possibly some errors
|
||||
# relating to the delete action attempt.
|
||||
type DeleteActionResponse implements Response {
|
||||
@@ -741,7 +758,7 @@ type EditCommentResponse implements Response {
|
||||
comment: Comment
|
||||
|
||||
# An array of errors relating to the mutation that occured.
|
||||
errors: [UserError]
|
||||
errors: [UserError]
|
||||
}
|
||||
|
||||
# All mutations for the application are defined on this object.
|
||||
@@ -765,8 +782,8 @@ type RootMutation {
|
||||
# Sets User status. Requires the `ADMIN` role.
|
||||
setUserStatus(id: ID!, status: USER_STATUS!): SetUserStatusResponse
|
||||
|
||||
# Sets User status to BANNED and canEditName to true. It sends a message to the banned User. Requires the `ADMIN` role.
|
||||
suspendUser(id: ID!, message: String): SuspendUserResponse
|
||||
# Suspends a user. Requires the `ADMIN` role.
|
||||
suspendUser(input: SuspendUserInput!): SuspendUserResponse
|
||||
|
||||
# Sets Comment status. Requires the `ADMIN` role.
|
||||
setCommentStatus(id: ID!, status: COMMENT_STATUS!): SetCommentStatusResponse
|
||||
|
||||
@@ -111,6 +111,18 @@ const UserSchema = new mongoose.Schema({
|
||||
default: false
|
||||
},
|
||||
|
||||
// User's suspension details.
|
||||
suspensionDetails: {
|
||||
mustChangeUsername: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
until: {
|
||||
type: Date,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
// User's settings
|
||||
settings: {
|
||||
bio: {
|
||||
@@ -139,6 +151,7 @@ const UserSchema = new mongoose.Schema({
|
||||
},
|
||||
|
||||
toJSON: {
|
||||
virtuals: true,
|
||||
transform: function (doc, ret) {
|
||||
delete ret.password;
|
||||
delete ret._id;
|
||||
@@ -147,6 +160,10 @@ const UserSchema = new mongoose.Schema({
|
||||
}
|
||||
});
|
||||
|
||||
UserSchema.virtual('suspended').get(function() {
|
||||
return this.suspensionDetails.mustChangeUsername || this.suspensionDetails.until > new Date();
|
||||
});
|
||||
|
||||
// Add the indixies on the user profile data.
|
||||
UserSchema.index({
|
||||
'profiles.id': 1,
|
||||
|
||||
+39
-29
@@ -451,40 +451,48 @@ module.exports = class UsersService {
|
||||
|
||||
/**
|
||||
* Suspend a user. It changes the status to BANNED and canEditName to True.
|
||||
* @param {String} id id of a user
|
||||
* @param {Function} done callback after the operation is complete
|
||||
* @param {String} id id of a user
|
||||
* @param {String} message message to be send to the user
|
||||
* @param {Boolean} mustChangeUsername if set the suspension lasts at least until user changed its username.
|
||||
* @param {Date} until if set the suspension lasts at least until date.
|
||||
*/
|
||||
static suspendUser(id, message) {
|
||||
return UserModel.findOneAndUpdate({
|
||||
id
|
||||
}, {
|
||||
static suspendUser(id, message, mustChangeUsername, until) {
|
||||
const changes = {
|
||||
$set: {
|
||||
status: 'BANNED',
|
||||
canEditName: true
|
||||
suspensionDetails: {},
|
||||
}
|
||||
})
|
||||
.then((user) => {
|
||||
if (message) {
|
||||
let localProfile = user.profiles.find((profile) => profile.provider === 'local');
|
||||
};
|
||||
if (mustChangeUsername) {
|
||||
changes.$set.status = 'BANNED';
|
||||
changes.$set.canEditName = true;
|
||||
changes.$set.suspensionDetails.mustChangeUsername = true;
|
||||
}
|
||||
if (until) {
|
||||
changes.$set.suspensionDetails.until = until;
|
||||
}
|
||||
return UserModel.findOneAndUpdate({id}, changes)
|
||||
.then((user) => {
|
||||
if (message) {
|
||||
let localProfile = user.profiles.find((profile) => profile.provider === 'local');
|
||||
|
||||
if (localProfile) {
|
||||
const options =
|
||||
{
|
||||
template: 'suspension', // needed to know which template to render!
|
||||
locals: { // specifies the template locals.
|
||||
body: message
|
||||
},
|
||||
subject: 'Email Suspension',
|
||||
to: localProfile.id // This only works if the user has registered via e-mail.
|
||||
// We may want a standard way to access a user's e-mail address in the future
|
||||
};
|
||||
if (localProfile) {
|
||||
const options =
|
||||
{
|
||||
template: 'suspension', // needed to know which template to render!
|
||||
locals: { // specifies the template locals.
|
||||
body: message
|
||||
},
|
||||
subject: 'Email Suspension',
|
||||
to: localProfile.id // This only works if the user has registered via e-mail.
|
||||
// We may want a standard way to access a user's e-mail address in the future
|
||||
};
|
||||
|
||||
return MailerService.sendSimple(options);
|
||||
} else {
|
||||
return Promise.reject(errors.ErrMissingEmail);
|
||||
return MailerService.sendSimple(options);
|
||||
} else {
|
||||
return Promise.reject(errors.ErrMissingEmail);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -813,13 +821,15 @@ module.exports = class UsersService {
|
||||
username: username,
|
||||
lowercaseUsername: username.toLowerCase(),
|
||||
canEditName: false,
|
||||
status: 'PENDING'
|
||||
status: 'PENDING',
|
||||
'suspensionDetails.mustChangeUsername': false,
|
||||
}
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.nModified <= 0) {
|
||||
return Promise.reject(errors.ErrPermissionUpdateUsername);
|
||||
}
|
||||
console.log(result);
|
||||
|
||||
return result;
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user