Something went wrong on our end
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
UserModule.java 11.39 KiB
/**
* 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.user;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.olat.NewControllerFactory;
import org.olat.admin.site.UserAdminSite;
import org.olat.admin.user.UserAdminContextEntryControllerCreator;
import org.olat.basesecurity.Authentication;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.BaseSecurityModule;
import org.olat.core.CoreSpringFactory;
import org.olat.core.configuration.AbstractSpringModule;
import org.olat.core.id.Identity;
import org.olat.core.id.User;
import org.olat.core.id.UserConstants;
import org.apache.logging.log4j.Logger;
import org.olat.core.logging.StartupException;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.ldap.LDAPLoginManager;
import org.olat.ldap.LDAPLoginModule;
import org.olat.user.propertyhandlers.UserPropertyHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* Desciption: The user module represents an implementation of
* the OLAT user with its database object, business managers and page actions.
*
* @author Florian Gnägi
*/
@Service
public class UserModule extends AbstractSpringModule {
private static final Logger log = Tracing.createLoggerFor(UserModule.class);
private static final String USER_EMAIL_MANDATORY = "userEmailMandatory";
private static final String USER_EMAIL_UNIQUE = "userEmailUnique";
private static final String ALLOW_REQUEST_DELETE_ACCOUNT = "allow.request.delete.account";
private static final String ALLOW_REQUEST_DELETE_ACCOUNT_DISCLAIMER = "allow.request.delete.account.disclaimer";
private static final String MAIL_REQUEST_DELETE_ACCOUNT = "request.delete.account.mail";
@Autowired @Qualifier("loginBlacklist")
private ArrayList<String> loginBlacklist;
private List<String> loginBlacklistChecked = new ArrayList<>();
@Value("${password.change.allowed}")
private boolean pwdchangeallowed;
@Value("${password.change.allowed.without.authentications:false}")
private boolean pwdChangeWithoutAuthenticationAllowed;
@Value("${allow.request.delete.account:false}")
private boolean allowRequestToDeleteAccount;
@Value("${allow.request.delete.account.disclaimer:false}")
private boolean allowRequestToDeleteAccountDisclaimer;
@Value("${request.delete.account.mail}")
private String mailToRequestAccountDeletion;
private String adminUserName = "administrator";
@Value("${user.logoByProfile:disabled}")
private String enabledLogoByProfile;
@Value("${user.email.mandatory:true}")
private boolean isEmailMandatory;
@Value("${user.email.unique:true}")
private boolean isEmailUnique;
@Autowired
private UserPropertiesConfig userPropertiesConfig;
@Autowired
public UserModule(CoordinatorManager coordinatorManager) {
super(coordinatorManager);
}
@Override
public void init() {
int count = 0;
for (String regexp : loginBlacklist) {
try {
Pattern.compile(regexp);
loginBlacklistChecked.add(regexp);
} catch (PatternSyntaxException pse) {
log.error("Invalid pattern syntax in blacklist. Pattern: " + regexp+". Removing from this entry from list ");
}
count ++;
}
log.info("Successfully added " + count + " entries to login blacklist.");
updateProperties();
// Check if user manager is configured properly and has user property
// handlers for the mandatory user properties used in OLAT
checkMandatoryUserProperty(UserConstants.FIRSTNAME);
checkMandatoryUserProperty(UserConstants.LASTNAME);
if (isEmailMandatory()) {
checkMandatoryUserProperty(UserConstants.EMAIL);
}
// Add controller factory extension point to launch user profile controller
NewControllerFactory.getInstance().addContextEntryControllerCreator(Identity.class.getSimpleName(),
new IdentityContextEntryControllerCreator());
NewControllerFactory.getInstance().addContextEntryControllerCreator("HomeSite",
new IdentityContextEntryControllerCreator());
NewControllerFactory.getInstance().addContextEntryControllerCreator("HomePage",
new HomePageContextEntryControllerCreator());
NewControllerFactory.getInstance().addContextEntryControllerCreator(User.class.getSimpleName(),
new UserAdminContextEntryControllerCreator());
NewControllerFactory.getInstance().addContextEntryControllerCreator(UserAdminSite.class.getSimpleName(),
new UserAdminContextEntryControllerCreator());
}
@Override
protected void initFromChangedProperties() {
updateProperties();
}
private void updateProperties() {
String userEmailOptionalValue = getStringPropertyValue(USER_EMAIL_MANDATORY, false);
if(StringHelper.containsNonWhitespace(userEmailOptionalValue)) {
isEmailMandatory = "true".equalsIgnoreCase(userEmailOptionalValue);
}
String userEmailUniquenessOptionalValue = getStringPropertyValue(USER_EMAIL_UNIQUE, false);
if(StringHelper.containsNonWhitespace(userEmailUniquenessOptionalValue)) {
isEmailUnique = "true".equalsIgnoreCase(userEmailUniquenessOptionalValue);
}
String allowRequestDeleteObj = getStringPropertyValue(ALLOW_REQUEST_DELETE_ACCOUNT, false);
if(StringHelper.containsNonWhitespace(allowRequestDeleteObj)) {
allowRequestToDeleteAccount = "true".equalsIgnoreCase(allowRequestDeleteObj);
}
String allowRequestDeleteDisclaimerObj = getStringPropertyValue(ALLOW_REQUEST_DELETE_ACCOUNT_DISCLAIMER, false);
if(StringHelper.containsNonWhitespace(allowRequestDeleteDisclaimerObj)) {
allowRequestToDeleteAccountDisclaimer = "true".equalsIgnoreCase(allowRequestDeleteDisclaimerObj);
}
String mailRequestDeleteObj = getStringPropertyValue(MAIL_REQUEST_DELETE_ACCOUNT, false);
if(StringHelper.containsNonWhitespace(mailRequestDeleteObj)) {
mailToRequestAccountDeletion = mailRequestDeleteObj;
}
}
private void checkMandatoryUserProperty(String userPropertyIdentifyer) {
List<UserPropertyHandler> propertyHandlers = userPropertiesConfig.getAllUserPropertyHandlers();
boolean propertyDefined = false;
for (UserPropertyHandler propertyHandler : propertyHandlers) {
if (propertyHandler.getName().equals(userPropertyIdentifyer)) {
propertyDefined = true;
break;
}
}
if ( ! propertyDefined) {
throw new StartupException("The user property handler for the mandatory user property "
+ userPropertyIdentifyer + " is not defined. Check your olat_userconfig.xml file!");
}
}
/**
* @return List of logins on blacklist.
*/
public List<String> getLoginBlacklist() {
return loginBlacklistChecked;
}
/**
* Check wether a login is on the blacklist.
*
* @param login
* @return True if login is in blacklist
*/
public boolean isLoginOnBlacklist(String login) {
login = login.toLowerCase();
for (String regexp: getLoginBlacklist()) {
if (login.matches(regexp)) {
log.info(Tracing.M_AUDIT, "Blacklist entry match for login '" + login + "' with regexp '" + regexp + "'.");
return true;
}
}
return false;
}
/**
* checks whether the given identity is allowed to change it's own password.
* default settings (olat.properties) :
* <ul>
* <li>LDAP-user are not allowed to change their pw</li>
* <li>other users are allowed to change their pw</li>
* </ul>
*
* @param id
* @return
*/
public boolean isPwdChangeAllowed(Identity id) {
if(id == null) {
return isAnyPasswordChangeAllowed();
}
// if this is set to false, nobody can change their password
if (!pwdchangeallowed) {
return false;
}
// call to CoreSpringFactory to break dependencies cycles
// (the method will only be called with a running application)
// check if the user has an OLAT provider token, otherwise a password change makes no sense
Authentication auth = CoreSpringFactory.getImpl(BaseSecurity.class)
.findAuthentication(id, BaseSecurityModule.getDefaultAuthProviderIdentifier());
if(auth == null && !pwdChangeWithoutAuthenticationAllowed) {
return false;
}
LDAPLoginManager ldapLoginManager = CoreSpringFactory.getImpl(LDAPLoginManager.class);
if (ldapLoginManager.isIdentityInLDAPSecGroup(id)) {
// it's an ldap-user
return CoreSpringFactory.getImpl(LDAPLoginModule.class)
.isPropagatePasswordChangedOnLdapServer();
}
return pwdchangeallowed;
}
/**
* use this if you don't have an identity-object (DMZ), and just want to
* check, if anyone could change his password
*
* @return
*/
public boolean isAnyPasswordChangeAllowed() {
return pwdchangeallowed;
}
public boolean isLogoByProfileEnabled() {
return "enabled".equals(enabledLogoByProfile);
}
public String getAdminUserName() {
return adminUserName;
}
public boolean isEmailMandatory() {
return isEmailMandatory;
}
public void setEmailMandatory(boolean isEmailMandatory) {
this.isEmailMandatory = isEmailMandatory;
String isEmailMandatoryStr = isEmailMandatory ? "true" : "false";
setStringProperty(USER_EMAIL_MANDATORY, isEmailMandatoryStr, true);
}
public boolean isEmailUnique() {
return isEmailUnique;
}
public void setEmailUnique(boolean isEmailUnique) {
this.isEmailUnique = isEmailUnique;
String isEmailUniqueStr = isEmailUnique ? "true" : "false";
setStringProperty(USER_EMAIL_UNIQUE, isEmailUniqueStr, true);
}
public boolean isAllowRequestToDeleteAccount() {
return allowRequestToDeleteAccount;
}
public void setAllowRequestToDeleteAccount(boolean allowRequestToDeleteAccount) {
this.allowRequestToDeleteAccount = allowRequestToDeleteAccount;
String allowed = allowRequestToDeleteAccount ? "true" : "false";
setStringProperty(ALLOW_REQUEST_DELETE_ACCOUNT, allowed, true);
}
public boolean isAllowRequestToDeleteAccountDisclaimer() {
return allowRequestToDeleteAccountDisclaimer;
}
public void setAllowRequestToDeleteAccountDisclaimer(boolean allowRequestToDeleteAccountDisclaimer) {
this.allowRequestToDeleteAccountDisclaimer = allowRequestToDeleteAccountDisclaimer;
String allowed = allowRequestToDeleteAccountDisclaimer ? "true" : "false";
setStringProperty(ALLOW_REQUEST_DELETE_ACCOUNT_DISCLAIMER, allowed, true);
}
public String getMailToRequestAccountDeletion() {
return mailToRequestAccountDeletion;
}
public void setMailToRequestAccountDeletion(String mailToRequestAccountDeletion) {
this.mailToRequestAccountDeletion = mailToRequestAccountDeletion;
setStringProperty(MAIL_REQUEST_DELETE_ACCOUNT, mailToRequestAccountDeletion, true);
}
}