Merge remote-tracking branch 'origin/feat/dev_251201' into feat/dev_251201
# Conflicts: # src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java # src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java # src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java # src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java
This commit is contained in:
@@ -11,7 +11,6 @@ import org.springframework.security.authentication.AuthenticationProvider;
|
|||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -19,7 +18,6 @@ import org.springframework.stereotype.Component;
|
|||||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
private final MembersRepository membersRepository;
|
private final MembersRepository membersRepository;
|
||||||
private final UserDetailsService userDetailsService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
@@ -32,6 +30,11 @@ 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())) {
|
||||||
|
throw new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
// jBCrypt + 커스텀 salt 로 저장된 패스워드 비교
|
// jBCrypt + 커스텀 salt 로 저장된 패스워드 비교
|
||||||
if (!BCrypt.checkpw(rawPassword, member.getPassword())) {
|
if (!BCrypt.checkpw(rawPassword, member.getPassword())) {
|
||||||
// 실패 카운트 저장
|
// 실패 카운트 저장
|
||||||
@@ -44,11 +47,6 @@ public class CustomAuthenticationProvider implements AuthenticationProvider {
|
|||||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 삭제 상태
|
|
||||||
if (member.getStatus().equals(StatusType.DELETED.getId())) {
|
|
||||||
throw new CustomApiException(AuthErrorCode.LOGIN_ID_NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 패스워드 실패 횟수 체크
|
// 패스워드 실패 횟수 체크
|
||||||
if (member.getLoginFailCount() >= 5) {
|
if (member.getLoginFailCount() >= 5) {
|
||||||
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_EXCEEDED);
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_EXCEEDED);
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ public class MapSheetMngDto {
|
|||||||
private String mngPath;
|
private String mngPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Schema(name = "DeleteFileReq", description = "파일 삭제 요청")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class DeleteFileReq {
|
||||||
|
@Schema(description = "파일 경로", example = "/app/original-images/2024/00000001.tif")
|
||||||
|
private String filePath;
|
||||||
|
}
|
||||||
|
|
||||||
@Schema(name = "MngDto", description = "영상관리 검색 리턴")
|
@Schema(name = "MngDto", description = "영상관리 검색 리턴")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ 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
|
||||||
@@ -227,6 +228,14 @@ public class MapSheetMngService {
|
|||||||
return mapSheetMngCoreService.mngDataSave(AddReq);
|
return mapSheetMngCoreService.mngDataSave(AddReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MapSheetMngDto.DmlReturn uploadFile(MultipartFile file, Long hstUid) {
|
||||||
|
return mapSheetMngCoreService.uploadFile(file, hstUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapSheetMngDto.DmlReturn deleteFile(MapSheetMngDto.DeleteFileReq req) {
|
||||||
|
return mapSheetMngCoreService.deleteFile(req);
|
||||||
|
}
|
||||||
|
|
||||||
public MapSheetMngDto.DmlReturn uploadProcess(@Valid List<Long> hstUidList) {
|
public MapSheetMngDto.DmlReturn uploadProcess(@Valid List<Long> hstUidList) {
|
||||||
return mapSheetMngCoreService.uploadProcess(hstUidList);
|
return mapSheetMngCoreService.uploadProcess(hstUidList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.kamco.cd.kamcoback.members;
|
|||||||
import com.kamco.cd.kamcoback.auth.CustomUserDetails;
|
import com.kamco.cd.kamcoback.auth.CustomUserDetails;
|
||||||
import com.kamco.cd.kamcoback.auth.JwtTokenProvider;
|
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.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.config.api.ApiResponseDto;
|
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||||
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
import com.kamco.cd.kamcoback.members.dto.MembersDto;
|
||||||
import com.kamco.cd.kamcoback.members.dto.SignInRequest;
|
import com.kamco.cd.kamcoback.members.dto.SignInRequest;
|
||||||
@@ -104,16 +107,25 @@ public class AuthController {
|
|||||||
SignInRequest request,
|
SignInRequest request,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
|
|
||||||
Authentication authentication =
|
// 사용자 상태 조회
|
||||||
authenticationManager.authenticate(
|
|
||||||
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
|
|
||||||
|
|
||||||
String status = authService.getUserStatus(request);
|
String status = authService.getUserStatus(request);
|
||||||
|
Authentication authentication = null;
|
||||||
MembersDto.Member member = new MembersDto.Member();
|
MembersDto.Member member = new MembersDto.Member();
|
||||||
|
|
||||||
|
// 비활성 상태면 임시패스워드를 비교함
|
||||||
|
if (StatusType.INACTIVE.getId().equals(status)) {
|
||||||
|
if (!authService.isTempPasswordValid(request)) {
|
||||||
|
throw new CustomApiException(AuthErrorCode.LOGIN_PASSWORD_MISMATCH);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authentication =
|
||||||
|
authenticationManager.authenticate(
|
||||||
|
new UsernamePasswordAuthenticationToken(
|
||||||
|
request.getUsername(), request.getPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
// INACTIVE 비활성 상태(새로운 패스워드 입력 해야함), DELETED 탈퇴
|
// INACTIVE 비활성 상태(새로운 패스워드 입력 해야함), DELETED 탈퇴
|
||||||
if (!"ACTIVE".equals(status)) {
|
if (!StatusType.ACTIVE.getId().equals(status)) {
|
||||||
return ApiResponseDto.ok(new TokenResponse(status, null, null, member));
|
return ApiResponseDto.ok(new TokenResponse(status, null, null, member));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,10 +153,15 @@ public class MembersDto {
|
|||||||
@Size(max = 255)
|
@Size(max = 255)
|
||||||
private String tempPassword;
|
private String tempPassword;
|
||||||
|
|
||||||
public UpdateReq(String employeeNo, String name, String tempPassword) {
|
@Schema(description = "상태", example = "ACTIVE")
|
||||||
|
@EnumValid(enumClass = StatusType.class, message = "status는 ACTIVE, INACTIVE, DELETED 만 가능합니다.")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
public UpdateReq(String employeeNo, String name, String tempPassword, String status) {
|
||||||
this.employeeNo = employeeNo;
|
this.employeeNo = employeeNo;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.tempPassword = tempPassword;
|
this.tempPassword = tempPassword;
|
||||||
|
this.status = status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,4 +33,14 @@ public class AuthService {
|
|||||||
public String getUserStatus(SignInRequest request) {
|
public String getUserStatus(SignInRequest request) {
|
||||||
return membersCoreService.getUserStatus(request);
|
return membersCoreService.getUserStatus(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 임시 패스워드 비교
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isTempPasswordValid(SignInRequest request) {
|
||||||
|
return membersCoreService.isTempPasswordValid(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class MembersCoreService {
|
|||||||
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().trim()); // 임시 패스워드는 암호화 하지 않음
|
||||||
memberEntity.setPassword(hashedPassword);
|
memberEntity.setPassword(hashedPassword);
|
||||||
memberEntity.setName(addReq.getName());
|
memberEntity.setName(addReq.getName());
|
||||||
memberEntity.setEmployeeNo(addReq.getEmployeeNo());
|
memberEntity.setEmployeeNo(addReq.getEmployeeNo());
|
||||||
@@ -71,13 +71,24 @@ public class MembersCoreService {
|
|||||||
|
|
||||||
// 임시 패스워드는 암호화 하지 않음
|
// 임시 패스워드는 암호화 하지 않음
|
||||||
if (StringUtils.isNotBlank(updateReq.getTempPassword())) {
|
if (StringUtils.isNotBlank(updateReq.getTempPassword())) {
|
||||||
memberEntity.setTempPassword(updateReq.getTempPassword());
|
// 임시 패스워드가 기존과 다르면 패스워드 변경으로 처리함
|
||||||
|
// 상태 INACTIVE로 변경하여 사용자가 로그인할때 패스워드 변경하게함
|
||||||
|
// 패스워드 리셋이므로 로그인 실패카운트 초기화처리함
|
||||||
|
if (!memberEntity.getTempPassword().equals(updateReq.getTempPassword().trim())) {
|
||||||
|
memberEntity.setStatus(StatusType.INACTIVE.getId());
|
||||||
|
memberEntity.setLoginFailCount(0);
|
||||||
|
}
|
||||||
|
memberEntity.setTempPassword(updateReq.getTempPassword().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(memberEntity.getEmployeeNo())) {
|
if (StringUtils.isNotBlank(updateReq.getEmployeeNo())) {
|
||||||
memberEntity.setEmployeeNo(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);
|
||||||
@@ -145,6 +156,21 @@ public class MembersCoreService {
|
|||||||
return memberEntity.getStatus();
|
return memberEntity.getStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 임시 패스워드 비교
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isTempPasswordValid(SignInRequest request) {
|
||||||
|
MemberEntity memberEntity =
|
||||||
|
membersRepository
|
||||||
|
.findByUserId(request.getUsername())
|
||||||
|
.orElseThrow(MemberNotFoundException::new);
|
||||||
|
|
||||||
|
return memberEntity.getTempPassword().equals(request.getPassword().trim());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 최초 로그인 저장 마지막 로그인 저장
|
* 최초 로그인 저장 마지막 로그인 저장
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ spring:
|
|||||||
jpa:
|
jpa:
|
||||||
show-sql: true
|
show-sql: true
|
||||||
hibernate:
|
hibernate:
|
||||||
ddl-auto: validate # 스키마 검증만 수행, 자동 변경하지 않음
|
ddl-auto: validate # 로컬만 완화(시킬려면 update으로 변경)
|
||||||
properties:
|
properties:
|
||||||
hibernate:
|
hibernate:
|
||||||
default_batch_fetch_size: 100 # ✅ 성능 - N+1 쿼리 방지
|
default_batch_fetch_size: 100 # ✅ 성능 - N+1 쿼리 방지
|
||||||
@@ -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:5432/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:
|
||||||
|
|||||||
Reference in New Issue
Block a user