Skip to content

Commit

Permalink
Merge pull request #192 from RollingPaper42/dev
Browse files Browse the repository at this point in the history
feat: 토큰을 담은 쿠키 추가
  • Loading branch information
tjdwns5063 authored Feb 19, 2024
2 parents 088288c + af41088 commit aac4857
Show file tree
Hide file tree
Showing 15 changed files with 418 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.strcat.service.OAuthUserService;
import com.strcat.util.JwtUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand Down Expand Up @@ -35,8 +36,12 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
String provider = request.getRequestURI().split("/")[4];
User user = oAuthUserService.signIn(authentication.getName(), provider);
String token = jwtUtils.createJwtToken(user.getId().toString());
Cookie cookie = new Cookie("token", token);

log.info("token: " + token);
cookie.setMaxAge(60 * 60);
cookie.setDomain(".strcat.me");


response.sendRedirect(String.format("%s?token=%s", REDIRECT_URI, token));
}
Expand Down
13 changes: 6 additions & 7 deletions src/main/java/com/strcat/controller/BoardController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.strcat.controller;

import com.strcat.domain.Board;
import com.strcat.domain.User;
import com.strcat.dto.CreateBoardReqDto;
import com.strcat.dto.CreateContentReqDto;
Expand All @@ -10,7 +9,6 @@
import com.strcat.service.BoardService;
import com.strcat.service.ContentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -25,7 +23,6 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand Down Expand Up @@ -57,9 +54,10 @@ public class BoardController {
@ApiResponse(responseCode = "401", description = "인증 실패", content = {
@Content(examples = {@ExampleObject("인증 실패")})
})
public String createBoard(@Parameter(hidden = true) @RequestHeader("Authorization") String token,
public String createBoard(Authentication authentication,
@RequestBody CreateBoardReqDto dto) {
return boardService.createBoard(dto, token);
Long userId = (Long) authentication.getPrincipal();
return boardService.createBoard(dto, userId);
}

@PostMapping("/{boardId}/contents")
Expand All @@ -84,9 +82,10 @@ public String createPicture(@PathVariable(name = "boardId") String encryptedBoar
@GetMapping("/{boardId}")
@SecurityRequirement(name = "Bearer Authentication")
@Operation(summary = "보드 조회", description = "보드에 대한 모든 정보와 보드 소유자 여부를 반환합니다.")
public ReadBoardResDto readBoard(@Parameter(hidden = true) @RequestHeader("Authorization") String token,
public ReadBoardResDto readBoard(Authentication authentication,
@PathVariable(name = "boardId") String encryptedBoardId) {
return boardService.readBoard(encryptedBoardId, token);
Long userId = (Long) authentication.getPrincipal();
return boardService.readBoard(encryptedBoardId, userId);
}

@GetMapping("/{boardId}/summaries")
Expand Down
32 changes: 28 additions & 4 deletions src/main/java/com/strcat/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package com.strcat.controller;


import com.strcat.dto.HistoryDto;
import com.strcat.dto.ReadMyInfoResDto;
import com.strcat.service.BoardService;
import com.strcat.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
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;

Expand All @@ -34,12 +37,33 @@
@RequiredArgsConstructor
public class UserController {
private final BoardService boardService;
private final UserService userService;

@GetMapping("/boards")
@SecurityRequirement(name = "Bearer Authentication")
@Operation(summary = "내 보드 조회", description = "내가 생성한 보드 정보 리스트를 반환합니다.")
public List<ReadMyInfoResDto> readMyBoardInfo(
@Parameter(hidden = true) @RequestHeader("Authorization") String token) {
return boardService.readMyBoardInfo(token);
Authentication authentication) {
Long userId = (Long) authentication.getPrincipal();

return userService.readMyBoardInfo(userId);
}
@GetMapping("/history")
@SecurityRequirement(name = "Bearer Authentication")
@Operation(summary = "최근 방문한 보드 조회", description = "내가 최근에 방문한 보드 리스트를 반환합니다.")
public HistoryDto readMyBoardHistory(
Authentication authentication) {
Long userId = (Long) authentication.getPrincipal();
return userService.readMyBoardHistory(userId);
}

@PostMapping("/history")
@SecurityRequirement(name = "Bearer Authentication")
@Operation(summary = "최근 방문한 보드 저장", description = "내가 최근에 방문한 보드 리스트를 저장합니다.")
public HistoryDto postMyBoardHistory(
Authentication authentication, @RequestBody HistoryDto dto) {
Long userId = (Long) authentication.getPrincipal();

return userService.postMyBoardHistory(userId, dto);
}
}
5 changes: 4 additions & 1 deletion src/main/java/com/strcat/domain/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

@Entity
@Data
@ToString
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class Board {
Expand Down Expand Up @@ -55,6 +54,10 @@ public class Board {
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL)
private List<Content> contents = new ArrayList<>();

@JsonIgnore
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL)
private List<History> history;

public Board(String title, String theme, User user) {
this.title = title;
this.theme = theme;
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/com/strcat/domain/History.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.strcat.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.strcat.dto.HistoryDto;
import com.strcat.dto.HistoryItem;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.apache.commons.lang3.builder.HashCodeExclude;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@Entity
@Data
@ToString(exclude = {"user", "board"})
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class History {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;

@JsonIgnore
@ManyToOne
@JoinColumn(name = "board_id", nullable = false)
private Board board;

@Column(name = "visited_at", nullable = false)
private LocalDateTime visitedAt;


public History(User user, Board board, LocalDateTime visitedAt) {
this.user = user;
this.board = board;
this.visitedAt = visitedAt;
}

public HistoryItem toDto() {
return new HistoryItem(board.getEncryptedId(), board.getTitle(), visitedAt);
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/strcat/domain/User.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.strcat.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -9,6 +10,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -30,4 +32,8 @@ public class User {

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Board> boards;

@JsonIgnore
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<History> histories = new ArrayList<>();
}
6 changes: 6 additions & 0 deletions src/main/java/com/strcat/dto/HistoryDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.strcat.dto;

import java.util.List;

public record HistoryDto(List<HistoryItem> history) {
}
17 changes: 17 additions & 0 deletions src/main/java/com/strcat/dto/HistoryItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.strcat.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;

@Schema(example = """
{
"encryptedBoardId": "string",
"title": "string",
"visitTime": "2024-02-07 07:54:54"
}
""")
public record HistoryItem(String encryptedBoardId, String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
LocalDateTime visitTime) {
}
3 changes: 1 addition & 2 deletions src/main/java/com/strcat/repository/BoardRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@

@Repository
public interface BoardRepository extends JpaRepository<Board, Long> {
List<Board> findByUserId(Long userId);
Optional<Board> findFirstByOrderByCreatedAtDesc();
Optional<Board> findByEncryptedId(String encryptedId);
}
21 changes: 21 additions & 0 deletions src/main/java/com/strcat/repository/HistoryRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.strcat.repository;

import com.strcat.domain.History;
import com.strcat.domain.User;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

public interface HistoryRepository extends JpaRepository<History, Long> {
public List<History> findByUserIdOrderByVisitedAtAsc(Long userId);

@Modifying
@Query("DELETE FROM History h WHERE h.user = :user")
public void deleteHistoriesByUser(User user);

@Modifying
@Query("DELETE FROM History h WHERE h.id = :id")
public void deleteById(Long id);

}
49 changes: 17 additions & 32 deletions src/main/java/com/strcat/service/BoardService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
import com.strcat.domain.Board;
import com.strcat.domain.User;
import com.strcat.dto.CreateBoardReqDto;
import com.strcat.dto.HistoryItem;
import com.strcat.dto.ReadBoardResDto;
import com.strcat.dto.ReadBoardSummaryResDto;
import com.strcat.dto.ReadMyInfoResDto;
import com.strcat.exception.NotAcceptableException;
import com.strcat.repository.BoardRepository;
import com.strcat.util.JwtUtils;
import com.strcat.repository.UserRepository;
import com.strcat.usecase.RecordHistoryUseCase;
import com.strcat.util.SecureDataUtils;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

Expand All @@ -21,24 +21,12 @@
public class BoardService {
private final BoardRepository boardRepository;
private final SecureDataUtils secureDataUtils;
private final UserService userService;
private final JwtUtils jwtUtils;
private final UserRepository userRepository;
private final RecordHistoryUseCase recordHistoryUseCase;

public List<Board> findByUserId(Long userId) {
return boardRepository.findByUserId(userId);
}

public List<ReadMyInfoResDto> readMyBoardInfo(String token) {
User user = userService.getUser(token);
List<Board> boards = findByUserId(user.getId());
return boards.stream()
.map(Board::toReadMyInfoResDto)
.collect(Collectors.toList());
}

public String createBoard(CreateBoardReqDto dto, String token) {
public String createBoard(CreateBoardReqDto dto, Long userId) {
Board board;
User user = userService.getUser(token);
User user = userRepository.findById(userId).orElseThrow(() -> new NotAcceptableException("유저가 존재하지 않습니다."));
board = new Board(dto.getTitle(), dto.getTheme(), user);
board = boardRepository.save(board);

Expand All @@ -48,10 +36,13 @@ public String createBoard(CreateBoardReqDto dto, String token) {
return encryptedBoardId;
}

public ReadBoardResDto readBoard(String encryptedBoardId, String token) {
Board board = getBoard(encryptedBoardId);
public ReadBoardResDto readBoard(String encryptedBoardId, Long userId) {
Board board = boardRepository.findByEncryptedId(encryptedBoardId)
.orElseThrow(() -> new NotAcceptableException("존재하지 않는 보드입니다."));

try {
Long userId = jwtUtils.parseUserId(jwtUtils.removeBearerString(token));
recordHistoryUseCase.write(userId,
List.of(new HistoryItem(encryptedBoardId, board.getTitle(), LocalDateTime.now())));
Boolean isOwner = userId.equals(board.getUser().getId());
return board.toReadBoardResDto(isOwner);
} catch (NotAcceptableException e) {
Expand All @@ -60,16 +51,10 @@ public ReadBoardResDto readBoard(String encryptedBoardId, String token) {
}

public ReadBoardSummaryResDto readSummary(String encryptedBoardId) {
return getBoard(encryptedBoardId).toReadBoardSummaryDto();
return boardRepository.findByEncryptedId(encryptedBoardId)
.orElseThrow(() -> new NotAcceptableException("존재하지 않는 보드입니다."))
.toReadBoardSummaryDto();
}

public Board getBoard(String encryptedBoardId) {
Long boardId = secureDataUtils.decrypt(encryptedBoardId);
Optional<Board> optionalBoard = boardRepository.findById(boardId);

if (optionalBoard.isEmpty()) {
throw new NotAcceptableException("존재하지 않는 보드입니다.");
}
return optionalBoard.get();
}
}
Loading

0 comments on commit aac4857

Please sign in to comment.