Skip to content

Commit 491cb58

Browse files
authored
Merge pull request #118 from woowacourse-teams/develop
스프린트2 Merge
2 parents d595111 + ec48886 commit 491cb58

File tree

248 files changed

+15725
-5022
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+15725
-5022
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
frontend/**/*.json linguist-generated

.github/workflows/backend.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
push:
55
branches:
66
- main
7-
- develop
87
pull_request:
98
branches:
109
- main
@@ -31,4 +30,9 @@ jobs:
3130
run: ./gradlew build --exclude-task test
3231

3332
- name: Test
34-
run: ./gradlew test
33+
env:
34+
client-id: ${{ secrets.CLIENT_ID }}
35+
client-secret: ${{ secrets.CLIENT_SECRET }}
36+
jwt-secret-key: ${{ secrets.JWT_SECRET_KEY }}
37+
jwt-expire-length: ${{ secrets.JWT_EXPIRE_LENGTH }}
38+
run: ./gradlew test -Doauth2.github.client-id=${{ env.client-id }} -Doauth2.github.client-secret=${{ env.client-secret }} -Dsecurity.jwt.token.secret-key=${{ env.jwt-secret-key }} -Dsecurity.jwt.token.expire-length=${{ env.jwt-expire-length }}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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: Deploy Backend Dev
9+
10+
on:
11+
push:
12+
branches : develop
13+
14+
defaults:
15+
run:
16+
working-directory: backend
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v3
24+
25+
- name: Set up JDK
26+
uses: actions/setup-java@v3
27+
with:
28+
java-version: '11'
29+
distribution: 'temurin'
30+
31+
- name: Build
32+
run: ./gradlew build --exclude-task test
33+
34+
- name: Test
35+
env:
36+
client-id: ${{ secrets.CLIENT_ID }}
37+
client-secret: ${{ secrets.CLIENT_SECRET }}
38+
jwt-secret-key: ${{ secrets.JWT_SECRET_KEY }}
39+
jwt-expire-length: ${{ secrets.JWT_EXPIRE_LENGTH }}
40+
run: ./gradlew test -Doauth2.github.client-id=${{ env.client-id }} -Doauth2.github.client-secret=${{ env.client-secret }} -Dsecurity.jwt.token.secret-key=${{ env.jwt-secret-key }} -Dsecurity.jwt.token.expire-length=${{ env.jwt-expire-length }}
41+
42+
- name : Deploy
43+
run: |
44+
curl ${{ secrets.DEPLOY_REQUEST_URL }}

backend/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ out/
3535

3636
### VS Code ###
3737
.vscode/
38+
39+
/src/main/resources/application-security.yml
40+
/src/test/resources/application-security.yml

backend/build.gradle

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
buildscript {
2+
ext {
3+
queryDslVersion = "5.0.0"
4+
}
5+
}
6+
17
plugins {
28
id 'org.springframework.boot' version '2.6.9'
39
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
410
id 'java'
11+
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
512
}
613

714
group = 'com.woowacourse'
@@ -26,11 +33,41 @@ dependencies {
2633
compileOnly 'org.projectlombok:lombok'
2734
annotationProcessor 'org.projectlombok:lombok'
2835

36+
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
37+
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
38+
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
39+
2940
testImplementation 'org.springframework.boot:spring-boot-starter-test'
3041
testImplementation 'io.rest-assured:rest-assured'
3142
runtimeOnly 'com.h2database:h2'
43+
runtimeOnly 'mysql:mysql-connector-java'
44+
45+
// querydsl
46+
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
47+
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
3248
}
3349

3450
tasks.named('test') {
3551
useJUnitPlatform()
52+
systemProperties = System.getProperties()
53+
}
54+
55+
// querydsl
56+
def querydslDir = "$buildDir/generated/querydsl"
57+
58+
querydsl {
59+
jpa = true
60+
querydslSourcesDir = querydslDir
61+
}
62+
sourceSets {
63+
main.java.srcDir querydslDir
64+
}
65+
compileQuerydsl {
66+
options.annotationProcessorPath = configurations.querydsl
67+
}
68+
configurations {
69+
compileOnly {
70+
extendsFrom annotationProcessor
71+
}
72+
querydsl.extendsFrom compileClasspath
3673
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.woowacourse.moamoa.auth.config;
2+
3+
import com.woowacourse.moamoa.auth.controller.AuthenticationArgumentResolver;
4+
import com.woowacourse.moamoa.auth.controller.AuthenticationInterceptor;
5+
import java.util.List;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.web.client.RestTemplate;
9+
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
10+
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
11+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
12+
13+
@Configuration
14+
public class AuthConfig implements WebMvcConfigurer {
15+
16+
private final AuthenticationInterceptor authenticationInterceptor;
17+
private final AuthenticationArgumentResolver authenticationArgumentResolver;
18+
19+
public AuthConfig(
20+
final AuthenticationInterceptor authenticationInterceptor,
21+
final AuthenticationArgumentResolver authenticationArgumentResolver) {
22+
this.authenticationInterceptor = authenticationInterceptor;
23+
this.authenticationArgumentResolver = authenticationArgumentResolver;
24+
}
25+
26+
@Override
27+
public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> resolvers) {
28+
resolvers.add(authenticationArgumentResolver);
29+
}
30+
31+
@Override
32+
public void addInterceptors(final InterceptorRegistry registry) {
33+
registry.addInterceptor(authenticationInterceptor)
34+
.addPathPatterns("/**");
35+
}
36+
37+
@Bean
38+
public RestTemplate restTemplate() {
39+
return new RestTemplate();
40+
}
41+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.woowacourse.moamoa.auth.config;
2+
3+
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
4+
5+
import java.util.Enumeration;
6+
import javax.servlet.http.HttpServletRequest;
7+
8+
public class AuthenticationExtractor {
9+
10+
private static String BEARER_TYPE = "Bearer";
11+
private static String ACCESS_TOKEN_TYPE = AuthenticationExtractor.class.getSimpleName() + ".ACCESS_TOKEN_TYPE";
12+
13+
public static String extract(HttpServletRequest request) {
14+
Enumeration<String> headers = request.getHeaders(AUTHORIZATION);
15+
16+
while (headers.hasMoreElements()) {
17+
String value = headers.nextElement();
18+
19+
if ((value.toLowerCase().startsWith(BEARER_TYPE.toLowerCase()))) {
20+
String authHeaderValue = value.substring(BEARER_TYPE.length()).trim();
21+
request.setAttribute(ACCESS_TOKEN_TYPE, value.substring(0, BEARER_TYPE.length()).trim());
22+
int commaIndex = authHeaderValue.indexOf(',');
23+
24+
if (commaIndex > 0) {
25+
authHeaderValue = authHeaderValue.substring(0, commaIndex);
26+
}
27+
return authHeaderValue;
28+
}
29+
}
30+
return null;
31+
}
32+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.woowacourse.moamoa.auth.config;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target(ElementType.PARAMETER)
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface AuthenticationPrincipal {
11+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.woowacourse.moamoa.auth.controller;
2+
3+
import com.woowacourse.moamoa.auth.service.AuthService;
4+
import com.woowacourse.moamoa.auth.service.response.TokenResponse;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.http.ResponseEntity;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequiredArgsConstructor
13+
public class AuthController {
14+
15+
private final AuthService authService;
16+
17+
@PostMapping("/api/login/token")
18+
public ResponseEntity<TokenResponse> login(@RequestParam final String code) {
19+
return ResponseEntity.ok().body(authService.createToken(code));
20+
}
21+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.woowacourse.moamoa.auth.controller;
2+
3+
import com.woowacourse.moamoa.auth.config.AuthenticationExtractor;
4+
import com.woowacourse.moamoa.auth.config.AuthenticationPrincipal;
5+
import com.woowacourse.moamoa.auth.infrastructure.TokenProvider;
6+
import com.woowacourse.moamoa.common.exception.UnauthorizedException;
7+
import javax.servlet.http.HttpServletRequest;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.core.MethodParameter;
10+
import org.springframework.stereotype.Component;
11+
import org.springframework.web.bind.support.WebDataBinderFactory;
12+
import org.springframework.web.context.request.NativeWebRequest;
13+
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
14+
import org.springframework.web.method.support.ModelAndViewContainer;
15+
16+
@Component
17+
@RequiredArgsConstructor
18+
public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver {
19+
20+
private final TokenProvider tokenProvider;
21+
22+
@Override
23+
public boolean supportsParameter(final MethodParameter parameter) {
24+
return parameter.hasParameterAnnotation(AuthenticationPrincipal.class);
25+
}
26+
27+
@Override
28+
public Object resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer,
29+
final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) {
30+
final HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
31+
32+
final String token = AuthenticationExtractor.extract(request);
33+
if (token == null) {
34+
throw new UnauthorizedException("인증 타입이 올바르지 않습니다.");
35+
}
36+
37+
return Long.valueOf(tokenProvider.getPayload(token));
38+
}
39+
}

0 commit comments

Comments
 (0)