Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/main/java/kr/warmlink/application/article/dto/ArticleDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package kr.warmlink.application.article.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import kr.warmlink.domain.auth.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.stream.Collectors;

public class ArticleDto {
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "ArticleDto.Request", description = "판매글 등록을 위한 DTO")
public static class Request {
@Schema(description = "게시글 제목", example = "초상화 그려드립니다.")
private String title;
@Schema(description = "게시글 내용", example = "1장에 8천원 이상, 택배비 별도 부담하셔야 합니다.")
private String content;
}

@Getter
@AllArgsConstructor
@Schema(name = "ArticleDto.Response", description = "판매글 등록에 대한 응답 DTO")
public static class Response {
@Schema(description = "응답 메시지", example = "게시글 등록에 성공하였습니다.")
private String message;

public static Response of(String message) {
return new Response(message);
}
}

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "ArticleDto.Overview", description = "게시글 목록 조회 응답 DTO")
public static class Overview {
@Schema(description = "게시글 id", example = "1")
private Long id;

@Schema(description = "게시글 제목", example = "초상화 그려드립니다.")
private String tile;

@Schema(description = "작성자 이름", example = "홍길동")
private String name;

public static List<Overview> from(User user) {
return user.getArticles().stream()
.filter(article -> article.isDeleted() == false)
.map(article -> Overview.builder()
.id(article.getId())
.tile(article.getTitle())
.name(user.getName())
.build())
.collect(Collectors.toUnmodifiableList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.servlet.http.HttpServletResponse;
import kr.warmlink.common.jwt.util.JwtProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
Expand All @@ -17,6 +18,7 @@
import java.util.Collections;

@Component
@Slf4j
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

Expand All @@ -27,7 +29,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
String token = jwtProvider.resolveToken(request);

if (token != null && jwtProvider.validateToken(token)) {
String email = jwtProvider.getEmail(token.split(" ")[1].trim());
String email = jwtProvider.getEmail(token);

Authentication authentication = new UsernamePasswordAuthenticationToken(
email, null, Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/kr/warmlink/common/jwt/util/JwtProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ public String generateRefreshToken(String email) {

public boolean validateToken(String token) {
try {
if (!token.startsWith(BEARER)) {
if (token == null) {
return false;
} else {
token = token.split(" ")[1].trim();
}
Jws<Claims> claims = Jwts.parserBuilder().setSigningKey(jwtProperties.getSecret().getBytes()).build().parseClaimsJws(token);
return !claims.getBody().getExpiration().before(new Date());
Expand All @@ -55,7 +53,11 @@ public boolean validateToken(String token) {
}

public String resolveToken(HttpServletRequest request) {
return request.getHeader(AUTH_HEADER);
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
return token.substring(7);
}
return null;
}

public String getEmail(String token) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kr.warmlink.domain.article.repository;

import kr.warmlink.domain.article.entity.Article;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ArticleRepository extends JpaRepository<Article, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package kr.warmlink.domain.article.service;

import jakarta.servlet.http.HttpServletRequest;
import kr.warmlink.application.article.dto.ArticleDto;
import kr.warmlink.common.jwt.util.JwtProvider;
import kr.warmlink.domain.article.entity.Article;
import kr.warmlink.domain.article.repository.ArticleRepository;
import kr.warmlink.domain.auth.entity.User;
import kr.warmlink.domain.auth.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class ArticleService {
private final JwtProvider jwtProvider;
private final UserService userService;
private final ArticleRepository articleRepository;

@Transactional
public ArticleDto.Response create(HttpServletRequest request, ArticleDto.Request dto) {
String accessToken = jwtProvider.resolveToken(request);
String email = jwtProvider.getEmail(accessToken);

User user = userService.read(email);
Article article = Article.builder()
.title(dto.getTitle())
.content(dto.getContent())
.user(user)
.build();

articleRepository.save(article);

String message = "게시글 등록이 완료되었습니다.";
return ArticleDto.Response.of(message);
}

@Transactional
public List<ArticleDto.Overview> read(HttpServletRequest request) {
String accessToken = jwtProvider.resolveToken(request);
String email = jwtProvider.getEmail(accessToken);

User user = userService.read(email);
return ArticleDto.Overview.from(user);
}

@Transactional
public Article read(Long id) {
return articleRepository.findById(id).orElse(null);
}

@Transactional
public ArticleDto.Response update(HttpServletRequest request, Long id, ArticleDto.Request dto) {
String accessToken = jwtProvider.resolveToken(request);
String email = jwtProvider.getEmail(accessToken);
Article article = read(id);

article.changeTitle(dto.getTitle());
article.changeContent(dto.getContent());

articleRepository.save(article);

String message = "게시글 수정을 완료했습니다.";
return ArticleDto.Response.of(message);
}

@Transactional
public ArticleDto.Response delete(HttpServletRequest request, Long id) {
String accessToken = jwtProvider.resolveToken(request);
String email = jwtProvider.getEmail(accessToken);

Article article = read(id);
article.delete();

articleRepository.save(article);

String message = "게시글이 정상적으로 삭제되었습니다.";
return ArticleDto.Response.of(message);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ public String register(SignInDto.Register dto) {
return message;
}

@Transactional
public User read(String email) {
return userRepository.findByEmail(email).orElse(null);
}

}
43 changes: 43 additions & 0 deletions src/main/java/kr/warmlink/presentation/api/ArticleApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package kr.warmlink.presentation.api;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import kr.warmlink.application.article.dto.ArticleDto;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

@Tag(name = "[판매글 관련 API]", description = "사용자 판매글 관련 API")
public interface ArticleApi {
@Operation(summary = "판매글 등록", description = "판매글 등록을 위한 API입니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "판매글 등록 성공"),
@ApiResponse(responseCode = "400", description = "판매글 등록 실패")
})
ResponseEntity<?> create(HttpServletRequest request, @RequestBody ArticleDto.Request dto);

@Operation(summary = "판매글 목록 조회", description = "특정 사용자가 등록한 모든 판매글을 조회하기 위한 API입니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "판매글 목록 조회 성공"),
@ApiResponse(responseCode = "400", description = "판매글 목록 조회 실패")
})
ResponseEntity<?> overview(HttpServletRequest request);

@Operation(summary = "판매글 수정", description = "사용자의 판매 게시글을 수정하기 위한 API")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "판매글 수정 성공"),
@ApiResponse(responseCode = "400", description = "판매글 수정 실패")
})
ResponseEntity<?> update(HttpServletRequest request, @PathVariable Long id, @RequestBody ArticleDto.Request dto);

@Operation(summary = "판매글 삭제", description = "사용자의 판매 게시글을 삭제하기 위한 API")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "판매글 수정 성공"),
@ApiResponse(responseCode = "400", description = "판매글 수정 실패")
})
ResponseEntity<?> delete(HttpServletRequest request, @PathVariable Long id);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package kr.warmlink.presentation.controller;

import jakarta.servlet.http.HttpServletRequest;
import kr.warmlink.application.article.dto.ArticleDto;
import kr.warmlink.domain.article.service.ArticleService;
import kr.warmlink.presentation.api.ArticleApi;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/articles")
@RequiredArgsConstructor
public class ArticleController implements ArticleApi {

private final ArticleService articleService;

@Override
@PostMapping("")
public ResponseEntity<?> create(HttpServletRequest request, ArticleDto.Request dto) {
return ResponseEntity.ok(articleService.create(request, dto));
}

@Override
@GetMapping("")
public ResponseEntity<?> overview(HttpServletRequest request) {
return ResponseEntity.ok(articleService.read(request));
}

@Override
@PatchMapping("/{id}")
public ResponseEntity<?> update(HttpServletRequest request, Long id, ArticleDto.Request dto) {
return ResponseEntity.ok(articleService.update(request, id, dto));
}

@Override
@PatchMapping("/{id}/delete")
public ResponseEntity<?> delete(HttpServletRequest request, Long id) {
return ResponseEntity.ok(articleService.delete(request, id));
}

}
Loading