관리자 관리 수정
This commit is contained in:
@@ -30,8 +30,8 @@ public class CustomAuthenticationProvider implements AuthenticationProvider {
|
|||||||
.findByUserId(username)
|
.findByUserId(username)
|
||||||
.orElseThrow(() -> new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND));
|
.orElseThrow(() -> new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND));
|
||||||
|
|
||||||
// 삭제 상태
|
// 미사용 상태
|
||||||
if (member.getStatus().equals(StatusType.DELETED.getId())) {
|
if (member.getStatus().equals(StatusType.INACTIVE.getId())) {
|
||||||
throw new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND);
|
throw new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,15 +39,12 @@ public class CustomAuthenticationProvider implements AuthenticationProvider {
|
|||||||
if (!BCrypt.checkpw(rawPassword, member.getPassword())) {
|
if (!BCrypt.checkpw(rawPassword, member.getPassword())) {
|
||||||
// 실패 카운트 저장
|
// 실패 카운트 저장
|
||||||
int cnt = member.getLoginFailCount() + 1;
|
int cnt = member.getLoginFailCount() + 1;
|
||||||
if (cnt >= 5) {
|
|
||||||
member.setStatus(StatusType.INACTIVE.getId());
|
|
||||||
}
|
|
||||||
member.setLoginFailCount(cnt);
|
member.setLoginFailCount(cnt);
|
||||||
membersRepository.save(member);
|
membersRepository.save(member);
|
||||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 패스워드 실패 횟수 체크
|
// 로그인 실패 체크
|
||||||
if (member.getLoginFailCount() >= 5) {
|
if (member.getLoginFailCount() >= 5) {
|
||||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_EXCEEDED);
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_EXCEEDED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import lombok.Getter;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum StatusType implements EnumType {
|
public enum StatusType implements EnumType {
|
||||||
ACTIVE("활성"),
|
ACTIVE("활성"),
|
||||||
INACTIVE("비활성"),
|
INACTIVE("미사용"),
|
||||||
DELETED("삭제");
|
PENDING("보류");
|
||||||
|
|
||||||
private final String desc;
|
private final String desc;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.kamco.cd.kamcoback.common.utils;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class CommonStringUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 영문, 숫자, 특수문자를 모두 포함하여 8~20자 이내의 비밀번호
|
||||||
|
*
|
||||||
|
* @param password
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isValidPassword(String password) {
|
||||||
|
String passwordPattern =
|
||||||
|
"^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-\\[\\]{};':\"\\\\|,.<>/?]).{8,20}$";
|
||||||
|
return Pattern.matches(passwordPattern, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -435,23 +435,38 @@ public class GlobalExceptionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExceptionHandler(CustomApiException.class)
|
@ExceptionHandler(CustomApiException.class)
|
||||||
public ResponseEntity<ApiResponseDto<String>> handleCustomApiException(
|
public ApiResponseDto<String> handleCustomApiException(
|
||||||
CustomApiException e, HttpServletRequest request) {
|
CustomApiException e, HttpServletRequest request) {
|
||||||
log.warn("[CustomApiException] resource : {}", e.getMessage());
|
log.warn("[CustomApiException] resource : {}", e.getMessage());
|
||||||
|
|
||||||
String codeName = e.getCodeName();
|
String codeName = e.getCodeName();
|
||||||
HttpStatus status = e.getStatus();
|
HttpStatus status = e.getStatus();
|
||||||
String message = e.getMessage() == null ? ApiResponseCode.getMessage(codeName) : e.getMessage();
|
// String message = e.getMessage() == null ? ApiResponseCode.getMessage(codeName) :
|
||||||
|
// e.getMessage();
|
||||||
ApiResponseCode apiCode = ApiResponseCode.getCode(codeName);
|
//
|
||||||
|
// ApiResponseCode apiCode = ApiResponseCode.getCode(codeName);
|
||||||
|
//
|
||||||
|
// ErrorLogEntity errorLog =
|
||||||
|
// saveErrorLogData(
|
||||||
|
// request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace());
|
||||||
|
//
|
||||||
|
// ApiResponseDto<String> body =
|
||||||
|
// ApiResponseDto.createException(apiCode, message, status, errorLog.getId());
|
||||||
|
|
||||||
ErrorLogEntity errorLog =
|
ErrorLogEntity errorLog =
|
||||||
saveErrorLogData(
|
saveErrorLogData(
|
||||||
request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace());
|
request,
|
||||||
|
ApiResponseCode.getCode(codeName),
|
||||||
|
HttpStatus.valueOf(status.value()),
|
||||||
|
ErrorLogDto.LogErrorLevel.WARNING,
|
||||||
|
e.getStackTrace());
|
||||||
|
|
||||||
ApiResponseDto<String> body =
|
return ApiResponseDto.createException(
|
||||||
ApiResponseDto.createException(apiCode, message, status, errorLog.getId());
|
ApiResponseCode.getCode(codeName),
|
||||||
|
ApiResponseCode.getMessage(codeName),
|
||||||
|
HttpStatus.valueOf(status.value()),
|
||||||
|
errorLog.getId());
|
||||||
|
|
||||||
return new ResponseEntity<>(body, status);
|
// return new ResponseEntity<>(body, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ public class SecurityConfig {
|
|||||||
// ADMIN, REVIEWER 접근
|
// ADMIN, REVIEWER 접근
|
||||||
.requestMatchers("/api/test/review")
|
.requestMatchers("/api/test/review")
|
||||||
.hasAnyRole("ADMIN", "REVIEWER")
|
.hasAnyRole("ADMIN", "REVIEWER")
|
||||||
|
.requestMatchers("/error")
|
||||||
|
.permitAll()
|
||||||
.requestMatchers(HttpMethod.OPTIONS, "/**")
|
.requestMatchers(HttpMethod.OPTIONS, "/**")
|
||||||
.permitAll() // preflight 허용
|
.permitAll() // preflight 허용
|
||||||
.requestMatchers(
|
.requestMatchers(
|
||||||
|
|||||||
@@ -74,8 +74,7 @@ public class MapSheetMngFileCheckerApiController {
|
|||||||
@Operation(summary = "파일 업로드", description = "파일 업로드 및 TIF 검증")
|
@Operation(summary = "파일 업로드", description = "파일 업로드 및 TIF 검증")
|
||||||
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
public ApiResponseDto<String> uploadFile(
|
public ApiResponseDto<String> uploadFile(
|
||||||
@RequestPart("file") MultipartFile file,
|
@RequestPart("file") MultipartFile file, @RequestParam("targetPath") String targetPath) {
|
||||||
@RequestParam("targetPath") String targetPath) {
|
|
||||||
return ApiResponseDto.createOK(mapSheetMngFileCheckerService.uploadFile(file, targetPath));
|
return ApiResponseDto.createOK(mapSheetMngFileCheckerService.uploadFile(file, targetPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.apache.commons.io.FilenameUtils;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
@@ -87,24 +86,4 @@ public class AdminApiController {
|
|||||||
adminService.updateMembers(uuid, updateReq);
|
adminService.updateMembers(uuid, updateReq);
|
||||||
return ApiResponseDto.createOK(UUID.randomUUID());
|
return ApiResponseDto.createOK(UUID.randomUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@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)
|
|
||||||
})
|
|
||||||
@DeleteMapping("/delete/{uuid}")
|
|
||||||
public ApiResponseDto<UUID> deleteAccount(@PathVariable UUID uuid) {
|
|
||||||
adminService.deleteAccount(uuid);
|
|
||||||
return ApiResponseDto.createOK(uuid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class AuthController {
|
|||||||
MembersDto.Member member = new MembersDto.Member();
|
MembersDto.Member member = new MembersDto.Member();
|
||||||
|
|
||||||
// 비활성 상태면 임시패스워드를 비교함
|
// 비활성 상태면 임시패스워드를 비교함
|
||||||
if (StatusType.INACTIVE.getId().equals(status)) {
|
if (StatusType.PENDING.getId().equals(status)) {
|
||||||
if (!authService.isTempPasswordValid(request)) {
|
if (!authService.isTempPasswordValid(request)) {
|
||||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||||
}
|
}
|
||||||
@@ -124,8 +124,9 @@ public class AuthController {
|
|||||||
request.getUsername(), request.getPassword()));
|
request.getUsername(), request.getPassword()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// INACTIVE 비활성 상태(새로운 패스워드 입력 해야함), DELETED 탈퇴
|
// PENDING 비활성 상태(새로운 패스워드 입력 해야함)
|
||||||
if (!StatusType.ACTIVE.getId().equals(status)) {
|
if (StatusType.PENDING.getId().equals(status)) {
|
||||||
|
member.setEmployeeNo(request.getUsername());
|
||||||
return ApiResponseDto.ok(new TokenResponse(status, null, null, member));
|
return ApiResponseDto.ok(new TokenResponse(status, null, null, member));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springdoc.core.annotations.ParameterObject;
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PatchMapping;
|
import org.springframework.web.bind.annotation.PatchMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
@@ -70,10 +69,6 @@ public class MembersApiController {
|
|||||||
@PatchMapping("/{memberId}/password")
|
@PatchMapping("/{memberId}/password")
|
||||||
public ApiResponseDto<String> resetPassword(
|
public ApiResponseDto<String> resetPassword(
|
||||||
@PathVariable String memberId, @RequestBody @Valid MembersDto.InitReq initReq) {
|
@PathVariable String memberId, @RequestBody @Valid MembersDto.InitReq initReq) {
|
||||||
|
|
||||||
authenticationManager.authenticate(
|
|
||||||
new UsernamePasswordAuthenticationToken(memberId, initReq.getTempPassword()));
|
|
||||||
|
|
||||||
membersService.resetPassword(memberId, initReq);
|
membersService.resetPassword(memberId, initReq);
|
||||||
return ApiResponseDto.createOK(memberId);
|
return ApiResponseDto.createOK(memberId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,32 +108,26 @@ public class MembersDto {
|
|||||||
|
|
||||||
@Schema(description = "관리자 유형", example = "ADMIN")
|
@Schema(description = "관리자 유형", example = "ADMIN")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
@EnumValid(enumClass = RoleType.class, message = "userRole은 ADMIN, LABELER, REVIEWER만 가능합니다.")
|
@EnumValid(enumClass = RoleType.class, message = "userRole은 ADMIN, LABELER, REVIEWER 만 가능합니다.")
|
||||||
private String userRole;
|
private String userRole;
|
||||||
|
|
||||||
|
@Schema(description = "사번", example = "K20251212001")
|
||||||
|
@Size(max = 50)
|
||||||
|
private String employeeNo;
|
||||||
|
|
||||||
@Schema(description = "이름", example = "홍길동")
|
@Schema(description = "이름", example = "홍길동")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
@Size(min = 2, max = 100)
|
@Size(min = 2, max = 100)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "ID", example = "gildong")
|
|
||||||
@NotBlank
|
|
||||||
@Size(min = 2, max = 50)
|
|
||||||
private String userId;
|
|
||||||
|
|
||||||
@Schema(description = "임시 비밀번호", example = "q!w@e#r4")
|
@Schema(description = "임시 비밀번호", example = "q!w@e#r4")
|
||||||
private String tempPassword;
|
private String tempPassword;
|
||||||
|
|
||||||
@Schema(description = "사번", example = "123456")
|
public AddReq(String userRole, String employeeNo, String name, String tempPassword) {
|
||||||
private String employeeNo;
|
|
||||||
|
|
||||||
public AddReq(
|
|
||||||
String userRole, String name, String userId, String tempPassword, String employeeNo) {
|
|
||||||
this.userRole = userRole;
|
this.userRole = userRole;
|
||||||
this.name = name;
|
|
||||||
this.userId = userId;
|
|
||||||
this.tempPassword = tempPassword;
|
|
||||||
this.employeeNo = employeeNo;
|
this.employeeNo = employeeNo;
|
||||||
|
this.name = name;
|
||||||
|
this.tempPassword = tempPassword;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,10 +135,6 @@ public class MembersDto {
|
|||||||
@Setter
|
@Setter
|
||||||
public static class UpdateReq {
|
public static class UpdateReq {
|
||||||
|
|
||||||
@Schema(description = "사번, 패스워드 변경시 필수 값", example = "11111")
|
|
||||||
@Size(max = 50)
|
|
||||||
private String employeeNo;
|
|
||||||
|
|
||||||
@Schema(description = "이름", example = "홍길동")
|
@Schema(description = "이름", example = "홍길동")
|
||||||
@Size(min = 2, max = 100)
|
@Size(min = 2, max = 100)
|
||||||
private String name;
|
private String name;
|
||||||
@@ -157,8 +147,7 @@ public class MembersDto {
|
|||||||
@EnumValid(enumClass = StatusType.class, message = "status는 ACTIVE, INACTIVE, DELETED 만 가능합니다.")
|
@EnumValid(enumClass = StatusType.class, message = "status는 ACTIVE, INACTIVE, DELETED 만 가능합니다.")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
public UpdateReq(String employeeNo, String name, String tempPassword, String status) {
|
public UpdateReq(String name, String tempPassword, String status) {
|
||||||
this.employeeNo = employeeNo;
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.tempPassword = tempPassword;
|
this.tempPassword = tempPassword;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class MemberException {
|
|||||||
|
|
||||||
public enum Field {
|
public enum Field {
|
||||||
USER_ID,
|
USER_ID,
|
||||||
|
EMPLOYEE_NO,
|
||||||
DEFAULT
|
DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.kamco.cd.kamcoback.members.service;
|
package com.kamco.cd.kamcoback.members.service;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.common.enums.StatusType;
|
||||||
|
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.CommonStringUtils;
|
||||||
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
||||||
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
|
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -22,6 +26,10 @@ public class AdminService {
|
|||||||
*/
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public Long saveMember(MembersDto.AddReq addReq) {
|
public Long saveMember(MembersDto.AddReq addReq) {
|
||||||
|
if (!CommonStringUtils.isValidPassword(addReq.getTempPassword())) {
|
||||||
|
throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
return membersCoreService.saveMembers(addReq);
|
return membersCoreService.saveMembers(addReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,16 +41,12 @@ public class AdminService {
|
|||||||
*/
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) {
|
public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) {
|
||||||
membersCoreService.updateMembers(uuid, updateReq);
|
if (StatusType.INACTIVE.getId().equals(updateReq.getStatus())) {
|
||||||
}
|
// 미사용 처리
|
||||||
|
membersCoreService.deleteMember(uuid);
|
||||||
/**
|
} else {
|
||||||
* 관리자 계정 미사용 처리
|
// 수정
|
||||||
*
|
membersCoreService.updateMembers(uuid, updateReq);
|
||||||
* @param uuid
|
}
|
||||||
*/
|
|
||||||
@Transactional
|
|
||||||
public void deleteAccount(UUID uuid) {
|
|
||||||
membersCoreService.deleteAccount(uuid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.kamco.cd.kamcoback.members.service;
|
package com.kamco.cd.kamcoback.members.service;
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.CommonStringUtils;
|
||||||
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
||||||
import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic;
|
import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic;
|
||||||
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
|
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -37,21 +37,9 @@ public class MembersService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public void resetPassword(String id, MembersDto.InitReq initReq) {
|
public void resetPassword(String id, MembersDto.InitReq initReq) {
|
||||||
|
|
||||||
if (!isValidPassword(initReq.getPassword())) {
|
if (!CommonStringUtils.isValidPassword(initReq.getPassword())) {
|
||||||
throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST);
|
throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
membersCoreService.resetPassword(id, initReq);
|
membersCoreService.resetPassword(id, initReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 영문, 숫자, 특수문자를 모두 포함하여 8~20자 이내의 비밀번호
|
|
||||||
*
|
|
||||||
* @param password
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isValidPassword(String password) {
|
|
||||||
String passwordPattern =
|
|
||||||
"^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-\\[\\]{};':\"\\\\|,.<>/?]).{8,20}$";
|
|
||||||
return Pattern.matches(passwordPattern, password);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package com.kamco.cd.kamcoback.postgres.core;
|
|||||||
|
|
||||||
import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator;
|
import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator;
|
||||||
import com.kamco.cd.kamcoback.common.enums.StatusType;
|
import com.kamco.cd.kamcoback.common.enums.StatusType;
|
||||||
|
import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode;
|
||||||
|
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.CommonStringUtils;
|
||||||
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
||||||
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
||||||
import com.kamco.cd.kamcoback.members.dto.MembersDto.AddReq;
|
import com.kamco.cd.kamcoback.members.dto.MembersDto.AddReq;
|
||||||
@@ -18,6 +21,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -34,8 +38,8 @@ public class MembersCoreService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Long saveMembers(AddReq addReq) {
|
public Long saveMembers(AddReq addReq) {
|
||||||
if (membersRepository.existsByUserId(addReq.getUserId())) {
|
if (membersRepository.existsByEmployeeNo(addReq.getEmployeeNo())) {
|
||||||
throw new DuplicateMemberException(Field.USER_ID, addReq.getUserId());
|
throw new DuplicateMemberException(Field.EMPLOYEE_NO, addReq.getEmployeeNo());
|
||||||
}
|
}
|
||||||
|
|
||||||
// salt 생성, 사번이 salt
|
// salt 생성, 사번이 salt
|
||||||
@@ -44,7 +48,7 @@ public class MembersCoreService {
|
|||||||
String hashedPassword = BCrypt.hashpw(addReq.getTempPassword(), salt);
|
String hashedPassword = BCrypt.hashpw(addReq.getTempPassword(), salt);
|
||||||
|
|
||||||
MemberEntity memberEntity = new MemberEntity();
|
MemberEntity memberEntity = new MemberEntity();
|
||||||
memberEntity.setUserId(addReq.getUserId());
|
memberEntity.setUserId(addReq.getEmployeeNo());
|
||||||
memberEntity.setUserRole(addReq.getUserRole());
|
memberEntity.setUserRole(addReq.getUserRole());
|
||||||
memberEntity.setTempPassword(addReq.getTempPassword().trim()); // 임시 패스워드는 암호화 하지 않음
|
memberEntity.setTempPassword(addReq.getTempPassword().trim()); // 임시 패스워드는 암호화 하지 않음
|
||||||
memberEntity.setPassword(hashedPassword);
|
memberEntity.setPassword(hashedPassword);
|
||||||
@@ -71,41 +75,35 @@ public class MembersCoreService {
|
|||||||
|
|
||||||
// 임시 패스워드는 암호화 하지 않음
|
// 임시 패스워드는 암호화 하지 않음
|
||||||
if (StringUtils.isNotBlank(updateReq.getTempPassword())) {
|
if (StringUtils.isNotBlank(updateReq.getTempPassword())) {
|
||||||
// 임시 패스워드가 기존과 다르면 패스워드 변경으로 처리함
|
/**
|
||||||
// 상태 INACTIVE로 변경하여 사용자가 로그인할때 패스워드 변경하게함
|
* 임시 패스워드가 기존과 다르면 패스워드 변경으로 처리함 상태 PENDING 으로 변경하여 사용자가 로그인할때 패스워드 변경하게함 패스워드 리셋이므로 로그인
|
||||||
// 패스워드 리셋이므로 로그인 실패카운트 초기화처리함
|
* 실패카운트 초기화처리함
|
||||||
|
*/
|
||||||
if (!memberEntity.getTempPassword().equals(updateReq.getTempPassword().trim())) {
|
if (!memberEntity.getTempPassword().equals(updateReq.getTempPassword().trim())) {
|
||||||
memberEntity.setStatus(StatusType.INACTIVE.getId());
|
// 패스워드 유효성 검사
|
||||||
|
if (!CommonStringUtils.isValidPassword(updateReq.getTempPassword())) {
|
||||||
|
throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
memberEntity.setStatus(StatusType.PENDING.getId());
|
||||||
memberEntity.setLoginFailCount(0);
|
memberEntity.setLoginFailCount(0);
|
||||||
}
|
}
|
||||||
memberEntity.setTempPassword(updateReq.getTempPassword().trim());
|
memberEntity.setTempPassword(updateReq.getTempPassword().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(updateReq.getEmployeeNo())) {
|
|
||||||
memberEntity.setEmployeeNo(updateReq.getEmployeeNo());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(updateReq.getStatus())) {
|
|
||||||
memberEntity.setStatus(updateReq.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
memberEntity.setUpdtrUid(userUtil.getId());
|
memberEntity.setUpdtrUid(userUtil.getId());
|
||||||
|
|
||||||
membersRepository.save(memberEntity);
|
membersRepository.save(memberEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 관리자 계정 삭제 처리
|
* 미사용 처리
|
||||||
*
|
*
|
||||||
* @param uuid
|
* @param uuid
|
||||||
*/
|
*/
|
||||||
public void deleteAccount(UUID uuid) {
|
public void deleteMember(UUID uuid) {
|
||||||
MemberEntity memberEntity =
|
MemberEntity memberEntity =
|
||||||
membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
|
membersRepository.findByUUID(uuid).orElseThrow(MemberNotFoundException::new);
|
||||||
|
memberEntity.setStatus(StatusType.INACTIVE.getId());
|
||||||
memberEntity.setStatus(StatusType.DELETED.getId());
|
|
||||||
memberEntity.setUpdatedDttm(ZonedDateTime.now());
|
|
||||||
memberEntity.setUpdtrUid(userUtil.getId());
|
|
||||||
membersRepository.save(memberEntity);
|
membersRepository.save(memberEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +114,12 @@ public class MembersCoreService {
|
|||||||
*/
|
*/
|
||||||
public void resetPassword(String id, MembersDto.InitReq initReq) {
|
public void resetPassword(String id, MembersDto.InitReq initReq) {
|
||||||
MemberEntity memberEntity =
|
MemberEntity memberEntity =
|
||||||
membersRepository.findByUserId(id).orElseThrow(() -> new MemberNotFoundException());
|
membersRepository.findByEmployeeNo(id).orElseThrow(() -> new MemberNotFoundException());
|
||||||
|
|
||||||
|
// 임시 패스워드 확인
|
||||||
|
if (!memberEntity.getTempPassword().equals(initReq.getTempPassword())) {
|
||||||
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||||
|
}
|
||||||
|
|
||||||
String salt =
|
String salt =
|
||||||
BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim());
|
BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim());
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class MemberEntity {
|
|||||||
@Size(max = 20)
|
@Size(max = 20)
|
||||||
@ColumnDefault("'INACTIVE'")
|
@ColumnDefault("'INACTIVE'")
|
||||||
@Column(name = "status", length = 20)
|
@Column(name = "status", length = 20)
|
||||||
private String status = StatusType.INACTIVE.getId();
|
private String status = StatusType.PENDING.getId();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ColumnDefault("now()")
|
@ColumnDefault("now()")
|
||||||
|
|||||||
@@ -170,48 +170,53 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
@Override
|
@Override
|
||||||
public void deleteByMngYyyyMngAll(int mngYyyy) {
|
public void deleteByMngYyyyMngAll(int mngYyyy) {
|
||||||
|
|
||||||
long deletedFileCount = queryFactory
|
long deletedFileCount =
|
||||||
.delete(mapSheetMngFileEntity)
|
queryFactory
|
||||||
.where(mapSheetMngFileEntity.mngYyyy.eq(mngYyyy))
|
.delete(mapSheetMngFileEntity)
|
||||||
.execute();
|
.where(mapSheetMngFileEntity.mngYyyy.eq(mngYyyy))
|
||||||
|
.execute();
|
||||||
|
|
||||||
long deletedHisCount = queryFactory
|
long deletedHisCount =
|
||||||
.delete(mapSheetMngHstEntity)
|
queryFactory
|
||||||
.where(mapSheetMngHstEntity.mngYyyy.eq(mngYyyy))
|
.delete(mapSheetMngHstEntity)
|
||||||
.execute();
|
.where(mapSheetMngHstEntity.mngYyyy.eq(mngYyyy))
|
||||||
|
.execute();
|
||||||
|
|
||||||
long deletedMngCount = queryFactory
|
long deletedMngCount =
|
||||||
.delete(mapSheetMngEntity)
|
queryFactory
|
||||||
.where(mapSheetMngEntity.mngYyyy.eq(mngYyyy))
|
.delete(mapSheetMngEntity)
|
||||||
.execute();
|
.where(mapSheetMngEntity.mngYyyy.eq(mngYyyy))
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByMngYyyyMng(int mngYyyy) {
|
public void deleteByMngYyyyMng(int mngYyyy) {
|
||||||
|
|
||||||
long deletedMngCount = queryFactory
|
long deletedMngCount =
|
||||||
.delete(mapSheetMngEntity)
|
queryFactory
|
||||||
.where(mapSheetMngEntity.mngYyyy.eq(mngYyyy))
|
.delete(mapSheetMngEntity)
|
||||||
.execute();
|
.where(mapSheetMngEntity.mngYyyy.eq(mngYyyy))
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByMngYyyyMngHst(int mngYyyy) {
|
public void deleteByMngYyyyMngHst(int mngYyyy) {
|
||||||
|
|
||||||
long deletedHisCount = queryFactory
|
long deletedHisCount =
|
||||||
.delete(mapSheetMngHstEntity)
|
queryFactory
|
||||||
.where(mapSheetMngHstEntity.mngYyyy.eq(mngYyyy))
|
.delete(mapSheetMngHstEntity)
|
||||||
.execute();
|
.where(mapSheetMngHstEntity.mngYyyy.eq(mngYyyy))
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByMngYyyyMngFile(int mngYyyy) {
|
public void deleteByMngYyyyMngFile(int mngYyyy) {
|
||||||
|
|
||||||
long deletedFileCount = queryFactory
|
long deletedFileCount =
|
||||||
.delete(mapSheetMngFileEntity)
|
queryFactory
|
||||||
.where(mapSheetMngFileEntity.mngYyyy.eq(mngYyyy))
|
.delete(mapSheetMngFileEntity)
|
||||||
.execute();
|
.where(mapSheetMngFileEntity.mngYyyy.eq(mngYyyy))
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ public interface MembersRepositoryCustom {
|
|||||||
|
|
||||||
boolean existsByUserId(String userId);
|
boolean existsByUserId(String userId);
|
||||||
|
|
||||||
|
boolean existsByEmployeeNo(String employeeNo);
|
||||||
|
|
||||||
|
Optional<MemberEntity> findByEmployeeNo(String employeeNo);
|
||||||
|
|
||||||
Optional<MemberEntity> findByUserId(String userId);
|
Optional<MemberEntity> findByUserId(String userId);
|
||||||
|
|
||||||
Optional<MemberEntity> findByUUID(UUID uuid);
|
Optional<MemberEntity> findByUUID(UUID uuid);
|
||||||
|
|||||||
@@ -40,6 +40,22 @@ public class MembersRepositoryImpl implements MembersRepositoryCustom {
|
|||||||
!= null;
|
!= null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 사용자 사번 조회
|
||||||
|
*
|
||||||
|
* @param employeeNo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean existsByEmployeeNo(String employeeNo) {
|
||||||
|
return queryFactory
|
||||||
|
.selectOne()
|
||||||
|
.from(memberEntity)
|
||||||
|
.where(memberEntity.employeeNo.eq(employeeNo))
|
||||||
|
.fetchFirst()
|
||||||
|
!= null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 사용자 조회 user id
|
* 사용자 조회 user id
|
||||||
*
|
*
|
||||||
@@ -52,6 +68,21 @@ public class MembersRepositoryImpl implements MembersRepositoryCustom {
|
|||||||
queryFactory.selectFrom(memberEntity).where(memberEntity.userId.eq(userId)).fetchOne());
|
queryFactory.selectFrom(memberEntity).where(memberEntity.userId.eq(userId)).fetchOne());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 사용자 조회 employeed no
|
||||||
|
*
|
||||||
|
* @param employeeNo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Optional<MemberEntity> findByEmployeeNo(String employeeNo) {
|
||||||
|
return Optional.ofNullable(
|
||||||
|
queryFactory
|
||||||
|
.selectFrom(memberEntity)
|
||||||
|
.where(memberEntity.employeeNo.eq(employeeNo))
|
||||||
|
.fetchOne());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 회원정보 목록 조회
|
* 회원정보 목록 조회
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ spring:
|
|||||||
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
#url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||||
url: jdbc:postgresql://localhost:15432/kamco_cds
|
#url: jdbc:postgresql://localhost:15432/kamco_cds
|
||||||
username: kamco_cds
|
username: kamco_cds
|
||||||
password: kamco_cds_Q!W@E#R$
|
password: kamco_cds_Q!W@E#R$
|
||||||
hikari:
|
hikari:
|
||||||
@@ -29,6 +29,10 @@ spring:
|
|||||||
port: 6379
|
port: 6379
|
||||||
password: 1234
|
password: 1234
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
org.springframework.security: DEBUG
|
||||||
|
|
||||||
jwt:
|
jwt:
|
||||||
secret: "kamco_token_9b71e778-19a3-4c1d-97bf-2d687de17d5b"
|
secret: "kamco_token_9b71e778-19a3-4c1d-97bf-2d687de17d5b"
|
||||||
access-token-validity-in-ms: 86400000 # 1일
|
access-token-validity-in-ms: 86400000 # 1일
|
||||||
|
|||||||
Reference in New Issue
Block a user