회원관리 관리 수정

This commit is contained in:
2025-12-10 17:30:54 +09:00
parent 51cffccf4c
commit bdb5ba7011
12 changed files with 470 additions and 502 deletions

View File

@@ -0,0 +1,31 @@
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();
}
}

View File

@@ -13,7 +13,6 @@ 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.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
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;
@@ -31,101 +30,81 @@ public class AdminApiController {
@Operation(summary = "관리자 계정 등록", description = "관리자 계정 등록") @Operation(summary = "관리자 계정 등록", description = "관리자 계정 등록")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "등록 성공", description = "등록 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Long.class))), schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PostMapping("/join") @PostMapping("/join")
public ApiResponseDto<Long> saveMember( public ApiResponseDto<Long> saveMember(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "관리자 계정 등록", description = "관리자 계정 등록",
required = true, required = true,
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = MembersDto.AddReq.class))) schema = @Schema(implementation = MembersDto.AddReq.class)))
@RequestBody @RequestBody
@Valid @Valid
MembersDto.AddReq addReq) { MembersDto.AddReq addReq) {
return ApiResponseDto.createOK(adminService.saveMember(addReq)); return ApiResponseDto.createOK(adminService.saveMember(addReq));
} }
@Operation(summary = "관리자 계정 수정", description = "관리자 계정 수정") @Operation(summary = "관리자 계정 수정", description = "관리자 계정 수정")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "수정 성공", description = "수정 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Long.class))), schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PutMapping("/{uuid}") @PutMapping("/{uuid}")
public ApiResponseDto<UUID> updateMembers( public ApiResponseDto<UUID> updateMembers(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "관리자 계정 수정", description = "관리자 계정 수정",
required = true, required = true,
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = MembersDto.UpdateReq.class))) schema = @Schema(implementation = MembersDto.UpdateReq.class)))
@PathVariable @PathVariable
UUID uuid, UUID uuid,
@RequestBody MembersDto.UpdateReq updateReq) { @RequestBody @Valid MembersDto.UpdateReq updateReq) {
adminService.updateMembers(uuid, updateReq); adminService.updateMembers(uuid, updateReq);
return ApiResponseDto.createOK(UUID.randomUUID()); return ApiResponseDto.createOK(UUID.randomUUID());
} }
@Operation(summary = "회원 탈퇴", description = "회원 탈퇴") @Operation(summary = "관리자 계정 미사용 처리", description = "관리자 계정 미사용 처리")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "회원 탈퇴", description = "관리자 계정 미사용 처리",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@DeleteMapping("/delete/{uuid}") @DeleteMapping("/delete/{uuid}")
public ApiResponseDto<UUID> deleteAccount(@PathVariable UUID uuid) { public ApiResponseDto<UUID> deleteAccount(@PathVariable UUID uuid) {
adminService.deleteAccount(uuid); adminService.deleteAccount(uuid);
return ApiResponseDto.createOK(uuid); return ApiResponseDto.createOK(uuid);
} }
@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)
})
@PatchMapping("/{memberId}/password")
public ApiResponseDto<Long> resetPassword(@PathVariable Long memberId) {
adminService.resetPassword(memberId);
return ApiResponseDto.createOK(memberId);
}
} }

View File

@@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.auth.JwtTokenProvider;
import com.kamco.cd.kamcoback.auth.RefreshTokenService; import com.kamco.cd.kamcoback.auth.RefreshTokenService;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
import com.kamco.cd.kamcoback.members.dto.SignInRequest; 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.Operation;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@@ -13,6 +14,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.nio.file.AccessDeniedException; import java.nio.file.AccessDeniedException;
import java.time.Duration; import java.time.Duration;
import java.util.UUID;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@@ -36,6 +38,7 @@ public class AuthController {
private final AuthenticationManager authenticationManager; private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider; private final JwtTokenProvider jwtTokenProvider;
private final RefreshTokenService refreshTokenService; private final RefreshTokenService refreshTokenService;
private final AuthService authService;
@Value("${token.refresh-cookie-name}") @Value("${token.refresh-cookie-name}")
private String refreshCookieName; private String refreshCookieName;
@@ -47,45 +50,49 @@ public class AuthController {
@Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.") @Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "로그인 성공", description = "로그인 성공",
content = @Content(schema = @Schema(implementation = TokenResponse.class))), content = @Content(schema = @Schema(implementation = TokenResponse.class))),
@ApiResponse( @ApiResponse(
responseCode = "401", responseCode = "401",
description = "ID 또는 비밀번호 불일치", description = "ID 또는 비밀번호 불일치",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
public ApiResponseDto<TokenResponse> signin( public ApiResponseDto<TokenResponse> signin(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "로그인 요청 정보", description = "로그인 요청 정보",
required = true) required = true)
@RequestBody @RequestBody
SignInRequest request, SignInRequest request,
HttpServletResponse response) { HttpServletResponse response) {
Authentication authentication = Authentication authentication =
authenticationManager.authenticate( authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())); new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
String username = authentication.getName(); // UserDetailsService 에서 사용한 username String username = authentication.getName(); // UserDetailsService 에서 사용한 username
// 로그인 시간 저장
authService.saveLogin(UUID.fromString(username));
String accessToken = jwtTokenProvider.createAccessToken(username); String accessToken = jwtTokenProvider.createAccessToken(username);
String refreshToken = jwtTokenProvider.createRefreshToken(username); String refreshToken = jwtTokenProvider.createRefreshToken(username);
// Redis에 RefreshToken 저장 (TTL = 7일) // Redis에 RefreshToken 저장 (TTL = 7일)
refreshTokenService.save( refreshTokenService.save(
username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs()); username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
// HttpOnly + Secure 쿠키에 RefreshToken 저장 // HttpOnly + Secure 쿠키에 RefreshToken 저장
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, refreshToken) ResponseCookie.from(refreshCookieName, refreshToken)
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs())) .maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ApiResponseDto.ok(new TokenResponse(accessToken, refreshToken)); return ApiResponseDto.ok(new TokenResponse(accessToken, refreshToken));
} }
@@ -93,16 +100,16 @@ public class AuthController {
@Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.") @Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "재발급 성공", description = "재발급 성공",
content = @Content(schema = @Schema(implementation = TokenResponse.class))), content = @Content(schema = @Schema(implementation = TokenResponse.class))),
@ApiResponse( @ApiResponse(
responseCode = "401", responseCode = "401",
description = "만료되었거나 유효하지 않은 리프레시 토큰", description = "만료되었거나 유효하지 않은 리프레시 토큰",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response) public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response)
throws AccessDeniedException { throws AccessDeniedException {
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) { if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다."); throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다.");
} }
@@ -120,17 +127,17 @@ public class AuthController {
// Redis 갱신 // Redis 갱신
refreshTokenService.save( refreshTokenService.save(
username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs()); username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
// 쿠키 갱신 // 쿠키 갱신
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, newRefreshToken) ResponseCookie.from(refreshCookieName, newRefreshToken)
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs())) .maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ResponseEntity.ok(new TokenResponse(newAccessToken, newRefreshToken)); return ResponseEntity.ok(new TokenResponse(newAccessToken, newRefreshToken));
@@ -140,12 +147,12 @@ public class AuthController {
@Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.") @Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "로그아웃 성공", description = "로그아웃 성공",
content = @Content(schema = @Schema(implementation = Void.class))) content = @Content(schema = @Schema(implementation = Void.class)))
}) })
public ApiResponseDto<ResponseEntity<Object>> logout( public ApiResponseDto<ResponseEntity<Object>> logout(
Authentication authentication, HttpServletResponse response) { Authentication authentication, HttpServletResponse response) {
if (authentication != null) { if (authentication != null) {
String username = authentication.getName(); String username = authentication.getName();
// Redis에서 RefreshToken 삭제 // Redis에서 RefreshToken 삭제
@@ -154,17 +161,19 @@ public class AuthController {
// 쿠키 삭제 (Max-Age=0) // 쿠키 삭제 (Max-Age=0)
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, "") ResponseCookie.from(refreshCookieName, "")
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(0) .maxAge(0)
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ApiResponseDto.createOK(ResponseEntity.noContent().build()); return ApiResponseDto.createOK(ResponseEntity.noContent().build());
} }
public record TokenResponse(String accessToken, String refreshToken) {} public record TokenResponse(String accessToken, String refreshToken) {
}
} }

View File

@@ -10,13 +10,13 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.UUID; import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; 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.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -31,41 +31,41 @@ public class MembersApiController {
@Operation(summary = "회원정보 목록", description = "회원정보 조회") @Operation(summary = "회원정보 목록", description = "회원정보 조회")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "검색 성공", description = "검색 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Page.class))), schema = @Schema(implementation = Page.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@GetMapping @GetMapping
public ApiResponseDto<Page<Basic>> getMemberList( public ApiResponseDto<Page<Basic>> getMemberList(
@ParameterObject MembersDto.SearchReq searchReq) { @ParameterObject MembersDto.SearchReq searchReq) {
return ApiResponseDto.ok(membersService.findByMembers(searchReq)); return ApiResponseDto.ok(membersService.findByMembers(searchReq));
} }
@Operation(summary = "회원정보 수정", description = "회원정보 수정")
@Operation(summary = "비밀번호 초기화", description = "비밀번호 초기화")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "회원정보 수정", description = "비밀번호 초기화",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PutMapping("/{uuid}") @PatchMapping("/{memberId}/password")
public ApiResponseDto<UUID> updateMember( public ApiResponseDto<Long> resetPassword(@PathVariable Long memberId, @RequestBody @Valid MembersDto.InitReq initReq) {
@PathVariable UUID uuid, @RequestBody MembersDto.UpdateReq updateReq) { membersService.resetPassword(memberId, initReq);
// membersService.updateMember(uuid, updateReq); return ApiResponseDto.createOK(memberId);
return ApiResponseDto.createOK(uuid);
} }
} }

View File

@@ -1,7 +1,5 @@
package com.kamco.cd.kamcoback.members.dto; package com.kamco.cd.kamcoback.members.dto;
import com.kamco.cd.kamcoback.common.enums.RoleType;
import com.kamco.cd.kamcoback.common.utils.interfaces.EnumValid;
import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@@ -23,33 +21,47 @@ public class MembersDto {
private Long id; private Long id;
private UUID uuid; private UUID uuid;
private String employeeNo; private String userRole;
private String name; private String name;
private String email; private String userId;
private String employeeNo;
private String tempPassword;
private String status; private String status;
private String roleName; @JsonFormatDttm
@JsonFormatDttm private ZonedDateTime createdDttm; private ZonedDateTime createdDttm;
@JsonFormatDttm private ZonedDateTime updatedDttm; @JsonFormatDttm
private ZonedDateTime updatedDttm;
@JsonFormatDttm
private ZonedDateTime firstLoginDttm;
@JsonFormatDttm
private ZonedDateTime lastLoginDttm;
public Basic( public Basic(
Long id, Long id,
UUID uuid, UUID uuid,
String employeeNo, String userRole,
String name, String name,
String email, String userId,
String status, String employeeNo,
String roleName, String tempPassword,
ZonedDateTime createdDttm, String status,
ZonedDateTime updatedDttm) { ZonedDateTime createdDttm,
ZonedDateTime updatedDttm,
ZonedDateTime firstLoginDttm,
ZonedDateTime lastLoginDttm
) {
this.id = id; this.id = id;
this.uuid = uuid; this.uuid = uuid;
this.employeeNo = employeeNo; this.userRole = userRole;
this.name = name; this.name = name;
this.email = email; this.userId = userId;
this.employeeNo = employeeNo;
this.tempPassword = tempPassword;
this.status = status; this.status = status;
this.roleName = roleName;
this.createdDttm = createdDttm; this.createdDttm = createdDttm;
this.updatedDttm = updatedDttm; this.updatedDttm = updatedDttm;
this.firstLoginDttm = firstLoginDttm;
this.lastLoginDttm = lastLoginDttm;
} }
} }
@@ -59,21 +71,12 @@ public class MembersDto {
@AllArgsConstructor @AllArgsConstructor
public static class SearchReq { public static class SearchReq {
@Schema(description = "이름(name), 이메일(email), 사번(employeeNo)", example = "name") @Schema(description = "전체, 관리자(ROLE_ADMIN), 라벨러(ROLE_LABELER), 검수자(ROLE_REVIEWER)", example = "")
private String field; private String userRole;
@Schema(description = "키워드", example = "홍길동") @Schema(description = "키워드", example = "홍길동")
private String keyword; private String keyword;
@Schema(description = "라벨러 포함 여부", example = "true")
private boolean labeler = true;
@Schema(description = "검수자 포함 여부", example = "true")
private boolean reviewer = true;
@Schema(description = "운영자 포함 여부", example = "true")
private boolean admin = true;
// 페이징 파라미터 // 페이징 파라미터
@Schema(description = "페이지 번호 (0부터 시작) ", example = "0") @Schema(description = "페이지 번호 (0부터 시작) ", example = "0")
private int page = 0; private int page = 0;
@@ -112,7 +115,7 @@ public class MembersDto {
private String employeeNo; private String employeeNo;
public AddReq( public AddReq(
String userRole, String name, String userId, String tempPassword, String employeeNo) { String userRole, String name, String userId, String tempPassword, String employeeNo) {
this.userRole = userRole; this.userRole = userRole;
this.name = name; this.name = name;
this.userId = userId; this.userId = userId;
@@ -146,29 +149,10 @@ public class MembersDto {
@Getter @Getter
@Setter @Setter
public static class RolesDto { public static class InitReq {
@Schema(description = "UUID", example = "4e89e487-c828-4a34-a7fc-0d5b0e3b53b5") @Schema(description = "패스워드", example = "")
private UUID uuid; @Size(max = 255)
private String password;
@Schema(description = "역할 ROLE_ADMIN, ROLE_LABELER, ROLE_REVIEWER", example = "ROLE_ADMIN")
@EnumValid(enumClass = RoleType.class)
private String roleName;
public RolesDto(UUID uuid, String roleName) {
this.uuid = uuid;
this.roleName = roleName;
}
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class StatusDto {
@Schema(description = "변경할 상태값 ACTIVE, INACTIVE, ARCHIVED", example = "ACTIVE")
@NotBlank
private String status;
} }
} }

View File

@@ -1,11 +1,9 @@
package com.kamco.cd.kamcoback.members.service; package com.kamco.cd.kamcoback.members.service;
import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator;
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.mindrot.jbcrypt.BCrypt;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -17,69 +15,35 @@ public class AdminService {
private final MembersCoreService membersCoreService; private final MembersCoreService membersCoreService;
/** /**
* 회원가입 * 관리자 계정 등록
* *
* @param addReq * @param addReq
* @return * @return
*/ */
@Transactional @Transactional
public Long saveMember(MembersDto.AddReq addReq) { public Long saveMember(MembersDto.AddReq addReq) {
// salt 생성, 사번이 salt
String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getUserId().trim());
// 패스워드 암호화, 초기 패스워드 고정
String hashedPassword = BCrypt.hashpw(addReq.getTempPassword(), salt);
addReq.setTempPassword(hashedPassword);
return membersCoreService.saveMembers(addReq); return membersCoreService.saveMembers(addReq);
} }
/**
* 관리자 계정 수정
*
* @param uuid
* @param updateReq
*/
@Transactional
public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) { public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) {
membersCoreService.updateMembers(uuid, updateReq); membersCoreService.updateMembers(uuid, updateReq);
} }
/**
* 역할 추가
*
* @param rolesDto
*/
@Transactional
public void saveRoles(MembersDto.RolesDto rolesDto) {
// membersCoreService.saveRoles(rolesDto);
}
/** /**
* 역할 삭제 * 관리자 계정 미사용 처리
*
* @param rolesDto
*/
public void deleteRoles(MembersDto.RolesDto rolesDto) {
// membersCoreService.deleteRoles(rolesDto);
}
/**
* 역할 수정
*
* @param statusDto
*/
public void updateStatus(UUID uuid, MembersDto.StatusDto statusDto) {
// membersCoreService.updateStatus(uuid, statusDto);
}
/**
* 회원 탈퇴
* *
* @param uuid * @param uuid
*/ */
@Transactional
public void deleteAccount(UUID uuid) { public void deleteAccount(UUID uuid) {
// membersCoreService.deleteAccount(uuid); membersCoreService.deleteAccount(uuid);
}
/**
* 패스워드 초기화
*
* @param id
*/
public void resetPassword(Long id) {
// membersCoreService.resetPassword(id);
} }
} }

View File

@@ -0,0 +1,35 @@
package com.kamco.cd.kamcoback.members.service;
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;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
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);
}
}

View File

@@ -1,11 +1,13 @@
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.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 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.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -23,38 +25,22 @@ public class MembersService {
* @return * @return
*/ */
public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) { public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) {
return null; // membersCoreService.findByMembers(searchReq); return membersCoreService.findByMembers(searchReq);
} }
/** /**
* 회원정보 수정 * 패스워드 사용자 변경
* *
* @param uuid * @param id
* @param updateReq * @param initReq
*/ */
// public void updateMember(UUID uuid, MembersDto.UpdateReq updateReq) { @Transactional
// public void resetPassword(Long id, MembersDto.InitReq initReq) {
// if (StringUtils.isNotBlank(updateReq.getPassword())) { if (!isValidPassword(initReq.getPassword())) {
// throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST);
// if (!this.isValidPassword(updateReq.getPassword())) { }
// throw new CustomApiException("WRONG_PASSWORD", HttpStatus.BAD_REQUEST); membersCoreService.resetPassword(id, initReq);
// } }
//
// if (StringUtils.isBlank(updateReq.getEmployeeNo())) {
// throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST);
// }
//
// // salt 생성, 사번이 salt
// String salt =
// BCryptSaltGenerator.generateSaltWithEmployeeNo(updateReq.getEmployeeNo().trim());
//
// // 패스워드 암호화, 초기 패스워드 고정
// String hashedPassword = BCrypt.hashpw(updateReq.getPassword(), salt);
// updateReq.setPassword(hashedPassword);
// }
//
// membersCoreService.updateMembers(uuid, updateReq);
// }
/** /**
* 대문자 1개 이상 소문자 1개 이상 숫자 1개 이상 특수문자(!@#$) 1개 이상 * 대문자 1개 이상 소문자 1개 이상 숫자 1개 이상 특수문자(!@#$) 1개 이상

View File

@@ -1,16 +1,20 @@
package com.kamco.cd.kamcoback.postgres.core; package com.kamco.cd.kamcoback.postgres.core;
import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator;
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;
import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic;
import com.kamco.cd.kamcoback.members.exception.MemberException.DuplicateMemberException; 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.DuplicateMemberException.Field;
import com.kamco.cd.kamcoback.members.exception.MemberException.MemberNotFoundException; import com.kamco.cd.kamcoback.members.exception.MemberException.MemberNotFoundException;
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
import com.kamco.cd.kamcoback.postgres.repository.members.MembersArchivedRepository;
import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository; import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository;
import java.time.ZonedDateTime;
import java.util.UUID; import java.util.UUID;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@@ -18,10 +22,9 @@ import org.springframework.stereotype.Service;
public class MembersCoreService { public class MembersCoreService {
private final MembersRepository membersRepository; private final MembersRepository membersRepository;
private final MembersArchivedRepository memberArchivedRepository;
/** /**
* 회원가입 * 관리자 계정 등록
* *
* @param addReq * @param addReq
* @return * @return
@@ -30,11 +33,17 @@ public class MembersCoreService {
if (membersRepository.existsByUserId(addReq.getUserId())) { if (membersRepository.existsByUserId(addReq.getUserId())) {
throw new DuplicateMemberException(Field.USER_ID, addReq.getUserId()); throw new DuplicateMemberException(Field.USER_ID, addReq.getUserId());
} }
// salt 생성, 사번이 salt
String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getUserId().trim());
// 패스워드 암호화, 초기 패스워드 고정
String hashedPassword = BCrypt.hashpw(addReq.getTempPassword(), salt);
MemberEntity memberEntity = new MemberEntity(); MemberEntity memberEntity = new MemberEntity();
memberEntity.setUserId(addReq.getUserId()); memberEntity.setUserId(addReq.getUserId());
memberEntity.setUserRole(addReq.getUserRole()); memberEntity.setUserRole(addReq.getUserRole());
memberEntity.setTempPassword(addReq.getTempPassword()); memberEntity.setTempPassword(addReq.getTempPassword()); // 임시 패스워드는 암호화 하지 않음
memberEntity.setPassword(addReq.getTempPassword()); memberEntity.setPassword(hashedPassword);
memberEntity.setName(addReq.getName()); memberEntity.setName(addReq.getName());
memberEntity.setEmployeeNo(addReq.getEmployeeNo()); memberEntity.setEmployeeNo(addReq.getEmployeeNo());
@@ -42,22 +51,22 @@ public class MembersCoreService {
} }
/** /**
* 회원정보 수정 * 관리자 계정 수정
* *
* @param uuid * @param uuid
* @param updateReq * @param updateReq
*/ */
public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) { public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository.findByUUID(uuid).orElseThrow(MemberNotFoundException::new); membersRepository.findByUUID(uuid).orElseThrow(MemberNotFoundException::new);
if (StringUtils.isNotBlank(updateReq.getName())) { if (StringUtils.isNotBlank(updateReq.getName())) {
memberEntity.setName(updateReq.getName()); memberEntity.setName(updateReq.getName());
} }
// 임시 패스워드는 암호화 하지 않음
if (StringUtils.isNotBlank(updateReq.getTempPassword())) { if (StringUtils.isNotBlank(updateReq.getTempPassword())) {
memberEntity.setTempPassword(updateReq.getTempPassword()); memberEntity.setTempPassword(updateReq.getTempPassword());
memberEntity.setPassword(updateReq.getTempPassword());
} }
if (StringUtils.isNotBlank(memberEntity.getEmployeeNo())) { if (StringUtils.isNotBlank(memberEntity.getEmployeeNo())) {
@@ -66,123 +75,42 @@ public class MembersCoreService {
membersRepository.save(memberEntity); membersRepository.save(memberEntity);
} }
//
// /**
// * 역할 추가 /**
// * * 관리자 계정 미사용 처리
// * @param rolesDto *
// */ * @param uuid
// public void saveRoles(MembersDto.RolesDto rolesDto) { */
// public void deleteAccount(UUID uuid) {
// MemberEntity memberEntity = MemberEntity memberEntity =
// membersRepository membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
// .findByUUID(rolesDto.getUuid())
// .orElseThrow(() -> new MemberNotFoundException()); memberEntity.setStatus("INACTIVE");
// memberEntity.setUpdatedDttm(ZonedDateTime.now());
// if (memberRoleRepository.findByUuidAndRoleName(rolesDto)) { membersRepository.save(memberEntity);
// throw new MemberException.DuplicateMemberException( }
// MemberException.DuplicateMemberException.Field.DEFAULT, "중복된 역할이 있습니다.");
// }
// /**
// MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId(); * 패스워드 변경
// memberRoleEntityId.setMemberUuid(rolesDto.getUuid()); *
// memberRoleEntityId.setRoleName(rolesDto.getRoleName()); * @param id
// */
// MemberRoleEntity memberRoleEntity = new MemberRoleEntity(); public void resetPassword(Long id, MembersDto.InitReq initReq) {
// memberRoleEntity.setId(memberRoleEntityId); MemberEntity memberEntity =
// memberRoleEntity.setMemberUuid(memberEntity); membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException());
// memberRoleEntity.setCreatedDttm(ZonedDateTime.now());
// memberRoleRepository.save(memberRoleEntity); String salt =
// } BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim());
// // 패스워드 암호화
// /** String hashedPassword = BCrypt.hashpw(initReq.getPassword(), salt);
// * 역할 삭제
// * memberEntity.setPassword(hashedPassword);
// * @param rolesDto memberEntity.setStatus("ACTIVE");
// */ memberEntity.setUpdatedDttm(ZonedDateTime.now());
// public void deleteRoles(MembersDto.RolesDto rolesDto) { membersRepository.save(memberEntity);
// MemberEntity memberEntity = }
// membersRepository
// .findByUUID(rolesDto.getUuid())
// .orElseThrow(() -> new MemberNotFoundException());
//
// MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId();
// memberRoleEntityId.setMemberUuid(rolesDto.getUuid());
// memberRoleEntityId.setRoleName(rolesDto.getRoleName());
//
// MemberRoleEntity memberRoleEntity = new MemberRoleEntity();
// memberRoleEntity.setId(memberRoleEntityId);
// memberRoleEntity.setMemberUuid(memberEntity);
//
// memberRoleRepository.delete(memberRoleEntity);
// }
//
// /**
// * 상태 수정
// *
// * @param statusDto
// */
// public void updateStatus(UUID uuid, MembersDto.StatusDto statusDto) {
// MemberEntity memberEntity =
// membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
//
// memberEntity.setStatus(statusDto.getStatus());
// memberEntity.setUpdatedDttm(ZonedDateTime.now());
// membersRepository.save(memberEntity);
// }
//
// /**
// * 회원 탈퇴
// *
// * @param uuid
// */
// public void deleteAccount(UUID uuid) {
// MemberEntity memberEntity =
// membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
//
// MemberArchivedEntityId memberArchivedEntityId = new MemberArchivedEntityId();
// memberArchivedEntityId.setUserId(memberEntity.getId());
// memberArchivedEntityId.setUuid(memberEntity.getUuid());
//
// MemberArchivedEntity memberArchivedEntity = new MemberArchivedEntity();
// memberArchivedEntity.setId(memberArchivedEntityId);
// memberArchivedEntity.setEmployeeNo(memberEntity.getEmployeeNo());
// memberArchivedEntity.setName(memberEntity.getName());
// memberArchivedEntity.setPassword(memberEntity.getPassword());
// memberArchivedEntity.setEmail(memberEntity.getEmail());
// memberArchivedEntity.setStatus(memberEntity.getStatus());
// memberArchivedEntity.setCreatedDttm(memberEntity.getCreatedDttm());
// memberArchivedEntity.setArchivedDttm(ZonedDateTime.now());
// memberArchivedRepository.save(memberArchivedEntity);
//
// memberEntity.setStatus("ARCHIVED");
// memberEntity.setName("**********");
// memberEntity.setEmployeeNo("**********");
// memberEntity.setPassword("**********");
// memberEntity.setEmail("**********");
// memberEntity.setUpdatedDttm(ZonedDateTime.now());
// membersRepository.save(memberEntity);
// }
//
// /**
// * 패스워드 초기화
// *
// * @param id
// */
// public void resetPassword(Long id) {
// MemberEntity memberEntity =
// membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException());
//
// String salt =
// BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim());
// // 패스워드 암호화, 초기 패스워드 고정
// String hashedPassword = BCrypt.hashpw(password, salt);
//
// memberEntity.setPassword(hashedPassword);
// memberEntity.setStatus("INACTIVE");
// memberEntity.setUpdatedDttm(ZonedDateTime.now());
// membersRepository.save(memberEntity);
// }
// //
/** /**
@@ -191,7 +119,42 @@ public class MembersCoreService {
* @param searchReq * @param searchReq
* @return * @return
*/ */
// public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) { public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) {
// return membersRepository.findByMembers(searchReq); 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);
}
} }

View File

@@ -73,4 +73,14 @@ public class MemberEntity {
@ColumnDefault("now()") @ColumnDefault("now()")
@Column(name = "updated_dttm") @Column(name = "updated_dttm")
private ZonedDateTime updatedDttm = ZonedDateTime.now(); private ZonedDateTime updatedDttm = ZonedDateTime.now();
@Column(name = "first_login_dttm")
private ZonedDateTime firstLoginDttm;
@Column(name = "last_login_dttm")
private ZonedDateTime lastLoginDttm;
@Column(name = "login_fail_count")
@ColumnDefault("0")
private Integer loginFailCount = 0;
} }

View File

@@ -1,20 +1,19 @@
package com.kamco.cd.kamcoback.postgres.repository.members; package com.kamco.cd.kamcoback.postgres.repository.members;
import com.kamco.cd.kamcoback.members.dto.MembersDto;
import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic;
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import org.springframework.data.domain.Page;
public interface MembersRepositoryCustom { public interface MembersRepositoryCustom {
boolean existsByUserId(String userId); boolean existsByUserId(String userId);
Optional<MemberEntity> findByUserId(String employeeNo); Optional<MemberEntity> findByUserId(String userId);
Optional<MemberEntity> findByUUID(UUID uuid); Optional<MemberEntity> findByUUID(UUID uuid);
//
// Page<Basic> findByMembers(MembersDto.SearchReq searchReq);
//
// Page<Basic> findByMembers(MembersDto.SearchReq searchReq);
// Optional<MemberEntity> findByEmployeeNo(String employeeNo);
} }

View File

@@ -1,11 +1,20 @@
package com.kamco.cd.kamcoback.postgres.repository.members; package com.kamco.cd.kamcoback.postgres.repository.members;
import com.kamco.cd.kamcoback.members.dto.MembersDto;
import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic;
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
import com.kamco.cd.kamcoback.postgres.entity.QMemberEntity; import com.kamco.cd.kamcoback.postgres.entity.QMemberEntity;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory; import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
@@ -24,96 +33,95 @@ public class MembersRepositoryImpl implements MembersRepositoryCustom {
@Override @Override
public boolean existsByUserId(String userId) { public boolean existsByUserId(String userId) {
return queryFactory return queryFactory
.selectOne() .selectOne()
.from(memberEntity) .from(memberEntity)
.where(memberEntity.userId.eq(userId)) .where(memberEntity.userId.eq(userId))
.fetchFirst() .fetchFirst()
!= null; != null;
} }
/**
* 사용자 조회 user id
*
* @param userId
* @return
*/
@Override @Override
public Optional<MemberEntity> findByUserId(String userId) { public Optional<MemberEntity> findByUserId(String userId) {
return Optional.ofNullable( return Optional.ofNullable(
queryFactory.selectFrom(memberEntity).where(memberEntity.userId.eq(userId)).fetchOne()); queryFactory.selectFrom(memberEntity).where(memberEntity.userId.eq(userId)).fetchOne());
} }
// /** /**
// * 회원정보 목록 조회 * 회원정보 목록 조회
// * *
// * @param searchReq * @param searchReq
// * @return * @return
// */ */
// @Override @Override
// public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) { public Page<Basic> findByMembers(MembersDto.SearchReq searchReq) {
// Pageable pageable = searchReq.toPageable(); Pageable pageable = searchReq.toPageable();
// BooleanBuilder builder = new BooleanBuilder(); BooleanBuilder builder = new BooleanBuilder();
// BooleanBuilder leftBuilder = new BooleanBuilder();
// // 검색어
// if (StringUtils.isNotBlank(searchReq.getField())) { if (StringUtils.isNotBlank(searchReq.getKeyword())) {
// switch (searchReq.getField()) { String contains = "%" + searchReq.getKeyword() + "%";
// case "name" ->
// builder.and(memberEntity.name.containsIgnoreCase(searchReq.getKeyword().trim())); builder.and(
// } memberEntity.name.likeIgnoreCase(contains)
// } .or(memberEntity.userId.likeIgnoreCase(contains))
// .or(memberEntity.employeeNo.likeIgnoreCase(contains))
// List<String> roles = new ArrayList<>(); );
// // 라벨러 }
// if (searchReq.isLabeler()) {
// roles.add(RoleType.ROLE_LABELER.getId()); // 권한
// } if (StringUtils.isNotBlank(searchReq.getUserRole())) {
// builder.and(memberEntity.userRole.eq(searchReq.getUserRole()));
// // 시스템 전체 관리자 }
// if (searchReq.isAdmin()) {
// roles.add(RoleType.ROLE_ADMIN.getId()); List<MembersDto.Basic> content =
// } queryFactory
// .select(
// // 검수자 Projections.constructor(
// if (searchReq.isReviewer()) { MembersDto.Basic.class,
// roles.add(RoleType.ROLE_REVIEWER.getId()); memberEntity.id,
// } memberEntity.uuid,
// memberEntity.userRole,
// // 역할 in 조건 추가 memberEntity.name,
// if (!roles.isEmpty()) { memberEntity.userId,
// leftBuilder.and(memberRoleEntity.id.roleName.in(roles)); memberEntity.employeeNo,
// } memberEntity.tempPassword,
// memberEntity.status,
// List<MembersDto.Basic> content = memberEntity.createdDttm,
// queryFactory memberEntity.updatedDttm,
// .select( memberEntity.firstLoginDttm,
// Projections.constructor( memberEntity.lastLoginDttm
// MembersDto.Basic.class, ))
// memberEntity.id, .from(memberEntity)
// memberEntity.uuid, .where(builder)
// memberEntity.employeeNo, .offset(pageable.getOffset())
// memberEntity.name, .limit(pageable.getPageSize())
// null, .orderBy(memberEntity.createdDttm.desc())
// memberEntity.status, .fetch();
// memberRoleEntity.id.roleName,
// memberEntity.createdDttm, long total =
// memberEntity.updatedDttm)) queryFactory
// .from(memberEntity) .select(memberEntity)
// .leftJoin(memberRoleEntity) .from(memberEntity)
// .on(memberRoleEntity.memberUuid.uuid.eq(memberEntity.uuid).and(leftBuilder)) .fetchCount();
// .where(builder)
// .offset(pageable.getOffset()) return new PageImpl<>(content, pageable, total);
// .limit(pageable.getPageSize()) }
// .orderBy(memberEntity.createdDttm.desc())
// .fetch(); /**
// * 사용자 ID 조회 UUID
// long total = *
// queryFactory * @param uuid
// .select(memberEntity) * @return
// .from(memberEntity) */
// .leftJoin(memberRoleEntity)
// .on(memberRoleEntity.memberUuid.uuid.eq(memberEntity.uuid).and(leftBuilder))
// .fetchCount();
//
// return new PageImpl<>(content, pageable, total);
// }
//
@Override @Override
public Optional<MemberEntity> findByUUID(UUID uuid) { public Optional<MemberEntity> findByUUID(UUID uuid) {
return Optional.ofNullable( return Optional.ofNullable(
queryFactory.selectFrom(memberEntity).where(memberEntity.uuid.eq(uuid)).fetchOne()); queryFactory.selectFrom(memberEntity).where(memberEntity.uuid.eq(uuid)).fetchOne());
} }
} }