Skip to content

Commit

Permalink
[FEAT] Redis 관련 설정 변경 (#154)
Browse files Browse the repository at this point in the history
  • Loading branch information
kssumin authored Sep 15, 2024
1 parent 3280f47 commit 62d6fb2
Show file tree
Hide file tree
Showing 16 changed files with 206 additions and 115 deletions.
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

0 comments on commit 62d6fb2

Please sign in to comment.