Skip to content

Commit

Permalink
Merge pull request #21 from goormthon-Univ/develop
Browse files Browse the repository at this point in the history
[develop] main merge
  • Loading branch information
JoongHyun-Kim authored Mar 21, 2024
2 parents 6c9a4c4 + de74ca3 commit f5fd0fc
Show file tree
Hide file tree
Showing 30 changed files with 1,001 additions and 0 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/com/hatcher/haemo/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.hatcher.haemo.comment.domain;

import com.hatcher.haemo.common.BaseEntity;
import com.hatcher.haemo.recruitment.domain.Recruitment;
import com.hatcher.haemo.user.domain.User;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicInsert;

@Entity
@Getter
@DynamicInsert
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long commentIdx;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "recruitment")
private Recruitment recruitment;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "writer")
private User writer;

@Column(nullable = false)
private String content;

@Builder
public Comment(Recruitment recruitment, User writer, String content) {
this.recruitment = recruitment;
this.writer = writer;
this.content = content;
}

public void setRecruitment(Recruitment recruitment) {
this.recruitment = recruitment;
recruitment.getComments().add(this);
}

public void setWriter(User writer) {
this.writer = writer;
writer.getComments().add(this);
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/hatcher/haemo/common/BaseEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.hatcher.haemo.common;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDate;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

@Column(columnDefinition = "varchar(10) default 'active'")
@Setter
private String status;

@CreatedDate
@Column(updatable = false)
private LocalDate createdDate;

@LastModifiedDate
private LocalDate lastModifiedDate;
}
13 changes: 13 additions & 0 deletions src/main/java/com/hatcher/haemo/common/BaseException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.hatcher.haemo.common;

import com.hatcher.haemo.common.enums.BaseResponseStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
public class BaseException extends Exception {
private BaseResponseStatus status;
}
50 changes: 50 additions & 0 deletions src/main/java/com/hatcher/haemo/common/BaseResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.hatcher.haemo.common;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.hatcher.haemo.common.enums.BaseResponseStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;

import static com.hatcher.haemo.common.enums.BaseResponseStatus.SUCCESS;

@Getter
@AllArgsConstructor
@JsonPropertyOrder({"isSuccess", "code", "message", "result"})
public class BaseResponse<T> {

private final int code;

@JsonProperty("isSuccess")
private final Boolean isSuccess;
private final String message;

@JsonInclude(JsonInclude.Include.NON_NULL)
private T result;


public static <T> BaseResponse<T> success() {
return new BaseResponse<>(
SUCCESS.getCode(),
SUCCESS.isSuccess(),
SUCCESS.getMessage(),
null);
}

public static <T> BaseResponse<T> success(T result) {
return new BaseResponse<>(
SUCCESS.getCode(),
SUCCESS.isSuccess(),
SUCCESS.getMessage(),
result);
}

public static <T> BaseResponse<T> failure(BaseResponseStatus status) {
return new BaseResponse<>(
status.getCode(),
status.isSuccess(),
status.getMessage(),
null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.hatcher.haemo.common.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class AppConfig {

@Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.hatcher.haemo.common.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173") //TODO: 프론트 배포 후 추가
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.hatcher.haemo.common.configuration;

import com.hatcher.haemo.common.jwt.JwtAuthenticationFilter;
import com.hatcher.haemo.common.jwt.JwtExceptionFilter;
import com.hatcher.haemo.user.application.AuthService;
import com.hatcher.haemo.user.application.UserService;
import lombok.RequiredArgsConstructor;
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.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.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.List;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig {
private final UserService userService;
private final AuthService authService;
private final JwtExceptionFilter jwtExceptionFilter;

@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowedOrigins(List.of("http://localhost:5173", "http://localhost:5174")); //TODO: 수정 필요
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}

@Bean
protected SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests((authorizeRequests) -> authorizeRequests
.requestMatchers(
new AntPathRequestMatcher("/users/login"),
new AntPathRequestMatcher("/users/signup"),
new AntPathRequestMatcher("/users/nickname"),
new AntPathRequestMatcher("/users/loginId"),
//new AntPathRequestMatcher("/users/reissue-token"),
new AntPathRequestMatcher("/recruitments/**", "GET"),
new AntPathRequestMatcher("/home", "GET")).permitAll() //TODO: 필요 시 추가
.anyRequest().authenticated())
.addFilterBefore(new JwtAuthenticationFilter(authService, userService), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtExceptionFilter, JwtAuthenticationFilter.class)
.build();
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/hatcher/haemo/common/constants/Constant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.hatcher.haemo.common.constants;

public class Constant {
public static final String ACTIVE = "active";
public static final String INACTIVE = "inactive"; // 탈퇴
public static final String LOGOUT = "logout"; // 로그아웃

public static class Recruitment {
public static final String RECRUITING = "recruiting"; // 모집중
public static final String DONE = "done"; // 모집완료
public static final String CANCELLED = "cancelled"; // 모집취소
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.hatcher.haemo.common.constants;

public class RequestURI {
public final static String user = "/users";
public final static String recruitment = "/recruitments";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.hatcher.haemo.common.enums;

import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public enum BaseResponseStatus {

/**
* 1000: 요청 성공
*/
SUCCESS(true, HttpStatus.OK, "요청에 성공하였습니다."),


/**
* 2000: Request 오류
*/
// user(2000-2049)
WRONG_PASSWORD(false, HttpStatus.BAD_REQUEST, "잘못된 password 입니다."),
INVALID_ACCESS_TOKEN(false, HttpStatus.BAD_REQUEST, "잘못된 access token 입니다."),
NULL_ACCESS_TOKEN(false, HttpStatus.BAD_REQUEST, "access token을 입력해주세요."),
INVALID_JWT_SIGNATURE(false, HttpStatus.BAD_REQUEST, "유효하지 않은 JWT 시그니처입니다."),
EXPIRED_ACCESS_TOKEN(false, HttpStatus.BAD_REQUEST, "만료된 토큰입니다."),
EMPTY_JWT_CLAIM(false, HttpStatus.BAD_REQUEST, "JWT claims string이 비었습니다."),
UNSUPPORTED_JWT_TOKEN(false, HttpStatus.BAD_REQUEST, "지원하지 않는 JWT 토큰 형식입니다."),

ACCESS_DENIED(false, HttpStatus.FORBIDDEN, "접근 권한이 없습니다."),

LOGIN_ID_NOT_FOUND(false, HttpStatus.NOT_FOUND, "해당 loginId로 user를 찾을 수 없습니다."),
INVALID_USER_IDX(false, HttpStatus.NOT_FOUND, "해당 userIdx로 user를 찾을 수 없습니다."),

DUPLICATED_NICKNAME(false, HttpStatus.CONFLICT, "중복된 닉네임입니다."),
DUPLICATED_LOGIN_ID(false, HttpStatus.CONFLICT, "중복된 로그인 아이디입니다."),

// recruitment(2100-2199)
WRONG_RECRUIT_TYPE(false, HttpStatus.NOT_FOUND, "해당 Recruit type을 찾을 수 없습니다."),

// comment(2200-2299)


/**
* 3000: Response 오류
*/
// user(3000-3099)

// recruitment(3100-3199)

// comment(3200-3299)


/**
* 4000: DB, Server 오류
*/
INTERNAL_SERVER_ERROR(false, HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error");

private final boolean isSuccess;
private final HttpStatus httpStatus;
private final String message;

BaseResponseStatus(boolean isSuccess, HttpStatus status, String message) {
this.isSuccess = isSuccess;
this.httpStatus = status;
this.message = message;
}

public int getCode() {
return httpStatus.value();
}
}

27 changes: 27 additions & 0 deletions src/main/java/com/hatcher/haemo/common/enums/RecruitType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.hatcher.haemo.common.enums;

import com.hatcher.haemo.common.BaseException;

import java.util.Arrays;

import static com.hatcher.haemo.common.enums.BaseResponseStatus.WRONG_RECRUIT_TYPE;

public enum RecruitType {
RESTAURANT("맛집"),
CAFE("카페"),
MOVIE("영화"),
EXHIBITION("전시회"),
BOARD_GAME("보드게임"),
ESCAPE_GAME("방탈출"),
COIN_KARAOKE("코인노래방"),
DELIVERY_FOOD("배달음식");

RecruitType(String name) {}

public static RecruitType getEnumByName(String name) throws BaseException {
return Arrays.stream(RecruitType.values())
.filter(contents -> contents.name().equalsIgnoreCase(name))
.findFirst()
.orElseThrow(() -> new BaseException(WRONG_RECRUIT_TYPE));
}
}
Loading

0 comments on commit f5fd0fc

Please sign in to comment.