Skip to content

Commit 3b3ef30

Browse files
authored
Merge pull request #10 from team-MoPlus/feature/#9
[feat/#9] 이메일 비밀번호 인증 필터 및 인증 provider 구현
2 parents 2292fe8 + 88c2033 commit 3b3ef30

File tree

28 files changed

+705
-191
lines changed

28 files changed

+705
-191
lines changed

.github/workflows/CI.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This workflow uses actions that are not certified by GitHub.
2+
# They are provided by a third-party and are governed by
3+
# separate terms of service, privacy policy, and support
4+
# documentation.
5+
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
6+
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
7+
8+
name: Gradle Package
9+
10+
on:
11+
pull_request:
12+
branches:
13+
- "master"
14+
- "develop"
15+
16+
jobs:
17+
build:
18+
19+
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read
22+
packages: write
23+
24+
steps:
25+
- name: checkout
26+
uses: actions/checkout@v3
27+
28+
- name: Set up JDK 17
29+
uses: actions/setup-java@v3
30+
with:
31+
java-version: '17'
32+
distribution: 'temurin'
33+
34+
35+
- name: build and test
36+
run: |
37+
chmod +x gradlew
38+
./gradlew build

build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ dependencies {
3333
testImplementation 'org.springframework.boot:spring-boot-starter-test'
3434
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
3535

36+
// Spring Security
37+
implementation 'org.springframework.boot:spring-boot-starter-security'
38+
testImplementation 'org.springframework.security:spring-security-test'
39+
3640
//db-h2
3741
implementation 'com.h2database:h2'
3842
testImplementation 'com.h2database:h2'
@@ -44,6 +48,14 @@ dependencies {
4448
//s3
4549
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
4650

51+
// JWT
52+
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
53+
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
54+
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
55+
56+
// validator
57+
implementation 'commons-validator:commons-validator:1.7'
58+
4759
}
4860

4961
tasks.named('test') {

src/main/java/com/moplus/moplus_server/MoplusServerApplication.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package com.moplus.moplus_server;
22

3-
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4-
import io.swagger.v3.oas.annotations.servers.Server;
53
import java.util.Arrays;
64
import org.springframework.boot.SpringApplication;
75
import org.springframework.boot.autoconfigure.SpringBootApplication;
86
import org.springframework.core.env.Environment;
97
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
108

11-
@OpenAPIDefinition(servers = {@Server(url = "https://dev.mopl.kr", description = "Default Server URL")})
129
@SpringBootApplication
1310
@EnableJpaAuditing
1411
public class MoplusServerApplication {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.moplus.moplus_server.domain.auth.controller;
2+
3+
import com.moplus.moplus_server.domain.auth.dto.request.AdminLoginRequest;
4+
import io.swagger.v3.oas.annotations.Operation;
5+
import io.swagger.v3.oas.annotations.headers.Header;
6+
import io.swagger.v3.oas.annotations.media.Schema;
7+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
8+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.web.bind.annotation.PostMapping;
11+
import org.springframework.web.bind.annotation.RequestBody;
12+
import org.springframework.web.bind.annotation.RequestMapping;
13+
import org.springframework.web.bind.annotation.RestController;
14+
15+
@RestController
16+
@RequestMapping("/api/v1/auth")
17+
@RequiredArgsConstructor
18+
public class AuthController {
19+
20+
@Operation(summary = "어드민 로그인", description = "아아디 패스워드 로그인 후 토큰 발급합니다.")
21+
@ApiResponses(value = {
22+
@ApiResponse(
23+
responseCode = "200",
24+
description = "로그인 성공",
25+
headers = {
26+
@Header(name = "Authorization", description = "Access Token", schema = @Schema(type = "string")),
27+
@Header(name = "RefreshToken", description = "Refresh Token", schema = @Schema(type = "string"))
28+
}
29+
),
30+
@ApiResponse(responseCode = "400", description = "잘못된 요청"),
31+
@ApiResponse(responseCode = "401", description = "인증 실패")
32+
})
33+
@PostMapping("/admin/login")
34+
public void adminLogin(
35+
@RequestBody AdminLoginRequest request
36+
) {
37+
// 실제 처리는 Security 필터에서 이루어지며, 이 메서드는 Swagger 명세용입니다.
38+
}
39+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.moplus.moplus_server.domain.auth.dto.request;
2+
3+
public record AdminLoginRequest(
4+
String email,
5+
String password
6+
) {
7+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.moplus.moplus_server.domain.member.domain;
2+
3+
import com.moplus.moplus_server.global.common.BaseEntity;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.EnumType;
7+
import jakarta.persistence.Enumerated;
8+
import jakarta.persistence.GeneratedValue;
9+
import jakarta.persistence.GenerationType;
10+
import jakarta.persistence.Id;
11+
import lombok.AccessLevel;
12+
import lombok.Builder;
13+
import lombok.Getter;
14+
import lombok.NoArgsConstructor;
15+
16+
@Getter
17+
@Entity
18+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
19+
public class Member extends BaseEntity {
20+
21+
@Id
22+
@GeneratedValue(strategy = GenerationType.IDENTITY)
23+
@Column(name = "member_id")
24+
private Long id;
25+
26+
private String email;
27+
private String password;
28+
29+
@Enumerated(EnumType.STRING)
30+
private MemberRole role;
31+
32+
@Builder
33+
public Member(String nickname, String email, String password, MemberRole role) {
34+
this.email = email;
35+
this.password = password;
36+
this.role = role;
37+
}
38+
39+
public boolean isMatchingPassword(String password) {
40+
return this.password.equals(password);
41+
}
42+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.moplus.moplus_server.domain.member.domain;
2+
3+
import java.util.Arrays;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
7+
@Getter
8+
@AllArgsConstructor
9+
public enum MemberRole {
10+
USER("ROLE_USER"),
11+
ADMIN("ROLE_ADMIN");
12+
13+
private final String value;
14+
15+
public static MemberRole findByKey(String value) {
16+
return Arrays.stream(MemberRole.values())
17+
.filter(role -> role.value.equals(value))
18+
.findFirst()
19+
.orElseThrow(() -> new IllegalArgumentException("No role with key: " + value));
20+
}
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.moplus.moplus_server.domain.member.repository;
2+
3+
import com.moplus.moplus_server.domain.member.domain.Member;
4+
import com.moplus.moplus_server.global.error.exception.ErrorCode;
5+
import com.moplus.moplus_server.global.error.exception.NotFoundException;
6+
import java.util.Optional;
7+
import org.springframework.data.jpa.repository.JpaRepository;
8+
9+
public interface MemberRepository extends JpaRepository<Member, Long> {
10+
Optional<Member> findByEmail(String email);
11+
12+
default Member findByEmailOrThrow(String email) {
13+
return findByEmail(email).orElseThrow(() -> new NotFoundException(ErrorCode.MEMBER_NOT_FOUND));
14+
}
15+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.moplus.moplus_server.domain.member.service;
2+
3+
import com.moplus.moplus_server.domain.member.domain.Member;
4+
import com.moplus.moplus_server.domain.member.repository.MemberRepository;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.stereotype.Service;
7+
import org.springframework.transaction.annotation.Transactional;
8+
9+
@Service
10+
@RequiredArgsConstructor
11+
public class MemberService {
12+
13+
private final MemberRepository memberRepository;
14+
15+
@Transactional(readOnly = true)
16+
public Member getMemberByEmail(String email) {
17+
return memberRepository.findByEmailOrThrow(email);
18+
}
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.moplus.moplus_server.global.config.properties;
2+
3+
import com.moplus.moplus_server.global.properties.jwt.JwtProperties;
4+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@EnableConfigurationProperties({
8+
JwtProperties.class
9+
})
10+
@Configuration
11+
public class PropertiesConfig {
12+
13+
}

0 commit comments

Comments
 (0)