Skip to content

Commit

Permalink
Include clientId in Redis user-registered events
Browse files Browse the repository at this point in the history
Signed-off-by: John Gomersall <[email protected]>
  • Loading branch information
john-gom committed Jan 8, 2025
1 parent 9f804c2 commit 4372023
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
Expand Down Expand Up @@ -56,8 +57,10 @@ public void onEvent(Event event) {
boolean isUserRegistrationEvent = isUserRegistrationEvent(event, realm);
if (isUserRegistrationEvent) {
final UserModel user = keycloakSession.users().getUserById(realm, event.getUserId());

if (user.getFirstAttribute(UserAttributes.REGISTERED) == null) {
OpenFoodFactsEventListenerProviderFactory.this.client.postUserRegistered(user, realm);
// Note that for normal events the clientId is the normal clientId, not the internal GUID
OpenFoodFactsEventListenerProviderFactory.this.client.postUserRegistered(user, realm, event.getClientId());
user.setSingleAttribute(UserAttributes.REGISTERED, UserAttributes.REGISTERED);
}
}
Expand All @@ -79,9 +82,16 @@ public void onEvent(AdminEvent event, boolean includeRepresentation) {
return;
}

// Note for admin events the clientId in the AuthDetails is the internal GUID
final ClientModel client = keycloakSession.clients().getClientById(realm, event.getAuthDetails().getClientId());
if (client == null) {
log.errorf("Failed to find client: %s", event.getAuthDetails().getClientId());
return;
}

if ((!realm.isVerifyEmail() || user.isEmailVerified())
&& user.getFirstAttribute(UserAttributes.REGISTERED) == null) {
OpenFoodFactsEventListenerProviderFactory.this.client.postUserRegistered(user, realm);
OpenFoodFactsEventListenerProviderFactory.this.client.postUserRegistered(user, realm, client.getClientId());
user.setSingleAttribute(UserAttributes.REGISTERED, UserAttributes.REGISTERED);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public RedisClient(final String url) {
this.jedis = new JedisPooled(url);
}

public void postUserRegistered(final UserModel user, final RealmModel realm) {
public void postUserRegistered(final UserModel user, final RealmModel realm, final String clientId) {
if (user == null) {
throw new IllegalArgumentException("user");
}
Expand All @@ -37,6 +37,8 @@ public void postUserRegistered(final UserModel user, final RealmModel realm) {
final String requestedOrg = user.getFirstAttribute(UserAttributes.REQUESTED_ORG);
putIfNotNull(additionalData, "requestedOrg", requestedOrg);

additionalData.put("clientId", clientId);

postUserEvent("user-registered", user, realm, additionalData);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ public EventType getType() {
return EventType.VERIFY_EMAIL;
}

@Override
public String getClientId() {
return "test-client-client-id";
}
});

// Assert
Expand All @@ -75,6 +79,7 @@ public EventType getType() {
Assertions.assertEquals("theUserName", fields.get("userName"));
Assertions.assertEquals("open-products-facts", fields.get("realm"));
Assertions.assertEquals("subscribe", fields.get("newsletter"));
Assertions.assertEquals("test-client-client-id", fields.get("clientId"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ public EventType getType() {
return EventType.REGISTER;
}

@Override
public String getClientId() {
return "test-client-client-id";
}
});

// Assert
Expand All @@ -74,6 +78,7 @@ public EventType getType() {
Assertions.assertEquals("[email protected]", fields.get("email"));
Assertions.assertEquals("theUserName", fields.get("userName"));
Assertions.assertEquals("open-products-facts", fields.get("realm"));
Assertions.assertEquals("test-client-client-id", fields.get("clientId"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public EventType getType() {

@Override
public String getClientId() {
return "test-client-id";
return "test-client-client-id";
}
});

Expand All @@ -78,7 +78,7 @@ public String getClientId() {
Assertions.assertEquals("[email protected]", fields.get("email"));
Assertions.assertEquals("theUserName", fields.get("userName"));
Assertions.assertEquals("open-products-facts", fields.get("realm"));
Assertions.assertEquals("test-client-id", fields.get("clientId"));
Assertions.assertEquals("test-client-client-id", fields.get("clientId"));
}
}

Expand Down
3 changes: 2 additions & 1 deletion tests/login.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ test("locale from app is respected", async ({ page }) => {

const myMessage2 = await redisClient.getMessageForUser(userName);
expect(myMessage2).toBeTruthy();

expect(myMessage2?.message.clientId).toBe(process.env.TEST_CLIENT_ID);

// Fetch the user via API and make sure locale is set correctly
const headers = await getKeycloakHeaders();
const users = await (await fetch(`${keycloakUserUrl}?exact=true&username=${userName}`, {headers})).json();
Expand Down
3 changes: 2 additions & 1 deletion tests/register.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ test("newsletter and producer fields", async ({ page }) => {
expect(myMessage).toBeTruthy();
expect(myMessage?.message.newsletter).toBe('subscribe');
expect(myMessage?.message.requestedOrg).toBe('carrefour');
expect(myMessage?.message.clientId).toBe('account-console');

// Newsletter field should be hidden on edit
await expect(page.getByLabel('^newsletter_description^')).not.toBeVisible();
Expand Down Expand Up @@ -109,7 +110,7 @@ test("user created by API doesn't need email verification", async ({page}) => {
expect(myMessage?.message.clientId).toBe(process.env.TEST_CLIENT_ID);
});

test("migrated user with invlaid email loaded with no messages", async ({page}) => {
test("migrated user with invalid email loaded with no messages", async ({page}) => {
const redisClient = await createRedisClient('user-registered');

const {userName, password, email} = generateRandomUser();
Expand Down

0 comments on commit 4372023

Please sign in to comment.