Skip to content

Commit

Permalink
Merge branch 'dev' into feature/swagger
Browse files Browse the repository at this point in the history
  • Loading branch information
wwingyou authored May 14, 2024
2 parents 60f0f00 + 2585ffb commit 418a45a
Show file tree
Hide file tree
Showing 37 changed files with 838 additions and 130 deletions.
14 changes: 13 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,25 @@ dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

annotationProcessor 'org.projectlombok:lombok'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

// jwt
// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.2'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2'

// gmail
implementation 'org.springframework.boot:spring-boot-starter-mail'

// thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'

// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import org.springframework.web.bind.annotation.*;

@RestController
//@RequestMapping("/api")
@RequestMapping("/admin")
@RequiredArgsConstructor
public class PostController {

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/kr/tgwing/tech/common/ApiResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package kr.tgwing.tech.common;

public record ApiResponse<T> (String message, T data){

public static <T> ApiResponse<T> ok() {
return new ApiResponse<>("ok", null);
}

public static <T> ApiResponse<T> ok(T result) {
return new ApiResponse<>("ok", result);
}

public static <T> ApiResponse<T> created(T result) {
return new ApiResponse<>("created", result);
}

public static <T> ApiResponse<T> updated(T result) {
return new ApiResponse<>("update", result);
}

public static <T> ApiResponse<T> delete(T result) {
return new ApiResponse<>("delete", result);
}
}
45 changes: 45 additions & 0 deletions src/main/java/kr/tgwing/tech/common/RedisConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package kr.tgwing.tech.common;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@EnableCaching
@Configuration
public class RedisConfig {

@Value("${spring.data.redis.host}")
private String host;

@Value("${spring.data.redis.port}")
private String port;

@Value("${spring.data.redis.password}")
private String password;

@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(Integer.parseInt(port));

LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration);
return lettuceConnectionFactory;
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}

}
11 changes: 11 additions & 0 deletions src/main/java/kr/tgwing/tech/common/exception/ExceptionMapper.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.tgwing.tech.common.exception;

import kr.tgwing.tech.user.exception.*;
import org.springframework.http.HttpStatus;

import java.util.LinkedHashMap;
Expand All @@ -16,6 +17,16 @@ public class ExceptionMapper { // 예외 객체 -> 예외 상태로 바꿔주는
}

private static void setUpUserException() {
mapper.put(UserNotFoundException.class,
ExceptionSituation.of("해당 사용자가 존재하지 않습니다.", HttpStatus.NOT_FOUND, 1000));
mapper.put(UserDuplicatedException.class,
ExceptionSituation.of("해당 사용자의 정보가 중복됩니다.", HttpStatus.CONFLICT, 1001));
mapper.put(PasswordException.class,
ExceptionSituation.of("비밀번호가 서로 일치하지 않습니다.", HttpStatus.BAD_REQUEST,1002));
mapper.put(MessageException.class,
ExceptionSituation.of("메일에서 에러가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR, 1003));
mapper.put(EmailCodeException.class,
ExceptionSituation.of("인증번호가 서로 인치하지 않습니다.", HttpStatus.CONFLICT, 1004));
}

private static void setUpPostException() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
public class ExceptionSituation {
private final String message;
private final HttpStatus statusCode;
private final int errorCode;
private final int errorCode; // 어느기능에서 에러가 났는지에 대한

public static ExceptionSituation of(String message, HttpStatus statusCode, int errorCode) {
return new ExceptionSituation(message, statusCode, errorCode);
Expand Down
72 changes: 72 additions & 0 deletions src/main/java/kr/tgwing/tech/reply/controller/ReplyController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package kr.tgwing.tech.reply.controller;

import jakarta.transaction.Transactional;
import kr.tgwing.tech.reply.dto.ReplyDto;
import kr.tgwing.tech.reply.service.ReplyService;
import kr.tgwing.tech.reply.service.ReplyServiceImpl;
import kr.tgwing.tech.security.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class ReplyController {

/*
* 특정 게시물 댓글 전부 가져오기 - GET, /tgwing.kr/info/notice/comment/{id}
* 게시물 댓글 달기 - POST, /tgwing.kr/notice/comment/post/{id}
* 자신이 작성한 댓글 삭제 - DELETE, /tgwing.kr/notice/comment/delete/{id}
* */

private final ReplyServiceImpl replyService;
private final JwtUtil jwtUtil;

@GetMapping("/info/notice/comment/{id}") // 특정 게시물 전체 댓글 가져오기
public ResponseEntity<List<ReplyDto>> getAllReplies(@PathVariable("id") Long postId) {
System.out.println("--- Get All Replies ---");

// post id 받고, 해당 post의 id를 reference로 가진 replies를 가져옴
List<ReplyDto> results = replyService.getAll(postId);
return ResponseEntity.ok(results);
}

@PostMapping("/notice/comment/post/{id}")
public ResponseEntity<ReplyDto> postReply(@PathVariable("id") Long postId,
@RequestBody ReplyDto reqDto) {
System.out.println("--- Post Reply ---");

ReplyDto result = replyService.post(reqDto, postId);
return ResponseEntity.ok(result);
}

@DeleteMapping("/notice/comment/delete/{id}")
public ResponseEntity deleteReply(@PathVariable("id") Long postId,
@RequestBody ReplyDto reqDto,
@RequestHeader("authorization") String token ) {
System.out.println("--- Delete Own Reply ---");

String jwt = token.split(" ")[1];
String tokenStudentId = jwtUtil.getStudentId(jwt);

return replyService.delete(postId, reqDto, tokenStudentId);
}

@GetMapping("/notice/comment/{id}")
@Transactional
public ResponseEntity<Page> getReplyInPage(@PathVariable("id") Long postId,
@RequestParam int page,
@RequestParam(required = false) int size,
@PageableDefault(size = 15) Pageable pageable) {
System.out.println("-- Get Replies in Page --");
// 첫 번째 페이지 page = 0이므로, page-1로 전달 -> 1부터 요청할 수 있도록
Page<ReplyDto> repliesInPage = replyService.findRepliesInPage(page-1, size, pageable, postId);

return ResponseEntity.ok(repliesInPage);
}
}
27 changes: 27 additions & 0 deletions src/main/java/kr/tgwing/tech/reply/dto/ReplyDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package kr.tgwing.tech.reply.dto;

import kr.tgwing.tech.reply.entity.ReplyEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
@Builder
public class ReplyDto {

private Long id;
private Long writer;
private String description;
private LocalDateTime modDate;

public static ReplyEntity toEntity(ReplyDto replyDto, Long postId) {
return ReplyEntity.builder()
.writer(replyDto.writer)
.description(replyDto.description)
.post(postId)
.build();
}
}
45 changes: 45 additions & 0 deletions src/main/java/kr/tgwing/tech/reply/entity/ReplyEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package kr.tgwing.tech.reply.entity;

import jakarta.persistence.*;
import kr.tgwing.tech.common.BaseEntity;
import kr.tgwing.tech.reply.dto.ReplyDto;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@Getter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "reply")
public class ReplyEntity extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@JoinColumn(referencedColumnName = "id", table = "user", nullable = false)
private Long writer;

@Column(nullable = false)
private String description;

@JoinColumn(referencedColumnName = "id", table = "post", nullable = false)
private Long post;

// @ManyToOne
// @JoinColumn(name = "post")
// private PostEntity post;

public static ReplyDto toDto(ReplyEntity replyEntity) {
return ReplyDto.builder()
.id(replyEntity.id)
.writer(replyEntity.writer)
.description(replyEntity.description)
.modDate(replyEntity.getModDate())
.build();
}

}
20 changes: 20 additions & 0 deletions src/main/java/kr/tgwing/tech/reply/repository/ReplyRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package kr.tgwing.tech.reply.repository;

import kr.tgwing.tech.reply.entity.ReplyEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ReplyRepository extends JpaRepository<ReplyEntity, Long> {
@Query(value = "select * from reply r where r.post = :postId", nativeQuery = true)
List<ReplyEntity> findAllByPost(Long postId);

void deleteById(Long id);

Page<ReplyEntity> findAllByPostOrderByModDateDesc(Pageable pageable, Long postId);
}
16 changes: 16 additions & 0 deletions src/main/java/kr/tgwing/tech/reply/service/ReplyService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kr.tgwing.tech.reply.service;

import kr.tgwing.tech.reply.dto.ReplyDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;

import java.util.List;

public interface ReplyService {

List<ReplyDto> getAll(Long postId);
ReplyDto post(ReplyDto reqDto, Long postId);
ResponseEntity delete(Long postId, ReplyDto reqDto, String token);
Page<ReplyDto> findRepliesInPage(int page, int size, Pageable pageable, Long postId);
}
Loading

0 comments on commit 418a45a

Please sign in to comment.