Skip to content
Open
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
7 changes: 7 additions & 0 deletions leeseo/umc10th/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ dependencies {
// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.1'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:3.0.1'

// Validation
implementation 'org.springframework.boot:spring-boot-starter-validation'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class Umc10thApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.umc10th.domain.auth.controller;

import com.example.umc10th.domain.auth.dto.AuthReqDto;
import com.example.umc10th.domain.auth.dto.AuthResDto;
import com.example.umc10th.domain.auth.exception.code.AuthSuccessCode;
import com.example.umc10th.domain.auth.service.AuthService;
import com.example.umc10th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
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;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/auth")
@Tag(name = "Auth", description = "인증 관련 API")
public class AuthController implements AuthControllerDocs{

private final AuthService authService;

@PostMapping("/sign-up")
public ApiResponse<AuthResDto.Id> signUp(
@RequestBody @Valid AuthReqDto.Signup dto
) {
return ApiResponse.onSuccess(AuthSuccessCode.SIGNUP_OK, authService.signUp(dto));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.umc10th.domain.auth.controller;

import com.example.umc10th.domain.auth.dto.AuthReqDto;
import com.example.umc10th.domain.auth.dto.AuthResDto;
import com.example.umc10th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.RequestBody;

public interface AuthControllerDocs {

@Operation(
summary = "회원가입",
description = "이메일 회원가입 진행"
)
public ApiResponse<AuthResDto.Id> signUp(
@RequestBody @Valid AuthReqDto.Signup dto
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.umc10th.domain.auth.converter;

import com.example.umc10th.domain.auth.dto.AuthReqDto;
import com.example.umc10th.domain.member.entity.Member;
import com.example.umc10th.domain.member.enums.SocialType;

import java.util.UUID;


public class AuthConverter {

public static Member toMember(
AuthReqDto.Signup dto,
String salt
) {
return Member.builder()
.email(dto.email())
.password(salt)
.nickname(dto.nickname())
.gender(dto.gender())
.birth(dto.birth())
.address(dto.address())
.fullAddress(dto.fullAddress())
.socialId("email"+UUID.randomUUID())
.socialType(SocialType.EMAIL)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.example.umc10th.domain.auth.dto;

import com.example.umc10th.domain.member.dto.MemberReqDto;
import com.example.umc10th.domain.member.enums.FoodType;
import com.example.umc10th.domain.member.enums.Gender;
import com.example.umc10th.domain.mission.enums.Address;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import java.time.LocalDate;
import java.util.List;

public class AuthReqDto {

@Schema(name = "SignUp", description = "회원가입 정보를 저장합합니다.")
public record Signup (
@Email
@NotBlank
String email,
@NotBlank
String password,
@NotBlank
String nickname,
@NotNull
Gender gender,
@NotNull
LocalDate birth,
@NotNull
Address address,
@NotBlank
String fullAddress,
@NotNull
List<FoodType> food
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.umc10th.domain.auth.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
public class AuthResDto {

@Builder
public record Id(
Long id
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.umc10th.domain.auth.exception;

import com.example.umc10th.global.apiPayload.code.BaseErrorCode;
import com.example.umc10th.global.apiPayload.exception.BaseException;

public class AuthException extends BaseException {
public AuthException(BaseErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.umc10th.domain.auth.exception.code;

import com.example.umc10th.global.apiPayload.code.BaseSuccessCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;

@Getter
@RequiredArgsConstructor
public enum AuthSuccessCode implements BaseSuccessCode {

SIGNUP_OK(HttpStatus.OK,
"AUTH200_1",
"회원가입 되었습니다.");

private final HttpStatus status;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.example.umc10th.domain.auth.service;

import com.example.umc10th.domain.auth.converter.AuthConverter;
import com.example.umc10th.domain.auth.dto.AuthReqDto;
import com.example.umc10th.domain.auth.dto.AuthResDto;
import com.example.umc10th.domain.member.converter.MemberConverter;
import com.example.umc10th.domain.member.entity.Food;
import com.example.umc10th.domain.member.entity.Member;
import com.example.umc10th.domain.member.enums.FoodType;
import com.example.umc10th.domain.member.exception.FoodException;
import com.example.umc10th.domain.member.exception.MemberException;
import com.example.umc10th.domain.member.exception.code.FoodErrorCode;
import com.example.umc10th.domain.member.exception.code.MemberErrorCode;
import com.example.umc10th.domain.member.repository.FoodRepository;
import com.example.umc10th.domain.member.repository.MemberRepository;
import com.example.umc10th.domain.member.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@RequiredArgsConstructor
public class AuthService {

private final FoodRepository foodRepository;
private final PasswordEncoder passwordEncoder;
private final MemberRepository memberRepository;

@Transactional
public AuthResDto.Id signUp(AuthReqDto.Signup dto) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

회원가입 시에 이메일 중복 검사를 추가하면 좋을 것 같습니다~

String salt = passwordEncoder.encode(dto.password());
Member member = AuthConverter.toMember(dto, salt);
List<Food> list = new ArrayList<>();
if (dto.food() != null) {
for (FoodType f : dto.food()) {
Food food = foodRepository.findByName(f)
.orElseThrow(() -> new FoodException(FoodErrorCode.FOOD_TYPE_NOT_FOUND));
list.add(food);
}
}
memberRepository.save(member);
member.updateFoodList(list);
Comment on lines +45 to +46
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재는 memberRepository.save(member) 이후 member.updateFoodList(list)를 호출하고 있는데, 음식 카테고리도 회원가입 과정에서 함께 생성되는 연관 정보이므로 먼저 연관관계를 세팅한 뒤 저장하는 흐름이 더 자연스러울 것 같습니다!

return AuthResDto.Id.builder().id(member.getId()).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.example.umc10th.domain.member.controller;

import com.example.umc10th.domain.member.dto.MemberReqDto;
import com.example.umc10th.domain.member.dto.MemberResDto;
import com.example.umc10th.domain.member.exception.code.MemberErrorCode;
import com.example.umc10th.domain.member.exception.code.MemberSuccessCode;
import com.example.umc10th.domain.member.service.MemberService;
import com.example.umc10th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

Expand All @@ -14,6 +17,8 @@
@Tag(name = "Member", description = "회원 관련 API")
public class MemberController implements MemberControllerDocs{

private final MemberService memberService;

@PostMapping("/me/term")
public ApiResponse<Void> saveTermAgreement(
@RequestBody MemberReqDto.TermList dto
Expand All @@ -22,19 +27,27 @@ public ApiResponse<Void> saveTermAgreement(
return ApiResponse.onSuccess(MemberSuccessCode.TERM_POST_OK, null);
}

@GetMapping("/me/profile")
public ApiResponse<MemberResDto.Profile> getProfile(
@RequestParam Long id
) {
MemberResDto.Profile response = memberService.getProfile(id);
return ApiResponse.onSuccess(MemberSuccessCode.PROFILE_GET_OK, response);
}

@PatchMapping("/me/profile")
public ApiResponse<Void> updateProfile(
@RequestBody MemberReqDto.Profile dto
@RequestBody @Valid MemberReqDto.Profile dto
) {
// 서비스 로직
memberService.updateProfile(dto);
return ApiResponse.onSuccess(MemberSuccessCode.PROFILE_PATCH_OK, null);
}

@PatchMapping("/me/nickname")
public ApiResponse<Void> updateNickname(
@RequestBody MemberReqDto.Nickname dto
@RequestBody @Valid MemberReqDto.Nickname dto
) {
// 서비스 로직
memberService.updateNickname(dto);
return ApiResponse.onSuccess(MemberSuccessCode.NICKNAME_PATCH_OK, null);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.example.umc10th.domain.member.controller;

import com.example.umc10th.domain.member.dto.MemberReqDto;
import com.example.umc10th.domain.member.dto.MemberResDto;
import com.example.umc10th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.web.bind.annotation.PatchMapping;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

public interface MemberControllerDocs {

Expand All @@ -16,20 +18,27 @@ public ApiResponse<Void> saveTermAgreement(
@RequestBody MemberReqDto.TermList dto
);

@Operation(
summary = "회원정보 조회",
description = "회원 프로필 정보를 조회합니다."
)
public ApiResponse<MemberResDto.Profile> getProfile(
@RequestParam Long id
);

@Operation(
summary = "회원정보 저장",
description = "회원 프로필 정보를 저장합니다."
)
public ApiResponse<Void> updateProfile(
@RequestBody MemberReqDto.Profile dto
@RequestBody @Valid MemberReqDto.Profile dto
);

@Operation(
summary = "닉네임 수정",
description = "닉네임을 수정합니다."
)
@PatchMapping("/me/nickname")
public ApiResponse<Void> updateNickname(
@RequestBody MemberReqDto.Nickname dto
@RequestBody @Valid MemberReqDto.Nickname dto
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
package com.example.umc10th.domain.member.converter;

import com.example.umc10th.domain.member.dto.MemberResDto;
import com.example.umc10th.domain.member.entity.Food;
import com.example.umc10th.domain.member.entity.Member;
import com.example.umc10th.domain.member.entity.mapping.MemberFood;

public class MemberConverter {

public static MemberResDto.Profile toProfile(
Member member
) {
return MemberResDto.Profile.builder()
.id(member.getId())
.nickname(member.getNickname())
.birth(member.getBirth())
.address(member.getAddress())
.fullAddress(member.getFullAddress())
.gender(member.getGender())
.food(member.getMemberFoodList().stream().map(MemberFood::getFood).toList())
.build();
}

public static MemberFood toMemberFood(
Food food,
Member member
) {
return MemberFood.builder()
.member(member)
.food(food)
.build();
}
}
Loading