Skip to content

Commit

Permalink
fix(be): fix not to use password to change non password fields (#2005)
Browse files Browse the repository at this point in the history
* fix(be): fix not to use password to change non password fields

* chore(be): add unidentifiedexception

* fix(be): fix error handling logic, docs

* docs(be): fix bruno docs of updateUser

* docs(be): change name of update all fields

* chore(be): refine error handling logic

---------

Co-authored-by: Jaehyeon Kim <65964601+Jaehyeon1020@users.noreply.github.com>
  • Loading branch information
jimin9038 and Jaehyeon1020 authored Aug 25, 2024
1 parent c2289f8 commit 1ff5af4
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 50 deletions.
3 changes: 2 additions & 1 deletion apps/backend/apps/client/src/user/dto/updateUser.dto.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { IsOptional, IsString, IsNumberString, Matches } from 'class-validator'

export class UpdateUserDto {
@IsOptional()
@IsString()
readonly password: string
readonly password?: string

@IsOptional()
@IsString()
Expand Down
29 changes: 27 additions & 2 deletions apps/backend/apps/client/src/user/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ import {
Controller,
Logger,
Delete,
Query
Query,
NotFoundException,
InternalServerErrorException
} from '@nestjs/common'
import { Prisma } from '@prisma/client'
import { Request, type Response } from 'express'
import { AuthenticatedRequest, AuthNotNeededIfOpenSpace } from '@libs/auth'
import {
EntityNotExistException,
UnidentifiedException,
UnprocessableDataException
} from '@libs/exception'
import { DeleteUserDto } from './dto/deleteUser.dto'
import { EmailAuthenticationPinDto } from './dto/email-auth-pin.dto'
import { NewPasswordDto } from './dto/newPassword.dto'
Expand Down Expand Up @@ -88,7 +96,24 @@ export class UserController {
@Req() req: AuthenticatedRequest,
@Body() updateUserDto: UpdateUserDto
) {
return await this.userService.updateUser(req, updateUserDto)
try {
return await this.userService.updateUser(req, updateUserDto)
} catch (error) {
if (
error instanceof Prisma.PrismaClientKnownRequestError &&
error.name == 'NotFoundError'
) {
throw new NotFoundException(error.message)
} else if (
error instanceof EntityNotExistException ||
error instanceof UnprocessableDataException ||
error instanceof UnidentifiedException
) {
throw error.convert2HTTPException()
}
this.logger.error(error)
throw new InternalServerErrorException()
}
}
}

Expand Down
33 changes: 19 additions & 14 deletions apps/backend/apps/client/src/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,24 +559,29 @@ export class UserService {

// update user field (password, studentId, major, realName)
async updateUser(req: AuthenticatedRequest, updateUserDto: UpdateUserDto) {
const user = await this.getUserCredential(req.user.username)
if (!user) {
throw new EntityNotExistException('User')
}

const isValidUser = await this.jwtAuthService.isValidUser(
user,
updateUserDto.password
)
if (!isValidUser) {
throw new UnidentifiedException('password')
}

let encryptedNewPassword: string | undefined = undefined

if (updateUserDto.newPassword) {
if (!updateUserDto.password) {
throw new UnprocessableDataException(
'current password needed to change password'
)
}
const user = await this.getUserCredential(req.user.username)
if (!user) {
throw new EntityNotExistException('User')
}

const isValidUser = await this.jwtAuthService.isValidUser(
user,
updateUserDto.password
)
if (!isValidUser) {
throw new UnidentifiedException('current password')
}

if (!this.isValidPassword(updateUserDto.newPassword)) {
throw new UnprocessableDataException('Bad password')
throw new UnprocessableDataException('Bad new password')
}
encryptedNewPassword = await hash(
updateUserDto.newPassword,
Expand Down
39 changes: 39 additions & 0 deletions collection/client/User/Update User/Optionally update.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
meta {
name: Optionally Update User
type: http
seq: 1
}

patch {
url: {{baseUrl}}/user
body: json
auth: none
}

body:json {
{
"password": "Useruser",
"newPassword": "Useruser",
// Don't change password in stage server please!!
"realName": "changedName",
"major": "changedMajor"
}
}

script:pre-request {
await require("./login").loginUser(req);
}

script:post-response {
// TODO: User Fields rollback
}

docs {
# user 정보 수정
- realname, studentId, major, 비밀번호를 선택적으로 수정할 수 있습니다.
비밀번호를 변경하려면 기존 password(=password 필드)와 new password(=newPassword 필드)를 같이 입력으로 주어야 하며,
이때 로그인한 유저의 DB정보를 통해 기존 password를 맞게 썼는지를 검사합니다.
- realname, studentId, major는 변경하려는 값으로만 입력해주시면 됩니다.
비밀번호를 변경하지 않을 경우 기존 password를 입력하지 않아야 합니다.
- 변경하려는 값이 없는 경우에는 해당 필드를 input에 넣지 않아야 합니다.
}
33 changes: 0 additions & 33 deletions collection/client/User/Update User/Succeed.bru

This file was deleted.

39 changes: 39 additions & 0 deletions collection/client/User/Update User/Update All Fields of User.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
meta {
name: Update All Fields of User
type: http
seq: 1
}

patch {
url: {{baseUrl}}/user
body: json
auth: none
}

body:json {
{
"password": "Useruser",
"newPassword": "Useruser",
// Don't change password in stage server please!!
"realName": "changedName",
"major": "changedMajor"
}
}

script:pre-request {
await require("./login").loginUser(req);
}

script:post-response {
// TODO: User Fields rollback
}

docs {
# user 정보 수정
- realname, studentId, major, 비밀번호를 선택적으로 수정할 수 있습니다.
비밀번호를 변경하려면 기존 password(=password 필드)와 new password(=newPassword 필드)를 같이 입력으로 주어야 하며,
이때 로그인한 유저의 DB정보를 통해 기존 password를 맞게 썼는지를 검사합니다.
- realname, studentId, major는 변경하려는 값으로만 입력해주시면 됩니다.
비밀번호를 변경하지 않을 경우 기존 password를 입력하지 않아야 합니다.
- 변경하려는 값이 없는 경우에는 해당 필드를 input에 넣지 않아야 합니다.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
meta {
name: [401] Incorrect current password
type: http
seq: 1
}

patch {
url: {{baseUrl}}/user
body: json
auth: none
}

body:json {
{
"password": "wrongpass",
"newPassword": "Useruser",
// Don't change password in stage server please!!
"realName": "changedName",
"major": "changedMajor"
}
}

script:pre-request {
await require("./login").loginUser(req);
}

script:post-response {
// TODO: User Fields rollback
}

docs {
# user 정보 수정
- realname, studentId, major, 비밀번호를 선택적으로 수정할 수 있습니다.
비밀번호를 변경하려면 기존 password(=password 필드)와 new password(=newPassword 필드)를 같이 입력으로 주어야 하며,
이때 로그인한 유저의 DB정보를 통해 기존 password를 맞게 썼는지를 검사합니다.
- realname, studentId, major는 변경하려는 값으로만 입력해주시면 됩니다.
비밀번호를 변경하지 않을 경우 기존 password를 입력하지 않아야 합니다.
- 변경하려는 값이 없는 경우에는 해당 필드를 input에 넣지 않아야 합니다.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
meta {
name: [422] current password needed to change password
type: http
seq: 1
}

patch {
url: {{baseUrl}}/user
body: json
auth: none
}

body:json {
{
"newPassword": "Useruser",
// Don't change password in stage server please!!
"realName": "changedName",
"major": "changedMajor"
}
}

script:pre-request {
await require("./login").loginUser(req);
}

script:post-response {
// TODO: User Fields rollback
}

docs {
# user 정보 수정
- realname, studentId, major, 비밀번호를 선택적으로 수정할 수 있습니다.
비밀번호를 변경하려면 기존 password(=password 필드)와 new password(=newPassword 필드)를 같이 입력으로 주어야 하며,
이때 로그인한 유저의 DB정보를 통해 기존 password를 맞게 썼는지를 검사합니다.
- realname, studentId, major는 변경하려는 값으로만 입력해주시면 됩니다.
비밀번호를 변경하지 않을 경우 기존 password를 입력하지 않아야 합니다.
- 변경하려는 값이 없는 경우에는 해당 필드를 input에 넣지 않아야 합니다.
}

0 comments on commit 1ff5af4

Please sign in to comment.