diff --git a/.github/workflows/ci-cd_dev.yml b/.github/workflows/ci-cd_dev.yml new file mode 100644 index 0000000..5b32541 --- /dev/null +++ b/.github/workflows/ci-cd_dev.yml @@ -0,0 +1,68 @@ +name: Development Server CI/CD with Gradle and Docker + +on: + push: + branches: [ "develop" ] + pull_request: + branches: [ "develop" ] + +jobs: + build-docker-image: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Create Firebase Config Directory + run: | + mkdir -p src/main/resources/firebase + echo "${{ secrets.FIREBASE_SERVICE_KEY }}" | base64 --decode > src/main/resources/firebase/firebaseServiceKey.json + shell: bash + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + + - name: Build with Gradle Wrapper + run: ./gradlew clean build -x test + + # Docker 관련 작업들은 push 시에만 실행되도록 설정 + - name: docker image build + if: github.event_name == 'push' + run: docker build -f Dockerfile-dev -t ${{ secrets.DOCKER_USERNAME }}/billilge-dev:latest . + + # DockerHub 로그인 + - name: docker login + if: github.event_name == 'push' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + # Docker Hub 이미지 푸시 + - name: docker Hub push + if: github.event_name == 'push' + run: docker push ${{ secrets.DOCKER_USERNAME }}/billilge-dev:latest + + run-docker-image-on-ec2: + needs: build-docker-image + #push 했을 때만 배포가 진행되도록 + if: github.event_name == 'push' + runs-on: self-hosted + steps: + - name: docker pull + run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/billilge-dev:latest + + - name: docker stop container + run: sudo docker stop springboot || true + + - name: docker run new container + run: sudo docker run --env-file /home/ubuntu/billilge.env --name springboot --rm -d -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/billilge-dev:latest + + - name: delete old docker image + run: sudo docker image prune -f \ No newline at end of file diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd_prod.yml similarity index 97% rename from .github/workflows/ci-cd.yml rename to .github/workflows/ci-cd_prod.yml index 41854b3..ee3bae9 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd_prod.yml @@ -1,4 +1,4 @@ -name: CI/CD with Gradle and Docker +name: Production Server CI/CD with Gradle and Docker on: push: diff --git a/Dockerfile-dev b/Dockerfile-dev new file mode 100644 index 0000000..3721652 --- /dev/null +++ b/Dockerfile-dev @@ -0,0 +1,10 @@ +# Dockerfile + +# jdk17 Image Start +FROM openjdk:17 + +# jar 파일 복제 +COPY build/libs/*.jar app.jar + +# 실행 명령어 +ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul", "-Dspring.profiles.active=dev", "-jar", "app.jar"] \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationApi.kt b/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationApi.kt index 1da6455..1bb3d1a 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationApi.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationApi.kt @@ -62,4 +62,19 @@ interface NotificationApi { fun getNotificationCount( @AuthenticationPrincipal userAuthInfo: UserAuthInfo ): ResponseEntity + + @Operation( + summary = "알림 모두 읽음 처리", + description = "사용자가 알림을 모두 읽음 처리합니다." + ) + @ApiResponses( + value = [ + ApiResponse(responseCode = "200", description = "알림 모두 읽음 처리 완료"), + ApiResponse(responseCode = "403", description = "권한이 없는 사용자"), + ApiResponse(responseCode = "404", description = "알림을 찾을 수 없음") + ] + ) + fun readAllNotifications( + @AuthenticationPrincipal userAuthInfo: UserAuthInfo + ): ResponseEntity } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationController.kt b/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationController.kt index 5d8c1ec..6b1074d 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationController.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/notification/controller/NotificationController.kt @@ -39,4 +39,13 @@ class NotificationController ( notificationService.readNotification(memberId, notificationId) return ResponseEntity.ok().build() } + + @PatchMapping("/all") + override fun readAllNotifications( + @AuthenticationPrincipal userAuthInfo: UserAuthInfo + ): ResponseEntity { + val memberId = userAuthInfo.memberId + notificationService.readAllNotifications(memberId) + return ResponseEntity.ok().build() + } } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/notification/entity/Notification.kt b/src/main/kotlin/site/billilge/api/backend/domain/notification/entity/Notification.kt index 7415bcf..1b4fb3d 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/notification/entity/Notification.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/notification/entity/Notification.kt @@ -11,9 +11,9 @@ import java.time.LocalDateTime @Table(name = "notifications") @EntityListeners(AuditingEntityListener::class) class Notification( - @JoinColumn(name = "member_id", nullable = false) + @JoinColumn(name = "member_id", nullable = true) @ManyToOne - val member: Member, + val member: Member? = null, @Enumerated(EnumType.STRING) @Column(name = "type", nullable = false) diff --git a/src/main/kotlin/site/billilge/api/backend/domain/notification/service/NotificationService.kt b/src/main/kotlin/site/billilge/api/backend/domain/notification/service/NotificationService.kt index 854cdc5..e3f9e80 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/notification/service/NotificationService.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/notification/service/NotificationService.kt @@ -30,7 +30,8 @@ class NotificationService( return NotificationFindAllResponse( notifications - .map { NotificationDetail.from(it) }) + .map { NotificationDetail.from(it) } + ) } @Transactional @@ -38,7 +39,9 @@ class NotificationService( val notification = notificationRepository.findById(notificationId) .orElseThrow { ApiException(NotificationErrorCode.NOTIFICATION_NOT_FOUND) } - if (notification.member.id != memberId) { + if (notification.isAdminStatus()) return; + + if (notification.member?.id != memberId) { throw ApiException(NotificationErrorCode.NOTIFICATION_ACCESS_DENIED) } @@ -58,7 +61,7 @@ class NotificationService( member: Member, status: NotificationStatus, formatValues: List, - needPush: Boolean = false + needPush: Boolean = false, ) { val notification = Notification( member = member, @@ -69,23 +72,32 @@ class NotificationService( notificationRepository.save(notification) if (needPush) { - val studentId = member.studentId + sendPushNotification(member, status, formatValues) + } + } - if (member.fcmToken == null) { - log.warn { "(studentId=${studentId}) FCM Token is null" } - return - } + private fun sendPushNotification( + member: Member, + status: NotificationStatus, + formatValues: List, + ) { + val studentId = member.studentId - fcmService.sendPushNotification( - member.fcmToken!!, - status.title, - status.formattedMessage(*formatValues.toTypedArray()), - status.link, - studentId - ) + if (member.fcmToken == null) { + log.warn { "(studentId=${studentId}) FCM Token is null" } + return } + + fcmService.sendPushNotification( + member.fcmToken!!, + status.title, + status.formattedMessage(*formatValues.toTypedArray()), + status.link, + studentId + ) } + @Transactional fun sendNotificationToAdmin( type: NotificationStatus, formatValues: List, @@ -93,8 +105,17 @@ class NotificationService( ) { val admins = memberRepository.findAllByRole(Role.ADMIN) - admins.forEach { admin -> - sendNotification(admin, type, formatValues, needPush) + val notification = Notification( + status = type, + formatValues = formatValues.joinToString(",") + ) + + notificationRepository.save(notification) + + if (needPush) { + admins.forEach { admin -> + sendPushNotification(admin, type, formatValues) + } } } @@ -103,4 +124,13 @@ class NotificationService( return NotificationCountResponse(count) } + + @Transactional + fun readAllNotifications(memberId: Long?) { + notificationRepository + .findAllUserNotificationsByMemberId(memberId!!) + .forEach { it.readNotification() } + } + + private fun Notification.isAdminStatus(): Boolean = status.name.contains("ADMIN", true) } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerApi.kt b/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerApi.kt index e39599b..241db2a 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerApi.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerApi.kt @@ -1,9 +1,12 @@ package site.billilge.api.backend.domain.payer.controller import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.Schema 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 org.springframework.core.io.InputStreamResource import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestParam @@ -62,4 +65,22 @@ interface AdminPayerApi { ] ) fun deletePayers(@RequestBody request: PayerDeleteRequest): ResponseEntity + + @Operation( + summary = "학생회비 납부자 Excel 파일 다운로드", + description = "학생회비 납부자 데이터를 엑셀 파일로 다운받을 수 있는 관리자용 API" + ) + @ApiResponses( + value = [ + ApiResponse( + responseCode = "200", + description = "파일 다운로드 성공", + content = [Content( + mediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + schema = Schema(type = "string", format = "binary") + )] + ) + ] + ) + fun createPayerExcel(): ResponseEntity } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerController.kt b/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerController.kt index ed74ab8..e4183b1 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerController.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerController.kt @@ -1,5 +1,9 @@ package site.billilge.api.backend.domain.payer.controller +import org.springframework.core.io.InputStreamResource +import org.springframework.http.ContentDisposition +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* import site.billilge.api.backend.domain.payer.dto.request.PayerDeleteRequest @@ -9,6 +13,8 @@ import site.billilge.api.backend.domain.payer.service.PayerService import site.billilge.api.backend.global.annotation.OnlyAdmin import site.billilge.api.backend.global.dto.PageableCondition import site.billilge.api.backend.global.dto.SearchCondition +import java.time.LocalDate +import java.time.format.DateTimeFormatter @RestController @RequestMapping("/admin/members/payers") @@ -35,4 +41,22 @@ class AdminPayerController( payerService.deletePayers(request) return ResponseEntity.noContent().build() } + + @GetMapping("/excel") + override fun createPayerExcel(): ResponseEntity { + val excel = payerService.createPayerExcel() + val currentDate = LocalDate.now() + val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd") + val headers = HttpHeaders().apply { + contentDisposition = ContentDisposition.builder("attachment") + .filename("kmusw_payers_${dateFormatter.format(currentDate)}.xlsx") + .build() + } + val excelMediaType = MediaType.valueOf("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + + return ResponseEntity.ok() + .headers(headers) + .contentType(excelMediaType) + .body(InputStreamResource((excel))) + } } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/payer/repository/PayerRepository.kt b/src/main/kotlin/site/billilge/api/backend/domain/payer/repository/PayerRepository.kt index a545714..ce0468a 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/payer/repository/PayerRepository.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/payer/repository/PayerRepository.kt @@ -15,4 +15,6 @@ interface PayerRepository : JpaRepository { @Query("SELECT p FROM Payer p WHERE p.name LIKE CONCAT('%', :name, '%')") fun findAllByNameContaining(@Param("name") name: String, pageable: Pageable): Page + + fun findAllByEnrollmentYear(enrollmentYear: String): List } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/payer/service/PayerService.kt b/src/main/kotlin/site/billilge/api/backend/domain/payer/service/PayerService.kt index df1e9d3..446fb8b 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/payer/service/PayerService.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/payer/service/PayerService.kt @@ -14,12 +14,19 @@ import site.billilge.api.backend.domain.payer.entity.Payer import site.billilge.api.backend.domain.payer.repository.PayerRepository import site.billilge.api.backend.global.dto.PageableCondition import site.billilge.api.backend.global.dto.SearchCondition +import site.billilge.api.backend.global.utils.ExcelGenerator +import site.billilge.api.backend.global.utils.ExcelRow +import java.io.ByteArrayInputStream +import java.time.Year @Service @Transactional(readOnly = true) class PayerService( private val payerRepository: PayerRepository, - private val memberRepository: MemberRepository + + private val memberRepository: MemberRepository, + + private val excelGenerator: ExcelGenerator ) { fun isPayer(name: String, studentId: String): Boolean { val enrollmentYear = studentId.substring(0, 4) @@ -71,6 +78,7 @@ class PayerService( @Transactional fun addPayers(request: PayerRequest) { + val newPayers = mutableListOf() request.payers.forEach { payerItem -> val name = payerItem.name val studentId = payerItem.studentId @@ -87,18 +95,19 @@ class PayerService( this.registered = registered } - payerRepository.save(payer) + newPayers.add(payer) } registeredMember?.isFeePaid = true } + + payerRepository.saveAll(newPayers) } @Transactional fun deletePayers(request: PayerDeleteRequest) { val payerStudentIds = payerRepository.findAllByIds(request.payerIds) .mapNotNull { it.studentId } - .toList() memberRepository.findAllByStudentIds(payerStudentIds) .forEach { member -> @@ -107,4 +116,21 @@ class PayerService( payerRepository.deleteAllById(request.payerIds) } + + fun createPayerExcel(): ByteArrayInputStream { + val startYear = 2015 + val currentYear = Year.now().value + val headerTitles = arrayOf("이름", "학번") + val sheetData = mutableMapOf, List>>() + + for (year in currentYear downTo startYear) { + val yearText = "$year" + val payersByYearExcelRow = payerRepository.findAllByEnrollmentYear(yearText) + .map { payer -> ExcelRow(payer.name, payer.studentId ?: "${yearText}XXXX") } + + sheetData.put(yearText, headerTitles to payersByYearExcelRow) + } + + return excelGenerator.generateByMultipleSheets(sheetData) + } } \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/domain/rental/dto/response/DashboardResponse.kt b/src/main/kotlin/site/billilge/api/backend/domain/rental/dto/response/DashboardResponse.kt index 2d9bc91..77ddb41 100644 --- a/src/main/kotlin/site/billilge/api/backend/domain/rental/dto/response/DashboardResponse.kt +++ b/src/main/kotlin/site/billilge/api/backend/domain/rental/dto/response/DashboardResponse.kt @@ -28,8 +28,8 @@ data class DashboardResponse( val renterStudentId: String, @field:Schema(description = "대여 상태", example = "PENDING") val status: RentalStatus, - @field:Schema(description = "신청일") - val applicatedAt: LocalDateTime + @field:Schema(description = "대여 시각") + val rentAt: LocalDateTime?, ) { companion object { @JvmStatic @@ -42,7 +42,7 @@ data class DashboardResponse( renterName = rentalHistory.member.name, renterStudentId = rentalHistory.member.studentId, status = rentalHistory.rentalStatus, - applicatedAt = rentalHistory.applicatedAt + rentAt = rentalHistory.rentAt ) } } diff --git a/src/main/kotlin/site/billilge/api/backend/global/config/AsyncConfig.kt b/src/main/kotlin/site/billilge/api/backend/global/config/AsyncConfig.kt new file mode 100644 index 0000000..71b0bd9 --- /dev/null +++ b/src/main/kotlin/site/billilge/api/backend/global/config/AsyncConfig.kt @@ -0,0 +1,9 @@ +package site.billilge.api.backend.global.config + +import org.springframework.context.annotation.Configuration +import org.springframework.scheduling.annotation.EnableAsync + +@EnableAsync +@Configuration +class AsyncConfig { +} \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/global/security/jwt/TokenProvider.kt b/src/main/kotlin/site/billilge/api/backend/global/security/jwt/TokenProvider.kt index 645ad33..2406778 100644 --- a/src/main/kotlin/site/billilge/api/backend/global/security/jwt/TokenProvider.kt +++ b/src/main/kotlin/site/billilge/api/backend/global/security/jwt/TokenProvider.kt @@ -37,10 +37,10 @@ class TokenProvider( fun generateToken(member: Member, expiredAt: Duration): String { val now = Date() - return makeToken(Date(now.time + expiredAt.toMillis()), member.studentId, member.role, member.name) + return makeToken(Date(now.time + expiredAt.toMillis()), member.studentId, member.role, member.name, member.isFeePaid) } - private fun makeToken(expiry: Date, studentId: String, role: Role, name: String): String { + private fun makeToken(expiry: Date, studentId: String, role: Role, name: String, isFeePaid: Boolean): String { val now = Date() return Jwts.builder() @@ -51,6 +51,7 @@ class TokenProvider( .setSubject(studentId) .claim("role", role.name) .claim("name", name) + .claim("isFeePaid", isFeePaid) .signWith(createSecretKey(), signatureAlgorithm) .compact() } diff --git a/src/main/kotlin/site/billilge/api/backend/global/security/oauth2/OAuth2AuthenticationSuccessHandler.kt b/src/main/kotlin/site/billilge/api/backend/global/security/oauth2/OAuth2AuthenticationSuccessHandler.kt index 4f1dcb5..1c99f35 100644 --- a/src/main/kotlin/site/billilge/api/backend/global/security/oauth2/OAuth2AuthenticationSuccessHandler.kt +++ b/src/main/kotlin/site/billilge/api/backend/global/security/oauth2/OAuth2AuthenticationSuccessHandler.kt @@ -23,7 +23,7 @@ class OAuth2AuthenticationSuccessHandler( private val memberRepository: MemberRepository, - @Value("\${login.redirect.url}") private val redirectUrl: String, + @Value("\${login.redirect-url}") private val redirectUrl: String, ) : SimpleUrlAuthenticationSuccessHandler() { override fun onAuthenticationSuccess( request: HttpServletRequest?, response: HttpServletResponse?, authentication: Authentication? diff --git a/src/main/kotlin/site/billilge/api/backend/global/utils/ExcelGenerator.kt b/src/main/kotlin/site/billilge/api/backend/global/utils/ExcelGenerator.kt new file mode 100644 index 0000000..58c9b56 --- /dev/null +++ b/src/main/kotlin/site/billilge/api/backend/global/utils/ExcelGenerator.kt @@ -0,0 +1,67 @@ +package site.billilge.api.backend.global.utils + +import org.apache.poi.ss.usermodel.IndexedColors +import org.apache.poi.xssf.streaming.SXSSFSheet +import org.apache.poi.xssf.streaming.SXSSFWorkbook +import org.springframework.stereotype.Component +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream + +private const val HEADER_ROW = 0 + +@Component +class ExcelGenerator { + + fun generateByMultipleSheets( + sheetData: Map, List>> + ): ByteArrayInputStream { + val workbook = SXSSFWorkbook() + + try { + sheetData.forEach { (sheetName, sheetContent) -> + val (headerTitles, rows) = sheetContent + val sheet = workbook.createSheet(sheetName) + styleHeaders(workbook, sheet, headerTitles) + fillData(sheet, rows) + } + + val out = ByteArrayOutputStream() + workbook.write(out) + return ByteArrayInputStream(out.toByteArray()) + } finally { + workbook.dispose() + workbook.close() + } + } + + private fun styleHeaders(workbook: SXSSFWorkbook, sheet: SXSSFSheet, headerTitles: Array) { + val headerFont = workbook.createFont() + headerFont.bold = true + + val headerCellStyle = workbook.createCellStyle() + headerCellStyle.setFont(headerFont) + headerCellStyle.fillForegroundColor = IndexedColors.GREY_25_PERCENT.index + headerCellStyle.fillPattern = org.apache.poi.ss.usermodel.FillPatternType.SOLID_FOREGROUND + + val headerRow = sheet.createRow(HEADER_ROW) + headerTitles.forEachIndexed { col, title -> + val cell = headerRow.createCell(col) + cell.setCellValue(title) + cell.cellStyle = headerCellStyle + } + + //이름 칸 너비 + sheet.setColumnWidth(0, 10 * 256) + //학번 칸 너비 + sheet.setColumnWidth(1, 16 * 256) + } + + private fun fillData(sheet: SXSSFSheet, rows: List) { + rows.forEachIndexed { index, excelRow -> + val row = sheet.createRow(index + 1) + excelRow.data.forEachIndexed { propertyIndex, property -> + row.createCell(propertyIndex).setCellValue(property) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/site/billilge/api/backend/global/utils/ExcelRow.kt b/src/main/kotlin/site/billilge/api/backend/global/utils/ExcelRow.kt new file mode 100644 index 0000000..c717b82 --- /dev/null +++ b/src/main/kotlin/site/billilge/api/backend/global/utils/ExcelRow.kt @@ -0,0 +1,7 @@ +package site.billilge.api.backend.global.utils + +data class ExcelRow( + val data: List +) { + constructor(vararg data: String) : this(data.toList()) +} \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..1202e12 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,70 @@ +spring: + application: + name: backend + + datasource: + url: jdbc:mysql://${DEV_DB_URL}?useSSL=false&serverTimezone=Asia/Seoul&characterEncoding=UTF-8&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + username: ${DEV_DB_USERNAME} + password: ${DEV_DB_PASSWORD} + + security: + oauth2: + client: + registration: + # 구글 로그인 추가 + google: + client-id: ${DEV_OAUTH2_GOOGLE_CLIENT_ID} + client-secret: ${DEV_OAUTH2_GOOGLE_CLIENT_SECRET} + redirect-uri: ${DEV_SWAGGER_SERVER_BASE_URL}/login/oauth2/code/google + scope: + - email + - profile + jpa: + properties: + hibernate: + format_sql: true + dialect: org.hibernate.dialect.MySQLDialect + dialect.storage_engine: innodb + show-sql: true + hibernate: + ddl-auto: update + + servlet: + multipart: + max-file-size: 5MB + max-request-size: 10MB + resolve-lazily: true + + +jwt: + secret_key: ${DEV_JWT_SECRET_KEY} + issuer: ${DEV_JWT_ISSUER} + +login: + admin-password: ${DEV_LOGIN_ADMIN_PASSWORD} + redirect-url: ${DEV_LOGIN_REDIRECT_URL} + +cors: + allowed-origins: ${DEV_CORS_ALLOWED_ORIGINS} + +exam-period: + start-date: ${DEV_EXAM_PERIOD_START_DATE} + end-date: ${DEV_EXAM_PERIOD_END_DATE} + +cloud: + aws: + s3: + bucket: ${DEV_S3_BUCKET} + base-url: ${DEV_S3_BASE_URL} + credentials: + access-key: ${DEV_S3_ACCESS_KEY} + secret-key: ${DEV_S3_SECRET_KEY} + region: + static: us-west-2 + stack: + auto: false + +swagger: + server: + base-url: ${DEV_SWAGGER_SERVER_BASE_URL} \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index fa273d8..6a207c6 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -42,8 +42,7 @@ jwt: login: admin-password: ${LOGIN_ADMIN_PASSWORD} - redirect: - url: ${LOGIN_REDIRECT_URL} + redirect-url: ${LOGIN_REDIRECT_URL} cors: allowed-origins: ${CORS_ALLOWED_ORIGINS} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ea5aa73..8c3d881 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,4 +15,4 @@ springdoc: show-actuator: true # Spring Actuator의 endpoint까지 보여줄 것인지? default-consumes-media-type: application/json # request media type 의 기본 값 default-produces-media-type: application/json # response media type 의 기본 값 - paths-to-match: /** # 해당 패턴에 매칭되는 controller만 swagger-ui에 노출한다. + paths-to-match: /** # 해당 패턴에 매칭되는 controller만 swagger-ui에 노출한다. \ No newline at end of file