우주먼지

1. 💡 상담사 기능

 

요구사항

Open-Session-in-view 옵션: false (트랜잭션 내부의 프록시객체 초기화 필요)

@ManyToOne 단방향 매핑으로 진행
FetchType : Lazy

1. 상담사 등록 (관리자만 등록 가능)
2. 상담사 로그인
3. 상담사 전체 조회 (관리자의 마이페이지)
4. 상담사 수정 (상담사 마이페이지)
5. 상담사 삭제 (괸라자만 삭제 가능)

2. 💡 소스코드

 

2.1. Entity

<java />
@Entity @Getter @Setter @NoArgsConstructor public class Counselor extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long counselorId; @Column(unique = true, length = 50, nullable = false) @Email private String email; @Column(length = 200) // @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@!%*#?&])[A-Za-z\\d@!%*#?&]{8,}$") private String password; @Column(nullable = false, length = 20) private String counselorName; //실명 @Column(length = 10) private String birth; // 생년월일 @Column private String graduated; //학력 @Column(length = 200) private String profile; //프로필 이미지 @Column private String career; //경력 @Column private String introduce; //소개 @Column(length = 100) private String expertiseField; @Enumerated(EnumType.STRING) @Column(nullable = false, length = 10) private Role role; // @Enumerated(EnumType.STRING) // @Column(nullable = false, length = 10) // private MemberType memberType; @Column(length = 250) private String refreshToken; private LocalDateTime tokenExpirationTime; @Builder public Counselor(Long counselorId, String email, String password,String expertiseField, String counselorName, String birth, String graduated, String profile, String career, String introduce) { this.counselorId = counselorId; this.email = email; this.expertiseField = expertiseField; this.password = password; this.counselorName = counselorName; this.birth = birth; this.graduated = graduated; this.profile = profile; this.career = career; this.introduce = introduce; } public void updateRefreshToken(JwtTokenDto jwtTokenDto) { this.refreshToken = jwtTokenDto.getRefreshToken(); this.tokenExpirationTime = DateTimeUtils.convertToLocalDateTime(jwtTokenDto.getRefreshTokenExpireTime()); } }

 

2.2. DTO

<code />
public class CounselorDto { @Getter public static class Post { private String profile; //프로필 이미지 private String counselorName; //실명 private String birth; private String graduated; //학력 private String expertiseField; @Email private String email; private String password; private String confirmPassword; private String career; private String introduce; } @Getter public static class Login { private String email; private String password; } @Getter @NoArgsConstructor public static class Patch{ private Long counselorId; private String password; private String newPassword; private String confirmNewPassword; public void updateCounselorId(Long counselorId) { this.counselorId = counselorId; } } @Builder @NoArgsConstructor @AllArgsConstructor @Getter @Setter public static class Response { private Long counselorId; private String profile; //프로필 이미지 private String counselorName; //실명 private String birth; private String graduated; //학력 private String email; private String password; private String career; private String introduce; private String expertiseField; private Role role; // private MemberType memberType; private String refreshToken; private LocalDateTime tokenExpirationTime; } @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public static class LoginResponse { private String grantType; private String accessToken; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") private Date accessTokenExpireTime; private String refreshToken; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") private Date refreshTokenExpireTime; private Role role; public static CounselorDto.LoginResponse of(JwtTokenDto jwtTokenDto, Role role){ return LoginResponse.builder() .role(role) .grantType(jwtTokenDto.getGrantType()) .accessToken(jwtTokenDto.getAccessToken()) .accessTokenExpireTime(jwtTokenDto.getAccessTokenExpireTime()) .refreshToken(jwtTokenDto.getRefreshToken()) .refreshTokenExpireTime(jwtTokenDto.getRefreshTokenExpireTime()) .build(); } } @Builder @NoArgsConstructor @AllArgsConstructor @Getter @Setter public static class MyPageResponse { private Long counselorId; private Role role; private String email; private String counselorName; private String password; } }

 

2.3. Mapper

<code />
@Mapper(componentModel = "spring") public interface CounselorMapper { Counselor counselorPostDtoToCounselor(CounselorDto.Post counselorPostDto); CounselorDto.Response counselorToCounselorResponse(Counselor counselor); Counselor counselorLoginDtoToCounselor(CounselorDto.Login counselorLogindto); CounselorDto.MyPageResponse counselorToMyPageResponse(Counselor counselor); @Mapping(source = "newPassword", target = "password") Counselor counselorPatchDtoToCounselor(CounselorDto.Patch counselorPatchDto); List<CounselorDto.MyPageResponse> counselorsToCounselorMyPageResponses(List<Counselor> counselors); }

 

2.4. Repository

<code />
public interface CounselorRepository extends JpaRepository<Counselor, Long> { Optional<Counselor> findByEmail(String email); }

 

2.5. Service

<java />
@Service @RequiredArgsConstructor public class CounselorService { private final CounselorRepository counselorRepository; private final TokenManager tokenManager; //for 토큰 생성 private final JasyptConfig jasyptConfig; //for 암호화 /** * 상담사 등록(회원가입) */ public Counselor createCounselor(Counselor counselor) { validateDuplicateCounselor(counselor); //동일 이메일 확인 // counselor.setMemberType(MemberType.DEFAULT); //상담사는 자체회원가입 밖에 없음 counselor.setRole(Role.COUNSELOR); counselor.setPassword(encryptPassword(counselor.getPassword())); return counselorRepository.save(counselor); } /** * 상담사 로그인 */ public CounselorDto.LoginResponse login(Counselor counselor) { JwtTokenDto jwtTokenDto; Optional<Counselor> optionalCounselor = findCounslerByEmail(counselor.getEmail()); if (optionalCounselor.isEmpty()) { throw new EntityNotFoundException(ErrorCode.COUNSELOR_NOT_EXISTS); } Counselor findCounselor = optionalCounselor.get(); if (!decryptPassword(findCounselor.getPassword()).equals(counselor.getPassword())) { throw new AuthenticationException(ErrorCode.WRONG_PASSWROD); } jwtTokenDto = tokenManager.createJwtTokenDto(findCounselor.getCounselorId(), findCounselor.getRole()); findCounselor.updateRefreshToken(jwtTokenDto); //토큰값 설정 counselorRepository.save(findCounselor); //db에 토큰 업데이트 return CounselorDto.LoginResponse.of(jwtTokenDto, findCounselor.getRole()); } /** * 상담사 목록 조회 */ @Transactional(readOnly = true) public Page<Counselor> findMembers(int page, int size) { Page<Counselor> findAllCounselor = counselorRepository.findAll( PageRequest.of(page,size, Sort.by("counselorId").descending()) ); return findAllCounselor; } /** * 상담사 수정 */ public Counselor updateCounselor(Counselor counselor) { Counselor findCounselor = findVerifiedCounselorByCounselorId(counselor.getCounselorId()); String password = encryptPassword(counselor.getPassword()); findCounselor.setPassword(password); return counselorRepository.save(findCounselor); } /** * 상담사 삭제 */ public void deleteCounselor(Long counselorId) { counselorRepository.deleteById(counselorId); } /** * 로그인한 상담사 정보 조회 */ @Transactional(readOnly = true) public Counselor getLoginCounselor(HttpServletRequest httpServletRequest) { String authorizationHeader = httpServletRequest.getHeader("Authorization"); String accessToken = authorizationHeader.split(" ")[1]; // Bearer askdhqwdkjwqbdkjwqbdkjqwbdkjwqb Claims tokenClaims = tokenManager.getTokenClaims(accessToken); Long counselorId = Long.valueOf((Integer) tokenClaims.get("memberId")); return findVerifiedCounselorByCounselorId(counselorId); } /** * 상담사 중복 확인 */ private void validateDuplicateCounselor(Counselor counselor) { Optional<Counselor> optionalCounselor = findCounslerByEmail(counselor.getEmail()); if(optionalCounselor.isPresent()){ throw new BusinessException(ErrorCode.ALREADY_REGISTERED_COUNSELOR); } } /** * 상담사 존재 확인 */ @Transactional(readOnly = true) public Counselor findVerifiedCounselorByCounselorId(Long counselorId) { return counselorRepository.findById(counselorId) .orElseThrow(() -> new EntityNotFoundException(ErrorCode.COUNSELOR_NOT_EXISTS)); } private Optional<Counselor> findCounslerByEmail(String email) { return counselorRepository.findByEmail(email); } /** * 비밀번호 암호화 */ public String encryptPassword(String password){ PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(4); encryptor.setPassword(jasyptConfig.getPassword()); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); return encryptor.encrypt(password); } /** * 비밀번호 복호화 */ public String decryptPassword(String password){ PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(4); encryptor.setPassword(jasyptConfig.getPassword()); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); return encryptor.decrypt(password); } }

 

2.6. Controller

<code />
@RestController @RequestMapping("/api/counselors") @Validated @RequiredArgsConstructor public class CounselorController { private final CounselorService counselorService; private final CounselorMapper counselorMapper; /** * 상담사 등록 */ @PostMapping("/new") public ResponseEntity postCounselor(@Valid @RequestBody CounselorDto.Post counselorPostDto){ if(!counselorPostDto.getPassword().equals(counselorPostDto.getConfirmPassword())){ //비밀번호와 비밀번호 확인이 같지 않으면 throw new AuthenticationException(ErrorCode.PASSWORD_MISMATCH); //에러 발생 } Counselor counselor = counselorService.createCounselor(counselorMapper.counselorPostDtoToCounselor(counselorPostDto)); CounselorDto.Response response = counselorMapper.counselorToCounselorResponse(counselor); return new ResponseEntity<>( new SingleResponseDto<>(response), HttpStatus.OK ); } /** * 상담사 로그인 * 기본 회원과 다르게 MemberType 사용되지 않음 */ @PostMapping("/login") public ResponseEntity loginCounselor(@Valid @RequestBody CounselorDto.Login counselorLogindto){ CounselorDto.LoginResponse jwtTokenResponseDto = counselorService.login(counselorMapper.counselorLoginDtoToCounselor(counselorLogindto)); return new ResponseEntity<>( new SingleResponseDto<>(jwtTokenResponseDto), HttpStatus.OK ); } /** * 상담사 조회(상담사 정보 수정 페이지) */ // @GetMapping("/look-up/{counselorId}") // public ResponseEntity getCounselor(@PathVariable("counselorId")@Positive Long counselorId){ // Counselor counselor = counselorService.findVerifiedCounselorByCounselorId(counselorId); // CounselorDto.MyPageResponse response = counselorMapper.counselorToMyPageResponse(counselor); // // return new ResponseEntity<>( // new SingleResponseDto<>(response), HttpStatus.OK // ); // } /** * 상담사 조회 수정 */ @GetMapping("/look-up") public ResponseEntity getCounselor(HttpServletRequest httpServletRequest){ Counselor counselor = counselorService.getLoginCounselor(httpServletRequest); CounselorDto.MyPageResponse response = counselorMapper.counselorToMyPageResponse(counselor); return new ResponseEntity<>( new SingleResponseDto<>(response), HttpStatus.OK ); } /** * 상담사 전체 조회 */ /** * 회원 전체 조회 * todo: 상담 횟수 필드 추가 */ @GetMapping("/total-look-up") public ResponseEntity getMembers(@Positive @RequestParam("page") int page, @Positive @RequestParam("size") int size){ Page<Counselor> pageCounselors = counselorService.findMembers(page-1, size); List<Counselor> counselors = pageCounselors.getContent(); return new ResponseEntity<>(new MultiResponseDto<>( counselorMapper.counselorsToCounselorMyPageResponses(counselors), pageCounselors) ,HttpStatus.OK); } /** * 상담사 정보 수정 */ @PatchMapping("/edit/{counselorId}") public ResponseEntity updateCounselor(@PathVariable("counselorId")@Positive Long counserlorId, @Valid @RequestBody CounselorDto.Patch counselorPatchDto){ counselorPatchDto.updateCounselorId(counserlorId); Counselor preCounselor = counselorService.findVerifiedCounselorByCounselorId(counserlorId); if (!counselorPatchDto.getNewPassword().equals(counselorPatchDto.getConfirmNewPassword())) { throw new EntityNotFoundException(ErrorCode.PASSWORD_MISMATCH); } String password = counselorService.decryptPassword(preCounselor.getPassword()); if (!password.equals(counselorPatchDto.getPassword())) { throw new AuthenticationException(ErrorCode.WRONG_PASSWROD); } Counselor counselor = counselorService.updateCounselor(counselorMapper.counselorPatchDtoToCounselor(counselorPatchDto)); CounselorDto.MyPageResponse response = counselorMapper.counselorToMyPageResponse(counselor); return new ResponseEntity<>( new SingleResponseDto<>(response), HttpStatus.OK ); } /** * 상담사 삭제 */ @DeleteMapping("/delete/{counselorId}") public ResponseEntity deleteCounselor(@PathVariable("counselorId") @Positive Long counselorId){ counselorService.deleteCounselor(counselorId); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } }

'Project > Main Project' 카테고리의 다른 글

💻 기능 개발 - 결제  (0) 2023.01.27
💻 기능 개발 - 프로그램  (0) 2023.01.27
💻 기능 개발 - 공지사항  (0) 2023.01.26
💻 기능 개발 - 게시물  (0) 2023.01.26
💻 기능 개발 - 회원  (0) 2023.01.26
profile

우주먼지

@o귤o

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그