Skip to content

Commit

Permalink
feat: add api of mypage (#11)
Browse files Browse the repository at this point in the history
* feat: add api to set pr ofile image

* fix: add validation of nickname duplication

* feat: add api to change nickname

* feat: add api to resign

* feat: add api to delete profile image

* fix: add validation of file extension

* fix: add validation logic at api to resign

* feat: add profileImage

* feat: add api to see my page

* fix: rename default filename

* fix: fix response

* fix: fix add file extension

* fix: fix file extension
  • Loading branch information
aiaiaiai1 authored Jul 24, 2024
1 parent d8ed1d2 commit 0272ebd
Show file tree
Hide file tree
Showing 29 changed files with 709 additions and 39 deletions.
10 changes: 10 additions & 0 deletions src/main/java/gymmi/controller/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import gymmi.request.LoginRequest;
import gymmi.request.RegistrationRequest;
import gymmi.request.ReissueRequest;
import gymmi.request.ResignRequest;
import gymmi.response.LoginResponse;
import gymmi.response.TokenResponse;
import gymmi.service.AuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
Expand Down Expand Up @@ -45,4 +47,12 @@ public ResponseEntity<Void> logout(@Logined User user) {
return ResponseEntity.ok().build();
}

@DeleteMapping("/auth/cuag")
public ResponseEntity<Void> resign(@Logined User user,
@RequestBody @Validated ResignRequest request
) {
authService.resign(user, request);
return ResponseEntity.ok().build();
}

}
56 changes: 56 additions & 0 deletions src/main/java/gymmi/controller/MyPageController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package gymmi.controller;

import gymmi.entity.User;
import gymmi.global.Logined;
import gymmi.request.EditingMyPageRequest;
import gymmi.response.MyPageResponse;
import gymmi.service.MyPageService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequiredArgsConstructor
public class MyPageController {

private final MyPageService myPageService;

@PutMapping(value = "/my/profile-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Void> editProfileImage(
@Logined User user,
@RequestParam("profileImage") MultipartFile profileImageFile
) {
myPageService.setProfileImage(user, profileImageFile);
return ResponseEntity.ok().build();
}

@DeleteMapping("/my/profile-image")
public ResponseEntity<Void> deleteProfileImage(
@Logined User user
) {
myPageService.deleteProfileImage(user);
return ResponseEntity.ok().build();
}

@PutMapping("/my/nickname/edit")
public ResponseEntity<Void> editMyPage(
@Logined User user,
@RequestBody @Validated EditingMyPageRequest request
) {
myPageService.editMyPage(user, request);
return ResponseEntity.ok().build();
}

@GetMapping("/my")
public ResponseEntity<MyPageResponse> seeMyPage(
@Logined User user
) {
MyPageResponse response = myPageService.getMyInfo(user);
return ResponseEntity.ok().body(response);
}


}
46 changes: 46 additions & 0 deletions src/main/java/gymmi/entity/ProfileImage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package gymmi.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ProfileImage {

public static final String EMPTY_NAME = "default.png";

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

@JoinColumn(name = "user_id", nullable = false, unique = true, updatable = false)
@OneToOne(fetch = FetchType.LAZY)
private User owner;

@Column(nullable = false)
private String originName;

@Column(nullable = false)
private String storedName;

@Builder
public ProfileImage(User owner, String originName, String storedName) {
this.owner = owner;
this.originName = originName;
this.storedName = storedName;
}

public Long getId() {
return id;
}

public String getOriginName() {
return originName;
}

public String getStoredName() {
return storedName;
}
}
61 changes: 47 additions & 14 deletions src/main/java/gymmi/entity/User.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
package gymmi.entity;

import static gymmi.utils.Regexpressions.REGEX_숫자;
import static gymmi.utils.Regexpressions.REGEX_영어;
import static gymmi.utils.Regexpressions.REGEX_영어_숫자_만;
import static gymmi.utils.Regexpressions.REGEX_영어_한글_초성_숫자_만;
import static gymmi.utils.Regexpressions.SPECIAL_CHARACTER;

import gymmi.exception.InvalidPatternException;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.util.regex.Pattern;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.EqualsAndHashCode;
Expand All @@ -22,6 +10,10 @@
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.util.StringUtils;

import java.util.regex.Pattern;

import static gymmi.utils.Regexpressions.*;

@Entity
@Table(name = "uuser")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand All @@ -33,6 +25,7 @@ public class User {
private static final Pattern REGEX_NICKNAME = REGEX_영어_한글_초성_숫자_만;
private static final Pattern REGEX_SPECIAL_CHARACTER = Pattern.compile("[" + SPECIAL_CHARACTER + "]");
private static final Pattern REGEX_EMAIL = Pattern.compile("^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]*$");
public static final String RESIGNED_NICKNAME = "(탈퇴한유저)";

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -51,6 +44,12 @@ public class User {
@ColumnDefault("''")
private String email;

@Column(nullable = false)
private boolean isResigned;

@OneToOne(mappedBy = "owner", fetch = FetchType.LAZY)
private ProfileImage profileImage; // 지연 로딩 안됨.

@Builder
public User(String loginId, String plainPassword, String nickname, String email) {
validateLoginId(loginId);
Expand All @@ -60,6 +59,7 @@ public User(String loginId, String plainPassword, String nickname, String email)
this.password = encryptPassword(plainPassword);
this.nickname = nickname;
this.email = validateEmail(email);
this.isResigned = false;
}

private String validateEmail(String email) {
Expand Down Expand Up @@ -101,10 +101,11 @@ public static void validateLoginId(String loginId) {
}
}

public static void validateNickname(String nickname) {
public static String validateNickname(String nickname) {
if (!REGEX_NICKNAME.matcher(nickname).matches()) {
throw new InvalidPatternException("닉네임은 한글(초성), 영문, 숫자만 가능합니다.");
}
return nickname;
}

public boolean canAuthenticate(String loginId, String plainPassword) {
Expand All @@ -114,11 +115,43 @@ public boolean canAuthenticate(String loginId, String plainPassword) {
return false;
}

public boolean canAuthenticate(String plainPassword) {
if (BCrypt.checkpw(plainPassword, password)) {
return true;
}
return false;
}

public void changeNickname(String nickname) {
this.nickname = validateNickname(nickname);
}

public Long getId() {
return id;
}

public String getNickname() {
return nickname;
}

public void resign() {
this.isResigned = true;
this.nickname = RESIGNED_NICKNAME;
}

public String getProfileImageName() {
if (profileImage == null) {
return ProfileImage.EMPTY_NAME;
}
return profileImage.getStoredName();
}

public String getLoginId() {
return loginId;
}

public String getEmail() {
return email;
}

}
4 changes: 4 additions & 0 deletions src/main/java/gymmi/exception/BadRequestException.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public BadRequestException(String message, Throwable cause, String errorCode, St
super(message, cause, errorCode, errorDescription);
}

public BadRequestException(String message, Throwable cause) {
this(message, cause, ERROR_CODE, ERROR_DESCRIPTION);
}

public BadRequestException(String message) {
this(message, ERROR_CODE, ERROR_DESCRIPTION);
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/gymmi/exception/ExceptionController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gymmi.exception;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -55,6 +56,17 @@ public ResponseEntity<ErrorResponse> handle500Exception(GymmiException e, HttpSe
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> handle500Exception(
Exception e,
HttpServletRequest request,
HttpServletResponse resp
) {
ErrorResponse response = new ErrorResponse("ERROR", e.getMessage());
log(e, request.getRequestURI());
return ResponseEntity.status(500).body(response);
}

private void log(Exception e, String requestURI) {
log.warn(System.lineSeparator() +
"[에러 발생 로그]" + System.lineSeparator() +
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/gymmi/exception/InvalidFileException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package gymmi.exception;

public class InvalidFileException extends BadRequestException {

public static final String ERROR_CODE = "INVALID_FILE";
public static final String ERROR_DESCRIPTION = "잘못된 파일의 요청인 경우";

public InvalidFileException(String message) {
super(message, ERROR_CODE, ERROR_DESCRIPTION);
}
}
4 changes: 4 additions & 0 deletions src/main/java/gymmi/exception/ServerLogicFaultException.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ public class ServerLogicFaultException extends GymmiException {
public ServerLogicFaultException(String message) {
super(message, ERROR_CODE, ERROR_DESCRIPTION);
}

public ServerLogicFaultException(String message, Throwable cause) {
super(message, cause, ERROR_CODE, ERROR_DESCRIPTION);
}
}
20 changes: 20 additions & 0 deletions src/main/java/gymmi/repository/ProfileImageRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package gymmi.repository;

import gymmi.entity.ProfileImage;
import gymmi.exception.NotFoundResourcesException;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.Optional;

public interface ProfileImageRepository extends JpaRepository<ProfileImage, Long> {

@Query("select p from ProfileImage p where p.owner.id =:userId")
Optional<ProfileImage> findByUserId(Long userId);

default ProfileImage getByUserId(Long userId) {
return findByUserId(userId)
.orElseThrow(() -> new NotFoundResourcesException("프로필 이미지가 존재하지 않습니다."));
}

}
2 changes: 1 addition & 1 deletion src/main/java/gymmi/repository/UserRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

public interface UserRepository extends JpaRepository<User, Long> {

@Query("select u from User u where u.loginId = :loginId")
@Query("select u from User u where u.loginId = :loginId and u.isResigned = false")
Optional<User> findByLoginId(String loginId);

@Query("select u from User u where u.id = :userId")
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/gymmi/request/EditingMyPageRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package gymmi.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;

@Getter
@NoArgsConstructor
public class EditingMyPageRequest {

@NotBlank(message = "닉네임을 입력해주세요.")
@Length(min = 2, max = 5, message = "닉네임은 2~5자까지 가능합니다.")
private String nickname;

public EditingMyPageRequest(String nickname) {
this.nickname = nickname;
}
}
17 changes: 17 additions & 0 deletions src/main/java/gymmi/request/ResignRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package gymmi.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class ResignRequest {

@NotBlank
private String password;

public ResignRequest(String password) {
this.password = password;
}
}
6 changes: 4 additions & 2 deletions src/main/java/gymmi/response/InsideWorkspaceResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import gymmi.entity.User;
import gymmi.entity.Worker;
import gymmi.entity.Workspace;
import java.util.ArrayList;
import java.util.List;
import lombok.Builder;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

@Getter
public class InsideWorkspaceResponse {

Expand Down Expand Up @@ -48,6 +49,7 @@ private List<WorkerResponse> getWorkerResponse(
.rank(workerRanks.get(i))
.isCreator(creator.equals(worker.getUser()))
.isMyself(worker.getUser().equals(loginedUser))
.profileImage(worker.getUser().getProfileImageName())
.build();
workerResponses.add(response);
}
Expand Down
Loading

0 comments on commit 0272ebd

Please sign in to comment.