Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Redis 관련 설정 변경 #154

Merged
merged 12 commits into from
Sep 15, 2024
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.blackcompany.eeos.auth.application.event;

import com.blackcompany.eeos.auth.application.domain.token.TokenResolver;
import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository;
import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository;
import com.blackcompany.eeos.target.persistence.AttendRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -17,7 +17,7 @@
@Slf4j
public class DeletedMemberEventListener {
private final AttendRepository attendRepository;
private final BlackAuthenticationRepository blackAuthenticationRepository;
private final InvalidTokenRepository invalidTokenRepository;
private final TokenResolver tokenResolver;

@Async
Expand All @@ -33,7 +33,7 @@ private void deleteTargetData(Long memberId) {
}

private void saveUsedToken(String token, Long memberId) {
blackAuthenticationRepository.save(token, memberId, getExpiredDate(token));
invalidTokenRepository.save(token, memberId, getExpiredDate(token));
}

private Long getExpiredDate(String token) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.blackcompany.eeos.auth.application.event.DeletedMemberEvent;
import com.blackcompany.eeos.auth.application.usecase.LogOutUsecase;
import com.blackcompany.eeos.auth.application.usecase.WithDrawUsecase;
import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository;
import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository;
import com.blackcompany.eeos.auth.persistence.OAuthMemberRepository;
import com.blackcompany.eeos.member.persistence.MemberRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -16,7 +16,7 @@
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class DeactivateMemberService implements LogOutUsecase, WithDrawUsecase {
private final BlackAuthenticationRepository blackAuthenticationRepository;
private final InvalidTokenRepository invalidTokenRepository;
private final TokenResolver tokenResolver;
private final ApplicationEventPublisher eventPublisher;
private final MemberRepository memberRepository;
Expand All @@ -39,7 +39,7 @@ public void withDraw(final String token, final Long memberId) {
}

private void saveUsedToken(final String token, final Long memberId) {
blackAuthenticationRepository.save(token, memberId, getExpiredToken(token));
invalidTokenRepository.save(token, memberId, getExpiredToken(token));
}

private Long getExpiredToken(final String token) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.blackcompany.eeos.auth.application.exception.InvalidTokenException;
import com.blackcompany.eeos.auth.application.support.AuthenticationTokenGenerator;
import com.blackcompany.eeos.auth.application.usecase.ReissueUsecase;
import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository;
import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -15,30 +15,30 @@
@Transactional(readOnly = true)
public class ReissueService implements ReissueUsecase {
private final AuthenticationTokenGenerator authenticationTokenGenerator;
private final BlackAuthenticationRepository blackAuthenticationRepository;
private final InvalidTokenRepository invalidTokenRepository;
private final TokenResolver tokenResolver;

@Transactional
@Override
public TokenModel execute(final String token) {
Long memberId = tokenResolver.getUserDataByRefreshToken(token);

validateToken(token);

Long memberId = tokenResolver.getUserDataByRefreshToken(token);
saveUsedToken(token, memberId);

return authenticationTokenGenerator.execute(memberId);
}

private void validateToken(final String token) {
boolean isExistToken = blackAuthenticationRepository.isExistToken(token);
Boolean isExistToken = invalidTokenRepository.isExistToken(token);

if (isExistToken) {
if (Boolean.TRUE.equals(isExistToken)) {
throw new InvalidTokenException();
}
}

private void saveUsedToken(final String token, final Long memberId) {
blackAuthenticationRepository.save(token, memberId, getExpiredToken(token));
invalidTokenRepository.save(token, memberId, getExpiredToken(token));
}

private Long getExpiredToken(final String token) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package com.blackcompany.eeos.auth.persistence;

import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface AccountRepository extends JpaRepository<AccountEntity, Long> {

@Query("SELECT a.memberId FROM AccountEntity a WHERE a.loginId = :loginId AND a.passWd = :passWd")
List<Long> findByMemberId(@Param("loginId") String loginId, @Param("passWd") String passWd);

@Query("SELECT a.passWd FROM AccountEntity a WHERE a.loginId=:loginId")
Optional<String> findByLoginId(@Param("loginId") String loginId);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

@Repository
@RequiredArgsConstructor
public class BlackAuthenticationRepository {
public class InvalidTokenRepository {

private final RedisTemplate<String, Object> redisTemplate;

public void save(String token, Long memberId, Long expiration) {
redisTemplate.opsForValue().set(token, memberId, expiration, TimeUnit.MILLISECONDS);
}

public boolean isExistToken(String key) {
public Boolean isExistToken(String key) {
return redisTemplate.hasKey(key);
}
}
10 changes: 10 additions & 0 deletions eeos/src/main/java/com/blackcompany/eeos/config/RedisConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
Expand All @@ -26,6 +28,14 @@ public RedisTemplate<String, Object> redisTemplate() {
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setEnableTransactionSupport(true);

redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());

redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

redisTemplate.afterPropertiesSet();

return redisTemplate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ public void init() {
@Override
public Long create() {
MemberEntity savedMember = saveMember(memberEntityConverter.toEntity(createMember()));
AccountEntity savedAccount =
saveAccount(accountEntityConverter.toEntity(createAccount(savedMember.getId())));
OAuthMemberEntity savedOauthMember =
saveOauthMember(oauthMemberEntityConverter.toEntity(savedMember.getId()));

saveAccount(accountEntityConverter.toEntity(createAccount(savedMember.getId())));
saveOauthMember(oauthMemberEntityConverter.toEntity(savedMember.getId()));

return savedMember.getId();
}

Expand All @@ -60,9 +60,7 @@ public boolean isExist() {
.filter(MemberEntity::isAdmin)
.collect(Collectors.toList());

if (!findAdminAccount() || !members.isEmpty() || !findAdminOauthMember()) return true;

return false;
return !members.isEmpty() || !findAdminAccount() || !findAdminOauthMember();
}

private MemberEntity saveMember(MemberEntity entity) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.blackcompany.eeos.program.application.support;

import com.blackcompany.eeos.program.persistence.ProgramRepository;
import com.blackcompany.eeos.program.persistence.RedisDelayedQueue;
import com.blackcompany.eeos.target.application.event.EndAttendModeEvent;
import java.util.Set;
Expand All @@ -15,7 +14,6 @@
public class ProgramAttendScheduler {

private final RedisDelayedQueue redisDelayedQueue;
private final ProgramRepository programRepository;
private final ApplicationEventPublisher eventPublisher;

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,34 @@
import com.blackcompany.eeos.auth.application.domain.token.TokenResolver;
import com.blackcompany.eeos.auth.application.exception.InvalidTokenException;
import com.blackcompany.eeos.auth.application.support.AuthenticationTokenGenerator;
import com.blackcompany.eeos.auth.persistence.BlackAuthenticationRepository;
import com.blackcompany.eeos.auth.persistence.InvalidTokenRepository;
import com.blackcompany.eeos.common.DataClearExtension;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;

@ExtendWith(MockitoExtension.class)
@SpringBootTest
@ExtendWith(DataClearExtension.class)
class ReissueServiceTest {

@Mock AuthenticationTokenGenerator authenticationTokenGenerator;
@Mock BlackAuthenticationRepository blackAuthenticationRepository;

@Mock TokenResolver tokenResolver;
@InjectMocks ReissueService reissueService;
@SpyBean AuthenticationTokenGenerator authenticationTokenGenerator;
@Autowired InvalidTokenRepository invalidTokenRepository;
@MockBean TokenResolver tokenResolver;
@Autowired ReissueService reissueService;

@Test
@DisplayName("블랙리스트에 등록된 토큰이라면 예외가 발생한다.")
void exception_when_token_invalid() {
// given
String token = "token";
Long memberId = 1L;
Long memberId = 2L;
Long validTime = 1000L * 1;

when(tokenResolver.getUserDataByRefreshToken(token)).thenReturn(memberId);
when(blackAuthenticationRepository.isExistToken(token)).thenReturn(Boolean.TRUE);
invalidTokenRepository.save(token, memberId, validTime);

// when & then
assertThrows(InvalidTokenException.class, () -> reissueService.execute(token));
Expand All @@ -43,19 +45,18 @@ void exception_when_token_invalid() {
void token_valid() {
// given
String token = "token";
Long memberId = 1L;
Long validTime = 1L;
Long memberId = 2L;
Long validTime = 1000L * 1;

when(tokenResolver.getUserDataByRefreshToken(token)).thenReturn(memberId);
when(blackAuthenticationRepository.isExistToken(token)).thenReturn(Boolean.FALSE);
when(tokenResolver.getExpiredDateByRefreshToken(token)).thenReturn(validTime);

// when
reissueService.execute(token);

// then
assertAll(
() -> verify(blackAuthenticationRepository).save(token, memberId, validTime),
() -> assertTrue(invalidTokenRepository.isExistToken(token)),
() -> verify(authenticationTokenGenerator).execute(memberId));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.blackcompany.eeos.common;

import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit.jupiter.SpringExtension;

Expand All @@ -10,11 +13,15 @@ public class DataClearExtension implements BeforeEachCallback {

@Override
public void beforeEach(ExtensionContext context) {
DatabaseCleaner dataCleaner = getDataCleaner(context);
dataCleaner.clear();
ApplicationContext appContext = SpringExtension.getApplicationContext(context);
List<DatabaseCleaner> dataCleaners = getDataCleaners(appContext);

for (DatabaseCleaner cleaner : dataCleaners) {
cleaner.clear();
}
}

private DatabaseCleaner getDataCleaner(final ExtensionContext extensionContext) {
return SpringExtension.getApplicationContext(extensionContext).getBean(DatabaseCleaner.class);
private List<DatabaseCleaner> getDataCleaners(ApplicationContext appContext) {
return new ArrayList<>(appContext.getBeansOfType(DatabaseCleaner.class).values());
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,5 @@
package com.blackcompany.eeos.common;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class DatabaseCleaner {
private static final String FOREIGN_KEY_CHECK_FORMAT = "SET FOREIGN_KEY_CHECKS = %d";
private static final String TRUNCATE_FORMAT = "TRUNCATE TABLE %s";
private static final String AUTO_INCREMENT_FORMAT = "ALTER TABLE %s AUTO_INCREMENT = 1";

@PersistenceContext private EntityManager entityManager;

@Transactional
public void clear() {
disableForeignKeyChecks();
List<String> tableNames = getTableNames();
truncate(tableNames);
enableForeignKeyChecks();
}

private void disableForeignKeyChecks() {
entityManager.createNativeQuery(String.format(FOREIGN_KEY_CHECK_FORMAT, 0)).executeUpdate();
}

private List<String> getTableNames() {
String query =
"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE()";
return entityManager.createNativeQuery(query).getResultList();
}

private void enableForeignKeyChecks() {
entityManager.createNativeQuery(String.format(FOREIGN_KEY_CHECK_FORMAT, 1)).executeUpdate();
}

private void truncate(List<String> tableNames) {
for (String tableName : tableNames) {
entityManager.createNativeQuery(String.format(TRUNCATE_FORMAT, tableName)).executeUpdate();
entityManager
.createNativeQuery(String.format(AUTO_INCREMENT_FORMAT, tableName))
.executeUpdate();
}
}
public interface DatabaseCleaner {
void clear();
}
Loading
Loading