Skip to content

Commit

Permalink
Merge branch 'master1803' into github
Browse files Browse the repository at this point in the history
  • Loading branch information
dofs197 committed Aug 31, 2020
2 parents 60b3d9a + 2a02b88 commit 9e39166
Show file tree
Hide file tree
Showing 22 changed files with 394 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected IdentitiesSetContainer(NamedIdentityType identitiesType) {

protected void validate(ScriptOperation scriptOperation, boolean requiredNotEmpty) {
for (NamedIdentitySet set : identitySets) {
set.ensureType(scriptOperation, identitiesType);
set.validate(scriptOperation, identitiesType);
}
for (Identity identity : identities) {
identity.validate(scriptOperation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected IdentitiesSetContainerOperation(NamedIdentityType identitiesType) {

protected void validate(boolean requiredNotEmpty) {
for (NamedIdentitySet set : identitySets) {
set.ensureType(this, identitiesType);
set.validate(this, identitiesType);
}
if (requiredNotEmpty) {
if (identitySets.size() == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class NamedIdentitySet {
@XmlAttribute(name = AdminScriptConstants.NAME_ATTRIBUTE_NAME)
public String name;

@XmlAttribute(name = AdminScriptConstants.TYPE_ATTRIBUTE_NAME, required = true)
@XmlAttribute(name = AdminScriptConstants.TYPE_ATTRIBUTE_NAME)
public NamedIdentityType type;

@XmlElement(name = AdminScriptConstants.IDENTITY_ELEMENT_NAME, namespace = AdminScriptConstants.NAMESPACE)
Expand All @@ -37,15 +37,18 @@ public class NamedIdentitySet {
* @param requiredType
* Required identity set type
*/
public void ensureType(ScriptOperation scriptOperation, NamedIdentityType requiredType) {
public void validate(ScriptOperation scriptOperation, NamedIdentityType requiredType) {
if (type == null) {
throw new ScriptValidationException(scriptOperation, "Type is required.");
}
if (requiredType != type) {
throw new ScriptValidationException(scriptOperation, "Required identity set of type " + requiredType.getScriptName() + ".");
}
for (NamedIdentitySet innerSet : identitySetsReferences) {
if (innerSet.type != type) {
throw new ScriptValidationException(scriptOperation, "Inner named identity must be the same type as outer.");
}
innerSet.ensureType(scriptOperation, requiredType);
innerSet.validate(scriptOperation, requiredType);
}
}

Expand Down Expand Up @@ -92,21 +95,21 @@ public void register(ScriptExecutionContext context) {

@XmlEnum
public enum NamedIdentityType {
@XmlEnumValue(value = "DEFINITION")
PROCESS_DEFINITION(SecuredObjectType.DEFINITION),
@XmlEnumValue(value = "ProcessDefinition")
PROCESS_DEFINITION(SecuredObjectType.DEFINITION, "ProcessDefinition"),

@XmlEnumValue(value = "EXECUTOR")
EXECUTOR(SecuredObjectType.EXECUTOR),
@XmlEnumValue(value = "Executor")
EXECUTOR(SecuredObjectType.EXECUTOR, "Executor"),

@XmlEnumValue(value = "REPORT")
REPORT(SecuredObjectType.REPORT);
@XmlEnumValue(value = "Report")
REPORT(SecuredObjectType.REPORT, "Report");

private SecuredObjectType securedObjectType;
private String scriptName;
private final SecuredObjectType securedObjectType;
private final String scriptName;

NamedIdentityType(SecuredObjectType type) {
NamedIdentityType(SecuredObjectType type, String scriptName) {
this.securedObjectType = type;
this.scriptName = type.getName();
this.scriptName = scriptName;
}

public String getScriptName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package ru.runa.wfe.script.common;

import com.google.common.collect.Maps;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.collect.Maps;

import ru.runa.wfe.bot.logic.BotLogic;
import ru.runa.wfe.commons.ApplicationContextFactory;
import ru.runa.wfe.definition.logic.DefinitionLogic;
Expand All @@ -25,7 +22,7 @@
public class ScriptExecutionContext {

@Autowired
ExecutorLogic executorLogic;
private ExecutorLogic executorLogic;
@Autowired
private RelationLogic relationLogic;
@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class SetActorInactiveOperation extends ScriptOperation {
public void validate(ScriptExecutionContext context) {
ScriptValidation.requiredAttribute(this, AdminScriptConstants.NAME_ATTRIBUTE_NAME, name);
for (NamedIdentitySet set : identities) {
set.ensureType(this, NamedIdentityType.EXECUTOR);
set.validate(this, NamedIdentityType.EXECUTOR);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,15 @@ public abstract class ChangePermissionsOperation extends ScriptOperation {
@XmlAttribute(name = "executor", required = true)
protected String xmlExecutor;

@SuppressWarnings("unused")
@XmlAttribute(name = "type")
private String xmlType;

@SuppressWarnings("unused")
@XmlAttribute(name = "name")
private String xmlName;

@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@XmlElement(name = "namedIdentitySet", namespace = AdminScriptConstants.NAMESPACE)
private List<NamedIdentitySet> xmlNamedIdentitySets = Lists.newArrayList();

@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@XmlElement(name = "permission", namespace = AdminScriptConstants.NAMESPACE)
private List<ru.runa.wfe.script.permission.Permission> xmlPermissions = new ArrayList<>();

Expand Down
125 changes: 62 additions & 63 deletions wfe-core/src/main/java/ru/runa/wfe/security/logic/LdapLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;
import javax.naming.ldap.PagedResultsResponseControl;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -70,12 +72,7 @@ public class LdapLogic {
private static final String ATTR_ACCOUNT_NAME = LdapProperties.getSynchronizationAccountNameAttribute();
private static final String ATTR_GROUP_NAME = LdapProperties.getSynchronizationGroupNameAttribute();
private static final String ATTR_GROUP_MEMBER = LdapProperties.getSynchronizationGroupMemberAttribute();
// for paging
private static final String LOGIN_FIRST_LETTER_FILTER = "(&(|({0}={1}*)({0}={2}*)){3})";
private static final String[] ALPHABETS = { "А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У",
"Ф", "Х", "Ч", "Ц", "Ш", "Щ", "Э", "Ю", "Я", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z" };

private static int pageSize = LdapProperties.getLdapPageSize();
@Autowired
protected ExecutorDao executorDao;
@Autowired
Expand All @@ -91,15 +88,15 @@ public synchronized int synchronizeExecutors() {
}
log.info("Synchronizing executors");
try {
importGroup = loadGroup(new Group(LdapProperties.getSynchronizationImportGroupName(),
LdapProperties.getSynchronizationImportGroupDescription()));
wasteGroup = loadGroup(new Group(LdapProperties.getSynchronizationWasteGroupName(),
LdapProperties.getSynchronizationWasteGroupDescription()));
DirContext dirContext = getContext();
importGroup = loadGroup(
new Group(LdapProperties.getSynchronizationImportGroupName(), LdapProperties.getSynchronizationImportGroupDescription()));
wasteGroup = loadGroup(
new Group(LdapProperties.getSynchronizationWasteGroupName(), LdapProperties.getSynchronizationWasteGroupDescription()));
LdapContext ldapContext = getContext();
Map<String, Actor> actorsByDistinguishedName = Maps.newHashMap();
int changesCount = synchronizeActors(dirContext, actorsByDistinguishedName);
changesCount += synchronizeGroups(dirContext, actorsByDistinguishedName);
dirContext.close();
int changesCount = synchronizeActors(ldapContext, actorsByDistinguishedName);
changesCount += synchronizeGroups(ldapContext, actorsByDistinguishedName);
ldapContext.close();
return changesCount;
} catch (Exception e) {
log.error("", e);
Expand All @@ -108,7 +105,7 @@ public synchronized int synchronizeExecutors() {
}
}

private int synchronizeActors(DirContext dirContext, Map<String, Actor> actorsByDistinguishedName) throws Exception {
private int synchronizeActors(LdapContext ldapContext, Map<String, Actor> actorsByDistinguishedName) throws Exception {
int changesCount = 0;
List<Actor> existingActorsList = executorDao.getAllActors(BatchPresentationFactory.ACTORS.createNonPaged());
Map<String, Actor> existingActorsMap = Maps.newHashMap();
Expand All @@ -119,30 +116,32 @@ private int synchronizeActors(DirContext dirContext, Map<String, Actor> actorsBy
if (LdapProperties.isSynchronizationDeleteExecutors()) {
ldapActorsToDelete.addAll(executorDao.getGroupActors(importGroup));
}
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
for (String ou : LdapProperties.getSynchronizationOrganizationUnits()) {
List<SearchResult> resultList = Lists.newArrayList();
try {
NamingEnumeration<SearchResult> list = dirContext.search(ou, OBJECT_CLASS_USER_FILTER, controls);
while (list.hasMore()) {
SearchResult searchResult = list.next();
resultList.add(searchResult);
byte[] cookie = null;
ldapContext.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
do {
NamingEnumeration<SearchResult> results = ldapContext.search(ou, OBJECT_CLASS_USER_FILTER, searchControls);
while (results.hasMoreElements()) {
SearchResult result = results.nextElement();
resultList.add(result);
}
list.close();
} catch (SizeLimitExceededException e) {
resultList.clear();
for (String y : ALPHABETS) {
NamingEnumeration<SearchResult> list = dirContext.search(ou,
MessageFormat.format(LOGIN_FIRST_LETTER_FILTER, ATTR_ACCOUNT_NAME, y, y.toLowerCase(), OBJECT_CLASS_USER_FILTER),
controls);
while (list.hasMore()) {
SearchResult searchResult = list.next();
resultList.add(searchResult);
results.close();
Control[] controls = ldapContext.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl response = (PagedResultsResponseControl) control;
cookie = response.getCookie();
}
}
list.close();
} else {
log.warn("Ldap server did not send controls for paging");
}
}
ldapContext.setRequestControls(new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
for (SearchResult searchResult : resultList) {
String name = getStringAttribute(searchResult, ATTR_ACCOUNT_NAME);
String description = getStringAttribute(searchResult, LdapProperties.getSynchronizationUserDescriptionAttribute());
Expand Down Expand Up @@ -232,7 +231,7 @@ private int synchronizeActors(DirContext dirContext, Map<String, Actor> actorsBy
return changesCount;
}

private int synchronizeGroups(DirContext dirContext, Map<String, Actor> actorsByDistinguishedName) throws NamingException {
private int synchronizeGroups(LdapContext ldapContext, Map<String, Actor> actorsByDistinguishedName) throws Exception {
int changesCount = 0;
List<Group> existingGroupsList = executorDao.getAllGroups();
Map<String, Group> existingGroupsByLdapNameMap = Maps.newHashMap();
Expand All @@ -250,35 +249,35 @@ private int synchronizeGroups(DirContext dirContext, Map<String, Actor> actorsBy
}
}
}
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
Map<String, SearchResult> groupResultsByDistinguishedName = Maps.newHashMap();
for (String ou : LdapProperties.getSynchronizationOrganizationUnits()) {
try {
NamingEnumeration<SearchResult> list = dirContext.search(ou, OBJECT_CLASS_GROUP_FILTER, controls);
while (list.hasMore()) {
SearchResult searchResult = list.next();
byte[] cookie = null;
ldapContext.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
do {
NamingEnumeration<SearchResult> results = ldapContext.search(ou, OBJECT_CLASS_GROUP_FILTER, searchControls);
while (results.hasMoreElements()) {
SearchResult searchResult = results.nextElement();
if (searchResult.getAttributes().get(ATTR_GROUP_MEMBER) == null) {
continue;
}
groupResultsByDistinguishedName.put(searchResult.getNameInNamespace(), searchResult);
}
list.close();
} catch (SizeLimitExceededException e) {
for (String y : ALPHABETS) {
NamingEnumeration<SearchResult> list = dirContext.search(ou,
MessageFormat.format(LOGIN_FIRST_LETTER_FILTER, ATTR_GROUP_NAME, y, y.toLowerCase(), OBJECT_CLASS_GROUP_FILTER),
controls);
while (list.hasMore()) {
SearchResult searchResult = list.next();
if (searchResult.getAttributes().get(ATTR_GROUP_MEMBER) == null) {
continue;
results.close();
Control[] controls = ldapContext.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl response = (PagedResultsResponseControl) control;
cookie = response.getCookie();
}
groupResultsByDistinguishedName.put(searchResult.getNameInNamespace(), searchResult);
}
list.close();
} else {
log.warn("Ldap server did not send controls for paging");
}
}
ldapContext.setRequestControls(new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
}
for (SearchResult searchResult : groupResultsByDistinguishedName.values()) {
String name = getStringAttribute(searchResult, ATTR_GROUP_NAME);
Expand Down Expand Up @@ -323,7 +322,7 @@ private int synchronizeGroups(DirContext dirContext, Map<String, Actor> actorsBy
Set<Actor> actorsToDelete = Sets.newHashSet(executorDao.getGroupActors(group));
Set<Actor> actorsToAdd = Sets.newHashSet();
Set<Actor> groupTargetActors = Sets.newHashSet();
fillTargetActorsRecursively(dirContext, groupTargetActors, searchResult, groupResultsByDistinguishedName, actorsByDistinguishedName);
fillTargetActorsRecursively(ldapContext, groupTargetActors, searchResult, groupResultsByDistinguishedName, actorsByDistinguishedName);
for (Actor targetActor : groupTargetActors) {
if (!actorsToDelete.remove(targetActor)) {
actorsToAdd.add(targetActor);
Expand Down Expand Up @@ -364,9 +363,9 @@ private Pattern getPatternForMissedPeople() {
return patternForMissedPeople;
}

private DirContext getContext() throws NamingException {
private LdapContext getContext() throws NamingException {
Hashtable<String, String> env = new Hashtable<>(LdapProperties.getAllProperties());
return new InitialDirContext(env);
return new InitialLdapContext(env, null);
}

private Group loadGroup(Group group) {
Expand All @@ -390,14 +389,14 @@ private String getStringAttribute(SearchResult searchResult, String name) throws
return null;
}

private void fillTargetActorsRecursively(DirContext dirContext, Set<Actor> recursiveActors, SearchResult searchResult,
private void fillTargetActorsRecursively(LdapContext ldapContext, Set<Actor> recursiveActors, SearchResult searchResult,
Map<String, SearchResult> groupResultsByDistinguishedName, Map<String, Actor> actorsByDistinguishedName) throws NamingException {
NamingEnumeration<String> namingEnum = (NamingEnumeration<String>) searchResult.getAttributes().get(ATTR_GROUP_MEMBER).getAll();
while (namingEnum.hasMore()) {
String executorDistinguishedName = namingEnum.next();
SearchResult groupSearchResult = groupResultsByDistinguishedName.get(executorDistinguishedName);
if (groupSearchResult != null) {
fillTargetActorsRecursively(dirContext, recursiveActors, groupSearchResult, groupResultsByDistinguishedName,
fillTargetActorsRecursively(ldapContext, recursiveActors, groupSearchResult, groupResultsByDistinguishedName,
actorsByDistinguishedName);
} else {
Actor actor = actorsByDistinguishedName.get(executorDistinguishedName);
Expand All @@ -406,7 +405,7 @@ private void fillTargetActorsRecursively(DirContext dirContext, Set<Actor> recur
} else {
Matcher m = getPatternForMissedPeople().matcher(executorDistinguishedName);
String executorPath = m.replaceAll("");
Attribute samAttribute = dirContext.getAttributes(executorPath).get(ATTR_ACCOUNT_NAME);
Attribute samAttribute = ldapContext.getAttributes(executorPath).get(ATTR_ACCOUNT_NAME);
if (samAttribute != null) {
String executorName = samAttribute.get().toString();
log.debug("Executor name " + executorDistinguishedName + " fetched by invocation: " + executorName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public static boolean isSynchronizationUpdateExecutors() {
public static boolean isSynchronizationDeleteExecutors() {
return RESOURCES.getBooleanProperty("synchronization.delete.executors.enabled", false);
}

public static int getLdapPageSize() {
return RESOURCES.getIntegerProperty("synchronization.pageSize", 1000);
}

public static List<String> getSynchronizationOrganizationUnits() {
return RESOURCES.getMultipleStringProperty("synchronization.organization.units");
Expand Down
Loading

0 comments on commit 9e39166

Please sign in to comment.