diff --git a/docker-compose.yml b/docker-compose.yml
index f14bf82..892ddd2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,7 +5,7 @@ services:
image: quay.io/keycloak/keycloak:21.0
command: [ 'start-dev', '--debug' ]
volumes:
- - ./target/keycloak-event-listener-sns-1.0.2-SNAPSHOT.jar:/opt/keycloak/providers/keycloak-event-listener-sns.jar
+ - ./target/keycloak-event-listener-sns-1.1.1-SNAPSHOT.jar:/opt/keycloak/providers/keycloak-event-listener-sns.jar
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
diff --git a/pom.xml b/pom.xml
index 77a8f54..cc62561 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,12 +65,13 @@
3.5.0
3.4.1
- 20.0.5
+ 21.1.2
1.12.578
5.9.2
3.24.2
3.5.3.Final
5.1.1
+ 1.1
@@ -250,7 +251,12 @@
${mockito.version}
test
-
+
+ javax.transaction
+ jta
+ ${jta.version}
+ test
+
diff --git a/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProvider.java b/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProvider.java
index 691a7dc..d5aad66 100644
--- a/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProvider.java
+++ b/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProvider.java
@@ -4,28 +4,24 @@
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerTransaction;
import org.keycloak.events.admin.AdminEvent;
-import org.keycloak.models.KeycloakTransactionManager;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
+import org.keycloak.models.*;
+
+import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction;
public class SnsEventListenerProvider implements EventListenerProvider {
private final SnsEventPublisher snsEventPublisher;
+ private final KeycloakSessionFactory sessionFactory;
private final EventListenerTransaction transaction = new EventListenerTransaction(this::sendAdminEvent,
this::sendEvent);
- private final UserProvider userProvider;
-
- private final RealmProvider realmProvider;
-
- public SnsEventListenerProvider(SnsEventPublisher snsEventPublisher, KeycloakTransactionManager transactionManager,
- UserProvider userProvider, RealmProvider realmProvider) {
+ public SnsEventListenerProvider(SnsEventPublisher snsEventPublisher,
+ KeycloakSessionFactory sessionFactory,
+ KeycloakTransactionManager transactionManager) {
this.snsEventPublisher = snsEventPublisher;
+ this.sessionFactory = sessionFactory;
transactionManager.enlistAfterCompletion(transaction);
- this.userProvider = userProvider;
- this.realmProvider = realmProvider;
}
@Override
@@ -44,19 +40,23 @@ public void close() {
}
private void sendEvent(Event event) {
- snsEventPublisher.sendEvent(new SnsEvent(event, getUsername(event.getRealmId(), event.getUserId())));
+ runJobInTransaction(sessionFactory, session ->
+ snsEventPublisher.sendEvent(new SnsEvent(event, getUsername(session.realms(), session.users(), event.getRealmId(), event.getUserId()))));
}
private void sendAdminEvent(AdminEvent adminEvent, boolean includeRepresentation) {
- String adminUserId = null;
- if (adminEvent.getAuthDetails() != null) {
- adminUserId = adminEvent.getAuthDetails().getUserId();
- }
- snsEventPublisher.sendAdminEvent(new SnsAdminEvent(adminEvent, getUsername(adminEvent.getRealmId(), adminUserId)));
-
+ runJobInTransaction(sessionFactory, session -> {
+ String adminUserId = null;
+ if (adminEvent.getAuthDetails() != null) {
+ adminUserId = adminEvent.getAuthDetails().getUserId();
+ }
+ snsEventPublisher.sendAdminEvent(
+ new SnsAdminEvent(adminEvent, getUsername(session.realms(), session.users(), adminEvent.getRealmId(), adminUserId)));
+ }
+ );
}
- private String getUsername(String realmId, String userId) {
+ private String getUsername(RealmProvider realmProvider, UserProvider userProvider, String realmId, String userId) {
UserModel user;
if (userId != null) {
user = userProvider.getUserById(realmProvider.getRealm(realmId), userId);
diff --git a/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProviderFactory.java b/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProviderFactory.java
index 4d5b8e2..eaee8e6 100644
--- a/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProviderFactory.java
+++ b/src/main/java/fr/redfroggy/keycloak/SnsEventListenerProviderFactory.java
@@ -28,7 +28,9 @@ public void close() {
public EventListenerProvider create(KeycloakSession session) {
AmazonSNSAsync snsClient = AmazonSNSAsyncClientBuilder.standard().build();
ObjectMapper mapper = new ObjectMapper();
- return new SnsEventListenerProvider(new SnsEventPublisher(snsClient, snsEventListenerConfiguration, mapper), session.getTransactionManager(), session.users(), session.realms());
+ return new SnsEventListenerProvider(new SnsEventPublisher(snsClient, snsEventListenerConfiguration, mapper),
+ session.getKeycloakSessionFactory(),
+ session.getTransactionManager());
}
@Override
diff --git a/src/test/java/fr/redfroggy/keycloak/SnsEventListenerProviderTest.java b/src/test/java/fr/redfroggy/keycloak/SnsEventListenerProviderTest.java
index 8191493..4a58ebf 100644
--- a/src/test/java/fr/redfroggy/keycloak/SnsEventListenerProviderTest.java
+++ b/src/test/java/fr/redfroggy/keycloak/SnsEventListenerProviderTest.java
@@ -9,11 +9,7 @@
import org.keycloak.events.EventListenerTransaction;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AuthDetails;
-import org.keycloak.models.KeycloakTransactionManager;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
+import org.keycloak.models.*;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
@@ -47,6 +43,12 @@ class SnsEventListenerProviderTest {
@Mock
private KeycloakTransactionManager transactionManagerMock;
+ @Mock
+ private KeycloakSessionFactory sessionFactory;
+
+ @Mock
+ private KeycloakSession session;
+
@Mock
private SnsEventPublisher snsEventPublisherMock;
@@ -76,6 +78,11 @@ void shouldAddEventToTransaction(){
when(realmProviderMock.getRealm("realmId")).thenReturn(realmMock);
when(userProviderMock.getUserById(realmMock, "userId")).thenReturn(userMock);
when(userMock.getUsername()).thenReturn("username");
+ when(sessionFactory.create()).thenReturn(session);
+ when(session.getTransactionManager()).thenReturn(transactionManagerMock);
+ when(session.realms()).thenReturn(realmProviderMock);
+ when(session.users()).thenReturn(userProviderMock);
+
snsEventListenerProvider.onEvent(eventMock);
verify(transactionManagerMock).enlistAfterCompletion(transactionCaptor.capture());
EventListenerTransaction transaction = transactionCaptor.getValue();
@@ -91,6 +98,9 @@ void shouldAddEventToTransaction(){
void shouldAddEventToTransactionWithUsernameToNullBecauseUserIdNull(){
when(eventMock.getUserId()).thenReturn(null);
when(eventMock.getRealmId()).thenReturn("realmId");
+ when(sessionFactory.create()).thenReturn(session);
+ when(session.getTransactionManager()).thenReturn(transactionManagerMock);
+
snsEventListenerProvider.onEvent(eventMock);
verify(transactionManagerMock).enlistAfterCompletion(transactionCaptor.capture());
EventListenerTransaction transaction = transactionCaptor.getValue();
@@ -109,6 +119,11 @@ void shouldAddEventToTransactionWithUsernameToNullBecauseUserNull(){
when(realmProviderMock.getRealm("realmId")).thenReturn(realmMock);
when(userProviderMock.getUserById(realmMock, "userId")).thenReturn(null);
snsEventListenerProvider.onEvent(eventMock);
+ when(sessionFactory.create()).thenReturn(session);
+ when(session.getTransactionManager()).thenReturn(transactionManagerMock);
+ when(session.realms()).thenReturn(realmProviderMock);
+ when(session.users()).thenReturn(userProviderMock);
+
verify(transactionManagerMock).enlistAfterCompletion(transactionCaptor.capture());
EventListenerTransaction transaction = transactionCaptor.getValue();
transaction.begin();
@@ -127,6 +142,11 @@ void shouldAddAdminEventToTransaction(){
when(realmProviderMock.getRealm("realmId")).thenReturn(realmMock);
when(userProviderMock.getUserById(realmMock, "userId")).thenReturn(userMock);
when(userMock.getUsername()).thenReturn("username");
+ when(sessionFactory.create()).thenReturn(session);
+ when(session.getTransactionManager()).thenReturn(transactionManagerMock);
+ when(session.realms()).thenReturn(realmProviderMock);
+ when(session.users()).thenReturn(userProviderMock);
+
snsEventListenerProvider.onEvent(adminEventMock, true);
verify(transactionManagerMock).enlistAfterCompletion(transactionCaptor.capture());
EventListenerTransaction transaction = transactionCaptor.getValue();
@@ -141,6 +161,9 @@ void shouldAddAdminEventToTransaction(){
@Test
void shouldAddAdminEventToTransactionWithUsernameToNullBecauseAuthDetailsNull(){
when(adminEventMock.getAuthDetails()).thenReturn(null);
+ when(sessionFactory.create()).thenReturn(session);
+ when(session.getTransactionManager()).thenReturn(transactionManagerMock);
+
snsEventListenerProvider.onEvent(adminEventMock, true);
verify(transactionManagerMock).enlistAfterCompletion(transactionCaptor.capture());
EventListenerTransaction transaction = transactionCaptor.getValue();