From 26fdd9affc1c2bcbc25ae1822b95ce5dbceb15bb Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Fri, 28 Jun 2019 17:07:21 +0200
Subject: [PATCH] OO-4119: refactor course node password to control guest
 access

---
 .../nodes/CourseNodePasswordManager.java      |  16 +-
 .../nodes/CourseNodePasswordManagerImpl.java  | 182 ++++++------------
 .../AdditionalConditionManager.java           |  11 +-
 .../PasswordCondition.java                    |  17 +-
 .../PasswordVerificationController.java       |   2 +-
 .../nodes/AbstractAccessableCourseNode.java   |  17 +-
 .../run/navigation/NavigationHandler.java     |  21 +-
 .../org/olat/upgrade/OLATUpgrade_13_2_8.java  | 115 +++++++++++
 .../olat/upgrade/_spring/upgradeContext.xml   |   1 +
 9 files changed, 210 insertions(+), 172 deletions(-)
 create mode 100644 src/main/java/org/olat/upgrade/OLATUpgrade_13_2_8.java

diff --git a/src/main/java/de/bps/course/nodes/CourseNodePasswordManager.java b/src/main/java/de/bps/course/nodes/CourseNodePasswordManager.java
index 4d28edabea7..080d1af168d 100644
--- a/src/main/java/de/bps/course/nodes/CourseNodePasswordManager.java
+++ b/src/main/java/de/bps/course/nodes/CourseNodePasswordManager.java
@@ -20,8 +20,7 @@
 package de.bps.course.nodes;
 
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
-import org.olat.course.condition.additionalconditions.AdditionalConditionAnswerContainer;
+import org.olat.core.id.IdentityEnvironment;
 
 public interface CourseNodePasswordManager {
 	
@@ -30,9 +29,9 @@ public interface CourseNodePasswordManager {
 	 * @param identity
 	 * @return
 	 */
-	public AdditionalConditionAnswerContainer getAnswerContainer(Identity identity);
+	public String getAnswer(IdentityEnvironment identityEnv, Long courseId, String nodeIdentifier);
 	
-	public AdditionalConditionAnswerContainer removeAnswerContainerFromCache(Identity identity);
+	public void removeAnswerContainerFromCache(Identity identity);
 
 	/**
 	 * updates inputted password
@@ -41,12 +40,7 @@ public interface CourseNodePasswordManager {
 	 * @param courseId
 	 * @param value
 	 */
-	public void updatePwd(Identity identity, String nodeIdentifier, Long courseId, String value);
-	
-	/**
-	 * deletes password for a repository entry
-	 * @param key
-	 */
-	public void deleteAllPasswordsFor(OLATResourceable ores);
+	public void updatePwd(IdentityEnvironment identityEnv, String nodeIdentifier, Long courseId, String value);
+
 	
 }
diff --git a/src/main/java/de/bps/course/nodes/CourseNodePasswordManagerImpl.java b/src/main/java/de/bps/course/nodes/CourseNodePasswordManagerImpl.java
index e9d32d402ac..97fd8242af0 100644
--- a/src/main/java/de/bps/course/nodes/CourseNodePasswordManagerImpl.java
+++ b/src/main/java/de/bps/course/nodes/CourseNodePasswordManagerImpl.java
@@ -20,13 +20,11 @@
 package de.bps.course.nodes;
 
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.IdentityEnvironment;
+import org.olat.core.id.Roles;
 import org.olat.course.condition.additionalconditions.AdditionalConditionAnswerContainer;
-import org.olat.course.condition.additionalconditions.PasswordStore;
 import org.olat.course.run.preview.PreviewIdentity;
 import org.olat.properties.Property;
 import org.olat.properties.PropertyManager;
@@ -43,7 +41,7 @@ import org.olat.properties.PropertyManager;
  */
 public class CourseNodePasswordManagerImpl implements CourseNodePasswordManager {
 
-	private final Map<Long, AdditionalConditionAnswerContainer> cache = new ConcurrentHashMap<Long, AdditionalConditionAnswerContainer>();
+	private static final String ATTR_COURSE_NODE_PREFIX = "course-node-password-prfx-";
 
 	private static CourseNodePasswordManagerImpl INSTANCE;
 	static {
@@ -61,41 +59,37 @@ public class CourseNodePasswordManagerImpl implements CourseNodePasswordManager
 		// no public constructor
 	}
 
-	/**
-	 * @see de.bps.course.nodes.CourseNodePasswordManager#getAnswerContainer(org.olat.core.id.Identity)
-	 */
 	@Override
-	public AdditionalConditionAnswerContainer getAnswerContainer(Identity identity) {
-		AdditionalConditionAnswerContainer acac;
-		if(identity == null) {
-			acac = new AdditionalConditionAnswerContainer();
-		} else if (cache.containsKey(identity.getKey())) {
-			acac = cache.get(identity.getKey());
+	public String getAnswer(IdentityEnvironment identityEnv, Long courseId, String nodeIdent) {
+		Identity identity = identityEnv == null ? null : identityEnv.getIdentity();
+		
+		String value;
+		if(identityEnv == null) {
+			value = null;
 		} else {
-			PropertyManager pm = PropertyManager.getInstance();
-			List<Property> properties = pm.listProperties(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME, null, null, AdditionalConditionAnswerContainer.RESOURCE_NAME);
-			if(properties == null) {
-				acac = null;
-			} else {
-				acac = new AdditionalConditionAnswerContainer();
-				for (Object object : properties) {
-					Property property = (Property) object;
-					PasswordStore store = new PasswordStore();
-					store.setPassword(property.getStringValue());
-					store.setCourseId(property.getLongValue());
-					store.setNodeIdent(property.getResourceTypeId());
-					acac.insertAnswer(Long.toString(property.getResourceTypeId()), property.getLongValue(), store);
+			String key = generateKey(courseId, Long.valueOf(nodeIdent));
+			value = identityEnv.getAttributes().get(key);
+			if(value == null && !identityEnv.getRoles().isGuestOnly()) {
+				PropertyManager pm = PropertyManager.getInstance();
+				List<Property> properties = pm.listProperties(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME,
+						Long.valueOf(nodeIdent), null, AdditionalConditionAnswerContainer.RESOURCE_NAME);
+				for (Property property : properties) {
+					String pKey = generateKey(property.getLongValue(), property.getResourceTypeId());
+					identityEnv.getAttributes().put(pKey, property.getStringValue());
 				}
-				cache.put(identity.getKey(), acac);
+				value = identityEnv.getAttributes().get(key);
 			}
 		}
-		return acac;
+		return value;
+	}
+	
+	private String generateKey(Long courseId, Long nodeIdent) {
+		return ATTR_COURSE_NODE_PREFIX + courseId + " " + nodeIdent;
 	}
 
 	@Override
-	public AdditionalConditionAnswerContainer removeAnswerContainerFromCache(Identity identity) {
-		if(identity == null) return null;
-		return cache.remove(identity.getKey());
+	public void removeAnswerContainerFromCache(Identity identity) {
+		//
 	}
 
 	/**
@@ -104,104 +98,52 @@ public class CourseNodePasswordManagerImpl implements CourseNodePasswordManager
 	 * @param identity
 	 * @param answers
 	 */
-	private void persistAnswerContainer(Identity identity, AdditionalConditionAnswerContainer answers) {
-		if(identity instanceof PreviewIdentity) {
-			//preview identity are not persistable
-			cache.put(identity.getKey(), answers);
-		} else if (!answers.isContainerEmpty()) {
-			boolean updateInDatabase = false;
+	private void persistAnswerContainer(IdentityEnvironment identityEnv, Long courseId, Long nodeIdent, String value) {
+		if(identityEnv == null || identityEnv.getRoles() == null
+				|| identityEnv.getIdentity() == null || identityEnv.getAttributes() == null) return;
+		
+		identityEnv.getAttributes().put(generateKey(courseId, nodeIdent), value);
+		
+		Roles roles = identityEnv.getRoles();
+		Identity identity = identityEnv.getIdentity();
+		if(!(identity instanceof PreviewIdentity) && !roles.isGuestOnly()) {
 			PropertyManager pm = PropertyManager.getInstance();
-			Map<String, Object> container = answers.getContainer();
-			for (String key : container.keySet()) {
-				PasswordStore store = (PasswordStore) container.get(key);
-				List<Property> properties = pm.listProperties(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME,
-						Long.valueOf(store.getNodeIdent()), null, AdditionalConditionAnswerContainer.RESOURCE_NAME);
-				if (properties != null && properties.size() > 0) {
-					// it exists properties with this key and from this identity
-					boolean pwdFounded = false;
-					for (Property prop : properties) {
-						if (store.getCourseId().equals(prop.getLongValue())) {
-							if(!store.getPassword().equals(prop.getStringValue())) {
-								// same course id and same node id
-								// not same pwd --> update
-								prop.setStringValue(store.getPassword());
-								pm.updateProperty(prop);
-								updateInDatabase = true;
-							}
-							// same store
-							pwdFounded = true;
-							break;
+			List<Property> properties = pm.listProperties(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME,
+					nodeIdent, null, AdditionalConditionAnswerContainer.RESOURCE_NAME);
+			if (properties != null && !properties.isEmpty()) {
+				// it exists properties with this key and from this identity
+				boolean pwdFounded = false;
+				for (Property prop : properties) {
+					if (courseId.equals(prop.getLongValue())) {
+						if(!value.equals(prop.getStringValue())) {
+							// same course id and same node id
+							// not same pwd --> update
+							prop.setStringValue(value);
+							pm.updateProperty(prop);
 						}
+						// same store
+						pwdFounded = true;
+						break;
 					}
-					if (!pwdFounded) {
-						Property p = pm.createUserPropertyInstance(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME, null, store.getCourseId(),
-								store.getPassword(), null);
-						p.setResourceTypeName(AdditionalConditionAnswerContainer.RESOURCE_NAME);
-						p.setResourceTypeId(Long.valueOf(store.getNodeIdent()));
-						pm.saveProperty(p);
-						updateInDatabase = true;
-					}
-				} else {
-					// it exists nothing properties with this key and from this identity
-					Property p = pm.createUserPropertyInstance(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME, null, store.getCourseId(),
-							store.getPassword(), null);
+				}
+				if (!pwdFounded) {
+					Property p = pm.createUserPropertyInstance(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME, null, courseId, value, null);
 					p.setResourceTypeName(AdditionalConditionAnswerContainer.RESOURCE_NAME);
-					p.setResourceTypeId(Long.valueOf(store.getNodeIdent()));
+					p.setResourceTypeId(nodeIdent);
 					pm.saveProperty(p);
-					updateInDatabase = true;
 				}
-			}
-			if (updateInDatabase) {
-				cache.put(identity.getKey(), answers);
+			} else {
+				// it exists nothing properties with this key and from this identity
+				Property p = pm.createUserPropertyInstance(identity, null, AdditionalConditionAnswerContainer.RESOURCE_NAME, null, courseId, value, null);
+				p.setResourceTypeName(AdditionalConditionAnswerContainer.RESOURCE_NAME);
+				p.setResourceTypeId(nodeIdent);
+				pm.saveProperty(p);
 			}
 		}
 	}
 
-	/**
-	 * @see de.bps.course.nodes.CourseNodePasswordManager#updatePwd(org.olat.core.id.Identity, java.lang.String, java.lang.String, java.lang.String)
-	 */
 	@Override
-	public void updatePwd(Identity identity, String nodeIdentifier, Long courseId, String value) {
-		AdditionalConditionAnswerContainer answers = getAnswerContainer(identity);
-
-		if (answers == null) {
-			answers = new AdditionalConditionAnswerContainer();
-		}
-		PasswordStore pwdStore = (PasswordStore)answers.getAnswers(nodeIdentifier, courseId);
-		
-		if(pwdStore != null) {
-			pwdStore.setPassword(value);
-		} else {
-			PasswordStore store = new PasswordStore();
-			store.setPassword(value);
-			store.setNodeIdent(Long.valueOf(nodeIdentifier));
-			store.setCourseId(Long.valueOf(courseId));
-			answers.insertAnswer(nodeIdentifier, courseId, store);
-		}
-		persistAnswerContainer(identity, answers);
-	}
-
-	/**
-	 * @see de.bps.course.nodes.CourseNodePasswordManager#deleteAllPasswordsFor(java.lang.Long)
-	 */
-	public void deleteAllPasswordsFor(OLATResourceable ores) {
-		PropertyManager pm = PropertyManager.getInstance();
-		List<Property> properties = pm.listProperties(null, null, AdditionalConditionAnswerContainer.RESOURCE_NAME,
-				null, null, AdditionalConditionAnswerContainer.RESOURCE_NAME, ores.getResourceableId(), null);
-		for (Property p : properties) {
-			Long nodeId = p.getResourceTypeId();
-			Long courseId = p.getLongValue();
-			removeAnswers(nodeId, courseId);
-			pm.deleteProperty(p);
-		}
-	}
-
-	private void removeAnswers(Long nodeId, Long courseId) {
-		for (Long key : cache.keySet()) {
-			AdditionalConditionAnswerContainer acac = cache.get(key);
-			if (acac.containsAnswer(Long.toString(nodeId), courseId)) {
-				acac.removeAnswer(Long.toString(nodeId), courseId);
-			}
-		}
+	public void updatePwd(IdentityEnvironment identityEnv, String nodeIdentifier, Long courseId, String value) {
+		persistAnswerContainer(identityEnv, courseId, Long.valueOf(nodeIdentifier), value);
 	}
 }
diff --git a/src/main/java/org/olat/course/condition/additionalconditions/AdditionalConditionManager.java b/src/main/java/org/olat/course/condition/additionalconditions/AdditionalConditionManager.java
index 12191c0779a..56df4fb5160 100644
--- a/src/main/java/org/olat/course/condition/additionalconditions/AdditionalConditionManager.java
+++ b/src/main/java/org/olat/course/condition/additionalconditions/AdditionalConditionManager.java
@@ -22,6 +22,7 @@ package org.olat.course.condition.additionalconditions;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.id.IdentityEnvironment;
 import org.olat.course.nodes.AbstractAccessableCourseNode;
 import org.olat.course.nodes.CourseNodeConfiguration;
 import org.olat.course.nodes.CourseNodeFactory;
@@ -31,12 +32,12 @@ import org.olat.course.run.userview.UserCourseEnvironment;
 public class AdditionalConditionManager {
 	
 	private AbstractAccessableCourseNode node ;
-	private final AdditionalConditionAnswerContainer answers;
+	private final IdentityEnvironment identityEnv;
 	private Long courseId;
 	
-	public AdditionalConditionManager(AbstractAccessableCourseNode node, Long courseId, AdditionalConditionAnswerContainer answers){
+	public AdditionalConditionManager(AbstractAccessableCourseNode node, Long courseId, IdentityEnvironment identityEnv) {
 		this.node = node;
-		this.answers = answers;
+		this.identityEnv = identityEnv;
 		this.courseId = courseId;
 	}
 	
@@ -45,7 +46,7 @@ public class AdditionalConditionManager {
 		for(AdditionalCondition cond : node.getAdditionalConditions()) {
 			cond.setNode(node);
 			cond.setCourseId(courseId);
-			retVal = cond.evaluate(answers);
+			retVal = cond.evaluate(identityEnv);
 			//otherwise all users on this node can enter the course if one user had known the correct answer 
 			if(!retVal) {
 				break;
@@ -66,7 +67,7 @@ public class AdditionalConditionManager {
 		for(AdditionalCondition cond : node.getAdditionalConditions()){
 			cond.setNode(node);
 			cond.setCourseId(courseId);
-			boolean retVal = cond.evaluate(answers);
+			boolean retVal = cond.evaluate(identityEnv);
 			if(!retVal) {
 				Controller ctrl = cond.getUserInputController(ureq, wControl, userCourseEnv);
 				CourseNodeConfiguration config = CourseNodeFactory.getInstance().getCourseNodeConfiguration(node.getType());
diff --git a/src/main/java/org/olat/course/condition/additionalconditions/PasswordCondition.java b/src/main/java/org/olat/course/condition/additionalconditions/PasswordCondition.java
index 632208a1db4..6b4ed1cbbad 100644
--- a/src/main/java/org/olat/course/condition/additionalconditions/PasswordCondition.java
+++ b/src/main/java/org/olat/course/condition/additionalconditions/PasswordCondition.java
@@ -22,9 +22,12 @@ package org.olat.course.condition.additionalconditions;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.id.IdentityEnvironment;
 import org.olat.course.nodes.AbstractAccessableCourseNode;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
+import de.bps.course.nodes.CourseNodePasswordManagerImpl;
+
 /**
  * Only a placeholder to import courses from other vendors
  * 
@@ -41,7 +44,7 @@ public class PasswordCondition extends AdditionalCondition {
 	@SuppressWarnings("unused") @Deprecated
 	private String answer;
 	
-	public final static String PASSWORD_ENDING = "password";
+	public static final String PASSWORD_ENDING = "password";
 	// </OLATCE-91>
 
 	public AbstractAccessableCourseNode getNode() {
@@ -52,17 +55,13 @@ public class PasswordCondition extends AdditionalCondition {
 	@Override
 	public boolean evaluate(Object userAnswerObj) {
 		String userAnswer = null;
-		if(userAnswerObj instanceof AdditionalConditionAnswerContainer) {
-			AdditionalConditionAnswerContainer answersContainer = (AdditionalConditionAnswerContainer)userAnswerObj;
-			Object obj = answersContainer.getAnswers(node.getIdent(), courseId); 
-			if(obj instanceof PasswordStore){
-				userAnswer = ((PasswordStore)obj).getPassword();
-			}
+		if(userAnswerObj instanceof IdentityEnvironment) {
+			IdentityEnvironment identityEnv = (IdentityEnvironment)userAnswerObj;
+			userAnswer = CourseNodePasswordManagerImpl.getInstance().getAnswer(identityEnv, courseId, node.getIdent());
 		} else if(userAnswerObj instanceof String) {
 			userAnswer = (String)userAnswerObj;
 		}
-
-		return password==null ? true : password.equals(userAnswer); 
+		return password == null || password.equals(userAnswer); 
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/condition/additionalconditions/PasswordVerificationController.java b/src/main/java/org/olat/course/condition/additionalconditions/PasswordVerificationController.java
index dc0e3f3a0c3..c009f612c15 100644
--- a/src/main/java/org/olat/course/condition/additionalconditions/PasswordVerificationController.java
+++ b/src/main/java/org/olat/course/condition/additionalconditions/PasswordVerificationController.java
@@ -91,7 +91,7 @@ public class PasswordVerificationController extends FormBasicController {
 			if (valid) {
 				CourseNodePasswordManager cnpm = CourseNodePasswordManagerImpl.getInstance();
 				//used the identity of the user course environment for the preview of courses
-				cnpm.updatePwd(userCourseEnv.getIdentityEnvironment().getIdentity(), condition.getNodeIdentifier(), condition.getCourseId(), pwElement.getValue());
+				cnpm.updatePwd(userCourseEnv.getIdentityEnvironment(), condition.getNodeIdentifier(), condition.getCourseId(), pwElement.getValue());
 			} else {
 				pwElement.setErrorKey("password.incorrect", new String[0]);
 			}
diff --git a/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java b/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java
index 3fe5d4c33b0..b2266f4cb56 100644
--- a/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java
@@ -28,19 +28,16 @@ package org.olat.course.nodes;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.olat.core.id.Identity;
+import org.olat.core.id.IdentityEnvironment;
 import org.olat.course.ICourse;
 import org.olat.course.condition.Condition;
 import org.olat.course.condition.additionalconditions.AdditionalCondition;
-import org.olat.course.condition.additionalconditions.AdditionalConditionAnswerContainer;
 import org.olat.course.condition.additionalconditions.AdditionalConditionManager;
 import org.olat.course.condition.interpreter.ConditionExpression;
 import org.olat.course.condition.interpreter.ConditionInterpreter;
 import org.olat.course.export.CourseEnvironmentMapper;
 import org.olat.course.run.userview.NodeEvaluation;
 
-import de.bps.course.nodes.CourseNodePasswordManagerImpl;
-
 /**
  * Initial Date: May 28, 2004
  * 
@@ -120,21 +117,19 @@ public abstract class AbstractAccessableCourseNode extends GenericCourseNode {
 	protected void calcAccessAndVisibility(ConditionInterpreter ci, NodeEvaluation nodeEval) {
 		// </OLATCE-91>
 		// for this node: only one role: accessing the node
-		boolean accessible = (getPreConditionAccess().getConditionExpression() == null ? true : ci.evaluateCondition(getPreConditionAccess()));
+		boolean accessible = getPreConditionAccess().getConditionExpression() == null || ci.evaluateCondition(getPreConditionAccess());
 		// <OLATCE-91>
 		if(accessible){
 			Long courseId = ci.getUserCourseEnvironment().getCourseEnvironment().getCourseResourceableId();
-			Identity identity = ci.getUserCourseEnvironment().getIdentityEnvironment().getIdentity();
-			AdditionalConditionAnswerContainer answers= CourseNodePasswordManagerImpl.getInstance().getAnswerContainer(identity);
-
+			IdentityEnvironment identityEnv = ci.getUserCourseEnvironment().getIdentityEnvironment();
 			nodeEval.putAccessStatus(BLOCKED_BY_ORIGINAL_ACCESS_RULES, false);
-			AdditionalConditionManager addMan = new AdditionalConditionManager(this, courseId, answers);
+			AdditionalConditionManager addMan = new AdditionalConditionManager(this, courseId, identityEnv);
 			accessible = addMan.evaluateConditions();
 		}
 		// </OLATCE-91>
 		nodeEval.putAccessStatus("access", accessible);
-		boolean visible = (getPreConditionVisibility().getConditionExpression() == null ? true : ci
-				.evaluateCondition(getPreConditionVisibility()));
+		boolean visible = getPreConditionVisibility().getConditionExpression() == null
+				|| ci.evaluateCondition(getPreConditionVisibility());
 		nodeEval.setVisible(visible);
 	}
 
diff --git a/src/main/java/org/olat/course/run/navigation/NavigationHandler.java b/src/main/java/org/olat/course/run/navigation/NavigationHandler.java
index 4f5facdf7c0..410d65c8787 100644
--- a/src/main/java/org/olat/course/run/navigation/NavigationHandler.java
+++ b/src/main/java/org/olat/course/run/navigation/NavigationHandler.java
@@ -47,7 +47,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.messages.MessageUIFactory;
 import org.olat.core.gui.control.generic.title.TitledWrapperController;
 import org.olat.core.gui.translator.Translator;
-import org.olat.core.id.Identity;
+import org.olat.core.id.IdentityEnvironment;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.BusinessControlFactory;
 import org.olat.core.id.context.ContextEntry;
@@ -61,7 +61,6 @@ import org.olat.core.util.Util;
 import org.olat.core.util.nodes.INode;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.xml.XStreamHelper;
-import org.olat.course.condition.additionalconditions.AdditionalConditionAnswerContainer;
 import org.olat.course.condition.additionalconditions.AdditionalConditionManager;
 import org.olat.course.editor.EditorMainController;
 import org.olat.course.nodes.AbstractAccessableCourseNode;
@@ -75,13 +74,8 @@ import org.olat.course.run.userview.TreeFilter;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.util.logging.activity.LoggingResourceable;
 
-import de.bps.course.nodes.CourseNodePasswordManager;
-import de.bps.course.nodes.CourseNodePasswordManagerImpl;
-
 
 /**
- * Description: <br>
- * TODO: Felix Jost Class Description for NavigationHandler
  * Initial Date: 19.01.2005 <br>
  * @author Felix Jost
  */
@@ -93,9 +87,9 @@ public class NavigationHandler implements Disposable {
 	
 	private String selectedCourseNodeId;
 	private TreeFilter filter;
-	private Set<String> openCourseNodeIds = new HashSet<String>();
-	private List<String> openTreeNodeIds = new ArrayList<String>();
-	private Map<String,SubTree> externalTreeModels = new HashMap<String,SubTree>();
+	private Set<String> openCourseNodeIds = new HashSet<>();
+	private List<String> openTreeNodeIds = new ArrayList<>();
+	private Map<String,SubTree> externalTreeModels = new HashMap<>();
 
 	/**
 	 * @param userCourseEnv
@@ -181,7 +175,6 @@ public class NavigationHandler implements Disposable {
 			}
 			
 			if (subtreemodelListener == null) {
-				//throw new AssertException("no handler for subtreemodelcall!");
 				//reattach the subtreemodellistener
 				TreeNode internNode = getFirstInternParentNode(selTN);
 				NodeEvaluation prevEval = (NodeEvaluation) internNode.getUserObject();
@@ -374,10 +367,8 @@ public class NavigationHandler implements Disposable {
 			AdditionalConditionManager addMan = null;
 			if (courseNode instanceof AbstractAccessableCourseNode) {
 				Long courseId = userCourseEnv.getCourseEnvironment().getCourseResourceableId();
-				CourseNodePasswordManager cnpm = CourseNodePasswordManagerImpl.getInstance();
-				Identity identity = userCourseEnv.getIdentityEnvironment().getIdentity();
-				AdditionalConditionAnswerContainer answerContainer = cnpm.getAnswerContainer(identity);
-				addMan = new AdditionalConditionManager( (AbstractAccessableCourseNode) courseNode, courseId, answerContainer);
+				IdentityEnvironment identityEnv = userCourseEnv.getIdentityEnvironment();
+				addMan = new AdditionalConditionManager((AbstractAccessableCourseNode)courseNode, courseId, identityEnv);
 			}
 			
 			if (!mayAccessWholeTreeUp|| (addMan != null && !addMan.evaluateConditions())) {
diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_13_2_8.java b/src/main/java/org/olat/upgrade/OLATUpgrade_13_2_8.java
new file mode 100644
index 00000000000..6b836ff7e57
--- /dev/null
+++ b/src/main/java/org/olat/upgrade/OLATUpgrade_13_2_8.java
@@ -0,0 +1,115 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.upgrade;
+
+import java.util.List;
+
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.OrganisationRoles;
+import org.olat.basesecurity.SearchIdentityParams;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.course.condition.additionalconditions.AdditionalConditionAnswerContainer;
+import org.olat.properties.Property;
+import org.olat.properties.PropertyManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 3 avr. 2019<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class OLATUpgrade_13_2_8 extends OLATUpgrade {
+	
+	private static final String VERSION = "OLAT_13.2.8";
+	private static final String GUEST_COURSE_NODES_PASSWORDS = "GUEST COURSE NODES PASSWORDS";
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
+	private PropertyManager propertyManager;
+	
+	public OLATUpgrade_13_2_8() {
+		super();
+	}
+	
+	@Override
+	public String getVersion() {
+		return VERSION;
+	}
+
+	@Override
+	public boolean doPreSystemInitUpgrade(UpgradeManager upgradeManager) {
+		return false;
+	}
+
+	@Override
+	public boolean doPostSystemInitUpgrade(UpgradeManager upgradeManager) {
+		UpgradeHistoryData uhd = upgradeManager.getUpgradesHistory(VERSION);
+		if (uhd == null) {
+			// has never been called, initialize
+			uhd = new UpgradeHistoryData();
+		} else if (uhd.isInstallationComplete()) {
+			return false;
+		}
+		
+		boolean allOk = true;
+		allOk &= deleteCourseNodePassworsForGuests(upgradeManager, uhd);
+
+		uhd.setInstallationComplete(allOk);
+		upgradeManager.setUpgradesHistory(uhd, VERSION);
+		if(allOk) {
+			log.audit("Finished OLATUpgrade_13_2_8 successfully!");
+		} else {
+			log.audit("OLATUpgrade_13_2_8 not finished, try to restart OpenOLAT!");
+		}
+		return allOk;
+	}
+	
+	/**
+	 * Find identities without organizations but not deleted.
+	 * 
+	 * @param upgradeManager The upgrade manager
+	 * @param uhd The upgrade history
+	 * @return true if successful
+	 */
+	private boolean deleteCourseNodePassworsForGuests(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
+		boolean allOk = true;
+		if (!uhd.getBooleanDataValue(GUEST_COURSE_NODES_PASSWORDS)) {
+			SearchIdentityParams params = new SearchIdentityParams();
+			params.setRoles(new OrganisationRoles[] { OrganisationRoles.guest });
+			List<Identity> guests = securityManager.getIdentitiesByPowerSearch(params, 0, -1);
+			for(Identity guest:guests) {
+				List<Property> properties = propertyManager.listProperties(guest, null, AdditionalConditionAnswerContainer.RESOURCE_NAME,
+						null, null, AdditionalConditionAnswerContainer.RESOURCE_NAME);
+				for(Property property:properties) {
+					propertyManager.deleteProperty(property);
+				}
+				dbInstance.commitAndCloseSession();
+			}
+			uhd.setBooleanDataValue(GUEST_COURSE_NODES_PASSWORDS, allOk);
+			upgradeManager.setUpgradesHistory(uhd, VERSION);
+		}
+		return allOk;
+	}
+}
diff --git a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml
index c834bd3f056..1033fccf9e1 100644
--- a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml
+++ b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml
@@ -48,6 +48,7 @@
 				<bean id="upgrade_13_1_0" class="org.olat.upgrade.OLATUpgrade_13_1_0"/>
 				<bean id="upgrade_13_2_0" class="org.olat.upgrade.OLATUpgrade_13_2_0"/>
 				<bean id="upgrade_13_2_4" class="org.olat.upgrade.OLATUpgrade_13_2_4"/>
+				<bean id="upgrade_13_2_8" class="org.olat.upgrade.OLATUpgrade_13_2_8"/>
 			</list>
 		</property>
 	</bean>
-- 
GitLab