회원관리 관리 수정

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

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

View File

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