Skip to content

Commit

Permalink
Feature: 회원가입 및 로그인 구현
Browse files Browse the repository at this point in the history
Feature: 회원가입 및 로그인 구현
  • Loading branch information
lcomment authored May 10, 2024
2 parents 840501c + 9d30bd4 commit 098fd1e
Show file tree
Hide file tree
Showing 20 changed files with 497 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ out/

### generated ###
src/main/generated/
*/.jqwik-database
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.cakk.api.controller.user;

import jakarta.validation.Valid;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;

import com.cakk.api.dto.request.user.UserSignInRequest;
import com.cakk.api.dto.request.user.UserSignUpRequest;
import com.cakk.api.dto.response.user.JwtResponse;
import com.cakk.api.service.user.UserService;
import com.cakk.common.response.ApiResponse;

@RestController
@RequiredArgsConstructor
public class SignController {

private final UserService userService;

@PostMapping("/sign-up")
public ApiResponse<JwtResponse> signUp(
@Valid @RequestBody UserSignUpRequest request
) {
return ApiResponse.success(userService.signUp(request));
}

@PostMapping("/sign-in")
public ApiResponse<JwtResponse> signIn(
@Valid @RequestBody UserSignInRequest request
) {
return ApiResponse.success(userService.signIn(request));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cakk.api.dto.request.user;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import com.cakk.common.enums.Provider;

public record UserSignInRequest(
@NotNull
Provider provider,
@NotBlank
String idToken
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.cakk.api.dto.request.user;

import java.time.LocalDate;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import com.cakk.common.enums.Gender;
import com.cakk.common.enums.Provider;

public record UserSignUpRequest(
@NotNull
Provider provider,
@NotBlank
String idToken,
String deviceOs,
String deviceToken,
@NotBlank
String nickname,
@NotBlank
String email,
@NotNull
LocalDate birthday,
@NotNull
Gender gender
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cakk.api.dto.response.user;

import com.cakk.api.vo.JsonWebToken;

public record JwtResponse(
String accessToken,
String refreshToken,
String grantType
) {

public static JwtResponse from(JsonWebToken jwt) {
return new JwtResponse(jwt.accessToken(), jwt.refreshToken(), jwt.grantType());
}
}
26 changes: 26 additions & 0 deletions cakk-api/src/main/java/com/cakk/api/mapper/UserMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.cakk.api.mapper;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import com.cakk.api.dto.request.user.UserSignUpRequest;
import com.cakk.common.enums.Role;
import com.cakk.domain.entity.user.User;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UserMapper {

public static User supplyUserBy(UserSignUpRequest dto, String providerId) {
return User.builder()
.provider(dto.provider())
.providerId(providerId)
.nickname(dto.nickname())
.email(dto.email())
.gender(dto.gender())
.birthday(dto.birthday())
.deviceOs(dto.deviceOs())
.deviceToken(dto.deviceToken())
.role(Role.USER)
.build();
}
}
33 changes: 33 additions & 0 deletions cakk-api/src/main/java/com/cakk/api/service/user/UserService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,43 @@
package com.cakk.api.service.user;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;

import com.cakk.api.dto.request.user.UserSignInRequest;
import com.cakk.api.dto.request.user.UserSignUpRequest;
import com.cakk.api.dto.response.user.JwtResponse;
import com.cakk.api.factory.OidcProviderFactory;
import com.cakk.api.mapper.UserMapper;
import com.cakk.api.provider.jwt.JwtProvider;
import com.cakk.domain.entity.user.User;
import com.cakk.domain.repository.reader.UserReader;
import com.cakk.domain.repository.writer.UserWriter;

@Service
@RequiredArgsConstructor
public class UserService {

private final OidcProviderFactory oidcProviderFactory;
private final JwtProvider jwtProvider;

private final UserReader userReader;
private final UserWriter userWriter;

@Transactional
public JwtResponse signUp(UserSignUpRequest dto) {
final String providerId = oidcProviderFactory.getProviderId(dto.provider(), dto.idToken());
final User user = userWriter.create(UserMapper.supplyUserBy(dto, providerId));

return JwtResponse.from(jwtProvider.generateToken(user));
}

@Transactional(readOnly = true)
public JwtResponse signIn(UserSignInRequest dto) {
final String providerId = oidcProviderFactory.getProviderId(dto.provider(), dto.idToken());
final User user = userReader.findByProviderId(providerId);

return JwtResponse.from(jwtProvider.generateToken(user));
}
}
16 changes: 16 additions & 0 deletions cakk-api/src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,19 @@ slack:
webhook:
is-enable: false
url: url

cloud:
aws:
credentials:
access-key: test
secret-key: test
s3:
bucket: test-bucket
expire-in: 180000
object-key: key
region:
static:
ap-northeast-2
stack:
auto:
false
8 changes: 4 additions & 4 deletions cakk-api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
server:
servlet:
context-path: /api/v1

spring:
application:
title: Cakk
version: 1.0.0
banner:
location: classpath:/app-banner.dat
servlet:
multipart:
max-file-size: 50MB
max-request-size: 50MB
jpa:
open-in-view: false
hibernate:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.cakk.api.common.base;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.ActiveProfiles;

import com.navercorp.fixturemonkey.FixtureMonkey;
import com.navercorp.fixturemonkey.api.introspector.BuilderArbitraryIntrospector;
import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector;
import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector;

@ActiveProfiles("test")
@SpringBootTest(
properties = "spring.profiles.active: test",
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
public abstract class IntegrationTest {

@Autowired
protected TestRestTemplate restTemplate;

protected final FixtureMonkey getConstructorMonkey() {
return FixtureMonkey.builder()
.objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE)
.build();
}

protected final FixtureMonkey getReflectionMonkey() {
return FixtureMonkey.builder()
.objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE)
.build();
}

protected final FixtureMonkey getBuilderMonkey() {
return FixtureMonkey.builder()
.objectIntrospector(BuilderArbitraryIntrospector.INSTANCE)
.build();
}
}
37 changes: 37 additions & 0 deletions cakk-api/src/test/java/com/cakk/api/common/base/ServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.cakk.api.common.base;

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;

import com.navercorp.fixturemonkey.FixtureMonkey;
import com.navercorp.fixturemonkey.api.introspector.BuilderArbitraryIntrospector;
import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector;
import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector;

import com.cakk.domain.config.JpaConfig;

@Import(JpaConfig.class)
@ActiveProfiles("test")
@ExtendWith(MockitoExtension.class)
public abstract class ServiceTest {

protected final FixtureMonkey getConstructorMonkey() {
return FixtureMonkey.builder()
.objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE)
.build();
}

protected final FixtureMonkey getReflectionMonkey() {
return FixtureMonkey.builder()
.objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE)
.build();
}

protected final FixtureMonkey getBuilderMonkey() {
return FixtureMonkey.builder()
.objectIntrospector(BuilderArbitraryIntrospector.INSTANCE)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.cakk.api.common.container;

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
public abstract class MysqlTestContainer {

private static final String MYSQL_VERSION = "mysql:8";
private static final String DATABASE_NAME = "cakk";

@Container
public static final MySQLContainer MYSQL_CONTAINER = new MySQLContainer(MYSQL_VERSION)
.withDatabaseName(DATABASE_NAME);

static {
MYSQL_CONTAINER.start();
}
}
Loading

0 comments on commit 098fd1e

Please sign in to comment.