From d026d333d8246dfddecfeb41825e16e2dcc0ed4a Mon Sep 17 00:00:00 2001 From: taehyeon Date: Mon, 31 Mar 2025 17:49:13 +0900 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EC=84=A4=EA=B3=84=EB=B0=8F=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20Entitiy=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + backend-board/build.gradle | 6 +-- .../com/backendboard/entity/AuthUser.java | 54 +++++++++++++++++++ .../com/backendboard/entity/BaseEntity.java | 4 ++ .../java/com/backendboard/entity/User.java | 40 ++++++++++++++ .../backendboard/entity/type/UserRole.java | 15 ++++++ 6 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 backend-board/src/main/java/com/backendboard/entity/AuthUser.java create mode 100644 backend-board/src/main/java/com/backendboard/entity/BaseEntity.java create mode 100644 backend-board/src/main/java/com/backendboard/entity/User.java create mode 100644 backend-board/src/main/java/com/backendboard/entity/type/UserRole.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..038a0a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +docker-compose.yml +/nginx \ No newline at end of file diff --git a/backend-board/build.gradle b/backend-board/build.gradle index 43f4702..c11768f 100644 --- a/backend-board/build.gradle +++ b/backend-board/build.gradle @@ -24,13 +24,13 @@ repositories { } dependencies { - //implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - //implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + runtimeOnly 'com.mysql:mysql-connector-j' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' - //runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' diff --git a/backend-board/src/main/java/com/backendboard/entity/AuthUser.java b/backend-board/src/main/java/com/backendboard/entity/AuthUser.java new file mode 100644 index 0000000..5e5bc3a --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/entity/AuthUser.java @@ -0,0 +1,54 @@ +package com.backendboard.entity; + +import com.backendboard.entity.type.UserRole; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class AuthUser extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String username; + + @Column(nullable = false) + private String password; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, columnDefinition = "VARCHAR(20)") + private UserRole role; + + private boolean status; + + public AuthUser(String username, String password, UserRole role) { + this.username = username; + this.password = password; + this.role = role; + this.status = true; + } + + public User createUser(String username, String nickname) { + return User.builder() + .username(username) + .nickname(nickname) + .authUser(this) + .build(); + } + + public void deactivate() { + this.status = false; + } +} diff --git a/backend-board/src/main/java/com/backendboard/entity/BaseEntity.java b/backend-board/src/main/java/com/backendboard/entity/BaseEntity.java new file mode 100644 index 0000000..426f01c --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/entity/BaseEntity.java @@ -0,0 +1,4 @@ +package com.backendboard.entity; + +public class BaseEntity { +} diff --git a/backend-board/src/main/java/com/backendboard/entity/User.java b/backend-board/src/main/java/com/backendboard/entity/User.java new file mode 100644 index 0000000..52fbc9e --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/entity/User.java @@ -0,0 +1,40 @@ +package com.backendboard.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class User extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String username; + + @Column(nullable = false, unique = true) + private String nickname; + + @OneToOne + @JoinColumn(name = "auth_user_id") + private AuthUser authUser; + + @Builder + private User(String username, String nickname, AuthUser authUser) { + this.username = username; + this.nickname = nickname; + this.authUser = authUser; + } +} diff --git a/backend-board/src/main/java/com/backendboard/entity/type/UserRole.java b/backend-board/src/main/java/com/backendboard/entity/type/UserRole.java new file mode 100644 index 0000000..ce7dff3 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/entity/type/UserRole.java @@ -0,0 +1,15 @@ +package com.backendboard.entity.type; + +import lombok.Getter; + +@Getter +public enum UserRole { + ADMIN("ROLE_ADMIN"), + USER("ROLE_USER"); + + private final String value; + + UserRole(String value) { + this.value = value; + } +} From 145f39904efdf53ec2c3ee31bceace106c6b68e1 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Mon, 31 Mar 2025 18:09:30 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat:=20checkstyle=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-board/build.gradle | 52 ++- backend-board/naver-checkstyle-rules.xml | 440 ++++++++++++++++++ .../naver-checkstyle-suppressions.xml | 7 + backend-board/naver-intellij-formatter.xml | 62 +++ 4 files changed, 539 insertions(+), 22 deletions(-) create mode 100644 backend-board/naver-checkstyle-rules.xml create mode 100644 backend-board/naver-checkstyle-suppressions.xml create mode 100644 backend-board/naver-intellij-formatter.xml diff --git a/backend-board/build.gradle b/backend-board/build.gradle index c11768f..ce6b122 100644 --- a/backend-board/build.gradle +++ b/backend-board/build.gradle @@ -1,42 +1,50 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.4.4' - id 'io.spring.dependency-management' version '1.1.7' + id 'java' + id 'org.springframework.boot' version '3.4.4' + id 'io.spring.dependency-management' version '1.1.7' + id 'checkstyle' +} + +checkstyle { + maxWarnings = 0 + configFile = file("${rootDir}/naver-checkstyle-rules.xml") + configProperties = ["suppressionFile": "${rootDir}/naver-checkstyle-suppressions.xml"] + toolVersion = "10.21.3" } group = 'com' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(21) - } + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - runtimeOnly 'com.mysql:mysql-connector-j' - implementation 'org.springframework.boot:spring-boot-starter-data-redis' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.security:spring-security-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + runtimeOnly 'com.mysql:mysql-connector-j' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.security:spring-security-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } diff --git a/backend-board/naver-checkstyle-rules.xml b/backend-board/naver-checkstyle-rules.xml new file mode 100644 index 0000000..a6e5eb3 --- /dev/null +++ b/backend-board/naver-checkstyle-rules.xml @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend-board/naver-checkstyle-suppressions.xml b/backend-board/naver-checkstyle-suppressions.xml new file mode 100644 index 0000000..3f11e0c --- /dev/null +++ b/backend-board/naver-checkstyle-suppressions.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/backend-board/naver-intellij-formatter.xml b/backend-board/naver-intellij-formatter.xml new file mode 100644 index 0000000..658fc65 --- /dev/null +++ b/backend-board/naver-intellij-formatter.xml @@ -0,0 +1,62 @@ + + + From 83e3c057a37bff7f1e21287e499aa0e83611477a Mon Sep 17 00:00:00 2001 From: taehyeon Date: Mon, 31 Mar 2025 18:11:01 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20checkstyle,=20=EB=B2=A1=EC=97=94?= =?UTF-8?q?=EB=93=9C=20=EB=B9=8C=EB=93=9C=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-test.yml | 50 +++++++++++++++++++++++++++++++ .github/workflows/check-style.yml | 30 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 .github/workflows/build-test.yml create mode 100644 .github/workflows/check-style.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000..47a849a --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,50 @@ +name: ✅ Build Test +run-name: ${{ github.actor }} is Build Test 🚀 +on: + push: + branches: + - main + pull_request: + branches: + - main + +defaults: + run: + working-directory: ./backend-board + +permissions: + contents: read + +jobs: + build-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Make docker-compose.yml + run: echo "${{ secrets.DOCKER_COMPOSE_YML }}" | base64 -d > docker-compose.yml + + - name: Run docker + run: docker compose -f "docker-compose.yml" up -d mysql-potato redis-potato + + - name: Wait for MySQL + run: | + while ! docker exec mysql-potato mysqladmin ping -h localhost --silent; do + echo "Waiting for MySQL..." + sleep 2 + done + + - name: Make application.yml + run: | + cd ./src/main/resources + echo "${{ secrets.APPLICATION_YML }}" | base64 -d > application.yml + + - name: Test with Gradle + run: ./gradlew clean test + + - name: Build with Gradle + run: ./gradlew clean build -x test \ No newline at end of file diff --git a/.github/workflows/check-style.yml b/.github/workflows/check-style.yml new file mode 100644 index 0000000..675bf8f --- /dev/null +++ b/.github/workflows/check-style.yml @@ -0,0 +1,30 @@ +name: 📝 Check Style +run-name: ${{ github.actor }} is Check Style 🚀 +on: + push: + branches: + - main + pull_request: + branches: + - main + +defaults: + run: + working-directory: ./backend-board + +permissions: + contents: read + +jobs: + check-style: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + - name: Main checkstyle + run: ./gradlew --console verbose clean checkstyleMain + - name: ️Test checkstyle + run: ./gradlew --console verbose clean checkstyleTest \ No newline at end of file From 10163a19eadea1da0d26d5480929355ba202a9a0 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Mon, 31 Mar 2025 18:30:25 +0900 Subject: [PATCH 04/14] =?UTF-8?q?feat:=20swagger=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-board/build.gradle | 1 + .../global/config/SwaggerConfig.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java diff --git a/backend-board/build.gradle b/backend-board/build.gradle index ce6b122..d481acf 100644 --- a/backend-board/build.gradle +++ b/backend-board/build.gradle @@ -43,6 +43,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0' } tasks.named('test') { diff --git a/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java b/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java new file mode 100644 index 0000000..fa67f07 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java @@ -0,0 +1,27 @@ +package com.backendboard.global.config; + +import org.springframework.context.annotation.Bean; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityScheme; + +public class SwaggerConfig { + @Bean + public OpenAPI openAPI() { + SecurityScheme securityScheme = new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .name("Authorization"); + + return new OpenAPI() + .components(new Components().addSecuritySchemes("bearerAuth", securityScheme)) + .info(new Info() + .title("샌드박스 API 문서") + .description("샌드박스 API 명세서") + .version("1.0.0")); + } +} From 26d0ebacee471265953b36ebfba942d7b119a1d4 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Mon, 31 Mar 2025 21:24:28 +0900 Subject: [PATCH 05/14] =?UTF-8?q?feat:=20CustomError=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 41 +++++++++++++++++++ .../domain/user/dto/JoinRequest.java | 4 ++ .../domain/user/dto/JoinResponse.java | 4 ++ .../user/repository/UserRepository.java | 4 ++ .../domain/user/service/UserService.java | 4 ++ .../domain/user/service/UserServiceImpl.java | 7 ++++ .../global/error/CustomError.java | 22 ++++++++++ .../global/error/CustomException.java | 10 +++++ .../controller/CustomExceptionHandler.java | 16 ++++++++ .../global/error/dto/ErrorResponse.java | 22 ++++++++++ 10 files changed, 134 insertions(+) create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java create mode 100644 backend-board/src/main/java/com/backendboard/global/error/CustomError.java create mode 100644 backend-board/src/main/java/com/backendboard/global/error/CustomException.java create mode 100644 backend-board/src/main/java/com/backendboard/global/error/controller/CustomExceptionHandler.java create mode 100644 backend-board/src/main/java/com/backendboard/global/error/dto/ErrorResponse.java diff --git a/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java new file mode 100644 index 0000000..c060dd9 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java @@ -0,0 +1,41 @@ +package com.backendboard.domain.user.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.backendboard.domain.user.dto.JoinRequest; +import com.backendboard.domain.user.dto.JoinResponse; +import com.backendboard.domain.user.service.UserService; +import com.backendboard.global.error.dto.ErrorResponse; + +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 jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@Tag(name = "회원", description = "회원 관련 API") +@RestController +@RequiredArgsConstructor +public class UserController { + private final UserService userService; + + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "201 성공", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = JoinResponse.class))), + @ApiResponse(responseCode = "UR100", description = "403 아이디가 중복입니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "UR101", description = "403 닉네임이 중복입니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), + }) + @PostMapping("/join") + public ResponseEntity join(@RequestBody @Valid JoinRequest request) { + JoinResponse response = userService.joinProcess(request); + return ResponseEntity.status(HttpStatus.CREATED).body(response); + } +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java new file mode 100644 index 0000000..5bf01ca --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java @@ -0,0 +1,4 @@ +package com.backendboard.domain.user.dto; + +public class JoinRequest { +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java new file mode 100644 index 0000000..f5eda5f --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java @@ -0,0 +1,4 @@ +package com.backendboard.domain.user.dto; + +public class JoinResponse { +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java b/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java new file mode 100644 index 0000000..51dea3d --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java @@ -0,0 +1,4 @@ +package com.backendboard.domain.user.repository; + +public interface UserRepository { +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java new file mode 100644 index 0000000..a00c2b4 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java @@ -0,0 +1,4 @@ +package com.backendboard.domain.user.service; + +public interface UserService { +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java new file mode 100644 index 0000000..956d97f --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java @@ -0,0 +1,7 @@ +package com.backendboard.domain.user.service; + +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl implements UserService{ +} diff --git a/backend-board/src/main/java/com/backendboard/global/error/CustomError.java b/backend-board/src/main/java/com/backendboard/global/error/CustomError.java new file mode 100644 index 0000000..3db4472 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/error/CustomError.java @@ -0,0 +1,22 @@ +package com.backendboard.global.error; + +import org.springframework.http.HttpStatus; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum CustomError { + //인증 유저 에러 + AUTH_USER_NOT_FOUND_ID(HttpStatus.NOT_FOUND, "AU100", "존재하지 않는 아이디 입니다."), + + //유저 에러 + USER_DUPLICATION_ID(HttpStatus.FORBIDDEN, "UR100", "중복된 아이디 입니다."), + USER_DUPLICATION_NICKNAME(HttpStatus.FORBIDDEN, "UR101", "중복된 닉네임 입니다."), + USER_NOT_MATCH(HttpStatus.FORBIDDEN, "UR102", "작성자가 일치하지 않습니다."); + + private final HttpStatus status; + private final String code; + private final String message; +} diff --git a/backend-board/src/main/java/com/backendboard/global/error/CustomException.java b/backend-board/src/main/java/com/backendboard/global/error/CustomException.java new file mode 100644 index 0000000..5b6f68b --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/error/CustomException.java @@ -0,0 +1,10 @@ +package com.backendboard.global.error; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class CustomException extends RuntimeException { + private final CustomError error; +} diff --git a/backend-board/src/main/java/com/backendboard/global/error/controller/CustomExceptionHandler.java b/backend-board/src/main/java/com/backendboard/global/error/controller/CustomExceptionHandler.java new file mode 100644 index 0000000..2e7c7b5 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/error/controller/CustomExceptionHandler.java @@ -0,0 +1,16 @@ +package com.backendboard.global.error.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import com.backendboard.global.error.CustomException; +import com.backendboard.global.error.dto.ErrorResponse; + +@ControllerAdvice +public class CustomExceptionHandler { + @ExceptionHandler(CustomException.class) + protected ResponseEntity handleCustomException(final CustomException exception) { + return ErrorResponse.toResponseEntity(exception); + } +} diff --git a/backend-board/src/main/java/com/backendboard/global/error/dto/ErrorResponse.java b/backend-board/src/main/java/com/backendboard/global/error/dto/ErrorResponse.java new file mode 100644 index 0000000..34ee24e --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/error/dto/ErrorResponse.java @@ -0,0 +1,22 @@ +package com.backendboard.global.error.dto; + +import org.springframework.http.ResponseEntity; + +import com.backendboard.global.error.CustomException; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Schema(description = "에러 응답 DTO") +@Getter +@AllArgsConstructor +public class ErrorResponse { + @Schema(description = "에러 메시지", example = "에러가 발생했습니다.") + private final String message; + + public static ResponseEntity toResponseEntity(final CustomException exception) { + return ResponseEntity.status(exception.getError().getStatus()) + .body(new ErrorResponse(exception.getError().getMessage())); + } +} From 72f45afdf0cd54362692009ff8319de9d31c297e Mon Sep 17 00:00:00 2001 From: taehyeon Date: Mon, 31 Mar 2025 21:29:55 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat:=20SecurityConfig=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/SecurityConfig.java | 47 +++++++++++++++++++ .../global/config/SwaggerConfig.java | 2 + 2 files changed, 49 insertions(+) create mode 100644 backend-board/src/main/java/com/backendboard/global/config/SecurityConfig.java diff --git a/backend-board/src/main/java/com/backendboard/global/config/SecurityConfig.java b/backend-board/src/main/java/com/backendboard/global/config/SecurityConfig.java new file mode 100644 index 0000000..e14fa6f --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/config/SecurityConfig.java @@ -0,0 +1,47 @@ +package com.backendboard.global.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import lombok.RequiredArgsConstructor; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class SecurityConfig { + private final AuthenticationConfiguration authenticationConfiguration; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + return http + .csrf(AbstractHttpConfigurer::disable) + .formLogin(AbstractHttpConfigurer::disable) + .authorizeHttpRequests((auth) -> auth + .requestMatchers("/login", "/join", "/swagger-ui/**", "/swagger-resources/**", + "/v3/api-docs/**") + .permitAll() + .anyRequest() + .authenticated()) + .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .build(); + } + + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { + return configuration.getAuthenticationManager(); + } +} diff --git a/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java b/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java index fa67f07..6c0a6b2 100644 --- a/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java +++ b/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java @@ -1,12 +1,14 @@ package com.backendboard.global.config; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityScheme; +@Configuration public class SwaggerConfig { @Bean public OpenAPI openAPI() { From 39e7aa964ae2fdbc5e30b22fa6a2eb9f2ff6bb1b Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 17:41:15 +0900 Subject: [PATCH 07/14] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/dto/JoinRequest.java | 29 ++++++++++++ .../domain/user/dto/JoinResponse.java | 34 ++++++++++++++ .../user/entitiy}/AuthUser.java | 7 +-- .../{entity => domain/user/entitiy}/User.java | 4 +- .../user/entitiy}/type/UserRole.java | 2 +- .../user/repository/AuthUserRepository.java | 11 +++++ .../user/repository/UserRepository.java | 9 +++- .../domain/user/service/UserService.java | 4 ++ .../domain/user/service/UserServiceImpl.java | 46 ++++++++++++++++++- .../com/backendboard/entity/BaseEntity.java | 4 -- .../global/entity/BaseEntity.java | 20 ++++++++ 11 files changed, 159 insertions(+), 11 deletions(-) rename backend-board/src/main/java/com/backendboard/{entity => domain/user/entitiy}/AuthUser.java (83%) rename backend-board/src/main/java/com/backendboard/{entity => domain/user/entitiy}/User.java (90%) rename backend-board/src/main/java/com/backendboard/{entity => domain/user/entitiy}/type/UserRole.java (78%) create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/repository/AuthUserRepository.java delete mode 100644 backend-board/src/main/java/com/backendboard/entity/BaseEntity.java create mode 100644 backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java index 5bf01ca..ed70f99 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java @@ -1,4 +1,33 @@ package com.backendboard.domain.user.dto; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Schema(description = "회원가입 요청 DTO") +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class JoinRequest { + @Schema(description = "로그인 아이디", example = "user") + @NotBlank + @Size(max = 30) + private String loginId; + + @Schema(description = "로그인 비밀번호", example = "1234") + @NotBlank + @Size(max = 30) + private String password; + + @Schema(description = "유저의 이름", example = "감자") + @NotBlank + @Size(max = 30) + private String username; + + @Schema(description = "닉네임", example = "배고픈감자") + @NotBlank + @Size(max = 30) + private String nickname; } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java index f5eda5f..859f5f5 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java @@ -1,4 +1,38 @@ package com.backendboard.domain.user.dto; +import com.backendboard.domain.user.entitiy.User; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Schema(description = "회원가입 응답 DTO") +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class JoinResponse { + @Schema(description = "회원 고유 번호", example = "1") + private Long id; + + @Schema(description = "로그인 아이디", example = "user") + private String loginId; + + @Schema(description = "닉네임", example = "배고픈감자") + private String nickname; + + @Builder + private JoinResponse(Long id, String loginId, String nickname) { + this.id = id; + this.loginId = loginId; + this.nickname = nickname; + } + + public static JoinResponse toDto(User user) { + return builder() + .id(user.getId()) + .loginId(user.getAuthUser().getUsername()) + .nickname(user.getNickname()) + .build(); + } } diff --git a/backend-board/src/main/java/com/backendboard/entity/AuthUser.java b/backend-board/src/main/java/com/backendboard/domain/user/entitiy/AuthUser.java similarity index 83% rename from backend-board/src/main/java/com/backendboard/entity/AuthUser.java rename to backend-board/src/main/java/com/backendboard/domain/user/entitiy/AuthUser.java index 5e5bc3a..c0ba726 100644 --- a/backend-board/src/main/java/com/backendboard/entity/AuthUser.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/entitiy/AuthUser.java @@ -1,6 +1,7 @@ -package com.backendboard.entity; +package com.backendboard.domain.user.entitiy; -import com.backendboard.entity.type.UserRole; +import com.backendboard.domain.user.entitiy.type.UserRole; +import com.backendboard.global.entity.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -28,7 +29,7 @@ public class AuthUser extends BaseEntity { private String password; @Enumerated(EnumType.STRING) - @Column(nullable = false, columnDefinition = "VARCHAR(20)") + @Column(nullable = false, columnDefinition = "VARCHAR(100)") private UserRole role; private boolean status; diff --git a/backend-board/src/main/java/com/backendboard/entity/User.java b/backend-board/src/main/java/com/backendboard/domain/user/entitiy/User.java similarity index 90% rename from backend-board/src/main/java/com/backendboard/entity/User.java rename to backend-board/src/main/java/com/backendboard/domain/user/entitiy/User.java index 52fbc9e..6f31544 100644 --- a/backend-board/src/main/java/com/backendboard/entity/User.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/entitiy/User.java @@ -1,4 +1,6 @@ -package com.backendboard.entity; +package com.backendboard.domain.user.entitiy; + +import com.backendboard.global.entity.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/backend-board/src/main/java/com/backendboard/entity/type/UserRole.java b/backend-board/src/main/java/com/backendboard/domain/user/entitiy/type/UserRole.java similarity index 78% rename from backend-board/src/main/java/com/backendboard/entity/type/UserRole.java rename to backend-board/src/main/java/com/backendboard/domain/user/entitiy/type/UserRole.java index ce7dff3..e84309a 100644 --- a/backend-board/src/main/java/com/backendboard/entity/type/UserRole.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/entitiy/type/UserRole.java @@ -1,4 +1,4 @@ -package com.backendboard.entity.type; +package com.backendboard.domain.user.entitiy.type; import lombok.Getter; diff --git a/backend-board/src/main/java/com/backendboard/domain/user/repository/AuthUserRepository.java b/backend-board/src/main/java/com/backendboard/domain/user/repository/AuthUserRepository.java new file mode 100644 index 0000000..2911908 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/repository/AuthUserRepository.java @@ -0,0 +1,11 @@ +package com.backendboard.domain.user.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.backendboard.domain.user.entitiy.AuthUser; + +@Repository +public interface AuthUserRepository extends JpaRepository { + boolean existsByUsername(String username); +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java b/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java index 51dea3d..be5447e 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/repository/UserRepository.java @@ -1,4 +1,11 @@ package com.backendboard.domain.user.repository; -public interface UserRepository { +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.backendboard.domain.user.entitiy.User; + +@Repository +public interface UserRepository extends JpaRepository { + boolean existsByNickname(String nickName); } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java index a00c2b4..d8ddc25 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java @@ -1,4 +1,8 @@ package com.backendboard.domain.user.service; +import com.backendboard.domain.user.dto.JoinRequest; +import com.backendboard.domain.user.dto.JoinResponse; + public interface UserService { + JoinResponse joinProcess(JoinRequest request); } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java index 956d97f..6d8eaaa 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java @@ -1,7 +1,51 @@ package com.backendboard.domain.user.service; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.backendboard.domain.user.dto.JoinRequest; +import com.backendboard.domain.user.dto.JoinResponse; +import com.backendboard.domain.user.entitiy.AuthUser; +import com.backendboard.domain.user.entitiy.User; +import com.backendboard.domain.user.entitiy.type.UserRole; +import com.backendboard.domain.user.repository.AuthUserRepository; +import com.backendboard.domain.user.repository.UserRepository; +import com.backendboard.global.error.CustomError; +import com.backendboard.global.error.CustomException; + +import lombok.RequiredArgsConstructor; @Service -public class UserServiceImpl implements UserService{ +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + private final AuthUserRepository authUserRepository; + private final BCryptPasswordEncoder bCryptPasswordEncoder; + + @Transactional + @Override + public JoinResponse joinProcess(JoinRequest request) { + validateDuplicationId(request.getLoginId()); + validateDuplicationNickname(request.getNickname()); + + AuthUser authUser = new AuthUser(request.getLoginId(), + bCryptPasswordEncoder.encode(request.getPassword()), UserRole.USER); + User user = authUser.createUser(request.getUsername(), request.getNickname()); + authUserRepository.save(authUser); + userRepository.save(user); + return JoinResponse.toDto(user); + } + + public void validateDuplicationNickname(String nickname) { + if (userRepository.existsByNickname(nickname)) { + throw new CustomException(CustomError.USER_DUPLICATION_NICKNAME); + } + } + + public void validateDuplicationId(String loginId) { + if (authUserRepository.existsByUsername(loginId)) { + throw new CustomException(CustomError.USER_DUPLICATION_ID); + } + } } diff --git a/backend-board/src/main/java/com/backendboard/entity/BaseEntity.java b/backend-board/src/main/java/com/backendboard/entity/BaseEntity.java deleted file mode 100644 index 426f01c..0000000 --- a/backend-board/src/main/java/com/backendboard/entity/BaseEntity.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.backendboard.entity; - -public class BaseEntity { -} diff --git a/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java b/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java new file mode 100644 index 0000000..5617c54 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java @@ -0,0 +1,20 @@ +package com.backendboard.global.entity; + +import java.time.LocalDateTime; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class BaseEntity { + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime lastModifiedAt; +} From 15029224536b81e3bf307a3b73e022aa0401ae87 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 18:55:44 +0900 Subject: [PATCH 08/14] =?UTF-8?q?test:=20AuthUserRepository=20username=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/AuthUserRepositoryTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java diff --git a/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java b/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java new file mode 100644 index 0000000..5240208 --- /dev/null +++ b/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java @@ -0,0 +1,39 @@ +package com.backendboard.domain.user.repository; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import com.backendboard.domain.user.entitiy.AuthUser; +import com.backendboard.domain.user.entitiy.type.UserRole; + +@DataJpaTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class AuthUserRepositoryTest { + @Autowired + AuthUserRepository authUserRepository; + + @Nested + @DisplayName("existsByUsername 메서드 테스트") + class ExistsByUsernameMethodTest { + @Test + @DisplayName("username이 중복이면 true 반환") + void returnsTrueWhenUsernameExists() { + //given + String username = "potato"; + AuthUser authUser = new AuthUser(username, "1234", UserRole.USER); + authUserRepository.save(authUser); + + //when + boolean exists = authUserRepository.existsByUsername(username); + + //then + Assertions.assertThat(exists).isTrue(); + } + } + +} From 9a1a587fdee9860e76f292f62af51db9c4f713e6 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 19:29:22 +0900 Subject: [PATCH 09/14] =?UTF-8?q?test:=20UserServiceImplTest=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=EA=B2=80=EC=A6=9D=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-board/build.gradle | 4 + .../domain/user/dto/JoinRequest.java | 10 ++ .../repository/AuthUserRepositoryTest.java | 6 +- .../user/service/UserServiceImplTest.java | 153 ++++++++++++++++++ 4 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java diff --git a/backend-board/build.gradle b/backend-board/build.gradle index d481acf..7888d43 100644 --- a/backend-board/build.gradle +++ b/backend-board/build.gradle @@ -49,3 +49,7 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +test { + jvmArgs = ["-javaagent:${configurations.testRuntimeClasspath.find { it.name.contains('mockito-core') }}"] +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java index ed70f99..2bc3e7f 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinRequest.java @@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,6 +12,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class JoinRequest { + @Schema(description = "로그인 아이디", example = "user") @NotBlank @Size(max = 30) @@ -30,4 +32,12 @@ public class JoinRequest { @NotBlank @Size(max = 30) private String nickname; + + @Builder + private JoinRequest(String loginId, String password, String username, String nickname) { + this.loginId = loginId; + this.password = password; + this.username = username; + this.nickname = nickname; + } } diff --git a/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java b/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java index 5240208..8152ca1 100644 --- a/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java +++ b/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java @@ -23,15 +23,15 @@ class ExistsByUsernameMethodTest { @Test @DisplayName("username이 중복이면 true 반환") void returnsTrueWhenUsernameExists() { - //given + //Given String username = "potato"; AuthUser authUser = new AuthUser(username, "1234", UserRole.USER); authUserRepository.save(authUser); - //when + //When boolean exists = authUserRepository.existsByUsername(username); - //then + //Then Assertions.assertThat(exists).isTrue(); } } diff --git a/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java b/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java new file mode 100644 index 0000000..bcb7d60 --- /dev/null +++ b/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java @@ -0,0 +1,153 @@ +package com.backendboard.domain.user.service; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import com.backendboard.domain.user.dto.JoinRequest; +import com.backendboard.domain.user.dto.JoinResponse; +import com.backendboard.domain.user.entitiy.AuthUser; +import com.backendboard.domain.user.entitiy.User; +import com.backendboard.domain.user.entitiy.type.UserRole; +import com.backendboard.domain.user.repository.AuthUserRepository; +import com.backendboard.domain.user.repository.UserRepository; +import com.backendboard.global.error.CustomError; +import com.backendboard.global.error.CustomException; + +@ExtendWith(MockitoExtension.class) +class UserServiceImplTest { + @Mock + private UserRepository userRepository; + + @Mock + private AuthUserRepository authUserRepository; + + @Mock + private BCryptPasswordEncoder bCryptPasswordEncoder; + + @InjectMocks + private UserServiceImpl userService; + + @Nested + @DisplayName("회원가입 프로세스 테스트") + class JoinProcessTest { + + private JoinRequest joinRequest; + private User user; + private AuthUser authUser; + + @BeforeEach + void setUp() { + joinRequest = JoinRequest.builder() + .loginId("testId") + .password("1234") + .username("potato") + .nickname("testNick") + .build(); + authUser = new AuthUser("potato", "encoded_password", UserRole.USER); + user = authUser.createUser("testId", "testNick"); + } + + @Test + @DisplayName("회원가입 요청 성공") + void success() { + // Given + when(userRepository.existsByNickname(anyString())).thenReturn(false); + when(authUserRepository.existsByUsername(anyString())).thenReturn(false); + when(bCryptPasswordEncoder.encode(anyString())).thenReturn("encoded_password"); + + when(userRepository.save(any(User.class))).thenReturn(user); + when(authUserRepository.save(any(AuthUser.class))).thenReturn(authUser); + + // When + JoinResponse response = userService.joinProcess(joinRequest); + + // Then + verify(userRepository).existsByNickname("testNick"); + verify(authUserRepository).existsByUsername("testId"); + verify(bCryptPasswordEncoder).encode("1234"); + verify(userRepository).save(any(User.class)); + verify(authUserRepository).save(any(AuthUser.class)); + + assertThat(response).isNotNull(); + } + + @Test + @DisplayName("중복된 아이디가 있으면 예외 발생") + void throwsExceptionWhenIdDuplicated() { + // Given + when(authUserRepository.existsByUsername(anyString())).thenReturn(true); + + // When & Then + CustomException exception = assertThrows(CustomException.class, + () -> userService.joinProcess(joinRequest)); + + assertThat(exception.getError()).isEqualTo(CustomError.USER_DUPLICATION_ID); + verify(authUserRepository).existsByUsername("testId"); + verify(userRepository, never()).existsByNickname(anyString()); + verify(authUserRepository, never()).save(any()); + verify(userRepository, never()).save(any()); + } + + @Test + @DisplayName("중복된 닉네임이 있으면 예외 발생") + void throwsExceptionWhenNicknameDuplicated() { + // Given + when(authUserRepository.existsByUsername(anyString())).thenReturn(false); + when(userRepository.existsByNickname(anyString())).thenReturn(true); + + // When & Then + CustomException exception = assertThrows(CustomException.class, + () -> userService.joinProcess(joinRequest)); + + assertThat(exception.getError()).isEqualTo(CustomError.USER_DUPLICATION_NICKNAME); + verify(authUserRepository).existsByUsername("testId"); + verify(userRepository).existsByNickname("testNick"); + verify(authUserRepository, never()).save(any()); + verify(userRepository, never()).save(any()); + } + } + + @Nested + @DisplayName("검증 테스트") + class ValidationTest { + + @Test + @DisplayName("중복된 닉네임 검증 시 예외 발생") + void validateDuplicationNickname() { + // Given + String nickname = "testNick"; + when(userRepository.existsByNickname(nickname)).thenReturn(true); + + // When & Then + CustomException exception = assertThrows(CustomException.class, + () -> userService.validateDuplicationNickname(nickname)); + + assertThat(exception.getError()).isEqualTo(CustomError.USER_DUPLICATION_NICKNAME); + } + + @Test + @DisplayName("중복된 아이디 검증 시 예외 발생") + void validateDuplicationId() { + // Given + String loginId = "testId"; + when(authUserRepository.existsByUsername(loginId)).thenReturn(true); + + // When & Then + CustomException exception = assertThrows(CustomException.class, + () -> userService.validateDuplicationId(loginId)); + + assertThat(exception.getError()).isEqualTo(CustomError.USER_DUPLICATION_ID); + } + } +} From a8614c9d2256ac4f00cee64ec9ded315effb1b53 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 21:04:40 +0900 Subject: [PATCH 10/14] =?UTF-8?q?test:=20UserController=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=ED=86=B5=ED=95=A9=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 ++ backend-board/.gitignore | 1 + backend-board/build.gradle | 2 + .../domain/user/dto/JoinResponse.java | 7 +- .../global/error/CustomError.java | 3 +- .../domain/user/UserMockData.java | 29 ++++++ .../user/controller/UserControllerTest.java | 94 +++++++++++++++++++ .../repository/AuthUserRepositoryTest.java | 6 +- .../user/service/UserServiceImplTest.java | 22 ++--- 9 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 backend-board/src/test/java/com/backendboard/domain/user/UserMockData.java create mode 100644 backend-board/src/test/java/com/backendboard/domain/user/controller/UserControllerTest.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/backend-board/.gitignore b/backend-board/.gitignore index 9fde395..4347661 100644 --- a/backend-board/.gitignore +++ b/backend-board/.gitignore @@ -26,6 +26,7 @@ out/ !**/src/main/**/out/ !**/src/test/**/out/ /src/main/resources/application.yml +/src/test/resources/application.yml ### NetBeans ### /nbproject/private/ diff --git a/backend-board/build.gradle b/backend-board/build.gradle index 7888d43..014ad9c 100644 --- a/backend-board/build.gradle +++ b/backend-board/build.gradle @@ -40,6 +40,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java index 859f5f5..758b99d 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/JoinResponse.java @@ -18,13 +18,17 @@ public class JoinResponse { @Schema(description = "로그인 아이디", example = "user") private String loginId; + @Schema(description = "유저의 이름", example = "감자") + private String username; + @Schema(description = "닉네임", example = "배고픈감자") private String nickname; @Builder - private JoinResponse(Long id, String loginId, String nickname) { + private JoinResponse(Long id, String loginId, String username, String nickname) { this.id = id; this.loginId = loginId; + this.username = username; this.nickname = nickname; } @@ -32,6 +36,7 @@ public static JoinResponse toDto(User user) { return builder() .id(user.getId()) .loginId(user.getAuthUser().getUsername()) + .username(user.getUsername()) .nickname(user.getNickname()) .build(); } diff --git a/backend-board/src/main/java/com/backendboard/global/error/CustomError.java b/backend-board/src/main/java/com/backendboard/global/error/CustomError.java index 3db4472..45794eb 100644 --- a/backend-board/src/main/java/com/backendboard/global/error/CustomError.java +++ b/backend-board/src/main/java/com/backendboard/global/error/CustomError.java @@ -13,8 +13,7 @@ public enum CustomError { //유저 에러 USER_DUPLICATION_ID(HttpStatus.FORBIDDEN, "UR100", "중복된 아이디 입니다."), - USER_DUPLICATION_NICKNAME(HttpStatus.FORBIDDEN, "UR101", "중복된 닉네임 입니다."), - USER_NOT_MATCH(HttpStatus.FORBIDDEN, "UR102", "작성자가 일치하지 않습니다."); + USER_DUPLICATION_NICKNAME(HttpStatus.FORBIDDEN, "UR101", "중복된 닉네임 입니다."); private final HttpStatus status; private final String code; diff --git a/backend-board/src/test/java/com/backendboard/domain/user/UserMockData.java b/backend-board/src/test/java/com/backendboard/domain/user/UserMockData.java new file mode 100644 index 0000000..6cd18f4 --- /dev/null +++ b/backend-board/src/test/java/com/backendboard/domain/user/UserMockData.java @@ -0,0 +1,29 @@ +package com.backendboard.domain.user; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Component; + +import com.backendboard.domain.user.dto.JoinRequest; +import com.backendboard.domain.user.entitiy.AuthUser; +import com.backendboard.domain.user.entitiy.User; +import com.backendboard.domain.user.entitiy.type.UserRole; +import com.backendboard.domain.user.repository.AuthUserRepository; +import com.backendboard.domain.user.repository.UserRepository; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class UserMockData { + private final AuthUserRepository authUserRepository; + private final UserRepository userRepository; + private final BCryptPasswordEncoder bCryptPasswordEncoder; + + public User createUserAndAuthUser(JoinRequest request) { + AuthUser authUser = new AuthUser(request.getLoginId(), + bCryptPasswordEncoder.encode(request.getPassword()), UserRole.USER); + User user = authUser.createUser(request.getUsername(), request.getNickname()); + authUserRepository.save(authUser); + return userRepository.save(user); + } +} diff --git a/backend-board/src/test/java/com/backendboard/domain/user/controller/UserControllerTest.java b/backend-board/src/test/java/com/backendboard/domain/user/controller/UserControllerTest.java new file mode 100644 index 0000000..fc82887 --- /dev/null +++ b/backend-board/src/test/java/com/backendboard/domain/user/controller/UserControllerTest.java @@ -0,0 +1,94 @@ +package com.backendboard.domain.user.controller; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.backendboard.domain.user.UserMockData; +import com.backendboard.domain.user.dto.JoinRequest; +import com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +class UserControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private UserMockData userMockData; + + @Nested + @DisplayName("회원가입 API 테스트") + class JoinTest { + private JoinRequest joinRequest; + + @BeforeEach + void setUp() { + joinRequest = JoinRequest.builder() + .loginId("testId") + .password("1234") + .username("potato") + .nickname("testNick") + .build(); + } + + @Transactional + @Test + @DisplayName("성공 201") + void success() throws Exception { + // given + + // when & then + mockMvc.perform(post("/join") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(joinRequest))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.loginId").value("testId")) + .andExpect(jsonPath("$.username").value("potato")) + .andExpect(jsonPath("$.nickname").value("testNick")); + } + + @Transactional + @Test + @DisplayName("아이디 중복 실패 403") + void duplicateIdFailure() throws Exception { + // given + userMockData.createUserAndAuthUser(joinRequest); + + // when & then + mockMvc.perform(post("/join") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(joinRequest))) + .andExpect(status().isForbidden()); + } + + @Transactional + @Test + @DisplayName("닉네임 중복 실패 403") + void duplicateNicknameFailure() throws Exception { + // given + userMockData.createUserAndAuthUser(joinRequest); + + // when & then + mockMvc.perform(post("/join") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(joinRequest))) + .andExpect(status().isForbidden()); + } + + } +} diff --git a/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java b/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java index 8152ca1..5240208 100644 --- a/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java +++ b/backend-board/src/test/java/com/backendboard/domain/user/repository/AuthUserRepositoryTest.java @@ -23,15 +23,15 @@ class ExistsByUsernameMethodTest { @Test @DisplayName("username이 중복이면 true 반환") void returnsTrueWhenUsernameExists() { - //Given + //given String username = "potato"; AuthUser authUser = new AuthUser(username, "1234", UserRole.USER); authUserRepository.save(authUser); - //When + //when boolean exists = authUserRepository.existsByUsername(username); - //Then + //then Assertions.assertThat(exists).isTrue(); } } diff --git a/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java b/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java index bcb7d60..76dd8c8 100644 --- a/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java +++ b/backend-board/src/test/java/com/backendboard/domain/user/service/UserServiceImplTest.java @@ -61,7 +61,7 @@ void setUp() { @Test @DisplayName("회원가입 요청 성공") void success() { - // Given + // given when(userRepository.existsByNickname(anyString())).thenReturn(false); when(authUserRepository.existsByUsername(anyString())).thenReturn(false); when(bCryptPasswordEncoder.encode(anyString())).thenReturn("encoded_password"); @@ -69,10 +69,10 @@ void success() { when(userRepository.save(any(User.class))).thenReturn(user); when(authUserRepository.save(any(AuthUser.class))).thenReturn(authUser); - // When + // when JoinResponse response = userService.joinProcess(joinRequest); - // Then + // then verify(userRepository).existsByNickname("testNick"); verify(authUserRepository).existsByUsername("testId"); verify(bCryptPasswordEncoder).encode("1234"); @@ -85,10 +85,10 @@ void success() { @Test @DisplayName("중복된 아이디가 있으면 예외 발생") void throwsExceptionWhenIdDuplicated() { - // Given + // given when(authUserRepository.existsByUsername(anyString())).thenReturn(true); - // When & Then + // when & then CustomException exception = assertThrows(CustomException.class, () -> userService.joinProcess(joinRequest)); @@ -102,11 +102,11 @@ void throwsExceptionWhenIdDuplicated() { @Test @DisplayName("중복된 닉네임이 있으면 예외 발생") void throwsExceptionWhenNicknameDuplicated() { - // Given + // given when(authUserRepository.existsByUsername(anyString())).thenReturn(false); when(userRepository.existsByNickname(anyString())).thenReturn(true); - // When & Then + // when & then CustomException exception = assertThrows(CustomException.class, () -> userService.joinProcess(joinRequest)); @@ -125,11 +125,11 @@ class ValidationTest { @Test @DisplayName("중복된 닉네임 검증 시 예외 발생") void validateDuplicationNickname() { - // Given + // given String nickname = "testNick"; when(userRepository.existsByNickname(nickname)).thenReturn(true); - // When & Then + // when & then CustomException exception = assertThrows(CustomException.class, () -> userService.validateDuplicationNickname(nickname)); @@ -139,11 +139,11 @@ void validateDuplicationNickname() { @Test @DisplayName("중복된 아이디 검증 시 예외 발생") void validateDuplicationId() { - // Given + // given String loginId = "testId"; when(authUserRepository.existsByUsername(loginId)).thenReturn(true); - // When & Then + // when & then CustomException exception = assertThrows(CustomException.class, () -> userService.validateDuplicationId(loginId)); From befc20cb7816adce93d20ae9fac9c874266b3e4f Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 21:12:10 +0900 Subject: [PATCH 11/14] =?UTF-8?q?feat:=20github=20action=20=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=ED=94=8C=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-build-test.yml | 50 +++++++++++++++++++ ...heck-style.yml => backend-check-style.yml} | 0 2 files changed, 50 insertions(+) create mode 100644 .github/workflows/backend-build-test.yml rename .github/workflows/{check-style.yml => backend-check-style.yml} (100%) diff --git a/.github/workflows/backend-build-test.yml b/.github/workflows/backend-build-test.yml new file mode 100644 index 0000000..b48d677 --- /dev/null +++ b/.github/workflows/backend-build-test.yml @@ -0,0 +1,50 @@ +name: ✅ Build Test +run-name: ${{ github.actor }} is Build Test 🚀 +on: + push: + branches: + - main + pull_request: + branches: + - main + +defaults: + run: + working-directory: ./backend-board + +permissions: + contents: read + +jobs: + build-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Make docker-compose.yml + run: echo "${{ secrets.DOCKER_COMPOSE_YML }}" | base64 -d > docker-compose.yml + + - name: Run docker + run: docker compose -f "docker-compose.yml" up -d mysql-sandbox redis-sandbox + + - name: Wait for MySQL + run: | + while ! docker exec mysql-potato mysqladmin ping -h localhost --silent; do + echo "Waiting for MySQL..." + sleep 2 + done + + - name: Make application.yml + run: | + cd ./src/main/resources + echo "${{ secrets.APPLICATION_YML }}" | base64 -d > application.yml + + - name: Test with Gradle + run: ./gradlew clean test + + - name: Build with Gradle + run: ./gradlew clean build -x test diff --git a/.github/workflows/check-style.yml b/.github/workflows/backend-check-style.yml similarity index 100% rename from .github/workflows/check-style.yml rename to .github/workflows/backend-check-style.yml From c9d81fc8d780715fc2c9f38a41f3007ee9de6a22 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 21:13:40 +0900 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20github=20action=20=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=ED=94=8C=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-test.yml | 50 -------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 .github/workflows/build-test.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml deleted file mode 100644 index 47a849a..0000000 --- a/.github/workflows/build-test.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: ✅ Build Test -run-name: ${{ github.actor }} is Build Test 🚀 -on: - push: - branches: - - main - pull_request: - branches: - - main - -defaults: - run: - working-directory: ./backend-board - -permissions: - contents: read - -jobs: - build-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '21' - - - name: Make docker-compose.yml - run: echo "${{ secrets.DOCKER_COMPOSE_YML }}" | base64 -d > docker-compose.yml - - - name: Run docker - run: docker compose -f "docker-compose.yml" up -d mysql-potato redis-potato - - - name: Wait for MySQL - run: | - while ! docker exec mysql-potato mysqladmin ping -h localhost --silent; do - echo "Waiting for MySQL..." - sleep 2 - done - - - name: Make application.yml - run: | - cd ./src/main/resources - echo "${{ secrets.APPLICATION_YML }}" | base64 -d > application.yml - - - name: Test with Gradle - run: ./gradlew clean test - - - name: Build with Gradle - run: ./gradlew clean build -x test \ No newline at end of file From 5346082f52aedd897bfe7635e2412df80a17f8fb Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 21:14:49 +0900 Subject: [PATCH 13/14] =?UTF-8?q?feat:=20github=20action=20=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=ED=94=8C=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backend-build-test.yml b/.github/workflows/backend-build-test.yml index b48d677..97b1338 100644 --- a/.github/workflows/backend-build-test.yml +++ b/.github/workflows/backend-build-test.yml @@ -33,7 +33,7 @@ jobs: - name: Wait for MySQL run: | - while ! docker exec mysql-potato mysqladmin ping -h localhost --silent; do + while ! docker exec mysql-sandbox mysqladmin ping -h localhost --silent; do echo "Waiting for MySQL..." sleep 2 done From 7cc0a35b1a0c31e3997db05978fddeb26f8f8b09 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 1 Apr 2025 21:19:49 +0900 Subject: [PATCH 14/14] =?UTF-8?q?feat:=20github=20action=20=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=ED=94=8C=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-build-test.yml | 3 ++- .github/workflows/backend-check-style.yml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backend-build-test.yml b/.github/workflows/backend-build-test.yml index 97b1338..22778c7 100644 --- a/.github/workflows/backend-build-test.yml +++ b/.github/workflows/backend-build-test.yml @@ -1,4 +1,4 @@ -name: ✅ Build Test +name: ✅ Backend Build Test run-name: ${{ github.actor }} is Build Test 🚀 on: push: @@ -40,6 +40,7 @@ jobs: - name: Make application.yml run: | + mkdir -p ./src/main/resources cd ./src/main/resources echo "${{ secrets.APPLICATION_YML }}" | base64 -d > application.yml diff --git a/.github/workflows/backend-check-style.yml b/.github/workflows/backend-check-style.yml index 675bf8f..b485a42 100644 --- a/.github/workflows/backend-check-style.yml +++ b/.github/workflows/backend-check-style.yml @@ -1,4 +1,4 @@ -name: 📝 Check Style +name: 📝 Backend Check Style run-name: ${{ github.actor }} is Check Style 🚀 on: push: @@ -27,4 +27,4 @@ jobs: - name: Main checkstyle run: ./gradlew --console verbose clean checkstyleMain - name: ️Test checkstyle - run: ./gradlew --console verbose clean checkstyleTest \ No newline at end of file + run: ./gradlew --console verbose clean checkstyleTest