관리자 관리수정, 에러코드 공통 추가
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
package com.kamco.cd.kamcoback.auth;
|
||||
|
||||
import com.kamco.cd.kamcoback.members.service.AuthService;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AuthFailureEventListener implements ApplicationListener<AbstractAuthenticationFailureEvent> {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractAuthenticationFailureEvent event) {
|
||||
// 로그인 시도에 사용된 (username)
|
||||
Object principal = event.getAuthentication().getPrincipal();
|
||||
|
||||
if (principal instanceof String username) {
|
||||
// 로그인 실패 카운트 증가 로직 호출
|
||||
authService.loginFail(UUID.fromString(username));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAsyncExecution() {
|
||||
return ApplicationListener.super.supportsAsyncExecution();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.kamco.cd.kamcoback.auth;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode;
|
||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -28,14 +30,34 @@ public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||
MemberEntity member =
|
||||
membersRepository
|
||||
.findByUserId(username)
|
||||
.orElseThrow(() -> new BadCredentialsException("ID 또는 비밀번호가 일치하지 않습니다."));
|
||||
.orElseThrow(() -> new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND));
|
||||
|
||||
// 2. jBCrypt + 커스텀 salt 로 저장된 패스워드 비교
|
||||
if (!BCrypt.checkpw(rawPassword, member.getPassword())) {
|
||||
throw new BadCredentialsException("ID 또는 비밀번호가 일치하지 않습니다.");
|
||||
// 실패 카운트 저장
|
||||
int cnt = member.getLoginFailCount() + 1;
|
||||
if (cnt >= 5) {
|
||||
member.setStatus("INACTIVE");
|
||||
}
|
||||
member.setLoginFailCount(cnt);
|
||||
membersRepository.save(member);
|
||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||
}
|
||||
|
||||
// 3. 인증 성공 → UserDetails 생성
|
||||
// 3. 패스워드 실패 횟수 체크
|
||||
if (member.getLoginFailCount() >= 5) {
|
||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_EXCEEDED);
|
||||
}
|
||||
|
||||
// 4. 인증 성공 로그인 시간 저장
|
||||
if (member.getFirstLoginDttm() == null) {
|
||||
member.setFirstLoginDttm(ZonedDateTime.now());
|
||||
}
|
||||
member.setLastLoginDttm(ZonedDateTime.now());
|
||||
member.setLoginFailCount(0);
|
||||
membersRepository.save(member);
|
||||
|
||||
// 5. 인증 성공 → UserDetails 생성
|
||||
CustomUserDetails userDetails = new CustomUserDetails(member);
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
|
||||
@@ -7,7 +7,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RoleType implements EnumType {
|
||||
ROLE_ADMIN("시스템 관리자"),
|
||||
ROLE_ADMIN("관리자"),
|
||||
ROLE_LABELER("라벨러"),
|
||||
ROLE_REVIEWER("검수자");
|
||||
|
||||
@@ -22,4 +22,13 @@ public enum RoleType implements EnumType {
|
||||
public String getText() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static RoleType from(String value) {
|
||||
for (RoleType type : values()) {
|
||||
if (type.name().equalsIgnoreCase(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.kamco.cd.kamcoback.common.enums;
|
||||
|
||||
import com.kamco.cd.kamcoback.config.enums.EnumType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum StatusType implements EnumType {
|
||||
ACTIVE("활성"),
|
||||
INACTIVE("비활성"),
|
||||
ARCHIVED("탈퇴");
|
||||
|
||||
private final String desc;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.kamco.cd.kamcoback.common.enums.error;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.utils.ErrorCode;
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@Getter
|
||||
public enum AuthErrorCode implements ErrorCode {
|
||||
|
||||
// 🔐 로그인 관련
|
||||
LOGIN_ID_NOT_FOUND(
|
||||
"LOGIN_ID_NOT_FOUND",
|
||||
HttpStatus.UNAUTHORIZED),
|
||||
|
||||
LOGIN_PASSWORD_MISMATCH(
|
||||
"LOGIN_PASSWORD_MISMATCH",
|
||||
HttpStatus.UNAUTHORIZED),
|
||||
|
||||
LOGIN_PASSWORD_EXCEEDED(
|
||||
"LOGIN_PASSWORD_EXCEEDED",
|
||||
HttpStatus.UNAUTHORIZED);
|
||||
|
||||
private final String code;
|
||||
private final HttpStatus status;
|
||||
|
||||
AuthErrorCode(String code, HttpStatus status) {
|
||||
this.code = code;
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.kamco.cd.kamcoback.common.exception;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.utils.ErrorCode;
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@@ -19,4 +20,9 @@ public class CustomApiException extends RuntimeException {
|
||||
this.codeName = codeName;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public CustomApiException(ErrorCode errorCode) {
|
||||
this.codeName = errorCode.getCode();
|
||||
this.status = errorCode.getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.kamco.cd.kamcoback.common.utils;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public interface ErrorCode {
|
||||
|
||||
String getCode();
|
||||
|
||||
HttpStatus getStatus();
|
||||
}
|
||||
@@ -6,12 +6,14 @@ import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
@@ -40,21 +42,21 @@ public class SecurityConfig {
|
||||
customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용
|
||||
.authorizeHttpRequests(
|
||||
auth ->
|
||||
auth.anyRequest().permitAll());
|
||||
// requestMatchers(HttpMethod.OPTIONS, "/**")
|
||||
// .permitAll() // preflight 허용
|
||||
// .requestMatchers(
|
||||
// "/api/auth/signin",
|
||||
// "/api/auth/refresh",
|
||||
// "/swagger-ui/**",
|
||||
// "/v3/api-docs/**")
|
||||
// .permitAll()
|
||||
// .anyRequest()
|
||||
// .authenticated())
|
||||
// .addFilterBefore(
|
||||
// jwtAuthenticationFilter,
|
||||
// UsernamePasswordAuthenticationFilter
|
||||
// .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장.
|
||||
auth.requestMatchers(HttpMethod.OPTIONS, "/**")
|
||||
.permitAll() // preflight 허용
|
||||
.requestMatchers(
|
||||
"/api/auth/signin",
|
||||
"/api/auth/refresh",
|
||||
"/swagger-ui/**",
|
||||
"/api/members/{memberId}/password",
|
||||
"/v3/api-docs/**")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated())
|
||||
.addFilterBefore(
|
||||
jwtAuthenticationFilter,
|
||||
UsernamePasswordAuthenticationFilter
|
||||
.class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장.
|
||||
;
|
||||
|
||||
return http.build();
|
||||
|
||||
@@ -20,9 +20,11 @@ public class ApiResponseDto<T> {
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private T errorData;
|
||||
|
||||
@JsonIgnore private HttpStatus httpStatus;
|
||||
@JsonIgnore
|
||||
private HttpStatus httpStatus;
|
||||
|
||||
@JsonIgnore private Long errorLogUid;
|
||||
@JsonIgnore
|
||||
private Long errorLogUid;
|
||||
|
||||
public ApiResponseDto(T data) {
|
||||
this.data = data;
|
||||
@@ -47,7 +49,7 @@ public class ApiResponseDto<T> {
|
||||
}
|
||||
|
||||
public ApiResponseDto(
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
|
||||
this.error = new Error(code.getId(), message);
|
||||
this.httpStatus = httpStatus;
|
||||
this.errorLogUid = errorLogUid;
|
||||
@@ -88,17 +90,17 @@ public class ApiResponseDto<T> {
|
||||
}
|
||||
|
||||
public static ApiResponseDto<String> createException(
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus) {
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus) {
|
||||
return new ApiResponseDto<>(code, message, httpStatus);
|
||||
}
|
||||
|
||||
public static ApiResponseDto<String> createException(
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
|
||||
return new ApiResponseDto<>(code, message, httpStatus, errorLogUid);
|
||||
}
|
||||
|
||||
public static <T> ApiResponseDto<T> createException(
|
||||
ApiResponseCode code, String message, T data) {
|
||||
ApiResponseCode code, String message, T data) {
|
||||
return new ApiResponseDto<>(code, message, data);
|
||||
}
|
||||
|
||||
@@ -114,7 +116,9 @@ public class ApiResponseDto<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/** Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object */
|
||||
/**
|
||||
* Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object
|
||||
*/
|
||||
@Getter
|
||||
public static class ResponseObj {
|
||||
|
||||
@@ -164,6 +168,9 @@ public class ApiResponseDto<T> {
|
||||
NOT_FOUND_USER_FOR_EMAIL("이메일로 유저를 찾을 수 없습니다."),
|
||||
NOT_FOUND_USER("사용자를 찾을 수 없습니다."),
|
||||
UNPROCESSABLE_ENTITY("이 데이터는 삭제할 수 없습니다."),
|
||||
LOGIN_ID_NOT_FOUND("아이디를 잘못 입력하셨습니다."),
|
||||
LOGIN_PASSWORD_MISMATCH("비밀번호를 잘못 입력하셨습니다."),
|
||||
LOGIN_PASSWORD_EXCEEDED("비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.\n로그인 오류에 대해 관리자에게 문의하시기 바랍니다."),
|
||||
INVALID_EMAIL_TOKEN(
|
||||
"You can only reset your password within 24 hours from when the email was sent.\n"
|
||||
+ "To reset your password again, please submit a new request through \"Forgot"
|
||||
|
||||
@@ -5,4 +5,17 @@ public interface EnumType {
|
||||
String getId();
|
||||
|
||||
String getText();
|
||||
|
||||
// code로 text
|
||||
static <E extends Enum<E> & EnumType> E fromId(Class<E> enumClass, String id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
for (E e : enumClass.getEnumConstants()) {
|
||||
if (id.equalsIgnoreCase(e.getId())) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null; // 못 찾으면 null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.kamco.cd.kamcoback.members.dto.SignInRequest;
|
||||
import com.kamco.cd.kamcoback.members.service.AuthService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
@@ -14,7 +15,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.nio.file.AccessDeniedException;
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -55,12 +55,43 @@ public class AuthController {
|
||||
content = @Content(schema = @Schema(implementation = TokenResponse.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "401",
|
||||
description = "ID 또는 비밀번호 불일치",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "400",
|
||||
description = "미사용 상태",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
description = "로그인 실패 (아이디/비밀번호 오류, 계정잠금 등)",
|
||||
content =
|
||||
@Content(
|
||||
schema = @Schema(implementation = ErrorResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "아이디 입력 오류",
|
||||
description = "존재하지 않는 아이디",
|
||||
value = """
|
||||
{
|
||||
"code": "LOGIN_ID_NOT_FOUND",
|
||||
"message": "아이디를 잘못 입력하셨습니다.",
|
||||
"detail": null
|
||||
}
|
||||
"""),
|
||||
@ExampleObject(
|
||||
name = "비밀번호 입력 오류 (4회 이하)",
|
||||
description = "아이디는 정상, 비밀번호를 여러 번 틀린 경우",
|
||||
value = """
|
||||
{
|
||||
"code": "LOGIN_PASSWORD_MISMATCH",
|
||||
"message": "비밀번호를 잘못 입력하셨습니다.",
|
||||
"detail": "비밀번호 입력 오류 3회, 2회 남았습니다."
|
||||
}
|
||||
"""),
|
||||
@ExampleObject(
|
||||
name = "비밀번호 오류 횟수 초과",
|
||||
description = "비밀번호 5회 이상 오류로 계정 잠김",
|
||||
value = """
|
||||
{
|
||||
"code": "LOGIN_PASSWORD_EXCEEDED",
|
||||
"message": "비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.",
|
||||
"detail": "로그인 오류에 대해 관리자에게 문의하시기 바랍니다."
|
||||
}
|
||||
""")
|
||||
}
|
||||
))
|
||||
})
|
||||
public ApiResponseDto<TokenResponse> signin(
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||
@@ -75,15 +106,14 @@ public class AuthController {
|
||||
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
|
||||
|
||||
String status = authService.getUserStatus(request);
|
||||
if ("INACTIVE".equals(status)) {
|
||||
|
||||
// INACTIVE 비활성 상태(새로운 패스워드 입력 해야함), ARCHIVED 탈퇴
|
||||
if (!"ACTIVE".equals(status)) {
|
||||
return ApiResponseDto.ok(new TokenResponse(status, null, null));
|
||||
}
|
||||
|
||||
String username = authentication.getName(); // UserDetailsService 에서 사용한 username
|
||||
|
||||
// 로그인 시간 저장
|
||||
authService.saveLogin(UUID.fromString(username));
|
||||
|
||||
String accessToken = jwtTokenProvider.createAccessToken(username);
|
||||
String refreshToken = jwtTokenProvider.createRefreshToken(username);
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public class MembersApiController {
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@PatchMapping("/{memberId}/password")
|
||||
public ApiResponseDto<Long> resetPassword(@PathVariable Long memberId, @RequestBody @Valid MembersDto.InitReq initReq) {
|
||||
public ApiResponseDto<String> resetPassword(@PathVariable String memberId, @RequestBody @Valid MembersDto.InitReq initReq) {
|
||||
membersService.resetPassword(memberId, initReq);
|
||||
return ApiResponseDto.createOK(memberId);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.kamco.cd.kamcoback.members.dto;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.enums.RoleType;
|
||||
import com.kamco.cd.kamcoback.common.enums.StatusType;
|
||||
import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
|
||||
import com.kamco.cd.kamcoback.config.enums.EnumType;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
@@ -22,11 +25,13 @@ public class MembersDto {
|
||||
private Long id;
|
||||
private UUID uuid;
|
||||
private String userRole;
|
||||
private String userRoleName;
|
||||
private String name;
|
||||
private String userId;
|
||||
private String employeeNo;
|
||||
private String tempPassword;
|
||||
private String status;
|
||||
private String statusName;
|
||||
@JsonFormatDttm
|
||||
private ZonedDateTime createdDttm;
|
||||
@JsonFormatDttm
|
||||
@@ -40,11 +45,13 @@ public class MembersDto {
|
||||
Long id,
|
||||
UUID uuid,
|
||||
String userRole,
|
||||
String userRoleName,
|
||||
String name,
|
||||
String userId,
|
||||
String employeeNo,
|
||||
String tempPassword,
|
||||
String status,
|
||||
String statusName,
|
||||
ZonedDateTime createdDttm,
|
||||
ZonedDateTime updatedDttm,
|
||||
ZonedDateTime firstLoginDttm,
|
||||
@@ -53,16 +60,29 @@ public class MembersDto {
|
||||
this.id = id;
|
||||
this.uuid = uuid;
|
||||
this.userRole = userRole;
|
||||
this.userRoleName = getUserRoleName(userRole);
|
||||
this.name = name;
|
||||
this.userId = userId;
|
||||
this.employeeNo = employeeNo;
|
||||
this.tempPassword = tempPassword;
|
||||
this.status = status;
|
||||
this.statusName = getStatusName(status);
|
||||
this.createdDttm = createdDttm;
|
||||
this.updatedDttm = updatedDttm;
|
||||
this.firstLoginDttm = firstLoginDttm;
|
||||
this.lastLoginDttm = lastLoginDttm;
|
||||
}
|
||||
|
||||
private String getUserRoleName(String roleId) {
|
||||
RoleType type = EnumType.fromId(RoleType.class, roleId);
|
||||
return type.getText();
|
||||
}
|
||||
|
||||
private String getStatusName(String status) {
|
||||
StatusType type = EnumType.fromId(StatusType.class, status);
|
||||
return type.getText();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.members.service;
|
||||
|
||||
import com.kamco.cd.kamcoback.members.dto.SignInRequest;
|
||||
import com.kamco.cd.kamcoback.postgres.core.MembersCoreService;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -14,26 +13,6 @@ public class AuthService {
|
||||
|
||||
private final MembersCoreService membersCoreService;
|
||||
|
||||
/**
|
||||
* 로그인 일시 저장
|
||||
*
|
||||
* @param uuid
|
||||
*/
|
||||
@Transactional
|
||||
public void saveLogin(UUID uuid) {
|
||||
membersCoreService.saveLogin(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인 실패 저장
|
||||
*
|
||||
* @param uuid
|
||||
*/
|
||||
@Transactional
|
||||
public void loginFail(UUID uuid) {
|
||||
membersCoreService.loginFail(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 상태 조회
|
||||
*
|
||||
|
||||
@@ -35,7 +35,7 @@ public class MembersService {
|
||||
* @param initReq
|
||||
*/
|
||||
@Transactional
|
||||
public void resetPassword(Long id, MembersDto.InitReq initReq) {
|
||||
public void resetPassword(String id, MembersDto.InitReq initReq) {
|
||||
if (!isValidPassword(initReq.getPassword())) {
|
||||
throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
@@ -49,7 +49,8 @@ public class MembersService {
|
||||
* @return
|
||||
*/
|
||||
private boolean isValidPassword(String password) {
|
||||
String regex = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[!@#$]).{8,20}$";
|
||||
return Pattern.matches(regex, password);
|
||||
String passwordPattern =
|
||||
"^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-\\[\\]{};':\"\\\\|,.<>/?]).{8,20}$";
|
||||
return Pattern.matches(passwordPattern, password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.kamco.cd.kamcoback.postgres.core;
|
||||
|
||||
import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator;
|
||||
import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode;
|
||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||
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.Basic;
|
||||
@@ -8,7 +10,6 @@ import com.kamco.cd.kamcoback.members.dto.SignInRequest;
|
||||
import com.kamco.cd.kamcoback.members.exception.MemberException.DuplicateMemberException;
|
||||
import com.kamco.cd.kamcoback.members.exception.MemberException.DuplicateMemberException.Field;
|
||||
import com.kamco.cd.kamcoback.members.exception.MemberException.MemberNotFoundException;
|
||||
import com.kamco.cd.kamcoback.members.exception.MemberException.PasswordNotFoundException;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository;
|
||||
import java.time.ZonedDateTime;
|
||||
@@ -99,12 +100,12 @@ public class MembersCoreService {
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void resetPassword(Long id, MembersDto.InitReq initReq) {
|
||||
public void resetPassword(String id, MembersDto.InitReq initReq) {
|
||||
MemberEntity memberEntity =
|
||||
membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException());
|
||||
membersRepository.findByUserId(id).orElseThrow(() -> new MemberNotFoundException());
|
||||
|
||||
if (!memberEntity.getTempPassword().equals(initReq.getTempPassword())) {
|
||||
throw new PasswordNotFoundException();
|
||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||
}
|
||||
|
||||
String salt =
|
||||
@@ -129,41 +130,6 @@ public class MembersCoreService {
|
||||
return membersRepository.findByMembers(searchReq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 최초 로그인 저장 마지막 로그인 저장
|
||||
*
|
||||
* @param uuid
|
||||
*/
|
||||
public void saveLogin(UUID uuid) {
|
||||
MemberEntity memberEntity =
|
||||
membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
|
||||
|
||||
if (memberEntity.getFirstLoginDttm() == null) {
|
||||
memberEntity.setFirstLoginDttm(ZonedDateTime.now());
|
||||
}
|
||||
memberEntity.setLastLoginDttm(ZonedDateTime.now());
|
||||
memberEntity.setLoginFailCount(0);
|
||||
membersRepository.save(memberEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인 실패시 상태 저장
|
||||
*
|
||||
* @param uuid
|
||||
*/
|
||||
public void loginFail(UUID uuid) {
|
||||
MemberEntity memberEntity =
|
||||
membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
|
||||
|
||||
int failCnt = memberEntity.getLoginFailCount() + 1;
|
||||
if (failCnt >= 5) {
|
||||
memberEntity.setStatus("INACTIVE");
|
||||
}
|
||||
|
||||
memberEntity.setLoginFailCount(failCnt);
|
||||
membersRepository.save(memberEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 상태 조회
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user