Skip to content

Commit

Permalink
fix: Check not null in ClientWriteRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
embesozzi committed Oct 12, 2023
1 parent 2653a27 commit d4b15e5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,22 @@ public class OpenFgaEventListenerProvider implements EventListenerProvider {
private KeycloakSession session;

public OpenFgaEventListenerProvider(OpenFgaClientHandler client, KeycloakSession session) {
LOG.info("[OpenFgaEventPublisher] OpenFgaEventListenerProvider initializing...");
this.client = client;
this.session = session;
}

@Override
public void onEvent(Event event) {
LOG.debug("[OpenFgaEventPublisher] Discarding onEvent type: " + event.getType().toString());
LOG.debug("Discarding onEvent() type: " + event.getType().toString());
}

@Override
public void onEvent(AdminEvent adminEvent, boolean includeRepresentation) {
LOG.debug("[OpenFgaEventPublisher] onEvent Admin received events");
LOG.debugf("Admin event received onEvent(): %s ", adminEvent.toString());

try {
LOG.debugf("[OpenFgaEventPublisher] admin event: " + adminEvent.toString());
EventParser event = new EventParser(adminEvent, session);
LOG.debugf("[OpenFgaEventPublisher] event received: " + event.toString());
LOG.debugf("Event parsed: %s ", event.toString());
client.publish(adminEvent.getId(), event);
} catch (IllegalArgumentException e) {
LOG.warn(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public String getEventObjectType() {
case GROUP_MEMBERSHIP:
return OBJECT_TYPE_GROUP;
default:
throw new IllegalArgumentException("Event is not handled, id:" + event.getId() + " resource name: " + event.getResourceType().name());
throw new IllegalArgumentException("Event is not handled, id:" + event.getId() + " resource: " + event.getResourceType().name());
}
}

Expand Down Expand Up @@ -122,7 +122,6 @@ private String getObjectByAttributeName(String attributeName) {
}

public String findRoleNameInRealm(String roleId) {
LOG.debug("Finding role name by role id: " + roleId);
return session.getContext().getRealm().getRoleById(roleId).getName();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.twogenidentity.keycloak.event.EventParser;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.utils.StringUtil;

import java.time.Duration;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -37,8 +38,8 @@ public OpenFgaClientHandler(Config.Scope config ) throws FgaInvalidParameterExce
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(5));

if(!getOpenFgaOpenStoreId().isEmpty()
&& !getOpenFgaAuthorizationModelId().isEmpty()) {
if(StringUtil.isNotBlank(getOpenFgaOpenStoreId())
&& StringUtil.isNotBlank(getOpenFgaAuthorizationModelId())) {
configuration.storeId(getOpenFgaOpenStoreId());
configuration.authorizationModelId(getOpenFgaAuthorizationModelId());
this.isClientInitialized = true;
Expand All @@ -51,31 +52,31 @@ public OpenFgaClientHandler(Config.Scope config ) throws FgaInvalidParameterExce

public void publish(String eventId , EventParser event) throws FgaInvalidParameterException, ExecutionException, InterruptedException {
if(!this.isClientInitialized && !this.discoverClientConfiguration()) {
LOG.error("[OpenFgaEventPublisher] Unable to initialized client for event " + eventId);
LOG.errorf("Unable to initialized OpenFga client. Discarding event %s, %s", eventId, event.toString());
}
else {
ClientWriteRequest request = fgaHelper.toClientWriteRequest(event);
if(!request.getWrites().isEmpty() || !request.getDeletes().isEmpty()) {
LOG.debug("[OpenFgaEventPublisher] Publishing event id: " + eventId + " event: " + event.toString());
if(fgaHelper.isAvailableClientRequest(request)) {
LOG.debugf("Publishing event id %", eventId);
var response = fgaClient.write(request, this.clientWriteOptions).get();
LOG.debug("[OpenFgaEventPublisher] Successfully sent tuple key to OpenFga, response: " + response);
LOG.debugf("Successfully sent tuple key to OpenFga, response: %s", response);
}
}
}

private boolean discoverClientConfiguration() throws FgaInvalidParameterException, ExecutionException, InterruptedException {
LOG.info("[OpenFgaEventPublisher] Discover store and authorization model");
LOG.info("Discover store and authorization model");
ListStoresResponse stores = fgaClient.listStores().get();
if(!stores.getStores().isEmpty()) {
Store store = stores.getStores().get(0);
LOG.info("[OpenFgaEventPublisher] Found store id:" + store.getId());
LOG.infof("Found store id: %s", store.getId());
this.fgaClient.setStoreId(store.getId());
ReadAuthorizationModelsResponse authorizationModels = fgaClient.readAuthorizationModels().get();
if(authorizationModels.getAuthorizationModels().size() > 0) {
AuthorizationModel model = authorizationModels.getAuthorizationModels().get(0);
LOG.info("[OpenFgaEventPublisher] Found authorization model id:" + model.getId());
LOG.infof("Found authorization model id: %s", model.getId());
this.fgaClient.setAuthorizationModelId(model.getId());
fgaHelper.loadModel(model);
this.fgaHelper.loadModel(model);
this.isClientInitialized = true;
}
}
Expand All @@ -87,10 +88,10 @@ public String getOpenFgaApiUrl() {
}

public String getOpenFgaOpenStoreId() {
return config.get(OPENFGA_STORE_ID);
return config.get(OPENFGA_STORE_ID) != null ? config.get(OPENFGA_STORE_ID) : "";
}

public String getOpenFgaAuthorizationModelId() {
return config.get(OPENFGA_AUTHORIZATION_MODEL_ID);
return config.get(OPENFGA_AUTHORIZATION_MODEL_ID) != null? config.get(OPENFGA_AUTHORIZATION_MODEL_ID) : "";
}
}
39 changes: 27 additions & 12 deletions src/main/java/com/twogenidentity/keycloak/utils/OpenFgaHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,27 @@ public class OpenFgaHelper {
private AuthorizationModel model;
private Map<String, String> modelTypeObjectAndRelation;

public OpenFgaHelper() {
this.modelTypeObjectAndRelation = new HashMap<>();
}

public void loadModel(AuthorizationModel model) {
this.model = model;
loadModelAsTypeObjectRelationshipMap();
this.loadModelAsTypeObjectRelationshipMap();
}

private Boolean isTypeDefinitionHandled(String eventObjectType) {
return this.model.getTypeDefinitions().stream()
private Boolean isTypeDefinitionInModel(String eventObjectType) {
return !this.model.getTypeDefinitions().stream()
.filter(r -> r.getType().equalsIgnoreCase(eventObjectType))
.findFirst().isEmpty();
}

private Boolean isRelationAvailableInModel(String typeDefinition, String objectType) {
return this.modelTypeObjectAndRelation.containsKey(typeDefinition + objectType);
}

private String getRelationFromModel(String typeDefinition, String objectType){
return modelTypeObjectAndRelation.get(typeDefinition + objectType); // Easy way to return the relation
return this.modelTypeObjectAndRelation.get(typeDefinition + objectType); // Easy way to return the relation
}

public ClientWriteRequest toClientWriteRequest(EventParser event) {
Expand All @@ -42,18 +50,20 @@ public ClientWriteRequest toClientWriteRequest(EventParser event) {
String eventUserType = event.getEventUserType();
String eventUserId = event.getTranslateUserId();

// Check if the authorization model is prepared to handle
// this object type a.k.a TypeDefinition
if(isTypeDefinitionHandled(eventObjectType)) {
// Obtain the relation based the event objectType and eventUserType
// For now, this combination is UNIQUE in the authorization model
// Check if the authorization model handles this object type a.k.a TypeDefinition
// Check if we have the relation for this object type and user type
if(isTypeDefinitionInModel(eventObjectType)
&& isRelationAvailableInModel(eventObjectType, eventUserType)) {

String relation = getRelationFromModel(eventObjectType, eventUserType);

ClientTupleKey tuple = new ClientTupleKey()
.user(eventUserType + ":" + eventUserId)
.relation(relation)
._object(eventObjectType +":"+ eventObjectId);

LOG.debugf("Tuple %s %s %s", tuple.getUser(), tuple.getRelation(), tuple.getObject());

if(event.isWriteOperation()) {
client.writes(List.of(tuple));
}
Expand All @@ -62,13 +72,13 @@ else if(event.isDeleteOperation()) {
}
}
else {
LOG.warn("[OpenFgaEventPublisher] Event not handled in OpenFGA, event: " + eventObjectType + " is not present in model.");
LOG.warnf("Event not handled in OpenFGA. Event: %s %s is not present in model %s.", eventObjectType, eventUserType, this.modelTypeObjectAndRelation);
}
return client;
}

private void loadModelAsTypeObjectRelationshipMap(){
this.modelTypeObjectAndRelation = new HashMap<>();
LOG.debugf("Loading internal model");
for (TypeDefinition typeDef : this.model.getTypeDefinitions()) {
for (Map.Entry<String, Userset> us : typeDef.getRelations().entrySet()) {
if (typeDef.getMetadata() != null
Expand All @@ -80,6 +90,11 @@ private void loadModelAsTypeObjectRelationshipMap(){
}
}
}
LOG.debug("[OpenFgaEventPublisher] Internal model as Map(TypeObject:Relation): " + modelTypeObjectAndRelation);
LOG.debugf("Internal model as Map(TypeObject:Relation): %s", this.modelTypeObjectAndRelation);
}

public Boolean isAvailableClientRequest(ClientWriteRequest request) {
return ((request.getWrites() != null && !request.getWrites().isEmpty())
|| (request.getDeletes() !=null && !request.getDeletes().isEmpty()));
}
}

0 comments on commit d4b15e5

Please sign in to comment.