Skip to content
Closed
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
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI with Gradle

on:
pull_request:
branches: [ "develop", "release", "master" ]

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
checks: write

steps:
- name: Checkout the code
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4

- name: Make Gradle wrapper executable
run: chmod +x ./gradlew

- name: Build with Gradle Wrapper
run: ./gradlew build
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,17 @@
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.stream.Collectors;

import static com.example.solidconnection.custom.exception.ErrorCode.FAILED_TO_READ_APPLE_PRIVATE_KEY;

/*
* 애플 OAuth 에 필요하 클라이언트 시크릿은 매번 동적으로 생성해야 한다.
* 애플 OAuth 에 필요한 클라이언트 시크릿은 매번 동적으로 생성해야 한다.
* 클라이언트 시크릿은 애플 개발자 계정에서 발급받은 개인키(*.p8)를 사용하여 JWT 를 생성한다.
* https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret
* */
Expand All @@ -32,14 +29,13 @@ public class AppleOAuthClientSecretProvider {

private static final String KEY_ID_HEADER = "kid";
private static final long TOKEN_DURATION = 1000 * 60 * 10; // 10min
private static final String SECRET_KEY_PATH = "secret/AppleOAuthKey.p8";

private final AppleOAuthClientProperties appleOAuthClientProperties;
private PrivateKey privateKey;

@PostConstruct
private void initPrivateKey() {
privateKey = readPrivateKey();
privateKey = generatePrivateKey();
}

public String generateClientSecret() {
Expand All @@ -57,16 +53,14 @@ public String generateClientSecret() {
.compact();
}

private PrivateKey readPrivateKey() {
try (InputStream is = getClass().getClassLoader().getResourceAsStream(SECRET_KEY_PATH);
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {

String secretKey = reader.lines().collect(Collectors.joining("\n"));
private PrivateKey generatePrivateKey() {
try {
String secretKey = appleOAuthClientProperties.secretKey();
byte[] encoded = Base64.decodeBase64(secretKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
return keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new CustomException(FAILED_TO_READ_APPLE_PRIVATE_KEY);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public record AppleOAuthClientProperties(
String publicKeyUrl,
String clientId,
String teamId,
String keyId
String keyId,
String secretKey
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ class 댓글_조회_테스트 {
() -> assertThat(response.parentId()).isNull(),
() -> assertThat(response.content()).isEqualTo(parentComment.getContent()),
() -> assertThat(response.isOwner()).isTrue(),
() -> assertThat(response.createdAt()).isEqualTo(parentComment.getCreatedAt()),
() -> assertThat(response.updatedAt()).isEqualTo(parentComment.getUpdatedAt()),
() -> assertThat(response.createdAt().withNano(0))
.isEqualTo(parentComment.getCreatedAt().withNano(0)),
() -> assertThat(response.updatedAt().withNano(0))
.isEqualTo(parentComment.getUpdatedAt().withNano(0)),

() -> assertThat(response.postFindSiteUserResponse().id())
.isEqualTo(parentComment.getSiteUser().getId()),
Expand All @@ -89,8 +91,10 @@ class 댓글_조회_테스트 {
() -> assertThat(response.parentId()).isEqualTo(parentComment.getId()),
() -> assertThat(response.content()).isEqualTo(childComment.getContent()),
() -> assertThat(response.isOwner()).isFalse(),
() -> assertThat(response.createdAt()).isEqualTo(childComment.getCreatedAt()),
() -> assertThat(response.updatedAt()).isEqualTo(childComment.getUpdatedAt()),
() -> assertThat(response.createdAt().withNano(0))
.isEqualTo(childComment.getCreatedAt().withNano(0)),
() -> assertThat(response.updatedAt().withNano(0))
.isEqualTo(childComment.getUpdatedAt().withNano(0)),

() -> assertThat(response.postFindSiteUserResponse().id())
.isEqualTo(childComment.getSiteUser().getId()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;

import java.sql.DatabaseMetaData;
import java.sql.SQLException;
Expand All @@ -20,7 +19,6 @@

@Disabled
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2, replace = AutoConfigureTestDatabase.Replace.ANY)
@ActiveProfiles("test")
@DataJpaTest
class DatabaseConnectionTest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ActiveProfiles;

import static org.assertj.core.api.Assertions.assertThat;

@Disabled
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RedisConnectionTest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

@ActiveProfiles("test")
@Component
public class DatabaseCleaner {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
package com.example.solidconnection.support;

import jakarta.annotation.PostConstruct;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;

@TestConfiguration
public class RedisTestContainer {
public class RedisTestContainer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

@Container
private static final GenericContainer<?> CONTAINER = new GenericContainer<>("redis:7.0");
private static final int ORIGINAL_PORT = 6379;
private static final GenericContainer<?> CONTAINER = new GenericContainer<>("redis:7.0")
.withExposedPorts(ORIGINAL_PORT);

@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("spring.redis.host", CONTAINER::getHost);
registry.add("spring.redis.port", CONTAINER::getFirstMappedPort);
static {
CONTAINER.start();
}

@PostConstruct
void startContainer() {
if (!CONTAINER.isRunning()) {
CONTAINER.start();
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
TestPropertyValues.of(
"spring.data.redis.host=" + CONTAINER.getHost(),
"spring.data.redis.port=" + CONTAINER.getMappedPort(ORIGINAL_PORT)
).applyTo(applicationContext.getEnvironment());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.junit.jupiter.Testcontainers;

import java.lang.annotation.ElementType;
Expand All @@ -13,7 +12,6 @@

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ActiveProfiles("test")
@Testcontainers
@Import(MySQLTestContainer.class)
@Target(ElementType.TYPE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.testcontainers.junit.jupiter.Testcontainers;

import java.lang.annotation.ElementType;
Expand All @@ -13,11 +13,11 @@
import java.lang.annotation.Target;

@ExtendWith({DatabaseClearExtension.class})
@ContextConfiguration(initializers = RedisTestContainer.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ActiveProfiles("test")
@Testcontainers
@Import({MySQLTestContainer.class, RedisTestContainer.class})
@Import({MySQLTestContainer.class})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestContainerSpringBootTest {
Expand Down
73 changes: 73 additions & 0 deletions src/test/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
spring:

# db
data:
redis:
host: localhost
port: 6379
jpa:
hibernate:
ddl-auto: create
generate-ddl: true
show-sql: true
database: mysql
properties:
hibernate:
format_sql: true
flyway:
enabled: false

# cloud
cloud:
aws:
credentials:
access-key: access-key
secret-key: access-key
region:
static: ap-northeast-2
stack:
auto: false
s3:
bucket: solid-connection-uploaded
url:
default: default-url
uploaded: uploaded-url
cloudFront:
url:
default: default-url
uploaded: uploaded-url

# variable
view:
count:
scheduling:
delay: 3000
oauth:
apple:
token-url: "https://appleid.apple.com/auth/token"
client-secret-audience-url: "https://appleid.apple.com"
public-key-url: "https://appleid.apple.com/auth/keys"
client-id: client-id
team-id: team-id
key-id: key-id
redirect-url: "https://localhost:8080/auth/apple"
secret-key: MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCAfGIQ3TtNYAZG7i3m72odmdhfymkM9wAFg2rEL2RKUEA==
kakao:
redirect-url: "http://localhost:8080/auth/kakao"
client-id: client-id
token-url: "https://kauth.kakao.com/oauth/token"
user-info_url: "https://kapi.kakao.com/v2/user/me"
sentry:
environment: test
dsn: "https://test-public-key@sentry.test-domain.io/123456"
send-default-pii: true
traces-sample-rate: 1.0
exception-resolver-order: -2147483647
university:
term: 2024-1
jwt:
secret:
1234567-1234-1234-1234-12345678901
cors:
allowed-origins:
- "http://localhost:8080"
Loading