Skip to content

Commit

Permalink
Merge pull request #60 from dev-hooon/feat/#17
Browse files Browse the repository at this point in the history
feat : Owner 회원가입 & 로그인 구현
  • Loading branch information
kkangh00n authored Jan 7, 2024
2 parents 5779770 + 4b756c2 commit 6fa48fc
Show file tree
Hide file tree
Showing 17 changed files with 550 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ public enum ErrorCode {
CAN_NOT_ENTRY("웨이팅을 입장 처리할 수 없습니다"),
WAITING_DOES_NOT_EXIST("웨이팅이 존재하지 않습니다"),
SHOP_NOT_RUNNING("가게가 영업시간이 아닙니다."),
INTERNAL_SERVER_ERROR("내부 서버 오류입니다.");
INTERNAL_SERVER_ERROR("내부 서버 오류입니다."),

ALREADY_EXIST_OWNER("이미 존재하는 점주입니다"),
BAD_REQUEST_EMAIL_OR_PASSWORD("이메일 혹은 비밀번호를 확인해주세요"),
BAD_REQUEST_INPUT_GENDER_TYPE("성별 타입을 양식대로 입력해주세요");

private final String message;
}
26 changes: 24 additions & 2 deletions src/main/java/com/prgrms/catchtable/member/domain/Gender.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
package com.prgrms.catchtable.member.domain;

import static com.prgrms.catchtable.common.exception.ErrorCode.BAD_REQUEST_INPUT_GENDER_TYPE;

import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException;
import java.util.Arrays;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum Gender {
MALE,
FEMALE
MALE("male"),
FEMALE("female");

private final String type;

public static Gender of(String input) {
return Arrays.stream(values())
.filter(gender -> gender.isEqual(input))
.findAny()
.orElseThrow(() -> new BadRequestCustomException(BAD_REQUEST_INPUT_GENDER_TYPE));
}

private boolean isEqual(String input) {
return input.equals(this.type);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.prgrms.catchtable.owner.controller;

import com.prgrms.catchtable.jwt.token.Token;
import com.prgrms.catchtable.owner.dto.request.JoinOwnerRequest;
import com.prgrms.catchtable.owner.dto.request.LoginOwnerRequest;
import com.prgrms.catchtable.owner.dto.response.JoinOwnerResponse;
import com.prgrms.catchtable.owner.service.OwnerService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
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;

@RestController
@RequiredArgsConstructor
@RequestMapping("/owners")
public class OwnerController {

private final OwnerService ownerService;

@PostMapping("/join")
public ResponseEntity<JoinOwnerResponse> join(
@Valid @RequestBody JoinOwnerRequest joinOwnerRequest) {
JoinOwnerResponse joinOwnerResponse = ownerService.joinOwner(joinOwnerRequest);

return ResponseEntity.status(HttpStatus.CREATED).body(joinOwnerResponse);
}

@PostMapping("/login")
public ResponseEntity<Token> login(@Valid @RequestBody LoginOwnerRequest loginOwnerRequest) {
Token responseToken = ownerService.loginOwner(loginOwnerRequest);

return ResponseEntity.ok(responseToken);
}

}
54 changes: 52 additions & 2 deletions src/main/java/com/prgrms/catchtable/owner/domain/Owner.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static lombok.AccessLevel.PROTECTED;

import com.prgrms.catchtable.common.BaseEntity;
import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.member.domain.Gender;
import com.prgrms.catchtable.shop.domain.Shop;
import jakarta.persistence.Column;
Expand All @@ -18,14 +19,19 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import java.time.LocalDate;
import java.util.Collection;
import java.util.Collections;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Getter
@NoArgsConstructor(access = PROTECTED)
@Entity
public class Owner extends BaseEntity {
public class Owner extends BaseEntity implements UserDetails {

@Id
@GeneratedValue(strategy = IDENTITY)
Expand All @@ -35,13 +41,23 @@ public class Owner extends BaseEntity {
@Column(name = "owner_name")
private String name;

@Column(name = "email")
private String email;

@Column(name = "password")
private String password;

@Column(name = "phone_number")
private String phoneNumber;

@Column(name = "gender")
@Enumerated(STRING)
private Gender gender;

@Column(name = "role")
@Enumerated(STRING)
private Role role;

@Column(name = "date_birth")
private LocalDate dateBirth;

Expand All @@ -50,11 +66,45 @@ public class Owner extends BaseEntity {
private Shop shop;

@Builder
public Owner(String name, String phoneNumber, Gender gender, LocalDate dateBirth) {
public Owner(String name, String email, String password, String phoneNumber, Gender gender,
LocalDate dateBirth) {
this.name = name;
this.email = email;
this.password = password;
this.phoneNumber = phoneNumber;
this.gender = gender;
this.dateBirth = dateBirth;
this.role = Role.OWNER;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(new SimpleGrantedAuthority(role.getRole()));
}

@Override
public String getUsername() {
return email;
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}

public void insertShop(Shop shop) {
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/com/prgrms/catchtable/owner/dto/OwnerMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.prgrms.catchtable.owner.dto;

import com.prgrms.catchtable.member.domain.Gender;
import com.prgrms.catchtable.owner.domain.Owner;
import com.prgrms.catchtable.owner.dto.request.JoinOwnerRequest;
import com.prgrms.catchtable.owner.dto.response.JoinOwnerResponse;

public class OwnerMapper {

public static Owner toEntity(JoinOwnerRequest joinOwnerRequest, String encodePassword,
Gender gender) {
return Owner.builder()
.name(joinOwnerRequest.name())
.email(joinOwnerRequest.email())
.password(encodePassword)
.phoneNumber(joinOwnerRequest.phoneNumber())
.gender(gender)
.dateBirth(joinOwnerRequest.dateBirth())
.build();
}

public static JoinOwnerResponse from(Owner owner) {
return JoinOwnerResponse.builder()
.name(owner.getName())
.email(owner.getEmail())
.phoneNumber(owner.getPhoneNumber())
.gender(owner.getGender().getType())
.dateBirth(owner.getDateBirth())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.prgrms.catchtable.owner.dto.request;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import java.time.LocalDate;
import lombok.Builder;

@Builder
public record JoinOwnerRequest(

String name,
@Email
String email,
String password,
@Pattern(regexp = "^(01[016789]){1}-([0-9]{3,4}){1}-([0-9]{4}){1}$")
String phoneNumber,
String gender,
@JsonFormat(pattern = "yyyy-MM-dd")
LocalDate dateBirth
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.prgrms.catchtable.owner.dto.request;

import jakarta.validation.constraints.Email;
import lombok.Builder;

@Builder
public record LoginOwnerRequest(

@Email
String email,
String password

) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.prgrms.catchtable.owner.dto.response;

import java.time.LocalDate;
import lombok.Builder;

@Builder
public record JoinOwnerResponse(

String name,
String email,
String phoneNumber,
String gender,
LocalDate dateBirth
) {

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.prgrms.catchtable.owner.repository;

import com.prgrms.catchtable.owner.domain.Owner;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OwnerRepository extends JpaRepository<Owner, Long> {

boolean existsOwnerByEmail(String email);

Optional<Owner> findOwnerByEmail(String email);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.prgrms.catchtable.owner.service;

import static com.prgrms.catchtable.common.exception.ErrorCode.ALREADY_EXIST_OWNER;
import static com.prgrms.catchtable.common.exception.ErrorCode.BAD_REQUEST_EMAIL_OR_PASSWORD;

import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException;
import com.prgrms.catchtable.jwt.provider.JwtTokenProvider;
import com.prgrms.catchtable.jwt.token.Token;
import com.prgrms.catchtable.member.domain.Gender;
import com.prgrms.catchtable.owner.domain.Owner;
import com.prgrms.catchtable.owner.dto.OwnerMapper;
import com.prgrms.catchtable.owner.dto.request.JoinOwnerRequest;
import com.prgrms.catchtable.owner.dto.request.LoginOwnerRequest;
import com.prgrms.catchtable.owner.dto.response.JoinOwnerResponse;
import com.prgrms.catchtable.owner.repository.OwnerRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class OwnerService {

private final OwnerRepository ownerRepository;
private final PasswordEncoder passwordEncoder;
private final JwtTokenProvider jwtTokenProvider;

public JoinOwnerResponse joinOwner(JoinOwnerRequest joinOwnerRequest) {

//이미 존재하는 이메일이라면
validateExistsOwner(joinOwnerRequest);

String encodePassword = passwordEncoder.encode(joinOwnerRequest.password());

Gender gender = Gender.of(joinOwnerRequest.gender());

Owner joinOwner = ownerRepository.save(
OwnerMapper.toEntity(joinOwnerRequest, encodePassword, gender));

return OwnerMapper.from(joinOwner);

}

private void validateExistsOwner(JoinOwnerRequest joinOwnerRequest) {
if (ownerRepository.existsOwnerByEmail(joinOwnerRequest.email())) {
throw new BadRequestCustomException(ALREADY_EXIST_OWNER);
}
}

public Token loginOwner(LoginOwnerRequest loginRequest) {

//email 확인
Owner loginOwner = ownerRepository.findOwnerByEmail(loginRequest.email())
.orElseThrow(() -> new BadRequestCustomException(BAD_REQUEST_EMAIL_OR_PASSWORD));

//password 확인
validatePassword(loginRequest, loginOwner);

return jwtTokenProvider.createToken(loginOwner.getEmail());
}

private void validatePassword(LoginOwnerRequest loginRequest, Owner loginOwner) {
if (!passwordEncoder.matches(loginRequest.password(), loginOwner.getPassword())) {
throw new BadRequestCustomException(BAD_REQUEST_EMAIL_OR_PASSWORD);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
Expand All @@ -23,6 +25,11 @@ public class SecurityConfig {
private final ExceptionHandlerFilter exceptionHandlerFilter;
private final JwtAuthenticationFilter jwtAuthenticationFilter;

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.prgrms.catchtable.common.base;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
Expand All @@ -15,6 +16,7 @@ public abstract class BaseIntegrationTest {
public MockMvc mockMvc;

public static String asJsonString(final Object object) throws Exception {
objectMapper.registerModule(new JavaTimeModule());
return objectMapper.writeValueAsString(object);
}
}
Loading

0 comments on commit 6fa48fc

Please sign in to comment.