본문 바로가기

내일배움캠프

TIL

profile 수정 관련 작성 CRUD

 

1. User 엔티티 업데이트

최근 사용한 비밀번호 목록을 저장하는 필드를 User 엔티티에 추가합니다.

 

package com.sparta.realestatefeed.entity;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
@NoArgsConstructor
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String userName;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String email;

    private String nickName;
    private String info;

    @ElementCollection
    @CollectionTable(name = "user_previous_passwords", joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "previous_password")
    private List<String> previousPasswords = new ArrayList<>();
}

 

2. ProfileService 클래스

비밀번호 변경 시 최근 사용한 비밀번호를 previousPasswords 필드에 저장하고, 최근 세 개의 비밀번호와 중복되지 않도록 합니다.

package com.sparta.realestatefeed.service;

import com.sparta.realestatefeed.dto.ProfileRequestDto;
import com.sparta.realestatefeed.dto.ProfileResponseDto;
import com.sparta.realestatefeed.entity.User;
import com.sparta.realestatefeed.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class ProfileService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    public ProfileResponseDto getUserProfile(String userName) {
        User user = userRepository.findByUserName(userName).orElseThrow(
            () -> new IllegalArgumentException("User not found")
        );
        return new ProfileResponseDto(user.getUserName(), user.getNickName(), user.getEmail(), user.getInfo());
    }

    public ProfileResponseDto updateUserProfile(String userName, ProfileRequestDto profileRequestDto) {
        User user = userRepository.findByUserName(userName).orElseThrow(
            () -> new IllegalArgumentException("User not found")
        );

        user.setNickName(profileRequestDto.getNickName());
        user.setInfo(profileRequestDto.getInfo());
        userRepository.save(user);

        return new ProfileResponseDto(user.getUserName(), user.getNickName(), user.getEmail(), user.getInfo());
    }

    public User updateUserPassword(String userName, String currentPassword, String newPassword) {
        User user = userRepository.findByUserName(userName).orElseThrow(
            () -> new IllegalArgumentException("User not found")
        );

        if (!passwordEncoder.matches(currentPassword, user.getPassword())) {
            throw new IllegalArgumentException("Current password is incorrect");
        }

        List<String> previousPasswords = user.getPreviousPasswords();
        if (previousPasswords.stream().anyMatch(password -> passwordEncoder.matches(newPassword, password))) {
            throw new IllegalArgumentException("New password must be different from the last three passwords");
        }

        // Add the current password to the list of previous passwords
        previousPasswords.add(0, user.getPassword());
        if (previousPasswords.size() > 3) {
            previousPasswords.remove(3);
        }

        // Update the user's password
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);

        return user;
    }
}

 

3. ProfileController 클래스

컨트롤러에서 서비스 메서드를 호출하여 클라이언트 요청을 처리합니다.

package com.sparta.realestatefeed.controller;

import com.sparta.realestatefeed.dto.CommonDto;
import com.sparta.realestatefeed.dto.ProfileRequestDto;
import com.sparta.realestatefeed.dto.ProfileResponseDto;
import com.sparta.realestatefeed.security.UserDetailsImpl;
import com.sparta.realestatefeed.service.ProfileService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/profiles")
@Validated
public class ProfileController {

    private final ProfileService profileService;

    public ProfileController(ProfileService profileService) {
        this.profileService = profileService;
    }

    @GetMapping("/")
    public ResponseEntity<?> getUserProfile(@AuthenticationPrincipal UserDetailsImpl userDetails) {
        String userName = userDetails.getUser().getUserName();
        ProfileResponseDto responseDto = profileService.getUserProfile(userName);
        CommonDto<ProfileResponseDto> response = new CommonDto<>(HttpStatus.OK.value(), "회원 조회", responseDto);
        return ResponseEntity.status(HttpStatus.OK).body(response);
    }

    @PutMapping("/")
    public ResponseEntity<?> updateUserProfile(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody ProfileRequestDto profileRequestDto) {
        String userName = userDetails.getUser().getUserName();
        ProfileResponseDto responseDto = profileService.updateUserProfile(userName, profileRequestDto);
        CommonDto<ProfileResponseDto> response = new CommonDto<>(HttpStatus.OK.value(), "회원 조회", responseDto);
        return ResponseEntity.status(HttpStatus.OK).body(response);
    }

    @PutMapping("/password")
    public ResponseEntity<?> updateUserPassword(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody Map<String, String> passwordRequest) {
        String userName = userDetails.getUser().getUserName();
        String currentPassword = passwordRequest.get("currentPassword");
        String newPassword = passwordRequest.get("newPassword");

        try {
            User user = profileService.updateUserPassword(userName, currentPassword, newPassword);
            return ResponseEntity.ok().body("Password updated successfully");
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}

 

 

4. ProfileRequestDto와 ProfileResponseDto 클래스

프로필 수정 및 조회에 필요한 DTO 클래스입니다.

package com.sparta.realestatefeed.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ProfileRequestDto {
    private String nickName;
    private String info;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ProfileResponseDto {
    private String userName;
    private String nickName;
    private String email;
    private String info;
}

 

'내일배움캠프' 카테고리의 다른 글

KPT 회고  (0) 2024.06.26
TIL  (0) 2024.06.19
TIL  (0) 2024.06.19
TIL  (0) 2024.06.18
TIL  (0) 2024.06.14