Skip to content

Commit

Permalink
Merge pull request #148 from ExclamationLabs/2024/10/FIN-12352_suppor…
Browse files Browse the repository at this point in the history
…t_attr_constraints

FIN-12352 - support attribute constraint meta information
  • Loading branch information
mike-elabs authored Oct 10, 2024
2 parents 24b46d0 + c16ed8a commit 815cfe3
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and minimize the interactions with the ConnId framework and have much of that
taken care of by a common API.

# Change Log
+ **4.2.9** - FIN-12352 - Support attribute meta information for constraints (10/10/2024)
+ **4.2.8** - Revert ConnectionBrokenException thrown for 500+ - delegate to FaultProcessor handling case-by-case (10/01/2024)
+ **4.2.7** - Throw ConnectionBrokenException upon server error (09/26/2024)
+ **4.2.6** - FIN-12383 - Change return type of quickTest method (09/19/2024)
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
software_version=4.2.8
software_version=4.2.9
test_connector_version=3.0.2
spring_boot_version=2.7.18

Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@

package com.exclamationlabs.connid.base.connector.attribute;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import org.identityconnectors.framework.common.objects.AttributeInfo;

/**
Expand All @@ -38,6 +35,18 @@ public final class ConnectorAttribute {

private Object value;

/**
* Provides JSON meta information about the connector attribute. In particular, this is used to
* store data constraint information for cases where data constraints (allowed characters, data
* length) need to be enforced. The actual enforcement is not handled by the base framework, and
* is instead handled by connector and onboarding implementations. Using the
* com.exclamationlabs.connid.base.connector.attribute.meta.AttributeMetaInfo structure is
* advised, but not enforced by the base framework. More Info: - Supplying this meta JSON is
* optional, and this value can be null. - The JSON supplied will be placed into the "subtype" for
* the ConnId AttributeInfo stored for this attribute (belonging to the schema/object class).
*/
private String metaInfoJson;

public ConnectorAttribute(
String attributeName,
ConnectorAttributeDataType attributeDataType,
Expand All @@ -60,17 +69,35 @@ public ConnectorAttribute(
String attributeName,
ConnectorAttributeDataType attributeDataType,
AttributeInfo.Flags... attributeFlags) {
this(attributeName, attributeName, attributeDataType, attributeFlags);
this(attributeName, attributeName, attributeDataType, null, attributeFlags);
}

public ConnectorAttribute(
String attributeName,
ConnectorAttributeDataType attributeDataType,
String metaInfoJson,
AttributeInfo.Flags... attributeFlags) {
this(attributeName, attributeName, attributeDataType, metaInfoJson, attributeFlags);
}

public ConnectorAttribute(
String attributeName,
String nativeNameInput,
ConnectorAttributeDataType attributeDataType,
AttributeInfo.Flags... attributeFlags) {
this(attributeName, nativeNameInput, attributeDataType, null, attributeFlags);
}

public ConnectorAttribute(
String attributeName,
String nativeNameInput,
ConnectorAttributeDataType attributeDataType,
String metaInfoJsonInput,
AttributeInfo.Flags... attributeFlags) {
name = attributeName;
nativeName = nativeNameInput;
dataType = attributeDataType;
metaInfoJson = metaInfoJsonInput;
flags = new HashSet<>();
flags.addAll(Arrays.asList(attributeFlags));
}
Expand Down Expand Up @@ -99,17 +126,20 @@ public String getNativeName() {
return nativeName;
}

public String getMetaInfoJson() {
return metaInfoJson;
}

@Override
public String toString() {
return name
+ "("
+ nativeName
+ ") ["
+ dataType
+ "] {"
+ (flags != null ? flags.toString() : "")
+ "}: "
+ (value != null ? value.toString() : "");
return String.format(
"%s(%s) [%s] `%s` {%s}: %s",
name,
nativeName,
dataType,
metaInfoJson,
flags != null ? flags.toString() : "",
value != null ? value.toString() : "");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.exclamationlabs.connid.base.connector.attribute.meta;

public class AttributeConstraint {
private Boolean outbound = Boolean.FALSE;
private Boolean inbound = Boolean.FALSE;

private AttributeConstraintRule rule;

private String ruleData;

public Boolean getOutbound() {
return outbound;
}

public void setOutbound(Boolean outbound) {
this.outbound = outbound;
}

public Boolean getInbound() {
return inbound;
}

public void setInbound(Boolean inbound) {
this.inbound = inbound;
}

public AttributeConstraintRule getRule() {
return rule;
}

public void setRule(AttributeConstraintRule rule) {
this.rule = rule;
}

public String getRuleData() {
return ruleData;
}

public void setRuleData(String ruleData) {
this.ruleData = ruleData;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.exclamationlabs.connid.base.connector.attribute.meta;

public enum AttributeConstraintRule {
MAX_LENGTH,
REGEX_MATCH
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.exclamationlabs.connid.base.connector.attribute.meta;

import java.util.List;

/**
* This class and others in this package are used to provide an advised structure for the optional
* attribute metaInfo. At this time, we're using this primarily to store attribute data
* constraint/validation info.
*/
public class AttributeMetaInfo {
List<AttributeConstraint> constraints;

public List<AttributeConstraint> getConstraints() {
return constraints;
}

public void setConstraints(List<AttributeConstraint> constraints) {
this.constraints = constraints;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.identityconnectors.framework.common.exceptions.ConfigurationException;
import org.identityconnectors.framework.common.objects.*;
import org.identityconnectors.framework.spi.operations.SearchOp;
Expand Down Expand Up @@ -111,6 +112,8 @@ private static AttributeInfo buildAttributeInfo(ConnectorAttribute current) {
return new AttributeInfoBuilder(current.getName())
.setNativeName(current.getNativeName())
.setType(current.getDataType().getClassType())
.setSubtype(
StringUtils.isNotBlank(current.getMetaInfoJson()) ? current.getMetaInfoJson() : null)
.setFlags(current.getFlags())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,27 @@ public void testTest() {

@Test
public void testSchema() {
assertNotNull(getConnectorFacade().schema());
var schema = getConnectorFacade().schema();
assertNotNull(schema);
var infos = schema.getObjectClassInfo();
assertNotNull(infos);
var userInfoLookup =
infos.stream().filter(it -> StringUtils.equalsIgnoreCase("user", it.getType())).findFirst();
assertTrue(userInfoLookup.isPresent());
var userInfo = userInfoLookup.get();
assertNotNull(userInfo.getAttributeInfo());
var constrainedLookup =
userInfo.getAttributeInfo().stream()
.filter(
it ->
StringUtils.equalsIgnoreCase(
StubUserAttribute.USER_TEST_MAX_CONSTRAINT.name(), it.getName()))
.findFirst();
assertTrue(constrainedLookup.isPresent());
assertTrue(
StringUtils.equalsIgnoreCase(
"{\"constraints\":[{\"outbound\":true,\"inbound\":false,\"rule\":\"MAX_LENGTH\",\"ruleData\":\"12\"}]}",
constrainedLookup.get().getSubtype()));
}

@Test
Expand Down Expand Up @@ -571,7 +591,7 @@ static void executeTestSchema(
ObjectClassInfo userSchema = schemaResult.findObjectClassInfo("user");
assertNotNull(userSchema);
assertNotNull(userSchema.getAttributeInfo());
assertEquals(19, userSchema.getAttributeInfo().size());
assertEquals(20, userSchema.getAttributeInfo().size());

ObjectClassInfo groupSchema = schemaResult.findObjectClassInfo("group");
assertNotNull(groupSchema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@

import static com.exclamationlabs.connid.base.connector.attribute.ConnectorAttributeDataType.*;
import static com.exclamationlabs.connid.base.connector.stub.attribute.StubUserAttribute.*;
import static org.identityconnectors.framework.common.objects.AttributeInfo.Flags.MULTIVALUED;
import static org.identityconnectors.framework.common.objects.AttributeInfo.Flags.NOT_UPDATEABLE;
import static org.identityconnectors.framework.common.objects.AttributeInfo.Flags.*;

import com.exclamationlabs.connid.base.connector.adapter.AdapterValueTypeConverter;
import com.exclamationlabs.connid.base.connector.adapter.BaseAdapter;
import com.exclamationlabs.connid.base.connector.attribute.ConnectorAttribute;
import com.exclamationlabs.connid.base.connector.attribute.meta.AttributeConstraint;
import com.exclamationlabs.connid.base.connector.attribute.meta.AttributeConstraintRule;
import com.exclamationlabs.connid.base.connector.attribute.meta.AttributeMetaInfo;
import com.exclamationlabs.connid.base.connector.stub.configuration.StubConfiguration;
import com.exclamationlabs.connid.base.connector.stub.model.StubUser;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.*;
import org.identityconnectors.framework.common.objects.*;

Expand Down Expand Up @@ -66,6 +70,10 @@ public Set<ConnectorAttribute> getConnectorAttributes() {
result.add(new ConnectorAttribute(USER_TEST_LONG.name(), LONG));
result.add(new ConnectorAttribute(USER_TEST_MAP.name(), MAP));

result.add(
new ConnectorAttribute(
USER_TEST_MAX_CONSTRAINT.name(), STRING, getMetaJson(), NOT_CREATABLE, NOT_UPDATEABLE));

return result;
}

Expand Down Expand Up @@ -123,4 +131,17 @@ protected Set<Attribute> constructAttributes(StubUser user) {
public Set<Attribute> constructAttributesTestAccess(StubUser user) {
return constructAttributes(user);
}

private String getMetaJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
AttributeConstraint constraint = new AttributeConstraint();
constraint.setOutbound(true);
constraint.setRule(AttributeConstraintRule.MAX_LENGTH);
constraint.setRuleData("12");
AttributeMetaInfo metaInfo = new AttributeMetaInfo();
metaInfo.setConstraints(Collections.singletonList(constraint));

Gson gson = gsonBuilder.create();
return gson.toJson(metaInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ public enum StubUserAttribute {
USER_TEST_GUARDED_STRING,
USER_TEST_INTEGER,
USER_TEST_LONG,
USER_TEST_MAP
USER_TEST_MAP,

USER_TEST_MAX_CONSTRAINT
}

0 comments on commit 815cfe3

Please sign in to comment.