package com.github.kazuki43zoo.web.security;
import com.github.kazuki43zoo.domain.repository.account.AccountRepository;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.inject.Inject;
@Aspect
@Component
public class SessionAuthenticationStrategySynchronizer {
@Inject
AccountRepository accountRepository;
private final TransactionTemplate transactionTemplate;
@Inject
public SessionAuthenticationStrategySynchronizer(final PlatformTransactionManager transactionManager) {
final DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setName(getClass().getName());
this.transactionTemplate = new TransactionTemplate(transactionManager, transactionDefinition);
}
@Around("execution( * org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy.onAuthentication(..))")
public void synchronize(final ProceedingJoinPoint joinPoint) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
final Authentication authentication = Authentication.class.cast(joinPoint.getArgs()[0]);
accountRepository.lockByAccountIdWithinTransaction(authentication.getName());
try {
joinPoint.proceed();
} catch (final RuntimeException e) {
throw e;
} catch (final Error e) {
throw e;
} catch (final Throwable e) {
throw new IllegalStateException(e);
}
}
});
}
}