회원가입, 회원정보수정, 회원탈퇴, 패스워드초기화, 상태수정, 역할 추가, 역할 삭제, 회원목록 추가

This commit is contained in:
2025-12-03 14:29:48 +09:00
parent 3d6393a65f
commit c8846e97f3
21 changed files with 483 additions and 172 deletions

View File

@@ -12,6 +12,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -19,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
@Tag(name = "회원정보 관리자 관리", description = "회원정보 관리자 관리 API")
@RestController
@RequestMapping("/api/admin")
@RequestMapping("/api/admin/members")
@RequiredArgsConstructor
public class AdminApiController {
@@ -39,7 +40,7 @@ public class AdminApiController {
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/members/join")
@PostMapping("/join")
public ApiResponseDto<Long> saveMember(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "회원가입",
@@ -55,7 +56,7 @@ public class AdminApiController {
return ApiResponseDto.createOK(adminService.saveMember(addReq));
}
@Operation(summary = "역할 저장", description = "역할 저장")
@Operation(summary = "역할 추가", description = "uuid 기준으로 역할 추가")
@ApiResponses(
value = {
@ApiResponse(
@@ -85,7 +86,7 @@ public class AdminApiController {
return ApiResponseDto.createOK(rolesDto.getUuid());
}
@Operation(summary = "역할 삭제", description = "역할 삭제")
@Operation(summary = "역할 삭제", description = "uuid 기준으로 역할 삭제")
@ApiResponses(
value = {
@ApiResponse(
@@ -114,4 +115,74 @@ public class AdminApiController {
adminService.deleteRoles(rolesDto);
return ApiResponseDto.createOK(rolesDto.getUuid());
}
@Operation(summary = "상태 수정", description = "상태 수정")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "201",
description = "상태 수정",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/status/update")
public ApiResponseDto<UUID> updateStatus(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "상태 수정",
required = true,
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = MembersDto.StatusDto.class)))
@RequestBody
@Valid
MembersDto.StatusDto statusDto) {
adminService.updateStatus(statusDto);
return ApiResponseDto.createOK(statusDto.getUuid());
}
@Operation(summary = "회원 탈퇴", description = "회원 탈퇴")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "201",
description = "회원 탈퇴",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/delete-account")
public ApiResponseDto<UUID> deleteAccount(MembersDto.StatusDto statusDto) {
adminService.deleteAccount(statusDto);
return ApiResponseDto.createOK(statusDto.getUuid());
}
@Operation(summary = "패스워드 초기화", description = "패스워드 초기화")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "201",
description = "패스워드 초기화",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/{memberId}/password")
public ApiResponseDto<Long> resetPassword(@PathVariable Long memberId) {
adminService.resetPassword(memberId);
return ApiResponseDto.createOK(memberId);
}
}

View File

@@ -10,8 +10,10 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -42,4 +44,25 @@ public class MembersApiController {
public ApiResponseDto<Page<Basic>> getMemberList(@RequestBody MembersDto.SearchReq searchReq) {
return ApiResponseDto.ok(membersService.findByMembers(searchReq));
}
@Operation(summary = "회원정보 수정", description = "회원정보 수정")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "201",
description = "회원정보 수정",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/{uuid}")
public ApiResponseDto<UUID> updateMember(
@PathVariable UUID uuid, @RequestBody MembersDto.UpdateReq updateReq) {
membersService.updateMember(uuid, updateReq);
return ApiResponseDto.createOK(uuid);
}
}

View File

@@ -99,9 +99,7 @@ public class MembersDto {
@Size(min = 2, max = 100)
private String name;
@Schema(description = "패스워드", example = "")
@NotBlank
@Size(max = 255)
@Schema(hidden = true)
private String password;
@Schema(description = "이메일", example = "gildong@daum.net")
@@ -116,12 +114,42 @@ public class MembersDto {
}
}
@Getter
@Setter
public static class UpdateReq {
@Schema(description = "사번, 패스워드 변경시 필수 값", example = "11111")
@Size(max = 50)
private String employeeNo;
@Schema(description = "이름", example = "홍길동")
@Size(min = 2, max = 100)
private String name;
@Schema(description = "패스워드", example = "")
@Size(max = 255)
private String password;
@Schema(description = "이메일", example = "gildong@daum.net")
@Size(max = 100)
private String email;
public UpdateReq(String employeeNo, String name, String password, String email) {
this.employeeNo = employeeNo;
this.name = name;
this.password = password;
this.email = email;
}
}
@Getter
@Setter
public static class RolesDto {
@Schema(description = "UUID", example = "4e89e487-c828-4a34-a7fc-0d5b0e3b53b5")
private UUID uuid;
@Schema(description = "역할 ROLE_ADMIN, ROLE_LABELER, ROLE_REVIEWER", example = "ROLE_ADMIN")
@EnumValid(enumClass = RoleType.class)
private String roleName;
@@ -130,4 +158,19 @@ public class MembersDto {
this.roleName = roleName;
}
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class StatusDto {
@Schema(description = "UUID", example = "4e89e487-c828-4a34-a7fc-0d5b0e3b53b5")
@NotBlank
private UUID uuid;
@Schema(description = "변경할 상태값 ACTIVE, INACTIVE, ARCHIVED", example = "ACTIVE")
@NotBlank
private String status;
}
}

View File

@@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.members.dto.MembersDto;
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
import lombok.RequiredArgsConstructor;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -15,6 +16,9 @@ public class AdminService {
private final MembersCoreService membersCoreService;
@Value("${member.init_password}")
private String password;
/**
* 회원가입
*
@@ -23,11 +27,11 @@ public class AdminService {
*/
@Transactional
public Long saveMember(MembersDto.AddReq addReq) {
// salt 생성
String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getEmployeeNo());
// salt 생성, 사번이 salt
String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getEmployeeNo().trim());
// 패스워드 암호화
String hashedPassword = BCrypt.hashpw(addReq.getPassword(), salt);
// 패스워드 암호화, 초기 패스워드 고정
String hashedPassword = BCrypt.hashpw(password, salt);
addReq.setPassword(hashedPassword);
return membersCoreService.saveMembers(addReq);
}
@@ -50,4 +54,31 @@ public class AdminService {
public void deleteRoles(MembersDto.RolesDto rolesDto) {
membersCoreService.deleteRoles(rolesDto);
}
/**
* 역할 수정
*
* @param statusDto
*/
public void updateStatus(MembersDto.StatusDto statusDto) {
membersCoreService.updateStatus(statusDto);
}
/**
* 회원 탈퇴
*
* @param statusDto
*/
public void deleteAccount(MembersDto.StatusDto statusDto) {
membersCoreService.deleteAccount(statusDto);
}
/**
* 패스워드 초기화
*
* @param id
*/
public void resetPassword(Long id) {
membersCoreService.resetPassword(id);
}
}

View File

@@ -1,10 +1,15 @@
package com.kamco.cd.kamcoback.members.service;
import com.kamco.cd.kamcoback.config.BCryptSaltGenerator;
import com.kamco.cd.kamcoback.members.dto.MembersDto;
import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic;
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.data.domain.Page;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -24,4 +29,30 @@ public class MembersService {
public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) {
return membersCoreService.findByMembers(searchReq);
}
/**
* 회원정보 수정
*
* @param uuid
* @param updateReq
*/
public void updateMember(UUID uuid, MembersDto.UpdateReq updateReq) {
if (StringUtils.isNotBlank(updateReq.getPassword())) {
if (StringUtils.isBlank(updateReq.getEmployeeNo())) {
throw new HttpMessageNotReadableException("패스워드 변경시 사번은 필수 값입니다.");
}
// salt 생성, 사번이 salt
String salt =
BCryptSaltGenerator.generateSaltWithEmployeeNo(updateReq.getEmployeeNo().trim());
// 패스워드 암호화, 초기 패스워드 고정
String hashedPassword = BCrypt.hashpw(updateReq.getPassword(), salt);
updateReq.setPassword(hashedPassword);
}
membersCoreService.updateMembers(uuid, updateReq);
}
}