Commit c4fdb5c6 authored by slogic-sa's avatar slogic-sa Committed by Marco Descher

[9918] CoreHub.actUser soll nicht Anwender sondern IUser sein (#381)

parent 513df158
Pipeline #12426 failed with stages
in 1 minute and 57 seconds
......@@ -143,7 +143,7 @@ public class Desk implements IApplication {
// perform login
cod.performLogin(UiDesk.getDisplay().getActiveShell());
if ((CoreHub.actUser == null) || !CoreHub.actUser.isValid()) {
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$
PersistentObject.disconnect();
......
......@@ -20,7 +20,6 @@ import ch.elexis.core.constants.ElexisSystemPropertyConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.extension.CoreOperationExtensionPoint;
import ch.elexis.core.exceptions.PersistenceException;
import ch.elexis.data.Anwender;
import ch.elexis.data.Kontakt;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Query;
......@@ -61,7 +60,7 @@ public class Application implements IApplication {
String password = System.getProperty(ElexisSystemPropertyConstants.LOGIN_PASSWORD);
log.debug("Starting Login as " + username);
if (username != null && password != null) {
if (!Anwender.login(username, password)) {
if (!CoreHub.login(username, password.toCharArray())) {
log.error("Authentication failed. Exiting.");
System.exit(1);
}
......@@ -71,7 +70,7 @@ public class Application implements IApplication {
}
// check if there is a valid user
if ((CoreHub.actUser == null) || !CoreHub.actUser.isValid()) {
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");
PersistentObject.disconnect();
......
......@@ -14,10 +14,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.elexis.core.constants.ElexisSystemPropertyConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.extension.AbstractCoreOperationAdvisor;
import ch.elexis.core.data.util.IRunnableWithProgress;
import ch.elexis.core.data.util.SqlRunner;
import ch.elexis.data.Anwender;
public class CoreOperationAdvisor extends AbstractCoreOperationAdvisor {
private Logger log = LoggerFactory.getLogger(CoreOperationAdvisor.class);
......@@ -60,7 +60,7 @@ public class CoreOperationAdvisor extends AbstractCoreOperationAdvisor {
* as command line parameters to elexis.
*/
log.error("Bypassing LoginDialog with username " + username);
if (!Anwender.login(username, password)) {
if (!CoreHub.login(username, password.toCharArray())) {
log.error("Authentication failed. Exiting");
}
}
......
......@@ -16,7 +16,7 @@ import ch.elexis.data.Role;
import ch.elexis.data.User;
/**
* @since 3.1 replaced the original AccessControl, which is kept in {@link AccessControlImpl}
* @since 3.1 replaced the original AccessControl, which is kept in the removed AccessControlImpl
*/
public abstract class AbstractAccessControl {
......
......@@ -18,9 +18,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.data.service.ContextServiceHolder;
import ch.elexis.core.jdt.NonNull;
import ch.elexis.core.jdt.Nullable;
import ch.elexis.core.model.IRole;
import ch.elexis.core.model.IUser;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Role;
import ch.elexis.data.User;
......@@ -57,6 +59,17 @@ public class RoleBasedAccessControl extends AbstractAccessControl {
return queryRight(QUERY_RIGHT_FOR_ROLE, r.getWrappedId(), ace);
}
protected static boolean queryRightForRoles(List<IRole> roles, @NonNull ACE ace){
if (roles != null) {
for (IRole role : roles) {
if (queryRightForRole(Role.load(role.getId()), ace)) {
return true;
}
}
}
return false;
}
private static boolean queryRight(String qs, String objId, ACE ace){
// TODO cache?
String queryString = String.format(qs, objId);
......@@ -122,10 +135,15 @@ public class RoleBasedAccessControl extends AbstractAccessControl {
return false;
if (user == null) {
user = (User) ElexisEventDispatcher.getSelected(User.class);
if (user == null) {
IUser iUser = ContextServiceHolder.get().getActiveUser().orElse(null);
if (iUser == null) {
return false;
}
if (!iUser.isInternal()) {
return iUser.isAdministrator()
|| RoleBasedAccessControl.queryRightForRoles(iUser.getRoles(), ace);
}
user = User.load(iUser.getId());
}
if (user.isAdministrator())
......
......@@ -14,12 +14,16 @@ 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;
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;
......@@ -40,18 +44,28 @@ 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.CoreOperationExtensionPoint;
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;
import ch.elexis.core.data.service.StockService;
import ch.elexis.core.data.service.internal.LocalLockService;
import ch.elexis.core.data.services.IOrderService;
import ch.elexis.core.data.services.IStockCommissioningSystemService;
import ch.elexis.core.data.services.IStockService;
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;
......@@ -121,7 +135,6 @@ public class CoreHub implements BundleActivator {
/** Mandantspezifische EInstellungen (Werden in der Datenbank gespeichert) */
public static Settings mandantCfg;
public static Anwender actUser; // TODO set
/**
* @deprecated please use {@link ElexisEventDispatcher#getSelectedMandator()} to retrieve
* current mandator
......@@ -157,6 +170,22 @@ public class CoreHub implements BundleActivator {
*/
private final PatientEventListener eeli_pat = new PatientEventListener();
/**
* Returns the actual contact of the logged in User. Use it only for PO compatibility instead
* use {@link IContextService#getActiveUser()} directly.
*
* @return the {@link Anwender} or null if no contact is present
* @since 3.8
*/
public static @Nullable Anwender getLoggedInContact(){
Optional<IContact> userContact = ContextServiceHolder.get().getActiveUserContact();
if (userContact.isPresent()) {
return Anwender.load(userContact.get().getId());
}
return null;
}
public static boolean isTooManyInstances(){
return tooManyInstances;
}
......@@ -464,13 +493,92 @@ public class CoreHub implements BundleActivator {
return localCfg.get(Preferences.ABL_LOGLEVEL, Log.ERRORS);
}
/**
* 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}
*/
public static boolean login(final String username, char[] password){
((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));
CoreOperationExtensionPoint.getCoreOperationAdvisor().adaptForUser();
CoreHub.getLoggedInContact().setInitialMandator();
CoreHub.userCfg = getUserSetting(CoreHub.getLoggedInContact());
CoreHub.heart.resume(true);
return true;
}
/**
* Perform the required tasks to log off the current {@link Anwender}
*
* @since 3.1 moved from {@link Anwender} class
*/
public static void logoffAnwender(){
if (CoreHub.actUser == null)
if (CoreHub.getLoggedInContact() == null)
return;
if (CoreHub.userCfg != null) {
......@@ -481,11 +589,11 @@ public class CoreHub implements BundleActivator {
CoreHub.setMandant(null);
CoreHub.heart.suspend();
CoreHub.actUser = null;
ContextServiceHolder.get().setActiveUser(null);
ElexisEventDispatcher.getInstance()
.fire(new ElexisEvent(null, Anwender.class, ElexisEvent.EVENT_USER_CHANGED));
ElexisEventDispatcher.getInstance()
.fire(new ElexisEvent(null, User.class, ElexisEvent.EVENT_DESELECTED));
.fire(new ElexisEvent(null, IUser.class, ElexisEvent.EVENT_DESELECTED));
CoreHub.userCfg = CoreHub.localCfg;
}
......
......@@ -265,7 +265,7 @@ public final class ElexisEvent implements Comparable<ElexisEvent> {
* @return
*/
public static ElexisEvent createUserEvent(){
return new ElexisEvent(CoreHub.actUser, Anwender.class, EVENT_USER_CHANGED);
return new ElexisEvent(CoreHub.getLoggedInContact(), Anwender.class, EVENT_USER_CHANGED);
}
/**
......
......@@ -37,7 +37,7 @@ public class PatientEventListener extends ElexisEventListenerImpl {
* Preferences.USR_SHOWPATCHGREMINDER condition.
*/
if (CoreHub.userCfg.get(Preferences.USR_SHOWPATCHGREMINDER, false)) {
List<Reminder> list = Reminder.findOpenRemindersResponsibleFor(CoreHub.actUser,
List<Reminder> list = Reminder.findOpenRemindersResponsibleFor(CoreHub.getLoggedInContact(),
false, (Patient) ev.getObject(), true);
if (list.size() != 0) {
StringBuilder sb = new StringBuilder();
......
......@@ -42,7 +42,7 @@ public abstract class AbstractCoreOperationAdvisor {
* Adapt the context to the change of a user login. That is e.g. de-/activate menus according to
* user rights etc. This was originally done in GlobalActions#adaptForUser()
*
* Called within {@link Anwender#login(String, String)}
* Called within {@link CoreHub#login(String, String)}
*/
public abstract void adaptForUser();
......
......@@ -2,11 +2,9 @@ package ch.elexis.core.data.server;
import ch.elexis.core.common.ElexisEventTopics;
import ch.elexis.core.data.events.ElexisEvent;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.data.service.ContextServiceHolder;
import ch.elexis.core.jdt.Nullable;
import ch.elexis.core.data.interfaces.IPersistentObject;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.User;
/**
* Maps internal {@link ElexisEvent} instances to outgoing ElexisEvent instances sent to
......@@ -35,9 +33,8 @@ public class ServerEventMapper {
object.getClass().getName());
}
IPersistentObject user = ElexisEventDispatcher.getSelected(User.class);
remoteEvent.getProperties().put(ElexisEventTopics.PROPKEY_USER, user.getId());
ContextServiceHolder.get().getActiveUser().ifPresent(
u -> remoteEvent.getProperties().put(ElexisEventTopics.PROPKEY_USER, u.getId()));
return remoteEvent;
}
......
......@@ -28,18 +28,19 @@ import ch.elexis.core.data.events.ElexisEvent;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.data.server.ElexisServerInstanceService;
import ch.elexis.core.data.server.ElexisServerLockService;
import ch.elexis.core.data.service.ContextServiceHolder;
import ch.elexis.core.data.service.StoreToStringServiceHolder;
import ch.elexis.core.data.status.ElexisStatus;
import ch.elexis.core.lock.types.LockInfo;
import ch.elexis.core.lock.types.LockRequest;
import ch.elexis.core.lock.types.LockRequest.Type;
import ch.elexis.core.lock.types.LockResponse;
import ch.elexis.core.model.IUser;
import ch.elexis.core.model.Identifiable;
import ch.elexis.core.server.IInstanceService;
import ch.elexis.core.server.ILockService;
import ch.elexis.core.services.ILocalLockService;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.User;
/**
* ILocalLockService implementation. Managing locks of PersistentObjects, or Identifiable.</br>
......@@ -140,7 +141,7 @@ public class LocalLockService implements ILocalLockService {
}
private LockResponse releaseLock(String storeToString){
User user = (User) ElexisEventDispatcher.getSelected(User.class);
IUser user = ContextServiceHolder.get().getActiveUser().orElse(null);
LockInfo lil = new LockInfo(storeToString, user.getId(), systemUuid.toString());
LockRequest lockRequest = new LockRequest(LockRequest.Type.RELEASE, lil);
return acquireOrReleaseLocks(lockRequest);
......@@ -215,7 +216,7 @@ public class LocalLockService implements ILocalLockService {
return LockResponse.DENIED(null);
}
User user = (User) ElexisEventDispatcher.getSelected(User.class);
IUser user = ContextServiceHolder.get().getActiveUser().orElse(null);
LockInfo lockInfo = new LockInfo(storeToString, user.getId(), systemUuid.toString());
LockRequest lockRequest = new LockRequest(LockRequest.Type.ACQUIRE, lockInfo);
return acquireOrReleaseLocks(lockRequest);
......@@ -364,7 +365,7 @@ public class LocalLockService implements ILocalLockService {
}
logger.debug("Checking lock on [" + object + "]");
User user = (User) ElexisEventDispatcher.getSelected(User.class);
IUser user = ContextServiceHolder.get().getActiveUser().orElse(null);
LockInfo lockInfo =
new LockInfo(StoreToStringServiceHolder.getStoreToString(object), user.getId(),
systemUuid.toString());
......@@ -452,7 +453,7 @@ public class LocalLockService implements ILocalLockService {
}
if (iis != null) {
User u = (User) ElexisEventDispatcher.getSelected(User.class);
IUser u = ContextServiceHolder.get().getActiveUser().orElse(null);
inst.setActiveUser((u != null) ? u.getId() : "NO USER ACTIVE");
iis.updateStatus(inst);
}
......
......@@ -913,7 +913,7 @@ public class BillingUtil {
"invoice correction: no konsultations exists for invoice id [{}]- a new invoice will not be created.",
rechnung.getNr());
output.append("Die Rechnung " + rechnung.getNr() + " wurde erfolgreich durch "
+ CoreHub.actUser.getLabel()
+ CoreHub.getLoggedInContact().getLabel()
+ " korrigiert.\nEs wurde keine neue Rechnung erstellt.");
historyEntryDTO.setIgnored(true);
}
......@@ -942,7 +942,7 @@ public class BillingUtil {
"invoice correction: create new invoice with number [{}] old invoice number [{}] ",
newRechnung.getNr(), rechnung.getNr());
output.append("Die Rechnung " + rechnung.getNr() + " wurde erfolgreich durch "
+ CoreHub.actUser.getLabel() + " korrigiert.\nNeue Rechnungsnummer lautet: "
+ CoreHub.getLoggedInContact().getLabel() + " korrigiert.\nNeue Rechnungsnummer lautet: "
+ invoiceCorrectionDTO.getNewInvoiceNumber());
}
}
......
......@@ -56,7 +56,7 @@ public class LocalLock {
return false;
} else {
StringBuilder sb = new StringBuilder();
String user = (CoreHub.actUser != null) ? CoreHub.actUser.getLabel() : "system";
String user = (CoreHub.getLoggedInContact() != null) ? CoreHub.getLoggedInContact().getLabel() : "system";
sb.append("INSERT INTO CONFIG (param,wert) VALUES (") //$NON-NLS-1$
.append(JdbcLink.wrap(lockString)).append(",") //$NON-NLS-1$
.append(JdbcLink.wrap(
......
......@@ -15,23 +15,22 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import javax.security.auth.login.LoginException;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.events.ElexisEvent;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.data.interfaces.events.MessageEvent;
import ch.elexis.core.data.server.ElexisServerEventService;
import ch.elexis.core.data.service.LocalLockServiceHolder;
import ch.elexis.core.data.service.internal.LocalLockService;
import ch.elexis.core.data.service.ContextServiceHolder;
import ch.elexis.core.data.service.CoreModelServiceHolder;
import ch.elexis.core.jdt.NonNull;
import ch.elexis.core.model.IContact;
import ch.elexis.core.model.IUser;
import ch.elexis.core.model.RoleConstants;
import ch.rgw.io.SqlSettings;
import ch.rgw.tools.JdbcLink;
import ch.rgw.tools.StringTool;
......@@ -198,94 +197,22 @@ public class Anwender extends Person {
* Initializes the first user to the system, the administrator
*/
protected static void initializeAdministratorUser(){
new User();
new User(); // compatibility - needed because of static db inits
Anwender admin = new Anwender();
admin.create(null);
admin.set(new String[] {
Person.NAME, FLD_LABEL, Kontakt.FLD_IS_USER
}, ADMINISTRATOR, ADMINISTRATOR, StringConstants.ONE);
User.load(ADMINISTRATOR).setAssignedContact(admin);
CoreHub.actUser = admin;
ElexisEventDispatcher.getInstance().fire(
new ElexisEvent(admin, Anwender.class, ElexisEvent.EVENT_USER_CHANGED));
}
/**
* 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, CoreHub.actUser
* gesetzt, else <code>false</code>
* @since 3.1 queries {@link User}
*/
public static boolean login(final String username, final String password) {
((LocalLockService) LocalLockServiceHolder.get()).reconfigure();
((ElexisServerEventService) CoreHub.getElexisServerEventService()).reconfigure();
CoreHub.logoffAnwender();
// check if user exists
User user = User.load(username);
if (!user.exists()) {
return false;
}
if(!username.equals(user.get(FLD_ID))) {
return false;
}
// is the user currently active, or locked?
if (!user.isActive()) {
return false;
}
// check if password is valid
boolean result = user.verifyPassword(password);
if (!result) {
return false;
}
// check anwender is valid
Anwender anwender = Anwender.load(user.getAssignedContactId());
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;
Optional<IUser> user = CoreModelServiceHolder.get().load(ADMINISTRATOR, IUser.class);
if (user.isPresent()) {
user.get().setAssignedContact(
CoreModelServiceHolder.get().load(admin.getId(), IContact.class).orElse(null));
ContextServiceHolder.get().setActiveUser(user.get());
ElexisEventDispatcher.getInstance()
.fire(new ElexisEvent(admin, Anwender.class, ElexisEvent.EVENT_USER_CHANGED));
} else {
throw new IllegalStateException("Incorrect DB state - No admin user found!");
}
// set user in system
CoreHub.actUser = anwender;
ElexisEventDispatcher.getInstance().fire(new ElexisEvent(user, User.class, ElexisEvent.EVENT_SELECTED));
ElexisEventDispatcher.getInstance()
.fire(new ElexisEvent(CoreHub.actUser, Anwender.class, ElexisEvent.EVENT_USER_CHANGED));
cod.adaptForUser();
CoreHub.actUser.setInitialMandator();
CoreHub.userCfg = new SqlSettings(getConnection(), "USERCONFIG", "Param", "Value",
"UserID=" + CoreHub.actUser.getWrappedId());
CoreHub.heart.resume(true);
return true;
}
/**
......@@ -295,7 +222,11 @@ public class Anwender extends Person {
CoreHub.logoffAnwender();
}
private void setInitialMandator(){
/**
* Sets the initial {@link Mandant}. Should be used carefully. Only {@link CoreHub} use it after
* login.
*/
public void setInitialMandator(){
Mandant initialMandator = null;
List<Mandant> workingFor = getExecutiveDoctorsWorkingFor();
if (workingFor != null && !workingFor.isEmpty()) {
......@@ -310,7 +241,7 @@ public class Anwender extends Person {
if (initialMandator != null) {
CoreHub.setMandant(initialMandator);
} else {
Mandant m = Mandant.load(CoreHub.actUser.getId());
Mandant m = Mandant.load(CoreHub.getLoggedInContact().getId());
if ((m != null) && m.isValid()) {
CoreHub.setMandant(m);
} else {
......
<
......@@ -33,8 +33,8 @@ public class DBLog extends PersistentObject {
typ = TYP.UNKNOWN;
}
String user = "?";
if (CoreHub.actUser != null) {
user = CoreHub.actUser.getId();
if (CoreHub.getLoggedInContact() != null) {