Commit 08e81a56 authored by Marco Descher's avatar Marco Descher
Browse files

[9918] Refactor login process, provide login contributors

parent 9d919e13
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ public class Desk implements IApplication {
		context.applicationRunning();
		
		// perform login
		cod.performLogin(UiDesk.getDisplay().getActiveShell());
		cod.performLogin(new Shell(UiDesk.getDisplay()));
		if ((CoreHub.getLoggedInContact() == null) || !CoreHub.getLoggedInContact().isValid()) {
			// no valid user, exit (don't consider this as an error)
			log.warn("Exit because no valid user logged-in"); //$NON-NLS-1$
+2 −82
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
@@ -22,8 +21,6 @@ import java.util.Properties;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.security.auth.login.LoginException;

import org.eclipse.equinox.internal.app.CommandLineArgs;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
@@ -44,14 +41,12 @@ import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.data.events.Heartbeat;
import ch.elexis.core.data.events.Heartbeat.HeartListener;
import ch.elexis.core.data.events.PatientEventListener;
import ch.elexis.core.data.extension.CoreOperationAdvisorHolder;
import ch.elexis.core.data.interfaces.ShutdownJob;
import ch.elexis.core.data.interfaces.events.MessageEvent;
import ch.elexis.core.data.interfaces.scripting.Interpreter;
import ch.elexis.core.data.preferences.CorePreferenceInitializer;
import ch.elexis.core.data.server.ElexisServerEventService;
import ch.elexis.core.data.service.ContextServiceHolder;
import ch.elexis.core.data.service.CoreModelServiceHolder;
import ch.elexis.core.data.service.LocalLockServiceHolder;
import ch.elexis.core.data.service.PoOrderService;
import ch.elexis.core.data.service.StockCommissioningSystemService;
@@ -64,15 +59,12 @@ import ch.elexis.core.jdt.Nullable;
import ch.elexis.core.model.IContact;
import ch.elexis.core.model.IUser;
import ch.elexis.core.services.IContextService;
import ch.elexis.core.services.IExternalLoginService;
import ch.elexis.core.utils.OsgiServiceUtil;
import ch.elexis.data.Anwender;
import ch.elexis.data.Kontakt;
import ch.elexis.data.Mandant;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.PersistentObjectFactory;
import ch.elexis.data.Query;
import ch.elexis.data.User;
import ch.rgw.io.LockFile;
import ch.rgw.io.Settings;
import ch.rgw.io.SqlSettings;
@@ -494,83 +486,11 @@ public class CoreHub implements BundleActivator {
	}
	
	/**
	 * Login: Anwender anmelden, passenden Mandanten anmelden. (Jeder Anwender ist entweder selber
	 * ein Mandant oder ist einem Mandanten zugeordnet)
	 * 
	 * @param username
	 *            Kurzname
	 * @param password
	 *            Passwort
	 * @return <code>true</code> erfolgreich angemeldet, {@link CoreHub#getLoggedInContact()}
	 *         gesetzt, else <code>false</code>
	 * @since 3.1 queries {@link User}
	 * @since 3.8 moved from Anwender to CoreHub
	 * @since 3.8
	 */
	public static boolean login(final String username, char[] password){
	public static void reconfigureServices() {
		((LocalLockService) LocalLockServiceHolder.get()).reconfigure();
		((ElexisServerEventService) CoreHub.getElexisServerEventService()).reconfigure();

		CoreHub.logoffAnwender();
		
		Optional<IExternalLoginService> externalLoginService =
			OsgiServiceUtil.getService(IExternalLoginService.class);
		
		IUser user = null;
		if (externalLoginService.isPresent()) {
			try {
				user = externalLoginService.get().login(username, password);
			} catch (LoginException e) {
				log.info("Login to external system failed", e);
			}
		}
		if (user == null) {
			// fallback internal login
			log.info("login to internal db");
			Optional<IUser> dbUser = CoreModelServiceHolder.get().load(username, IUser.class);
			if (dbUser.isPresent()) {
				user = dbUser.get().login(username, password);
			}
			if (user == null) {
				return false;
			}
		}
	
		// check anwender is valid
		Anwender anwender = Anwender.load(user.getAssignedContact().getId());
		if (anwender == null) {
			log.error("username: {}", username, new LoginException("anwender is null"));
			return false;
		}
		
		if (!anwender.isValid()) {
			log.error("username: {}", username,
				new LoginException("anwender is invalid or deleted"));
			return false;
		}
		
		if (!anwender.istAnwender()) {
			log.error("username: {}", username,
				new LoginException("anwender is not a istAnwender"));
			return false;
		}
		
		//security - reset password in memory
		Arrays.fill(password, '*');
		
		// set user in system
		ContextServiceHolder.get().setActiveUser(user);
		ElexisEventDispatcher.getInstance()
			.fire(new ElexisEvent(CoreHub.getLoggedInContact(), Anwender.class, ElexisEvent.EVENT_USER_CHANGED));

		CoreOperationAdvisorHolder.get().adaptForUser();
		
		CoreHub.getLoggedInContact().setInitialMandator();

		CoreHub.userCfg = getUserSetting(CoreHub.getLoggedInContact());

		CoreHub.heart.resume(true);

		return true;
	}
	
	/**
+5 −3
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ package ch.elexis.core.data.extension;

import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.util.IRunnableWithProgress;
import ch.elexis.core.jdt.Nullable;
import ch.elexis.data.Anwender;
import ch.elexis.data.PersistentObject;

@@ -73,14 +74,15 @@ public interface ICoreOperationAdvisor {
	 * Required Post-Condition: {@link CoreHub#actUser} and {@link CoreHub#actMandant} have to
	 * contain valid elements.
	 * 
	 * UI-useage: Presents either the user a dialog prompting for username/password or uses the
	 * UI-usage: Presents either the user a dialog prompting for username/password or uses the
	 * System.properties ch.elexis.username and ch.elexis.password to bypass the login dialog. The
	 * second is needed for automated GUI tests.
	 * 
	 * @param shell
	 *            and object castable to org.eclipse.swt.widgets.Shell
	 *            an object castable to org.eclipse.swt.widgets.Shell or <code>null</code>
	 * @return if the login was successful
	 */
	public void performLogin(Object shell);
	public boolean performLogin(@Nullable Object shell);
	
	/**
	 * UI only
+7 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="ch.elexis.core.services.internal.EnvVarsLoginContributor">
   <service>
      <provide interface="ch.elexis.core.services.ILoginContributor"/>
   </service>
   <implementation class="ch.elexis.core.services.internal.EnvVarsLoginContributor"/>
</scr:component>
 No newline at end of file
+56 −0
Original line number Diff line number Diff line
package ch.elexis.core.services.internal;

import java.util.Optional;

import javax.security.auth.login.LoginException;

import org.apache.commons.lang3.StringUtils;
import org.osgi.service.component.annotations.Component;
import org.slf4j.LoggerFactory;

import ch.elexis.core.constants.ElexisSystemPropertyConstants;
import ch.elexis.core.model.IUser;
import ch.elexis.core.services.ILoginContributor;
import ch.elexis.core.services.holder.CoreModelServiceHolder;

/**
 * Allow bypassing the login dialog, eg. for automated GUI-tests. Example: when having a demoDB you
 * may login directly by passing
 * <code>-vmargs -Dch.elexis.username=test -Dch.elexis.password=test</code> as command line
 * parameters to Elexis.
 * 
 * This service performs authentication only against the local database.
 * 
 * @since 3.8 extracted from CoreOperationAdvisor
 */
@Component(immediate = true)
public class EnvVarsLoginContributor implements ILoginContributor {
	
	@Override
	public int getPriority(){
		return 1000;
	}
	
	@Override
	public IUser performLogin(Object shell) throws LoginException{
		String username = System.getProperty(ElexisSystemPropertyConstants.LOGIN_USERNAME);
		String password = System.getProperty(ElexisSystemPropertyConstants.LOGIN_PASSWORD);
		
		if (StringUtils.isNotEmpty(username)) {
			LoggerFactory.getLogger(getClass())
				.warn("Bypassing LoginDialog with username " + username);
			Optional<IUser> dbUser = CoreModelServiceHolder.get().load(username, IUser.class);
			if (dbUser.isPresent()) {
				IUser user = dbUser.get().login(username, password.toCharArray());
				if (user != null && user.isActive()) {
					return user;
				} else {
					LoggerFactory.getLogger(getClass()).error("Authentication failed.");
				}
			}
		}
		
		return null;
	}
	
}
Loading