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
package org.caosdb.server.jobs.core;
import java.util.Map;
import org.apache.shiro.authz.AuthorizationException;
import org.caosdb.server.entity.DeleteEntity;
import org.caosdb.server.entity.Message;
......@@ -18,6 +19,9 @@ import org.caosdb.server.utils.ServerMessages;
@JobAnnotation(time = JobExecutionTime.POST_CHECK, transaction = WriteTransaction.class)
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 =
new Message(MessageType.Error, "Transition not allowed.");
private static final Message INITIAL_STATE_NOT_ALLOWED =
......@@ -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 state machine's usual state cycle.
*/
private static final String FORCE_FINAL_STATE = "forceFinalState";
private static final String FLAG_FORCE_FINAL_STATE = "forceFinalState";
@Override
protected void run() {
......@@ -131,14 +135,13 @@ public class CheckStateTransition extends EntityStateJob {
*/
private void checkFinalState(State oldState) throws Message {
if (!oldState.isFinal()) {
if ("true".equalsIgnoreCase(getTransaction().getContainer().getFlags().get(FORCE_FINAL_STATE))
|| "true".equalsIgnoreCase(getEntity().getFlag(FORCE_FINAL_STATE))) {
// TODO permissions
return;
}
if (isForceFinal()) {
getUser().checkPermission(PERMISSION_STATE_FORCE_FINAL);
} else {
throw FINAL_STATE_NOT_ALLOWED;
}
// TODO permissions
}
getUser().checkPermission(PERMISSION_STATE_UNASSIGN + oldState.getStateModelName());
}
/**
......@@ -151,6 +154,13 @@ public class CheckStateTransition extends EntityStateJob {
if (!newState.isInitial()) {
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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
......@@ -17,6 +18,7 @@ import org.caosdb.server.datatype.IndexedSingleValue;
import org.caosdb.server.datatype.ReferenceDatatype;
import org.caosdb.server.datatype.ReferenceDatatype2;
import org.caosdb.server.datatype.ReferenceValue;
import org.caosdb.server.datatype.TextDatatype;
import org.caosdb.server.entity.ClientMessage;
import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.Message;
......@@ -74,6 +76,8 @@ public abstract class EntityStateJob extends EntityJob {
public static final String STATE_ATTRIBUTE_NAME = "name";
public static final String STATE_ATTRIBUTE_DESCRIPTION = "description";
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 =
new Message(MessageType.Error, "StateModel not found.");
......@@ -103,12 +107,24 @@ public abstract class EntityStateJob extends EntityJob {
private String description;
private State fromState;
private State toState;
private Map<String, String> transitionProperties;
public Transition(EntityInterface transition) throws Message {
this.name = transition.getName();
this.description = transition.getDescription();
this.fromState = getFromState(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 {
......@@ -185,18 +201,30 @@ public abstract class EntityStateJob extends EntityJob {
public Element toElement() {
Element result = new Element(TRANSITION_XML_TAG);
if (this.name != null) result.setAttribute(TRANSITION_ATTRIBUTE_NAME, this.name);
if (this.description != null)
if (this.transitionProperties != 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);
}
Element to = new Element(TO_XML_TAG);
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);
from.setAttribute(STATE_ATTRIBUTE_NAME, this.fromState.stateName);
return result.addContent(from).addContent(to);
}
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 {
private String stateDescription = null;
private Integer stateId = null;
private EntityACL stateACL = null;
private Map<String, String> stateProperties;
public State(String stateName, String stateModelName) throws Message {
this.stateName = stateName;
......@@ -243,12 +272,23 @@ public abstract class EntityStateJob extends EntityJob {
this.stateModelEntity = stateModelEntity;
this.stateModelName = stateModelEntity.getName();
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) {
LinkedList<EntityACI> rules = new LinkedList<>();
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;
String role = aci.getResponsibleAgent().toString().substring(7, end);
rules.add(
......@@ -289,6 +329,15 @@ public abstract class EntityStateJob extends EntityJob {
@Override
public void addToElement(Element ret) {
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) {
e.setAttribute(STATE_ATTRIBUTE_MODEL, this.stateModelName);
}
......@@ -318,7 +367,7 @@ public abstract class EntityStateJob extends EntityJob {
ret.addContent(e);
}
private String getStateModelName() {
public String getStateModelName() {
return this.stateModelName;
}
......@@ -452,7 +501,7 @@ public abstract class EntityStateJob extends EntityJob {
* @throws Message if the transitions could ne be created.
*/
private Set<Transition> createTransitions(Property p) throws Message {
Set<Transition> result = new HashSet<>();
Set<Transition> result = new LinkedHashSet<>();
try {
if (!(p.getDatatype() instanceof AbstractCollectionDatatype)) {
return result;
......@@ -486,7 +535,7 @@ public abstract class EntityStateJob extends EntityJob {
private Set<State> getStates(Set<Transition> transitions, StateModel stateModel)
throws Message {
Iterator<Transition> it = transitions.iterator();
Set<State> result = new HashSet<>();
Set<State> result = new LinkedHashSet<>();
while (it.hasNext()) {
Transition t = it.next();
result.add(t.getFromState());
......@@ -657,7 +706,7 @@ public abstract class EntityStateJob extends EntityJob {
EntityInterface stateEntity = cache.get("state" + Integer.toString(refid.getId()));
boolean cached = true;
if (stateEntity == null || !cached) {
stateEntity = retrieveValidSparseEntityById(refid.getId(), null);
stateEntity = retrieveValidEntity(refid.getId());
cache.put("state" + Integer.toString(refid.getId()), stateEntity);
}
......
......@@ -76,8 +76,10 @@ public class InitEntityStateJobs extends EntityStateJob implements Observer {
oldState = null;
if (states.size() == 1) {
oldState = states.get(0);
if (newState != null) {
((UpdateEntity) getEntity()).getOriginal().setEntityACL(getEntity().getEntityACL());
}
}
if (!Objects.equals(newState, oldState)) {
getEntity().acceptObserver(this);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment