Skip to content

Commit

Permalink
Support LDAP DN-like names in DummyConnector
Browse files Browse the repository at this point in the history
This is to write tests for MID-8929.
  • Loading branch information
mederly committed Sep 14, 2023
1 parent 192bfe0 commit af7bcd3
Show file tree
Hide file tree
Showing 25 changed files with 771 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ public void init(Configuration configuration) {
}
resource.setMonsterization(this.configuration.isMonsterized());
resource.setUidMode(this.configuration.getUidMode());
resource.setHierarchicalObjectsEnabled(this.configuration.isHierarchicalObjectsEnabled());

if (connected) {
throw new IllegalStateException("Double connect in " + this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ public Set<AttributeDelta> updateDelta(final ObjectClass objectClass, final Uid
throw new org.identityconnectors.framework.common.exceptions.AlreadyExistsException(e.getMessage(), e);
}
// We need to change the returned uid here
addUidChange(sideEffectChanges, newName);
if (configuration.isUidBoundToName()) {
addUidChange(sideEffectChanges, newName);
}
}
} else if (delta.is(OperationalAttributes.PASSWORD_NAME)) {
throw new InvalidAttributeValueException("Attempt to change password on group");
Expand Down Expand Up @@ -225,7 +227,9 @@ public Set<AttributeDelta> updateDelta(final ObjectClass objectClass, final Uid
throw new org.identityconnectors.framework.common.exceptions.AlreadyExistsException(e.getMessage(), e);
}
// We need to change the returned uid here
addUidChange(sideEffectChanges, newName);
if (configuration.isUidBoundToName()) {
addUidChange(sideEffectChanges, newName);
}
}
} else if (delta.is(OperationalAttributes.PASSWORD_NAME)) {
throw new InvalidAttributeValueException("Attempt to change password on privilege");
Expand Down Expand Up @@ -266,7 +270,9 @@ public Set<AttributeDelta> updateDelta(final ObjectClass objectClass, final Uid
throw new org.identityconnectors.framework.common.exceptions.AlreadyExistsException(e.getMessage(), e);
}
// We need to change the returned uid here
addUidChange(sideEffectChanges, newName);
if (configuration.isUidBoundToName()) {
addUidChange(sideEffectChanges, newName);
}
} else if (delta.is(OperationalAttributes.PASSWORD_NAME)) {
throw new InvalidAttributeValueException("Attempt to change password on org");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
package com.evolveum.icf.dummy.connector;

import com.evolveum.icf.dummy.resource.*;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;

import org.apache.commons.lang3.StringUtils;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
Expand Down Expand Up @@ -113,7 +115,9 @@ public Uid create(final ObjectClass objectClass, final Set<Attribute> createAttr
} catch (ObjectAlreadyExistsException e) {
// Note: let's do the bad thing and add exception loaded by this classloader as inner exception here
// The framework should deal with it ... somehow
throw new AlreadyExistsException(e.getMessage(),e);
throw new AlreadyExistsException(e.getMessage(), e);
} catch (ObjectDoesNotExistException e) {
throw new InvalidAttributeValueException(e.getMessage(), e); // TODO explain
} catch (ConnectException e) {
throw new ConnectionFailedException(e.getMessage(), e);
} catch (IllegalArgumentException e) {
Expand Down Expand Up @@ -375,8 +379,8 @@ private ObjectClassInfo createPrivilegeObjectClass() {
}

private ObjectClassInfo createOrgObjectClass() {
ObjectClassInfoBuilder objClassBuilder = createCommonObjectClassBuilder(OBJECTCLASS_ORG_NAME,
resource.getPrivilegeObjectClass(), false);
ObjectClassInfoBuilder objClassBuilder =
createCommonObjectClassBuilder(OBJECTCLASS_ORG_NAME, resource.getOrgObjectClass(), false);
return objClassBuilder.build();
}

Expand Down Expand Up @@ -1174,18 +1178,15 @@ private ConnectorObject convertToConnectorObject(DummyPrivilege priv, Collection
}

private ConnectorObject convertToConnectorObject(DummyOrg org, Collection<String> attributesToGet) {
ConnectorObjectBuilder builder = createConnectorObjectBuilderCommon(org, resource.getPrivilegeObjectClass(),
attributesToGet, false);
ConnectorObjectBuilder builder =
createConnectorObjectBuilderCommon(org, resource.getOrgObjectClass(), attributesToGet, false);
builder.setObjectClass(new ObjectClass(OBJECTCLASS_ORG_NAME));
return builder.build();
}

private DummyAccount convertToAccount(Set<Attribute> createAttributes) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException, InterruptedException {
LOG.ok("Create attributes: {0}", createAttributes);
String userName = Utils.getMandatoryStringAttribute(createAttributes, Name.NAME);
if (configuration.getUpCaseName()) {
userName = StringUtils.upperCase(userName);
}
String userName = getIcfName(createAttributes);
LOG.ok("Username {0}", userName);
final DummyAccount newAccount = new DummyAccount(userName);

Expand Down Expand Up @@ -1248,11 +1249,7 @@ private DummyAccount convertToAccount(Set<Attribute> createAttributes) throws Co
}

private DummyGroup convertToGroup(Set<Attribute> createAttributes) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException, InterruptedException {
String icfName = Utils.getMandatoryStringAttribute(createAttributes,Name.NAME);
if (configuration.getUpCaseName()) {
icfName = StringUtils.upperCase(icfName);
}
final DummyGroup newGroup = new DummyGroup(icfName);
final DummyGroup newGroup = new DummyGroup(getIcfName(createAttributes));

Boolean enabled = null;
for (Attribute attr : createAttributes) {
Expand Down Expand Up @@ -1297,11 +1294,7 @@ private DummyGroup convertToGroup(Set<Attribute> createAttributes) throws Connec
}

private DummyPrivilege convertToPriv(Set<Attribute> createAttributes) throws ConnectException, FileNotFoundException, ConflictException {
String icfName = Utils.getMandatoryStringAttribute(createAttributes,Name.NAME);
if (configuration.getUpCaseName()) {
icfName = StringUtils.upperCase(icfName);
}
final DummyPrivilege newPriv = new DummyPrivilege(icfName);
final DummyPrivilege newPriv = new DummyPrivilege(getIcfName(createAttributes));

for (Attribute attr : createAttributes) {
if (attr.is(Uid.NAME)) {
Expand Down Expand Up @@ -1331,13 +1324,9 @@ private DummyPrivilege convertToPriv(Set<Attribute> createAttributes) throws Con
return newPriv;
}

private DummyOrg convertToOrg(Set<Attribute> createAttributes) throws ConnectException, FileNotFoundException, ConflictException {
String icfName = Utils.getMandatoryStringAttribute(createAttributes,Name.NAME);
if (configuration.getUpCaseName()) {
icfName = StringUtils.upperCase(icfName);
}
final DummyOrg newOrg = new DummyOrg(icfName);

private DummyOrg convertToOrg(Set<Attribute> createAttributes)
throws ConnectException, FileNotFoundException, ConflictException {
DummyOrg newOrg = new DummyOrg(getIcfName(createAttributes));
for (Attribute attr : createAttributes) {
if (attr.is(Uid.NAME)) {
throw new IllegalArgumentException("UID explicitly specified in the org attributes");
Expand All @@ -1362,10 +1351,18 @@ private DummyOrg convertToOrg(Set<Attribute> createAttributes) throws ConnectExc
}
}
}

return newOrg;
}

private String getIcfName(Set<Attribute> createAttributes) {
String icfName = Utils.getMandatoryStringAttribute(createAttributes, Name.NAME);
if (configuration.getUpCaseName()) {
return StringUtils.upperCase(icfName);
} else {
return icfName;
}
}

protected Boolean getBoolean(Attribute attr) {
if (attr.getValue() == null || attr.getValue().isEmpty()) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public class DummyConfiguration extends AbstractConfiguration {
private String uselessString;
private GuardedString uselessGuardedString;
private boolean requireUselessString = false;
private boolean generateAccountDescriptionOnCreate = false; // simulates volatile behavior (on create)
private boolean generateAccountDescriptionOnUpdate = false; // simulates volatile behavior (on update)
private boolean generateAccountDescriptionOnCreate = false; // simulates volatile behavior (on create)
private boolean generateAccountDescriptionOnUpdate = false; // simulates volatile behavior (on update)
private String[] forbiddenNames = new String[0];
private boolean useLegacySchema = true;
private String requiredBaseContextOrgName = null;
Expand All @@ -66,6 +66,7 @@ public class DummyConfiguration extends AbstractConfiguration {
private boolean impreciseTokenValues = false;
private String[] alwaysRequireUpdateOfAttribute = new String[0];
private boolean canRead = true;
private boolean hierarchicalObjectsEnabled;

/**
* Defines name of the dummy resource instance. There may be several dummy resource running in
Expand Down Expand Up @@ -456,15 +457,30 @@ public void setCanRead(boolean canRead) {
this.canRead = canRead;
}

@ConfigurationProperty
public boolean isHierarchicalObjectsEnabled() {
return hierarchicalObjectsEnabled;
}

public void setHierarchicalObjectsEnabled(boolean hierarchicalObjectsEnabled) {
this.hierarchicalObjectsEnabled = hierarchicalObjectsEnabled;
}

/**
* {@inheritDoc}
*/
@Override
public void validate() {
LOG.info("begin");

if (isUidBoundToName() && !enforceUniqueName) {
throw new IllegalArgumentException("Cannot use name UID mode without enforceUniqueName");
if (!enforceUniqueName) {
if (isUidBoundToName()) {
throw new ConfigurationException("Cannot use name UID mode without enforceUniqueName");
}

if (hierarchicalObjectsEnabled) {
throw new ConfigurationException("Cannot use hierarchical objects without enforceUniqueName");
}
}

LOG.info("uselessString: {0}", uselessString);
Expand Down
4 changes: 4 additions & 0 deletions icf-connectors/dummy-resource/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,9 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public Collection<String> getMembers() {
return getAttributeValues(ATTR_MEMBERS_NAME, String.class);
}

public void addMember(String newMember) throws SchemaViolationException, ConnectException, FileNotFoundException, ConflictException, InterruptedException {
public void addMember(String newMember)
throws SchemaViolationException, ConnectException, FileNotFoundException, ConflictException, InterruptedException {
addAttributeValue(ATTR_MEMBERS_NAME, newMember);
}

Expand All @@ -41,10 +42,11 @@ public boolean containsMember(String member) {
if (members == null) {
return false;
}
return members.contains(member); // TODO ok? what about case ignoring scenarios?
return members.contains(member); // TODO ok? what about case ignoring scenarios?
}

public void removeMember(String newMember) throws SchemaViolationException, ConnectException, FileNotFoundException, ConflictException, InterruptedException {
public void removeMember(String newMember)
throws SchemaViolationException, ConnectException, FileNotFoundException, ConflictException, InterruptedException {
removeAttributeValue(ATTR_MEMBERS_NAME, newMember);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ public abstract class DummyObject implements DebugDumpable {
private String id;
// private int internalId = -1;
private String name;

private final Map<String,Set<Object>> attributes = new ConcurrentHashMap<>();
private Boolean enabled = true;
private Date validFrom = null;
private Date validTo = null;
private String lastModifier;
protected DummyResource resource;

/** Present only if hierarchy is supported. Set when object is added on the resource (we need to know the normalization). */
private HierarchicalName normalizedHierarchicalName;

private final Set<String> auxiliaryObjectClassNames = ConcurrentHashMap.newKeySet();

private BreakMode modifyBreakMode = null;
Expand Down Expand Up @@ -69,6 +73,17 @@ public String getName() {

public void setName(String username) {
this.name = username;
if (resource != null) {
resource.updateNormalizedHierarchicalName(this);
}
}

/**
* The normalized hierarchical name cannot be computed by the object itself. It needs the resource
* (normalization, hierarchy support). This method is called from there. It is intentionally package-private.
*/
void setNormalizedHierarchicalName(HierarchicalName normalizedHierarchicalName) {
this.normalizedHierarchicalName = normalizedHierarchicalName;
}

public Boolean isEnabled() {
Expand Down Expand Up @@ -507,4 +522,9 @@ public boolean isReturnedByDefault(String attrName) {
return false;
}
}

/** Assumes hierarchical object support is on. */
boolean containedByOrg(HierarchicalName normalizedOrgName) {
return normalizedHierarchicalName != null && normalizedHierarchicalName.residesIn(normalizedOrgName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ public DummyOrg() {
super();
}

public DummyOrg(String username) {
super(username);
public DummyOrg(String orgName) {
super(orgName);
}

@Override
protected DummyObjectClass getObjectClass() throws ConnectException, FileNotFoundException, SchemaViolationException {
return resource.getPrivilegeObjectClass();
return resource.getOrgObjectClass();
}

@Override
protected DummyObjectClass getObjectClassNoExceptions() {
return resource.getPrivilegeObjectClass();
return resource.getOrgObjectClass();
}

@Override
Expand Down

0 comments on commit af7bcd3

Please sign in to comment.