Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public SignInResponse signIn(EmailSignInRequest signInRequest) {
throw new CustomException(USER_NOT_FOUND, "이메일과 비밀번호를 확인해주세요.");
}

private void validatePassword(String rawPassword, String encodedPassword) throws CustomException {
private void validatePassword(String rawPassword, String encodedPassword) {
if (!passwordEncoder.matches(rawPassword, encodedPassword)) {
throw new CustomException(USER_NOT_FOUND, "이메일과 비밀번호를 확인해주세요.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public enum ErrorCode {
CAN_NOT_UPDATE_DEPRECATED_COMMENT(HttpStatus.BAD_REQUEST.value(), "이미 삭제된 댓글을 수정할 수 없습니다."),
INVALID_POST_LIKE(HttpStatus.BAD_REQUEST.value(), "존재하지 않는 게시글 좋아요입니다."),
DUPLICATE_POST_LIKE(HttpStatus.BAD_REQUEST.value(), "이미 좋아요한 게시글입니다."),
ALREADY_LIKED_UNIVERSITY(HttpStatus.BAD_REQUEST.value(), "이미 좋아요한 대학입니다."),
NOT_LIKED_UNIVERSITY(HttpStatus.BAD_REQUEST.value(), "좋아요하지 않은 대학입니다."),

// score
INVALID_GPA_SCORE(HttpStatus.BAD_REQUEST.value(), "존재하지 않는 학점입니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@
import com.example.solidconnection.custom.resolver.AuthorizedUser;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.dto.MyPageUpdateResponse;
import com.example.solidconnection.siteuser.dto.NicknameUpdateRequest;
import com.example.solidconnection.siteuser.dto.NicknameUpdateResponse;
import com.example.solidconnection.siteuser.dto.ProfileImageUpdateResponse;
import com.example.solidconnection.siteuser.service.SiteUserService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RequiredArgsConstructor
@RequestMapping("/my-page")
@RequestMapping("/my")
@RestController
class SiteUserController {

Expand All @@ -34,29 +28,13 @@ public ResponseEntity<MyPageResponse> getMyPageInfo(
return ResponseEntity.ok(myPageResponse);
}

@GetMapping("/update")
public ResponseEntity<MyPageUpdateResponse> getMyPageInfoToUpdate(
@AuthorizedUser SiteUser siteUser
) {
MyPageUpdateResponse myPageUpdateDto = siteUserService.getMyPageInfoToUpdate(siteUser);
return ResponseEntity.ok(myPageUpdateDto);
}

@PatchMapping("/update/profileImage")
public ResponseEntity<ProfileImageUpdateResponse> updateProfileImage(
@AuthorizedUser SiteUser siteUser,
@RequestParam(value = "file", required = false) MultipartFile imageFile
) {
ProfileImageUpdateResponse profileImageUpdateResponse = siteUserService.updateProfileImage(siteUser, imageFile);
return ResponseEntity.ok().body(profileImageUpdateResponse);
}

@PatchMapping("/update/nickname")
public ResponseEntity<NicknameUpdateResponse> updateNickname(
@PatchMapping
public ResponseEntity<Void> updateMyPageInfo(
@AuthorizedUser SiteUser siteUser,
@Valid @RequestBody NicknameUpdateRequest nicknameUpdateRequest
@RequestParam("file") MultipartFile imageFile,
@RequestParam("nickname") String nickname
) {
NicknameUpdateResponse nicknameUpdateResponse = siteUserService.updateNickname(siteUser, nicknameUpdateRequest);
return ResponseEntity.ok().body(nicknameUpdateResponse);
siteUserService.updateMyPageInfo(siteUser, imageFile, nickname);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
import com.example.solidconnection.s3.UploadedFileUrlResponse;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.dto.MyPageUpdateResponse;
import com.example.solidconnection.siteuser.dto.NicknameUpdateRequest;
import com.example.solidconnection.siteuser.dto.NicknameUpdateResponse;
import com.example.solidconnection.siteuser.dto.ProfileImageUpdateResponse;
import com.example.solidconnection.siteuser.repository.LikedUniversityRepository;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.type.ImgType;
Expand Down Expand Up @@ -48,68 +44,27 @@ public MyPageResponse getMyPageInfo(SiteUser siteUser) {
}

/*
* 내 정보를 수정하기 위한 마이페이지 정보를 조회한다. (닉네임, 프로필 사진)
* */
@Transactional(readOnly = true)
public MyPageUpdateResponse getMyPageInfoToUpdate(SiteUser siteUser) {
return MyPageUpdateResponse.from(siteUser);
}

/*
* 관심 대학교 목록을 조회한다.
* */
@Transactional(readOnly = true)
public List<UniversityInfoForApplyPreviewResponse> getWishUniversity(SiteUser siteUser) {
List<LikedUniversity> likedUniversities = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId());
return likedUniversities.stream()
.map(likedUniversity -> UniversityInfoForApplyPreviewResponse.from(likedUniversity.getUniversityInfoForApply()))
.toList();
}

/*
* 프로필 이미지를 수정한다.
* 마이페이지 정보를 수정한다.
* */
@Transactional
public ProfileImageUpdateResponse updateProfileImage(SiteUser siteUser, MultipartFile imageFile) {
validateProfileImage(imageFile);
public void updateMyPageInfo(SiteUser siteUser, MultipartFile imageFile, String nickname) {
validateNicknameUnique(nickname);
validateNicknameNotChangedRecently(siteUser.getNicknameModifiedAt());
validateProfileImageNotEmpty(imageFile);

// 프로필 이미지를 처음 수정하는 경우에는 deleteExProfile 수행하지 않음
if (!isDefaultProfileImage(siteUser.getProfileImageUrl())) {
s3Service.deleteExProfile(siteUser);
}
UploadedFileUrlResponse uploadedFileUrlResponse = s3Service.uploadFile(imageFile, ImgType.PROFILE);
siteUser.setProfileImageUrl(uploadedFileUrlResponse.fileUrl());
siteUserRepository.save(siteUser);

return ProfileImageUpdateResponse.from(siteUser);
}

private void validateProfileImage(MultipartFile imageFile) {
if (imageFile == null || imageFile.isEmpty()) {
throw new CustomException(PROFILE_IMAGE_NEEDED);
}
}
private boolean isDefaultProfileImage(String profileImageUrl) {
String prefix = "profile/";
return profileImageUrl == null || !profileImageUrl.startsWith(prefix);
}
UploadedFileUrlResponse uploadedFile = s3Service.uploadFile(imageFile, ImgType.PROFILE);
String profileImageUrl = uploadedFile.fileUrl();

/*
* 닉네임을 수정한다.
* */
@Transactional
public NicknameUpdateResponse updateNickname(SiteUser siteUser, NicknameUpdateRequest nicknameUpdateRequest) {
validateNicknameDuplicated(nicknameUpdateRequest.nickname());
validateNicknameNotChangedRecently(siteUser.getNicknameModifiedAt());

siteUser.setNickname(nicknameUpdateRequest.nickname());
siteUser.setProfileImageUrl(profileImageUrl);
siteUser.setNickname(nickname);
siteUser.setNicknameModifiedAt(LocalDateTime.now());
siteUserRepository.save(siteUser);

return NicknameUpdateResponse.from(siteUser);
}

private void validateNicknameDuplicated(String nickname) {
private void validateNicknameUnique(String nickname) {
if (siteUserRepository.existsByNickname(nickname)) {
throw new CustomException(NICKNAME_ALREADY_EXISTED);
}
Expand All @@ -125,4 +80,26 @@ private void validateNicknameNotChangedRecently(LocalDateTime lastModifiedAt) {
throw new CustomException(CAN_NOT_CHANGE_NICKNAME_YET, formatLastModifiedAt);
}
}

private void validateProfileImageNotEmpty(MultipartFile imageFile) {
if (imageFile == null || imageFile.isEmpty()) {
throw new CustomException(PROFILE_IMAGE_NEEDED);
}
}

private boolean isDefaultProfileImage(String profileImageUrl) {
String prefix = "profile/";
return profileImageUrl == null || !profileImageUrl.startsWith(prefix);
}

/*
* 관심 대학교 목록을 조회한다.
* */
@Transactional(readOnly = true)
public List<UniversityInfoForApplyPreviewResponse> getWishUniversity(SiteUser siteUser) {
List<LikedUniversity> likedUniversities = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId());
return likedUniversities.stream()
.map(likedUniversity -> UniversityInfoForApplyPreviewResponse.from(likedUniversity.getUniversityInfoForApply()))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.example.solidconnection.university.service.UniversityRecommendService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -24,7 +25,7 @@
import java.util.List;

@RequiredArgsConstructor
@RequestMapping("/university")
@RequestMapping("/universities")
@RestController
public class UniversityController {

Expand All @@ -33,7 +34,7 @@ public class UniversityController {
private final UniversityRecommendService universityRecommendService;
private final SiteUserService siteUserService;

@GetMapping("/recommends")
@GetMapping("/recommend")
public ResponseEntity<UniversityRecommendsResponse> getUniversityRecommends(
@AuthorizedUser SiteUser siteUser
) {
Expand Down Expand Up @@ -70,7 +71,16 @@ public ResponseEntity<LikeResultResponse> addWishUniversity(
return ResponseEntity.ok(likeResultResponse);
}

@GetMapping("/detail/{universityInfoForApplyId}")
@DeleteMapping("/{universityInfoForApplyId}/like")
public ResponseEntity<LikeResultResponse> cancelWishUniversity(
@AuthorizedUser SiteUser siteUser,
@PathVariable Long universityInfoForApplyId
) {
LikeResultResponse likeResultResponse = universityLikeService.cancelLikeUniversity(siteUser, universityInfoForApplyId);
return ResponseEntity.ok(likeResultResponse);
}

@GetMapping("/{universityInfoForApplyId}")
public ResponseEntity<UniversityDetailResponse> getUniversityDetails(
@PathVariable Long universityInfoForApplyId
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.solidconnection.university.service;

import com.example.solidconnection.custom.exception.CustomException;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.repository.LikedUniversityRepository;
import com.example.solidconnection.university.domain.LikedUniversity;
Expand All @@ -14,6 +15,9 @@

import java.util.Optional;

import static com.example.solidconnection.custom.exception.ErrorCode.ALREADY_LIKED_UNIVERSITY;
import static com.example.solidconnection.custom.exception.ErrorCode.NOT_LIKED_UNIVERSITY;

@RequiredArgsConstructor
@Service
public class UniversityLikeService {
Expand All @@ -29,16 +33,14 @@ public class UniversityLikeService {

/*
* 대학교를 '좋아요' 한다.
* - 이미 좋아요가 눌러져있다면, 좋아요를 취소한다.
* */
@Transactional
public LikeResultResponse likeUniversity(SiteUser siteUser, Long universityInfoForApplyId) {
UniversityInfoForApply universityInfoForApply = universityInfoForApplyRepository.getUniversityInfoForApplyById(universityInfoForApplyId);

Optional<LikedUniversity> alreadyLikedUniversity = likedUniversityRepository.findBySiteUserAndUniversityInfoForApply(siteUser, universityInfoForApply);
if (alreadyLikedUniversity.isPresent()) {
likedUniversityRepository.delete(alreadyLikedUniversity.get());
return new LikeResultResponse(LIKE_CANCELED_MESSAGE);
Optional<LikedUniversity> optionalLikedUniversity = likedUniversityRepository.findBySiteUserAndUniversityInfoForApply(siteUser, universityInfoForApply);
if (optionalLikedUniversity.isPresent()) {
throw new CustomException(ALREADY_LIKED_UNIVERSITY);
}

LikedUniversity likedUniversity = LikedUniversity.builder()
Expand All @@ -49,6 +51,22 @@ public LikeResultResponse likeUniversity(SiteUser siteUser, Long universityInfoF
return new LikeResultResponse(LIKE_SUCCESS_MESSAGE);
}

/*
* 대학교 '좋아요'를 취소한다.
* */
@Transactional
public LikeResultResponse cancelLikeUniversity(SiteUser siteUser, long universityInfoForApplyId) throws CustomException {
UniversityInfoForApply universityInfoForApply = universityInfoForApplyRepository.getUniversityInfoForApplyById(universityInfoForApplyId);

Optional<LikedUniversity> optionalLikedUniversity = likedUniversityRepository.findBySiteUserAndUniversityInfoForApply(siteUser, universityInfoForApply);
if (optionalLikedUniversity.isEmpty()) {
throw new CustomException(NOT_LIKED_UNIVERSITY);
}

likedUniversityRepository.delete(optionalLikedUniversity.get());
return new LikeResultResponse(LIKE_CANCELED_MESSAGE);
}

/*
* '좋아요'한 대학교인지 확인한다.
* */
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ VALUES ('BN', '브루나이', 'ASIA'),
('MY', '말레이시아', 'ASIA'),
('RU', '러시아', 'EUROPE');

INSERT INTO site_user (birth, email, nickname, profile_image_url, gender, preparation_stage, role, password, auth_type)
VALUES ('1999-01-01', '[email protected]', 'yonso','https://github.com/nayonsoso.png',
'FEMALE', 'CONSIDERING', 'MENTEE',
'$2a$10$psmwlxPfqWnIlq9JrlQJkuXr1XtjRNsyVOgcTWYZub5jFfn0TML76', 'EMAIL'); -- 12341234

INSERT INTO university(id, country_code, region_code, english_name, format_name, korean_name,
accommodation_url, english_course_url, homepage_url,
details_for_local, logo_image_url, background_image_url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void setUpUserAndToken() {
MyPageResponse myPageResponse = RestAssured.given()
.header("Authorization", "Bearer " + accessToken)
.log().all()
.get("/my-page")
.get("/my")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.extract().as(MyPageResponse.class);
Expand Down
Loading