Skip to content
Snippets Groups Projects
Verified Commit 1343a94e authored by Timm Fitschen's avatar Timm Fitschen
Browse files

More permission checks for transitions

parent 875b74f5
Branches
Tags
3 merge requests!21Release v0.4.0,!7F fsm,!6Draft: F acm permissions2
This commit is part of merge request !7. Comments created here will be created in the context of that merge request.
package org.caosdb.server.jobs.core; package org.caosdb.server.jobs.core;
import java.util.Map;
import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.authz.AuthorizationException;
import org.caosdb.server.entity.DeleteEntity; import org.caosdb.server.entity.DeleteEntity;
import org.caosdb.server.entity.Message; import org.caosdb.server.entity.Message;
...@@ -18,6 +19,9 @@ import org.caosdb.server.utils.ServerMessages; ...@@ -18,6 +19,9 @@ import org.caosdb.server.utils.ServerMessages;
@JobAnnotation(time = JobExecutionTime.POST_CHECK, transaction = WriteTransaction.class) @JobAnnotation(time = JobExecutionTime.POST_CHECK, transaction = WriteTransaction.class)
public class CheckStateTransition extends EntityStateJob { public class CheckStateTransition extends EntityStateJob {
private static final String PERMISSION_STATE_FORCE_FINAL = "STATE:FORCE:FINAL";
private static final String PERMISSION_STATE_UNASSIGN = "STATE:UNASSIGN:";
private static final String PERMISSION_STATE_ASSIGN = "STATE:ASSIGN:";
private static final Message TRANSITION_NOT_ALLOWED = private static final Message TRANSITION_NOT_ALLOWED =
new Message(MessageType.Error, "Transition not allowed."); new Message(MessageType.Error, "Transition not allowed.");
private static final Message INITIAL_STATE_NOT_ALLOWED = private static final Message INITIAL_STATE_NOT_ALLOWED =
...@@ -29,7 +33,7 @@ public class CheckStateTransition extends EntityStateJob { ...@@ -29,7 +33,7 @@ public class CheckStateTransition extends EntityStateJob {
* The forceFinalState flag is especially useful if you want to delete entities in the middle of * The forceFinalState flag is especially useful if you want to delete entities in the middle of
* the state machine's usual state cycle. * the state machine's usual state cycle.
*/ */
private static final String FORCE_FINAL_STATE = "forceFinalState"; private static final String FLAG_FORCE_FINAL_STATE = "forceFinalState";
@Override @Override
protected void run() { protected void run() {
...@@ -131,14 +135,13 @@ public class CheckStateTransition extends EntityStateJob { ...@@ -131,14 +135,13 @@ public class CheckStateTransition extends EntityStateJob {
*/ */
private void checkFinalState(State oldState) throws Message { private void checkFinalState(State oldState) throws Message {
if (!oldState.isFinal()) { if (!oldState.isFinal()) {
if ("true".equalsIgnoreCase(getTransaction().getContainer().getFlags().get(FORCE_FINAL_STATE)) if (isForceFinal()) {
|| "true".equalsIgnoreCase(getEntity().getFlag(FORCE_FINAL_STATE))) { getUser().checkPermission(PERMISSION_STATE_FORCE_FINAL);
// TODO permissions } else {
return;
}
throw FINAL_STATE_NOT_ALLOWED; throw FINAL_STATE_NOT_ALLOWED;
} }
// TODO permissions }
getUser().checkPermission(PERMISSION_STATE_UNASSIGN + oldState.getStateModelName());
} }
/** /**
...@@ -151,6 +154,13 @@ public class CheckStateTransition extends EntityStateJob { ...@@ -151,6 +154,13 @@ public class CheckStateTransition extends EntityStateJob {
if (!newState.isInitial()) { if (!newState.isInitial()) {
throw INITIAL_STATE_NOT_ALLOWED; throw INITIAL_STATE_NOT_ALLOWED;
} }
// TODO permissions getUser().checkPermission(PERMISSION_STATE_ASSIGN + newState.getStateModelName());
}
private boolean isForceFinal() {
Map<String, String> containerFlags = getTransaction().getContainer().getFlags();
return (containerFlags != null
&& "true".equalsIgnoreCase(containerFlags.get(FLAG_FORCE_FINAL_STATE)))
|| "true".equalsIgnoreCase(getEntity().getFlag(FLAG_FORCE_FINAL_STATE));
} }
} }
...@@ -2,8 +2,9 @@ package org.caosdb.server.jobs.core; ...@@ -2,8 +2,9 @@ package org.caosdb.server.jobs.core;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -17,6 +18,7 @@ import org.caosdb.server.datatype.IndexedSingleValue; ...@@ -17,6 +18,7 @@ import org.caosdb.server.datatype.IndexedSingleValue;
import org.caosdb.server.datatype.ReferenceDatatype; import org.caosdb.server.datatype.ReferenceDatatype;
import org.caosdb.server.datatype.ReferenceDatatype2; import org.caosdb.server.datatype.ReferenceDatatype2;
import org.caosdb.server.datatype.ReferenceValue; import org.caosdb.server.datatype.ReferenceValue;
import org.caosdb.server.datatype.TextDatatype;
import org.caosdb.server.entity.ClientMessage; import org.caosdb.server.entity.ClientMessage;
import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.Message; import org.caosdb.server.entity.Message;
...@@ -74,6 +76,8 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -74,6 +76,8 @@ public abstract class EntityStateJob extends EntityJob {
public static final String STATE_ATTRIBUTE_NAME = "name"; public static final String STATE_ATTRIBUTE_NAME = "name";
public static final String STATE_ATTRIBUTE_DESCRIPTION = "description"; public static final String STATE_ATTRIBUTE_DESCRIPTION = "description";
public static final String STATE_ATTRIBUTE_ID = "id"; public static final String STATE_ATTRIBUTE_ID = "id";
public static final String ENTITY_STATE_ROLE_MARKER = "?STATE?";
public static final String PERMISSION_STATE_TRANSION = "STATE:TRANSITION:";
public static final Message STATE_MODEL_NOT_FOUND = public static final Message STATE_MODEL_NOT_FOUND =
new Message(MessageType.Error, "StateModel not found."); new Message(MessageType.Error, "StateModel not found.");
...@@ -103,12 +107,24 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -103,12 +107,24 @@ public abstract class EntityStateJob extends EntityJob {
private String description; private String description;
private State fromState; private State fromState;
private State toState; private State toState;
private Map<String, String> transitionProperties;
public Transition(EntityInterface transition) throws Message { public Transition(EntityInterface transition) throws Message {
this.name = transition.getName(); this.name = transition.getName();
this.description = transition.getDescription(); this.description = transition.getDescription();
this.fromState = getFromState(transition); this.fromState = getFromState(transition);
this.toState = getToState(transition); this.toState = getToState(transition);
this.transitionProperties = getTransitionProperties(transition);
}
private Map<String, String> getTransitionProperties(EntityInterface transition) {
Map<String, String> result = new LinkedHashMap<>();
for (Property p : transition.getProperties()) {
if (p.getDatatype() instanceof TextDatatype) {
result.put(p.getName(), p.getValue().toString());
}
}
return result;
} }
private State getToState(EntityInterface transition) throws Message { private State getToState(EntityInterface transition) throws Message {
...@@ -185,18 +201,30 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -185,18 +201,30 @@ public abstract class EntityStateJob extends EntityJob {
public Element toElement() { public Element toElement() {
Element result = new Element(TRANSITION_XML_TAG); Element result = new Element(TRANSITION_XML_TAG);
if (this.name != null) result.setAttribute(TRANSITION_ATTRIBUTE_NAME, this.name); if (this.transitionProperties != null) {
if (this.description != null) this.transitionProperties.forEach(
(String key, String value) -> {
result.setAttribute(key, value);
});
}
if (this.name != null) {
result.setAttribute(TRANSITION_ATTRIBUTE_NAME, this.name);
}
if (this.description != null) {
result.setAttribute(TRANSITION_ATTRIBUTE_DESCRIPTION, this.description); result.setAttribute(TRANSITION_ATTRIBUTE_DESCRIPTION, this.description);
}
Element to = new Element(TO_XML_TAG); Element to = new Element(TO_XML_TAG);
to.setAttribute(STATE_ATTRIBUTE_NAME, this.toState.stateName); to.setAttribute(STATE_ATTRIBUTE_NAME, this.toState.stateName);
if (this.toState.stateDescription != null) {
to.setAttribute(STATE_ATTRIBUTE_DESCRIPTION, this.toState.stateDescription);
}
Element from = new Element(FROM_XML_TAG); Element from = new Element(FROM_XML_TAG);
from.setAttribute(STATE_ATTRIBUTE_NAME, this.fromState.stateName); from.setAttribute(STATE_ATTRIBUTE_NAME, this.fromState.stateName);
return result.addContent(from).addContent(to); return result.addContent(from).addContent(to);
} }
public boolean isPermitted(Subject user) { public boolean isPermitted(Subject user) {
return user.isPermitted("STATE:TRANSITION:" + this.name); return user.isPermitted(PERMISSION_STATE_TRANSION + this.name);
} }
} }
...@@ -229,6 +257,7 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -229,6 +257,7 @@ public abstract class EntityStateJob extends EntityJob {
private String stateDescription = null; private String stateDescription = null;
private Integer stateId = null; private Integer stateId = null;
private EntityACL stateACL = null; private EntityACL stateACL = null;
private Map<String, String> stateProperties;
public State(String stateName, String stateModelName) throws Message { public State(String stateName, String stateModelName) throws Message {
this.stateName = stateName; this.stateName = stateName;
...@@ -243,12 +272,23 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -243,12 +272,23 @@ public abstract class EntityStateJob extends EntityJob {
this.stateModelEntity = stateModelEntity; this.stateModelEntity = stateModelEntity;
this.stateModelName = stateModelEntity.getName(); this.stateModelName = stateModelEntity.getName();
this.stateACL = createStateACL(stateEntity.getEntityACL()); this.stateACL = createStateACL(stateEntity.getEntityACL());
this.stateProperties = createStateProperties(stateEntity);
}
private Map<String, String> createStateProperties(EntityInterface stateEntity) {
Map<String, String> result = new LinkedHashMap<>();
for (Property p : stateEntity.getProperties()) {
if (p.getDatatype() instanceof TextDatatype) {
result.put(p.getName(), p.getValue().toString());
}
}
return result;
} }
private EntityACL createStateACL(EntityACL entityACL) { private EntityACL createStateACL(EntityACL entityACL) {
LinkedList<EntityACI> rules = new LinkedList<>(); LinkedList<EntityACI> rules = new LinkedList<>();
for (EntityACI aci : entityACL.getRules()) { for (EntityACI aci : entityACL.getRules()) {
if (aci.getResponsibleAgent().toString().startsWith("?STATE?")) { if (aci.getResponsibleAgent().toString().startsWith(ENTITY_STATE_ROLE_MARKER)) {
int end = aci.getResponsibleAgent().toString().length() - 1; int end = aci.getResponsibleAgent().toString().length() - 1;
String role = aci.getResponsibleAgent().toString().substring(7, end); String role = aci.getResponsibleAgent().toString().substring(7, end);
rules.add( rules.add(
...@@ -289,6 +329,15 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -289,6 +329,15 @@ public abstract class EntityStateJob extends EntityJob {
@Override @Override
public void addToElement(Element ret) { public void addToElement(Element ret) {
Element e = new Element(STATE_XML_TAG); Element e = new Element(STATE_XML_TAG);
if (this.stateProperties == null && this.stateEntity != null) {
this.stateProperties = createStateProperties(this.stateEntity);
}
if (this.stateProperties != null && this.stateProperties.size() > 0) {
this.stateProperties.forEach(
(String key, String value) -> {
e.setAttribute(key, value);
});
}
if (this.stateModelName != null) { if (this.stateModelName != null) {
e.setAttribute(STATE_ATTRIBUTE_MODEL, this.stateModelName); e.setAttribute(STATE_ATTRIBUTE_MODEL, this.stateModelName);
} }
...@@ -318,7 +367,7 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -318,7 +367,7 @@ public abstract class EntityStateJob extends EntityJob {
ret.addContent(e); ret.addContent(e);
} }
private String getStateModelName() { public String getStateModelName() {
return this.stateModelName; return this.stateModelName;
} }
...@@ -452,7 +501,7 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -452,7 +501,7 @@ public abstract class EntityStateJob extends EntityJob {
* @throws Message if the transitions could ne be created. * @throws Message if the transitions could ne be created.
*/ */
private Set<Transition> createTransitions(Property p) throws Message { private Set<Transition> createTransitions(Property p) throws Message {
Set<Transition> result = new HashSet<>(); Set<Transition> result = new LinkedHashSet<>();
try { try {
if (!(p.getDatatype() instanceof AbstractCollectionDatatype)) { if (!(p.getDatatype() instanceof AbstractCollectionDatatype)) {
return result; return result;
...@@ -486,7 +535,7 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -486,7 +535,7 @@ public abstract class EntityStateJob extends EntityJob {
private Set<State> getStates(Set<Transition> transitions, StateModel stateModel) private Set<State> getStates(Set<Transition> transitions, StateModel stateModel)
throws Message { throws Message {
Iterator<Transition> it = transitions.iterator(); Iterator<Transition> it = transitions.iterator();
Set<State> result = new HashSet<>(); Set<State> result = new LinkedHashSet<>();
while (it.hasNext()) { while (it.hasNext()) {
Transition t = it.next(); Transition t = it.next();
result.add(t.getFromState()); result.add(t.getFromState());
...@@ -657,7 +706,7 @@ public abstract class EntityStateJob extends EntityJob { ...@@ -657,7 +706,7 @@ public abstract class EntityStateJob extends EntityJob {
EntityInterface stateEntity = cache.get("state" + Integer.toString(refid.getId())); EntityInterface stateEntity = cache.get("state" + Integer.toString(refid.getId()));
boolean cached = true; boolean cached = true;
if (stateEntity == null || !cached) { if (stateEntity == null || !cached) {
stateEntity = retrieveValidSparseEntityById(refid.getId(), null); stateEntity = retrieveValidEntity(refid.getId());
cache.put("state" + Integer.toString(refid.getId()), stateEntity); cache.put("state" + Integer.toString(refid.getId()), stateEntity);
} }
......
...@@ -76,8 +76,10 @@ public class InitEntityStateJobs extends EntityStateJob implements Observer { ...@@ -76,8 +76,10 @@ public class InitEntityStateJobs extends EntityStateJob implements Observer {
oldState = null; oldState = null;
if (states.size() == 1) { if (states.size() == 1) {
oldState = states.get(0); oldState = states.get(0);
if (newState != null) {
((UpdateEntity) getEntity()).getOriginal().setEntityACL(getEntity().getEntityACL()); ((UpdateEntity) getEntity()).getOriginal().setEntityACL(getEntity().getEntityACL());
} }
}
if (!Objects.equals(newState, oldState)) { if (!Objects.equals(newState, oldState)) {
getEntity().acceptObserver(this); getEntity().acceptObserver(this);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment