Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions services/api/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const userValidator = checkSchema({
},
})

const createUserValidator = checkSchema({
const roleValidator = checkSchema({
role: {
matches: {
errorMessage: `Role should be "${ROLES.WRITER}" or "${ROLES.READER}"`,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can only add writer and reader except for admin?

Expand All @@ -41,9 +41,9 @@ const createUserValidator = checkSchema({
})

const changePasswordValidator = checkSchema({
password: {
newPassword: {
exists: true,
errorMessage: 'Password is required',
errorMessage: 'New password is required',
},
})

Expand Down Expand Up @@ -144,22 +144,71 @@ async function deleteUser(req, res, next) {
}

async function changePassword(req, res, next) {
const { id } = req.params
const { id: targetId } = req.params
const { _id: requesterId } = req.user
const { oldPassword, newPassword } = req.body

if (!isValidId(id)) {
if (!isValidId(targetId)) {
return next(createError(400, 'Invalid ID'))
}

try {
const targetUser = await models.users.findById(targetId)

if (!targetUser) {
return next(createError(404, 'User not existed'))
}

// If the user changes its own password and it is not the first time
// to be changed, then the request also needs old password.
if (requesterId.toString() === targetId && targetUser.passwordLastUpdated) {
if (oldPassword !== targetUser.password) {
return next(createError(400, 'Incorrect old password'))
}
}

const updated = {
password: req.body.password,
password: newPassword,
passwordLastUpdated: new Date(),
}
const options = {
new: true,
runValidators: true,
}
const result = await models.users.findByIdAndUpdate(id, updated, options)
const result = await models.users.findByIdAndUpdate(targetId, updated, options)

if (!result) {
return next(createError(404, 'User not existed'))
}

return res.status(204).send()
} catch (err) {
return next(createError(500, null, err))
}
}

async function updateRole(req, res, next) {
const { id: targetId } = req.params
const { role } = req.body
const { _id: requesterId } = req.user

try {
const targetUser = await models.users.findById(targetId)

if (!targetUser) {
return next(createError(404, 'User not existed'))
}

if (targetUser.role === ROLES.ADMIN) {
return next(createError(400, 'Updating admin role is not allowed'))
}

const updated = { role }
const options = {
new: true,
runValidators: true,
}
const result = await models.users.findByIdAndUpdate(targetId, updated, options)

if (!result) {
return next(createError(404, 'User not existed'))
Expand Down Expand Up @@ -223,13 +272,14 @@ async function createAdminUser() {
routesWithAuth(
router,
['get', '/users', getAllUsers],
['post', '/users', userValidator, createUserValidator, validate, createUser],
['post', '/users', userValidator, roleValidator, validate, createUser],
)
routesWithAuth(
router,
['get', '/user/:id', isSelfOrAdmin, getUser],
['delete', '/user/:id', isSelfOrAdmin, deleteUser],
['patch', '/user/:id/password', isSelfOrAdmin, changePasswordValidator, validate, changePassword],
['patch', '/user/:id/role', roleValidator, validate, updateRole],
)
router.post('/login', userValidator, validate, login)

Expand Down