/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <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>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.admin.user;
import java.util.List;
import org.olat.admin.user.course.CourseOverviewController;
import org.olat.admin.user.groups.GroupOverviewController;
import org.olat.basesecurity.Authentication;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.BaseSecurityManager;
import org.olat.basesecurity.BaseSecurityModule;
import org.olat.basesecurity.Constants;
import org.olat.basesecurity.SecurityGroup;
import org.olat.core.commons.modules.bc.FolderConfig;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.commons.services.notifications.ui.NotificationSubscriptionController;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.stack.BreadcrumbedStackedPanel;
import org.olat.core.gui.components.tabbedpane.TabbedPane;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.id.Identity;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.core.logging.OLATSecurityException;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.vfs.QuotaManager;
import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListController;
import org.olat.ldap.LDAPLoginManager;
import org.olat.ldap.LDAPLoginModule;
import org.olat.properties.Property;
import org.olat.user.ChangePrefsController;
import org.olat.user.DisplayPortraitController;
import org.olat.user.ProfileAndHomePageEditController;
import org.olat.user.PropFoundEvent;
import org.olat.user.UserPropertiesController;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Initial Date: Jul 29, 2003
* @author Sabina Jeger
* <pre>
* Complete rebuild on 17. jan 2006 by Florian Gnaegi
*
* Functionality to change or view all kind of things for this user
* based on the configuration for the user manager.
* This controller should only be used by the UserAdminMainController.
*
* </pre>
*/
public class UserAdminController extends BasicController implements Activateable2 {
// NLS support
private static final String NLS_ERROR_NOACCESS_TO_USER = "error.noaccess.to.user";
private static final String NLS_FOUND_PROPERTY = "found.property";
private static final String NLS_EDIT_UPROFILE = "edit.uprofile";
private static final String NLS_EDIT_UPREFS = "edit.uprefs";
private static final String NLS_EDIT_UPWD = "edit.upwd";
private static final String NLS_EDIT_UAUTH = "edit.uauth";
private static final String NLS_EDIT_UPROP = "edit.uprop";
private static final String NLS_EDIT_UROLES = "edit.uroles";
private static final String NLS_EDIT_UQUOTA = "edit.uquota";
private static final String NLS_VIEW_GROUPS = "view.groups";
private static final String NLS_VIEW_COURSES = "view.courses";
private static final String NLS_VIEW_EFF_STATEMENTS = "view.effStatements";
private static final String NLS_VIEW_SUBSCRIPTIONS = "view.subscriptions";
private VelocityContainer myContent;
private Identity myIdentity = null;
// controllers used in tabbed pane
private TabbedPane userTabP;
private Controller prefsCtr, propertiesCtr, pwdCtr, quotaCtr, policiesCtr, rolesCtr, userShortDescrCtr;
private DisplayPortraitController portraitCtr;
private UserAuthenticationsEditorController authenticationsCtr;
private Link backLink;
private ProfileAndHomePageEditController userProfileCtr;
private CourseOverviewController courseCtr;
private GroupOverviewController grpCtr;
private CertificateAndEfficiencyStatementListController efficicencyCtrl;
private final boolean isOlatAdmin;
@Autowired
private BaseSecurity securityManager;
@Autowired
private LDAPLoginModule ldapLoginModule;
@Autowired
private LDAPLoginManager ldapLoginManager;
/**
* Constructor that creates a back - link as default
* @param ureq
* @param wControl
* @param identity
*/
public UserAdminController(UserRequest ureq, WindowControl wControl, Identity identity) {
super(ureq, wControl);
isOlatAdmin = ureq.getUserSession().getRoles().isOLATAdmin();
if (!securityManager.isIdentityPermittedOnResourceable(
ureq.getIdentity(),
Constants.PERMISSION_ACCESS,
OresHelper.lookupType(this.getClass()))) {
throw new OLATSecurityException("Insufficient permissions to access UserAdminController");
}
myIdentity = identity;
if (allowedToManageUser(ureq, myIdentity)) {
myContent = createVelocityContainer("udispatcher");
backLink = LinkFactory.createLinkBack(myContent, this);
userShortDescrCtr = new UserShortDescription(ureq, wControl, identity);
myContent.put("userShortDescription", userShortDescrCtr.getInitialComponent());
setBackButtonEnabled(true); // default
initTabbedPane(myIdentity, ureq);
exposeUserDataToVC(ureq, myIdentity);
putInitialPanel(myContent);
} else {
String supportAddr = WebappHelper.getMailConfig("mailSupport");
showWarning(NLS_ERROR_NOACCESS_TO_USER, supportAddr);
putInitialPanel(new Panel("empty"));
}
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
if(entries == null || entries.isEmpty()) return;
String entryPoint = entries.get(0).getOLATResourceable().getResourceableTypeName();
if("tab".equals(entryPoint)) {
userTabP.activate(ureq, entries, state);
} else if("table".equals(entryPoint)) {
if(entries.size() > 2) {
List<ContextEntry> subEntries = entries.subList(2, entries.size());
userTabP.activate(ureq, subEntries, state);
}
} else if (userTabP != null) {
userTabP.setSelectedPane(translate(entryPoint));
}
}
/**
* @param backButtonEnabled
*/
public void setBackButtonEnabled(boolean backButtonEnabled) {
if (myContent != null) {
myContent.contextPut("showButton", Boolean.valueOf(backButtonEnabled));
}
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
*/
@Override
public void event(UserRequest ureq, Component source, Event event) {
if (source == backLink) {
fireEvent(ureq, Event.BACK_EVENT);
} else if (source == userTabP) {
userTabP.addToHistory(ureq, getWindowControl());
}
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
*/
@Override
public void event(UserRequest ureq, Controller source, Event event) {
if (source == propertiesCtr) {
if (event.getCommand().equals("PropFound")){
PropFoundEvent foundEvent = (PropFoundEvent) event;
Property myfoundProperty = foundEvent.getProperty();
this.showInfo(NLS_FOUND_PROPERTY,myfoundProperty.getKey().toString());
}
} else if (source == pwdCtr) {
if (event == Event.DONE_EVENT) {
// rebuild authentication tab, could be wrong now
if (authenticationsCtr != null) authenticationsCtr.rebuildAuthenticationsTableDataModel();
}
} else if (source == userProfileCtr){
if (event == Event.DONE_EVENT){
//reload profile data on top
myIdentity = (Identity) DBFactory.getInstance().loadObject(myIdentity);
exposeUserDataToVC(ureq, myIdentity);
userProfileCtr.resetForm(ureq);
}
}
}
/**
* Check if user allowed to modify this identity. Only modification of user
* that have lower rights is allowed. No one exept admins can manage usermanager
* and admins
* @param ureq
* @param identity
* @return boolean
*/
private boolean allowedToManageUser(UserRequest ureq, Identity identity) {
//fxdiff FXOLAT-184 prevent editing of users that are in frentix-superadmin group (except "frentix" wants to change own profile)
Identity editor = ureq.getUserSession().getIdentity();
SecurityGroup frentixSuperAdminGroup = BaseSecurityManager.getInstance().findSecurityGroupByName("fxadmins");
if(BaseSecurityManager.getInstance().isIdentityInSecurityGroup(identity, frentixSuperAdminGroup)){
if(editor.equals(identity) || BaseSecurityManager.getInstance().isIdentityInSecurityGroup(editor, frentixSuperAdminGroup)) {
return true;
}
return false;
}
if (isOlatAdmin) return true;
// only admins can administrate admin and usermanager users
boolean isAdmin = securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_ADMIN);
boolean isUserManager = securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_USERMANAGER);
if (isAdmin || isUserManager) return false;
// if user is author ony allowed to edit if configured
boolean isAuthor = securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_AUTHOR);
Boolean canManageAuthor = BaseSecurityModule.USERMANAGER_CAN_MANAGE_AUTHORS;
if (isAuthor && !canManageAuthor.booleanValue()) return false;
// if user is groupmanager ony allowed to edit if configured
boolean isGroupManager = securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_GROUPMANAGER);
Boolean canManageGroupmanager = BaseSecurityModule.USERMANAGER_CAN_MANAGE_GROUPMANAGERS;
if (isGroupManager && !canManageGroupmanager.booleanValue()) return false;
// if user is guest ony allowed to edit if configured
boolean isGuestOnly = securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_GUESTONLY);
Boolean canManageGuest = BaseSecurityModule.USERMANAGER_CAN_MANAGE_GUESTS;
if (isGuestOnly && !canManageGuest.booleanValue()) return false;
// passed all tests, current user is allowed to edit given identity
return true;
}
/**
* Initialize the tabbed pane according to the users rights and the system
* configuration
* @param identity
* @param ureq
*/
private void initTabbedPane(Identity identity, UserRequest ureq) {
// first Initialize the user details tabbed pane
userTabP = new TabbedPane("userTabP", ureq.getLocale());
userTabP.addListener(this);
/**
* Determine, whether the user admin is or is not able to edit all fields in user
* profile form. The system admin is always able to do so.
*/
Boolean canEditAllFields = BaseSecurityModule.USERMANAGER_CAN_EDIT_ALL_PROFILE_FIELDS;
if (BaseSecurityManager.getInstance().isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_ADMIN)) {
canEditAllFields = Boolean.TRUE;
}
userProfileCtr = new ProfileAndHomePageEditController(ureq, getWindowControl(), identity, canEditAllFields.booleanValue());
listenTo(userProfileCtr);
userTabP.addTab(translate(NLS_EDIT_UPROFILE), userProfileCtr.getInitialComponent());
prefsCtr = new ChangePrefsController(ureq, getWindowControl(), identity);
userTabP.addTab(translate(NLS_EDIT_UPREFS), prefsCtr.getInitialComponent());
if (isPasswordChangesAllowed(identity)) {
pwdCtr = new UserChangePasswordController(ureq, getWindowControl(), identity);
listenTo(pwdCtr); // listen when finished to update authentications model
userTabP.addTab(translate(NLS_EDIT_UPWD), pwdCtr.getInitialComponent());
}
Boolean canAuth = BaseSecurityModule.USERMANAGER_ACCESS_TO_AUTH;
if (canAuth.booleanValue() || isOlatAdmin) {
authenticationsCtr = new UserAuthenticationsEditorController(ureq, getWindowControl(), identity);
userTabP.addTab(translate(NLS_EDIT_UAUTH), authenticationsCtr.getInitialComponent());
}
Boolean canProp = BaseSecurityModule.USERMANAGER_ACCESS_TO_PROP;
if (canProp.booleanValue() || isOlatAdmin) {
propertiesCtr = new UserPropertiesController(ureq, getWindowControl(), identity);
this.listenTo(propertiesCtr);
userTabP.addTab(translate(NLS_EDIT_UPROP), propertiesCtr.getInitialComponent());
}
Boolean canStartGroups = BaseSecurityModule.USERMANAGER_CAN_START_GROUPS;
grpCtr = new GroupOverviewController(ureq, getWindowControl(), identity, canStartGroups);
listenTo(grpCtr);
userTabP.addTab(translate(NLS_VIEW_GROUPS), grpCtr.getInitialComponent());
courseCtr = new CourseOverviewController(ureq, getWindowControl(), identity);
listenTo(courseCtr);
userTabP.addTab(translate(NLS_VIEW_COURSES), courseCtr.getInitialComponent());
if (isOlatAdmin) {
efficicencyCtrl = new CertificateAndEfficiencyStatementListController(ureq, getWindowControl(), identity, true);
BreadcrumbedStackedPanel stackPanel = new BreadcrumbedStackedPanel("statements", getTranslator(), efficicencyCtrl);
stackPanel.pushController(translate(NLS_VIEW_EFF_STATEMENTS), efficicencyCtrl);
efficicencyCtrl.setBreadcrumbPanel(stackPanel);
stackPanel.setInvisibleCrumb(1);
userTabP.addTab(translate(NLS_VIEW_EFF_STATEMENTS), stackPanel);
}
Boolean canSubscriptions = BaseSecurityModule.USERMANAGER_CAN_MODIFY_SUBSCRIPTIONS;
if (canSubscriptions.booleanValue() || isOlatAdmin) {
Controller subscriptionsCtr = new NotificationSubscriptionController(ureq, getWindowControl(), identity, true);
listenTo(subscriptionsCtr); // auto-dispose
userTabP.addTab(translate(NLS_VIEW_SUBSCRIPTIONS), subscriptionsCtr.getInitialComponent());
}
rolesCtr = new SystemRolesAndRightsController(getWindowControl(), ureq, identity);
userTabP.addTab(translate(NLS_EDIT_UROLES), rolesCtr.getInitialComponent());
Boolean canQuota = BaseSecurityModule.USERMANAGER_ACCESS_TO_QUOTA;
if (canQuota.booleanValue() || isOlatAdmin) {
String relPath = FolderConfig.getUserHomes() + "/" + identity.getName();
quotaCtr = QuotaManager.getInstance().getQuotaEditorInstance(ureq, getWindowControl(), relPath, false);
userTabP.addTab(translate(NLS_EDIT_UQUOTA), quotaCtr.getInitialComponent());
}
// now push to velocity
myContent.put("userTabP", userTabP);
}
private boolean isPasswordChangesAllowed(Identity identity) {
Boolean canChangePwd = BaseSecurityModule.USERMANAGER_CAN_MODIFY_PWD;
if (canChangePwd.booleanValue() || isOlatAdmin) {
// show pwd form only if user has also right to create new passwords in case
// of a user that has no password yet
if(ldapLoginModule.isLDAPEnabled() && ldapLoginManager.isIdentityInLDAPSecGroup(identity)) {
// it's an ldap-user
return ldapLoginModule.isPropagatePasswordChangedOnLdapServer();
}
Boolean canCreatePwd = BaseSecurityModule.USERMANAGER_CAN_CREATE_PWD;
Authentication olatAuth = securityManager.findAuthentication(identity, BaseSecurityModule.getDefaultAuthProviderIdentifier());
if (olatAuth != null || canCreatePwd.booleanValue() || isOlatAdmin) {
return true;
}
}
return false;
}
/**
* Add some user data to velocity container including the users portrait
* @param ureq
* @param identity
*/
private void exposeUserDataToVC(UserRequest ureq, Identity identity) {
removeAsListenerAndDispose(portraitCtr);
portraitCtr = new DisplayPortraitController(ureq, getWindowControl(), identity, true, true);
myContent.put("portrait", portraitCtr.getInitialComponent());
removeAsListenerAndDispose(userShortDescrCtr);
userShortDescrCtr = new UserShortDescription(ureq, getWindowControl(), identity);
myContent.put("userShortDescription", userShortDescrCtr.getInitialComponent());
}
/**
*
* @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
*/
@Override
protected void doDispose() {
//child controllers registered with listenTo get disposed in BasicController
if (quotaCtr != null) {
quotaCtr.dispose();
quotaCtr = null;
}
if (authenticationsCtr != null) {
authenticationsCtr.dispose();
authenticationsCtr = null;
}
if (prefsCtr != null) {
prefsCtr.dispose();
prefsCtr = null;
}
if (policiesCtr != null) {
policiesCtr.dispose();
policiesCtr = null;
}
if (rolesCtr != null) {
rolesCtr.dispose();
rolesCtr = null;
}
if (portraitCtr != null) {
portraitCtr.dispose();
portraitCtr = null;
}
if (userShortDescrCtr!=null) {
userShortDescrCtr.dispose();
userShortDescrCtr = null;
}
}
}