diff --git a/build.gradle b/build.gradle index 75701b2..efe30fb 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-mail' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' diff --git a/src/main/java/com/baekyangdan/scheduler/code/user/SignUpValidationCode.java b/src/main/java/com/baekyangdan/scheduler/code/user/SignUpValidationCode.java new file mode 100644 index 0000000..45ebf01 --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/code/user/SignUpValidationCode.java @@ -0,0 +1,22 @@ +package com.baekyangdan.scheduler.code.user; + +public enum SignUpValidationCode { + ID_EMPTY("ID를 입력해주십시오"), + ID_DUPLICATED("중복된 ID가 존재합니다"), + EMAIL_EMPTY("Email을 입력해주십시오"), + EMAIL_FORM_INVALID("Email 형식이 올바르지 않습니다"), + EMAIL_DUPLICATED("중복된 Email이 존재합니다"), + PASSWORD_EMPTY("비밀번호를 입력해주십시오"), + NAME_EMPTY("이름을 입력해주십시오"), + NICKNAME_EMPTY("닉네임을 입력해주십시오"); + + private String message; + + SignUpValidationCode(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/baekyangdan/scheduler/code/user/UserStatus.java b/src/main/java/com/baekyangdan/scheduler/code/user/UserStatus.java new file mode 100644 index 0000000..b8a2962 --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/code/user/UserStatus.java @@ -0,0 +1,21 @@ +package com.baekyangdan.scheduler.code.user; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum UserStatus { + ACTIVE("active"), + WAIT("wait"), + REST("rest"), + WITHDRAW("withdraw"); + + private final String value; + + UserStatus(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/com/baekyangdan/scheduler/config/DisableWebSecurityConfig.java b/src/main/java/com/baekyangdan/scheduler/config/DisableWebSecurityConfig.java new file mode 100644 index 0000000..420049d --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/config/DisableWebSecurityConfig.java @@ -0,0 +1,18 @@ +package com.baekyangdan.scheduler.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +public class DisableWebSecurityConfig { + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.csrf(csrf -> csrf.disable()) + .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()); + + return http.build(); + } +} diff --git a/src/main/java/com/baekyangdan/scheduler/config/SecurityConfig.java b/src/main/java/com/baekyangdan/scheduler/config/SecurityConfig.java new file mode 100644 index 0000000..1857307 --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/config/SecurityConfig.java @@ -0,0 +1,15 @@ +package com.baekyangdan.scheduler.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/baekyangdan/scheduler/config/SnakeCaseNameStrategy.java b/src/main/java/com/baekyangdan/scheduler/config/SnakeCaseNamingStrategy.java similarity index 92% rename from src/main/java/com/baekyangdan/scheduler/config/SnakeCaseNameStrategy.java rename to src/main/java/com/baekyangdan/scheduler/config/SnakeCaseNamingStrategy.java index 253c48e..3c8aae5 100644 --- a/src/main/java/com/baekyangdan/scheduler/config/SnakeCaseNameStrategy.java +++ b/src/main/java/com/baekyangdan/scheduler/config/SnakeCaseNamingStrategy.java @@ -1,15 +1,17 @@ -import org.hibernate.boot.model.naming.Identifier; -import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl; -import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; - -public class SnakeCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl { - - @Override - public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnv) { - String snakeCase = name.getText() - .replaceAll("([a-z])([A-Z])", "$1_$2") - .toLowerCase(); - - return Identifier.toIdentifier(snakeCase); - } +package com.baekyangdan.scheduler.config; + +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; + +public class SnakeCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl { + + @Override + public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnv) { + String snakeCase = name.getText() + .replaceAll("([a-z])([A-Z])", "$1_$2") + .toLowerCase(); + + return Identifier.toIdentifier(snakeCase); + } } \ No newline at end of file diff --git a/src/main/java/com/baekyangdan/scheduler/controller/user/UserController.java b/src/main/java/com/baekyangdan/scheduler/controller/user/UserController.java index febf7df..388e8c2 100644 --- a/src/main/java/com/baekyangdan/scheduler/controller/user/UserController.java +++ b/src/main/java/com/baekyangdan/scheduler/controller/user/UserController.java @@ -1,5 +1,23 @@ package com.baekyangdan.scheduler.controller.user; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +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; + +import com.baekyangdan.scheduler.request.user.UserRequest; + + +@RestController +@RequestMapping("/user") public class UserController { + @PostMapping("/signup") + public ResponseEntity signUp(@RequestBody UserRequest.SignUp body) { + System.out.println("test5"); + return new ResponseEntity("테스트", HttpStatus.OK); + } } diff --git a/src/main/java/com/baekyangdan/scheduler/entity/ExampleEntity.java b/src/main/java/com/baekyangdan/scheduler/entity/ExampleEntity.java deleted file mode 100644 index d4d313f..0000000 --- a/src/main/java/com/baekyangdan/scheduler/entity/ExampleEntity.java +++ /dev/null @@ -1,41 +0,0 @@ -import jakarta.persistence.*; -import lombok.*; -import org.hibernate.annotations.CreationTimestamp; -import org.hibernate.annotations.UpdateTimestamp; -import java.time.LocalDateTime; -import java.util.UUID; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -@Builder -@Entity -@Table( - name = "users", - indexes = @Index(name = "idx_users_email", columnList = "email") -) -public class User { - - @Id - @GeneratedValue - @org.hibernate.annotations.UuidGenerator - private UUID id; - - @Column(nullable = false, length = 50) - private String userName; - - @Column(nullable = false, unique = true, length = 100) - private String email; - - @Column(nullable = false) - private Boolean active; - - @Enumerated(EnumType.STRING) - private Role role; - - @CreationTimestamp - private LocalDateTime createdAt; - - @UpdateTimestamp - private LocalDateTime updatedAt; -} \ No newline at end of file diff --git a/src/main/java/com/baekyangdan/scheduler/entity/user/UserEntity.java b/src/main/java/com/baekyangdan/scheduler/entity/user/UserEntity.java new file mode 100644 index 0000000..6d5c2ed --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/entity/user/UserEntity.java @@ -0,0 +1,62 @@ +package com.baekyangdan.scheduler.entity.user; + +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.CreationTimestamp; + +import com.baekyangdan.scheduler.code.user.UserStatus; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +/** + * DB 상의 "USER" 테이블에 해당하는 Entity + */ +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder +@Entity +@Table( + name = "USER", + indexes = @Index(name = "user_pk", columnList = "id") +) +public class UserEntity { + + @Id + @Column(nullable = false) + private String id; + + @Column(nullable = false, length = 50) + private String name; + + @Column(nullable = false, length = 100) + private String email; + + @Column(nullable = false) + private Boolean isDeleted; + + @Column(nullable = false) + private String password; + + @Column + private String nickname; + + @Column + private LocalDateTime birthday; + + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "user_status") + private UserStatus status; + + @CreationTimestamp + @Column(updatable = false) + private LocalDateTime createdAt; + + /** + * 사용자가 참여중인 일정들의 id 목록을 가져오는 1대다 매핑 컬럼 + */ + // @OneToMany(mappedBy = "participant_id", cascade = CascadeType.ALL) + // private List participatedScheduleList; +} \ No newline at end of file diff --git a/src/main/java/com/baekyangdan/scheduler/repository/comment/CommentDao.java b/src/main/java/com/baekyangdan/scheduler/repository/comment/CommentDao.java deleted file mode 100644 index 74c1c05..0000000 --- a/src/main/java/com/baekyangdan/scheduler/repository/comment/CommentDao.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baekyangdan.scheduler.dao.comment; - -public class CommentDao { - -} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/comment/CommentRepository.java b/src/main/java/com/baekyangdan/scheduler/repository/comment/CommentRepository.java new file mode 100644 index 0000000..3bee36a --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/repository/comment/CommentRepository.java @@ -0,0 +1,5 @@ +package com.baekyangdan.scheduler.repository.comment; + +public class CommentRepository { + +} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/follow/FollowDao.java b/src/main/java/com/baekyangdan/scheduler/repository/follow/FollowDao.java deleted file mode 100644 index ed19ba6..0000000 --- a/src/main/java/com/baekyangdan/scheduler/repository/follow/FollowDao.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baekyangdan.scheduler.dao.follow; - -public class FollowDao { - -} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/follow/FollowRepository.java b/src/main/java/com/baekyangdan/scheduler/repository/follow/FollowRepository.java new file mode 100644 index 0000000..715334e --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/repository/follow/FollowRepository.java @@ -0,0 +1,5 @@ +package com.baekyangdan.scheduler.repository.follow; + +public class FollowRepository { + +} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/schedule/ScheduleDao.java b/src/main/java/com/baekyangdan/scheduler/repository/schedule/ScheduleDao.java deleted file mode 100644 index b7802f0..0000000 --- a/src/main/java/com/baekyangdan/scheduler/repository/schedule/ScheduleDao.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baekyangdan.scheduler.dao.schedule; - -public class ScheduleDao { - -} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/schedule/ScheduleRepository.java b/src/main/java/com/baekyangdan/scheduler/repository/schedule/ScheduleRepository.java new file mode 100644 index 0000000..ad46600 --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/repository/schedule/ScheduleRepository.java @@ -0,0 +1,5 @@ +package com.baekyangdan.scheduler.repository.schedule; + +public class ScheduleRepository { + +} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/user/UserDao.java b/src/main/java/com/baekyangdan/scheduler/repository/user/UserDao.java deleted file mode 100644 index 76b74f6..0000000 --- a/src/main/java/com/baekyangdan/scheduler/repository/user/UserDao.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baekyangdan.scheduler.dao.user; - -public class UserDao { - -} diff --git a/src/main/java/com/baekyangdan/scheduler/repository/user/UserRepository.java b/src/main/java/com/baekyangdan/scheduler/repository/user/UserRepository.java new file mode 100644 index 0000000..0f1ec3a --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/repository/user/UserRepository.java @@ -0,0 +1,15 @@ +package com.baekyangdan.scheduler.repository.user; + + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.baekyangdan.scheduler.entity.user.UserEntity; + +@Repository +public interface UserRepository extends JpaRepository { + Optional findByEmail(String email); + Optional findById(String id); +} diff --git a/src/main/java/com/baekyangdan/scheduler/request/user/UserRequest.java b/src/main/java/com/baekyangdan/scheduler/request/user/UserRequest.java new file mode 100644 index 0000000..85e8109 --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/request/user/UserRequest.java @@ -0,0 +1,85 @@ +package com.baekyangdan.scheduler.request.user; + +import java.time.LocalDateTime; + +import com.baekyangdan.scheduler.code.user.UserStatus; + +import lombok.Getter; +import lombok.Setter; + +/** + * 회원 관련 요청 데이터 클래스 + */ +public class UserRequest { + // 프로그램 실행 순서에 맞춰서 클래스 작성 + // 1. 회원 가입 + // 1-1. Id 중복 검사 요청 클래스 + @Getter + @Setter + public static class CheckIdDuplication { + private String id; + } + + // 1-2. 이메일 중복 검사 요청 클래스 + @Getter + @Setter + public static class CheckEmailDuplication { + private String email; + } + + // 1-3. 회원 가입 요청 클래스 + @Getter + @Setter + public static class SignUp { + private String id; + private String email; + private String name; + private String nickname; + private String password; + private String passwordResetCode; + } + + // 2. 로그인 + // 2-1. 비밀번호 초기화 요청 클래스 + @Getter + @Setter + public static class ResetPassword { + private String email; + private String passwordResetCode; + } + + // 2-2. 로그인 요청 클래스 + @Getter + @Setter + public static class Login { + // identifier: id or email + private String identifier; + private String password; + } + + // 3. 회원 정보 수정 요청 클래스 + @Getter + @Setter + public static class Update { + private String newId; + private String newName; + private String newEmail; + private String newPassword; + private LocalDateTime newBirthday; + private UserStatus newUserStatus; + } + + // 4. 회원 탈퇴 요청 클래스 + @Getter + @Setter + public static class Delete { + private String id; + } + + // 5. id로 회원 목록 검색 요청 클래스 + @Getter + @Setter + public static class FindById { + private String id; + } +} diff --git a/src/main/java/com/baekyangdan/scheduler/service/user/UserService.java b/src/main/java/com/baekyangdan/scheduler/service/user/UserService.java index 7c974fa..a32774a 100644 --- a/src/main/java/com/baekyangdan/scheduler/service/user/UserService.java +++ b/src/main/java/com/baekyangdan/scheduler/service/user/UserService.java @@ -1,5 +1,8 @@ package com.baekyangdan.scheduler.service.user; +import org.springframework.stereotype.Service; + +@Service public class UserService { } diff --git a/src/main/java/com/baekyangdan/scheduler/utils/validation/UserValidation.java b/src/main/java/com/baekyangdan/scheduler/utils/validation/UserValidation.java new file mode 100644 index 0000000..8b7fa4a --- /dev/null +++ b/src/main/java/com/baekyangdan/scheduler/utils/validation/UserValidation.java @@ -0,0 +1,33 @@ +package com.baekyangdan.scheduler.utils.validation; + +import org.springframework.security.access.method.P; + +import com.baekyangdan.scheduler.code.user.SignUpValidationCode; +import com.baekyangdan.scheduler.repository.user.UserRepository; +import com.baekyangdan.scheduler.request.user.UserRequest; + +public class UserValidation { + + public static boolean validateSignUpForm(UserRequest.SignUp data) throws Exception { + + if (validateStringEmpty(data.getId())) { + throw new Exception(SignUpValidationCode.ID_EMPTY.getMessage()); + } + if (data.getEmail() == null || data.getEmail().trim().isEmpty()) { + + } + return true; + } + + private static boolean validateStringEmpty(String value) { + if (value == null) { + return true; + } + + if (value.trim().isEmpty()) { + return true; + } + + return false; + } +} diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties new file mode 100644 index 0000000..daa76b4 --- /dev/null +++ b/src/main/resources/application-local.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:postgresql://192.168.219.107:5454/scheduler +spring.datasource.username=baekyangdan +spring.datasource.password=qwas745478! +spring.datasource.driver-class-name=org.postgresql.Driver +spring.devtools.restart.enabled=true +spring.devtools.livereload.enabled=true \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0807319..d17d74e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ spring.application.name=scheduler +spring.profiles.active=local \ No newline at end of file