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: 3 additions & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@ jobs:
V_DISCORD_WEBHOOK_5XX_URL: ${{ secrets.DISCORD_WEBHOOK_5XX_URL }}
V_DISCORD_WEBHOOK_4XX_URL: ${{ secrets.DISCORD_WEBHOOK_4XX_URL }}
V_DISCORD_WEBHOOK_INQUIRY_URL: ${{ secrets.DISCORD_WEBHOOK_INQUIRY_URL }}
V_DISCORD_WEBHOOK_REPORT_URL: ${{ secrets.DISCORD_WEBHOOK_REPORT_URL }}
V_MAIL_USERNAME: ${{ secrets.MAIL_USERNAME }}
V_MAIL_PASSWORD: ${{ secrets.MAIL_PASSWORD }}
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 2222
envs: V_GHCR_TOKEN,V_GHCR_USER,V_DB_URL,V_DB_USERNAME,V_DB_PASSWORD,V_JWT_SECRET,V_GOOGLE_CLIENT_ID,V_GOOGLE_CLIENT_SECRET,V_KAKAO_CLIENT_ID,V_KAKAO_CLIENT_SECRET,V_CORS_ALLOWED_ORIGINS,V_OAUTH2_REDIRECT_BASE_URI,V_GOOGLE_REDIRECT_URI,V_KAKAO_REDIRECT_URI,V_DATA_PIPELINE_SECRET,V_DATA_PIPELINE_BASE_URL,V_REDIS_PASSWORD,V_DISCORD_WEBHOOK_5XX_URL,V_DISCORD_WEBHOOK_4XX_URL,V_DISCORD_WEBHOOK_INQUIRY_URL,V_MAIL_USERNAME,V_MAIL_PASSWORD
envs: V_GHCR_TOKEN,V_GHCR_USER,V_DB_URL,V_DB_USERNAME,V_DB_PASSWORD,V_JWT_SECRET,V_GOOGLE_CLIENT_ID,V_GOOGLE_CLIENT_SECRET,V_KAKAO_CLIENT_ID,V_KAKAO_CLIENT_SECRET,V_CORS_ALLOWED_ORIGINS,V_OAUTH2_REDIRECT_BASE_URI,V_GOOGLE_REDIRECT_URI,V_KAKAO_REDIRECT_URI,V_DATA_PIPELINE_SECRET,V_DATA_PIPELINE_BASE_URL,V_REDIS_PASSWORD,V_DISCORD_WEBHOOK_5XX_URL,V_DISCORD_WEBHOOK_4XX_URL,V_DISCORD_WEBHOOK_INQUIRY_URL,V_DISCORD_WEBHOOK_REPORT_URL,V_MAIL_USERNAME,V_MAIL_PASSWORD
script: |
echo "$V_GHCR_TOKEN" | docker login ghcr.io -u "$V_GHCR_USER" --password-stdin

Expand All @@ -100,6 +101,7 @@ jobs:
printf 'DISCORD_WEBHOOK_5XX_URL=%s\n' "$V_DISCORD_WEBHOOK_5XX_URL" >> ~/compose/be.env
printf 'DISCORD_WEBHOOK_4XX_URL=%s\n' "$V_DISCORD_WEBHOOK_4XX_URL" >> ~/compose/be.env
printf 'DISCORD_WEBHOOK_INQUIRY_URL=%s\n' "$V_DISCORD_WEBHOOK_INQUIRY_URL" >> ~/compose/be.env
printf 'DISCORD_WEBHOOK_REPORT_URL=%s\n' "$V_DISCORD_WEBHOOK_REPORT_URL" >> ~/compose/be.env
printf 'MAIL_USERNAME=%s\n' "$V_MAIL_USERNAME" >> ~/compose/be.env
printf 'MAIL_PASSWORD=%s\n' "$V_MAIL_PASSWORD" >> ~/compose/be.env

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,21 @@
import com.Coming.Backend.admin.dto.AdminInquiryDetailResponse;
import com.Coming.Backend.admin.dto.AdminInquiryListItemResponse;
import com.Coming.Backend.admin.dto.AdminInquiryStatusUpdateRequest;
import com.Coming.Backend.admin.dto.AdminNoticeCreateRequest;
import com.Coming.Backend.admin.dto.AdminNoticeCreateResponse;
import com.Coming.Backend.admin.dto.AdminNoticeDetailResponse;
import com.Coming.Backend.admin.dto.AdminNoticeListItemResponse;
import com.Coming.Backend.admin.dto.AdminNoticeUpdateRequest;
import com.Coming.Backend.admin.dto.AdminPendingConcertResponse;
import com.Coming.Backend.admin.dto.AdminReportDetailResponse;
import com.Coming.Backend.admin.dto.AdminReportListItemResponse;
import com.Coming.Backend.admin.dto.AdminReportStatusUpdateRequest;
import com.Coming.Backend.admin.service.AdminService;
import com.Coming.Backend.common.response.PageResponse;
import com.Coming.Backend.inquiry.entity.InquiryStatus;
import com.Coming.Backend.inquiry.entity.InquiryType;
import com.Coming.Backend.report.entity.ReportStatus;
import com.Coming.Backend.report.entity.ReportTargetType;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand All @@ -35,6 +45,7 @@
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -106,6 +117,72 @@ public ResponseEntity<Void> updateInquiryStatus(
return ResponseEntity.ok().build();
}

@Operation(summary = "전체 공지사항 목록 조회")
@GetMapping("/notices")
public ResponseEntity<PageResponse<AdminNoticeListItemResponse>> getNotices(
@PageableDefault(size = 20) Pageable pageable) {
return ResponseEntity.ok(adminService.getNotices(pageable));
}

@Operation(summary = "공지사항 상세 조회 (비활성 포함)")
@ApiResponse(responseCode = "404", description = "NOTICE_NOT_FOUND")
@GetMapping("/notices/{id}")
public ResponseEntity<AdminNoticeDetailResponse> getAdminNotice(@PathVariable Long id) {
return ResponseEntity.ok(adminService.getAdminNotice(id));
}

@Operation(summary = "공지사항 작성")
@PostMapping("/notices")
public ResponseEntity<AdminNoticeCreateResponse> createNotice(
@AuthenticationPrincipal Long adminId,
@RequestBody @Valid AdminNoticeCreateRequest request) {
return ResponseEntity.status(HttpStatus.CREATED).body(adminService.createNotice(adminId, request));
}

@Operation(summary = "공지사항 수정")
@ApiResponse(responseCode = "404", description = "NOTICE_NOT_FOUND")
@PatchMapping("/notices/{id}")
public ResponseEntity<Void> updateNotice(
@PathVariable Long id,
@RequestBody @Valid AdminNoticeUpdateRequest request) {
adminService.updateNotice(id, request);
return ResponseEntity.ok().build();
}

@Operation(summary = "공지사항 삭제")
@ApiResponse(responseCode = "404", description = "NOTICE_NOT_FOUND")
@DeleteMapping("/notices/{id}")
public ResponseEntity<Void> deleteNotice(@PathVariable Long id) {
adminService.deleteNotice(id);
return ResponseEntity.noContent().build();
}

@Operation(summary = "전체 신고 목록 조회")
@GetMapping("/reports")
public ResponseEntity<PageResponse<AdminReportListItemResponse>> getReports(
@RequestParam(required = false) ReportTargetType targetType,
@RequestParam(required = false) ReportStatus status,
@PageableDefault(size = 20) Pageable pageable) {
return ResponseEntity.ok(adminService.getReports(targetType, status, pageable));
}

@Operation(summary = "신고 상세 조회")
@ApiResponse(responseCode = "404", description = "REPORT_NOT_FOUND")
@GetMapping("/reports/{id}")
public ResponseEntity<AdminReportDetailResponse> getReportDetail(@PathVariable Long id) {
return ResponseEntity.ok(adminService.getReportDetail(id));
}

@Operation(summary = "신고 처리 상태 변경 (deleteTarget=true 시 대상 게시글·댓글 강제 삭제)")
@ApiResponse(responseCode = "404", description = "REPORT_NOT_FOUND")
@PatchMapping("/reports/{id}/status")
public ResponseEntity<Void> updateReportStatus(
@PathVariable Long id,
@RequestBody @Valid AdminReportStatusUpdateRequest request) {
adminService.updateReportStatus(id, request);
return ResponseEntity.ok().build();
}

@Operation(summary = "EXCLUDED 공연 목록 조회")
@GetMapping("/concerts/excluded")
public ResponseEntity<PageResponse<AdminExcludedConcertResponse>> getExcludedConcerts(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.Coming.Backend.admin.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record AdminNoticeCreateRequest(
@NotBlank @Size(max = 255) String title,
@NotBlank String content,
Boolean active
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.Coming.Backend.admin.dto;

public record AdminNoticeCreateResponse(Long noticeId) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.Coming.Backend.admin.dto;

import com.Coming.Backend.notice.entity.Notice;

import java.time.LocalDateTime;

public record AdminNoticeDetailResponse(
Long id,
String title,
String content,
boolean active,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
public static AdminNoticeDetailResponse of(Notice notice) {
return new AdminNoticeDetailResponse(
notice.getId(),
notice.getTitle(),
notice.getContent(),
notice.isActive(),
notice.getCreatedAt(),
notice.getUpdatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.Coming.Backend.admin.dto;

import com.Coming.Backend.notice.entity.Notice;

import java.time.LocalDateTime;

public record AdminNoticeListItemResponse(
Long id,
String title,
boolean active,
LocalDateTime createdAt
) {
public static AdminNoticeListItemResponse of(Notice notice) {
return new AdminNoticeListItemResponse(
notice.getId(),
notice.getTitle(),
notice.isActive(),
notice.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.Coming.Backend.admin.dto;

import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

public record AdminNoticeUpdateRequest(
@Pattern(regexp = "(?s).*\\S.*", message = "제목은 공백일 수 없습니다")
@Size(max = 255)
String title,

@Pattern(regexp = "(?s).*\\S.*", message = "내용은 공백일 수 없습니다")
String content,
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Boolean active
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.Coming.Backend.admin.dto;

import com.Coming.Backend.report.entity.Report;
import com.Coming.Backend.report.entity.ReportReason;
import com.Coming.Backend.report.entity.ReportStatus;
import com.Coming.Backend.report.entity.ReportTargetType;

import java.time.LocalDateTime;

public record AdminReportDetailResponse(
Long id,
ReportTargetType targetType,
Long targetId,
ReportReason reason,
String detail,
ReportStatus status,
String adminNote,
Long reporterId,
String reporterNickname,
LocalDateTime createdAt
) {
public static AdminReportDetailResponse of(Report report, String reporterNickname) {
return new AdminReportDetailResponse(
report.getId(),
report.getTargetType(),
report.getTargetId(),
report.getReason(),
report.getDetail(),
report.getStatus(),
report.getAdminNote(),
report.getReporterId(),
reporterNickname,
report.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.Coming.Backend.admin.dto;

import com.Coming.Backend.report.entity.Report;
import com.Coming.Backend.report.entity.ReportReason;
import com.Coming.Backend.report.entity.ReportStatus;
import com.Coming.Backend.report.entity.ReportTargetType;

import java.time.LocalDateTime;

public record AdminReportListItemResponse(
Long id,
ReportTargetType targetType,
Long targetId,
ReportReason reason,
ReportStatus status,
Long reporterId,
String reporterNickname,
LocalDateTime createdAt
) {
public static AdminReportListItemResponse of(Report report, String reporterNickname) {
return new AdminReportListItemResponse(
report.getId(),
report.getTargetType(),
report.getTargetId(),
report.getReason(),
report.getStatus(),
report.getReporterId(),
reporterNickname,
report.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.Coming.Backend.admin.dto;

import com.Coming.Backend.report.entity.ReportStatus;
import jakarta.validation.constraints.NotNull;

public record AdminReportStatusUpdateRequest(
@NotNull ReportStatus status,
String adminNote,
Boolean deleteTarget
) {
}
Loading
Loading