Skip to content

Commit

Permalink
Merge pull request #9 from real-world-study/kwj1270-issue5
Browse files Browse the repository at this point in the history
[kwj1270-issue5] 회원가입 기능
  • Loading branch information
kwj1270 committed Aug 6, 2021
2 parents f7b58eb + 4984ede commit eae9248
Show file tree
Hide file tree
Showing 19 changed files with 763 additions and 6 deletions.
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ repositories {
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Expand All @@ -24,4 +25,4 @@ apply from: 'test.gradle'

test {
useJUnitPlatform()
}
}
44 changes: 44 additions & 0 deletions src/main/java/com/study/realworld/domain/BaseTimeEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.study.realworld.domain;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {

@CreatedDate
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;

@LastModifiedDate
@Column(name = "updated_at")
private LocalDateTime updatedAt;

@Column(name = "deleted_at")
private LocalDateTime deletedAt;

public LocalDateTime createdAt() {
return createdAt;
}

public LocalDateTime updatedAt() {
return updatedAt;
}

public LocalDateTime deletedAt() {
return deletedAt;
}

// 추후 삭제시 읽어서 기록하는 방식으로 변경 예정
public void recordDeletedTime(final LocalDateTime deletedAt) {
this.deletedAt = deletedAt;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.study.realworld.domain.user.application;

import com.study.realworld.domain.user.domain.User;
import com.study.realworld.domain.user.domain.UserRepository;
import com.study.realworld.domain.user.dto.UserJoinRequest;
import com.study.realworld.domain.user.dto.UserJoinResponse;
import org.springframework.stereotype.Service;

import javax.validation.Valid;

@Service
public class UserJoinService {

private final UserRepository userRepository;

public UserJoinService(final UserRepository userRepository) {
this.userRepository = userRepository;
}

@Valid
public UserJoinResponse join(final UserJoinRequest userJoinRequest) {
final User user = userRepository.save(userJoinRequest.toUser());
return UserJoinResponse.fromUser(user);
}

}
106 changes: 106 additions & 0 deletions src/main/java/com/study/realworld/domain/user/domain/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.study.realworld.domain.user.domain;

import com.study.realworld.domain.BaseTimeEntity;

import javax.persistence.*;

@Entity
public class User extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;

@Column(name = "user_email", length = 50, nullable = false, unique = true)
private String email;

@Column(name = "user_username", length = 20, nullable = false)
private String username;

@Column(name = "uesr_password", nullable = false)
private String password;

@Column(name = "user_bio")
private String bio;

@Column(name = "user_image")
private String image;

protected User() {
}

private User(final UserBuilder userBuilder) {
this.email = userBuilder.email;
this.username = userBuilder.username;
this.password = userBuilder.password;
this.bio = userBuilder.bio;
this.image = userBuilder.image;
}

public String email() {
return email;
}

public String username() {
return username;
}

public String bio() {
return bio;
}

public String image() {
return image;
}

public static UserBuilder Builder() {
return new UserBuilder();
}

public boolean checkPassword(final String otherPassword) {
return password.equals(otherPassword);
}

public static class UserBuilder {
private String email;
private String username;
private String password;
private String bio;
private String image;

private UserBuilder() {
}

public UserBuilder email(final String email) {
this.email = email;
return this;
}

public UserBuilder username(final String username) {
this.username = username;
return this;
}

public UserBuilder password(final String password) {
this.password = password;
return this;
}

public UserBuilder bio(final String bio) {
this.bio = bio;
return this;
}

public UserBuilder image(final String image) {
this.image = image;
return this;
}

public User build() {
return new User(this);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.study.realworld.domain.user.domain;

import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.study.realworld.domain.user.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.study.realworld.domain.user.domain.User;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;

@JsonTypeName("user")
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
public final class UserJoinRequest {

@NotBlank
@JsonProperty("username")
private String username;

@Email
@NotBlank
@JsonProperty("email")
private String email;

@NotBlank
@JsonProperty("password")
private String password;

private UserJoinRequest() {
}

// 테스트용 오버로딩 생성자 -> 주관적인 생각으로 이런 상황은 오버로딩으로 유연성을 주는게 좋다고 생각합니다.
UserJoinRequest(final String username, final String email, final String password) {
this.username = username;
this.email = email;
this.password = password;
}

public final User toUser() {
return User.Builder()
.email(email)
.username(username)
.password(password)
.build();
}

@Override
public final String toString() {
return "UserJoinRequest{" +
"username='" + username + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
'}';
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.study.realworld.domain.user.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.study.realworld.domain.user.domain.User;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;

@JsonTypeName("user")
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
public final class UserJoinResponse {

@NotBlank
@JsonProperty("username")
private String username;

@Email
@NotBlank
@JsonProperty("email")
private String email;

@JsonProperty("bio")
private String bio;

@JsonProperty("image")
private String image;

public static final UserJoinResponse fromUser(final User user) {
return new UserJoinResponse(user);
}

private UserJoinResponse() {
}

private UserJoinResponse(final User user) {
this.email = user.email();
this.username = user.username();
this.bio = user.bio();
this.image = user.image();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.study.realworld.domain.user.ui;

import com.study.realworld.domain.user.application.UserJoinService;
import com.study.realworld.domain.user.dto.UserJoinRequest;
import com.study.realworld.domain.user.dto.UserJoinResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RestController;

import javax.validation.Valid;

@RestController
public class UserRestController {

private static final String JOIN_REQUEST_LOG_MESSAGE = "join request: {}";
private static final Logger log = LoggerFactory.getLogger(UserRestController.class);

private final UserJoinService userJoinService;

public UserRestController(final UserJoinService userJoinService) {
this.userJoinService = userJoinService;
}

@PostMapping("/api/users")
public ResponseEntity<UserJoinResponse> join(@Valid @RequestBody final UserJoinRequest userJoinRequest) {
log.info(JOIN_REQUEST_LOG_MESSAGE, userJoinRequest.toString());
return ResponseEntity.ok().body(userJoinService.join(userJoinRequest));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.study.realworld.global.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@Configuration
public class JpaConfig {
}
5 changes: 2 additions & 3 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ spring:
encoding: UTF-8
cache-duration: PT1H
datasource:
platform: h2
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:real-world;MODE=MYSQL;DB_CLOSE_DELAY=-1
username: sa
Expand All @@ -19,7 +18,7 @@ spring:
console:
enabled: true
path: /h2-console

logging.level:
org.hibernate.SQL: debug
server:
port: 8080

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.study.realworld;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

class RealworldApplicationTests {

Expand Down

0 comments on commit eae9248

Please sign in to comment.