Skip to content

Commit

Permalink
Merge pull request #19 from Tune-Fun/feature/account/social_login
Browse files Browse the repository at this point in the history
Feature/account/social login
  • Loading branch information
habinkim authored Mar 7, 2024
2 parents c16665b + f94f9bc commit c611cb1
Show file tree
Hide file tree
Showing 131 changed files with 2,387 additions and 1,036 deletions.
File renamed without changes.
48 changes: 35 additions & 13 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.2'
id 'org.springframework.boot' version '3.2.3'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.asciidoctor.jvm.convert' version '3.3.2'
id 'com.epages.restdocs-api-spec' version '0.18.2'
Expand Down Expand Up @@ -34,9 +34,9 @@ ext {
set('generated', file("src/main/generated"))
set('docsDir', "src/main/resources/static/docs")
set('springCloudVersion', "2023.0.0")
set('testcontainersVersion', "1.19.3")
set('testcontainersVersion', "1.19.7")
set('jwtVersion', '0.12.3')
set('queryDslVersion', "6.0")
set('queryDslVersion', "6.1")
set('mapstructVersion', "1.5.5.Final")
}

Expand All @@ -54,9 +54,14 @@ dependencies {

// Persistence Layer
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-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation "io.github.openfeign.querydsl:querydsl-jpa-spring:${queryDslVersion}"
implementation ("io.github.openfeign.querydsl:querydsl-mongodb:${queryDslVersion}") {
exclude group: 'org.mongodb', module: 'mongo-java-driver'
}
implementation "io.github.openfeign.querydsl:querydsl-collections:${queryDslVersion}"
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
Expand All @@ -72,10 +77,6 @@ dependencies {
implementation 'software.amazon.awssdk:s3:2.21.29'
implementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager:3.1.0'
implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-jdbc:2.0.2'
implementation 'com.amazonaws:aws-xray-recorder-sdk-spring:2.15.1'
implementation 'com.amazonaws:aws-xray-recorder-sdk-log4j:2.15.1'
implementation 'com.amazonaws:aws-xray-recorder-sdk-sql-mysql:2.15.1'
implementation 'com.amazonaws:aws-xray-recorder-sdk-sql:2.15.1'
implementation 'com.slack.api:slack-app-backend:1.38.0' // Chat
implementation 'io.netty:netty-resolver-dns-native-macos:4.1.68.Final:osx-aarch_64'

Expand All @@ -85,6 +86,7 @@ dependencies {

// Authentication, Authorization
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation "io.jsonwebtoken:jjwt-api:${jwtVersion}"
runtimeOnly "io.jsonwebtoken:jjwt-impl:${jwtVersion}"
runtimeOnly "io.jsonwebtoken:jjwt-jackson:${jwtVersion}"
Expand All @@ -106,6 +108,8 @@ dependencies {
annotationProcessor(
'org.springframework.boot:spring-boot-configuration-processor',
"io.github.openfeign.querydsl:querydsl-jpa-spring:${queryDslVersion}",
"io.github.openfeign.querydsl:querydsl-mongodb:${queryDslVersion}",
'org.springframework.boot:spring-boot-starter-data-mongodb',
'org.projectlombok:lombok',
"org.mapstruct:mapstruct-processor:${mapstructVersion}",
'org.projectlombok:lombok-mapstruct-binding:0.2.0'
Expand All @@ -115,9 +119,9 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'com.c4-soft.springaddons:spring-addons-oauth2-test:7.6.3'
testImplementation 'org.springframework.kafka:spring-kafka-test'
testImplementation 'org.apache.commons:commons-lang3:3.13.0'
testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
testImplementation 'com.tngtech.archunit:archunit-junit5:1.1.0' // Architecture Rule Test
testImplementation "com.navercorp.fixturemonkey:fixture-monkey-starter:1.0.12" // Test Double
testImplementation 'org.quickperf:quick-perf-junit5:1.1.0' // Performance Test
Expand All @@ -140,14 +144,29 @@ dependencies {
testImplementation 'org.testcontainers:kafka'
testImplementation 'org.testcontainers:localstack'

testAnnotationProcessor 'org.projectlombok:lombok'
testAnnotationProcessor(
'org.springframework.boot:spring-boot-configuration-processor',
"io.github.openfeign.querydsl:querydsl-jpa-spring:${queryDslVersion}",
"io.github.openfeign.querydsl:querydsl-mongodb:${queryDslVersion}",
'org.springframework.boot:spring-boot-starter-data-mongodb',
'org.projectlombok:lombok',
"org.mapstruct:mapstruct-processor:${mapstructVersion}",
'org.projectlombok:lombok-mapstruct-binding:0.2.0'
)
}

sourceSets {
main.java.srcDirs += [generated]
}

tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [
"-processor", 'lombok.launch.AnnotationProcessorHider$AnnotationProcessor,' +
'org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor,' +
'com.querydsl.apt.jpa.JPAAnnotationProcessor,' +
'org.mapstruct.ap.MappingProcessor,' +
'org.springframework.boot.configurationprocessor.ConfigurationMetadataAnnotationProcessor'
]
options.annotationProcessorGeneratedSourcesDirectory(file(generated))
}

Expand All @@ -170,7 +189,10 @@ test {
}

openapi3 { // Swagger OAS Generate
server = "http://localhost:8080"
servers = [
{ url = "https://api.tunefun.net" },
{ url = "http://localhost:8080"}
]
title = "Tune Fun REST API V1 Documentation"
description = "Spring REST Docs with SwaggerUI."
version = "${version}"
Expand All @@ -181,7 +203,7 @@ openapi3 { // Swagger OAS Generate
}

postman { // Postman API Collection
baseUrl = 'http://localhost:8080'
baseUrl = 'https://api.tunefun.net'
title = 'Tune Fun REST API V1 Documentation'
version = "${version}"
outputFileNamePrefix = "${group}-postman-collection"
Expand All @@ -194,7 +216,7 @@ asciidoctor {
inputs.dir snippetsDir
configurations 'asciidoctorExt'

sources{
sources {
include("**/index.adoc")
}

Expand Down
12 changes: 0 additions & 12 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,3 @@ services:
MONGO_INITDB_ROOT_USERNAME: root
ports:
- '27016:27017'

aws-xray:
image: 'amazon/aws-xray-daemon:latest'
container_name: 'tune_fun_aws_xray'
restart: always
environment:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_REGION: ap-northeast-2
ports:
- '2000:2000/udp'
- '2000:2000/tcp'
6 changes: 6 additions & 0 deletions src/docs/asciidoc/account-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ operation::register-success[snippets='http-request,http-response,request-fields,

operation::login-success[snippets='http-request,http-response,request-fields,response-fields']

=== 구글 소셜 로그인 페이지 진입 API

==== 성공

operation::oauth2-authorization-google-success[snippets='http-request,http-response']

=== 로그아웃 API

==== 성공
Expand Down
4 changes: 4 additions & 0 deletions src/docs/asciidoc/otp-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

operation::verify-otp-success[snippets='http-request,http-response,request-fields,response-fields']

==== 실패

operation::verify-otp-fail-case1[snippets='http-request,http-response,request-fields,response-fields']


=== OTP 재전송

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.tune_fun.v1.common.response.BasePayload;
import com.tune_fun.v1.common.response.Response;
import com.tune_fun.v1.common.response.ResponseMapper;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand All @@ -28,7 +27,7 @@ public class CheckEmailDuplicateController {

@GetMapping(value = Uris.CHECK_EMAIL_DUPLICATE)
public ResponseEntity<Response<BasePayload>> checkUsernameDuplicate(@RequestParam(name = "email")
@NotBlank(message = "{email.not_blank}") final String email) {
@NotBlank(message = "{email.not_blank}") final String email) {
checkEmailDuplicateUseCase.checkEmailDuplicate(email);
return responseMapper.ok(SUCCESS_EMAIL_UNIQUE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class CheckUsernameDuplicateController {

@GetMapping(value = Uris.CHECK_USERNAME_DUPLICATE)
public ResponseEntity<Response<BasePayload>> checkUsernameDuplicate(@RequestParam(name = "username")
@NotBlank(message = "{username.not_blank}") final String username) {
@NotBlank(message = "{username.not_blank}") final String username) {
checkUsernameDuplicateUseCase.checkUsernameDuplicate(username);
return responseMapper.ok(SUCCESS_USERNAME_UNIQUE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@WebAdapter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.tune_fun.v1.account.adapter.input.rest;

import com.amazonaws.xray.spring.aop.XRayEnabled;
import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
import com.tune_fun.v1.account.application.port.input.usecase.LoginUseCase;
import com.tune_fun.v1.account.domain.state.LoginResult;
Expand All @@ -15,7 +14,7 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@XRayEnabled

@RestController
@WebAdapter
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.tune_fun.v1.common.response.Response;
import com.tune_fun.v1.common.response.ResponseMapper;
import com.tune_fun.v1.common.util.StringUtil;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
Optional<String> matchedUri = Arrays.stream(Uris.PERMIT_ALL_URIS)
.filter(uri -> uri.equals(request.getServletPath()))
.filter(uri -> uri.equals(request.getServletPath()) || "".equals(request.getServletPath()))
.findFirst();

return matchedUri.isPresent();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.tune_fun.v1.account.adapter.output.mail;

import com.amazonaws.xray.spring.aop.XRayEnabled;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tune_fun.v1.account.application.port.output.SendUsernamePort;
Expand All @@ -11,7 +10,7 @@

import java.util.Map;

@XRayEnabled

@Component
@RequiredArgsConstructor
public class AccountMailAdapter implements SendUsernamePort {
Expand All @@ -21,6 +20,10 @@ public class AccountMailAdapter implements SendUsernamePort {
private final MailHandler mailHandler;
private final ObjectMapper objectMapper;

private static String getSubject() {
return "TuneFun - 아이디 찾기 결과입니다.";
}

@Override
public void sendUsername(final SendUsername sendUsername) throws Exception {
Map<String, Object> marshalledVariable = getTemplateVariables(sendUsername);
Expand All @@ -33,9 +36,6 @@ private Map<String, Object> getTemplateVariables(final SendUsername sendUsername
});
}

private static String getSubject() {
return "TuneFun - 아이디 찾기 결과입니다.";
private record UsernameSendMailVariables(String username) {
}

private record UsernameSendMailVariables(String username) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
@RequiredArgsConstructor
public class AccountCustomRepositoryImpl implements AccountCustomRepository {

private final JPAQueryFactory queryFactory;

private static final QAccountJpaEntity ACCOUNT = QAccountJpaEntity.accountJpaEntity;
private final JPAQueryFactory queryFactory;

@Override
public Optional<AccountJpaEntity> findActive(final String username, final String email, final String nickname) {
Expand All @@ -25,10 +24,10 @@ public Optional<AccountJpaEntity> findActive(final String username, final String
return Optional.ofNullable(
queryFactory.selectFrom(ACCOUNT)
.where(predicate)
.where(ACCOUNT.isEnabled.eq(true))
.where(ACCOUNT.isAccountNonLocked.eq(true))
.where(ACCOUNT.isAccountNonExpired.eq(true))
.where(ACCOUNT.isCredentialsNonExpired.eq(true))
.where(ACCOUNT.enabled.eq(true))
.where(ACCOUNT.accountNonLocked.eq(true))
.where(ACCOUNT.accountNonExpired.eq(true))
.where(ACCOUNT.credentialsNonExpired.eq(true))
.fetchOne()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.UpdateTimestamp;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
Expand Down Expand Up @@ -56,7 +55,7 @@ public class AccountJpaEntity extends BaseEntity implements UserDetails {

@Convert(converter = EncryptConverter.class)
@NotNull
@Column(name = "email", nullable = false)
@Column(name = "email")
@Comment("이메일")
private String email;

Expand Down Expand Up @@ -101,48 +100,29 @@ public class AccountJpaEntity extends BaseEntity implements UserDetails {
protected LocalDateTime deletedAt;

@Builder.Default
@Column(name = "is_account_non_expired")
private Boolean isAccountNonExpired = true;
@Column(name = "account_non_expired")
private boolean accountNonExpired = true;

@Builder.Default
@Column(name = "is_account_non_locked")
private Boolean isAccountNonLocked = true;
@Column(name = "account_non_locked")
private boolean accountNonLocked = true;

@Builder.Default
@Column(name = "is_credentials_non_expired")
private Boolean isCredentialsNonExpired = true;
@Column(name = "credentials_non_expired")
private boolean credentialsNonExpired = true;

@Builder.Default
@Column(name = "is_enabled")
private Boolean isEnabled = true;
@Column(name = "enabled")
private boolean enabled = true;

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles;
}

@Override
public boolean isAccountNonExpired() {
return isAccountNonExpired;
}

@Override
public boolean isAccountNonLocked() {
return isAccountNonLocked;
}

@Override
public boolean isCredentialsNonExpired() {
return isCredentialsNonExpired;
}

@Override
public boolean isEnabled() {
return isEnabled;
}

public boolean isAvailable() {
return !isAccountNonExpired && !isAccountNonLocked && !isCredentialsNonExpired && !isEnabled;
return !accountNonExpired && !accountNonLocked && !credentialsNonExpired && !enabled;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public abstract class AccountMapper {
@Mapping(target = "notificationConfig.voteProgressNotification", source = "voteProgressNotification")
@Mapping(target = "notificationConfig.voteEndNotification", source = "voteEndNotification")
@Mapping(target = "notificationConfig.voteDeliveryNotification", source = "voteDeliveryNotification")
public abstract AccountJpaEntity fromSaveAccountValue(final SaveAccount saveAccount);
public abstract AccountJpaEntity fromSaveAccountBehavior(final SaveAccount behavior);

@Mapping(target = "roles", source = "roles", qualifiedByName = "roleValues")
public abstract RegisteredAccount registeredAccountInfo(AccountJpaEntity accountJpaEntity);
Expand Down
Loading

0 comments on commit c611cb1

Please sign in to comment.