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
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,14 @@ dependencies {
implementation 'mysql:mysql-connector-java:8.0.32'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.projectlombok:lombok:1.18.24'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.1.Final'
implementation 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'

// OAuth
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.Alchive.backend.adapter.in.web.controller;

import com.Alchive.backend.adapter.in.web.dto.request.UserCreateRequestDTO;
import com.Alchive.backend.adapter.in.web.dto.request.UserUpdateRequestDTO;
import com.Alchive.backend.adapter.in.web.dto.response.UserResponseDTO;
import com.Alchive.backend.application.command.ChangeUserDetailCommand;
import com.Alchive.backend.application.command.SignUpCommand;
import com.Alchive.backend.application.port.in.UserUseCase;
import com.Alchive.backend.config.result.ResultCode;
Expand All @@ -10,10 +12,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@Tag(name = "사용자", description = "사용자 관련 api입니다.")
@RequestMapping("/api/v2/users")
Expand All @@ -29,4 +28,26 @@ public ResponseEntity<ResultResponse> signUp(@RequestBody UserCreateRequestDTO u
UserResponseDTO userResponseDTO = userUseCase.signUp(signUpCommand);
return ResponseEntity.ok(ResultResponse.of(ResultCode.USER_CREATE_SUCCESS, userResponseDTO));
}

@Operation(summary = "회원정보 수정", description = "회원 설명글과 자동 저장 설정을 변경하는 메서드입니다. ")
@PostMapping("/{id}")
public ResponseEntity<ResultResponse> updateUser(@RequestBody UserUpdateRequestDTO userUpdateRequestDTO, @PathVariable Long id) {
ChangeUserDetailCommand changeUserDetailCommand = ChangeUserDetailCommand.of(userUpdateRequestDTO);
UserResponseDTO userResponseDTO = userUseCase.changeUserDetail(id, changeUserDetailCommand);
return ResponseEntity.ok(ResultResponse.of(ResultCode.USER_UPDATE_SUCCESS, userResponseDTO));
}

@Operation(summary = "회원정보 조회", description = "회원정보를 조회하는 메서드입니다. ")
@GetMapping("/{id}")
public ResponseEntity<ResultResponse> getUser(@PathVariable Long id){
UserResponseDTO userResponseDTO = userUseCase.viewUserDetail(id);
return ResponseEntity.ok(ResultResponse.of(ResultCode.USER_DETAIL_INFO_SUCCESS, userResponseDTO));
}

@Operation(summary = "회원 삭제", description = "회원을 삭제하는 메서드입니다. ")
@DeleteMapping("/{id}")
public ResponseEntity<ResultResponse> deleteUser(@PathVariable Long id) {
userUseCase.deleteUser(id);
return ResponseEntity.ok(ResultResponse.of(ResultCode.USER_DELETE_SUCCESS));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.Alchive.backend.adapter.in.web.dto.request;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserUpdateRequestDTO {
private String userDescription;
private Boolean autoSave;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@

import com.Alchive.backend.adapter.out.persistence.entity.UserEntity;
import com.Alchive.backend.adapter.out.persistence.repository.UserRepository;
import com.Alchive.backend.application.port.out.user.CreateUserPort;
import com.Alchive.backend.application.port.out.user.ExistUserPort;
import com.Alchive.backend.application.port.out.user.FindUserPort;
import com.Alchive.backend.application.port.out.user.*;
import com.Alchive.backend.config.error.exception.user.NoSuchUserIdException;
import com.Alchive.backend.mapper.UserMapper;
import com.Alchive.backend.mapper.IUserMapper;
import com.Alchive.backend.model.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@RequiredArgsConstructor
@Component
public class UserPersistenceAdapter implements CreateUserPort, FindUserPort, ExistUserPort {
public class UserPersistenceAdapter implements CreateUserPort, FindUserPort, ExistUserPort, UpdateUserPort, DeleteUserPort {
private final UserRepository userRepository;
private final UserMapper userMapper;
private final IUserMapper userMapper;

@Override
public User createUser(User user) {
// UserEntity userEntity = userMapper.toEntity(user);
UserEntity userEntity = new UserEntity(user.getEmail(), user.getName());
UserEntity userEntity = userMapper.toEntity(user);
UserEntity savedUser = userRepository.save(userEntity);
return userMapper.toDomain(savedUser);
}
Expand All @@ -32,6 +29,13 @@ public User findUserByEmail(String email) {
return userMapper.toDomain(userEntity);
}

@Override
public User findById(Long id) {
UserEntity userEntity = userRepository.findById(id)
.orElseThrow(NoSuchUserIdException::new);
return userMapper.toDomain(userEntity);
}

@Override
public Boolean ExistByUserEmail(String email) {
return userRepository.existsUserEntityByEmail(email);
Expand All @@ -41,4 +45,15 @@ public Boolean ExistByUserEmail(String email) {
public Boolean ExistByUserName(String name) {
return userRepository.existsUserEntityByName(name);
}

@Override
public void updateUser(User user) {
userRepository.updateUser(user.getDescription(), user.getAutoSave(), user.getId());
}

@Override
public void deleteUser(User user) {
UserEntity userEntity = userMapper.toEntity(user);
userRepository.delete(userEntity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@SuperBuilder
@NoArgsConstructor
@MappedSuperclass
@Getter
@EntityListeners(AuditingEntityListener.class)
Expand All @@ -23,6 +28,7 @@ public abstract class BaseEntity {
@Column(name = "updated_at")
private LocalDateTime updatedAt;

@Builder.Default
@Column(name = "is_deleted", nullable = false, columnDefinition = "bit(1) default 0")
private Boolean isDeleted = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import com.Alchive.backend.model.User;
import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor
@SuperBuilder
@Getter
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Entity
@SQLDelete(sql = "UPDATE user SET is_deleted = true WHERE id = ?")
@Where(clause = "is_deleted = false")
Expand All @@ -31,12 +32,6 @@ public class UserEntity extends BaseEntity {
private String description;

@Column(name = "auto_save", nullable = false)
@ColumnDefault("true")
@Builder.Default
private Boolean autoSave = true;

@Builder
public UserEntity (String email, String name) {
this.email = email;
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import com.Alchive.backend.adapter.out.persistence.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.security.core.parameters.P;

import java.util.Optional;

Expand All @@ -10,4 +14,7 @@ public interface UserRepository extends JpaRepository<UserEntity, Long> {
Optional<UserEntity> findUserEntityByName(String email);
Boolean existsUserEntityByEmail(String email);
Boolean existsUserEntityByName(String name);
@Modifying(clearAutomatically = true)
@Query("UPDATE UserEntity userEntity SET userEntity.description = :description, userEntity.autoSave = :autoSave WHERE userEntity.id = :id")
void updateUser(@Param(value = "description") String description, @Param(value = "autoSave") Boolean autoSave, @Param(value = "id") Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.Alchive.backend.application.command;

import com.Alchive.backend.adapter.in.web.dto.request.UserUpdateRequestDTO;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor
public class ChangeUserDetailCommand {
private final String description;
@NotBlank
private final Boolean autoSave;

public static ChangeUserDetailCommand of(UserUpdateRequestDTO userUpdateRequestDTO) {
return ChangeUserDetailCommand.builder()
.description(userUpdateRequestDTO.getUserDescription())
.autoSave(userUpdateRequestDTO.getAutoSave())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public class SignUpCommand {
private Long id;
private String email;
private String name;
private String description;
private Boolean autoSave;

public static SignUpCommand of(UserCreateRequestDTO userCreateRequestDTO) {
return SignUpCommand.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.Alchive.backend.application.port.in;

import com.Alchive.backend.adapter.in.web.dto.response.UserResponseDTO;
import com.Alchive.backend.application.command.ChangeUserDetailCommand;
import com.Alchive.backend.application.command.SignUpCommand;
import com.Alchive.backend.model.User;

public interface UserUseCase {
UserResponseDTO signUp(SignUpCommand signUpCommand);
UserResponseDTO changeUserDetail(Long id, ChangeUserDetailCommand changeDescriptionCommand);
UserResponseDTO viewUserDetail(Long id);
void deleteUser(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.Alchive.backend.application.port.out.user;

import com.Alchive.backend.model.User;

public interface DeleteUserPort {
void deleteUser(User user);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

public interface FindUserPort {
User findUserByEmail(String email);
User findById(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.Alchive.backend.application.port.out.user;

import com.Alchive.backend.model.User;

public interface UpdateUserPort {
void updateUser(User user);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.Alchive.backend.application.service;

import com.Alchive.backend.adapter.in.web.dto.response.UserResponseDTO;
import com.Alchive.backend.application.command.ChangeUserDetailCommand;
import com.Alchive.backend.application.command.SignUpCommand;
import com.Alchive.backend.application.port.in.UserUseCase;
import com.Alchive.backend.application.port.out.user.CreateUserPort;
import com.Alchive.backend.application.port.out.user.ExistUserPort;
import com.Alchive.backend.application.port.out.user.FindUserPort;
import com.Alchive.backend.mapper.UserMapper;
import com.Alchive.backend.application.port.out.user.*;
import com.Alchive.backend.config.jwt.JwtTokenProvider;
import com.Alchive.backend.mapper.IUserMapper;
import com.Alchive.backend.model.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -16,33 +16,65 @@
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class UserService implements UserUseCase {
private final UserMapper userMapper;
private final IUserMapper userMapper;
private final JwtTokenProvider jwtTokenProvider;

private final CreateUserPort createUserPort;
private final FindUserPort findUserPort;
private final ExistUserPort existUserPort;
private final UpdateUserPort updateUserPort;
private final DeleteUserPort deleteUserPort;
@Transactional
@Override
public UserResponseDTO signUp(SignUpCommand signUpCommand) {
// 회원가입 요청 도메인 생성
User user = userMapper.commandToDomain(signUpCommand);
log.info("도메인 생성 완료");
// 비즈니스 로직 호출
User user = new User();
Boolean isEmailExist = existUserPort.ExistByUserEmail(user.getEmail());
Boolean isNameExist = existUserPort.ExistByUserName(user.getName());

user.createUser(user.getEmail(), user.getName(), isEmailExist, isNameExist);
log.info("비즈니스 로직 호출 완료");
// 비즈니스 로직 호출
user.createUser(signUpCommand.getEmail(), signUpCommand.getName(), isEmailExist, isNameExist);
// 회원정보 저장
User savedUser = createUserPort.createUser(user);
log.info("엔티티 저장 완료");

// 토큰 발급
String accessToken = jwtTokenProvider.createAccessToken(user.getEmail());
String refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail());

// 저장된 회원 도메인을 응답 DTO로 변환
return userMapper.domainToResponseDTO(user);
log.info("access Token: ", accessToken);
log.info("refresh Token: ", refreshToken);
return userMapper.domainToResponseDTO(savedUser);
}

public User findByEmail(String email) {
User user = findUserPort.findUserByEmail(email);
return user;
}

@Transactional
@Override
public UserResponseDTO changeUserDetail(Long id, ChangeUserDetailCommand changeDescriptionCommand) {
User targetUser = findUserPort.findById(id);

targetUser.changeUserDetail(changeDescriptionCommand.getDescription(), changeDescriptionCommand.getAutoSave());
// JPA update
updateUserPort.updateUser(targetUser);

return userMapper.domainToResponseDTO(targetUser);
}

@Override
public UserResponseDTO viewUserDetail(Long id) {
User user = findUserPort.findById(id);
return userMapper.domainToResponseDTO(user);
}

@Transactional
@Override
public void deleteUser(Long id) {
User user = findUserPort.findById(id);
deleteUserPort.deleteUser(user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
Map.entry("/api/v2/users/username/{name}", List.of("GET")),
Map.entry("/api/v2/sns/{snsId}", List.of("GET")),
Map.entry("/api/v2/slack/reminder", List.of("GET")),
Map.entry("/api/v2/slack/added", List.of("GET"))
Map.entry("/api/v2/slack/added", List.of("GET")),
Map.entry("/api/v2/jwt", List.of("GET"))
);

// EXCLUDE_URL과 메서드에 일치할 경우 현재 필터를 진행하지 않고 다음 필터 진행
Expand Down
Loading
Loading