summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolfram2013-05-06 07:47:39 -0400
committerStephan Born2013-09-06 07:18:10 -0400
commite06648e65da97d8c1d3e0ad0ffbcfb988a53bd58 (patch)
tree2d40ff250f8c0619e0fcfc903b13a1227db49eea
parent8e66ce0d3d3e93e574eab255d54a618b3246323a (diff)
downloadorg.eclipse.stardust.engine-e06648e65da97d8c1d3e0ad0ffbcfb988a53bd58.zip
org.eclipse.stardust.engine-e06648e65da97d8c1d3e0ad0ffbcfb988a53bd58.tar.gz
org.eclipse.stardust.engine-e06648e65da97d8c1d3e0ad0ffbcfb988a53bd58.tar.xz
Jira-ID: CRNT-27043
Merge from r60363 to 60391 git-svn-id: https://svn.csa.sungard.com/repos/ipp2/product/trunk/stardust/engine@64714 8100b5e0-4d52-466c-ae9c-bdeccbdeaf6b Signed-off-by: Thomas Wolfram <thomas.wolfram@sungard.com>
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/SqlBuilderBase.java59
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/WorklistQueryEvaluator.java144
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/audittrail/management/ActivityInstanceUtils.java10
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/ActivityInstanceBean.java18
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/DeputyBean.java39
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserBean.java16
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserParticipantLink.java32
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserServiceImpl.java20
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserUtils.java200
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/WorkflowServiceImpl.java30
-rw-r--r--stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/utils/AuthorizationContext.java3
11 files changed, 457 insertions, 114 deletions
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/SqlBuilderBase.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/SqlBuilderBase.java
index 3107b14..f06525e 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/SqlBuilderBase.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/SqlBuilderBase.java
@@ -11,20 +11,8 @@
package org.eclipse.stardust.engine.api.query;
import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
import javax.xml.namespace.QName;
@@ -68,25 +56,7 @@ import org.eclipse.stardust.engine.core.persistence.Predicates;
import org.eclipse.stardust.engine.core.persistence.jdbc.ITableDescriptor;
import org.eclipse.stardust.engine.core.persistence.jdbc.PersistentBean;
import org.eclipse.stardust.engine.core.persistence.jdbc.TypeDescriptor;
-import org.eclipse.stardust.engine.core.runtime.beans.ActivityInstanceBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ActivityInstanceHistoryBean;
-import org.eclipse.stardust.engine.core.runtime.beans.AuditTrailActivityBean;
-import org.eclipse.stardust.engine.core.runtime.beans.AuditTrailProcessDefinitionBean;
-import org.eclipse.stardust.engine.core.runtime.beans.IDepartment;
-import org.eclipse.stardust.engine.core.runtime.beans.IUserGroup;
-import org.eclipse.stardust.engine.core.runtime.beans.LogEntryBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ModelManager;
-import org.eclipse.stardust.engine.core.runtime.beans.ModelManagerFactory;
-import org.eclipse.stardust.engine.core.runtime.beans.ModelPersistorBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ProcessInstanceBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ProcessInstanceHierarchyBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ProcessInstanceLinkBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ProcessInstanceLinkTypeBean;
-import org.eclipse.stardust.engine.core.runtime.beans.ProcessInstanceScopeBean;
-import org.eclipse.stardust.engine.core.runtime.beans.UserBean;
-import org.eclipse.stardust.engine.core.runtime.beans.UserGroupBean;
-import org.eclipse.stardust.engine.core.runtime.beans.UserRealmBean;
-import org.eclipse.stardust.engine.core.runtime.beans.WorkItemBean;
+import org.eclipse.stardust.engine.core.runtime.beans.*;
import org.eclipse.stardust.engine.core.runtime.beans.removethis.KernelTweakingProperties;
import org.eclipse.stardust.engine.core.runtime.internal.changelog.ChangeLogDigester;
import org.eclipse.stardust.engine.core.spi.extensions.runtime.DataFilterExtension;
@@ -1120,15 +1090,28 @@ public abstract class SqlBuilderBase implements SqlBuilder, FilterEvaluationVisi
{
VisitationContext context = (VisitationContext) rawContext;
- final long userOID;
+ List<Long> userOidList = CollectionUtils.newArrayList();
if (PerformingUserFilter.CURRENT_USER.equals(filter)
&& (null != context.getEvaluationContext().getUser()))
{
- userOID = context.getEvaluationContext().getUser().getOID();
+ // add current user
+ userOidList.add(context.getEvaluationContext().getUser().getOID());
+
+ // if current user is deputy for other user add them as well
+ Date now = new Date();
+ IUser user = context.getEvaluationContext().getUser();
+ List<DeputyBean> deputies = UserUtils.getDeputies(user);
+ for (DeputyBean deputy : deputies)
+ {
+ if (deputy.isActive(now))
+ {
+ userOidList.add(deputy.user);
+ }
+ }
}
else
{
- userOID = filter.getUserOID();
+ userOidList.add(filter.getUserOID());
}
PredicateTerm term;
@@ -1136,12 +1119,12 @@ public abstract class SqlBuilderBase implements SqlBuilder, FilterEvaluationVisi
{
term = Predicates.andTerm( //
Predicates.isEqual(WorkItemBean.FR__PERFORMER_KIND, PerformerType.USER), //
- Predicates.isEqual(WorkItemBean.FR__PERFORMER, userOID));
+ Predicates.inList(WorkItemBean.FR__PERFORMER, userOidList));
}
else
{
- term = Predicates.isEqual(ActivityInstanceBean.FR__CURRENT_USER_PERFORMER,
- userOID);
+ term = Predicates.inList(ActivityInstanceBean.FR__CURRENT_USER_PERFORMER,
+ userOidList);
}
return term;
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/WorklistQueryEvaluator.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/WorklistQueryEvaluator.java
index 5430285..af4cfc3 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/WorklistQueryEvaluator.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/api/query/WorklistQueryEvaluator.java
@@ -135,13 +135,35 @@ public class WorklistQueryEvaluator
OrTerm contributionsPredicate = new OrTerm();
- final long userOid = context.getUser().getOID();
+ final IUser user = context.getUser();
if (userContribution.isIncluded())
{
- // add user contribution
- contributionsPredicate.add(Predicates.andTerm( //
- Predicates.isEqual(WorkItemBean.FR__PERFORMER_KIND, PerformerType.USER), //
- Predicates.isEqual(WorkItemBean.FR__PERFORMER, userOid)));
+ OrTerm userOrTerm = new OrTerm();
+
+ // add the user itself
+ userOrTerm.add(Predicates.isEqual(WorkItemBean.FR__PERFORMER, user.getOID()));
+
+ // add the original users being deputy of
+ if (UserUtils.isDeputyOfAny(user))
+ {
+ Date now = new Date();
+ List<DeputyBean> deputies = UserUtils.getDeputies(user);
+ for (DeputyBean deputy : deputies)
+ {
+ if (deputy.isActive(now))
+ {
+ userOrTerm.add(Predicates.isEqual(WorkItemBean.FR__PERFORMER,
+ deputy.user));
+ }
+ }
+ }
+
+ // put all together:
+ // kind == UserType AND ( user1 OR user2 OR ...)
+ PredicateTerm userPredicate = Predicates.andTerm(
+ Predicates.isEqual(WorkItemBean.FR__PERFORMER_KIND, PerformerType.USER),
+ userOrTerm);
+ contributionsPredicate.add(userPredicate);
}
if ( !modelParticipantInfos.isEmpty())
@@ -325,25 +347,25 @@ public class WorklistQueryEvaluator
private Worklist buildStandardWorklist()
{
- final WorklistCollector userWorklist = collectUserWorklist();
-
- final List participantWorklists = collectParticipantWorklists();
+ final boolean consolidatedUserWorklist = true;
- final List subWorklists = new ArrayList();
+ final WorklistCollector userWorklistCollector = collectUserWorklist();
+ // List<WorklistCollector> collectDeputyUserWorklistCollectors =
+ // collectDeputyUserWorklists(consolidatedUserWorklist);
- for (Iterator itr = participantWorklists.iterator(); itr.hasNext();)
+ final List<WorklistCollector> participantWorklistCollectors = collectParticipantWorklists();
+ final List<Worklist> subWorklists = CollectionUtils.newArrayList();
+ for (WorklistCollector participantWorklistCollector : participantWorklistCollectors)
{
- WorklistCollector participantWorklist = (WorklistCollector) itr.next();
-
- subWorklists.add(convertParticipantWorklist(participantWorklist));
+ subWorklists.add(convertParticipantWorklist(participantWorklistCollector));
}
final UserInfo owner = DetailsFactory.create(context.getUser(), IUser.class,
UserInfoDetails.class);
- return new UserWorklist(owner, query, userWorklist.subset,
- userWorklist.retrievedItems, userWorklist.hasMore, subWorklists,
- userWorklist.hasTotalCount() ? new Long(userWorklist.getTotalCount()) : null,
- userWorklist.getTotalCountThreshold());
+ return new UserWorklist(owner, query, userWorklistCollector.subset,
+ userWorklistCollector.retrievedItems, userWorklistCollector.hasMore,
+ subWorklists, userWorklistCollector.hasTotalCount() ? new Long(
+ userWorklistCollector.getTotalCount()) : null);
}
/**
@@ -426,7 +448,7 @@ public class WorklistQueryEvaluator
}
}
}
-
+
private WorklistCollector collectUserWorklist()
{
final WorklistQuery.UserContribution userContribution = query.getUserContribution();
@@ -444,11 +466,93 @@ public class WorklistQueryEvaluator
}
return userWorklist;
+ }
+
+ private WorklistCollector collectUserWorklist(boolean consolidated)
+ {
+ final WorklistQuery.UserContribution userContribution = query.getUserContribution();
+ final SubsetPolicy subset = getContributionSubset(userContribution);
+ UserInfo userInfo = new UserInfoDetails(context.getUser());
+ WorklistCollector userWorklist = new WorklistCollector(userInfo, subset);
+ if (userContribution.isIncluded())
+ {
+ ActivityInstanceQuery userWorklistQuery = userWorklistQuery = new ActivityInstanceQuery(
+ query);
+ FilterOrTerm perfUserOrTerm = userWorklistQuery.getFilter().addOrTerm();
+
+ perfUserOrTerm.add(PerformingUserFilter.CURRENT_USER);
+
+ if (consolidated)
+ {
+ final IUser deputyUser = context.getUser();
+ if (UserUtils.isDeputyOfAny(deputyUser))
+ {
+ Date now = new Date();
+
+ List<DeputyBean> deputies = UserUtils.getDeputies(deputyUser);
+ for (DeputyBean deputy : deputies)
+ {
+ if (deputy.isActive(now))
+ {
+ UserInfo deputyForUserInfo = new UserInfoDetails(deputy.user);
+ perfUserOrTerm.add(new PerformingUserFilter(
+ deputyForUserInfo.getOID()));
+ }
+ }
+ }
+ }
+ userWorklistQuery.setPolicy(subset);
+
+ collectWorklistItems(userWorklistQuery, userWorklist);
+ }
+
+ return userWorklist;
+ }
+
+ /**
+ * Returns a list of WorklistConnectors for users the current user is and active deputy
+ * for.
+ *
+ * @return
+ */
+ private List<WorklistCollector> collectDeputyUserWorklists(boolean consolidated)
+ {
+ final WorklistQuery.UserContribution userContribution = query.getUserContribution();
+ final SubsetPolicy subset = getContributionSubset(userContribution);
+
+ List<WorklistCollector> deputyWorklists = CollectionUtils.newArrayList();
+
+ final IUser deputyUser = context.getUser();
+ if (UserUtils.isDeputyOfAny(deputyUser))
+ {
+ Date now = new Date();
+
+ List<DeputyBean> deputies = UserUtils.getDeputies(deputyUser);
+ for (DeputyBean deputy : deputies)
+ {
+ if (deputy.isActive(now))
+ {
+ UserInfo deputyForUserInfo = new UserInfoDetails(deputy.user);
+ WorklistCollector userWorklist = new WorklistCollector(deputyForUserInfo,
+ subset);
+ if (userContribution.isIncluded())
+ {
+ ActivityInstanceQuery userWorklistQuery = new ActivityInstanceQuery(
+ query, new PerformingUserFilter(deputyForUserInfo.getOID()));
+ userWorklistQuery.setPolicy(subset);
+
+ collectWorklistItems(userWorklistQuery, userWorklist);
+ }
+ }
+ }
+ }
+
+ return deputyWorklists;
}
- private List collectParticipantWorklists()
+ private List<WorklistCollector> collectParticipantWorklists()
{
- final List participantWorklists = new ArrayList();
+ final List<WorklistCollector> participantWorklists = CollectionUtils.newArrayList();
final Set<IParticipant> participantClosure = QueryUtils
.findScopedParticipantClosure(context.getUser());
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/audittrail/management/ActivityInstanceUtils.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/audittrail/management/ActivityInstanceUtils.java
index 70677bf..ccc020b 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/audittrail/management/ActivityInstanceUtils.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/audittrail/management/ActivityInstanceUtils.java
@@ -133,11 +133,12 @@ public class ActivityInstanceUtils
{
long current = ai.getCurrentUserPerformerOID();
if (current != SecurityProperties.getUserOID()
- && ai.getState() == ActivityInstanceState.Application)
+ && ai.getState() == ActivityInstanceState.Application
+ && !UserUtils.isDeputyOf(SecurityProperties.getUser(), current))
{
throw new AccessForbiddenException(
- BpmRuntimeError.BPMRT_AI_CURRENTLY_ACTIVATED_BY_OTHER.raise(new Long(ai
- .getOID()), new Long(current)));
+ BpmRuntimeError.BPMRT_AI_CURRENTLY_ACTIVATED_BY_OTHER.raise(
+ ai.getOID(), current));
}
}
}
@@ -245,7 +246,8 @@ public class ActivityInstanceUtils
long currentUserPerformerOid = activityInstance.getCurrentUserPerformerOID();
- if (0 != currentUserPerformerOid && currentUserPerformerOid != currentUser.getOID())
+ if (0 != currentUserPerformerOid && currentUserPerformerOid != currentUser.getOID()
+ && !UserUtils.isDeputyOf(currentUser, currentUserPerformerOid))
{
boolean isAdmin = false;
if (allowAdmin)
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/ActivityInstanceBean.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/ActivityInstanceBean.java
index 5a6eb66..0bc8727 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/ActivityInstanceBean.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/ActivityInstanceBean.java
@@ -2151,12 +2151,18 @@ public class ActivityInstanceBean extends AttributedIdentifiablePersistentBean
private void assertDelegationGranted() throws AccessForbiddenException
{
- if (getState() != ActivityInstanceState.Suspended
- && getState() != ActivityInstanceState.Hibernated)
- {
- throw new AccessForbiddenException(
- BpmRuntimeError.BPMRT_AI_CAN_NOT_BE_DELEGATED_IN_CURRENT_STATE.raise(
- Long.valueOf(getOID()), getState()));
+ fetch();
+ switch (state)
+ {
+ case ActivityInstanceState.SUSPENDED:
+ case ActivityInstanceState.HIBERNATED:
+ case ActivityInstanceState.APPLICATION:
+ // do nothing
+ break;
+ default:
+ throw new AccessForbiddenException(
+ BpmRuntimeError.BPMRT_AI_CAN_NOT_BE_DELEGATED_IN_CURRENT_STATE.raise(
+ Long.valueOf(getOID()), getState()));
}
}
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/DeputyBean.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/DeputyBean.java
index 7ae4bf2..30d1384 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/DeputyBean.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/DeputyBean.java
@@ -29,9 +29,22 @@ import org.eclipse.stardust.engine.api.dto.DeputyDetails;
import org.eclipse.stardust.engine.api.runtime.Deputy;
import org.eclipse.stardust.engine.api.runtime.UserInfo;
+/**
+ * Internal class to help with creation and parsing of the deputy information.
+ *
+ * The element names are intentionally 1 character long and no namespace and XML declaration
+ * to keep the serialized version as small as possible.
+ *
+ * Top element ("d") must have no attributes and the user element ("u") must be the first child,
+ * i.e. the serialized form must have the format "&lt;d&gt;&lt;u&gt;user-oid&lt;/u&gt;...other
+ * children...&lt;/d&gt;".
+ *
+ * @author Florin.Herinean
+ * @version $Revision: $
+ */
@XmlRootElement(name="d")
@XmlType(propOrder={"user", "from", "to"})
-class DeputyBean
+public class DeputyBean
{
private static class DateAdapter extends XmlAdapter<Long, Date>
{
@@ -49,19 +62,20 @@ class DeputyBean
}
@XmlElement(name="u")
- long user;
+ public long user;
@XmlElement(name="f")
@XmlJavaTypeAdapter(DateAdapter.class)
- Date from;
+ public Date from;
@XmlElement(name="t")
@XmlJavaTypeAdapter(DateAdapter.class)
- Date to;
+ public Date to;
+ // required default constructor
DeputyBean()
{
- // required default constructor
+
}
DeputyBean(long oid, Date fromDate, Date toDate)
@@ -122,8 +136,19 @@ class DeputyBean
return null;
}
- public static void main(String[] args)
+ public boolean isActive(Date now)
{
- System.out.println(new DeputyBean(12345, new Date(), null));
+ return (from == null || now.compareTo(from) >= 0)
+ && (to == null || now.compareTo(to) <= 0);
+ }
+
+ public boolean isExpired(Date now)
+ {
+ return to != null && now.after(to);
}
+
+ /*public static void main(String[] args)
+ {
+ System.out.println(new DeputyBean(12345, new Date(), null));
+ }*/
}
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserBean.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserBean.java
index e3739f8..04b7b61 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserBean.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserBean.java
@@ -519,6 +519,12 @@ public class UserBean extends AttributedIdentifiablePersistentBean implements IU
public void addToParticipants(IModelParticipant participant, IDepartment department)
{
+ addToParticipants(participant, department, 0);
+ }
+
+ void addToParticipants(IModelParticipant participant, IDepartment department,
+ long onBehalfOf)
+ {
fetch();
int cardinality = participant.getCardinality();
@@ -543,7 +549,7 @@ public class UserBean extends AttributedIdentifiablePersistentBean implements IU
markModified();
}
- UserParticipantLink link = new UserParticipantLink(this, participant, department);
+ UserParticipantLink link = new UserParticipantLink(this, participant, department, onBehalfOf);
StringBuffer buffer = new StringBuffer();
buffer.append("Granting ")//
@@ -555,6 +561,10 @@ public class UserBean extends AttributedIdentifiablePersistentBean implements IU
buffer.append(" in ")
.append(department);
}
+ if (onBehalfOf != 0)
+ {
+ buffer.append(" on behalf of ").append(onBehalfOf);
+ }
buffer.append(".");
AuditTrailLogger.getInstance(LogCode.SECURITY, this).info(buffer.toString());
@@ -1120,6 +1130,8 @@ public class UserBean extends AttributedIdentifiablePersistentBean implements IU
}
}
+ // TODO: (fh) user properties
+
cis.close();
}
@@ -1185,6 +1197,8 @@ public class UserBean extends AttributedIdentifiablePersistentBean implements IU
cos.writeLong(group == null ? 0 : group.getOID());
}
+ // TODO: (fh) user properties
+
cos.flush();
byte[] bytes = cos.getBytes();
cos.close();
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserParticipantLink.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserParticipantLink.java
index c538fa3..15c13cc 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserParticipantLink.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserParticipantLink.java
@@ -23,13 +23,7 @@ import org.eclipse.stardust.common.log.Logger;
import org.eclipse.stardust.engine.api.model.IModelParticipant;
import org.eclipse.stardust.engine.api.model.IOrganization;
import org.eclipse.stardust.engine.api.model.PredefinedConstants;
-import org.eclipse.stardust.engine.core.persistence.ComparisonTerm;
-import org.eclipse.stardust.engine.core.persistence.FieldRef;
-import org.eclipse.stardust.engine.core.persistence.Join;
-import org.eclipse.stardust.engine.core.persistence.Joins;
-import org.eclipse.stardust.engine.core.persistence.Predicates;
-import org.eclipse.stardust.engine.core.persistence.QueryDescriptor;
-import org.eclipse.stardust.engine.core.persistence.QueryExtension;
+import org.eclipse.stardust.engine.core.persistence.*;
import org.eclipse.stardust.engine.core.persistence.jdbc.IdentifiablePersistentBean;
import org.eclipse.stardust.engine.core.persistence.jdbc.QueryUtils;
import org.eclipse.stardust.engine.core.persistence.jdbc.Session;
@@ -206,11 +200,17 @@ public class UserParticipantLink extends IdentifiablePersistentBean
public UserParticipantLink(UserBean workflowUser, IModelParticipant participant)
{
- this(workflowUser, participant, null);
+ this(workflowUser, participant, null, 0);
}
public UserParticipantLink(UserBean workflowUser, IModelParticipant participant, IDepartment department)
{
+ this(workflowUser, participant, department, 0);
+ }
+
+ UserParticipantLink(UserBean workflowUser, IModelParticipant participant,
+ IDepartment department, long onBehalfOf)
+ {
this.workflowUser = workflowUser;
long rtOid = ModelManagerFactory.getCurrent().getRuntimeOid(participant);
@@ -221,6 +221,7 @@ public class UserParticipantLink extends IdentifiablePersistentBean
this.participant = rtOid;
this.department = department == null ? 0 : department.getOID();
+ this.onBehalfOf = onBehalfOf;
}
/**
@@ -283,6 +284,12 @@ public class UserParticipantLink extends IdentifiablePersistentBean
fetch();
return department;
}
+
+ public long getOnBehalfOf()
+ {
+ fetch();
+ return onBehalfOf;
+ }
public static void deleteAllForDepartment(IDepartment department)
{
@@ -298,4 +305,13 @@ public class UserParticipantLink extends IdentifiablePersistentBean
((UserBean) link.getUser()).removeFromParticipants(link.getParticipant(), link.getDepartment());
}
}
+
+ public static ClosableIterator<UserParticipantLink> findForUsers(long[] others)
+ {
+ org.eclipse.stardust.engine.core.persistence.Session session = SessionFactory.getSession(SessionFactory.AUDIT_TRAIL);
+ PredicateTerm predicate = Predicates.andTerm(
+ Predicates.isEqual(FR__ON_BEHALF_OF, 0), Predicates.inList(FR__USER, others));
+ return session.getIterator(UserParticipantLink.class,
+ QueryExtension.where(predicate));
+ }
}
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserServiceImpl.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserServiceImpl.java
index 4052175..186ce4b 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserServiceImpl.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserServiceImpl.java
@@ -882,6 +882,11 @@ public class UserServiceImpl implements UserService, Serializable
@Override
public Deputy modifyDeputy(UserInfo user, UserInfo deputyUser, DeputyOptions options)
{
+ if (options == null)
+ {
+ options = DeputyOptions.DEFAULT;
+ }
+
List<Deputy> deputies = getUsersBeingDeputyFor(deputyUser);
for (Deputy deputy : deputies)
{
@@ -903,6 +908,7 @@ public class UserServiceImpl implements UserService, Serializable
UserBean deputyUserBean = UserBean.findByOid(deputyUser.getOID());
UserUtils.removeExistingDeputy(user.getOID(), deputyUserBean);
+ UserUtils.updateDeputyGrants(deputyUserBean);
}
@Override
@@ -949,17 +955,11 @@ public class UserServiceImpl implements UserService, Serializable
List<Deputy> result = CollectionUtils.newArrayList();
UserBean deputyUserBean = UserBean.findByOid(deputyUser.getOID());
-
- if (UserUtils.isDeputyOfAny(deputyUserBean))
- {
- List<UserProperty> propertyList = (List<UserProperty>) deputyUserBean.getPropertyValue(UserUtils.IS_DEPUTY_OF);
+ List<DeputyBean> deputies = UserUtils.getDeputies(deputyUserBean);
- for (UserProperty userProperty : propertyList)
- {
- String stringValue = (String) userProperty.getValue();
- DeputyBean deputyBean = DeputyBean.fromString(stringValue);
- result.add(deputyBean.createDeputyDetails(deputyUser));
- }
+ for (DeputyBean deputy : deputies)
+ {
+ result.add(deputy.createDeputyDetails(deputyUser));
}
return result;
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserUtils.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserUtils.java
index 85322c4..d3cc138 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserUtils.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/UserUtils.java
@@ -19,7 +19,10 @@ import org.eclipse.stardust.common.StringUtils;
import org.eclipse.stardust.engine.api.dto.UserDetails;
import org.eclipse.stardust.engine.api.dto.UserDetails.AddedGrant;
import org.eclipse.stardust.engine.api.dto.UserDetailsLevel;
+import org.eclipse.stardust.engine.api.model.IModelParticipant;
+import org.eclipse.stardust.engine.api.model.PredefinedConstants;
import org.eclipse.stardust.engine.api.runtime.*;
+import org.eclipse.stardust.engine.core.persistence.ClosableIterator;
import org.eclipse.stardust.engine.core.runtime.beans.removethis.SecurityProperties;
import org.eclipse.stardust.engine.core.security.utils.SecurityUtils;
@@ -250,24 +253,205 @@ public final class UserUtils
deputyUserBean.removeProperty(IS_DEPUTY_OF, Long.valueOf(oid));
}
- static void updateDeputyGrants(UserBean deputyUserBean)
+ static void updateDeputyGrants(UserBean user)
{
- long now = new Date().getTime();
- List<Attribute> existing = (List<Attribute>) deputyUserBean.getPropertyValue(IS_DEPUTY_OF);
- for (Attribute attribute : existing)
+ Map<Long, Map<Long, Set<Long>>> participantMap = getParticipantsfromDeputees(user);
+
+ if (participantMap == null)
{
- String value = (String) attribute.getValue();
+ Iterator<UserParticipantLink> links = user.getAllParticipantLinks();
+ while (links.hasNext())
+ {
+ UserParticipantLink link = links.next();
+ if (link.getOnBehalfOf() != 0)
+ {
+ user.removeFromParticipants(link.getParticipant(), link.getDepartment());
+ }
+ }
+ }
+ else
+ {
+ // filter out user's own grants and already existing grants
+ Iterator<UserParticipantLink> links = user.getAllParticipantLinks();
+ while (links.hasNext())
+ {
+ UserParticipantLink link = links.next();
+ long runtimeParticipantOid = link.getRuntimeParticipantOid();
+ long departmentOid = link.getDepartmentOid();
+ long onBehalfOf = link.getOnBehalfOf();
+ Map<Long, Set<Long>> departmentMap = participantMap.get(runtimeParticipantOid);
+ Set<Long> users = departmentMap == null
+ ? null
+ : departmentMap.get(departmentOid);
+ if (onBehalfOf == 0)
+ {
+ // user has it's own grant, remove all inherited grants
+ if (departmentMap != null)
+ {
+ departmentMap.remove(departmentOid);
+ }
+ }
+ else
+ {
+ // this inherited grant is no longer available, remove it
+ if (users == null || !users.remove(onBehalfOf))
+ {
+ user.removeFromParticipants(link.getParticipant(), link.getDepartment());
+ }
+ if (users != null && users.isEmpty())
+ {
+ departmentMap.remove(departmentOid);
+ }
+ }
+ if (departmentMap != null && departmentMap.isEmpty())
+ {
+ participantMap.remove(runtimeParticipantOid);
+ }
+ }
+
+ // now add grants left in the participant map, if any
+ if ( !participantMap.isEmpty())
+ {
+ for (long runtimeParticipantOid : participantMap.keySet())
+ {
+ Map<Long, Set<Long>> departmentMap = participantMap.get(runtimeParticipantOid);
+ for (long departmentOid : departmentMap.keySet())
+ {
+ Set<Long> users = departmentMap.get(departmentOid);
+ // create a grant only for the first user
+ IModelParticipant participant = ModelManagerFactory.getCurrent()
+ .findModelParticipant(PredefinedConstants.ANY_MODEL,
+ runtimeParticipantOid);
+ IDepartment department = departmentOid == 0
+ ? null
+ : DepartmentBean.findByOID(departmentOid);
+ user.addToParticipants(participant, department, users.iterator().next());
+ }
+ }
+ }
+ }
+ }
+
+ private static Map<Long, Map<Long, Set<Long>>> getParticipantsfromDeputees(
+ UserBean user)
+ {
+ Map<Long/* participant */, Map<Long/* department */, Set<Long>/* onBehalfOf */>> participantMap = CollectionUtils.newMap();
+
+ long[] others = getUpdatedUserOids(user);
+ if (others == null)
+ {
+ return null;
+ }
+
+ // TODO: performance issue - this is fetching users too and we don't need that, only
+ // user oids
+ ClosableIterator<UserParticipantLink> itr = UserParticipantLink.findForUsers(others);
+ try
+ {
+ while (itr.hasNext())
+ {
+ UserParticipantLink link = itr.next();
+ long participantRuntimeOid = link.getRuntimeParticipantOid();
+ Map<Long/* department */, Set<Long>/* onBehalfOf */> departmentMap = participantMap.get(participantRuntimeOid);
+ if (departmentMap == null)
+ {
+ departmentMap = CollectionUtils.newMap();
+ participantMap.put(participantRuntimeOid, departmentMap);
+ }
+ long departmentOid = link.getDepartmentOid();
+ Set<Long> userSet = departmentMap.get(departmentOid);
+ if (userSet == null)
+ {
+ userSet = CollectionUtils.newSet();
+ departmentMap.put(departmentOid, userSet);
+ }
+ userSet.add(link.getUser().getOID());
+ }
+ }
+ finally
+ {
+ if (itr != null)
+ {
+ itr.close();
+ }
+ }
+
+ return participantMap;
+ }
+
+ /**
+ * @return the user OIDs for which the user is a deputy
+ */
+ private static long[] getUpdatedUserOids(UserBean user)
+ {
+ List<Attribute> existing = (List<Attribute>) user.getPropertyValue(IS_DEPUTY_OF);
+ if (existing == null || existing.isEmpty())
+ {
+ return null;
+ }
+ Date now = new Date();
+ long[] others = new long[existing.size()];
+ for (int i = 0; i < others.length; i++ )
+ {
+ String value = (String) existing.get(i).getValue();
DeputyBean db = DeputyBean.fromString(value);
- /*
- * if (db.isActive()) { updateDeputyGrants(); }
- */
+ if (db.isActive(now))
+ {
+ others[i] = db.user;
+ }
+ else if (db.isExpired(now))
+ {
+ // cleanup expired deputies
+ user.removeProperty(IS_DEPUTY_OF, value);
+ }
}
+ return others;
}
public static boolean isDeputyOfAny(IUser user)
{
return user.isPropertyAvailable(UserBean.EXTENDED_STATE_FLAG_DEPUTY_OF_PROP);
}
+
+ public static boolean isDeputyOf(IUser user, long otherOID)
+ {
+ if (isDeputyOfAny(user))
+ {
+ Date now = new Date();
+
+ List<UserProperty> propertyList = (List<UserProperty>) user.getPropertyValue(UserUtils.IS_DEPUTY_OF);
+
+ for (UserProperty userProperty : propertyList)
+ {
+ String stringValue = (String) userProperty.getValue();
+ DeputyBean deputyBean = DeputyBean.fromString(stringValue);
+ if (deputyBean.user == otherOID)
+ {
+ return deputyBean.isActive(now);
+ }
+ }
+ }
+ return false;
+ }
+
+ public static List<DeputyBean> getDeputies(IUser deputyUser)
+ {
+ List<DeputyBean> result = CollectionUtils.newArrayList();
+
+ if (isDeputyOfAny(deputyUser))
+ {
+ List<UserProperty> propertyList = (List<UserProperty>) deputyUser.getPropertyValue(UserUtils.IS_DEPUTY_OF);
+
+ for (UserProperty userProperty : propertyList)
+ {
+ String stringValue = (String) userProperty.getValue();
+ DeputyBean deputyBean = DeputyBean.fromString(stringValue);
+ result.add(deputyBean);
+ }
+ }
+ return result;
+ }
+
private UserUtils() {}
}
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/WorkflowServiceImpl.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/WorkflowServiceImpl.java
index b7d100f..4a5eb7f 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/WorkflowServiceImpl.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/beans/WorkflowServiceImpl.java
@@ -855,19 +855,20 @@ public class WorkflowServiceImpl implements Serializable, WorkflowService
{
ActivityInstanceUtils.assertNotTerminated(activityInstance);
ActivityInstanceUtils.assertNotInAbortingProcess(activityInstance);
- ActivityInstanceUtils.assertNotActivatedByOther(activityInstance);
+ //ActivityInstanceUtils.assertNotActivatedByOther(activityInstance);
ActivityInstanceUtils.assertNoSubprocess(activityInstance);
ActivityInstanceUtils.assertNotOnOtherUserWorklist(activityInstance, false);
ActivityInstanceUtils.assertNotDefaultCaseInstance(activityInstance);
- if (activityInstance.getState() == ActivityInstanceState.Application)
+ IUser currentUser = SecurityProperties.getUser();
+ if (activityInstance.getActivity().isInteractive() && currentUser != null
+ && currentUser.getOID() != 0
+ && activityInstance.getCurrentUserPerformerOID() != currentUser.getOID())
{
- return;
+ activityInstance.delegateToUser(currentUser);
}
- IUser currentUser = SecurityProperties.getUser();
- if (activityInstance.getActivity().isInteractive() && null != currentUser
- && 0 != currentUser.getOID())
+ if (activityInstance.getState() != ActivityInstanceState.Application)
{
if (activityInstance instanceof ActivityInstanceBean)
{
@@ -876,11 +877,9 @@ public class WorkflowServiceImpl implements Serializable, WorkflowService
}
else
{
- activityInstance.delegateToUser(currentUser);
+ activityInstance.activate();
}
}
-
- activityInstance.activate();
}
private void complete(IActivityInstance activityInstance, String context,
@@ -944,6 +943,7 @@ public class WorkflowServiceImpl implements Serializable, WorkflowService
IParticipant participant = null;
IDepartment department = null;
+ long currentUser = activityInstance.getCurrentUserPerformerOID();
Iterator<ActivityInstanceHistoryBean> history = ActivityInstanceHistoryBean.getAllForActivityInstance(
activityInstance, false);
@@ -952,9 +952,17 @@ public class WorkflowServiceImpl implements Serializable, WorkflowService
ActivityInstanceHistoryBean aih = history.next();
if (ActivityInstanceState.Application == aih.getState())
{
- continue;
+ IParticipant performer = aih.getPerformer();
+ if (performer instanceof IUser && ((IUser) performer).getOID() != currentUser)
+ {
+ participant = performer;
+ }
+ else
+ {
+ continue;
+ }
}
- if (ActivityInstanceState.Suspended == aih.getState())
+ else if (ActivityInstanceState.Suspended == aih.getState())
{
participant = aih.getPerformer();
department = aih.getDepartment();
diff --git a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/utils/AuthorizationContext.java b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/utils/AuthorizationContext.java
index 72c307c..2dc1cf2 100644
--- a/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/utils/AuthorizationContext.java
+++ b/stardust-engine-core/src/main/java/org/eclipse/stardust/engine/core/runtime/utils/AuthorizationContext.java
@@ -575,7 +575,8 @@ public class AuthorizationContext
}
else if (currentUserPerformer != 0)
{
- return getUser() == null || getUser().getOID() == currentUserPerformer;
+ return getUser() == null || getUser().getOID() == currentUserPerformer
+ || UserUtils.isDeputyOf(getUser(), currentUserPerformer);
}
return false;
}