2025-05-10 02:09:06 +02:00
/ * !
* Copyright ( c ) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License : https : //github.com/plankanban/planka/blob/master/LICENSE.md
* /
2025-09-08 16:20:27 +02:00
/ * *
* @ swagger
2025-09-08 18:25:26 +02:00
* /users/ { id } / password :
2025-09-08 16:20:27 +02:00
* patch :
* summary : Update user password
* description : Updates a user 's password. Users must provide a current password when updating their own password. Admins can update any user' s password without the current password . Returns a new access token when updating own password .
* tags :
* - Users
2025-09-12 12:17:01 +02:00
* operationId : updateUserPassword
2025-09-08 16:20:27 +02:00
* parameters :
* - in : path
* name : id
* required : true
* description : ID of the user whose password to update
* schema :
* type : string
2025-09-08 19:14:31 +02:00
* example : "1357158568008091264"
2025-09-08 16:20:27 +02:00
* requestBody :
* required : true
* content :
* application / json :
* schema :
* type : object
* required :
* - password
* properties :
* password :
* type : string
* maxLength : 256
* description : Password ( must meet password requirements )
* example : SecurePassword123 !
* currentPassword :
* type : string
* maxLength : 256
* description : Current password ( required when updating own password )
* example : SecurePassword456 !
* responses :
* 200 :
* description : Password updated successfully
* content :
* application / json :
* schema :
* type : object
* required :
* - item
* properties :
* item :
* $ref : '#/components/schemas/User'
* included :
* type : object
* required :
* - accessTokens
* properties :
* accessTokens :
* type : array
* description : New acces tokens ( when updating own password )
* items :
* type : string
2025-09-12 12:17:01 +02:00
* example : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ4 ...
2025-09-08 16:20:27 +02:00
* 400 :
* $ref : '#/components/responses/ValidationError'
* 401 :
* $ref : '#/components/responses/Unauthorized'
* 403 :
* $ref : '#/components/responses/Forbidden'
* 404 :
* $ref : '#/components/responses/NotFound'
* /
2019-10-18 08:06:34 +05:00
const bcrypt = require ( 'bcrypt' ) ;
2025-05-10 02:09:06 +02:00
const { isPassword } = require ( '../../../utils/validators' ) ;
const { idInput } = require ( '../../../utils/inputs' ) ;
const { getRemoteAddress } = require ( '../../../utils/remote-address' ) ;
2022-09-07 18:39:33 +05:00
2019-10-18 08:06:34 +05:00
const Errors = {
2023-10-17 19:18:19 +02:00
NOT _ENOUGH _RIGHTS : {
notEnoughRights : 'Not enough rights' ,
} ,
2020-04-03 00:35:25 +05:00
INVALID _CURRENT _PASSWORD : {
invalidCurrentPassword : 'Invalid current password' ,
2019-11-05 18:01:42 +05:00
} ,
2025-05-10 02:09:06 +02:00
USER _NOT _FOUND : {
userNotFound : 'User not found' ,
} ,
2019-10-18 08:06:34 +05:00
} ;
module . exports = {
inputs : {
id : {
2025-05-10 02:09:06 +02:00
... idInput ,
2019-11-05 18:01:42 +05:00
required : true ,
2019-10-18 08:06:34 +05:00
} ,
password : {
type : 'string' ,
2025-05-10 02:09:06 +02:00
maxLength : 256 ,
custom : isPassword ,
2019-11-05 18:01:42 +05:00
required : true ,
2019-10-18 08:06:34 +05:00
} ,
currentPassword : {
type : 'string' ,
2019-11-05 18:01:42 +05:00
isNotEmptyString : true ,
2025-05-10 02:09:06 +02:00
maxLength : 256 ,
2019-11-05 18:01:42 +05:00
} ,
2019-10-18 08:06:34 +05:00
} ,
exits : {
2023-10-17 19:18:19 +02:00
notEnoughRights : {
responseType : 'forbidden' ,
} ,
2020-04-03 00:35:25 +05:00
invalidCurrentPassword : {
2019-11-05 18:01:42 +05:00
responseType : 'forbidden' ,
} ,
2025-05-10 02:09:06 +02:00
userNotFound : {
responseType : 'notFound' ,
} ,
2019-10-18 08:06:34 +05:00
} ,
2021-06-24 01:05:22 +05:00
async fn ( inputs ) {
2024-09-01 09:31:04 +02:00
const { currentSession , currentUser } = this . req ;
2019-10-18 08:06:34 +05:00
if ( inputs . id === currentUser . id ) {
if ( ! inputs . currentPassword ) {
2020-04-03 00:35:25 +05:00
throw Errors . INVALID _CURRENT _PASSWORD ;
2019-10-18 08:06:34 +05:00
}
2025-05-10 02:09:06 +02:00
} else if ( currentUser . role !== User . Roles . ADMIN ) {
2019-10-18 08:06:34 +05:00
throw Errors . USER _NOT _FOUND ; // Forbidden
}
2025-05-10 02:09:06 +02:00
let user = await User . qm . getOneById ( inputs . id ) ;
2019-10-18 08:06:34 +05:00
if ( ! user ) {
throw Errors . USER _NOT _FOUND ;
}
2025-05-10 02:09:06 +02:00
if ( user . email === sails . config . custom . defaultAdminEmail || user . isSsoUser ) {
2023-10-17 19:18:19 +02:00
throw Errors . NOT _ENOUGH _RIGHTS ;
2023-09-12 01:12:38 +02:00
}
2025-05-10 02:09:06 +02:00
if ( inputs . id === currentUser . id ) {
const isCurrentPasswordValid = await bcrypt . compare ( inputs . currentPassword , user . password ) ;
if ( ! isCurrentPasswordValid ) {
throw Errors . INVALID _CURRENT _PASSWORD ;
}
2019-10-18 08:06:34 +05:00
}
const values = _ . pick ( inputs , [ 'password' ] ) ;
2022-12-26 21:10:50 +01:00
user = await sails . helpers . users . updateOne . with ( {
values ,
record : user ,
2024-06-12 00:51:36 +02:00
actorUser : currentUser ,
2022-12-26 21:10:50 +01:00
request : this . req ,
} ) ;
2019-10-18 08:06:34 +05:00
if ( ! user ) {
throw Errors . USER _NOT _FOUND ;
}
2022-08-09 18:03:21 +02:00
if ( user . id === currentUser . id ) {
2024-09-01 09:31:04 +02:00
const { token : accessToken } = sails . helpers . utils . createJwtToken (
user . id ,
2025-05-10 02:09:06 +02:00
user . passwordChangedAt ,
2024-09-01 09:31:04 +02:00
) ;
2022-08-09 18:03:21 +02:00
2025-05-10 02:09:06 +02:00
await Session . qm . createOne ( {
2022-09-07 18:39:33 +05:00
accessToken ,
2024-09-01 09:31:04 +02:00
httpOnlyToken : currentSession . httpOnlyToken ,
2022-09-07 18:39:33 +05:00
userId : user . id ,
remoteAddress : getRemoteAddress ( this . req ) ,
userAgent : this . req . headers [ 'user-agent' ] ,
} ) ;
2022-08-09 18:03:21 +02:00
return {
2025-05-10 02:09:06 +02:00
item : sails . helpers . users . presentOne ( user , currentUser ) ,
2022-08-09 22:31:43 +02:00
included : {
accessTokens : [ accessToken ] ,
} ,
2022-08-09 18:03:21 +02:00
} ;
}
2021-06-24 01:05:22 +05:00
return {
2025-05-10 02:09:06 +02:00
item : sails . helpers . users . presentOne ( user , currentUser ) ,
2021-06-24 01:05:22 +05:00
} ;
2019-11-05 18:01:42 +05:00
} ,
2019-10-18 08:06:34 +05:00
} ;