From 8c19de3c2ac12b21ff24b44a6640dcf0bee83a7a Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 27 Jun 2013 15:38:26 +0200
Subject: [PATCH] OO-627: implement data protection feature for "last visit" in
 course, group and repository member management

---
 .../admin/privacy/PrivacyAdminController.java | 28 ++++--
 .../privacy/_i18n/LocalStrings_de.properties  |  1 +
 .../olat/basesecurity/BaseSecurityModule.java | 99 +++++++++++++++++++
 .../_spring/baseSecurityContext.xml           |  6 ++
 .../ui/main/AbstractMemberListController.java | 11 ++-
 .../resources/serviceconfig/olat.properties   | 15 ++-
 6 files changed, 148 insertions(+), 12 deletions(-)

diff --git a/src/main/java/org/olat/admin/privacy/PrivacyAdminController.java b/src/main/java/org/olat/admin/privacy/PrivacyAdminController.java
index a605ee7418a..7817c14bf6d 100644
--- a/src/main/java/org/olat/admin/privacy/PrivacyAdminController.java
+++ b/src/main/java/org/olat/admin/privacy/PrivacyAdminController.java
@@ -39,6 +39,7 @@ import org.olat.core.gui.control.WindowControl;
 public class PrivacyAdminController extends FormBasicController {
 	
 	private MultipleSelectionElement adminPropsEl;
+	private MultipleSelectionElement lastloginEl;
 
 	private final BaseSecurityModule module;
 	
@@ -71,6 +72,14 @@ public class PrivacyAdminController extends FormBasicController {
 		adminPropsEl.select("groupmanagers", "enabled".equals(module.getUserSearchAdminPropsForGroupmanagers()));
 		adminPropsEl.select("administrators", "enabled".equals(module.getUserSearchAdminPropsForAdministrators()));
 		adminPropsEl.addActionListener(this, FormEvent.ONCHANGE);
+
+		lastloginEl = uifactory.addCheckboxesVertical("last.login", formLayout, adminPropKeys, adminPropValues, null, 1);
+		lastloginEl.select("users", "enabled".equals(module.getUserLastLoginVisibleForUsers()));
+		lastloginEl.select("authors", "enabled".equals(module.getUserLastLoginVisibleForAuthors()));
+		lastloginEl.select("usermanagers", "enabled".equals(module.getUserLastLoginVisibleForUsermanagers()));
+		lastloginEl.select("groupmanagers", "enabled".equals(module.getUserLastLoginVisibleForGroupmanagers()));
+		lastloginEl.select("administrators", "enabled".equals(module.getUserLastLoginVisibleForAdministrators()));
+		lastloginEl.addActionListener(this, FormEvent.ONCHANGE);
 	}
 	
 	@Override
@@ -81,12 +90,19 @@ public class PrivacyAdminController extends FormBasicController {
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(source == adminPropsEl) {
-			Set<String> enrolmentSelectedKeys = adminPropsEl.getSelectedKeys();
-			module.setUserSearchAdminPropsForUsers(enrolmentSelectedKeys.contains("users") ? "enabled" : "disabled");
-			module.setUserSearchAdminPropsForAuthors(enrolmentSelectedKeys.contains("authors") ? "enabled" : "disabled");
-			module.setUserSearchAdminPropsForUsermanagers(enrolmentSelectedKeys.contains("usermanagers") ? "enabled" : "disabled");
-			module.setUserSearchAdminPropsForGroupmanagers(enrolmentSelectedKeys.contains("groupmanagers") ? "enabled" : "disabled");
-			module.setUserSearchAdminPropsForAdministrators(enrolmentSelectedKeys.contains("administrators") ? "enabled" : "disabled");
+			Set<String> selectedKeys = adminPropsEl.getSelectedKeys();
+			module.setUserSearchAdminPropsForUsers(selectedKeys.contains("users") ? "enabled" : "disabled");
+			module.setUserSearchAdminPropsForAuthors(selectedKeys.contains("authors") ? "enabled" : "disabled");
+			module.setUserSearchAdminPropsForUsermanagers(selectedKeys.contains("usermanagers") ? "enabled" : "disabled");
+			module.setUserSearchAdminPropsForGroupmanagers(selectedKeys.contains("groupmanagers") ? "enabled" : "disabled");
+			module.setUserSearchAdminPropsForAdministrators(selectedKeys.contains("administrators") ? "enabled" : "disabled");
+		} else if(source == lastloginEl) {
+			Set<String> selectedKeys = lastloginEl.getSelectedKeys();
+			module.setUserLastLoginVisibleForUsers(selectedKeys.contains("users") ? "enabled" : "disabled");
+			module.setUserLastLoginVisibleForAuthors(selectedKeys.contains("authors") ? "enabled" : "disabled");
+			module.setUserLastLoginVisibleForUsermanagers(selectedKeys.contains("usermanagers") ? "enabled" : "disabled");
+			module.setUserLastLoginVisibleForGroupmanagers(selectedKeys.contains("groupmanagers") ? "enabled" : "disabled");
+			module.setUserLastLoginVisibleForAdministrators(selectedKeys.contains("administrators") ? "enabled" : "disabled");
 		}
 	}
 
diff --git a/src/main/java/org/olat/admin/privacy/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/privacy/_i18n/LocalStrings_de.properties
index c4edfc67c95..6e3e789105b 100644
--- a/src/main/java/org/olat/admin/privacy/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/admin/privacy/_i18n/LocalStrings_de.properties
@@ -1,6 +1,7 @@
 #Mon Mar 02 09:54:03 CET 2009
 admin.menu.title=Datenschutz
 admin.menu.title.alt=Datenschutz
+last.login=Last visit
 admin.props=Admin. properties
 admin.props.desc=Roles die den Admin. Properties sehen darf.			
 admin.props.administrators=Systemadministratoren
diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityModule.java b/src/main/java/org/olat/basesecurity/BaseSecurityModule.java
index 5a5802efaee..90244aa75e8 100644
--- a/src/main/java/org/olat/basesecurity/BaseSecurityModule.java
+++ b/src/main/java/org/olat/basesecurity/BaseSecurityModule.java
@@ -64,6 +64,12 @@ public class BaseSecurityModule extends AbstractOLATModule {
 	private static final String USERSEARCH_ADMINPROPS_USERMANAGERS = "userSearchAdminPropsForUsermanagers";
 	private static final String USERSEARCH_ADMINPROPS_GROUPMANAGERS = "userSearchAdminPropsForGroupmanagers";
 	private static final String USERSEARCH_ADMINPROPS_ADMINISTRATORS = "userSearchAdminPropsForAdministrators";
+	
+	private static final String USER_LASTLOGIN_VISIBLE_USERS = "userLastLoginVisibleForUsers";
+	private static final String USER_LASTLOGIN_VISIBLE_AUTHORS = "userLastLoginVisibleForAuthors";
+	private static final String USER_LASTLOGIN_VISIBLE_USERMANAGERS = "userLastLoginVisibleForUsermanagers";
+	private static final String USER_LASTLOGIN_VISIBLE_GROUPMANAGERS = "userLastLoginVisibleForGroupmanagers";
+	private static final String USER_LASTLOGIN_VISIBLE_ADMINISTRATORS = "userLastLoginVisibleForAdministrators";
 
 	private static final String USERSEARCHAUTOCOMPLETE_USERS = "userSearchAutocompleteForUsers";
 	private static final String USERSEARCHAUTOCOMPLETE_AUTHORS = "userSearchAutocompleteForAuthors";
@@ -101,6 +107,12 @@ public class BaseSecurityModule extends AbstractOLATModule {
 	private String userSearchAdminPropsForGroupmanagers;
 	private String userSearchAdminPropsForAdministrators;
 	
+	private String userLastLoginVisibleForUsers;
+	private String userLastLoginVisibleForAuthors;
+	private String userLastLoginVisibleForUsermanagers;
+	private String userLastLoginVisibleForGroupmanagers;
+	private String userLastLoginVisibleForAdministrators;
+	
 	private String userSearchMaxResults;
 	private String userSearchAutocompleteForUsers;
 	private String userSearchAutocompleteForAuthors;
@@ -158,6 +170,12 @@ public class BaseSecurityModule extends AbstractOLATModule {
 		userSearchAdminPropsForGroupmanagers = getStringConfigParameter(USERSEARCH_ADMINPROPS_GROUPMANAGERS, "enabled", true);
 		userSearchAdminPropsForAdministrators = getStringConfigParameter(USERSEARCH_ADMINPROPS_ADMINISTRATORS, "enabled", true);
 
+		userLastLoginVisibleForUsers = getStringConfigParameter(USER_LASTLOGIN_VISIBLE_USERS, "disabled", true);
+		userLastLoginVisibleForAuthors = getStringConfigParameter(USER_LASTLOGIN_VISIBLE_AUTHORS, "enabled", true);
+		userLastLoginVisibleForUsermanagers = getStringConfigParameter(USER_LASTLOGIN_VISIBLE_USERMANAGERS, "enabled", true);
+		userLastLoginVisibleForGroupmanagers = getStringConfigParameter(USER_LASTLOGIN_VISIBLE_GROUPMANAGERS, "enabled", true);
+		userLastLoginVisibleForAdministrators = getStringConfigParameter(USER_LASTLOGIN_VISIBLE_ADMINISTRATORS, "enabled", true);
+
 		userSearchAutocompleteForUsers = getStringConfigParameter(USERSEARCHAUTOCOMPLETE_USERS, "enabled", true);
 		userSearchAutocompleteForAuthors = getStringConfigParameter(USERSEARCHAUTOCOMPLETE_AUTHORS, "enabled", true);
 		userSearchAutocompleteForUsermanagers = getStringConfigParameter(USERSEARCHAUTOCOMPLETE_USERMANAGERS, "enabled", true);
@@ -192,6 +210,27 @@ public class BaseSecurityModule extends AbstractOLATModule {
 		if(StringHelper.containsNonWhitespace(enabled)) {
 			userSearchAdminPropsForAdministrators = enabled;
 		}
+		
+		enabled = getStringPropertyValue(USER_LASTLOGIN_VISIBLE_USERS, true);
+		if(StringHelper.containsNonWhitespace(enabled)) {
+			userLastLoginVisibleForUsers = enabled;
+		}
+		enabled = getStringPropertyValue(USER_LASTLOGIN_VISIBLE_AUTHORS, true);
+		if(StringHelper.containsNonWhitespace(enabled)) {
+			userLastLoginVisibleForAuthors = enabled;
+		}
+		enabled = getStringPropertyValue(USER_LASTLOGIN_VISIBLE_USERMANAGERS, true);
+		if(StringHelper.containsNonWhitespace(enabled)) {
+			userLastLoginVisibleForUsermanagers = enabled;
+		}
+		enabled = getStringPropertyValue(USER_LASTLOGIN_VISIBLE_GROUPMANAGERS, true);
+		if(StringHelper.containsNonWhitespace(enabled)) {
+			userLastLoginVisibleForGroupmanagers = enabled;
+		}
+		enabled = getStringPropertyValue(USER_LASTLOGIN_VISIBLE_ADMINISTRATORS, true);
+		if(StringHelper.containsNonWhitespace(enabled)) {
+			userLastLoginVisibleForAdministrators = enabled;
+		}
 
 		enabled = getStringPropertyValue(USERSEARCHAUTOCOMPLETE_USERS, true);
 		if(StringHelper.containsNonWhitespace(enabled)) {
@@ -284,6 +323,66 @@ public class BaseSecurityModule extends AbstractOLATModule {
 	public void setUserSearchAdminPropsForAdministrators(String enable) {
 		setStringProperty(USERSEARCH_ADMINPROPS_ADMINISTRATORS, enable, true);
 	}
+	
+	public boolean isUserLastVisitVisible(Roles roles) {
+		if(roles == null) return false;
+		if(roles.isOLATAdmin()) {
+			return "enabled".equals(userLastLoginVisibleForAdministrators);
+		}
+		if(roles.isGroupManager()) {
+			return "enabled".equals(userLastLoginVisibleForGroupmanagers);
+		}
+		if(roles.isUserManager()) {
+			return "enabled".equals(userLastLoginVisibleForUsermanagers);
+		}
+		if(roles.isAuthor()) {
+			return "enabled".equals(userLastLoginVisibleForAuthors);
+		}
+		if(roles.isInvitee()) {
+			return false;
+		}
+		return "enabled".equals(userLastLoginVisibleForUsers);
+	}
+
+	public String getUserLastLoginVisibleForUsers() {
+		return userLastLoginVisibleForUsers;
+	}
+
+	public void setUserLastLoginVisibleForUsers(String enable) {
+		setStringProperty(USER_LASTLOGIN_VISIBLE_USERS, enable, true);
+	}
+
+	public String getUserLastLoginVisibleForAuthors() {
+		return userLastLoginVisibleForAuthors;
+	}
+
+	public void setUserLastLoginVisibleForAuthors(String enable) {
+		setStringProperty(USER_LASTLOGIN_VISIBLE_AUTHORS, enable, true);
+	}
+
+	public String getUserLastLoginVisibleForUsermanagers() {
+		return userLastLoginVisibleForUsermanagers;
+	}
+
+	public void setUserLastLoginVisibleForUsermanagers(String enable) {
+		setStringProperty(USER_LASTLOGIN_VISIBLE_USERMANAGERS, enable, true);
+	}
+
+	public String getUserLastLoginVisibleForGroupmanagers() {
+		return userLastLoginVisibleForGroupmanagers;
+	}
+
+	public void setUserLastLoginVisibleForGroupmanagers(String enable) {
+		setStringProperty(USER_LASTLOGIN_VISIBLE_GROUPMANAGERS, enable, true);
+	}
+
+	public String getUserLastLoginVisibleForAdministrators() {
+		return userLastLoginVisibleForAdministrators;
+	}
+
+	public void setUserLastLoginVisibleForAdministrators(String enable) {
+		setStringProperty(USER_LASTLOGIN_VISIBLE_ADMINISTRATORS, enable, true);
+	}
 
 	public boolean isUserAllowedAutoComplete(Roles roles) {
 		if(roles == null) return false;
diff --git a/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml b/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml
index fd5d28d8981..693e5b3eeb2 100644
--- a/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml
+++ b/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml
@@ -38,6 +38,12 @@
 						userSearchAdminPropsForGroupmanagers=${usersearch.adminProps.groupmanagers}
 						userSearchAdminPropsForAdministrators=${usersearch.adminProps.administrators}
 						
+						userLastLoginVisibleForUsers=${user.lastlogin.visible.users}
+						userLastLoginVisibleForAuthors=${user.lastlogin.visible.authors}
+						userLastLoginVisibleForUsermanagers=${user.lastlogin.visible.usermanagers}
+						userLastLoginVisibleForGroupmanagers=${user.lastlogin.visible.groupmanagers}
+						userLastLoginVisibleForAdministrators=${user.lastlogin.visible.administrators}
+						
 						userSearchAutocompleteForUsers=${usersearch.autocomplete.users}
 						userSearchAutocompleteForAuthors=${usersearch.autocomplete.authors}
 						userSearchAutocompleteForUsermanagers=${usersearch.autocomplete.usermanagers}
diff --git a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
index a508de1b557..972d493216e 100644
--- a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
+++ b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
@@ -56,6 +56,7 @@ import org.olat.core.gui.control.generic.dtabs.Activateable2;
 import org.olat.core.gui.control.generic.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.id.Identity;
+import org.olat.core.id.Roles;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.core.util.StringHelper;
@@ -115,6 +116,7 @@ public abstract class AbstractMemberListController extends BasicController imple
 
 	private final RepositoryEntry repoEntry;
 	private final BusinessGroup businessGroup;
+	private final boolean isLastVisitVisible;
 	private final boolean isAdministrativeUser;
 	private final boolean chatEnabled;
 	
@@ -159,8 +161,10 @@ public abstract class AbstractMemberListController extends BasicController imple
 		sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class);
 		memberViewComparator = new GroupMemberViewComparator(Collator.getInstance(getLocale()));
 		
+		Roles roles = ureq.getUserSession().getRoles();
 		chatEnabled = imModule.isEnabled() && imModule.isPrivateEnabled();
-		isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
+		isAdministrativeUser = securityModule.isUserAllowedAdminProps(roles);
+		isLastVisitVisible = securityModule.isUserLastVisitVisible(roles);
 		mainVC = createVelocityContainer(page);
 
 		//table
@@ -207,7 +211,10 @@ public abstract class AbstractMemberListController extends BasicController imple
 		}
 		
 		memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.firstTime.i18n(), Cols.firstTime.ordinal(), null, getLocale()));
-		memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
+		if(isLastVisitVisible) {
+			memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
+		}
+		
 		CustomCellRenderer roleRenderer = new CourseRoleCellRenderer(getLocale());
 		memberListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer) {
 			@Override
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index b00ac26c043..a139d207c5a 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -542,22 +542,29 @@ i18n.application.src.dir=
 i18n.application.opt.src.dir = ${i18n.application.src.dir}
 
 ########################################################################
-# User search
+# User search / privacy
 ########################################################################
-#whic roles see the administrative user properties
+# which roles see the administrative user properties
 usersearch.adminProps.users=disabled
 usersearch.adminProps.authors=enabled
 usersearch.adminProps.usermanagers=enabled
 usersearch.adminProps.groupmanagers=enabled
 usersearch.adminProps.administrators=enabled
 
-#which roles see the autocompletion
+# which roles are allowed to see the last visited date of group, course and other learning resources
+user.lastlogin.visible.users=disabled
+user.lastlogin.visible.authors=enabled
+user.lastlogin.visible.usermanagers=enabled
+user.lastlogin.visible.groupmanagers=enabled
+user.lastlogin.visible.administrators=enabled
+
+# which roles see the autocompletion
 usersearch.autocomplete.users=enabled
 usersearch.autocomplete.authors=enabled
 usersearch.autocomplete.usermanagers=enabled
 usersearch.autocomplete.groupmanagers=enabled
 usersearch.autocomplete.administrators=enabled
-#the maximum of identities returned by search (-1 is unlimited)
+# the maximum of identities returned by search (-1 is unlimited)
 usersearch.maxResults=-1
 usersearch.maxResults.values=-1,20,50
 
-- 
GitLab