Skip to content

Commit

Permalink
Merge pull request #12 from KNU-HAEDAL/issue/#8
Browse files Browse the repository at this point in the history
Issue/#8
  • Loading branch information
bayy1216 authored May 31, 2024
2 parents 948b77f + a2df275 commit 3de7285
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.haedal.zzansuni.controller.admin;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.haedal.zzansuni.controller.auth.AuthReq;
import org.haedal.zzansuni.core.api.ApiResponse;
import org.haedal.zzansuni.domain.auth.AuthService;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "admin", description = "관리자 API")
@RequiredArgsConstructor
@RestController
public class AdminController {
private final AuthService authService;

@ResponseStatus(HttpStatus.CREATED)
@Operation(summary= "매니저 등록", description = "매니저를 등록한다.")
@PostMapping("/api/auth/manager")
public ApiResponse<Void> createManager(@RequestBody @Valid AuthReq.EmailSignupRequest request) {
authService.createManager(request.toCommand());
return ApiResponse.success(null, "매니저 등록 성공");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ public ApiResponse<AuthRes.LoginResponse> oauth2(@RequestBody @Valid AuthReq.OAu
return ApiResponse.success(response);
}

@Operation(summary = "이메일 회원가입", description = "이메일 회원가입을 한다.")
@PostMapping("/api/auth/signup")
public ApiResponse<AuthRes.LoginResponse> signup(@RequestBody @Valid AuthReq.EmailSignupRequest request) {
Pair<JwtToken, UserModel> pair = authService.signup(request.toCommand());
var response = AuthRes.LoginResponse.from(pair.getFirst(), pair.getSecond());
return ApiResponse.success(response);
}

@Operation(summary = "로그인", description = "로그인한다.")
@PostMapping("/api/auth/login")
public ApiResponse<AuthRes.LoginResponse> login(@RequestBody @Valid AuthReq.EmailLoginRequest request) {
Pair<JwtToken, UserModel> pair = authService.login(request.email(), request.password());
var response = AuthRes.LoginResponse.from(pair.getFirst(), pair.getSecond());
return ApiResponse.success(response);
}

@Operation(summary = "로그아웃", description = "로그아웃한다.")
@PostMapping("/api/auth/logout")
public ApiResponse<Void> logout() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.haedal.zzansuni.domain.auth.OAuth2Provider;
import org.haedal.zzansuni.domain.user.UserCommand;

public class AuthReq {
public record OAuth2LoginRequest(
Expand All @@ -13,4 +14,29 @@ public record OAuth2LoginRequest(
String state
) {
}

public record EmailSignupRequest(
@NotBlank(message = "email은 필수입니다.")
String email,
@NotBlank(message = "password는 필수입니다.")
String password,
@NotBlank(message = "nickname은 필수입니다.")
String nickname
) {
public UserCommand.Create toCommand() {
return UserCommand.Create.builder()
.email(email)
.password(password)
.nickname(nickname)
.build();
}
}

public record EmailLoginRequest(
@NotBlank(message = "email은 필수입니다.")
String email,
@NotBlank(message = "password는 필수입니다.")
String password
) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
import org.springframework.data.util.Pair;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class AuthService {
private final List<OAuth2Client> oAuth2Clients;
private final BCryptPasswordEncoder passwordEncoder;
private final JwtUtils jwtUtils;
private final UserReader userReader;
private final UserStore userStore;
Expand Down Expand Up @@ -59,4 +62,42 @@ private JwtToken createToken(User user) {
return jwtUtils.createToken(jwtUser);
}

@Transactional
public Pair<JwtToken, UserModel> signup(UserCommand.Create command){
if(userReader.existsByEmail(command.getEmail())){
throw new IllegalArgumentException("이미 존재하는 이메일입니다.");
}
command.changePassword(passwordEncoder.encode(command.getPassword()));

User user = User.create(command);
userStore.store(user);
JwtToken jwtToken = createToken(user);
UserModel userModel = UserModel.from(user);
return Pair.of(jwtToken, userModel);
}

@Transactional
public void createManager(UserCommand.Create command){
if(userReader.existsByEmail(command.getEmail())){
throw new IllegalArgumentException("이미 존재하는 이메일입니다.");
}
command.changePassword(passwordEncoder.encode(command.getPassword()));

User user = User.createManager(command);
userStore.store(user);
}

@Transactional(readOnly = true)
public Pair<JwtToken, UserModel> login(String email, String password) {
User user = userReader.findByEmail(email)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이메일입니다."));

if(!passwordEncoder.matches(password, user.getPassword())){
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
}

JwtToken jwtToken = createToken(user);
UserModel userModel = UserModel.from(user);
return Pair.of(jwtToken, userModel);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,32 @@ public static User create(UserCommand.CreateOAuth2 command) {
.build();
}

public static User create(UserCommand.Create command){
return User.builder()
.nickname(command.getNickname())
.email(command.getEmail())
.password(command.getPassword())
.role(Role.USER)
.provider(null)
.authToken(null)
.exp(0)
.profileImageUrl(null)
.build();
}

public static User createManager(UserCommand.Create command){
return User.builder()
.nickname(command.getNickname())
.email(command.getEmail())
.password(command.getPassword())
.role(Role.MANAGER)
.provider(null)
.authToken(null)
.exp(0)
.profileImageUrl(null)
.build();
}

public void update(UserCommand.Update userUpdate) {
this.nickname = userUpdate.getNickname();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.haedal.zzansuni.domain.user;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
Expand All @@ -8,7 +9,30 @@
import org.haedal.zzansuni.core.utils.SelfValidating;
import org.haedal.zzansuni.domain.auth.OAuth2Provider;

import java.util.function.Function;

public class UserCommand {
@Getter
@Builder
public static class Create extends SelfValidating<UserCommand.Create> {
@Email(message = "이메일 형식은 유효하여야 합니다.")
private final String email;
@NotBlank(message = "password는 필수입니다.")
private String password;
@NotBlank(message = "닉네임은 필수입니다.")
private final String nickname;

public Create(String email, String password, String nickname) {
this.email = email;
this.password = password;
this.nickname = nickname;
this.validateSelf();
}

public void changePassword(String encodedPassword){
this.password = encodedPassword;
}
}

@Getter
@Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
public interface UserReader {
User getById(Long id);

boolean existsByEmail(String email);

Optional<User> findByEmail(String email);

Optional<User> findByAuthToken(String authToken);

Page<User> getUserPagingByRanking(Pageable pageable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ public User getById(Long id) {
return userRepository.findById(id).orElseThrow(NoSuchElementException::new);
}

@Override
public boolean existsByEmail(String email) {
return userRepository.existsByEmail(email);
}

@Override
public Optional<User> findByEmail(String email) {
return userRepository.findByEmail(email);
}

@Override
public Optional<User> findByAuthToken(String authToken) {
return userRepository.findByAuthToken(authToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@

public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByAuthToken(String authToken);
boolean existsByEmail(String email);

Optional<User> findByEmail(String email);
}

0 comments on commit 3de7285

Please sign in to comment.