diff --git a/.github/workflows/develop-branch-test-coverage.yml b/.github/workflows/develop-branch-test-coverage.yml index abbec24..f1ced1a 100644 --- a/.github/workflows/develop-branch-test-coverage.yml +++ b/.github/workflows/develop-branch-test-coverage.yml @@ -42,8 +42,8 @@ jobs: - name: test run: ./gradlew test --info --stacktrace --no-daemon - - name: analyze - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: ./gradlew sonar --info --stacktrace --no-daemon \ No newline at end of file +# - name: analyze +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} +# run: ./gradlew sonar --info --stacktrace --no-daemon \ No newline at end of file diff --git a/IDP-Api/build.gradle b/IDP-Api/build.gradle index 3ddcf0d..7d3b7bb 100644 --- a/IDP-Api/build.gradle +++ b/IDP-Api/build.gradle @@ -1,12 +1,9 @@ dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' - //jwt implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'commons-io:commons-io:2.8.0' - implementation 'org.springdoc:springdoc-openapi-ui:1.6.12' - implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springdoc:springdoc-openapi-ui:1.5.7' implementation project(':IDP-Domain') implementation project(':IDP-Common') implementation project(':IDP-Infrastructure') diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/IdpApiApplication.java b/IDP-Api/src/main/java/com/econovation/idpapi/IdpApiApplication.java index e7791bf..79a5ed6 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/IdpApiApplication.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/IdpApiApplication.java @@ -13,7 +13,7 @@ import org.springframework.web.filter.ForwardedHeaderFilter; @RequiredArgsConstructor -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.econovation") @Slf4j public class IdpApiApplication implements ApplicationListener { private final Environment environment; diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountController.java b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountController.java index 7eef86a..5ade30f 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountController.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountController.java @@ -3,16 +3,16 @@ import com.econovation.idpapi.application.port.in.AccountSignUpUseCase; import com.econovation.idpapi.application.port.in.AccountUseCase; -import com.econovation.idpapi.application.port.in.JwtProviderUseCase; +import com.econovation.idpapi.application.service.AccountJwtService; import com.econovation.idpapi.common.BasicResponse; import com.econovation.idpcommon.exception.GetExpiredTimeException; +import com.econovation.idpcommon.jwt.JwtProvider; import com.econovation.idpdomain.domains.dto.LoginRequestDto; import com.econovation.idpdomain.domains.dto.LoginResponseDto; import com.econovation.idpdomain.domains.dto.LoginResponseDtoWithExpiredTime; import com.econovation.idpdomain.domains.dto.LoginResponseDtoWithRedirectUrl; import com.econovation.idpdomain.domains.dto.SignUpRequestDto; import com.econovation.idpdomain.domains.dto.UserResponseMatchedTokenDto; -import com.econovation.idpdomain.domains.users.domain.Account; import io.reactivex.rxjava3.annotations.Nullable; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -47,7 +47,8 @@ public class AccountController { private final AccountUseCase accountUseCase; private final AccountSignUpUseCase accountSignUpUseCase; - private final JwtProviderUseCase jwtProviderUseCase; + private final JwtProvider jwtProvider; + private final AccountJwtService accountJwtService; @Value("${login.page.url}") private String loginPageUrl; @@ -78,7 +79,7 @@ public ResponseEntity duplicateCheck( @GetMapping("/accounts/re-issue") public ResponseEntity reIssue( String refreshToken, HttpServletRequest request) { - if (!jwtProviderUseCase.validateToken(request, refreshToken).isAuthenticated()) { + if (!accountJwtService.validateToken(request, refreshToken).isAuthenticated()) { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } LoginResponseDto responseDto = accountUseCase.reIssueAccessToken(request, refreshToken); @@ -108,7 +109,7 @@ public ResponseEntity login( if (refreshToken != null) { // 토큰 검증 - Authentication authentication = jwtProviderUseCase.validateToken(request, refreshToken); + Authentication authentication = accountJwtService.validateToken(request, refreshToken); if (!authentication.isAuthenticated()) { // 검증 실패 BasicResponse result = new BasicResponse("유효하지 않은 토큰입니다.", HttpStatus.OK); @@ -173,7 +174,7 @@ private Cookie createRefreshTokenCookie(String refreshToken) { @GetMapping("/accounts/re-check") public ResponseEntity checkValideToken( HttpServletRequest request, String refreshToken) { - Authentication authentication = jwtProviderUseCase.validateToken(request, refreshToken); + Authentication authentication = accountJwtService.validateToken(request, refreshToken); if (!authentication.isAuthenticated()) { BasicResponse result = new BasicResponse("유효하지 않은 토큰입니다.", HttpStatus.OK); return new ResponseEntity<>(result, HttpStatus.UNAUTHORIZED); @@ -193,7 +194,7 @@ public ResponseEntity loginWithExpiredTime( throws URISyntaxException, GetExpiredTimeException { LoginResponseDto responseDto = accountUseCase.login(loginDto.getUserEmail(), loginDto.getPassword()); - Date expiredTime = jwtProviderUseCase.getExpiredTime(responseDto.getRefreshToken()); + Date expiredTime = jwtProvider.getExpiredTime(responseDto.getRefreshToken()); URI redirectUri = new URI(redirectUrl); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setLocation(redirectUri); @@ -211,10 +212,4 @@ public ResponseEntity simpleRequest(HttpServletRequ UserResponseMatchedTokenDto byAccessToken = accountUseCase.findByAccessToken(accessToken); return new ResponseEntity<>(byAccessToken, HttpStatus.OK); } - - @GetMapping("/users/me") - public ResponseEntity findByMe() { - Account account = accountUseCase.findByMe().get(); - return ResponseEntity.ok(account); - } } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountCookieController.java b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountCookieController.java index 63e2436..75aa962 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountCookieController.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/AccountCookieController.java @@ -2,7 +2,7 @@ import com.econovation.idpapi.application.port.in.AccountUseCase; -import com.econovation.idpapi.application.port.in.JwtProviderUseCase; +import com.econovation.idpapi.application.service.AccountJwtService; import com.econovation.idpdomain.domains.dto.LoginRequestDto; import com.econovation.idpdomain.domains.dto.LoginResponseDto; import io.swagger.v3.oas.annotations.Operation; @@ -33,7 +33,8 @@ public class AccountCookieController { private final AccountUseCase accountUseCase; private Cookie[] cookies = null; - private final JwtProviderUseCase jwtProviderUseCase; + // private final JwtProviderUseCase jwtProviderUseCase; + private final AccountJwtService accountJwtService; final long tokenInvalidTime = 1000L * 60 * 60; // 1h @@ -96,7 +97,7 @@ public ResponseEntity reIssue(HttpServletRequest request) { cookies = request.getCookies(); String refreshToken = getCookieValue(request, "refreshToken"); log.info(refreshToken); - if (!jwtProviderUseCase.validateToken(request, refreshToken).isAuthenticated()) { + if (!accountJwtService.validateToken(request, refreshToken).isAuthenticated()) { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } LoginResponseDto responseDto = accountUseCase.reIssueAccessToken(request, refreshToken); diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/NonUserController.java b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/NonUserController.java index 7252053..5c0bbe9 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/NonUserController.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/NonUserController.java @@ -3,7 +3,7 @@ import com.econovation.idpapi.application.port.in.UserUseCase; import com.econovation.idpdomain.domains.dto.NonAccountResponseDto; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -30,7 +30,7 @@ public class NonUserController { public ResponseEntity findUserById( @PathVariable(value = "user-id") Long userId) { HttpHeaders headers = new HttpHeaders(); - Account account = userService.findUserById(userId); + Accounts account = userService.findUserById(userId); NonAccountResponseDto nonAccountResponseDto = account.toNonLoginUser(account); return new ResponseEntity<>(nonAccountResponseDto, headers, HttpStatus.OK); } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/UserController.java b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/UserController.java index c24b6cc..d86b774 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/UserController.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/adapter/in/controller/UserController.java @@ -1,13 +1,13 @@ package com.econovation.idpapi.adapter.in.controller; -import com.econovation.idpapi.application.port.in.JwtProviderUseCase; import com.econovation.idpapi.application.port.in.UserUseCase; +import com.econovation.idpapi.application.service.AccountJwtService; import com.econovation.idpapi.common.BasicResponse; import com.econovation.idpdomain.domains.dto.UserFindDto; import com.econovation.idpdomain.domains.dto.UserPasswordUpdateDto; import com.econovation.idpdomain.domains.dto.UserUpdateRequestDto; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -34,14 +34,15 @@ @AllArgsConstructor @CrossOrigin(origins = "*") @SecurityRequirement(name = "access-token") -@Tag(name = "WebApplication User 제공 서비스", description = "유저 정보 조회") +@Tag(name = "[1.0] User 제공 서비스", description = "유저 정보 조회") public class UserController { private final UserUseCase userService; - private final JwtProviderUseCase jwtProviderUseCase; + + private final AccountJwtService accountJwtService; @GetMapping("/api/users/page/{page}") - public ResponseEntity> findUserAll(@PathVariable int page) { - List listAccount = userService.findAll(page); + public ResponseEntity> findUserAll(@PathVariable int page) { + List listAccount = userService.findAll(page); return new ResponseEntity<>(listAccount, HttpStatus.OK); } @@ -60,9 +61,9 @@ public ResponseEntity findUserAll( @Operation(summary = "findUserById", description = "Id로 회원조회") @GetMapping("/api/users/{user-id}") - public ResponseEntity findUserById(@PathVariable(value = "user-id") Long userId) { + public ResponseEntity findUserById(@PathVariable(value = "user-id") Long userId) { HttpHeaders headers = new HttpHeaders(); - Account account = userService.findUserById(userId); + Accounts account = userService.findUserById(userId); return new ResponseEntity<>(account, headers, HttpStatus.OK); } @@ -82,24 +83,24 @@ public ResponseEntity countAllUser() { @Operation(summary = "이름으로 회원 조회", description = "동명이인 포함 회원 정보 조회") @GetMapping("/api/users") - public ResponseEntity> findUserByUserName(String userName) { - List userListByUserName = userService.findUserByUserName(userName); + public ResponseEntity> findUserByUserName(String userName) { + List userListByUserName = userService.findUserByUserName(userName); return new ResponseEntity<>(userListByUserName, HttpStatus.OK); } @Operation(summary = "Role으로 회원 조회", description = "Role(USER,GUEST,ADMIN)로 회원정보 조회 with Page") @ApiResponses({@ApiResponse(description = "Role에 따른 회원 조횐 return")}) @GetMapping("/api/users/role/{page}/{role}") - public ResponseEntity> findUserByRole( + public ResponseEntity> findUserByRole( @PathVariable int page, @PathVariable String role) { - List userByRole = userService.findUserByRole(page, role); + List userByRole = userService.findUserByRole(page, role); return new ResponseEntity<>(userByRole, HttpStatus.OK); } @Operation(summary = "Email 찾기 기능", description = "Email 찾기 ( 기수, 이름 ) 으로 조회") @GetMapping("/api/users/find-email/") public ResponseEntity findEmail(@Valid UserFindDto userFindDto) { - Account userByYearAndUserName = + Accounts userByYearAndUserName = userService.findUserByYearAndUserName( userFindDto.getUserName(), userFindDto.getYear()); return new ResponseEntity<>(userByYearAndUserName.getProfile().getEmail(), HttpStatus.OK); @@ -107,18 +108,18 @@ public ResponseEntity findEmail(@Valid UserFindDto userFindDto) { @Operation(summary = "Email로 회원 조회", description = "이메일로 회원 조회") @GetMapping("/api/users/{userEmail}") - public ResponseEntity findUserByEmail(@PathVariable String userEmail) { - Account userByUserEmail = userService.findUserByUserEmail(userEmail); + public ResponseEntity findUserByEmail(@PathVariable String userEmail) { + Accounts userByUserEmail = userService.findUserByUserEmail(userEmail); return new ResponseEntity<>(userByUserEmail, HttpStatus.OK); } @Operation(summary = "회원정보 수정", description = "로그인된 상태에서, 회원정보 수정") @PostMapping("/api/users/") - public ResponseEntity updateUser( + public ResponseEntity updateUser( HttpServletRequest request, UserUpdateRequestDto userUpdateRequestDto) { String accessToken = request.getHeader("Authorization").substring(7); - if (!jwtProviderUseCase.validateToken(request, accessToken).isAuthenticated()) { + if (!accountJwtService.validateToken(request, accessToken).isAuthenticated()) { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } return new ResponseEntity<>(userService.updateUser(userUpdateRequestDto), HttpStatus.OK); @@ -134,8 +135,8 @@ public ResponseEntity deleteUser(@PathVariable Long userId) { @Operation(summary = "비밀번호 수정", description = "비밀번호 수정") @PostMapping("/api/users/update/password") - public ResponseEntity setPassword(@Valid UserPasswordUpdateDto userPasswordUpdateDto) { - Account account = userService.setPassword(userPasswordUpdateDto); + public ResponseEntity setPassword(@Valid UserPasswordUpdateDto userPasswordUpdateDto) { + Accounts account = userService.setPassword(userPasswordUpdateDto); return new ResponseEntity<>(account, HttpStatus.OK); } } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/AccountUseCase.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/AccountUseCase.java index cf843cf..dc52a18 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/AccountUseCase.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/AccountUseCase.java @@ -4,8 +4,6 @@ import com.econovation.idpcommon.exception.GetExpiredTimeException; import com.econovation.idpdomain.domains.dto.LoginResponseDto; import com.econovation.idpdomain.domains.dto.UserResponseMatchedTokenDto; -import com.econovation.idpdomain.domains.users.domain.Account; -import java.util.Optional; import javax.servlet.http.HttpServletRequest; public interface AccountUseCase { @@ -16,6 +14,4 @@ public interface AccountUseCase { public LoginResponseDto login(String email, String password); public void logout(String refreshToken) throws GetExpiredTimeException; - - Optional findByMe(); } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/JwtProviderUseCase.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/JwtProviderUseCase.java index e88bbb7..d96bae3 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/JwtProviderUseCase.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/JwtProviderUseCase.java @@ -1,10 +1,7 @@ +/* package com.econovation.idpapi.application.port.in; -import com.econovation.idpcommon.exception.GetExpiredTimeException; -import java.util.Date; -import javax.servlet.http.HttpServletRequest; -import org.springframework.security.core.Authentication; public interface JwtProviderUseCase { public void logout(String refreshToken) throws GetExpiredTimeException; @@ -16,6 +13,6 @@ public interface JwtProviderUseCase { public Date getExpiredTime(String token) throws GetExpiredTimeException; public Authentication validateToken(HttpServletRequest request, String token); - public Long getIdpId(String token); } +*/ diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/UserUseCase.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/UserUseCase.java index 2d283c9..3098001 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/UserUseCase.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/in/UserUseCase.java @@ -3,32 +3,32 @@ import com.econovation.idpdomain.domains.dto.UserPasswordUpdateDto; import com.econovation.idpdomain.domains.dto.UserUpdateRequestDto; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import java.util.List; import java.util.Map; public interface UserUseCase { - List findAll(Integer page); + List findAll(Integer page); - Account findUserById(Long userId); + Accounts findUserById(Long userId); Long countUserByRole(String role); Long countAllUser(); - List findUserByUserName(String userName); + List findUserByUserName(String userName); - List findUserByRole(int page, String role); + List findUserByRole(int page, String role); - Account findUserByYearAndUserName(String userName, Integer year); + Accounts findUserByYearAndUserName(String userName, Integer year); - Account findUserByUserEmail(String userEmail); + Accounts findUserByUserEmail(String userEmail); - Account updateUser(UserUpdateRequestDto userUpdateRequestDto); + Accounts updateUser(UserUpdateRequestDto userUpdateRequestDto); void deleteUserById(Long userId); - Account setPassword(UserPasswordUpdateDto userPasswordUpdateDto); + Accounts setPassword(UserPasswordUpdateDto userPasswordUpdateDto); Map findAllWithLastPageInPage(Integer page); } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/out/LoadAccountPort.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/out/LoadAccountPort.java deleted file mode 100644 index 6cccbc2..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/out/LoadAccountPort.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.econovation.idpapi.application.port.out; - - -import com.econovation.idpdomain.domains.users.domain.Account; -import com.econovation.idpdomain.domains.users.domain.AccountRole; -import java.util.List; -import java.util.Optional; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -public interface LoadAccountPort { - boolean existsAccountByUserEmail(String email); - - List loadByUserName(String userName); - - Optional loadByUserEmail(String userEmail); - - Page loadAllByPage(Pageable pageable); - - Long countAllByRole(AccountRole role); - - Account loadById(Long id); - - Optional loadUserByUserNameAndYear(String userName, Integer year); -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/out/RecordAccountPort.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/port/out/RecordAccountPort.java deleted file mode 100644 index 6d7f60c..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/port/out/RecordAccountPort.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.econovation.idpapi.application.port.out; - - -import com.econovation.idpdomain.domains.users.domain.Account; - -public interface RecordAccountPort { - Account save(Account account); -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountJwtService.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountJwtService.java index ff2ac98..8126580 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountJwtService.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountJwtService.java @@ -1,51 +1,56 @@ package com.econovation.idpapi.application.service; +import com.econovation.idp.redis.RedisService; import com.econovation.idpapi.application.port.in.AccountUseCase; -import com.econovation.idpapi.application.port.in.JwtProviderUseCase; -import com.econovation.idpapi.application.port.out.LoadAccountPort; -import com.econovation.idpapi.config.jwt.JwtProvider; -import com.econovation.idpapi.config.security.SecurityUtils; +import com.econovation.idpapi.config.security.AuthDetails; import com.econovation.idpapi.utils.EntityMapper; +import com.econovation.idpcommon.dto.AccessTokenInfo; import com.econovation.idpcommon.exception.BadRequestException; import com.econovation.idpcommon.exception.GetExpiredTimeException; +import com.econovation.idpcommon.jwt.JwtProvider; import com.econovation.idpdomain.domains.dto.LoginResponseDto; import com.econovation.idpdomain.domains.dto.UserResponseMatchedTokenDto; -import com.econovation.idpdomain.domains.users.domain.Account; import com.econovation.idpdomain.domains.users.domain.AccountRepository; -import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.Optional; +import com.econovation.idpdomain.domains.users.domain.Accounts; +import com.econovation.idpdomain.domains.users.port.LoadAccountPort; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; import javax.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor @Slf4j @Service -@Tag(name = "1. 회원 인증(로그인, 로그아웃, 회원 가입)") public class AccountJwtService implements AccountUseCase { private static final String NO_ACCOUNT_MESSAGE = "존재하지 않는 유저입니다."; - private final PasswordEncoder passwordEncoder; private final LoadAccountPort loadAccountPort; private final AccountRepository accountRepository; - private final JwtProviderUseCase jwtProviderUseCase; private final EntityMapper entityMapper; private final JwtProvider jwtProvider; + private final RedisService redisService; + + @Value("${auth.jwt.blacklist.prefix}") + private String blackListATPrefix; @Override @Transactional public LoginResponseDto reIssueAccessToken(HttpServletRequest request, String refreshedToken) { - Long idpId = jwtProviderUseCase.getIdpId(refreshedToken); - Account account = + Long idpId = jwtProvider.getIdpId(refreshedToken); + Accounts account = accountRepository .findById(idpId) .orElseThrow(() -> new IllegalArgumentException(NO_ACCOUNT_MESSAGE)); // refreshToken 검증 절차 - Authentication authentication = jwtProviderUseCase.validateToken(request, refreshedToken); + Authentication authentication = validateToken(request, refreshedToken); if (authentication.isAuthenticated()) { String refreshToken = jwtProvider.generateRefreshToken(idpId); @@ -59,8 +64,8 @@ public LoginResponseDto reIssueAccessToken(HttpServletRequest request, String re @Override public UserResponseMatchedTokenDto findByAccessToken(String accessToken) { - Long idpId = jwtProviderUseCase.getIdpId(accessToken); - Account account = + Long idpId = jwtProvider.getIdpId(accessToken); + Accounts account = accountRepository .findById(idpId) .orElseThrow(() -> new IllegalArgumentException(NO_ACCOUNT_MESSAGE)); @@ -68,7 +73,7 @@ public UserResponseMatchedTokenDto findByAccessToken(String accessToken) { } @Transactional - public LoginResponseDto createToken(Account account) { + public LoginResponseDto createToken(Accounts account) { String accessToken = jwtProvider.generateAccessToken(account.getId(), account.getAccountRole().name()); String refreshToken = jwtProvider.generateRefreshToken(account.getId()); @@ -79,29 +84,53 @@ public LoginResponseDto createToken(Account account) { @Transactional public LoginResponseDto login(String email, String password) { log.info("email : " + email + " / password : " + password); - Account account = + Accounts account = loadAccountPort .loadByUserEmail(email) .orElseThrow(() -> new BadRequestException("해당하는 이메일이 존재하지 않습니다")); - checkPassword(password, account.getPassword()); + // checkPassword(password, account.getPassword()); return createToken(account); } @Override public void logout(String refreshToken) throws GetExpiredTimeException { - jwtProviderUseCase.logout(refreshToken); + jwtProvider.logout(refreshToken); } - private void checkPassword(String password, String encodePassword) { + /* private void checkPassword(String password, String encodePassword) { boolean isMatch = passwordEncoder.matches(password, encodePassword); if (!isMatch) { throw new BadRequestException("비밀번호를 확인하세요"); } + }*/ + + public Authentication validateToken(HttpServletRequest request, String token) { + String exception = "exception"; + try { + String expiredAT = redisService.getValues(blackListATPrefix + token); + if (expiredAT != null) { + throw new ExpiredJwtException(null, null, null); + } + // Jws claimsJws = + // Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); + log.info("validateToken : {}", token); + return getAuthentication(token); + } catch (MalformedJwtException | UnsupportedJwtException e) { + request.setAttribute(exception, "토큰의 형식을 확인하세요"); + } catch (ExpiredJwtException e) { + request.setAttribute(exception, "토큰이 만료되었습니다."); + } catch (IllegalArgumentException e) { + request.setAttribute(exception, "JWT compact of handler are invalid"); + } + return null; } - @Override - public Optional findByMe() { - Long currentId = SecurityUtils.getCurrentUserId(); - return accountRepository.findById(currentId); + public Authentication getAuthentication(String token) { + AccessTokenInfo accessTokenInfo = jwtProvider.parseAccessToken(token); + + UserDetails userDetails = + new AuthDetails(accessTokenInfo.getUserId().toString(), accessTokenInfo.getRole()); + return new UsernamePasswordAuthenticationToken( + userDetails, "user", userDetails.getAuthorities()); } } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountSignUpService.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountSignUpService.java index 833a8b0..5625189 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountSignUpService.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/AccountSignUpService.java @@ -4,8 +4,8 @@ import com.econovation.idpapi.application.port.in.AccountSignUpUseCase; import com.econovation.idpapi.common.BasicResponse; import com.econovation.idpcommon.exception.BadRequestException; -import com.econovation.idpdomain.domains.users.domain.Account; import com.econovation.idpdomain.domains.users.domain.AccountRepository; +import com.econovation.idpdomain.domains.users.domain.Accounts; import com.econovation.idpdomain.domains.users.domain.Profile; import java.util.List; import java.util.Optional; @@ -35,14 +35,14 @@ public void signUp(String userName, Integer year, String userEmail, String passw throw new BadRequestException("중복된 이메일입니다"); } String encodePassword = passwordEncoder.encode(password); - Account newAccount = new Account(new Profile(userName, userEmail, year), encodePassword); + Accounts newAccount = new Accounts(new Profile(userName, userEmail, year), encodePassword); accountRepository.save(newAccount); } // 중복된 이메일 확인 @Override public BasicResponse isDuplicateEmail(String email) { - boolean isDuplicate = accountRepository.existsAccountByUserEmail(email); + boolean isDuplicate = accountRepository.existsAccountsByUserEmail(email); if (isDuplicate) { return new BasicResponse("중복된 이메일입니다.", HttpStatus.CONFLICT); } @@ -54,11 +54,11 @@ public BasicResponse isDuplicateEmail(String email) { @Transactional public String sendfindingPasswordConfirmationCode(String name, Integer year) throws IllegalAccessException { - List byUserName = + List byUserName = accountRepository.findByUserName(name).stream() .filter(u -> u.getProfile().getYear().equals(year)) .collect(Collectors.toList()); - Optional first = byUserName.stream().findFirst(); + Optional first = byUserName.stream().findFirst(); if (first.isEmpty()) { throw new IllegalAccessException("잘못된 이름과 기수를 입력했습니다."); } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ConfirmationTokenService.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ConfirmationTokenService.java index f081a87..55c35ca 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ConfirmationTokenService.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ConfirmationTokenService.java @@ -21,7 +21,9 @@ public class ConfirmationTokenService { private final ConfirmationTokenRepository confirmationTokenRepository; private final EmailSenderService emailSenderService; + // @Value("${sending.email}") + @Value("${mail.destination.url}") private String destinationEmail; diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ImageService.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ImageService.java index 67d4cf2..61f5b33 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ImageService.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/ImageService.java @@ -1,12 +1,12 @@ package com.econovation.idpapi.application.service; -import com.econovation.idpapi.application.port.out.LoadAccountPort; import com.econovation.idpapi.config.security.SecurityUtils; import com.econovation.idpdomain.domains.dto.ImageUploadDto; import com.econovation.idpdomain.domains.images.Image; import com.econovation.idpdomain.domains.images.ImageRepository; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; +import com.econovation.idpdomain.domains.users.port.LoadAccountPort; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -20,7 +20,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,7 +30,7 @@ public class ImageService { private static final String NO_MATCH_IMAGE = "업로드 된 이미지가 없습니다"; private final ImageRepository imageRepository; private final LoadAccountPort loadAccountPort; - private final ResourceLoader resourceLoader; + // private final ResourceLoader resourceLoader; /* 이미지 업로드 폴더 */ @Value("${file.path}") @@ -41,7 +40,7 @@ public class ImageService { public List imageSearch() { Long idpId = SecurityUtils.getCurrentUserId(); log.info("uploadFolder : " + uploadFolder); - Account account = loadAccountPort.loadById(idpId); + Accounts account = loadAccountPort.loadById(idpId); return imageRepository.findByAccount(account); } @@ -53,7 +52,7 @@ public void upload(ImageUploadDto imageUploadDto) { Path imageFilePath = Paths.get(uploadFolder + imageFileName); Long idpId = imageUploadDto.getIdpId(); - Account account = loadAccountPort.loadById(idpId); + Accounts account = loadAccountPort.loadById(idpId); try { Path write = Files.write(imageFilePath, imageUploadDto.getFile().getBytes()); diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/UserService.java b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/UserService.java index 1c1480a..6ad4fd5 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/application/service/UserService.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/application/service/UserService.java @@ -5,9 +5,9 @@ import com.econovation.idpcommon.exception.BadRequestException; import com.econovation.idpdomain.domains.dto.UserPasswordUpdateDto; import com.econovation.idpdomain.domains.dto.UserUpdateRequestDto; -import com.econovation.idpdomain.domains.users.domain.Account; import com.econovation.idpdomain.domains.users.domain.AccountRepository; import com.econovation.idpdomain.domains.users.domain.AccountRole; +import com.econovation.idpdomain.domains.users.domain.Accounts; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -38,7 +38,7 @@ public class UserService implements UserUseCase { @Override @Transactional - public List findAll(Integer page) { + public List findAll(Integer page) { Pageable pageable = PageRequest.of(page, PAGE_PER_REQUEST); return userRepository.findAll(pageable).stream().collect(Collectors.toList()); } @@ -47,8 +47,8 @@ public List findAll(Integer page) { public Map findAllWithLastPageInPage(Integer page) { Pageable pageable = PageRequest.of(page, PAGE_PER_REQUEST); - Slice usersWithPagination = userRepository.findSliceBy(pageable); - List users = usersWithPagination.stream().collect(Collectors.toList()); + Slice usersWithPagination = userRepository.findSliceBy(pageable); + List users = usersWithPagination.stream().collect(Collectors.toList()); Map map = new HashMap(); map.put("users", users); if (map.isEmpty()) throw new IllegalArgumentException(NOT_FOUND_USER_MESSAGE); @@ -56,8 +56,8 @@ public Map findAllWithLastPageInPage(Integer page) { } @Transactional - public Account setPassword(UserPasswordUpdateDto userPasswordUpdateDto) { - Account user = + public Accounts setPassword(UserPasswordUpdateDto userPasswordUpdateDto) { + Accounts user = findUserByYearAndUserName( userPasswordUpdateDto.getUserName(), userPasswordUpdateDto.getYear()); String encodedPassword = passwordEncoder.encode(userPasswordUpdateDto.getPassword()); @@ -74,7 +74,7 @@ public Account setPassword(UserPasswordUpdateDto userPasswordUpdateDto) { * @return Account */ @Transactional - public List findUserByRole(int page, String role) { + public List findUserByRole(int page, String role) { Pageable pageable = PageRequest.of(page, 8); return userRepository.findAll(pageable).stream() .filter(u -> u.getAccountRole().equals(role)) @@ -100,7 +100,7 @@ public Long countUserByRole(String role) { * @return Account */ @Transactional - public Account findUserById(Long id) { + public Accounts findUserById(Long id) { return userRepository .findById(id) .orElseThrow(() -> new IllegalArgumentException(NOT_FOUND_USER_MESSAGE)); @@ -112,8 +112,8 @@ public Account findUserById(Long id) { * @return List 동명이인이 있을 수 있어서 List를 받는다. */ @Transactional - public List findUserByUserName(String userName) { - List users = userRepository.findByUserName(userName); + public List findUserByUserName(String userName) { + List users = userRepository.findByUserName(userName); if (users.isEmpty()) { throw new IllegalArgumentException(NOT_FOUND_USER_MESSAGE); } @@ -122,8 +122,8 @@ public List findUserByUserName(String userName) { @Override @Transactional - public Account findUserByYearAndUserName(String userName, Integer year) { - Account findUser = + public Accounts findUserByYearAndUserName(String userName, Integer year) { + Accounts findUser = userRepository.findByUserName(userName).stream() .filter(m -> m.getProfile().getYear().equals(year)) .collect(Collectors.toList()) @@ -134,18 +134,18 @@ public Account findUserByYearAndUserName(String userName, Integer year) { return findUser; } /** - * Get Account By One userEmail + * Get Accounts By One userEmail * - * @return Account + * @return Accounts */ @Transactional - public Account findUserByUserEmail(String idpId) { + public Accounts findUserByUserEmail(String idpId) { return userRepository .findById(Long.valueOf(idpId)) .orElseThrow(() -> new BadRequestException("없는 이메일입니다.")); } - // ----Account + // ----Accounts // Authentication------------------------------------------------------------------ /** @@ -158,7 +158,7 @@ public Account findUserByUserEmail(String idpId) { * ConfirmationToken findConfirmationToken = * confirmationTokenService.findByIdAndExpirationDateAfterAndExpired(uuid); * log.info(String.valueOf(findConfirmationToken.getId())); // 여기서 UserId가 Null Exception - * log.info(String.valueOf(findConfirmationToken.getUserId())); Account findUser = + * log.info(String.valueOf(findConfirmationToken.getUserId())); Accounts findUser = * userRepository.findById(findConfirmationToken.getUserId()) .orElseThrow(()->new * IllegalArgumentException(NOT_FOUND_USER_MESSAGE)); findConfirmationToken.useToken(); // 토큰 만료 * 로직을 구현해주면 된다. ex) expired 값을 true로 변경 findUser.emailVerifiedSuccess(); // 유저의 이메일 인증 값 변경 로직을 @@ -167,13 +167,13 @@ public Account findUserByUserEmail(String idpId) { // ------------------------------------------------------------------------------------- /** - * delete One Account Data @Param userId + * delete One Accounts Data @Param userId * * @return void */ public void deleteUserById(final Long userId) { // 관리자만 삭제할 수 있게 관리자 인증 추가 예정 - Account user = + Accounts user = userRepository .findById(userId) .orElseThrow(() -> new IllegalArgumentException(NOT_FOUND_USER_MESSAGE)); @@ -182,14 +182,14 @@ public void deleteUserById(final Long userId) { } /** - * update One Account Data @Param userEmail : String!, password : String!, year : Int!, userName - * : String! + * update One Accounts Data @Param userEmail : String!, password : String!, year : Int!, + * userName : String! * * @return boolean */ @Override - public Account updateUser(UserUpdateRequestDto userUpdateRequestDto) { - Account user = + public Accounts updateUser(UserUpdateRequestDto userUpdateRequestDto) { + Accounts user = userRepository .findUserByUserNameAndYear( userUpdateRequestDto.getUserName(), userUpdateRequestDto.getYear()) diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/common/handler/AccountRegisterEventHandler.java b/IDP-Api/src/main/java/com/econovation/idpapi/common/handler/AccountRegisterEventHandler.java index ce8c5d3..13b6bc1 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/common/handler/AccountRegisterEventHandler.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/common/handler/AccountRegisterEventHandler.java @@ -1,10 +1,10 @@ package com.econovation.idpapi.common.handler; -import com.econovation.idpapi.application.port.out.LoadAccountPort; import com.econovation.idpapi.application.service.ConfirmationTokenService; import com.econovation.idpdomain.common.events.user.AccountRegisterEvent; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; +import com.econovation.idpdomain.domains.users.port.LoadAccountPort; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; @@ -25,7 +25,7 @@ public class AccountRegisterEventHandler { phase = TransactionPhase.AFTER_COMPLETION) public void handleAccountRegisterEvent(AccountRegisterEvent accountRegisterEvent) { log.info(accountRegisterEvent.toString()); - Account account = loadAccountPort.loadById(accountRegisterEvent.getUserId()); + Accounts account = loadAccountPort.loadById(accountRegisterEvent.getUserId()); mailService.createEmailConfirmationToken(account.getId(), account.getProfile().getEmail()); } } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/LogConfig.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/LogConfig.java deleted file mode 100644 index b26f1da..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/LogConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.econovation.idpapi.config; - - -import com.econovation.idpapi.config.auth.AuthComponent; -import com.econovation.idpapi.config.auth.LogInterceptor; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -@RequiredArgsConstructor -public class LogConfig implements WebMvcConfigurer { - private final AuthComponent authComponent; - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new LogInterceptor(authComponent)); - } -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/SwaggerConfig.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/SwaggerConfig.java index f33cf5c..0f54ba4 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/SwaggerConfig.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/config/SwaggerConfig.java @@ -47,7 +47,7 @@ public class SwaggerConfig { public GroupedOpenApi AccountApi() { return GroupedOpenApi.builder() .group("AccountController") - .packagesToScan("com.econovation.idp.adapter.in.controller") +// .packagesToScan("com.econovation.idpapi.adapter.in.controller") .pathsToExclude("/api/users/**") .pathsToMatch("/api/accounts/**") .build(); @@ -57,7 +57,7 @@ public GroupedOpenApi AccountApi() { public GroupedOpenApi UserApi() { return GroupedOpenApi.builder() .group("UserController") - .packagesToScan("com.econovation.idp.adapter.in.controller") +// .packagesToScan("com.econovation.idpapi.adapter.in.controller") .pathsToExclude("/api/accounts/**") .pathsToMatch("/api/users/**") .build(); diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/Auth.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/Auth.java deleted file mode 100644 index c9014b9..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/Auth.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.econovation.idpapi.config.auth; - - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Auth { - Role role() default Role.GUEST; - - enum Role { - ADMIN, - USER, - GUEST - } -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/AuthComponent.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/AuthComponent.java deleted file mode 100644 index 62c17d9..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/AuthComponent.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.econovation.idpapi.config.auth; - - -import com.econovation.idpapi.config.jwt.JwtProvider; -import java.time.LocalDateTime; -import javax.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@RequiredArgsConstructor -@Component -@Slf4j -public class AuthComponent { - private final JwtProvider jwtProvider; - - public void validateUser(HttpServletRequest request) { - String accessToken = request.getHeader("Authorization").substring(7); - if (!jwtProvider.validateToken(request, accessToken).isAuthenticated()) { - log.info("[ " + LocalDateTime.now() + " ] not USER is Approach"); - } - } - - public void validateAdmin(HttpServletRequest request) { - String accessToken = request.getHeader("Authorization").substring(7); - if (!jwtProvider.validateToken(request, accessToken).isAuthenticated()) { - log.info("[ " + LocalDateTime.now() + " ] not ADMIN is Approach"); - } - } -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/LogInterceptor.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/LogInterceptor.java deleted file mode 100644 index 60dacda..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/auth/LogInterceptor.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.econovation.idpapi.config.auth; - - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; - -@Slf4j -@Component -@RequiredArgsConstructor -public class LogInterceptor implements HandlerInterceptor { - - private final AuthComponent authComponent; - - @Override - public boolean preHandle( - HttpServletRequest request, HttpServletResponse response, Object handler) { - if (!(handler instanceof HandlerMethod)) { - return true; - } - HandlerMethod handlerMethod = (HandlerMethod) handler; - - Auth auth = handlerMethod.getMethodAnnotation(Auth.class); - if (auth == null) { - return true; - } - // 비회원인지 인증 - if (auth.role().compareTo(Auth.Role.GUEST) == 0) { - return true; - } - - if (auth.role().compareTo(Auth.Role.USER) == 0) { - authComponent.validateUser(request); - } - // 그룹에 속해있는 멤버인지 확인 (관리자 or 일반 멤버) - if (auth.role().compareTo(Auth.Role.ADMIN) == 0) { - authComponent.validateAdmin(request); - } - return true; - } -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtAuthenticationFilter.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtAuthenticationFilter.java index 9b8174b..5ffdf67 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtAuthenticationFilter.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtAuthenticationFilter.java @@ -1,7 +1,7 @@ package com.econovation.idpapi.config.jwt; -import com.econovation.idpcommon.properties.JwtProperties; +import com.econovation.idpapi.application.service.AccountJwtService; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -21,9 +21,7 @@ @Slf4j @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { - - private final JwtProvider jwtProvider; - private final JwtProperties jwtProperties; + private final AccountJwtService accountJwtService; @Override protected void doFilterInternal( @@ -32,7 +30,7 @@ protected void doFilterInternal( String token = resolveToken(request.getHeader("Authorization")); boolean isLogin = false; if (token != null) { - Authentication authentication = jwtProvider.validateToken(request, token); + Authentication authentication = accountJwtService.validateToken(request, token); SecurityContextHolder.getContext().setAuthentication(authentication); isLogin = true; } @@ -59,7 +57,7 @@ protected void doFilterInternal( log.info(request.getRequestURI().toString()); } - private String resolveToken(String authorization) { + public String resolveToken(String authorization) { return authorization != null ? authorization.substring(7) : null; } } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/redis/RedisConfig.java b/IDP-Api/src/main/java/com/econovation/idpapi/config/redis/RedisConfig.java deleted file mode 100644 index 705e13e..0000000 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/redis/RedisConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.econovation.idpapi.config.redis; - - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.StringRedisSerializer; - -@Configuration -public class RedisConfig { - - @Value("${spring.data.redis.host}") - private String host; - - @Value("${spring.data.redis.port}") - private int port; - - // Redis Configuration - @Bean - public RedisConnectionFactory redisConnectionFactory() { - return new LettuceConnectionFactory(host, port); - } - - @Bean - public RedisTemplate redisTemplate() { - RedisTemplate redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new StringRedisSerializer()); - redisTemplate.setConnectionFactory(redisConnectionFactory()); - return redisTemplate; - } -} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/utils/AuthenticationValidator.java b/IDP-Api/src/main/java/com/econovation/idpapi/utils/AuthenticationValidator.java new file mode 100644 index 0000000..e2fd535 --- /dev/null +++ b/IDP-Api/src/main/java/com/econovation/idpapi/utils/AuthenticationValidator.java @@ -0,0 +1,3 @@ +package com.econovation.idpapi.utils; + +public class AuthenticationValidator {} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/utils/EntityMapper.java b/IDP-Api/src/main/java/com/econovation/idpapi/utils/EntityMapper.java index 2b55748..e7d90d8 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/utils/EntityMapper.java +++ b/IDP-Api/src/main/java/com/econovation/idpapi/utils/EntityMapper.java @@ -2,12 +2,12 @@ import com.econovation.idpdomain.domains.dto.UserResponseMatchedTokenDto; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import org.springframework.stereotype.Component; @Component public class EntityMapper { - public UserResponseMatchedTokenDto toUserResponseMatchedTokenDto(Account account) { + public UserResponseMatchedTokenDto toUserResponseMatchedTokenDto(Accounts account) { return UserResponseMatchedTokenDto.builder() .id(account.getId()) .profile(account.getProfile()) diff --git a/IDP-Api/src/main/resources/application.yml b/IDP-Api/src/main/resources/application.yml index f6e3cd7..336974c 100644 --- a/IDP-Api/src/main/resources/application.yml +++ b/IDP-Api/src/main/resources/application.yml @@ -4,17 +4,11 @@ spring: - infrastructure - domain - common - data: - redis: - host: ${REDIS_HOST:localhost} - port: ${REDIS_PORT:6379} throttle: greedyRefill: ${THROTTLE_GREEDY_REFILL:10} overdraft: ${THROTTLE_OVERDRAFT:10} -auth: - jwt: - blacklist: - prefix: ${JWT_BLACKLIST_PREFIX:BlackList_AccessToken_} + + login: page: url: ${LOGIN_PAGE_URL:http://localhost:8080/login} @@ -24,13 +18,16 @@ login: url: ${LOGIN_FAILURE_URL:http://localhost:8080/loginFailure} acl: whiteList: ${ACL_WHITE_LIST:localhost} - +auth: + jwt: + blacklist: + prefix: ${JWT_BLACKLIST_PREFIX:jwt_blacklist_} springdoc: version: v1 default-produces-media-type: application/json default-consumes-media-type: application/json - packages-to-scan: com.econovation.idp - path-to-match: /api/** + packages-to-scan: com.econovation.idpapi +# path-to-match: /** swagger-ui: path: /swagger-ui.html tags-sorter: alpha @@ -52,6 +49,8 @@ swagger: mail: destination: url: ${MAIL_DESTINATION_URL:http://localhost:8080} +file: + path: ${IMAGE_SAVE_URL:classpath:static/images/} --- spring: config: diff --git "a/IDP-Api/src/main/resources/\343\205\201\343\205\201.properties" "b/IDP-Api/src/main/resources/\343\205\201\343\205\201.properties" deleted file mode 100644 index e90f32d..0000000 --- "a/IDP-Api/src/main/resources/\343\205\201\343\205\201.properties" +++ /dev/null @@ -1,35 +0,0 @@ -#spring.profiles.include=infrastructure,domain,common -# -# -##h2 console -##spring.h2.console.enabled=true -##spring.h2.console.path=/h2-console -#server.error.include-exception=false -#server.error.include-stacktrace=never -#server.servlet.encoding.charset=UTF-8 -#server.servlet.encoding.force-response=true -#logging.level.org.springframework.web=DEBUG -#spring.mvc.log-request-details=true -# -#management.health.mail.enabled=false -#management.endpoints.web.exposure.include= * -#management.endpoint.health.show-details= always -# - -# -## logging -##logging.level.root=INFO -#logging.level.org.hibernate.SQL = DEBUG -#logging.level.org.springframework.boot.autoconfigure = ERROR -##HikariCP -#spring.datasource.hikari.maximum-pool-size=30 -# -#sending.email = localhost:8080 -#debug=true -# -#login.page.url = https://auth.econovation.kr/ -## Image Management -#file.path=/Users/blackbean/IdeaProjects/ECONOVATION_IDP/image/ -#server.port=8080 -#batchSize = 500 -#rows = 10000 \ No newline at end of file diff --git a/IDP-Common/build.gradle b/IDP-Common/build.gradle index 63ab387..0b8b8b5 100644 --- a/IDP-Common/build.gradle +++ b/IDP-Common/build.gradle @@ -1,11 +1,12 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.10.1' implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.1' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' api 'org.springframework.boot:spring-boot-starter-aop' + api project(':IDP-Infrastructure') + } bootJar.enabled = false diff --git a/IDP-Common/src/main/java/com/econovation/idpcommon/config/EnableConfigProperties.java b/IDP-Common/src/main/java/com/econovation/idpcommon/config/EnableConfigProperties.java new file mode 100644 index 0000000..e4b0042 --- /dev/null +++ b/IDP-Common/src/main/java/com/econovation/idpcommon/config/EnableConfigProperties.java @@ -0,0 +1,10 @@ +package com.econovation.idpcommon.config; + + +import com.econovation.idpcommon.properties.JwtProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@EnableConfigurationProperties({JwtProperties.class}) +@Configuration +public class EnableConfigProperties {} diff --git a/IDP-Common/src/main/java/com/econovation/idpcommon/exception/InvalidTokenException.java b/IDP-Common/src/main/java/com/econovation/idpcommon/exception/InvalidTokenException.java index 75c89c7..dfde065 100644 --- a/IDP-Common/src/main/java/com/econovation/idpcommon/exception/InvalidTokenException.java +++ b/IDP-Common/src/main/java/com/econovation/idpcommon/exception/InvalidTokenException.java @@ -3,7 +3,7 @@ public class InvalidTokenException extends IdpCodeException { public static final IdpCodeException EXCEPTION = new InvalidTokenException(); - private InvalidTokenException() { + public InvalidTokenException() { super(GlobalErrorCode.INVALID_TOKEN); } } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtProvider.java b/IDP-Common/src/main/java/com/econovation/idpcommon/jwt/JwtProvider.java similarity index 71% rename from IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtProvider.java rename to IDP-Common/src/main/java/com/econovation/idpcommon/jwt/JwtProvider.java index 8547bc1..c1674ac 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/config/jwt/JwtProvider.java +++ b/IDP-Common/src/main/java/com/econovation/idpcommon/jwt/JwtProvider.java @@ -1,10 +1,8 @@ -package com.econovation.idpapi.config.jwt; +package com.econovation.idpcommon.jwt; import static com.econovation.idpcommon.consts.IdpStatic.*; -import com.econovation.idpapi.application.port.in.JwtProviderUseCase; -import com.econovation.idpapi.common.redis.RedisService; -import com.econovation.idpapi.config.security.AuthDetails; +import com.econovation.idp.redis.RedisService; import com.econovation.idpcommon.dto.AccessTokenInfo; import com.econovation.idpcommon.exception.ExpiredTokenException; import com.econovation.idpcommon.exception.GetExpiredTimeException; @@ -14,35 +12,24 @@ import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; import java.nio.charset.StandardCharsets; import java.security.Key; import java.time.Duration; import java.util.Date; -import javax.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor @Slf4j -public class JwtProvider implements JwtProviderUseCase { +public class JwtProvider { private final RedisService redisService; - private final JwtProperties jwtProperties; - @Value("${auth.jwt.blacklist.prefix}") - private String blackListATPrefix; - - private Jws getJws(String token) { + public Jws getJws(String token) { try { return Jwts.parserBuilder().setSigningKey(getSecretKey()).build().parseClaimsJws(token); } catch (ExpiredJwtException e) { @@ -53,17 +40,16 @@ private Jws getJws(String token) { } private Key getSecretKey() { - return Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8)); + return Keys.hmacShaKeyFor(jwtProperties.getSecretKey().getBytes(StandardCharsets.UTF_8)); } - @Override public void logout(String refreshToken) throws GetExpiredTimeException { long expiredAccessTokenTime = getExpiredTime(refreshToken).getTime() - new Date().getTime(); // 이메일 조회 // accessToken To userEmail Long idpId = getIdpId(refreshToken); redisService.setValues( - blackListATPrefix + refreshToken, + jwtProperties.getSecretKey() + refreshToken, String.valueOf(idpId), Duration.ofMillis(expiredAccessTokenTime)); redisService.deleteValues(String.valueOf(idpId)); // Delete RefreshToken In Redis @@ -84,14 +70,12 @@ private String createToken(Integer idpId, String role, long tokenInvalidTime) { } // accessToken 은 redis에 저장하지 않는다. - @Override public String createAccessToken(Long idpId, String role) { long tokenInvalidTime = 1000L * 60 * 60; // 1h return this.createToken(Math.toIntExact(idpId), role, tokenInvalidTime); } // refreshToken 은 redis 에 저장해야한다. - @Override public String createRefreshToken(Long idpId, String role) { // String refreshToken = this.createToken(Math.toIntExact(idpId), role, // tokenInvalidTime); @@ -99,20 +83,21 @@ public String createRefreshToken(Long idpId, String role) { final Date issuedAt = new Date(); // integer MILLT_TOSECOND to Long final Date refreshTokenExpiresIn = - new Date(issuedAt.getTime() + jwtProperties.getRefresh() * MILLI_TO_SECOND); + new Date(issuedAt.getTime() + jwtProperties.getRefreshExp() * MILLI_TO_SECOND); String refreshToken = buildRefreshToken(idpId, issuedAt, refreshTokenExpiresIn); redisService.setValues( String.valueOf(idpId), refreshToken, - Duration.ofMillis(jwtProperties.getRefresh() * MILLI_TO_SECOND)); + Duration.ofMillis(jwtProperties.getRefreshExp() * MILLI_TO_SECOND)); return refreshToken; } public String generateAccessToken(Long id, String role) { final Date issuedAt = new Date(); + final Date accessTokenExpiresIn = - new Date(issuedAt.getTime() + jwtProperties.getAccess() * MILLI_TO_SECOND); + new Date(issuedAt.getTime() + jwtProperties.getAccessExp() * MILLI_TO_SECOND); return buildAccessToken(id, issuedAt, accessTokenExpiresIn, role); } @@ -120,7 +105,7 @@ public String generateAccessToken(Long id, String role) { public String generateRefreshToken(Long id) { final Date issuedAt = new Date(); final Date refreshTokenExpiresIn = - new Date(issuedAt.getTime() + jwtProperties.getRefresh() * MILLI_TO_SECOND); + new Date(issuedAt.getTime() + jwtProperties.getRefreshExp() * MILLI_TO_SECOND); return buildRefreshToken(id, issuedAt, refreshTokenExpiresIn); } @@ -150,7 +135,6 @@ private String buildRefreshToken(Long id, Date issuedAt, Date accessTokenExpires .compact(); } - @Override public Long getIdpId(String token) { final Key secretKey = getSecretKey(); Long aLong = @@ -163,7 +147,6 @@ public Long getIdpId(String token) { return aLong; } - @Override public Date getExpiredTime(String token) throws GetExpiredTimeException { final Key secretKey = getSecretKey(); try { @@ -174,39 +157,6 @@ public Date getExpiredTime(String token) throws GetExpiredTimeException { } } - @Override - public Authentication validateToken(HttpServletRequest request, String token) { - String exception = "exception"; - final Key secretKey = getSecretKey(); - try { - String expiredAT = redisService.getValues(blackListATPrefix + token); - if (expiredAT != null) { - throw new ExpiredJwtException(null, null, null); - } - // Jws claimsJws = - // Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); - log.info("validateToken : {}", token); - return getAuthentication(token); - } catch (MalformedJwtException | UnsupportedJwtException e) { - request.setAttribute(exception, "토큰의 형식을 확인하세요"); - } catch (ExpiredJwtException e) { - request.setAttribute(exception, "토큰이 만료되었습니다."); - } catch (IllegalArgumentException e) { - request.setAttribute(exception, "JWT compact of handler are invalid"); - } - return null; - } - - public boolean isAccessToken(String token) { - // npe - log.info(getJws(token).getBody().get(TOKEN_TYPE).toString()); - return getJws(token).getBody().get(TOKEN_TYPE).equals(ACCESS_TOKEN); - } - - public boolean isRefreshToken(String token) { - return getJws(token).getBody().get(TOKEN_TYPE).equals(REFRESH_TOKEN); - } - public AccessTokenInfo parseAccessToken(String token) { if (isAccessToken(token)) { Claims claims = getJws(token).getBody(); @@ -218,12 +168,13 @@ public AccessTokenInfo parseAccessToken(String token) { throw InvalidTokenException.EXCEPTION; } - public Authentication getAuthentication(String token) { - AccessTokenInfo accessTokenInfo = parseAccessToken(token); + public boolean isAccessToken(String token) { + // npe + log.info(getJws(token).getBody().get(TOKEN_TYPE).toString()); + return getJws(token).getBody().get(TOKEN_TYPE).equals(ACCESS_TOKEN); + } - UserDetails userDetails = - new AuthDetails(accessTokenInfo.getUserId().toString(), accessTokenInfo.getRole()); - return new UsernamePasswordAuthenticationToken( - userDetails, "user", userDetails.getAuthorities()); + public boolean isRefreshToken(String token) { + return getJws(token).getBody().get(TOKEN_TYPE).equals(REFRESH_TOKEN); } } diff --git a/IDP-Common/src/main/java/com/econovation/idpcommon/properties/JwtProperties.java b/IDP-Common/src/main/java/com/econovation/idpcommon/properties/JwtProperties.java index 07f35a2..fa656f2 100644 --- a/IDP-Common/src/main/java/com/econovation/idpcommon/properties/JwtProperties.java +++ b/IDP-Common/src/main/java/com/econovation/idpcommon/properties/JwtProperties.java @@ -1,19 +1,17 @@ package com.econovation.idpcommon.properties; +import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConstructorBinding; -import org.springframework.stereotype.Component; @Getter -@Setter -@Component +@AllArgsConstructor @ConstructorBinding @ConfigurationProperties(prefix = "auth.jwt") public class JwtProperties { - private String secret; - private Integer access; - private Integer refresh; + private String secretKey; + private Long accessExp; + private Long refreshExp; } diff --git a/IDP-Common/src/main/resources/application-common.yml b/IDP-Common/src/main/resources/application-common.yml index e61be6f..bff5d3c 100644 --- a/IDP-Common/src/main/resources/application-common.yml +++ b/IDP-Common/src/main/resources/application-common.yml @@ -1,9 +1,8 @@ auth: jwt: - secret: ${JWT_SECRET_KEY:testkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkey} - access: ${JWT_ACCESS_EXP:3600} - refresh: ${JWT_REFRESH_EXP:86400} - + secret-key: ${JWT_SECRET_KEY:testkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkey} + access-exp: ${JWT_ACCESS_EXP:3600} + refresh-exp: ${JWT_REFRESH_EXP:86400} # Redis Dependencies - Login, Logout ???? #spring.jwt.secret-key =SECRET_KEY #spring.jwt.blacklist.access-token =BlackList_AccessToken_ diff --git a/IDP-Domain/build.gradle b/IDP-Domain/build.gradle index 340e7a6..2edaa49 100644 --- a/IDP-Domain/build.gradle +++ b/IDP-Domain/build.gradle @@ -3,12 +3,11 @@ jar { enabled = true } dependencies { // multipart - api 'org.springframework.boot:spring-boot-starter-web' api 'org.springframework.boot:spring-boot-starter-data-jpa' api 'mysql:mysql-connector-java' // h2 driver - runtimeOnly 'com.h2database:h2' +// runtimeOnly 'com.h2database:h2' implementation project(':IDP-Common') implementation project(':IDP-Infrastructure') diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/dto/ImageUploadDto.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/dto/ImageUploadDto.java index 88a04cb..f43ff3a 100644 --- a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/dto/ImageUploadDto.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/dto/ImageUploadDto.java @@ -2,7 +2,7 @@ import com.econovation.idpdomain.domains.images.Image; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import lombok.Data; import org.springframework.web.multipart.MultipartFile; @@ -12,7 +12,7 @@ public class ImageUploadDto { private MultipartFile file; private String caption; - public Image toEntity(Account account, String post_image_url) { + public Image toEntity(Accounts account, String post_image_url) { return Image.builder() .account(account) .post_image_url(post_image_url) diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/Image.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/Image.java index 92d7a89..e6769f9 100644 --- a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/Image.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/Image.java @@ -1,7 +1,7 @@ package com.econovation.idpdomain.domains.images; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import com.econovation.idpdomain.domains.users.domain.BaseTimeEntity; import javax.persistence.*; import lombok.*; @@ -21,6 +21,6 @@ public class Image extends BaseTimeEntity { private String post_image_url; // 사진을 전달받아서 서버의 특정 폴더에 저장할 것이므로 사진이 저장된 경로를 저장 @ManyToOne - @JoinColumn(name = "account_id") - private Account account; + @JoinColumn(name = "accounts_id") + private Accounts account; } diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/ImageRepository.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/ImageRepository.java index 6d48b3b..5aef6bc 100644 --- a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/ImageRepository.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/images/ImageRepository.java @@ -1,12 +1,12 @@ package com.econovation.idpdomain.domains.images; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpdomain.domains.users.domain.Accounts; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ImageRepository extends JpaRepository { - List findByAccount(Account account); + List findByAccount(Accounts account); } diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/out/persistence/AccountPersistenceAdapter.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/adaptor/AccountAdaptor.java similarity index 63% rename from IDP-Api/src/main/java/com/econovation/idpapi/adapter/out/persistence/AccountPersistenceAdapter.java rename to IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/adaptor/AccountAdaptor.java index 4cc7346..d52aa88 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/adapter/out/persistence/AccountPersistenceAdapter.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/adaptor/AccountAdaptor.java @@ -1,43 +1,43 @@ -package com.econovation.idpapi.adapter.out.persistence; +package com.econovation.idpdomain.domains.users.adaptor; -import com.econovation.idpapi.application.port.out.LoadAccountPort; -import com.econovation.idpapi.application.port.out.RecordAccountPort; -import com.econovation.idpdomain.domains.users.domain.Account; +import com.econovation.idpcommon.annotation.Adaptor; import com.econovation.idpdomain.domains.users.domain.AccountRepository; import com.econovation.idpdomain.domains.users.domain.AccountRole; +import com.econovation.idpdomain.domains.users.domain.Accounts; +import com.econovation.idpdomain.domains.users.port.LoadAccountPort; +import com.econovation.idpdomain.domains.users.port.RecordAccountPort; import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Component; -@Component +@Adaptor @Slf4j @RequiredArgsConstructor -public class AccountPersistenceAdapter implements LoadAccountPort, RecordAccountPort { +public class AccountAdaptor implements LoadAccountPort, RecordAccountPort { private static final String NO_MATCH_ACCOUNT = "해당하는 ACCOUNT가 존재하지 않습니다"; private final AccountRepository accountRepository; @Override public boolean existsAccountByUserEmail(String email) { - return accountRepository.existsAccountByUserEmail(email); + return accountRepository.existsAccountsByUserEmail(email); } @Override - public List loadByUserName(String userName) { + public List loadByUserName(String userName) { return accountRepository.findByUserName(userName); } @Override - public Optional loadByUserEmail(String email) { + public Optional loadByUserEmail(String email) { return accountRepository.findByUserEmail(email); } @Override - public Page loadAllByPage(Pageable pageable) { + public Page loadAllByPage(Pageable pageable) { return accountRepository.findAll(pageable); } @@ -47,23 +47,23 @@ public Long countAllByRole(AccountRole role) { } @Override - public Account loadById(Long id) { + public Accounts loadById(Long id) { return accountRepository .findById(id) .orElseThrow(() -> new IllegalArgumentException(NO_MATCH_ACCOUNT)); } @Override - public Optional loadUserByUserNameAndYear(String userName, Integer year) { + public Optional loadUserByUserNameAndYear(String userName, Integer year) { return accountRepository.findUserByUserNameAndYear(userName, year); } @Override - public Account save(Account account) { + public Accounts save(Accounts account) { return accountRepository.save(account); } - public Account loadAccountByUserEmail(String email) { + public Accounts loadAccountByUserEmail(String email) { return accountRepository .findByUserEmail(email) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다.")); diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/AccountRepository.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/AccountRepository.java index 502876d..2636270 100644 --- a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/AccountRepository.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/AccountRepository.java @@ -12,32 +12,32 @@ import org.springframework.stereotype.Repository; @Repository -public interface AccountRepository extends JpaRepository { +public interface AccountRepository extends JpaRepository { - List findAll(); + List findAll(); @Query( - "SELECT CASE WHEN COUNT(a) > 0 THEN true ELSE false END FROM Account a WHERE a.profile.email = :email") - boolean existsAccountByUserEmail(@Param("email") String email); + "SELECT CASE WHEN COUNT(a) > 0 THEN true ELSE false END FROM Accounts a WHERE a.profile.email = :email") + boolean existsAccountsByUserEmail(@Param("email") String email); - @Query("SELECT u FROM Account u WHERE u.profile.name = :name") - List findByUserName(@Param("name") String name); + @Query("SELECT u FROM Accounts u WHERE u.profile.name = :name") + List findByUserName(@Param("name") String name); - @Query("SELECT u FROM Account u WHERE u.profile.email = :email") - Optional findByUserEmail(@Param("email") String email); + @Query("SELECT u FROM Accounts u WHERE u.profile.email = :email") + Optional findByUserEmail(@Param("email") String email); - Page findAll(Pageable pageable); + Page findAll(Pageable pageable); - Slice findSliceBy(Pageable pageable); + Slice findSliceBy(Pageable pageable); - @Query("SELECT COUNT(a) FROM Account a WHERE a.accountRole = :role") + @Query("SELECT COUNT(a) FROM Accounts a WHERE a.accountRole = :role") Long countAllByRole(@Param("role") AccountRole role); - @Query("SELECT u FROM Account u WHERE u.password = :password") - Optional findByPassword(@Param("password") String password); + @Query("SELECT u FROM Accounts u WHERE u.password = :password") + Optional findByPassword(@Param("password") String password); - @Query("SELECT u FROM Account u WHERE u.profile.name = :name AND u.profile.year = :year") - Optional findUserByUserNameAndYear( + @Query("SELECT u FROM Accounts u WHERE u.profile.name = :name AND u.profile.year = :year") + Optional findUserByUserNameAndYear( @Param("name") String name, @Param("year") Integer year); /* 유효성 검사 - 중복 체크 diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Account.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Accounts.java similarity index 92% rename from IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Account.java rename to IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Accounts.java index 0df0af9..f958894 100644 --- a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Account.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Accounts.java @@ -1,6 +1,5 @@ package com.econovation.idpdomain.domains.users.domain; - import com.econovation.idpdomain.common.aop.domainEvent.Events; import com.econovation.idpdomain.common.events.user.AccountRegisterEvent; import com.econovation.idpdomain.domains.dto.NonAccountResponseDto; @@ -16,7 +15,6 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.PostPersist; -import javax.persistence.Table; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -26,17 +24,16 @@ @Entity @Getter -@AllArgsConstructor @NoArgsConstructor +@AllArgsConstructor @DynamicInsert @Slf4j @Builder -@Table(name = "accounts") -public class Account extends BaseTimeEntity { +public class Accounts extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "account_id") + @Column(name = "accounts_id") private Long id; private String password; @@ -74,7 +71,7 @@ public void login() { lastLoginAt = LocalDateTime.now(); } - public Account(Profile profile, String password) { + public Accounts(Profile profile, String password) { this.profile = profile; this.password = password; } @@ -83,7 +80,7 @@ public void update(UserUpdateRequestDto userUpdateRequestDto) { this.profile = userUpdateRequestDto.toProfile(userUpdateRequestDto); } - public NonAccountResponseDto toNonLoginUser(Account account) { + public NonAccountResponseDto toNonLoginUser(Accounts account) { return new NonAccountResponseDto( account.profile.getYear(), account.profile.getName(), account.getId()); } diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Profile.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Profile.java index 7747037..7d6c14c 100644 --- a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Profile.java +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/domain/Profile.java @@ -9,7 +9,7 @@ @Embeddable @Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor public class Profile { private String name; private String email; diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/port/LoadAccountPort.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/port/LoadAccountPort.java new file mode 100644 index 0000000..0ba2762 --- /dev/null +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/port/LoadAccountPort.java @@ -0,0 +1,27 @@ +package com.econovation.idpdomain.domains.users.port; + + +import com.econovation.idpcommon.annotation.Port; +import com.econovation.idpdomain.domains.users.domain.AccountRole; +import com.econovation.idpdomain.domains.users.domain.Accounts; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +@Port +public interface LoadAccountPort { + boolean existsAccountByUserEmail(String email); + + List loadByUserName(String userName); + + Optional loadByUserEmail(String userEmail); + + Page loadAllByPage(Pageable pageable); + + Long countAllByRole(AccountRole role); + + Accounts loadById(Long id); + + Optional loadUserByUserNameAndYear(String userName, Integer year); +} diff --git a/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/port/RecordAccountPort.java b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/port/RecordAccountPort.java new file mode 100644 index 0000000..256822d --- /dev/null +++ b/IDP-Domain/src/main/java/com/econovation/idpdomain/domains/users/port/RecordAccountPort.java @@ -0,0 +1,10 @@ +package com.econovation.idpdomain.domains.users.port; + + +import com.econovation.idpcommon.annotation.Port; +import com.econovation.idpdomain.domains.users.domain.Accounts; + +@Port +public interface RecordAccountPort { + Accounts save(Accounts account); +} diff --git a/IDP-Domain/src/main/resources/application-domain.yml b/IDP-Domain/src/main/resources/application-domain.yml index 0447683..9a8d4f3 100644 --- a/IDP-Domain/src/main/resources/application-domain.yml +++ b/IDP-Domain/src/main/resources/application-domain.yml @@ -4,15 +4,14 @@ spring: activate: on-profile: local datasource: - url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${DB_NAME}?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&tinyInt1isBit=false + url: jdbc:mysql://${MYSQL_HOST:econovation}:${MYSQL_PORT:3306}/${DB_NAME:econovation}?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&tinyInt1isBit=false driver-class-name: com.mysql.cj.jdbc.Driver hikari: maxLifetime: 580000 - maximum-pool-size: 10 - password: ${MYSQL_PASSWORD} - username: ${MYSQL_USERNAME:root} + maximum-pool-size: 20 + password: ${MYSQL_PASSWORD:root} + username: ${MYSQL_USERNAME:dltjgus119@@} jpa: - generate-ddl: true show-sql: ${SHOW_SQL:true} properties: hibernate: @@ -33,15 +32,6 @@ logging: org.springframework.orm.jpa: DEBUG org.springframework.transaction: DEBUG org.springframework.aop: DEBUG - - ---- -spring: - config: - activate: - on-profile: test - datasource: - url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=MYSQL --- spring: config: @@ -56,17 +46,33 @@ spring: password: ${MYSQL_PASSWORD} username: ${MYSQL_USERNAME} jpa: + show-sql: ${SHOW_SQL:true} generate-ddl: true properties: hibernate: default_batch_fetch_size: ${JPA_BATCH_FETCH_SIZE:100} + format_sql: ${FORMAT_SQL:true} hibernate: ddl-auto: update + sql: + init: + mode: always + open-in-view: false database-platform: org.hibernate.dialect.MySQL5InnoDBDialect logging: level: + com.zaxxer.hikari.HikariConfig: DEBUG + com.zaxxer.hikari: TRACE org.springframework.orm.jpa: DEBUG org.springframework.transaction: DEBUG + org.springframework.aop: DEBUG +--- +spring: + config: + activate: + on-profile: test + datasource: + url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=MYSQL --- spring: config: diff --git a/IDP-Infrastructure/build.gradle b/IDP-Infrastructure/build.gradle index 20fbacd..82317f6 100644 --- a/IDP-Infrastructure/build.gradle +++ b/IDP-Infrastructure/build.gradle @@ -12,6 +12,7 @@ dependencies { testImplementation "org.springframework.cloud:spring-cloud-starter-contract-stub-runner:3.1.5" testImplementation "org.springframework.cloud:spring-cloud-contract-wiremock:3.1.5" +// api project(':IDP-Common') } tasks.named('test') { diff --git a/IDP-Infrastructure/src/main/java/com/econovation/idp/redis/RedisConfig.java b/IDP-Infrastructure/src/main/java/com/econovation/idp/redis/RedisConfig.java new file mode 100644 index 0000000..72ae332 --- /dev/null +++ b/IDP-Infrastructure/src/main/java/com/econovation/idp/redis/RedisConfig.java @@ -0,0 +1,57 @@ +package com.econovation.idp.redis; + + +import java.time.Duration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + /* @Value("${spring.data.redis.host}") + private String redisHost; + + @Value("${spring.data.redis.password}") + private String redisPassword; + + @Value("${spring.data.redis.port}") + private int redisPort;*/ + + // Redis Configuration + // @Bean + // public RedisConnectionFactory redisConnectionFactory() { + // return new LettuceConnectionFactory(host, port); + // } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + return redisTemplate; + } + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisConfig = + new RedisStandaloneConfiguration("localhost", 3306); + + // if (redisPassword != null && !redisPassword.isBlank()) + // redisConfig.setPassword(redisPassword); + redisConfig.setPassword(""); + + LettuceClientConfiguration clientConfig = + LettuceClientConfiguration.builder() + .commandTimeout(Duration.ofSeconds(1)) + .shutdownTimeout(Duration.ZERO) + .build(); + return new LettuceConnectionFactory(redisConfig, clientConfig); + } +} diff --git a/IDP-Api/src/main/java/com/econovation/idpapi/common/redis/RedisService.java b/IDP-Infrastructure/src/main/java/com/econovation/idp/redis/RedisService.java similarity index 95% rename from IDP-Api/src/main/java/com/econovation/idpapi/common/redis/RedisService.java rename to IDP-Infrastructure/src/main/java/com/econovation/idp/redis/RedisService.java index 5be64ea..b524fbc 100644 --- a/IDP-Api/src/main/java/com/econovation/idpapi/common/redis/RedisService.java +++ b/IDP-Infrastructure/src/main/java/com/econovation/idp/redis/RedisService.java @@ -1,4 +1,4 @@ -package com.econovation.idpapi.common.redis; +package com.econovation.idp.redis; import java.time.Duration; diff --git a/IDP-Infrastructure/src/main/resources/application-infrastructure.yml b/IDP-Infrastructure/src/main/resources/application-infrastructure.yml index 70a92f1..da871bd 100644 --- a/IDP-Infrastructure/src/main/resources/application-infrastructure.yml +++ b/IDP-Infrastructure/src/main/resources/application-infrastructure.yml @@ -1,7 +1,9 @@ -file: - path: ${IMAGE_SAVE_URL:classpath:static/images/} - spring: + data: + redis: + host: ${REDIS_HOST:localhost} + password: ${REDIS_PASSWORD:} + port: ${REDIS_PORT:6379} mail: host: smtp.gmail.com port: 587 diff --git a/build.gradle b/build.gradle index b201c3d..da5df71 100644 --- a/build.gradle +++ b/build.gradle @@ -101,6 +101,9 @@ subprojects { annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-security' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' testCompileOnly 'org.projectlombok:lombok' diff --git a/docker-compose.yml b/docker-compose.yml index 8634066..c9e2dbf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,48 +1,48 @@ -version: "3.7" -services: - redis: - image: "redis:alpine" - ports: - - "6379:6379" - environment: - - TZ=Asia/Seoul - -# --------------------------------------------------------- -#version: "3" +#version: "3.7" #services: -# db: -# restart: always -# image: mysql:8.0 -# ports: -# - 3308:3306 -# environment: -# - ./db/conf.d:/etc/mysql/conf.d -# - ./db/data/:/var/lib/mysql/ -# - MYSQL_ROOT_PASSWORD=dltjgus119 -# - TZ=Asia/Seoul -# - MYSQL_DATABASE=econovation # redis: -# container_name: redis -# image: redis +# image: "redis:alpine" # ports: -# - 6379:6379 -# command: ["redis-server", "--protected-mode", "no"] -# extra_hosts: -# - "host.docker.internal:host-gateway" -# app: -# build: . +# - "6379:6379" # environment: -# SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/econovation?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul -# SPRING_DATASOURCE_USERNAME: root -# SPRING_DATASOURCE_PASSWORD: dltjgus119 -# container_name: spring-app -# image: blackbean99/econovation_idp:latest -# links: -# - redis -# ports: -# - 8080:8080 -# depends_on: -# - db -# - redis -# restart: always -# tty: true \ No newline at end of file +# - TZ=Asia/Seoul + +# --------------------------------------------------------- +version: "3" +services: + db: + restart: always + image: mysql:8.0 + ports: + - 3308:3306 + environment: + - ./db/conf.d:/etc/mysql/conf.d + - ./db/data/:/var/lib/mysql/ + - MYSQL_ROOT_PASSWORD=dltjgus119 + - TZ=Asia/Seoul + - MYSQL_DATABASE=econovation + redis: + container_name: redis + image: redis + ports: + - 6379:6379 + command: ["redis-server", "--protected-mode", "no"] + extra_hosts: + - "host.docker.internal:host-gateway" + app: + build: . + environment: + SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/econovation?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul + SPRING_DATASOURCE_USERNAME: root + SPRING_DATASOURCE_PASSWORD: dltjgus119 + container_name: spring-app + image: blackbean99/econovation_idp:latest + links: + - redis + ports: + - 8080:8080 + depends_on: + - db + - redis + restart: always + tty: true \ No newline at end of file