Skip to content

Commit

Permalink
Merge pull request #163 from prgrms-web-devcourse-final-project/develop
Browse files Browse the repository at this point in the history
[merge] develop to main
  • Loading branch information
DongWooKim4343 authored Dec 4, 2024
2 parents 7e939cb + 720374e commit 5e561f7
Show file tree
Hide file tree
Showing 60 changed files with 1,841 additions and 679 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/CICD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- main


jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -20,6 +21,9 @@ jobs:
# application.yml 파일 생성
- run: touch ./src/main/resources/application.properties
- run: echo "${{secrets.APPLICATION}}" > ./src/main/resources/application.properties
- run: echo "spring.cloud.aws.credentials.access-key=${{secrets.AWS_ACTION_ACCESS_KEY}}" >> ./src/main/resources/application.properties
- run: echo "spring.cloud.aws.credentials.secret-key=${{secrets.AWS_ACTION_SECRET_ACCESS_KEY}}" >> ./src/main/resources/application.properties


# 생성된 파일들을 아티팩트로 업로드
- uses: actions/upload-artifact@v3
Expand Down
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ dependencies {

implementation 'mysql:mysql-connector-java:8.0.33'

//Spring Cloud AWS, S3
implementation 'io.awspring.cloud:spring-cloud-aws-starter:3.1.1'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.777'


}
jar {
enabled = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import com.mallangs.domain.article.dto.request.MapBoundsRequest;
import com.mallangs.domain.article.dto.response.ArticleResponse;
import com.mallangs.domain.article.dto.response.MapBoundsResponse;
import com.mallangs.domain.article.entity.CaseStatus;
import com.mallangs.domain.article.service.ArticleService;
import com.mallangs.domain.article.service.LocationService;
import com.mallangs.domain.article.validation.ValidationGroups;
import com.mallangs.global.jwt.entity.CustomMemberDetails;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -17,6 +19,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
Expand All @@ -41,7 +44,7 @@ public class ArticleController {
@PreAuthorize("hasAuthority('ROLE_USER') or hasAuthority('ROLE_ADMIN')")
@PostMapping
public ResponseEntity<ArticleResponse> createArticle(
@RequestBody ArticleCreateRequest articleCreateRequest,
@Validated(ValidationGroups.CreateGroup.class) @RequestBody ArticleCreateRequest articleCreateRequest,
@Parameter(description = "현재 인증된 사용자 정보", required = true)
@AuthenticationPrincipal CustomMemberDetails principal) {
Long memberId = principal.getMemberId();
Expand All @@ -53,16 +56,26 @@ public ResponseEntity<ArticleResponse> createArticle(


// 조회
// 관리자 전부 조회 가능
// 회원 visible + 자신의 글 조회 가능
// 비회원 mapVisible 만 조회 가능
@Operation(summary = "글타래 단건 조회", description = "글타래를 단건 조회합니다.")
@GetMapping("/public/{articleId}")
public ResponseEntity<ArticleResponse> getArticleByArticleId(
@Parameter(description = "조회할 글타래 ID", required = true) @PathVariable Long articleId) {
ArticleResponse articleResponse = articleService.getArticleById(articleId);
@Parameter(description = "조회할 글타래 ID", required = true) @PathVariable Long articleId,
@AuthenticationPrincipal CustomMemberDetails principal) {

String userRole = principal.getRole();
Long memberId = principal.getMemberId();

ArticleResponse articleResponse = articleService.getArticleById(articleId, userRole, memberId);

return ResponseEntity.ok(articleResponse);
}

// 관리자 페이지
// articleType : lost rescue place user
// placeCategory : place 하위
@Operation(summary = "관리자 글타래 전체 조회", description = "관리자가 글타래를 조회합니다.")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@GetMapping("/admin")
Expand All @@ -79,16 +92,30 @@ public ResponseEntity<Page<ArticleResponse>> getArticles(
if (placeCategory == null || placeCategory.isEmpty()) {
articles = articleService.findArticlesByArticleType(pageable, articleType);
} else {
articles = articleService.findPlaceArticlesByCategory(pageable, placeCategory);
articles = articleService.findPlaceArticlesByCategory(pageable, articleType, placeCategory);
}

}

return ResponseEntity.ok(articles);
}

// 실종 페이지
// map visible 만 보임
@Operation(summary = "실종 글타래 전체 조회", description = "실종 글타래를 조회합니다.")
@GetMapping("/public/lost")
public ResponseEntity<Page<ArticleResponse>> getLostArticles(
@Parameter(description = "페이징 요청 정보", required = true) Pageable pageable,
@RequestParam(value = "lostStatus", required = false) CaseStatus lostStatus) {

Page<ArticleResponse> articles = articleService.findLostArticles(pageable, lostStatus);

return ResponseEntity.ok(articles);
}


// 지도에 마커 표시 위한 경로
// 위치 기준 지도 전체 글타래 조회 // 타입별 조회
// map visible 만 보임
@Operation(summary = "지도에서 글타래 조회", description = "지도에서 글타래를 조회합니다.")
@PostMapping("/public/articlesMarkers")
public ResponseEntity<List<MapBoundsResponse>> getMarkersInBounds(
Expand Down Expand Up @@ -117,7 +144,7 @@ public ResponseEntity<List<MapBoundsResponse>> getMarkersInBounds(
articlesInBounds = locationService.findArticlesInBoundsByType(
southWestLat, southWestLon,
northEastLat, northEastLon, articleType); // 실종 목격 구조 장소 사용자등록장소
} else { // 시설 업체, 사용자 등록 장소 소분류 존재
} else { // 시설 업체, 사용자 등록 => 장소 소분류 존재
articlesInBounds = locationService.findPlaceArticlesInBoundsByCategory(
southWestLat, southWestLon,
northEastLat, northEastLon, articleType, placeCategory);
Expand All @@ -128,6 +155,7 @@ public ResponseEntity<List<MapBoundsResponse>> getMarkersInBounds(
}

// 검색 조회
// map visible 만 보임
@Operation(summary = "글타래 검색", description = "글타래에서 검색합니다.")
@GetMapping("/public/search")
public ResponseEntity<Page<ArticleResponse>> searchSightingPosts(
Expand All @@ -140,6 +168,7 @@ public ResponseEntity<Page<ArticleResponse>> searchSightingPosts(


// 회원 자신이 작성한 글타래 목록 조회
// is deleted false 안 보임
@Operation(summary = "사용자가 작성한 전체 글타래 조회", description = "사용자가 자신이 작성한 글타래 목록을 조회합니다.")
@PreAuthorize("hasAuthority('ROLE_USER')")
@GetMapping("/myArticles")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.mallangs.domain.article.entity.ArticleType;
import com.mallangs.domain.article.validation.ValidationGroups;
import com.mallangs.domain.board.entity.BoardStatus;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMax;
Expand Down Expand Up @@ -33,22 +34,22 @@
})
public class ArticleCreateRequest {

@NotBlank(message = "글 타입은 필수입니다.")
@NotBlank(message = "글 타입은 필수입니다.", groups = ValidationGroups.CreateGroup.class)
@JsonProperty("type")
private ArticleType articleType; // 글타래 종류

@NotBlank(message = "글 상태는 필수입니다.")
@NotBlank(message = "글 상태는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private BoardStatus articleStatus;

@NotBlank(message = "제목은 필수입니다.")
@NotBlank(message = "제목은 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private String title; // 장소인 경우 장소이름

@NotNull(message = "위도는 필수입니다.")
@NotNull(message = "위도는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
@DecimalMin(value = "-90.0", message = "위도는 -90.0 이상이어야 합니다.")
@DecimalMax(value = "90.0", message = "위도는 90.0 이하이어야 합니다.")
private Double latitude;

@NotNull(message = "경도는 필수입니다.")
@NotNull(message = "경도는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
@DecimalMin(value = "-180.0", message = "경도는 -180.0 이상이어야 합니다.")
@DecimalMax(value = "180.0", message = "경도는 180.0 이하이어야 합니다.")
private Double longitude;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mallangs.domain.article.dto.request;

import com.mallangs.domain.article.entity.CaseStatus;
import com.mallangs.domain.article.validation.ValidationGroups;
import com.mallangs.domain.pet.entity.PetGender;
import com.mallangs.domain.pet.entity.PetType;
import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -18,7 +19,7 @@
@Schema(description = "자식 클래스 DTO", allOf = ArticleCreateRequest.class)
public class LostCreateRequest extends ArticleCreateRequest {

@NotBlank(message = "동물 타입은 필수입니다.")
@NotBlank(message = "동물 타입은 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private PetType petType;

private String breed;
Expand All @@ -37,12 +38,12 @@ public class LostCreateRequest extends ArticleCreateRequest {

private LocalDateTime lostDate;

@NotBlank(message = "실종 장소는 필수입니다.")
@NotBlank(message = "실종 장소는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private String lostLocation;

private String contact;

@NotBlank(message = "실종 상태는 필수입니다.")
@NotBlank(message = "실종 상태는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private CaseStatus lostStatus;


Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.mallangs.domain.article.dto.request;

import com.mallangs.domain.article.validation.ValidationGroups;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
Expand Down Expand Up @@ -32,8 +34,9 @@ public class PlaceCreateRequest extends ArticleCreateRequest {

private String contact;

@NotNull
private Boolean isPublicData;
@NotNull(message = "공공데이터 여부는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
@Builder.Default
private Boolean isPublicData = false;


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mallangs.domain.article.dto.request;

import com.mallangs.domain.article.entity.CaseStatus;
import com.mallangs.domain.article.validation.ValidationGroups;
import com.mallangs.domain.pet.entity.PetType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
Expand All @@ -18,13 +19,13 @@
@Schema(description = "자식 클래스 DTO", allOf = ArticleCreateRequest.class)
public class RescueCreateRequest extends ArticleCreateRequest {

@NotNull(message = "동물 타입은 필수입니다.")
@NotNull(message = "동물 타입은 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private PetType petType;

@NotNull(message = "구조 상태는 필수입니다.")
@NotNull(message = "구조 상태는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private CaseStatus rescueStatus;

@NotBlank(message = "발견 장소는 필수입니다.")
@NotBlank(message = "발견 장소는 필수입니다.", groups = ValidationGroups.CreateGroup.class)
private String rescueLocation; // 발견 장소

private LocalDateTime rescueDate; // 발견 일시
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.mallangs.domain.article.entity.Article;
import com.mallangs.domain.article.entity.ArticleType;
import com.mallangs.domain.article.entity.CaseStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -12,29 +13,36 @@
@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {

// 실종 게시판 별도 확인
// 관리자
// 글타래 타입 별 조회
@Query("SELECT a FROM Article a WHERE a.articleType = :articleType")
Page<Article> findByArticleType(Pageable pageable, ArticleType articleType);

// 다양한 타입 설정 -> 관리자
// 모든 사용자
// 실종 게시판 별도 확인
// article 에서 map visible
@Query("SELECT l FROM LostArticle l JOIN Article a ON l.id = a.id WHERE l.lostStatus = :lostStatus AND a.mapVisibility = 'VISIBLE'")
Page<Article> findLostArticles(Pageable pageable, CaseStatus lostStatus);

// 관리자 목록 조회
// 다양한 타입 설정
// 장소 중에 소분류
@Query("SELECT p FROM PlaceArticle p WHERE p.category = :placeCategory")
Page<Article> findPlaceArticlesByCategory(Pageable pageable, String placeCategory);
@Query("SELECT p FROM PlaceArticle p WHERE p.isPublicData = :isPublicData AND p.category = :placeCategory")
Page<Article> findPlaceArticlesByCategory(Pageable pageable, boolean isPublicData,
String placeCategory);

// 멤버 개인 글타래 목록 조회
@Query("SELECT a FROM Article a WHERE a.member.memberId = :memberId")
// 논리 삭제 된 것 제외
@Query("SELECT a FROM Article a WHERE a.member.memberId = :memberId AND a.isDeleted = false")
Page<Article> findByMemberId(Pageable pageable, Long memberId);

// 모든 사용자
// 검색
@Query("SELECT a FROM Article a WHERE (a.title LIKE %:title% OR a.description LIKE %:description%) AND a.mapVisibility = 'VISIBLE'")
Page<Article> findByTitleContainingOrDescriptionContainingAndMapVisibility(
@Param("title") String title,
@Param("description") String description,
Pageable pageable);

// Page<Article> findByTitleContainingOrDescriptionContaining(
// String title, String description, Pageable pageable);


}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,39 @@ public List<MapBoundsResponse> findArticlesInBoundsByType(double southWestLat,
);
}

@Override
public List<MapBoundsResponse> findPlaceArticlesInBoundsByType(double southWestLat,
double southWestLon, double northEastLat, double northEastLon, boolean isPublicData) {

String query = String.format(
"SELECT a.article_id, a.type, a.title, ST_X(a.geography) AS latitude, " +
"ST_Y(a.geography) AS longitude, a.description " +
"FROM place p "
+ "JOIN article a ON p.article_id = a.article_id" +
"WHERE MBRContains(ST_GeomFromText('POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))', 4326), a.geography) "
+ "AND p.is_public_data = %b",
southWestLat, southWestLon,
southWestLat, northEastLon,
northEastLat, northEastLon,
northEastLat, southWestLon,
southWestLat, southWestLon,
isPublicData);

log.info(query);

return jdbcTemplate.query(query, (rs, rowNum) ->
new MapBoundsResponse(
rs.getLong("article_id"),
rs.getString("type"),
rs.getString("title"),
rs.getDouble("latitude"), // geography의 x 값
rs.getDouble("longitude"), // geography의 y 값
rs.getString("description")
)
);
}


@Override
public List<MapBoundsResponse> findPlaceArticlesInBoundsByCategory(double southWestLat,
double southWestLon, double northEastLat, double northEastLon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ List<MapBoundsResponse> findArticlesInBounds(double southWestLat, double southWe
List<MapBoundsResponse> findArticlesInBoundsByType(double southWestLat, double southWestLon,
double northEastLat, double northEastLon, String type);

List<MapBoundsResponse> findPlaceArticlesInBoundsByType(double southWestLat,
double southWestLon, double northEastLat, double northEastLon, boolean isPublicData);

List<MapBoundsResponse> findPlaceArticlesInBoundsByCategory(double southWestLat,
double southWestLon,
double northEastLat, double northEastLon, String placeCategory, boolean isPublicData);
Expand Down
Loading

0 comments on commit 5e561f7

Please sign in to comment.