Skip to content

Commit

Permalink
Merge pull request #19 from coffee-meet/feat/#6
Browse files Browse the repository at this point in the history
  • Loading branch information
smartandhandsome authored Oct 23, 2023
2 parents c611af3 + 146a38a commit 9b5846e
Show file tree
Hide file tree
Showing 18 changed files with 341 additions and 109 deletions.
155 changes: 79 additions & 76 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,116 +1,119 @@
import org.hidetake.gradle.swagger.generator.GenerateSwaggerUI

buildscript {
ext {
restdocsApiSpecVersion = '0.18.3' // restdocsApiSpecVersion 버전 변수 설정
}
ext {
restdocsApiSpecVersion = '0.18.3' // restdocsApiSpecVersion 버전 변수 설정
}
}

plugins {
id 'java'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
id 'com.epages.restdocs-api-spec' version "${restdocsApiSpecVersion}"
id 'org.hidetake.swagger.generator' version '2.18.2'
id 'java'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
id 'com.epages.restdocs-api-spec' version "${restdocsApiSpecVersion}"
id 'org.hidetake.swagger.generator' version '2.18.2'
}

group = 'coffee-meet'
version = '0.0.1-SNAPSHOT'

java {
sourceCompatibility = '17'
sourceCompatibility = '17'
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
mavenCentral()
}

ext {
set('snippetsDir', file("build/generated-snippets"))
set('snippetsDir', file("build/generated-snippets"))
}

dependencies {
/* Database */
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.h2database:h2'

/* Spring */
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'

/* JWT */
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

/* Lombok */
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

/* Test */
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation group: 'org.instancio', name: 'instancio-junit', version: '3.0.0'

/* TestContainer */
testImplementation "org.testcontainers:testcontainers:1.19.0"
testImplementation "org.testcontainers:junit-jupiter:1.19.0"

/* Docs & UI */
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation "com.epages:restdocs-api-spec-mockmvc:${restdocsApiSpecVersion}"
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
swaggerUI 'org.webjars:swagger-ui:4.11.1'
/* Database */
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.h2database:h2'

/* Spring */
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'

/* JWT */
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

/* Lombok */
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

/* Test */
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation group: 'org.instancio', name: 'instancio-junit', version: '3.0.0'

/* TestContainer */
testImplementation "org.testcontainers:testcontainers:1.19.0"
testImplementation "org.testcontainers:junit-jupiter:1.19.0"

/* Docs & UI */
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation "com.epages:restdocs-api-spec-mockmvc:${restdocsApiSpecVersion}"
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
swaggerUI 'org.webjars:swagger-ui:4.11.1'

/* Cloud */
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}

swaggerSources {
sample {
setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml"))
}
sample {
setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml"))
}
}

openapi3 {
servers = [
{ url = "http://localhost:8080" },
{ url = "http://13.209.253.204:8080" }
]
title = "API 문서"
description = "RestDocsWithSwagger Docs"
version = "0.0.1"
format = "yaml"
servers = [
{ url = "http://localhost:8080" },
{ url = "http://13.209.253.204:8080" }
]
title = "API 문서"
description = "RestDocsWithSwagger Docs"
version = "0.0.1"
format = "yaml"
}

tasks.withType(GenerateSwaggerUI) {
dependsOn 'openapi3'
doFirst {
def swaggerUIFile = file("${openapi3.outputDirectory}/openapi3.yaml")

def securitySchemesContent = " securitySchemes:\n" + \
" APIKey:\n" + \
" type: apiKey\n" + \
" name: Authorization\n" + \
" in: header\n" + \
"security:\n" +
" - APIKey: [] # Apply the security scheme here"

swaggerUIFile.append securitySchemesContent
}
dependsOn 'openapi3'
doFirst {
def swaggerUIFile = file("${openapi3.outputDirectory}/openapi3.yaml")

def securitySchemesContent = " securitySchemes:\n" + \
" APIKey:\n" + \
" type: apiKey\n" + \
" name: Authorization\n" + \
" in: header\n" + \
"security:\n" +
" - APIKey: [] # Apply the security scheme here"

swaggerUIFile.append securitySchemesContent
}
}

bootJar {
dependsOn generateSwaggerUISample
from("${generateSwaggerUISample.outputDir}") {
into 'static/docs'
}
dependsOn generateSwaggerUISample
from("${generateSwaggerUISample.outputDir}") {
into 'static/docs'
}
}
4 changes: 3 additions & 1 deletion src/main/java/coffeemeet/server/admin/domain/Admin.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package coffeemeet.server.admin.domain;

import coffeemeet.server.common.entity.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
Expand All @@ -12,12 +13,13 @@
@Getter
@Table(name = "admins")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Admin {
public class Admin extends BaseEntity {

@Id
@Column(nullable = false)
private String id;

@Column(nullable = false)
private String password;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package coffeemeet.server.certification.controller;

import static org.springframework.http.HttpStatus.CREATED;

import coffeemeet.server.certification.service.CertificationService;
import coffeemeet.server.common.util.FileUtils;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequiredArgsConstructor
@RequestMapping("/certification")
public class CertificationController {

private final CertificationService certificationService;

@PostMapping("/users/{userId}/business-card")
@ResponseStatus(CREATED)
public void uploadBusinessCard(
@PathVariable("userId")
@NotNull(message = "유저 ID는 null일 수 없습니다.")
long userId,
@RequestPart("businessCard")
@NotNull(message = "명함 이미지는 null일 수 없습니다.")
MultipartFile businessCard
) {
certificationService.uploadBusinessCard(userId,
FileUtils.convertMultipartFileToFile(businessCard));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package coffeemeet.server.certification.service;

import java.time.LocalDateTime;
import java.util.UUID;
import org.springframework.stereotype.Service;

@Service
public class BusinessCardS3KeyGenerator {

public String generate() {
return String.format("BusinessCard-%s-%s", LocalDateTime.now(), UUID.randomUUID());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package coffeemeet.server.certification.service;

import coffeemeet.server.common.media.S3MediaService;
import coffeemeet.server.common.util.FileUtils;
import coffeemeet.server.user.service.UserService;
import java.io.File;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class CertificationService {

private final S3MediaService s3MediaService;
private final UserService userService;
private final BusinessCardS3KeyGenerator businessCardS3KeyGenerator;

public void uploadBusinessCard(long userId, File file) {
String key = businessCardS3KeyGenerator.generate();

s3MediaService.upload(key, file);
userService.updateBusinessCardUrl(userId, s3MediaService.getUrl(key));

FileUtils.delete(file);
}
}
37 changes: 37 additions & 0 deletions src/main/java/coffeemeet/server/common/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package coffeemeet.server.common.config;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {

private final String accessKey;
private final String secretKey;
private final String region;

public S3Config(
@Value("${cloud.aws.credentials.access-key}") String accessKey,
@Value("${cloud.aws.credentials.secret-key}") String secretKey,
@Value("${cloud.aws.region.static}") String region) {
this.accessKey = accessKey;
this.secretKey = secretKey;
this.region = region;
}

@Bean
public AmazonS3 amazonS3Client() {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder
.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
}

}
34 changes: 34 additions & 0 deletions src/main/java/coffeemeet/server/common/media/S3MediaService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package coffeemeet.server.common.media;

import com.amazonaws.services.s3.AmazonS3;
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class S3MediaService {

private final AmazonS3 amazonS3;
private final String bucketName;

public S3MediaService(
AmazonS3 amazonS3,
@Value("${cloud.aws.s3.bucket}") String bucketName
) {
this.amazonS3 = amazonS3;
this.bucketName = bucketName;
}

public void upload(String key, File file) {
amazonS3.putObject(bucketName, key, file);
}

public void delete(String key) {
amazonS3.deleteObject(bucketName, key);
}

public String getUrl(String key) {
return amazonS3.getUrl(bucketName, key).toExternalForm();
}

}
Loading

0 comments on commit 9b5846e

Please sign in to comment.