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
4 changes: 0 additions & 4 deletions src/main/java/io/github/petty/community/Comments.java

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/java/io/github/petty/community/CommunityService.java

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/java/io/github/petty/community/PostLike.java

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/java/io/github/petty/community/PostViews.java

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/java/io/github/petty/community/Posts.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.github.petty.community.controller;

import io.github.petty.community.dto.CommentRequest;
import io.github.petty.community.dto.CommentResponse;
import io.github.petty.community.service.CommentService;
import io.github.petty.users.dto.CustomUserDetails;
import io.github.petty.users.entity.Users;
import io.github.petty.users.repository.UsersRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class CommentController {

private final CommentService commentService;
private final UsersRepository usersRepository;

@GetMapping("/api/posts/{postId}/comments")
public ResponseEntity<List<CommentResponse>> getComments(@PathVariable Long postId) {
return ResponseEntity.ok(commentService.getComments(postId));
}

@PostMapping("/api/posts/{postId}/comments")
public ResponseEntity<?> addComment(@PathVariable Long postId,
@RequestBody CommentRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
Long commentId = commentService.addComment(postId, request, user);
return ResponseEntity.ok().body(commentId);
}

@PutMapping("/api/comments/{commentId}")
public ResponseEntity<?> updateComment(@PathVariable Long commentId,
@RequestBody CommentRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
commentService.updateComment(commentId, request, user);
return ResponseEntity.ok().build();
}

@DeleteMapping("/api/comments/{commentId}")
public ResponseEntity<?> deleteComment(@PathVariable Long commentId,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
commentService.deleteComment(commentId, user);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.github.petty.community.controller;

import io.github.petty.community.dto.PostDetailResponse;
import io.github.petty.community.dto.PostRequest;
import io.github.petty.community.entity.Post;
import io.github.petty.community.service.PostService;
import io.github.petty.users.dto.CustomUserDetails;
import io.github.petty.users.entity.Users;
import io.github.petty.users.repository.UsersRepository;
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.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

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

private final PostService postService;
private final UsersRepository usersRepository;

@PostMapping
public ResponseEntity<?> create(@RequestBody PostRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
Long id = postService.save(request, user);
return ResponseEntity.ok(Map.of("id", id));
}

@PutMapping("/{id}")
public ResponseEntity<?> update(@PathVariable Long id,
@RequestBody PostRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
postService.update(id, request, user);
System.out.println("📥 요청 들어옴: " + request);
return ResponseEntity.ok().build();
}

@DeleteMapping("/{id}")
public ResponseEntity<?> delete(@PathVariable Long id,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
postService.delete(id, user);
return ResponseEntity.ok().build();
}

@GetMapping
public ResponseEntity<Page<?>> getAllByType(@RequestParam("type") Post.PostType type,
@PageableDefault(size = 9) Pageable pageable) {
Page<?> posts = postService.findAllByType(String.valueOf(type), pageable);
return ResponseEntity.ok(posts);
}

@GetMapping("/{id}")
public ResponseEntity<PostDetailResponse> getPost(@PathVariable Long id) {
PostDetailResponse post = postService.findById(id);
return ResponseEntity.ok(post);
}

@PostMapping("/{id}/like")
public ResponseEntity<?> likePost(@PathVariable Long id,
@AuthenticationPrincipal CustomUserDetails userDetails) {
String username = userDetails.getUsername();
Users user = usersRepository.findByUsername(username);
int newCount = postService.toggleLike(id, user); // 좋아요 또는 취소
return ResponseEntity.ok(Map.of("likeCount", newCount));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package io.github.petty.community.controller;

import io.github.petty.community.util.SupabaseUploader;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/images")
@RequiredArgsConstructor
@Slf4j
public class PostImageUploadController {

private final SupabaseUploader supabaseUploader;
private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
private static final List<String> ALLOWED_EXTENSIONS = List.of("jpg", "jpeg", "png", "gif");

// ✅ 단일 이미지 업로드
@PostMapping("/upload")
public ResponseEntity<?> uploadImage(
@RequestParam("file") MultipartFile file,
@AuthenticationPrincipal UserDetails userDetails) {

if (userDetails == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error", "로그인이 필요합니다"));
}

// 파일 유효성 검사
if (!isValidImage(file)) {
return ResponseEntity.badRequest().body(Map.of(
"error", "유효하지 않은 파일",
"message", "5MB 이하의 jpg, jpeg, png, gif 파일만 업로드 가능합니다"
));
}

try {
String imageUrl = supabaseUploader.upload(file);
return ResponseEntity.ok(Map.of("url", imageUrl));
} catch (IOException e) {
log.error("이미지 업로드 실패", e);
return ResponseEntity.internalServerError().body(Map.of("error", "업로드 실패", "message", e.getMessage()));
}
}

// ✅ 다중 이미지 업로드
@PostMapping("/upload/multi")
public ResponseEntity<?> uploadMultipleImages(
@RequestParam("files") List<MultipartFile> files,
@AuthenticationPrincipal UserDetails userDetails) {

if (userDetails == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error", "로그인이 필요합니다"));
}

// 파일 수 제한
if (files.size() > 5) {
return ResponseEntity.badRequest().body(Map.of(
"error", "이미지 제한 초과",
"message", "최대 5개의 이미지만 업로드 가능합니다"
));
}

// 모든 파일의 유효성 검사
for (MultipartFile file : files) {
if (!isValidImage(file)) {
return ResponseEntity.badRequest().body(Map.of(
"error", "유효하지 않은 파일",
"message", "5MB 이하의 jpg, jpeg, png, gif 파일만 업로드 가능합니다"
));
}
}

List<Map<String, Object>> imageResponses = new ArrayList<>();

try {
int order = 0;
for (MultipartFile file : files) {
String url = supabaseUploader.upload(file);

Map<String, Object> imageMap = new HashMap<>();
imageMap.put("imageUrl", url);
imageMap.put("ordering", order++);
imageMap.put("isDeleted", false);

imageResponses.add(imageMap);
}
return ResponseEntity.ok(Map.of("images", imageResponses));
} catch (IOException e) {
log.error("이미지 업로드 실패", e);
return ResponseEntity.internalServerError().body(Map.of("error", "이미지 업로드 실패", "message", e.getMessage()));
}
}

private boolean isValidImage(MultipartFile file) {
if (file.isEmpty() || file.getSize() > MAX_FILE_SIZE) {
return false;
}

String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
return false;
}

String extension = originalFilename.substring(originalFilename.lastIndexOf('.') + 1).toLowerCase();
return ALLOWED_EXTENSIONS.contains(extension);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.github.petty.community.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class PostViewController {

// 📌 후기 게시판
@GetMapping("/posts/review")
public String reviewListPage() {
return "post-review-list";
}

@GetMapping("/posts/review/new")
public String reviewFormPage() {
return "post-review-form";
}

@GetMapping("/posts/review/edit")
public String reviewEditPage() {
return "edit-review";
}

// 📌 자랑 게시판
@GetMapping("/posts/showoff")
public String showoffListPage() {
return "post-showoff-list";
}

@GetMapping("/posts/showoff/new")
public String showoffFormPage() {
return "post-showoff-form";
}

@GetMapping("/posts/showoff/edit")
public String showoffEditPage() {
return "edit-showoff";
}

// 📌 질문 게시판
@GetMapping("/posts/qna")
public String qnaListPage() {
return "post-qna-list";
}

@GetMapping("/posts/qna/new")
public String qnaFormPage() {
return "post-qna-form";
}

@GetMapping("/posts/qna/edit")
public String qnaEditPage() {
return "edit-qna";
}

// 📌 상세페이지 (공통)
@GetMapping("/posts/detail")
public String detailPage() {
return "post-detail";
}
}

10 changes: 10 additions & 0 deletions src/main/java/io/github/petty/community/dto/CommentRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.github.petty.community.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class CommentRequest {
private String content;
}
15 changes: 15 additions & 0 deletions src/main/java/io/github/petty/community/dto/CommentResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.github.petty.community.dto;

import lombok.Getter;
import lombok.Builder;

import java.time.LocalDateTime;

@Getter
@Builder
public class CommentResponse {
private Long id;
private String writer;
private String content;
private LocalDateTime createdAt;
}
Loading