From 97c932e4a06858e011a10870c2a098419d3d0cd3 Mon Sep 17 00:00:00 2001 From: Sylinsic <38617929+Sylinsic@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:08:12 +0100 Subject: [PATCH 1/5] Provide configuration for any-object attributes - Allow configuration of name attribute for any-objects - Allow configuration of object classes for any-objects - Provide messages for the above mentioned config properties. --- .../bundles/ldap/LdapConfiguration.java | 81 +++++++++++++------ .../connid/bundles/ldap/Messages.properties | 8 ++ .../bundles/ldap/Messages_de.properties | 9 +++ .../bundles/ldap/Messages_es.properties | 8 ++ .../bundles/ldap/Messages_fr.properties | 8 ++ .../bundles/ldap/Messages_it.properties | 8 ++ .../bundles/ldap/Messages_ja.properties | 8 ++ .../bundles/ldap/Messages_ko.properties | 8 ++ .../bundles/ldap/Messages_pt.properties | 8 ++ .../bundles/ldap/Messages_zh.properties | 8 ++ .../bundles/ldap/Messages_zh_TW.properties | 10 ++- 11 files changed, 138 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java b/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java index 5e72db0..e027cfa 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java @@ -267,6 +267,13 @@ public void validate() { checkNotEmpty(groupConfig.getShortNameLdapAttributes(), "groupNameAttributes.notEmpty"); checkNoBlankValues(groupConfig.getShortNameLdapAttributes(), "groupNameAttributes.noBlankValues"); + checkNotEmpty(allConfig.getLdapClasses(), "anyObjectClasses.notEmpty"); + checkNoBlankValues(allConfig.getLdapClasses(), "anyObjectClasses.noBlankValues"); + + checkNotEmpty(allConfig.getShortNameLdapAttributes(), "anyObjectNameAttributes.notEmpty"); + checkNoBlankValues(allConfig.getShortNameLdapAttributes(), "anyObjectNameAttributes.noBlankValues"); + + checkNotBlank(groupMemberAttribute, "groupMemberAttribute.notBlank"); checkNotBlank(vlvSortAttribute, "vlvSortAttribute.notBlank"); @@ -562,6 +569,30 @@ public void setAddPrincipalToNewGroups(boolean addPrincipalToNewGroups) { } @ConfigurationProperty(order = 18, + displayMessageKey = "anyObjectClasses.display", + helpMessageKey = "anyObjectClasses.help") + public String[] getAnyObjectClasses() { + List ldapClasses = allConfig.getLdapClasses(); + return ldapClasses.toArray(new String[ldapClasses.size()]); + } + + public void setAnyObjectClasses(String... anyObjectClasses) { + allConfig.setLdapClasses(Arrays.asList(anyObjectClasses)); + } + + @ConfigurationProperty(order = 19, + displayMessageKey = "anyObjectNameAttributes.display", + helpMessageKey = "anyObjectNameAttributes.help") + public String[] getAnyObjectNameAttributes() { + List shortNameLdapAttributes = allConfig.getShortNameLdapAttributes(); + return shortNameLdapAttributes.toArray(new String[shortNameLdapAttributes.size()]); + } + + public void setAnyObjectNameAttributes(String... anyObjectNameAttributes) { + allConfig.setShortNameLdapAttributes(Arrays.asList(anyObjectNameAttributes)); + } + + @ConfigurationProperty(order = 20, displayMessageKey = "passwordHashAlgorithm.display", helpMessageKey = "passwordHashAlgorithm.help") public String getPasswordHashAlgorithm() { @@ -572,7 +603,7 @@ public void setPasswordHashAlgorithm(String passwordHashAlgorithm) { this.passwordHashAlgorithm = passwordHashAlgorithm; } - @ConfigurationProperty(order = 19, + @ConfigurationProperty(order = 21, displayMessageKey = "respectResourcePasswordPolicyChangeAfterReset.display", helpMessageKey = "respectResourcePasswordPolicyChangeAfterReset.help") public boolean isRespectResourcePasswordPolicyChangeAfterReset() { @@ -583,7 +614,7 @@ public void setRespectResourcePasswordPolicyChangeAfterReset(boolean respectReso this.respectResourcePasswordPolicyChangeAfterReset = respectResourcePasswordPolicyChangeAfterReset; } - @ConfigurationProperty(order = 20, + @ConfigurationProperty(order = 22, displayMessageKey = "useVlvControls.display", helpMessageKey = "useVlvControls.help") public boolean isUseVlvControls() { @@ -594,7 +625,7 @@ public void setUseVlvControls(boolean useVlvControls) { this.useVlvControls = useVlvControls; } - @ConfigurationProperty(order = 21, + @ConfigurationProperty(order = 23, displayMessageKey = "vlvSortAttribute.display", helpMessageKey = "vlvSortAttribute.help") public String getVlvSortAttribute() { @@ -605,7 +636,7 @@ public void setVlvSortAttribute(String vlvSortAttribute) { this.vlvSortAttribute = vlvSortAttribute; } - @ConfigurationProperty(order = 22, + @ConfigurationProperty(order = 24, displayMessageKey = "uidAttribute.display", helpMessageKey = "uidAttribute.help") public String getUidAttribute() { @@ -616,7 +647,7 @@ public void setUidAttribute(final String uidAttribute) { this.uidAttribute = uidAttribute; } - @ConfigurationProperty(order = 23, + @ConfigurationProperty(order = 25, displayMessageKey = "gidAttribute.display", helpMessageKey = "gidAttribute.help") public String getGidAttribute() { @@ -627,7 +658,7 @@ public void setGidAttribute(final String gidAttribute) { this.gidAttribute = gidAttribute; } - @ConfigurationProperty(order = 23, + @ConfigurationProperty(order = 26, displayMessageKey = "readSchema.display", helpMessageKey = "readSchema.help") public boolean isReadSchema() { @@ -639,7 +670,7 @@ public void setReadSchema(boolean readSchema) { } // Sync properties getters and setters. - @ConfigurationProperty(order = 24, operations = { SyncOp.class }, + @ConfigurationProperty(order = 27, operations = { SyncOp.class }, displayMessageKey = "baseContextsToSynchronize.display", helpMessageKey = "baseContextsToSynchronize.help") public String[] getBaseContextsToSynchronize() { @@ -650,7 +681,7 @@ public void setBaseContextsToSynchronize(String... baseContextsToSynchronize) { this.baseContextsToSynchronize = baseContextsToSynchronize.clone(); } - @ConfigurationProperty(order = 25, operations = { SyncOp.class }, + @ConfigurationProperty(order = 28, operations = { SyncOp.class }, displayMessageKey = "objectClassesToSynchronize.display", helpMessageKey = "objectClassesToSynchronize.help") public String[] getObjectClassesToSynchronize() { @@ -661,7 +692,7 @@ public void setObjectClassesToSynchronize(String... objectClassesToSynchronize) this.objectClassesToSynchronize = objectClassesToSynchronize.clone(); } - @ConfigurationProperty(order = 26, operations = { SyncOp.class }, + @ConfigurationProperty(order = 29, operations = { SyncOp.class }, displayMessageKey = "attributesToSynchronize.display", helpMessageKey = "attributesToSynchronize.help") public String[] getAttributesToSynchronize() { @@ -672,7 +703,7 @@ public void setAttributesToSynchronize(String... attributesToSynchronize) { this.attributesToSynchronize = attributesToSynchronize.clone(); } - @ConfigurationProperty(order = 27, operations = { SyncOp.class }, + @ConfigurationProperty(order = 30, operations = { SyncOp.class }, displayMessageKey = "modifiersNamesToFilterOut.display", helpMessageKey = "modifiersNamesToFilterOut.help") public String[] getModifiersNamesToFilterOut() { @@ -683,7 +714,7 @@ public void setModifiersNamesToFilterOut(String... modifiersNamesToFilterOut) { this.modifiersNamesToFilterOut = modifiersNamesToFilterOut.clone(); } - @ConfigurationProperty(order = 28, operations = { SyncOp.class }, + @ConfigurationProperty(order = 31, operations = { SyncOp.class }, displayMessageKey = "accountSynchronizationFilter.display", helpMessageKey = "accountSynchronizationFilter.help") public String getAccountSynchronizationFilter() { @@ -694,7 +725,7 @@ public void setAccountSynchronizationFilter(String accountSynchronizationFilter) this.accountSynchronizationFilter = accountSynchronizationFilter; } - @ConfigurationProperty(order = 29, operations = { SyncOp.class }, + @ConfigurationProperty(order = 32, operations = { SyncOp.class }, displayMessageKey = "changeLogBlockSize.display", helpMessageKey = "changeLogBlockSize.help") public int getChangeLogBlockSize() { @@ -705,7 +736,7 @@ public void setChangeLogBlockSize(int changeLogBlockSize) { this.changeLogBlockSize = changeLogBlockSize; } - @ConfigurationProperty(order = 30, operations = { SyncOp.class }, + @ConfigurationProperty(order = 33, operations = { SyncOp.class }, displayMessageKey = "changeNumberAttribute.display", helpMessageKey = "changeNumberAttribute.help") public String getChangeNumberAttribute() { @@ -716,7 +747,7 @@ public void setChangeNumberAttribute(String changeNumberAttribute) { this.changeNumberAttribute = changeNumberAttribute; } - @ConfigurationProperty(order = 31, operations = { SyncOp.class }, + @ConfigurationProperty(order = 34, operations = { SyncOp.class }, displayMessageKey = "filterWithOrInsteadOfAnd.display", helpMessageKey = "filterWithOrInsteadOfAnd.help") public boolean isFilterWithOrInsteadOfAnd() { @@ -727,7 +758,7 @@ public void setFilterWithOrInsteadOfAnd(boolean filterWithOrInsteadOfAnd) { this.filterWithOrInsteadOfAnd = filterWithOrInsteadOfAnd; } - @ConfigurationProperty(order = 32, operations = { SyncOp.class }, + @ConfigurationProperty(order = 35, operations = { SyncOp.class }, displayMessageKey = "removeLogEntryObjectClassFromFilter.display", helpMessageKey = "removeLogEntryObjectClassFromFilter.help") public boolean isRemoveLogEntryObjectClassFromFilter() { @@ -738,7 +769,7 @@ public void setRemoveLogEntryObjectClassFromFilter(boolean removeLogEntryObjectC this.removeLogEntryObjectClassFromFilter = removeLogEntryObjectClassFromFilter; } - @ConfigurationProperty(order = 33, operations = { SyncOp.class }, + @ConfigurationProperty(order = 36, operations = { SyncOp.class }, displayMessageKey = "synchronizePasswords.display", helpMessageKey = "synchronizePasswords.help") public boolean isSynchronizePasswords() { @@ -749,7 +780,7 @@ public void setSynchronizePasswords(boolean synchronizePasswords) { this.synchronizePasswords = synchronizePasswords; } - @ConfigurationProperty(order = 34, operations = { SyncOp.class }, + @ConfigurationProperty(order = 37, operations = { SyncOp.class }, displayMessageKey = "passwordAttributeToSynchronize.display", helpMessageKey = "passwordAttributeToSynchronize.help") public String getPasswordAttributeToSynchronize() { @@ -760,7 +791,7 @@ public void setPasswordAttributeToSynchronize(String passwordAttributeToSynchron this.passwordAttributeToSynchronize = passwordAttributeToSynchronize; } - @ConfigurationProperty(order = 35, operations = { SyncOp.class }, confidential = true, + @ConfigurationProperty(order = 38, operations = { SyncOp.class }, confidential = true, displayMessageKey = "passwordDecryptionKey.display", helpMessageKey = "passwordDecryptionKey.help") public GuardedByteArray getPasswordDecryptionKey() { @@ -772,7 +803,7 @@ public void setPasswordDecryptionKey(GuardedByteArray passwordDecryptionKey) { copy() : null; } - @ConfigurationProperty(order = 36, operations = { SyncOp.class }, confidential = true, + @ConfigurationProperty(order = 39, operations = { SyncOp.class }, confidential = true, displayMessageKey = "passwordDecryptionInitializationVector.display", helpMessageKey = "passwordDecryptionInitializationVector.help") public GuardedByteArray getPasswordDecryptionInitializationVector() { @@ -785,7 +816,7 @@ public void setPasswordDecryptionInitializationVector(GuardedByteArray passwordD copy() : null; } - @ConfigurationProperty(order = 37, + @ConfigurationProperty(order = 40, displayMessageKey = "statusManagementClass.display", helpMessageKey = "statusManagementClass.help") public String getStatusManagementClass() { @@ -796,7 +827,7 @@ public void setStatusManagementClass(String statusManagementClass) { this.statusManagementClass = statusManagementClass; } - @ConfigurationProperty(order = 38, + @ConfigurationProperty(order = 41, displayMessageKey = "retrievePasswordsWithSearch.display", helpMessageKey = "retrievePasswordsWithSearch.help") public boolean getRetrievePasswordsWithSearch() { @@ -807,7 +838,7 @@ public void setRetrievePasswordsWithSearch(boolean retrievePasswordsWithSearch) this.retrievePasswordsWithSearch = retrievePasswordsWithSearch; } - @ConfigurationProperty(order = 39, + @ConfigurationProperty(order = 42, displayMessageKey = "dnAttribute.display", helpMessageKey = "dnAttribute.help") public String getDnAttribute() { @@ -818,7 +849,7 @@ public void setDnAttribute(String dnAttribute) { this.dnAttribute = dnAttribute; } - @ConfigurationProperty(order = 40, + @ConfigurationProperty(order = 43, displayMessageKey = "groupSearchFilter.display", helpMessageKey = "groupSearchFilter.help") public String getGroupSearchFilter() { @@ -829,7 +860,7 @@ public void setGroupSearchFilter(String groupSearchFilter) { this.groupSearchFilter = groupSearchFilter; } - @ConfigurationProperty(order = 41, + @ConfigurationProperty(order = 44, displayMessageKey = "readTimeout.display", helpMessageKey = "readTimeout.help") public long getReadTimeout() { @@ -840,7 +871,7 @@ public void setReadTimeout(long readTimeout) { this.readTimeout = readTimeout; } - @ConfigurationProperty(order = 42, + @ConfigurationProperty(order = 45, displayMessageKey = "connectTimeout.display", helpMessageKey = "connectTimeout.help") public long getConnectTimeout() { diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties index 449cc5a..7ba66b7 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties @@ -95,6 +95,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. Default is "cn". +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) @@ -120,6 +124,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=The group member attribute cannot be blank vlvSortAttribute.notBlank=The VLV sort attribute cannot be blank uidAttribute.notBlank=The attribute to map to Uid cannot be blank diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties index 6c85e29..2af2a3f 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties @@ -107,6 +107,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=Das Gruppenmitgliedattribut darf nicht leer sein vlvSortAttribute.notBlank=Das VLV-Sortierattribut darf nicht leer sein uidAttribute.notBlank=Das zur UID zuzuordnende Attribut darf nicht leer sein @@ -138,6 +142,11 @@ groupObjectClasses.help=The group class or classes that will be used when creati groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. + dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) useVlvControls.display= diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties index ca5b118..6b64602 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=El atributo de miembro de grupo no puede quedar en blanco vlvSortAttribute.notBlank=El atributo de ordenaci\u00f3n de VLV no puede quedar en blanco uidAttribute.notBlank=El atributo de asignaci\u00f3n a Uid no puede quedar en blanco @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties index a727800..ec12084 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=L\u2019attribut de membre de groupe doit \u00eatre sp\u00e9cifi\u00e9. vlvSortAttribute.notBlank=L\u2019attribut de tri VLV doit \u00eatre sp\u00e9cifi\u00e9. uidAttribute.notBlank=L\u2019attribut \u00e0 mapper \u00e0 l\u2019UID doit \u00eatre sp\u00e9cifi\u00e9. @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties index 406fee7..7af84d7 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=L\u2019elenco delle classi oggetto del gruppo non pu groupObjectClasses.noBlankValues=L\u2019elenco delle classi oggetto del gruppo non pu\u00f2 contenere valori vuoti groupNameAttributes.notEmpty=L\u2019elenco di attributi del nome dei gruppi non pu\u00f2 essere vuoto groupNameAttributes.noBlankValues=L\u2019elenco di attributi del nome dei gruppi non pu\u00f2 contenere valori vuoti +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=L\u2019attributo del gruppo non pu\u00f2 essere vuoto vlvSortAttribute.notBlank=L\u2019attributo di ordinamento VLV non pu\u00f2 essere vuoto uidAttribute.notBlank=L\u2019attributo da assegnare all\u2019Uid non pu\u00f2 essere vuoto @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Nome attributo per DN dnAttribute.help=Nome attributo per DN (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties index cdfe699..76c78fc 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=\u30b0\u30eb\u30fc\u30d7\u30e1\u30f3\u30d0\u30fc\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 vlvSortAttribute.notBlank=VLV \u4e26\u3079\u66ff\u3048\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 uidAttribute.notBlank=UID \u306b\u30de\u30c3\u30d7\u3059\u308b\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties index 8126bc1..c81e5b2 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=\uadf8\ub8f9 \uad6c\uc131\uc6d0 \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. vlvSortAttribute.notBlank=VLV \uc815\ub82c \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. uidAttribute.notBlank=UID\uc5d0 \ub9e4\ud551\ud560 \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties index a8e6b9b..eaa167e 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=O atributo de membro de grupo n\u00e3o pode ficar em branco vlvSortAttribute.notBlank=O atributo de classifica\u00e7\u00e3o VLV n\u00e3o pode ficar em branco uidAttribute.notBlank=O atributo de mapeamento para Uid n\u00e3o pode ficar em branco @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties index 1b14d38..325762a 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties @@ -104,6 +104,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=\u7ec4\u6210\u5458\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a vlvSortAttribute.notBlank=VLV \u6392\u5e8f\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a uidAttribute.notBlank=\u8981\u6620\u5c04\u5230 UID \u7684\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a @@ -136,6 +140,10 @@ groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties index 0dca7b3..989e3b1 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties @@ -75,7 +75,11 @@ changeLogBlockSize.help=\u6bcf\u6b21\u67e5\u8a62\u6240\u64f7\u53d6\u7684\u8b8a\u changeNumberAttribute.display=\u8b8a\u66f4\u6578\u5b57\u5c6c\u6027groupObjectClasses.display=Group Object Classes groupObjectClasses.help=The group class or classes that will be used when creating new group objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple group classes. Some group classes may require that you specify all group classes in the class hierarchy. groupNameAttributes.display=Group Name Attributes -groupNameAttributes.help=Attribute or attributes which holds the group''s name. +groupNameAttributes.help=Attribute or attributes which holds the group''s name. +anyObjectClasses.display=Any-object Object Classes +anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. +anyObjectNameAttributes.display=Any-object Name Attributes +anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. changeNumberAttribute.help=\u8b8a\u66f4\u8a18\u9304\u9805\u76ee\u4e2d\u4e4b\u8b8a\u66f4\u6578\u5b57\u5c6c\u6027\u7684\u540d\u7a31\u3002 filterWithOrInsteadOfAnd.display=\u4f7f\u7528 OR \u800c\u4e0d\u4f7f\u7528 AND \u7be9\u9078 filterWithOrInsteadOfAnd.help=\u4e00\u822c\u5728\u64f7\u53d6\u8b8a\u66f4\u8a18\u9304\u9805\u76ee\u6642\uff0c\u6703\u4f7f\u7528 AND \u7be9\u9078\u5668\u64f7\u53d6\u4e00\u6bb5\u671f\u9593\u5167\u7684\u8b8a\u66f4\u9805\u76ee\u3002\u82e5\u8a2d\u5b9a\u6b64\u7279\u6027\uff0c\u5247\u6703\u6539\u7528 OR \u7be9\u9078\u5668\u642d\u914d\u6240\u9700\u7684\u8b8a\u66f4\u6578\u5b57\u3002 @@ -107,6 +111,10 @@ groupObjectClasses.notEmpty=The list of group object classes cannot be empty groupObjectClasses.noBlankValues=The list of group object classes cannot contain blank values groupNameAttributes.notEmpty=The list of group name attributes cannot be empty groupNameAttributes.noBlankValues=The list of group name attributes cannot contain blank values +anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty +anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values +anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty +anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values groupMemberAttribute.notBlank=\u7fa4\u7d44\u6210\u54e1\u5c6c\u6027\u4e0d\u53ef\u70ba\u7a7a\u767d vlvSortAttribute.notBlank=VLV \u6392\u5e8f\u5c6c\u6027\u4e0d\u53ef\u70ba\u7a7a\u767d uidAttribute.notBlank=\u8981\u5c0d\u6620\u81f3 Uid \u7684\u5c6c\u6027\u4e0d\u53ef\u70ba\u7a7a\u767d From 2f33c4bb70daa92872fe640d5111187396454ce9 Mon Sep 17 00:00:00 2001 From: Sylinsic <38617929+Sylinsic@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:51:52 +0100 Subject: [PATCH 2/5] Add tests for anyObjects Creating a 'device' object --- .../bundles/ldap/LdapConfigurationTests.java | 38 +++++++++++++++++++ .../bundles/ldap/LdapConnectorTestBase.java | 6 +++ .../bundles/ldap/modify/LdapCreateTests.java | 38 +++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java index 7b53d41..65e50b1 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java @@ -113,6 +113,42 @@ public void accountUserNameAttributesItemNotNull() { assertThrows(ConfigurationException.class, () -> config.validate()); } + @Test + public void anyObjectNameAttributesNotEmpty() { + config.setAnyObjectNameAttributes(); + assertThrows(ConfigurationException.class, () -> config.validate()); + } + + @Test + public void anyObjectNameAttributesNotNull() { + config.setAnyObjectNameAttributes((String) null); + assertThrows(ConfigurationException.class, () -> config.validate()); + } + + @Test + public void anyObjectNameAttributesNotBlank() { + config.setAnyObjectNameAttributes(" "); + assertThrows(ConfigurationException.class, () -> config.validate()); + } + + @Test + public void anyObjectClassesNotEmpty() { + config.setAnyObjectClasses(); + assertThrows(ConfigurationException.class, () -> config.validate()); + } + + @Test + public void anyObjectClassesNotNull() { + config.setAnyObjectClasses((String) null); + assertThrows(ConfigurationException.class, () -> config.validate()); + } + + @Test + public void anyObjectClassesNotBlank() { + config.setAnyObjectClasses(" "); + assertThrows(ConfigurationException.class, () -> config.validate()); + } + @Test public void groupMemberAttributeNotNull() { config.setGroupMemberAttribute(null); @@ -311,6 +347,8 @@ public void defaultValues() { assertNull(config.getGroupSearchFilter()); assertEquals(0, config.getReadTimeout()); assertEquals(0, config.getConnectTimeout()); + assertEquals(CollectionUtil.newList("top"), Arrays.asList(config.getAnyObjectClasses())); + assertEquals(CollectionUtil.newList("entryUUID"), Arrays.asList(config.getAnyObjectNameAttributes())); } private static void assertCanValidate(LdapConfiguration config) { diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java index 64d1b83..f7e8281 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java @@ -149,6 +149,12 @@ public abstract class LdapConnectorTestBase { public static final String USER_0_GIVEN_NAME = "Aaccf"; + public static final String DEVICE_0_DN = "cn=Laptop,o=Small Company,dc=example,dc=com"; + + public static final String DEVICE_0_CN = "Laptop"; + + public static final String DEVICE_0_SERIALNUMBER = "42"; + @BeforeAll public static void init() throws IOException { InputStream propStream = null; diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/modify/LdapCreateTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/modify/LdapCreateTests.java index 2c049a5..3b4f880 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/modify/LdapCreateTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/modify/LdapCreateTests.java @@ -197,6 +197,44 @@ private void doCreateArbitrary(ConnectorFacade facade) { assertEquals(name, newObject.getName()); } + @Test + public void createArbitraryWhenNameAttributesNotDefault() { + LdapConfiguration config = newConfiguration(); + assertFalse(config.getUidAttribute().equalsIgnoreCase("entryDN")); + config.setAnyObjectNameAttributes("cn"); + config.setBaseContexts(SMALL_COMPANY_DN); + ConnectorFacade facade = newFacade(config); + + doCreateDevice(facade); + } + + @Test + public void createArbitraryWhenObjectClassesNotDefault() { + LdapConfiguration config = newConfiguration(); + assertFalse(config.getUidAttribute().equalsIgnoreCase("entryDN")); + config.setAnyObjectClasses("top", "organization"); + config.setBaseContexts(SMALL_COMPANY_DN); + ConnectorFacade facade = newFacade(config); + + doCreateDevice(facade); + } + + private void doCreateDevice(ConnectorFacade facade) { + Set attributes = new HashSet<>(); + Name name = new Name(DEVICE_0_DN); + attributes.add(name); + attributes.add(AttributeBuilder.build("cn", DEVICE_0_CN)); + attributes.add(AttributeBuilder.build("serialNumber", DEVICE_0_SERIALNUMBER)); + + ObjectClass oclass = new ObjectClass("device"); + Uid uid = facade.create(oclass, attributes, null); + + ConnectorObject newObject = facade.getObject(oclass, uid, null); + assertEquals(name, newObject.getName()); + + } + + @Test public void createBinaryAttributes() throws IOException { ConnectorFacade facade = newFacade(); From 4e8b1d4cc7e3969dc583150bac51e4cd8fd326ec Mon Sep 17 00:00:00 2001 From: Sylinsic <38617929+Sylinsic@users.noreply.github.com> Date: Mon, 20 Nov 2023 00:44:49 +0000 Subject: [PATCH 3/5] Add SearchScope functionality and anyobject filtering Add the ability to set the search scope (object, onelevel, subtree) for each of User, Group and Any objects Add search filters for any objects. Currently an issue with tests throwing an UnknownUidException - probably due to the anyobject filter filtering out the organization --- .../bundles/ldap/LdapConfiguration.java | 158 +++++++++++++---- .../bundles/ldap/search/LdapSearch.java | 21 ++- .../connid/bundles/ldap/Messages.properties | 14 ++ .../bundles/ldap/Messages_de.properties | 14 ++ .../bundles/ldap/Messages_es.properties | 14 ++ .../bundles/ldap/Messages_fr.properties | 14 ++ .../bundles/ldap/Messages_it.properties | 14 ++ .../bundles/ldap/Messages_ja.properties | 14 ++ .../bundles/ldap/Messages_ko.properties | 14 ++ .../bundles/ldap/Messages_pt.properties | 14 ++ .../bundles/ldap/Messages_zh.properties | 14 ++ .../bundles/ldap/Messages_zh_TW.properties | 14 ++ .../ldap/AdapterCompatibilityTests.java | 2 +- .../bundles/ldap/LdapConfigurationTests.java | 72 ++++++++ .../bundles/ldap/LdapConnectorTestBase.java | 26 ++- .../bundles/ldap/search/LdapSearchTests.java | 167 ++++++++++++++++++ src/test/resources/opendj/data.ldif | 34 +++- 17 files changed, 563 insertions(+), 57 deletions(-) diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java b/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java index e027cfa..e4d7f75 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java @@ -45,6 +45,7 @@ import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.framework.common.exceptions.ConfigurationException; import org.identityconnectors.framework.common.objects.ObjectClass; +import org.identityconnectors.framework.common.objects.OperationOptions; import org.identityconnectors.framework.spi.AbstractConfiguration; import org.identityconnectors.framework.spi.ConfigurationProperty; import org.identityconnectors.framework.spi.operations.SyncOp; @@ -112,6 +113,11 @@ public class LdapConfiguration extends AbstractConfiguration { */ private String groupSearchFilter = null; + /** + * A search filter that any anyObject needs to match in order to be returned + */ + private String anyObjectSearchFilter = null; + /** * The LDAP attribute holding the member for non-POSIX static groups. */ @@ -199,6 +205,21 @@ public class LdapConfiguration extends AbstractConfiguration { private String dnAttribute = "entryDN"; + /** + * The SearchScope for user objects + */ + private SearchScope userSearchScope = SearchScope.subtree; + + /** + * The SearchScope for group objects + */ + private SearchScope groupSearchScope = SearchScope.subtree; + + /** + * The SearchScope for anyObject objects + */ + private SearchScope anyObjectSearchScope = SearchScope.subtree; + /** * Whether to retrieve passwords when searching. The default is "false". */ @@ -273,6 +294,14 @@ public void validate() { checkNotEmpty(allConfig.getShortNameLdapAttributes(), "anyObjectNameAttributes.notEmpty"); checkNoBlankValues(allConfig.getShortNameLdapAttributes(), "anyObjectNameAttributes.noBlankValues"); + checkNotBlank(getUserSearchScope(), "userSearchScope.notBlank"); + checkValidScope(getUserSearchScope(), "userSearchScope.invalidScope"); + + checkNotBlank(getGroupSearchScope(), "groupSearchScope.notBlank"); + checkValidScope(getGroupSearchScope(), "groupSearchScope.invalidScope"); + + checkNotBlank(getAnyObjectSearchScope(), "anyObjectSearchScope.notBlank"); + checkValidScope(getAnyObjectSearchScope(), "anyObjectSearchScope.invalidScope"); checkNotBlank(groupMemberAttribute, "groupMemberAttribute.notBlank"); @@ -368,6 +397,17 @@ private void checkNoInvalidLdapNames(String[] array, String errorMessage) { } } + private void checkValidScope(String scope, String errorMessage) { + switch (scope) { + case OperationOptions.SCOPE_OBJECT: + case OperationOptions.SCOPE_ONE_LEVEL: + case OperationOptions.SCOPE_SUBTREE: + break; + default: + failValidation(errorMessage); + } + } + private void failValidation(String key, Object... args) { String message = getConnectorMessages().format(key, null, args); throw new ConfigurationException(message); @@ -490,6 +530,17 @@ public void setAccountUserNameAttributes(String... accountUserNameAttributes) { } @ConfigurationProperty(order = 11, + displayMessageKey = "userSearchScope.display", + helpMessageKey = "userSearchScope.help") + public String getUserSearchScope() { + return userSearchScope.toString(); + } + + public void setUserSearchScope(String userSearchScope) { + this.userSearchScope = SearchScope.valueOf(userSearchScope.toLowerCase()); + } + + @ConfigurationProperty(order = 12, displayMessageKey = "accountSearchFilter.display", helpMessageKey = "accountSearchFilter.help") public String getAccountSearchFilter() { @@ -500,7 +551,7 @@ public void setAccountSearchFilter(String accountSearchFilter) { this.accountSearchFilter = accountSearchFilter; } - @ConfigurationProperty(order = 12, + @ConfigurationProperty(order = 13, displayMessageKey = "groupObjectClasses.display", helpMessageKey = "groupObjectClasses.help") public String[] getGroupObjectClasses() { @@ -512,7 +563,7 @@ public void setGroupObjectClasses(String... groupObjectClasses) { groupConfig.setLdapClasses(Arrays.asList(groupObjectClasses)); } - @ConfigurationProperty(order = 13, + @ConfigurationProperty(order = 14, displayMessageKey = "groupNameAttributes.display", helpMessageKey = "groupNameAttributes.help") public String[] getGroupNameAttributes() { @@ -524,7 +575,18 @@ public void setGroupNameAttributes(String... groupNameAttributes) { groupConfig.setShortNameLdapAttributes(Arrays.asList(groupNameAttributes)); } - @ConfigurationProperty(order = 14, + @ConfigurationProperty(order = 15, + displayMessageKey = "groupSearchScope.display", + helpMessageKey = "groupSearchScope.help") + public String getGroupSearchScope() { + return groupSearchScope.toString(); + } + + public void setGroupSearchScope(String groupSearchScope) { + this.groupSearchScope = SearchScope.valueOf(groupSearchScope.toLowerCase()); + } + + @ConfigurationProperty(order = 16, displayMessageKey = "groupMemberAttribute.display", helpMessageKey = "groupMemberAttribute.help") public String getGroupMemberAttribute() { @@ -535,7 +597,7 @@ public void setGroupMemberAttribute(String groupMemberAttribute) { this.groupMemberAttribute = groupMemberAttribute; } - @ConfigurationProperty(order = 15, + @ConfigurationProperty(order = 17, displayMessageKey = "maintainLdapGroupMembership.display", helpMessageKey = "maintainLdapGroupMembership.help") public boolean isMaintainLdapGroupMembership() { @@ -546,7 +608,7 @@ public void setMaintainLdapGroupMembership(boolean maintainLdapGroupMembership) this.maintainLdapGroupMembership = maintainLdapGroupMembership; } - @ConfigurationProperty(order = 16, + @ConfigurationProperty(order = 18, displayMessageKey = "maintainPosixGroupMembership.display", helpMessageKey = "maintainPosixGroupMembership.help") public boolean isMaintainPosixGroupMembership() { @@ -557,7 +619,7 @@ public void setMaintainPosixGroupMembership(boolean maintainPosixGroupMembership this.maintainPosixGroupMembership = maintainPosixGroupMembership; } - @ConfigurationProperty(order = 17, + @ConfigurationProperty(order = 19, displayMessageKey = "addPrincipalToNewGroups.display", helpMessageKey = "addPrincipalToNewGroups.help") public boolean isAddPrincipalToNewGroups() { @@ -568,7 +630,7 @@ public void setAddPrincipalToNewGroups(boolean addPrincipalToNewGroups) { this.addPrincipalToNewGroups = addPrincipalToNewGroups; } - @ConfigurationProperty(order = 18, + @ConfigurationProperty(order = 20, displayMessageKey = "anyObjectClasses.display", helpMessageKey = "anyObjectClasses.help") public String[] getAnyObjectClasses() { @@ -580,7 +642,7 @@ public void setAnyObjectClasses(String... anyObjectClasses) { allConfig.setLdapClasses(Arrays.asList(anyObjectClasses)); } - @ConfigurationProperty(order = 19, + @ConfigurationProperty(order = 21, displayMessageKey = "anyObjectNameAttributes.display", helpMessageKey = "anyObjectNameAttributes.help") public String[] getAnyObjectNameAttributes() { @@ -592,7 +654,29 @@ public void setAnyObjectNameAttributes(String... anyObjectNameAttributes) { allConfig.setShortNameLdapAttributes(Arrays.asList(anyObjectNameAttributes)); } - @ConfigurationProperty(order = 20, + @ConfigurationProperty(order = 22, + displayMessageKey = "anyObjectSearchFilter.display", + helpMessageKey = "anyObjectSearchFilter.help") + public String getAnyObjectSearchFilter() { + return anyObjectSearchFilter; + } + + public void setAnyObjectSearchFilter(String anyObjectSearchFilter) { + this.anyObjectSearchFilter = anyObjectSearchFilter; + } + + @ConfigurationProperty(order = 23, + displayMessageKey = "anyObjectSearchScope.display", + helpMessageKey = "anyObjectSearchScope.help") + public String getAnyObjectSearchScope() { + return anyObjectSearchScope.toString(); + } + + public void setAnyObjectSearchScope(String anyObjectSearchScope) { + this.anyObjectSearchScope = SearchScope.valueOf(anyObjectSearchScope.toLowerCase()); + } + + @ConfigurationProperty(order = 24, displayMessageKey = "passwordHashAlgorithm.display", helpMessageKey = "passwordHashAlgorithm.help") public String getPasswordHashAlgorithm() { @@ -603,7 +687,7 @@ public void setPasswordHashAlgorithm(String passwordHashAlgorithm) { this.passwordHashAlgorithm = passwordHashAlgorithm; } - @ConfigurationProperty(order = 21, + @ConfigurationProperty(order = 25, displayMessageKey = "respectResourcePasswordPolicyChangeAfterReset.display", helpMessageKey = "respectResourcePasswordPolicyChangeAfterReset.help") public boolean isRespectResourcePasswordPolicyChangeAfterReset() { @@ -614,7 +698,7 @@ public void setRespectResourcePasswordPolicyChangeAfterReset(boolean respectReso this.respectResourcePasswordPolicyChangeAfterReset = respectResourcePasswordPolicyChangeAfterReset; } - @ConfigurationProperty(order = 22, + @ConfigurationProperty(order = 26, displayMessageKey = "useVlvControls.display", helpMessageKey = "useVlvControls.help") public boolean isUseVlvControls() { @@ -625,7 +709,7 @@ public void setUseVlvControls(boolean useVlvControls) { this.useVlvControls = useVlvControls; } - @ConfigurationProperty(order = 23, + @ConfigurationProperty(order = 27, displayMessageKey = "vlvSortAttribute.display", helpMessageKey = "vlvSortAttribute.help") public String getVlvSortAttribute() { @@ -636,7 +720,7 @@ public void setVlvSortAttribute(String vlvSortAttribute) { this.vlvSortAttribute = vlvSortAttribute; } - @ConfigurationProperty(order = 24, + @ConfigurationProperty(order = 28, displayMessageKey = "uidAttribute.display", helpMessageKey = "uidAttribute.help") public String getUidAttribute() { @@ -647,7 +731,7 @@ public void setUidAttribute(final String uidAttribute) { this.uidAttribute = uidAttribute; } - @ConfigurationProperty(order = 25, + @ConfigurationProperty(order = 29, displayMessageKey = "gidAttribute.display", helpMessageKey = "gidAttribute.help") public String getGidAttribute() { @@ -658,7 +742,7 @@ public void setGidAttribute(final String gidAttribute) { this.gidAttribute = gidAttribute; } - @ConfigurationProperty(order = 26, + @ConfigurationProperty(order = 30, displayMessageKey = "readSchema.display", helpMessageKey = "readSchema.help") public boolean isReadSchema() { @@ -670,7 +754,7 @@ public void setReadSchema(boolean readSchema) { } // Sync properties getters and setters. - @ConfigurationProperty(order = 27, operations = { SyncOp.class }, + @ConfigurationProperty(order = 31, operations = { SyncOp.class }, displayMessageKey = "baseContextsToSynchronize.display", helpMessageKey = "baseContextsToSynchronize.help") public String[] getBaseContextsToSynchronize() { @@ -681,7 +765,7 @@ public void setBaseContextsToSynchronize(String... baseContextsToSynchronize) { this.baseContextsToSynchronize = baseContextsToSynchronize.clone(); } - @ConfigurationProperty(order = 28, operations = { SyncOp.class }, + @ConfigurationProperty(order = 32, operations = { SyncOp.class }, displayMessageKey = "objectClassesToSynchronize.display", helpMessageKey = "objectClassesToSynchronize.help") public String[] getObjectClassesToSynchronize() { @@ -692,7 +776,7 @@ public void setObjectClassesToSynchronize(String... objectClassesToSynchronize) this.objectClassesToSynchronize = objectClassesToSynchronize.clone(); } - @ConfigurationProperty(order = 29, operations = { SyncOp.class }, + @ConfigurationProperty(order = 33, operations = { SyncOp.class }, displayMessageKey = "attributesToSynchronize.display", helpMessageKey = "attributesToSynchronize.help") public String[] getAttributesToSynchronize() { @@ -703,7 +787,7 @@ public void setAttributesToSynchronize(String... attributesToSynchronize) { this.attributesToSynchronize = attributesToSynchronize.clone(); } - @ConfigurationProperty(order = 30, operations = { SyncOp.class }, + @ConfigurationProperty(order = 34, operations = { SyncOp.class }, displayMessageKey = "modifiersNamesToFilterOut.display", helpMessageKey = "modifiersNamesToFilterOut.help") public String[] getModifiersNamesToFilterOut() { @@ -714,7 +798,7 @@ public void setModifiersNamesToFilterOut(String... modifiersNamesToFilterOut) { this.modifiersNamesToFilterOut = modifiersNamesToFilterOut.clone(); } - @ConfigurationProperty(order = 31, operations = { SyncOp.class }, + @ConfigurationProperty(order = 35, operations = { SyncOp.class }, displayMessageKey = "accountSynchronizationFilter.display", helpMessageKey = "accountSynchronizationFilter.help") public String getAccountSynchronizationFilter() { @@ -725,7 +809,7 @@ public void setAccountSynchronizationFilter(String accountSynchronizationFilter) this.accountSynchronizationFilter = accountSynchronizationFilter; } - @ConfigurationProperty(order = 32, operations = { SyncOp.class }, + @ConfigurationProperty(order = 36, operations = { SyncOp.class }, displayMessageKey = "changeLogBlockSize.display", helpMessageKey = "changeLogBlockSize.help") public int getChangeLogBlockSize() { @@ -736,7 +820,7 @@ public void setChangeLogBlockSize(int changeLogBlockSize) { this.changeLogBlockSize = changeLogBlockSize; } - @ConfigurationProperty(order = 33, operations = { SyncOp.class }, + @ConfigurationProperty(order = 37, operations = { SyncOp.class }, displayMessageKey = "changeNumberAttribute.display", helpMessageKey = "changeNumberAttribute.help") public String getChangeNumberAttribute() { @@ -747,7 +831,7 @@ public void setChangeNumberAttribute(String changeNumberAttribute) { this.changeNumberAttribute = changeNumberAttribute; } - @ConfigurationProperty(order = 34, operations = { SyncOp.class }, + @ConfigurationProperty(order = 38, operations = { SyncOp.class }, displayMessageKey = "filterWithOrInsteadOfAnd.display", helpMessageKey = "filterWithOrInsteadOfAnd.help") public boolean isFilterWithOrInsteadOfAnd() { @@ -758,7 +842,7 @@ public void setFilterWithOrInsteadOfAnd(boolean filterWithOrInsteadOfAnd) { this.filterWithOrInsteadOfAnd = filterWithOrInsteadOfAnd; } - @ConfigurationProperty(order = 35, operations = { SyncOp.class }, + @ConfigurationProperty(order = 39, operations = { SyncOp.class }, displayMessageKey = "removeLogEntryObjectClassFromFilter.display", helpMessageKey = "removeLogEntryObjectClassFromFilter.help") public boolean isRemoveLogEntryObjectClassFromFilter() { @@ -769,7 +853,7 @@ public void setRemoveLogEntryObjectClassFromFilter(boolean removeLogEntryObjectC this.removeLogEntryObjectClassFromFilter = removeLogEntryObjectClassFromFilter; } - @ConfigurationProperty(order = 36, operations = { SyncOp.class }, + @ConfigurationProperty(order = 40, operations = { SyncOp.class }, displayMessageKey = "synchronizePasswords.display", helpMessageKey = "synchronizePasswords.help") public boolean isSynchronizePasswords() { @@ -780,7 +864,7 @@ public void setSynchronizePasswords(boolean synchronizePasswords) { this.synchronizePasswords = synchronizePasswords; } - @ConfigurationProperty(order = 37, operations = { SyncOp.class }, + @ConfigurationProperty(order = 41, operations = { SyncOp.class }, displayMessageKey = "passwordAttributeToSynchronize.display", helpMessageKey = "passwordAttributeToSynchronize.help") public String getPasswordAttributeToSynchronize() { @@ -791,7 +875,7 @@ public void setPasswordAttributeToSynchronize(String passwordAttributeToSynchron this.passwordAttributeToSynchronize = passwordAttributeToSynchronize; } - @ConfigurationProperty(order = 38, operations = { SyncOp.class }, confidential = true, + @ConfigurationProperty(order = 42, operations = { SyncOp.class }, confidential = true, displayMessageKey = "passwordDecryptionKey.display", helpMessageKey = "passwordDecryptionKey.help") public GuardedByteArray getPasswordDecryptionKey() { @@ -803,7 +887,7 @@ public void setPasswordDecryptionKey(GuardedByteArray passwordDecryptionKey) { copy() : null; } - @ConfigurationProperty(order = 39, operations = { SyncOp.class }, confidential = true, + @ConfigurationProperty(order = 43, operations = { SyncOp.class }, confidential = true, displayMessageKey = "passwordDecryptionInitializationVector.display", helpMessageKey = "passwordDecryptionInitializationVector.help") public GuardedByteArray getPasswordDecryptionInitializationVector() { @@ -816,7 +900,7 @@ public void setPasswordDecryptionInitializationVector(GuardedByteArray passwordD copy() : null; } - @ConfigurationProperty(order = 40, + @ConfigurationProperty(order = 44, displayMessageKey = "statusManagementClass.display", helpMessageKey = "statusManagementClass.help") public String getStatusManagementClass() { @@ -827,7 +911,7 @@ public void setStatusManagementClass(String statusManagementClass) { this.statusManagementClass = statusManagementClass; } - @ConfigurationProperty(order = 41, + @ConfigurationProperty(order = 45, displayMessageKey = "retrievePasswordsWithSearch.display", helpMessageKey = "retrievePasswordsWithSearch.help") public boolean getRetrievePasswordsWithSearch() { @@ -838,7 +922,7 @@ public void setRetrievePasswordsWithSearch(boolean retrievePasswordsWithSearch) this.retrievePasswordsWithSearch = retrievePasswordsWithSearch; } - @ConfigurationProperty(order = 42, + @ConfigurationProperty(order = 46, displayMessageKey = "dnAttribute.display", helpMessageKey = "dnAttribute.help") public String getDnAttribute() { @@ -849,7 +933,7 @@ public void setDnAttribute(String dnAttribute) { this.dnAttribute = dnAttribute; } - @ConfigurationProperty(order = 43, + @ConfigurationProperty(order = 47, displayMessageKey = "groupSearchFilter.display", helpMessageKey = "groupSearchFilter.help") public String getGroupSearchFilter() { @@ -860,7 +944,7 @@ public void setGroupSearchFilter(String groupSearchFilter) { this.groupSearchFilter = groupSearchFilter; } - @ConfigurationProperty(order = 44, + @ConfigurationProperty(order = 48, displayMessageKey = "readTimeout.display", helpMessageKey = "readTimeout.help") public long getReadTimeout() { @@ -871,7 +955,7 @@ public void setReadTimeout(long readTimeout) { this.readTimeout = readTimeout; } - @ConfigurationProperty(order = 45, + @ConfigurationProperty(order = 49, displayMessageKey = "connectTimeout.display", helpMessageKey = "connectTimeout.help") public long getConnectTimeout() { @@ -1009,4 +1093,10 @@ public boolean equals(Object obj) { } return false; } + + public enum SearchScope { + object, + onelevel, + subtree; + } } diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java index 0ff685d..d6d1831 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java @@ -210,6 +210,8 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { searchFilter = conn.getConfiguration().getAccountSearchFilter(); } else if (oclass.equals(ObjectClass.GROUP)) { searchFilter = conn.getConfiguration().getGroupSearchFilter(); + } else { + searchFilter = conn.getConfiguration().getAnyObjectSearchFilter(); } String nativeFilter = filter == null ? null : filter.getNativeFilter(); return new LdapInternalSearch(conn, @@ -451,13 +453,24 @@ private void removeNonReadableAttributes(final Set attributes) { private int getLdapSearchScope() { String scope = options.getScope(); - if (OperationOptions.SCOPE_OBJECT.equals(scope)) { + if (scope == null) { + if (oclass.is(ObjectClass.ACCOUNT_NAME)) { + scope = conn.getConfiguration().getUserSearchScope(); + } else if (oclass.is(ObjectClass.GROUP_NAME)) { + scope = conn.getConfiguration().getGroupSearchScope(); + } else { + scope = conn.getConfiguration().getAnyObjectSearchScope(); + } + } + + switch (scope) { + case OperationOptions.SCOPE_OBJECT: return SearchControls.OBJECT_SCOPE; - } else if (OperationOptions.SCOPE_ONE_LEVEL.equals(scope)) { + case OperationOptions.SCOPE_ONE_LEVEL: return SearchControls.ONELEVEL_SCOPE; - } else if (OperationOptions.SCOPE_SUBTREE.equals(scope) || scope == null) { + case OperationOptions.SCOPE_SUBTREE: return SearchControls.SUBTREE_SCOPE; - } else { + default: throw new IllegalArgumentException("Invalid search scope " + scope); } } diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties index 7ba66b7..6d6d5f0 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages.properties @@ -99,6 +99,14 @@ anyObjectClasses.display=Any-object Object Classes anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. anyObjectNameAttributes.display=Any-object Name Attributes anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' dnAttribute.display=Entry DN attribute name dnAttribute.help=Entry DN attribute name (default: entryDN) @@ -143,6 +151,12 @@ changeLogBlockSize.legalValue=The synchronization block size should be greather passwordAttributeToSynchronize.notBlank=The password attribute to synchronize cannot be blank decryptionKey.notBlank=The decryption key cannot be blank decryptionInitializationVector.notBlank=The decryption initialization vector cannot be blank +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=Entry "{0}" not found readingPasswordsNotSupported=Returning passwords from a search operation is not supported diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties index 2af2a3f..90e8c3e 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_de.properties @@ -111,6 +111,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=Das Gruppenmitgliedattribut darf nicht leer sein vlvSortAttribute.notBlank=Das VLV-Sortierattribut darf nicht leer sein uidAttribute.notBlank=Das zur UID zuzuordnende Attribut darf nicht leer sein @@ -126,6 +134,12 @@ changeLogBlockSize.legalValue=Die Gr\u00f6\u00dfe des Synchronisationsblocks mus passwordAttributeToSynchronize.notBlank=Das zu synchronisierende Passwortattribut darf nicht leer sein decryptionKey.notBlank=Der Entschl\u00fcsselungsschl\u00fcssel darf nicht leer sein decryptionInitializationVector.notBlank=Der Initialisierungsvektor zur Entschl\u00fcsselung darf nicht leer sein +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=Eintrag "{0}" nicht gefunden readingPasswordsNotSupported=Die Wiedergabe von Passw\u00f6rtern \u00fcber einen Suchvorgang wird nicht unterst\u00fctzt diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties index 6b64602..743107e 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_es.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=El atributo de miembro de grupo no puede quedar en blanco vlvSortAttribute.notBlank=El atributo de ordenaci\u00f3n de VLV no puede quedar en blanco uidAttribute.notBlank=El atributo de asignaci\u00f3n a Uid no puede quedar en blanco @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=El tama\u00f1o de bloque de sincronizaci\u00f3n de passwordAttributeToSynchronize.notBlank=El atributo de contrase\u00f1a para sincronizar no puede quedar en blanco decryptionKey.notBlank=La clave de descifrado no puede quedar en blanco decryptionInitializationVector.notBlank=El vector de inicializaci\u00f3n de descifrado no puede quedar en blanco +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=Entrada "{0}" no encontrada readingPasswordsNotSupported=Una operaci\u00f3n de b\u00fasqueda no puede devolver contrase\u00f1as diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties index ec12084..a1ccfba 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_fr.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=L\u2019attribut de membre de groupe doit \u00eatre sp\u00e9cifi\u00e9. vlvSortAttribute.notBlank=L\u2019attribut de tri VLV doit \u00eatre sp\u00e9cifi\u00e9. uidAttribute.notBlank=L\u2019attribut \u00e0 mapper \u00e0 l\u2019UID doit \u00eatre sp\u00e9cifi\u00e9. @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=La taille de bloc de synchronisation doit \u00eatr passwordAttributeToSynchronize.notBlank=L\u2019attribut de mot de passe \u00e0 synchroniser doit \u00eatre sp\u00e9cifi\u00e9. decryptionKey.notBlank=La cl\u00e9 de d\u00e9chiffrement doit \u00eatre sp\u00e9cifi\u00e9e. decryptionInitializationVector.notBlank=Le vecteur d\u2019initialisation de d\u00e9chiffrement doit \u00eatre sp\u00e9cifi\u00e9. +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=L\u2019entr\u00e9e \u2019{0}\u2019 est introuvable. readingPasswordsNotSupported=Le renvoi de mots de passe \u00e0 partir d\u2019une op\u00e9ration de recherche n\u2019est pas pris en charge. diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties index 7af84d7..531f548 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_it.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=L\u2019attributo del gruppo non pu\u00f2 essere vuoto vlvSortAttribute.notBlank=L\u2019attributo di ordinamento VLV non pu\u00f2 essere vuoto uidAttribute.notBlank=L\u2019attributo da assegnare all\u2019Uid non pu\u00f2 essere vuoto @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=La dimensione del blocco di sincronizzazione deve passwordAttributeToSynchronize.notBlank=L\u2019attributo password da sincronizzare non pu\u00f2 essere vuoto decryptionKey.notBlank=La chiave di decrittazione non pu\u00f2 essere vuota decryptionInitializationVector.notBlank=Il vettore di inizializzazione di decrittazione non pu\u00f2 essere vuoto +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=Voce "{0}" non trovata readingPasswordsNotSupported=Non \u00e8 possibile restituire le password in un\u2019operazione di ricerca diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties index 76c78fc..8d69a09 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ja.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=\u30b0\u30eb\u30fc\u30d7\u30e1\u30f3\u30d0\u30fc\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 vlvSortAttribute.notBlank=VLV \u4e26\u3079\u66ff\u3048\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 uidAttribute.notBlank=UID \u306b\u30de\u30c3\u30d7\u3059\u308b\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=\u540c\u671f\u30d6\u30ed\u30c3\u30af\u30b5\u30a4\u passwordAttributeToSynchronize.notBlank=\u540c\u671f\u3059\u308b\u30d1\u30b9\u30ef\u30fc\u30c9\u5c5e\u6027\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 decryptionKey.notBlank=\u5fa9\u53f7\u5316\u30ad\u30fc\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 decryptionInitializationVector.notBlank=\u5fa9\u53f7\u5316\u306e\u521d\u671f\u5316\u30d9\u30af\u30c8\u30eb\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093 +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=\u30a8\u30f3\u30c8\u30ea "{0}" \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 readingPasswordsNotSupported=\u691c\u7d22\u51e6\u7406\u304b\u3089\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8fd4\u3059\u64cd\u4f5c\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u307e\u305b\u3093 diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties index c81e5b2..58e42ed 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_ko.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=\uadf8\ub8f9 \uad6c\uc131\uc6d0 \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. vlvSortAttribute.notBlank=VLV \uc815\ub82c \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. uidAttribute.notBlank=UID\uc5d0 \ub9e4\ud551\ud560 \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=\ub3d9\uae30\ud654 \ube14\ub85d \ud06c\uae30\ub294 passwordAttributeToSynchronize.notBlank=\ub3d9\uae30\ud654\ud560 \ube44\ubc00\ubc88\ud638 \uc18d\uc131\uc740 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. decryptionKey.notBlank=\ud574\ub3c5 \ud0a4\ub294 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. decryptionInitializationVector.notBlank=\ud574\ub3c5 \ucd08\uae30\ud654 \ubca1\ud130\ub294 \ube44\uc6cc \ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound="{0}" \ud56d\ubaa9\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. readingPasswordsNotSupported=\uac80\uc0c9 \uc791\uc5c5\uc5d0\uc11c \ube44\ubc00\ubc88\ud638\ub294 \ubc18\ud658\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties index eaa167e..52e51c8 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_pt.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=O atributo de membro de grupo n\u00e3o pode ficar em branco vlvSortAttribute.notBlank=O atributo de classifica\u00e7\u00e3o VLV n\u00e3o pode ficar em branco uidAttribute.notBlank=O atributo de mapeamento para Uid n\u00e3o pode ficar em branco @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=O tamanho do bloco de sincroniza\u00e7\u00e3o deve passwordAttributeToSynchronize.notBlank=O atributo de senha para sincroniza\u00e7\u00e3o n\u00e3o pode ficar em branco decryptionKey.notBlank=A chave de descriptografia n\u00e3o pode ficar em branco decryptionInitializationVector.notBlank=O vetor de inicializa\u00e7\u00e3o da descriptografia n\u00e3o pode ficar em branco +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=A entrada "{0}" n\u00e3o foi encontrada readingPasswordsNotSupported=N\u00e3o existe suporte para o retorno de senhas de uma opera\u00e7\u00e3o de pesquisa diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties index 325762a..d24bb36 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh.properties @@ -108,6 +108,14 @@ anyObjectClasses.notEmpty=The list of any-object object classes cannot be empty anyObjectClasses.noBlankValues=The list of any-object object classes cannot contain blank values anyObjectNameAttributes.notEmpty=The list of any-object name attributes cannot be empty anyObjectNameAttributes.noBlankValues=The list of any-object name attributes cannot contain blank values +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' groupMemberAttribute.notBlank=\u7ec4\u6210\u5458\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a vlvSortAttribute.notBlank=VLV \u6392\u5e8f\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a uidAttribute.notBlank=\u8981\u6620\u5c04\u5230 UID \u7684\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a @@ -123,6 +131,12 @@ changeLogBlockSize.legalValue=\u540c\u6b65\u5757\u5927\u5c0f\u5e94\u5927\u4e8e 0 passwordAttributeToSynchronize.notBlank=\u8981\u540c\u6b65\u7684\u5bc6\u7801\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a decryptionKey.notBlank=\u89e3\u5bc6\u5bc6\u94a5\u4e0d\u80fd\u4e3a\u7a7a decryptionInitializationVector.notBlank=\u89e3\u5bc6\u521d\u59cb\u5316\u5411\u91cf\u4e0d\u80fd\u4e3a\u7a7a +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=\u627e\u4e0d\u5230\u6761\u76ee\u201c{0}\u201d readingPasswordsNotSupported=\u4e0d\u652f\u6301\u4ece\u641c\u7d22\u64cd\u4f5c\u8fd4\u56de\u5bc6\u7801 diff --git a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties index 989e3b1..e951738 100644 --- a/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties +++ b/src/main/resources/net/tirasa/connid/bundles/ldap/Messages_zh_TW.properties @@ -80,6 +80,14 @@ anyObjectClasses.display=Any-object Object Classes anyObjectClasses.help=The object class or classes that will be used when creating new any-object objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate multiple object classes. Some classes may require that you specify all object classes in the class hierarchy. anyObjectNameAttributes.display=Any-object Name Attributes anyObjectNameAttributes.help=Attribute or attributes which holds the any-object''s name. +userSearchScope.display=User search scope +userSearchScope.help=The scope to utilise when searching for users. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +groupSearchScope.display=Group search scope +groupSearchScope.help=The scope to utilise when searching for groups. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' +anyObjectSearchFilter.display=LDAP filter for retrieving Any Objects +anyObjectSearchFilter.help=An optional LDAP filter to control which any objects are returned from the LDAP resource. If no filter is specified, only any objects that include all specified object classes are returned. +anyObjectSearchScope.display=Any Object search scope +anyObjectSearchScope.help=The scope to utilise when searching for any objects. Must be one of 'object', 'onelevel', 'subtree'. Default is 'subtree' changeNumberAttribute.help=\u8b8a\u66f4\u8a18\u9304\u9805\u76ee\u4e2d\u4e4b\u8b8a\u66f4\u6578\u5b57\u5c6c\u6027\u7684\u540d\u7a31\u3002 filterWithOrInsteadOfAnd.display=\u4f7f\u7528 OR \u800c\u4e0d\u4f7f\u7528 AND \u7be9\u9078 filterWithOrInsteadOfAnd.help=\u4e00\u822c\u5728\u64f7\u53d6\u8b8a\u66f4\u8a18\u9304\u9805\u76ee\u6642\uff0c\u6703\u4f7f\u7528 AND \u7be9\u9078\u5668\u64f7\u53d6\u4e00\u6bb5\u671f\u9593\u5167\u7684\u8b8a\u66f4\u9805\u76ee\u3002\u82e5\u8a2d\u5b9a\u6b64\u7279\u6027\uff0c\u5247\u6703\u6539\u7528 OR \u7be9\u9078\u5668\u642d\u914d\u6240\u9700\u7684\u8b8a\u66f4\u6578\u5b57\u3002 @@ -130,6 +138,12 @@ changeLogBlockSize.legalValue=\u540c\u6b65\u5340\u6bb5\u5927\u5c0f\u61c9\u5927\u passwordAttributeToSynchronize.notBlank=\u8981\u540c\u6b65\u7684\u5bc6\u78bc\u5c6c\u6027\u4e0d\u53ef\u70ba\u7a7a\u767d decryptionKey.notBlank=\u89e3\u5bc6\u91d1\u9470\u4e0d\u53ef\u70ba\u7a7a\u767d decryptionInitializationVector.notBlank=\u89e3\u5bc6\u521d\u59cb\u5316\u5411\u91cf\u4e0d\u53ef\u70ba\u7a7a\u767d +userSearchScope.notBlank=The user search scope cannot be blank +userSearchScope.invalidScope=The user search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +groupSearchScope.notBlank=The group search scope cannot be blank +groupSearchScope.invalidScope=The group search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' +anyObjectSearchScope.notBlank=The any object search scope cannot be blank +anyObjectSearchScope.invalidScope=The any object search scope was invalid, it must be one of 'object', 'onelevel' or 'subtree' entryNotFound=\u627e\u4e0d\u5230\u9805\u76ee\u300c{0}\u300d readingPasswordsNotSupported=\u4e0d\u652f\u63f4\u5f9e\u641c\u5c0b\u4f5c\u696d\u50b3\u56de\u5bc6\u78bc diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/AdapterCompatibilityTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/AdapterCompatibilityTests.java index 15e697c..aaa47a4 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/AdapterCompatibilityTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/AdapterCompatibilityTests.java @@ -134,7 +134,7 @@ public void createGroupOfUniqueNamesWithoutMembers() { ObjectClass oclass = new ObjectClass("groupOfUniqueNames"); Set attributes = new HashSet<>(); - Name name = new Name("cn=Another Group," + ACME_DN); + Name name = new Name("cn=Another Group," + ACME_GROUPS_DN); attributes.add(name); attributes.add(AttributeBuilder.build("cn", "Another Group")); // If "uniqueMember" is sent to the server as an empty attribute, the server complains. diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java index 65e50b1..d13bf58 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java @@ -23,6 +23,7 @@ */ package net.tirasa.connid.bundles.ldap; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -34,6 +35,7 @@ import org.identityconnectors.common.CollectionUtil; import org.identityconnectors.common.security.GuardedByteArray; import org.identityconnectors.framework.common.exceptions.ConfigurationException; +import org.identityconnectors.framework.common.objects.OperationOptions; import org.identityconnectors.test.common.TestHelpers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -349,6 +351,76 @@ public void defaultValues() { assertEquals(0, config.getConnectTimeout()); assertEquals(CollectionUtil.newList("top"), Arrays.asList(config.getAnyObjectClasses())); assertEquals(CollectionUtil.newList("entryUUID"), Arrays.asList(config.getAnyObjectNameAttributes())); + assertEquals(OperationOptions.SCOPE_SUBTREE, config.getUserSearchScope()); + assertEquals(OperationOptions.SCOPE_SUBTREE, config.getGroupSearchScope()); + assertEquals(OperationOptions.SCOPE_SUBTREE, config.getAnyObjectSearchScope()); + assertNull(config.getAnyObjectSearchFilter()); + } + + @Test + public void userSearchScopeNotNull() { + assertThrows(NullPointerException.class, () -> config.setUserSearchScope((String) null)); + } + + @Test + public void userSearchScopeNotBlank() { + assertThrows(IllegalArgumentException.class, () -> config.setUserSearchScope(" ")); + } + + @Test + public void userSearchScopeInvalid() { + assertThrows(IllegalArgumentException.class, () -> config.setUserSearchScope("abc")); + } + + @Test + public void userSearchScopeValid() { + assertDoesNotThrow(() -> config.setUserSearchScope("object")); + assertDoesNotThrow(() -> config.setUserSearchScope("onelevel")); + assertDoesNotThrow(() -> config.setUserSearchScope("subtree")); + } + + @Test + public void groupSearchScopeNotNull() { + assertThrows(NullPointerException.class, () -> config.setGroupSearchScope((String) null)); + } + + @Test + public void groupSearchScopeNotBlank() { + assertThrows(IllegalArgumentException.class, () -> config.setGroupSearchScope(" ")); + } + + @Test + public void groupSearchScopeInvalid() { + assertThrows(IllegalArgumentException.class, () -> config.setGroupSearchScope("abc")); + } + + @Test + public void groupSearchScopeValid() { + assertDoesNotThrow(() -> config.setGroupSearchScope("object")); + assertDoesNotThrow(() -> config.setGroupSearchScope("onelevel")); + assertDoesNotThrow(() -> config.setGroupSearchScope("subtree")); + } + + @Test + public void anyObjectSearchScopeNotNull() { + assertThrows(NullPointerException.class, () -> config.setAnyObjectSearchScope((String) null)); + } + + @Test + public void anyObjectSearchScopeNotBlank() { + assertThrows(IllegalArgumentException.class, () -> config.setAnyObjectSearchScope(" ")); + } + + @Test + public void anyObjectSearchScopeInvalid() { + assertThrows(IllegalArgumentException.class, () -> config.setAnyObjectSearchScope("abc")); + } + + @Test + public void anyObjectSearchScopeValid() { + assertDoesNotThrow(() -> config.setAnyObjectSearchScope("object")); + assertDoesNotThrow(() -> config.setAnyObjectSearchScope("onelevel")); + assertDoesNotThrow(() -> config.setAnyObjectSearchScope("subtree")); } private static void assertCanValidate(LdapConfiguration config) { diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java index f7e8281..388d8c2 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java @@ -81,6 +81,10 @@ public abstract class LdapConnectorTestBase { public static final String ACME_USERS_DN = "ou=Users,o=Acme,dc=example,dc=com"; + public static final String ACME_GROUPS_DN = "ou=Groups,o=Acme,dc=example,dc=com"; + + public static final String ACME_DEVICES_DN = "ou=Devices,o=Acme,dc=example,dc=com"; + public static final String BUGS_BUNNY_DN = "uid=bugs.bunny,ou=Users,o=Acme,dc=example,dc=com"; public static final String RENAME_ONE_TEST_DN = "uid=rename.one,ou=Users,o=Acme,dc=example,dc=com"; @@ -105,25 +109,29 @@ public abstract class LdapConnectorTestBase { public static final String EXPIRED_UID = "expired"; - public static final String BUGS_AND_FRIENDS_DN = "cn=Bugs and Friends,o=Acme,dc=example,dc=com"; + public static final String BUGS_AND_FRIENDS_DN = "cn=Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String EXTERNAL_PEERS_DN = "cn=External Peers,o=Acme,dc=example,dc=com"; + public static final String EXTERNAL_PEERS_DN = "cn=External Peers,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String UNIQUE_BUGS_AND_FRIENDS_DN = "cn=Unique Bugs and Friends,o=Acme,dc=example,dc=com"; + public static final String UNIQUE_BUGS_AND_FRIENDS_DN = "cn=Unique Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; public static final String UNIQUE_BUGS_AND_FRIENDS_CN = "Unique Bugs and Friends"; - public static final String UNIQUE_EXTERNAL_PEERS_DN = "cn=Unique External Peers,o=Acme,dc=example,dc=com"; + public static final String UNIQUE_EXTERNAL_PEERS_DN = "cn=Unique External Peers,ou=Groups,o=Acme,dc=example,dc=com"; + + public static final String UNIQUE_EMPTY_GROUP_DN = "cn=Unique Empty Group,ou=Groups,o=Acme,dc=example,dc=com"; + + public static final String POSIX_BUGS_AND_FRIENDS_DN = "cn=POSIX Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String UNIQUE_EMPTY_GROUP_DN = "cn=Unique Empty Group,o=Acme,dc=example,dc=com"; + public static final String POSIX_EXTERNAL_PEERS_DN = "cn=POSIX External Peers,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String POSIX_BUGS_AND_FRIENDS_DN = "cn=POSIX Bugs and Friends,o=Acme,dc=example,dc=com"; + public static final String POSIX_EMPTY_GROUP_DN = "cn=POSIX Empty Group,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String POSIX_EXTERNAL_PEERS_DN = "cn=POSIX External Peers,o=Acme,dc=example,dc=com"; + public static final String POSIX_BUGS_BUNNY_GROUP = "cn=POSIX Bugs Bunny Group,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String POSIX_EMPTY_GROUP_DN = "cn=POSIX Empty Group,o=Acme,dc=example,dc=com"; + public static final String CARROT_LAPTOP_DN = "cn=Carrot Laptop,ou=Devices,o=Acme,dc=example,dc=com"; - public static final String POSIX_BUGS_BUNNY_GROUP = "cn=POSIX Bugs Bunny Group,o=Acme,dc=example,dc=com"; + public static final String CARROT_LAPTOP_CN = "Carrot Laptop"; public static final String SMALL_COMPANY_DN = "o=Small Company,dc=example,dc=com"; diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java index 41b74b4..818ebea 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java @@ -332,6 +332,126 @@ public void scope() { assertFalse(objects.isEmpty()); } + @Test + public void configurableUserScope() { + LdapConfiguration configuration = newConfiguration(); + configuration.setUserSearchScope("object"); + ConnectorFacade facade = newFacade(configuration); + + // Find an organization to pass in OP_CONTAINER. + ObjectClass oclass = new ObjectClass("organization"); + ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); + + // Prepare options + OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); + optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); + optionsBuilder.setPageSize(100); + OperationOptions options = optionsBuilder.build(); + + // We can get bugs bunny with an 'object' search by DN + ConnectorObject bugsBunny = searchByAttribute(facade, ObjectClass.ACCOUNT, new Name(BUGS_BUNNY_DN)); + assertNotNull(bugsBunny); + + // Reconfigure for 'onelevel' search + configuration.setUserSearchScope("onelevel"); + configuration.setAccountSearchFilter("(uid=" + BUGS_BUNNY_UID + ")"); + facade = newFacade(configuration); + + // Bugs Bunny doesn't exist directly under the organisation.. + List objects = TestHelpers.searchToList( + facade, ObjectClass.ACCOUNT, null, options); + assertTrue(objects.isEmpty()); + + // Reconfigure for 'subtree' search + configuration.setUserSearchScope("subtree"); + facade = newFacade(configuration); + + // ... but does in the organisation subtree + objects = TestHelpers.searchToList(facade, ObjectClass.ACCOUNT, null, options); + assertFalse(objects.isEmpty()); + } + + @Test + public void configurableGroupScope() { + LdapConfiguration configuration = newConfiguration(); + configuration.setGroupSearchScope("object"); + ConnectorFacade facade = newFacade(configuration); + + // Find an organization to pass in OP_CONTAINER. + ObjectClass oclass = new ObjectClass("organization"); + ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); + + // Prepare options + OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); + optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); + optionsBuilder.setPageSize(100); + OperationOptions options = optionsBuilder.build(); + + // We can get 'unique bugs and friends' with an 'object' search by DN + ConnectorObject uniqueBugsAndFriends = searchByAttribute(facade, ObjectClass.GROUP, new Name(UNIQUE_BUGS_AND_FRIENDS_DN)); + assertNotNull(uniqueBugsAndFriends); + + // Reconfigure for 'onelevel' search + configuration.setGroupSearchScope("onelevel"); + configuration.setGroupSearchFilter("(cn=" + UNIQUE_BUGS_AND_FRIENDS_CN + ")"); + facade = newFacade(configuration); + + // Bugs Bunny doesn't exist directly under the organisation.. + List objects = TestHelpers.searchToList( + facade, ObjectClass.GROUP, null, options); + assertTrue(objects.isEmpty()); + + // Reconfigure for 'subtree' search + configuration.setGroupSearchScope("subtree"); + facade = newFacade(configuration); + + // ... but does in the organisation subtree + objects = TestHelpers.searchToList(facade, ObjectClass.GROUP, null, options); + assertFalse(objects.isEmpty()); + } + + @Test + public void configurableAnyObjectScope() { + LdapConfiguration configuration = newConfiguration(); + configuration.setAnyObjectSearchScope("object"); + ConnectorFacade facade = newFacade(configuration); + + // Find an organization to pass in OP_CONTAINER. + ObjectClass oclass = new ObjectClass("organization"); + ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); + + // Prepare options + OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); + optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); + optionsBuilder.setPageSize(100); + OperationOptions options = optionsBuilder.build(); + + // Set up for 'device' search + ObjectClass deviceObjectClass = new ObjectClass("device"); + + // We can get the 'carrot laptop' device with an 'object' search by DN + ConnectorObject carrotLaptop = searchByAttribute(facade, deviceObjectClass, new Name(CARROT_LAPTOP_DN)); + assertNotNull(carrotLaptop); + + // Reconfigure for 'onelevel' search + configuration.setAnyObjectSearchScope("onelevel"); + configuration.setAnyObjectSearchFilter("(cn=" + CARROT_LAPTOP_CN + ")"); + facade = newFacade(configuration); + + // 'carrot laptop'' doesn't exist directly under the organisation.. + List objects = TestHelpers.searchToList( + facade, deviceObjectClass, null, options); + assertTrue(objects.isEmpty()); + + // Reconfigure for 'subtree' search + configuration.setAnyObjectSearchScope("subtree"); + facade = newFacade(configuration); + + // ... but does in the organisation subtree + objects = TestHelpers.searchToList(facade, deviceObjectClass, null, options); + assertFalse(objects.isEmpty()); + } + @Test public void accountSearchFilter() { ConnectorFacade facade = newFacade(); @@ -421,6 +541,53 @@ public void missingParenthesesAddedToGroupSearchFilter() { assertNotNull(searchByAttribute(facade, ObjectClass.GROUP, new Name(UNIQUE_BUGS_AND_FRIENDS_DN))); } + @Test + public void anyObjectSearchFilter() { + ConnectorFacade facade = newFacade(); + // Find an organization to pass in OP_CONTAINER. + ObjectClass oclass = new ObjectClass("organization"); + ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); + + // First just check that there really are some anyObjects (devices in this case). + ObjectClass deviceObjectClass = new ObjectClass("device"); + + OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); + optionsBuilder.setScope(OperationOptions.SCOPE_SUBTREE); + optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); + List objects = TestHelpers.searchToList( + facade, deviceObjectClass, null, optionsBuilder.build()); + assertNotNull(getObjectByName(objects, CARROT_LAPTOP_DN)); + + // Test the anyObject search filter + LdapConfiguration config = newConfiguration(); + config.setAnyObjectSearchFilter("(cn=" + CARROT_LAPTOP_CN + ")"); + facade = newFacade(config); + objects = TestHelpers.searchToList(facade, deviceObjectClass, null, optionsBuilder.build()); + assertEquals(1, objects.size()); + assertNotNull(getObjectByName(objects, CARROT_LAPTOP_DN)); + } + + @Test + public void anyObjectSearchFilterOnlyAppliesToAnyObjects() { + LdapConfiguration config = newConfiguration(); + config.setAnyObjectSearchFilter("(cn=foobarbaz)"); + ConnectorFacade facade = newFacade(config); + ConnectorObject bugsBunny = searchByAttribute(facade, ObjectClass.ACCOUNT, new Name(BUGS_BUNNY_DN)); + + // If the (cn=foobarbaz) filter above applied, the search would return nothing. + assertNotNull(bugsBunny); + } + + @Test + public void missingParenthesesAddedToAnyObjectSearchFilter() { + LdapConfiguration config = newConfiguration(); + config.setAnyObjectSearchFilter("cn=" + CARROT_LAPTOP_CN); // No parentheses enclosing the filter. + ConnectorFacade facade = newFacade(config); + + // If parentheses were not added, the search would fail. + assertNotNull(searchByAttribute(facade, new ObjectClass("device"), new Name(CARROT_LAPTOP_DN))); + } + @Test public void multipleBaseDNs() { ConnectorFacade facade = newFacade(); diff --git a/src/test/resources/opendj/data.ldif b/src/test/resources/opendj/data.ldif index 8c86c36..6188b7a 100644 --- a/src/test/resources/opendj/data.ldif +++ b/src/test/resources/opendj/data.ldif @@ -44,6 +44,16 @@ objectClass: top objectClass: organizationalUnit ou: Users +dn: ou=Groups,o=Acme,dc=example,dc=com +objectClass: top +objectClass: organizationalUnit +ou: Groups + +dn: ou=Devices,o=Acme,dc=example,dc=com +objectClass: top +objectClass: organizationalUnit +ou: Devices + dn: uid=bugs.bunny,ou=Users,o=Acme,dc=example,dc=com objectClass: top objectClass: person @@ -86,7 +96,7 @@ ds-pwp-password-policy-dn: cn=Quickly Expiring Password Policy,cn=Password Polic # Non-unique groups. -dn: cn=Bugs and Friends,o=Acme,dc=example,dc=com +dn: cn=Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: groupOfNames cn: Bugs and Friends @@ -94,7 +104,7 @@ member: uid=bugs.bunny,ou=Users,o=Acme,dc=example,dc=com member: uid=elmer.fudd,ou=Users,o=Acme,dc=example,dc=com member: uid=sylvester,ou=Users,o=Acme,dc=example,dc=com -dn: cn=External Peers,o=Acme,dc=example,dc=com +dn: cn=External Peers,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: groupOfNames cn: External Peers @@ -103,7 +113,7 @@ member: uid=sylvester,ou=Users,o=Acme,dc=example,dc=com # Unique groups. -dn: cn=Unique Bugs and Friends,o=Acme,dc=example,dc=com +dn: cn=Unique Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: groupOfUniqueNames cn: Unique Bugs and Friends @@ -111,21 +121,21 @@ uniqueMember: uid=bugs.bunny,ou=Users,o=Acme,dc=example,dc=com uniqueMember: uid=elmer.fudd,ou=Users,o=Acme,dc=example,dc=com uniqueMember: uid=sylvester,ou=Users,o=Acme,dc=example,dc=com -dn: cn=Unique External Peers,o=Acme,dc=example,dc=com +dn: cn=Unique External Peers,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: groupOfUniqueNames cn: Unique External Peers uniqueMember: uid=single.account,o=Small Company,dc=example,dc=com uniqueMember: uid=sylvester,ou=Users,o=Acme,dc=example,dc=com -dn: cn=Unique Empty Group,o=Acme,dc=example,dc=com +dn: cn=Unique Empty Group,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: groupOfUniqueNames cn: Unique Empty Group # POSIX groups. -dn: cn=POSIX Bugs and Friends,o=Acme,dc=example,dc=com +dn: cn=POSIX Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: namedObject objectClass: posixGroup @@ -135,7 +145,7 @@ memberUid: bugs.bunny memberUid: elmer.fudd memberUid: sylvester -dn: cn=POSIX External Peers,o=Acme,dc=example,dc=com +dn: cn=POSIX External Peers,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: namedObject objectClass: posixGroup @@ -145,14 +155,14 @@ memberUid: single.account memberUid: owner memberUid: sylvester -dn: cn=POSIX Empty Group,o=Acme,dc=example,dc=com +dn: cn=POSIX Empty Group,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: namedObject objectClass: posixGroup cn: POSIX Empty Group gidNumber: 3 -dn: cn=POSIX Bugs Bunny Group,o=Acme,dc=example,dc=com +dn: cn=POSIX Bugs Bunny Group,ou=Groups,o=Acme,dc=example,dc=com objectClass: top objectClass: namedObject objectClass: posixGroup @@ -160,6 +170,12 @@ cn: POSIX Bugs Bunny Group gidNumber: 4 memberUid: bbunny +dn: cn=Carrot Laptop,ou=Devices,o=Acme,dc=example,dc=com +objectclass: top +objectClass: device +cn: Carrot Laptop +serialNumber: carrot + # A small company with an account and a person. dn: o=Small Company,dc=example,dc=com From 1a9b182e8a2467298f2664a55c1a57d5855efbcf Mon Sep 17 00:00:00 2001 From: Sylinsic <38617929+Sylinsic@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:50:37 +0000 Subject: [PATCH 4/5] Override custom anyObject configs for scope and filters for baseDNs --- .../bundles/ldap/search/LdapSearch.java | 31 ++++++++++++------- .../bundles/ldap/search/LdapSearches.java | 18 ++++++++--- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java index d6d1831..4c15fd6 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java @@ -66,6 +66,8 @@ * @author Andrei Badea */ public class LdapSearch { + // An Operation Option specific for usage with LDAP + public static final String OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG = "IGNORE_CUSTOM_ANY_OBJECT_CONFIG"; private static final Log LOG = Log.getLog(LdapSearch.class); @@ -167,7 +169,7 @@ public boolean handle(final String baseDN, final SearchResult result) throws Nam return results[0]; } - + private LdapInternalSearch getInternalSearch(final Set attrsToGet) { // This is a bit tricky. If the LdapFilter has an entry DN, // we only need to look at that entry and check whether it matches @@ -182,12 +184,17 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { LdapSearchStrategy strategy; List dns; int searchScope; + boolean ignoreUserAnyObjectConfig = false; String filterEntryDN = filter == null ? null : filter.getEntryDN(); if (filterEntryDN == null) { strategy = getSearchStrategy(); dns = getBaseDNs(); - searchScope = getLdapSearchScope(); + if (options.getOptions().containsKey(OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG)) + { + ignoreUserAnyObjectConfig = (boolean) options.getOptions().get(OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG); + } + searchScope = getLdapSearchScope(ignoreUserAnyObjectConfig); } else { // Would be good to check that filterEntryDN is under the configured base contexts. // However, the adapter is likely to pass entries outside the base contexts, @@ -202,7 +209,7 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { controls.setReturningAttributes(ldapAttrsToGet.toArray(new String[ldapAttrsToGet.size()])); - controls.setSearchScope(searchScope); + controls.setSearchScope(searchScope); String optionsFilter = LdapConstants.getSearchFilter(options); String searchFilter = null; @@ -210,7 +217,7 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { searchFilter = conn.getConfiguration().getAccountSearchFilter(); } else if (oclass.equals(ObjectClass.GROUP)) { searchFilter = conn.getConfiguration().getGroupSearchFilter(); - } else { + } else if (!ignoreUserAnyObjectConfig){ searchFilter = conn.getConfiguration().getAnyObjectSearchFilter(); } String nativeFilter = filter == null ? null : filter.getNativeFilter(); @@ -377,7 +384,7 @@ private List getBaseDNs() { if (container != null) { result = Collections.singletonList( - LdapSearches.findEntryDN(conn, container.getObjectClass(), container.getUid())); + LdapSearches.findEntryDN(conn, container.getObjectClass(), container.getUid(), true)); } else { result = Arrays.asList(baseDNs); } @@ -450,7 +457,7 @@ private void removeNonReadableAttributes(final Set attributes) { } } - private int getLdapSearchScope() { + private int getLdapSearchScope(boolean ignoreUserAnyObjectConfig) { String scope = options.getScope(); if (scope == null) { @@ -458,20 +465,22 @@ private int getLdapSearchScope() { scope = conn.getConfiguration().getUserSearchScope(); } else if (oclass.is(ObjectClass.GROUP_NAME)) { scope = conn.getConfiguration().getGroupSearchScope(); - } else { + } else if (!ignoreUserAnyObjectConfig) { scope = conn.getConfiguration().getAnyObjectSearchScope(); + } else { + scope = OperationOptions.SCOPE_SUBTREE; } } switch (scope) { case OperationOptions.SCOPE_OBJECT: - return SearchControls.OBJECT_SCOPE; + return SearchControls.OBJECT_SCOPE; case OperationOptions.SCOPE_ONE_LEVEL: - return SearchControls.ONELEVEL_SCOPE; + return SearchControls.ONELEVEL_SCOPE; case OperationOptions.SCOPE_SUBTREE: - return SearchControls.SUBTREE_SCOPE; + return SearchControls.SUBTREE_SCOPE; default: - throw new IllegalArgumentException("Invalid search scope " + scope); + throw new IllegalArgumentException("Invalid search scope " + scope); } } } diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java index b27880b..0e5a6e4 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java @@ -69,17 +69,26 @@ private LdapSearches() { * if such an entry does not exists. */ public static String getEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid) { - return findEntryDN(conn, oclass, uid, true); + return findEntryDN(conn, oclass, uid, true, false); } + public static String getEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean ignoreCustomAnyObjectConfig) + { + return findEntryDN(conn, oclass, uid, true, ignoreCustomAnyObjectConfig); + } + /** * Returns the DN of the entry identified by the given Uid. May throw UnknownUidException * if such an entry does not exists, but not necessarily. */ public static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid) { - return findEntryDN(conn, oclass, uid, false); + return findEntryDN(conn, oclass, uid, false, false); } - + + public static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean ignoreCustomAnyObjectConfig) { + return findEntryDN(conn, oclass, uid, false, ignoreCustomAnyObjectConfig); + } + /** * Finds the DN of the entry corresponding to the given Uid. If the check * parameter is false, the method will take the quickest path to return the DN, but will not necessarily @@ -87,7 +96,7 @@ public static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid ui * the method will throw a UnknownUidException if the entry identified * by the Uid does not exist. */ - private static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean check) { + private static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean check, boolean ignoreCustomAnyObjectConfig) { LOG.ok("Searching for object {0} of class {1}", uid.getUidValue(), oclass.getObjectClassValue()); LdapFilter ldapFilter = null; @@ -112,6 +121,7 @@ private static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid u OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setAttributesToGet(conn.getConfiguration().getDnAttribute()); + builder.setOption(LdapSearch.OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG, ignoreCustomAnyObjectConfig); LdapSearch search = new LdapSearch(conn, oclass, ldapFilter, null, builder.build()); ConnectorObject object = search.getSingleResult(); From 22715fd91162e1dff2f67880280ad9ce59f93264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Thu, 23 Nov 2023 12:14:56 +0100 Subject: [PATCH 5/5] Minor: formatting (really need to add checkstyle...) --- .../bundles/ldap/LdapConfiguration.java | 15 ++++---- .../bundles/ldap/search/LdapSearch.java | 16 ++++----- .../bundles/ldap/search/LdapSearches.java | 35 ++++++++++++------- .../bundles/ldap/LdapConfigurationTests.java | 6 ++-- .../bundles/ldap/LdapConnectorTestBase.java | 6 ++-- .../bundles/ldap/search/LdapSearchTests.java | 27 +++++++------- 6 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java b/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java index e4d7f75..73c4d9b 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java @@ -57,6 +57,13 @@ */ public class LdapConfiguration extends AbstractConfiguration { + public enum SearchScope { + object, + onelevel, + subtree; + + } + // XXX should try to connect to the resource. public static final int DEFAULT_PORT = 389; @@ -675,7 +682,7 @@ public String getAnyObjectSearchScope() { public void setAnyObjectSearchScope(String anyObjectSearchScope) { this.anyObjectSearchScope = SearchScope.valueOf(anyObjectSearchScope.toLowerCase()); } - + @ConfigurationProperty(order = 24, displayMessageKey = "passwordHashAlgorithm.display", helpMessageKey = "passwordHashAlgorithm.help") @@ -1093,10 +1100,4 @@ public boolean equals(Object obj) { } return false; } - - public enum SearchScope { - object, - onelevel, - subtree; - } } diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java index 4c15fd6..8246c1c 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java @@ -66,6 +66,7 @@ * @author Andrei Badea */ public class LdapSearch { + // An Operation Option specific for usage with LDAP public static final String OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG = "IGNORE_CUSTOM_ANY_OBJECT_CONFIG"; @@ -169,7 +170,7 @@ public boolean handle(final String baseDN, final SearchResult result) throws Nam return results[0]; } - + private LdapInternalSearch getInternalSearch(final Set attrsToGet) { // This is a bit tricky. If the LdapFilter has an entry DN, // we only need to look at that entry and check whether it matches @@ -190,8 +191,7 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { if (filterEntryDN == null) { strategy = getSearchStrategy(); dns = getBaseDNs(); - if (options.getOptions().containsKey(OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG)) - { + if (options.getOptions().containsKey(OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG)) { ignoreUserAnyObjectConfig = (boolean) options.getOptions().get(OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG); } searchScope = getLdapSearchScope(ignoreUserAnyObjectConfig); @@ -207,9 +207,9 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { SearchControls controls = LdapInternalSearch.createDefaultSearchControls(); Set ldapAttrsToGet = getLdapAttributesToGet(attrsToGet); - controls.setReturningAttributes(ldapAttrsToGet.toArray(new String[ldapAttrsToGet.size()])); + controls.setReturningAttributes(ldapAttrsToGet.toArray(new String[0])); - controls.setSearchScope(searchScope); + controls.setSearchScope(searchScope); String optionsFilter = LdapConstants.getSearchFilter(options); String searchFilter = null; @@ -217,7 +217,7 @@ private LdapInternalSearch getInternalSearch(final Set attrsToGet) { searchFilter = conn.getConfiguration().getAccountSearchFilter(); } else if (oclass.equals(ObjectClass.GROUP)) { searchFilter = conn.getConfiguration().getGroupSearchFilter(); - } else if (!ignoreUserAnyObjectConfig){ + } else if (!ignoreUserAnyObjectConfig) { searchFilter = conn.getConfiguration().getAnyObjectSearchFilter(); } String nativeFilter = filter == null ? null : filter.getNativeFilter(); @@ -271,8 +271,8 @@ private ConnectorObject createConnectorObject( builder.setUid(conn.getSchemaMapping().createUid(oclass, entry)); builder.setName(conn.getSchemaMapping().createName(oclass, entry)); - final List ldapGroups = new ArrayList(); - final List posixGroups = new ArrayList(); + final List ldapGroups = new ArrayList<>(); + final List posixGroups = new ArrayList<>(); for (String attrName : attrsToGet) { Attribute attribute; diff --git a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java index 0e5a6e4..17ebd56 100644 --- a/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java +++ b/src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearches.java @@ -72,11 +72,11 @@ public static String getEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid return findEntryDN(conn, oclass, uid, true, false); } - public static String getEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean ignoreCustomAnyObjectConfig) - { - return findEntryDN(conn, oclass, uid, true, ignoreCustomAnyObjectConfig); + public static String getEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, + boolean ignoreCustomAnyObjectConfig) { + return findEntryDN(conn, oclass, uid, true, ignoreCustomAnyObjectConfig); } - + /** * Returns the DN of the entry identified by the given Uid. May throw UnknownUidException * if such an entry does not exists, but not necessarily. @@ -84,11 +84,16 @@ public static String getEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid public static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid) { return findEntryDN(conn, oclass, uid, false, false); } - - public static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean ignoreCustomAnyObjectConfig) { - return findEntryDN(conn, oclass, uid, false, ignoreCustomAnyObjectConfig); + + public static String findEntryDN( + LdapConnection conn, + ObjectClass oclass, + Uid uid, + boolean ignoreCustomAnyObjectConfig) { + + return findEntryDN(conn, oclass, uid, false, ignoreCustomAnyObjectConfig); } - + /** * Finds the DN of the entry corresponding to the given Uid. If the check * parameter is false, the method will take the quickest path to return the DN, but will not necessarily @@ -96,10 +101,16 @@ public static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid ui * the method will throw a UnknownUidException if the entry identified * by the Uid does not exist. */ - private static String findEntryDN(LdapConnection conn, ObjectClass oclass, Uid uid, boolean check, boolean ignoreCustomAnyObjectConfig) { + private static String findEntryDN( + LdapConnection conn, + ObjectClass oclass, + Uid uid, + boolean check, + boolean ignoreCustomAnyObjectConfig) { + LOG.ok("Searching for object {0} of class {1}", uid.getUidValue(), oclass.getObjectClassValue()); - LdapFilter ldapFilter = null; + LdapFilter ldapFilter; // If the Uid is actually the entry DN, we do not need to do a search do find the entry DN. String uidAttr = conn.getSchemaMapping().getLdapUidAttribute(oclass); @@ -137,7 +148,7 @@ public static List findObjects( LOG.ok("Searching for object with attribute {0} of class {1} in {2}", attr, oclass.getObjectClassValue(), baseDN); - final List result = new ArrayList(); + final List result = new ArrayList<>(); EqualsFilter filter = (EqualsFilter) FilterBuilder.equalTo(attr); LdapFilter ldapFilter = new LdapFilterTranslator(conn.getSchemaMapping(), oclass). @@ -177,7 +188,7 @@ public static ConnectorObject findObject( public static LdapEntry getEntry(LdapConnection conn, LdapName entryDN, String... ldapAttrsToGet) { LOG.ok("Searching for entry {0}", entryDN); - final List result = new ArrayList(); + final List result = new ArrayList<>(); if (!LdapUtil.isUnderContexts(entryDN, conn.getConfiguration(). getBaseContextsAsLdapNames())) { return null; diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java index d13bf58..060e6df 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConfigurationTests.java @@ -366,7 +366,7 @@ public void userSearchScopeNotNull() { public void userSearchScopeNotBlank() { assertThrows(IllegalArgumentException.class, () -> config.setUserSearchScope(" ")); } - + @Test public void userSearchScopeInvalid() { assertThrows(IllegalArgumentException.class, () -> config.setUserSearchScope("abc")); @@ -388,7 +388,7 @@ public void groupSearchScopeNotNull() { public void groupSearchScopeNotBlank() { assertThrows(IllegalArgumentException.class, () -> config.setGroupSearchScope(" ")); } - + @Test public void groupSearchScopeInvalid() { assertThrows(IllegalArgumentException.class, () -> config.setGroupSearchScope("abc")); @@ -410,7 +410,7 @@ public void anyObjectSearchScopeNotNull() { public void anyObjectSearchScopeNotBlank() { assertThrows(IllegalArgumentException.class, () -> config.setAnyObjectSearchScope(" ")); } - + @Test public void anyObjectSearchScopeInvalid() { assertThrows(IllegalArgumentException.class, () -> config.setAnyObjectSearchScope("abc")); diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java index 388d8c2..f922665 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/LdapConnectorTestBase.java @@ -113,7 +113,8 @@ public abstract class LdapConnectorTestBase { public static final String EXTERNAL_PEERS_DN = "cn=External Peers,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String UNIQUE_BUGS_AND_FRIENDS_DN = "cn=Unique Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; + public static final String UNIQUE_BUGS_AND_FRIENDS_DN = + "cn=Unique Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; public static final String UNIQUE_BUGS_AND_FRIENDS_CN = "Unique Bugs and Friends"; @@ -121,7 +122,8 @@ public abstract class LdapConnectorTestBase { public static final String UNIQUE_EMPTY_GROUP_DN = "cn=Unique Empty Group,ou=Groups,o=Acme,dc=example,dc=com"; - public static final String POSIX_BUGS_AND_FRIENDS_DN = "cn=POSIX Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; + public static final String POSIX_BUGS_AND_FRIENDS_DN = + "cn=POSIX Bugs and Friends,ou=Groups,o=Acme,dc=example,dc=com"; public static final String POSIX_EXTERNAL_PEERS_DN = "cn=POSIX External Peers,ou=Groups,o=Acme,dc=example,dc=com"; diff --git a/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java b/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java index 818ebea..476cdfc 100644 --- a/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java +++ b/src/test/java/net/tirasa/connid/bundles/ldap/search/LdapSearchTests.java @@ -337,17 +337,17 @@ public void configurableUserScope() { LdapConfiguration configuration = newConfiguration(); configuration.setUserSearchScope("object"); ConnectorFacade facade = newFacade(configuration); - + // Find an organization to pass in OP_CONTAINER. ObjectClass oclass = new ObjectClass("organization"); ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); - + // Prepare options OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); optionsBuilder.setPageSize(100); OperationOptions options = optionsBuilder.build(); - + // We can get bugs bunny with an 'object' search by DN ConnectorObject bugsBunny = searchByAttribute(facade, ObjectClass.ACCOUNT, new Name(BUGS_BUNNY_DN)); assertNotNull(bugsBunny); @@ -370,17 +370,17 @@ public void configurableUserScope() { objects = TestHelpers.searchToList(facade, ObjectClass.ACCOUNT, null, options); assertFalse(objects.isEmpty()); } - + @Test public void configurableGroupScope() { LdapConfiguration configuration = newConfiguration(); configuration.setGroupSearchScope("object"); ConnectorFacade facade = newFacade(configuration); - + // Find an organization to pass in OP_CONTAINER. ObjectClass oclass = new ObjectClass("organization"); ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); - + // Prepare options OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); @@ -388,9 +388,10 @@ public void configurableGroupScope() { OperationOptions options = optionsBuilder.build(); // We can get 'unique bugs and friends' with an 'object' search by DN - ConnectorObject uniqueBugsAndFriends = searchByAttribute(facade, ObjectClass.GROUP, new Name(UNIQUE_BUGS_AND_FRIENDS_DN)); + ConnectorObject uniqueBugsAndFriends = searchByAttribute( + facade, ObjectClass.GROUP, new Name(UNIQUE_BUGS_AND_FRIENDS_DN)); assertNotNull(uniqueBugsAndFriends); - + // Reconfigure for 'onelevel' search configuration.setGroupSearchScope("onelevel"); configuration.setGroupSearchFilter("(cn=" + UNIQUE_BUGS_AND_FRIENDS_CN + ")"); @@ -409,7 +410,7 @@ public void configurableGroupScope() { objects = TestHelpers.searchToList(facade, ObjectClass.GROUP, null, options); assertFalse(objects.isEmpty()); } - + @Test public void configurableAnyObjectScope() { LdapConfiguration configuration = newConfiguration(); @@ -419,7 +420,7 @@ public void configurableAnyObjectScope() { // Find an organization to pass in OP_CONTAINER. ObjectClass oclass = new ObjectClass("organization"); ConnectorObject organization = searchByAttribute(facade, oclass, new Name(ACME_DN)); - + // Prepare options OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid())); @@ -442,11 +443,11 @@ public void configurableAnyObjectScope() { List objects = TestHelpers.searchToList( facade, deviceObjectClass, null, options); assertTrue(objects.isEmpty()); - + // Reconfigure for 'subtree' search configuration.setAnyObjectSearchScope("subtree"); facade = newFacade(configuration); - + // ... but does in the organisation subtree objects = TestHelpers.searchToList(facade, deviceObjectClass, null, options); assertFalse(objects.isEmpty()); @@ -550,7 +551,7 @@ public void anyObjectSearchFilter() { // First just check that there really are some anyObjects (devices in this case). ObjectClass deviceObjectClass = new ObjectClass("device"); - + OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder(); optionsBuilder.setScope(OperationOptions.SCOPE_SUBTREE); optionsBuilder.setContainer(new QualifiedUid(oclass, organization.getUid()));