-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(User): 회원 정보에 권한 추가 * feat(User): API Docs 설정 추가 * feat(User): 회원가입 API 추가 * feat(Login): Redis에 JWT 정보를 기록 * feat(Login): JWT 로그인 구현 * feat(Login): JWT 재발급 구현 * refactor(Login): Device Tag를 이용하여 자동 회원가입 및 로그인이 가능하도록 처리 * refactor(User): 회원가입 API 제거 * refactor(Login): User 테이블 컬럼명(id->device_tag) 변경, 회원가입시 UUID를 통해 랜덤 비밀번호를 생성하도록 설정 * refactor(Login): 토큰을 헤더에 담아 반환하도록 변경 * refactor(User): 회원가입시 비밀번호를 지정 가능하게 변경 * refactor(User): 비밀번호 생성 로직 강화 * refactor(Test): 미사용 테스트 코드 제거
- Loading branch information
Showing
35 changed files
with
949 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/main/java/com/stempo/api/domain/application/service/LoginService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import com.stempo.api.domain.presentation.dto.response.TokenInfo; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
|
||
public interface LoginService { | ||
|
||
TokenInfo loginOrRegister(String deviceTag, String password); | ||
|
||
TokenInfo reissueToken(HttpServletRequest request); | ||
} |
53 changes: 53 additions & 0 deletions
53
src/main/java/com/stempo/api/domain/application/service/LoginServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import com.stempo.api.domain.domain.model.RedisToken; | ||
import com.stempo.api.domain.domain.model.User; | ||
import com.stempo.api.domain.presentation.dto.response.TokenInfo; | ||
import com.stempo.api.global.auth.exception.TokenForgeryException; | ||
import com.stempo.api.global.auth.jwt.JwtTokenProvider; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class LoginServiceImpl implements LoginService { | ||
|
||
private final UserService userService; | ||
private final RedisTokenService redisTokenService; | ||
private final JwtTokenProvider jwtTokenProvider; | ||
|
||
@Override | ||
public TokenInfo loginOrRegister(String deviceTag, String password) { | ||
User user = userService.findById(deviceTag) | ||
.orElseGet(() -> userService.registerUser(deviceTag, password)); | ||
return generateAndSaveToken(user); | ||
} | ||
|
||
@Override | ||
public TokenInfo reissueToken(HttpServletRequest request) { | ||
String refreshToken = jwtTokenProvider.resolveToken(request); | ||
Authentication authentication = jwtTokenProvider.getAuthentication(refreshToken); | ||
RedisToken redisToken = redisTokenService.findByRefreshToken(refreshToken); | ||
|
||
validateUserExistence(authentication); | ||
|
||
TokenInfo newTokenInfo = jwtTokenProvider.generateToken(redisToken.getId(), redisToken.getRole()); | ||
redisTokenService.saveToken(redisToken.getId(), redisToken.getRole(), newTokenInfo); | ||
return newTokenInfo; | ||
} | ||
|
||
private TokenInfo generateAndSaveToken(User loginUser) { | ||
TokenInfo tokenInfo = jwtTokenProvider.generateToken(loginUser.getDeviceTag(), loginUser.getRole()); | ||
redisTokenService.saveToken(loginUser.getDeviceTag(), loginUser.getRole(), tokenInfo); | ||
return tokenInfo; | ||
} | ||
|
||
private void validateUserExistence(Authentication authentication) { | ||
String id = authentication.getName(); | ||
if (!userService.existsById(id)) { | ||
throw new TokenForgeryException("Non-existent user token."); | ||
} | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/com/stempo/api/domain/application/service/PasswordService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
public interface PasswordService { | ||
String encodePassword(String password); | ||
} |
17 changes: 17 additions & 0 deletions
17
src/main/java/com/stempo/api/domain/application/service/PasswordServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class PasswordServiceImpl implements PasswordService { | ||
|
||
private final PasswordEncoder passwordEncoder; | ||
|
||
@Override | ||
public String encodePassword(String rawPassword) { | ||
return passwordEncoder.encode(rawPassword); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/stempo/api/domain/application/service/RedisTokenService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import com.stempo.api.domain.domain.model.RedisToken; | ||
import com.stempo.api.domain.domain.model.Role; | ||
import com.stempo.api.domain.presentation.dto.response.TokenInfo; | ||
|
||
public interface RedisTokenService { | ||
|
||
RedisToken findByAccessToken(String token); | ||
|
||
RedisToken findByRefreshToken(String token); | ||
|
||
void saveToken(String id, Role role, TokenInfo tokenInfo); | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/com/stempo/api/domain/application/service/RedisTokenServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import com.stempo.api.domain.domain.model.RedisToken; | ||
import com.stempo.api.domain.domain.model.Role; | ||
import com.stempo.api.domain.domain.repository.RedisTokenRepository; | ||
import com.stempo.api.domain.presentation.dto.response.TokenInfo; | ||
import com.stempo.api.global.auth.exception.TokenNotFoundException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class RedisTokenServiceImpl implements RedisTokenService { | ||
|
||
private final RedisTokenRepository redisTokenRepository; | ||
|
||
@Override | ||
public RedisToken findByAccessToken(String token) { | ||
return redisTokenRepository.findByAccessToken(token) | ||
.orElseThrow(() -> new TokenNotFoundException("존재하지 않는 토큰입니다.")); | ||
} | ||
|
||
@Override | ||
public RedisToken findByRefreshToken(String token) { | ||
return redisTokenRepository.findByRefreshToken(token) | ||
.orElseThrow(() -> new TokenNotFoundException("존재하지 않는 토큰입니다.")); | ||
} | ||
|
||
@Override | ||
public void saveToken(String id, Role role, TokenInfo tokenInfo) { | ||
RedisToken redisToken = RedisToken.create(id, role, tokenInfo); | ||
redisTokenRepository.save(redisToken); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/stempo/api/domain/application/service/UserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import com.stempo.api.domain.domain.model.User; | ||
|
||
import java.util.Optional; | ||
|
||
public interface UserService { | ||
|
||
User registerUser(String deviceTag, String password); | ||
|
||
Optional<User> findById(String id); | ||
|
||
boolean existsById(String id); | ||
} |
37 changes: 37 additions & 0 deletions
37
src/main/java/com/stempo/api/domain/application/service/UserServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package com.stempo.api.domain.application.service; | ||
|
||
import com.stempo.api.domain.domain.model.User; | ||
import com.stempo.api.domain.domain.repository.UserRepository; | ||
import com.stempo.api.global.util.PasswordUtil; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.Optional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class UserServiceImpl implements UserService { | ||
|
||
private final UserRepository userRepository; | ||
private final PasswordService passwordService; | ||
private final PasswordUtil passwordUtil; | ||
|
||
@Override | ||
public User registerUser(String deviceTag, String password) { | ||
String rawPassword = password != null ? password : passwordUtil.generateStrongPassword(); | ||
User user = User.create(deviceTag, rawPassword); | ||
String encodedPassword = passwordService.encodePassword(user.getPassword()); | ||
user.updatePassword(encodedPassword); | ||
return userRepository.save(user); | ||
} | ||
|
||
@Override | ||
public Optional<User> findById(String id) { | ||
return userRepository.findById(id); | ||
} | ||
|
||
@Override | ||
public boolean existsById(String id) { | ||
return userRepository.existsById(id); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
src/main/java/com/stempo/api/domain/domain/model/RedisToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.stempo.api.domain.domain.model; | ||
|
||
import com.stempo.api.domain.presentation.dto.response.TokenInfo; | ||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Id; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
import org.springframework.data.redis.core.RedisHash; | ||
import org.springframework.data.redis.core.index.Indexed; | ||
|
||
@Getter | ||
@Setter | ||
@Builder | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
@RedisHash(value = "refresh", timeToLive = 60 * 60 * 24 * 14) | ||
public class RedisToken { | ||
|
||
@Id | ||
@Column(name = "user_id") | ||
private String id; | ||
|
||
private Role role; | ||
|
||
@Indexed | ||
private String accessToken; | ||
|
||
@Indexed | ||
private String refreshToken; | ||
|
||
public static RedisToken create(String id, Role role, TokenInfo tokenInfo) { | ||
return RedisToken.builder() | ||
.id(id) | ||
.role(role) | ||
.accessToken(tokenInfo.getAccessToken()) | ||
.refreshToken(tokenInfo.getRefreshToken()) | ||
.build(); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/stempo/api/domain/domain/model/Role.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.stempo.api.domain.domain.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum Role { | ||
|
||
USER("ROLE_USER", "Normal User"), | ||
ADMIN("ROLE_ADMIN", "Administrator"); | ||
|
||
private final String key; | ||
private final String description; | ||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/com/stempo/api/domain/domain/model/User.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.stempo.api.domain.domain.model; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@Builder | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class User { | ||
|
||
private String deviceTag; | ||
private String password; | ||
private Role role; | ||
|
||
public static User create(String deviceTag, String password) { | ||
return new User(deviceTag, password, Role.USER); | ||
} | ||
|
||
public void updatePassword(String encodedPassword) { | ||
setPassword(encodedPassword); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/stempo/api/domain/domain/repository/RedisTokenRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.stempo.api.domain.domain.repository; | ||
|
||
import com.stempo.api.domain.domain.model.RedisToken; | ||
|
||
import java.util.Optional; | ||
|
||
public interface RedisTokenRepository { | ||
|
||
Optional<RedisToken> findByAccessToken(String token); | ||
|
||
Optional<RedisToken> findByRefreshToken(String token); | ||
|
||
void save(RedisToken redisToken); | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/stempo/api/domain/domain/repository/UserRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.stempo.api.domain.domain.repository; | ||
|
||
import com.stempo.api.domain.domain.model.User; | ||
|
||
import java.util.Optional; | ||
|
||
public interface UserRepository { | ||
|
||
User save(User user); | ||
|
||
Optional<User> findById(String id); | ||
|
||
boolean existsById(String id); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
src/main/java/com/stempo/api/domain/persistence/mappper/UserMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.stempo.api.domain.persistence.mappper; | ||
|
||
import com.stempo.api.domain.domain.model.User; | ||
import com.stempo.api.domain.persistence.entity.UserEntity; | ||
|
||
public class UserMapper { | ||
|
||
public static UserEntity toEntity(User user) { | ||
return UserEntity.builder() | ||
.deviceTag(user.getDeviceTag()) | ||
.password(user.getPassword()) | ||
.role(user.getRole()) | ||
.build(); | ||
} | ||
|
||
public static User toDomain(UserEntity entity) { | ||
return User.builder() | ||
.deviceTag(entity.getDeviceTag()) | ||
.password(entity.getPassword()) | ||
.role(entity.getRole()) | ||
.build(); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/stempo/api/domain/persistence/repository/RedisTokenJpaRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.stempo.api.domain.persistence.repository; | ||
|
||
import com.stempo.api.domain.domain.model.RedisToken; | ||
import org.springframework.data.repository.CrudRepository; | ||
|
||
import java.util.Optional; | ||
|
||
public interface RedisTokenJpaRepository extends CrudRepository<RedisToken, String> { | ||
|
||
Optional<RedisToken> findByAccessToken(String token); | ||
|
||
Optional<RedisToken> findByRefreshToken(String token); | ||
} |
Oops, something went wrong.