From: Mathieu Baudier Date: Fri, 20 May 2022 14:48:15 +0000 (+0200) Subject: Move CMS session management to CMS Context. X-Git-Tag: v2.3.10~223 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=c2366f32052deada7d96f635e86f745f438f094e;p=lgpl%2Fargeo-commons.git Move CMS session management to CMS Context. --- diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/parts/EgoDashboard.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/parts/EgoDashboard.java index 5a805d1e9..f2a73f210 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/parts/EgoDashboard.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/parts/EgoDashboard.java @@ -1,23 +1,18 @@ package org.argeo.cms.e4.parts; -import java.security.AccessController; import java.time.ZonedDateTime; import javax.annotation.PostConstruct; -import javax.security.auth.Subject; import org.argeo.api.cms.CmsSession; import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.osgi.CmsOsgiUtils; import org.argeo.cms.swt.CmsSwtUtils; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; /** A canonical view of the logged in user. */ public class EgoDashboard { - private BundleContext bc = FrameworkUtil.getBundle(EgoDashboard.class).getBundleContext(); +// private BundleContext bc = FrameworkUtil.getBundle(EgoDashboard.class).getBundleContext(); @PostConstruct public void createPartControl(Composite p) { @@ -33,14 +28,14 @@ public class EgoDashboard { CmsSwtUtils.txt(p, role); } - Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject != null) { - CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bc, subject); - ZonedDateTime loggedIndSince = cmsSession.getCreationTime(); - CmsSwtUtils.lbl(p, "Session:"); - CmsSwtUtils.txt(p, cmsSession.getUuid().toString()); - CmsSwtUtils.lbl(p, "Logged in since:"); - CmsSwtUtils.txt(p, loggedIndSince.toString()); - } +// Subject subject = Subject.getSubject(AccessController.getContext()); +// if (subject != null) { + CmsSession cmsSession = CurrentUser.getCmsSession(); + ZonedDateTime loggedIndSince = cmsSession.getCreationTime(); + CmsSwtUtils.lbl(p, "Session:"); + CmsSwtUtils.txt(p, cmsSession.getUuid().toString()); + CmsSwtUtils.lbl(p, "Logged in since:"); + CmsSwtUtils.txt(p, loggedIndSince.toString()); +// } } } diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java index 8bb3cc765..064c7e686 100644 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java @@ -17,7 +17,6 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; public class CmsUserApp extends AbstractCmsApp { - private CmsContext cmsContext; private ContentRepository contentRepository; @Override @@ -35,7 +34,7 @@ public class CmsUserApp extends AbstractCmsApp { CmsSwtUi cmsUi = new CmsSwtUi(parent, SWT.NONE); if ("login".equals(uiName)) { CmsView cmsView = CmsSwtUtils.getCmsView(cmsUi); - CmsLogin cmsLogin = new CmsLogin(cmsView, cmsContext); + CmsLogin cmsLogin = new CmsLogin(cmsView, getCmsContext()); cmsLogin.createUi(cmsUi); } else if ("data".equals(uiName)) { @@ -61,8 +60,4 @@ public class CmsUserApp extends AbstractCmsApp { this.contentRepository = contentRepository; } - public void setCmsContext(CmsContext cmsContext) { - this.cmsContext = cmsContext; - } - } \ No newline at end of file diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/CmsApp.java b/org.argeo.api.cms/src/org/argeo/api/cms/CmsApp.java index af9665a63..99c619c80 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/CmsApp.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/CmsApp.java @@ -30,4 +30,6 @@ public interface CmsApp { void addCmsAppListener(CmsAppListener listener); void removeCmsAppListener(CmsAppListener listener); + + CmsContext getCmsContext(); } diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/CmsContext.java b/org.argeo.api.cms/src/org/argeo/api/cms/CmsContext.java index fa26b253a..8f4161c50 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/CmsContext.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/CmsContext.java @@ -3,6 +3,8 @@ package org.argeo.api.cms; import java.util.List; import java.util.Locale; +import javax.security.auth.Subject; + /** * A logical view on this CMS instance, independently of a particular launch or * deployment. @@ -20,7 +22,9 @@ public interface CmsContext { Long getAvailableSince(); - /** Mark this group as a workgroup */ void createWorkgroup(String groupDn); + + /** Get the CMS session of this subject. */ + CmsSession getCmsSession(Subject subject); } diff --git a/org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java b/org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java index 7bf2c96d5..c2d52f3d0 100644 --- a/org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java +++ b/org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java @@ -8,10 +8,13 @@ import java.util.Map; import org.argeo.api.cms.CmsApp; import org.argeo.api.cms.CmsAppListener; +import org.argeo.api.cms.CmsContext; import org.argeo.api.cms.CmsTheme; /** Base class for {@link CmsApp}s. */ public abstract class AbstractCmsApp implements CmsApp { + private CmsContext cmsContext; + private Map themes = Collections.synchronizedMap(new HashMap<>()); private List cmsAppListeners = new ArrayList<>(); @@ -69,4 +72,15 @@ public abstract class AbstractCmsApp implements CmsApp { cmsAppListeners.remove(listener); } + @Override + public CmsContext getCmsContext() { + return cmsContext; + } + + public void setCmsContext(CmsContext cmsContext) { + this.cmsContext = cmsContext; + } + + + } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java index 72676611e..46adcf8a5 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java @@ -19,6 +19,7 @@ import org.argeo.api.cms.CmsConstants; import org.argeo.cms.internal.auth.CmsSessionImpl; import org.argeo.cms.internal.auth.ImpliedByPrincipal; import org.argeo.cms.internal.http.WebCmsSessionImpl; +import org.argeo.cms.internal.runtime.CmsContextImpl; import org.argeo.cms.security.NodeSecurityUtils; import org.argeo.osgi.useradmin.AuthenticatingUser; import org.osgi.framework.BundleContext; @@ -136,7 +137,7 @@ class CmsAuthUtils { request.setAttribute(HttpContext.AUTHORIZATION, authorization); CmsSessionImpl cmsSession; - CmsSessionImpl currentLocalSession = CmsSessionImpl.getByLocalId(httpSessId); + CmsSessionImpl currentLocalSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessId); if (currentLocalSession != null) { boolean currentLocalSessionAnonymous = currentLocalSession.getAuthorization().getName() == null; if (!anonymous) { @@ -165,6 +166,7 @@ class CmsAuthUtils { } else { // new CMS session cmsSession = new WebCmsSessionImpl(subject, authorization, locale, request); + CmsContextImpl.getCmsContext().registerCmsSession(cmsSession); } if (cmsSession == null)// should be dead code (cf. SuppressWarning of the method) @@ -181,33 +183,34 @@ class CmsAuthUtils { } } else { CmsSessionImpl cmsSession = new CmsSessionImpl(subject, authorization, locale, "desktop"); + CmsContextImpl.getCmsContext().registerCmsSession(cmsSession); CmsSessionId nodeSessionId = new CmsSessionId(cmsSession.getUuid()); subject.getPrivateCredentials().add(nodeSessionId); } } - public static CmsSessionImpl cmsSessionFromHttpSession(BundleContext bc, String httpSessionId) { - Authorization authorization = null; - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, - "(" + CmsSession.SESSION_LOCAL_ID + "=" + httpSessionId + ")"); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS session for id " + httpSessionId, e); - } - CmsSessionImpl cmsSession; - if (sr.size() == 1) { - cmsSession = (CmsSessionImpl) bc.getService(sr.iterator().next()); -// locale = cmsSession.getLocale(); - authorization = cmsSession.getAuthorization(); - if (authorization.getName() == null) - return null;// anonymous is not sufficient - } else if (sr.size() == 0) - return null; - else - throw new IllegalStateException(sr.size() + ">1 web sessions detected for http session " + httpSessionId); - return cmsSession; - } +// public static CmsSessionImpl cmsSessionFromHttpSession(BundleContext bc, String httpSessionId) { +// Authorization authorization = null; +// Collection> sr; +// try { +// sr = bc.getServiceReferences(CmsSession.class, +// "(" + CmsSession.SESSION_LOCAL_ID + "=" + httpSessionId + ")"); +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS session for id " + httpSessionId, e); +// } +// CmsSessionImpl cmsSession; +// if (sr.size() == 1) { +// cmsSession = (CmsSessionImpl) bc.getService(sr.iterator().next()); +//// locale = cmsSession.getLocale(); +// authorization = cmsSession.getAuthorization(); +// if (authorization.getName() == null) +// return null;// anonymous is not sufficient +// } else if (sr.size() == 0) +// return null; +// else +// throw new IllegalStateException(sr.size() + ">1 web sessions detected for http session " + httpSessionId); +// return cmsSession; +// } public static T getSinglePrincipal(Subject subject, Class clss) { Set principals = subject.getPrincipals(clss); diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java index 86a748325..cbe428692 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java @@ -124,7 +124,7 @@ public final class CurrentUser { public static CmsSession getCmsSession() { Subject subject = currentSubject(); CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next(); - return CmsSessionImpl.getByUuid(cmsSessionId.getUuid()); + return CmsContextImpl.getCmsContext().getCmsSessionByUuid(cmsSessionId.getUuid()); } /* @@ -151,7 +151,7 @@ public final class CurrentUser { nodeSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next().getUuid(); else return false; - CmsSessionImpl cmsSession = CmsSessionImpl.getByUuid(nodeSessionId.toString()); + CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByUuid(nodeSessionId); // FIXME logout all views // TODO check why it is sometimes null diff --git a/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java index d51997d74..6274bb146 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java @@ -8,14 +8,12 @@ import java.util.function.Supplier; import javax.security.auth.Subject; import org.argeo.api.cms.CmsSession; -import org.argeo.cms.osgi.CmsOsgiUtils; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; +import org.argeo.cms.internal.runtime.CmsContextImpl; /** Remote authentication utilities. */ public class RemoteAuthUtils { static final String REMOTE_USER = "org.osgi.service.http.authentication.remote.user"; - private static BundleContext bundleContext = FrameworkUtil.getBundle(RemoteAuthUtils.class).getBundleContext(); +// private static BundleContext bundleContext = FrameworkUtil.getBundle(RemoteAuthUtils.class).getBundleContext(); /** * Execute this supplier, using the CMS class loader as context classloader. @@ -58,7 +56,7 @@ public class RemoteAuthUtils { public static CmsSession getCmsSession(RemoteAuthRequest req) { Subject subject = Subject .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName())); - CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, subject); + CmsSession cmsSession = CmsContextImpl.getCmsContext().getCmsSession(subject); return cmsSession; } } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java index 962094d4a..b5734afd3 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java @@ -17,9 +17,8 @@ import javax.security.auth.spi.LoginModule; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.cms.internal.auth.CmsSessionImpl; +import org.argeo.cms.internal.runtime.CmsContextImpl; import org.argeo.cms.internal.runtime.KernelUtils; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; import org.osgi.service.http.HttpContext; import org.osgi.service.useradmin.Authorization; @@ -34,7 +33,7 @@ public class RemoteSessionLoginModule implements LoginModule { private RemoteAuthRequest request = null; private RemoteAuthResponse response = null; - private BundleContext bc; +// private BundleContext bc; private Authorization authorization; private Locale locale; @@ -43,8 +42,8 @@ public class RemoteSessionLoginModule implements LoginModule { @Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { - bc = FrameworkUtil.getBundle(RemoteSessionLoginModule.class).getBundleContext(); - assert bc != null; +// bc = FrameworkUtil.getBundle(RemoteSessionLoginModule.class).getBundleContext(); +// assert bc != null; this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = (Map) sharedState; @@ -71,8 +70,8 @@ public class RemoteSessionLoginModule implements LoginModule { String httpSessionId = httpSession.getId(); // if (log.isTraceEnabled()) // log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId); - CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId); - if (cmsSession != null) { + CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId); + if (cmsSession != null && !cmsSession.isAnonymous()) { authorization = cmsSession.getAuthorization(); locale = cmsSession.getLocale(); if (log.isTraceEnabled()) @@ -91,8 +90,8 @@ public class RemoteSessionLoginModule implements LoginModule { String httpSessionId = httpSession.getId(); // if (log.isTraceEnabled()) // log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId); - CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId); - if (cmsSession != null) { + CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId); + if (cmsSession != null && !cmsSession.isAnonymous()) { authorization = cmsSession.getAuthorization(); locale = cmsSession.getLocale(); if (log.isTraceEnabled()) diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index 738b507e7..ea7d1f370 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -80,7 +80,7 @@ public class UserAdminLoginModule implements LoginModule { @Override public boolean login() throws LoginException { - UserAdmin userAdmin = CmsContextImpl.getUserAdmin(); + UserAdmin userAdmin = CmsContextImpl.getCmsContext().getUserAdmin(); final String username; final char[] password; Object certificateChain = null; @@ -212,7 +212,7 @@ public class UserAdminLoginModule implements LoginModule { // if (singleUser) { // OsUserUtils.loginAsSystemUser(subject); // } - UserAdmin userAdmin = CmsContextImpl.getUserAdmin(); + UserAdmin userAdmin = CmsContextImpl.getCmsContext().getUserAdmin(); Authorization authorization; if (callbackHandler == null) {// anonymous authorization = userAdmin.getAuthorization(null); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java index aa3a6ad17..a3670c0cb 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java @@ -28,6 +28,7 @@ import javax.security.auth.x500.X500Principal; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsSession; +import org.argeo.cms.internal.runtime.CmsContextImpl; import org.argeo.cms.security.NodeSecurityUtils; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; @@ -39,7 +40,7 @@ import org.osgi.service.useradmin.Authorization; /** Default CMS session implementation. */ public class CmsSessionImpl implements CmsSession, Serializable { private static final long serialVersionUID = 1867719354246307225L; - private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionImpl.class).getBundleContext(); +// private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionImpl.class).getBundleContext(); private final static CmsLog log = CmsLog.getLog(CmsSessionImpl.class); // private final Subject initialSubject; @@ -85,18 +86,20 @@ public class CmsSessionImpl implements CmsSession, Serializable { this.userDn = NodeSecurityUtils.ROLE_ANONYMOUS_NAME; this.anonymous = true; } + // TODO use time-based UUID? this.uuid = UUID.randomUUID(); // register as service - Hashtable props = new Hashtable<>(); - props.put(CmsSession.USER_DN, userDn.toString()); - props.put(CmsSession.SESSION_UUID, uuid.toString()); - props.put(CmsSession.SESSION_LOCAL_ID, localSessionId); - serviceRegistration = bc.registerService(CmsSession.class, this, props); +// Hashtable props = new Hashtable<>(); +// props.put(CmsSession.USER_DN, userDn.toString()); +// props.put(CmsSession.SESSION_UUID, uuid.toString()); +// props.put(CmsSession.SESSION_LOCAL_ID, localSessionId); +// serviceRegistration = bc.registerService(CmsSession.class, this, props); } public void close() { end = ZonedDateTime.now(); - serviceRegistration.unregister(); + CmsContextImpl.getCmsContext().unregisterCmsSession(this); +// serviceRegistration.unregister(); for (Consumer onClose : onCloseCallbacks) { onClose.accept(this); @@ -205,59 +208,59 @@ public class CmsSessionImpl implements CmsSession, Serializable { } public String toString() { - return "CMS Session " + userDn + " local=" + localSessionId + ", uuid=" + uuid; + return "CMS Session " + userDn + " localId=" + localSessionId + ", uuid=" + uuid; } - public static CmsSessionImpl getByLocalId(String localId) { - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_LOCAL_ID + "=" + localId + ")"); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS session for id " + localId, e); - } - ServiceReference cmsSessionRef; - if (sr.size() == 1) { - cmsSessionRef = sr.iterator().next(); - return (CmsSessionImpl) bc.getService(cmsSessionRef); - } else if (sr.size() == 0) { - return null; - } else - throw new IllegalStateException(sr.size() + " CMS sessions registered for " + localId); - - } - - public static CmsSessionImpl getByUuid(Object uuid) { - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")"); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e); - } - ServiceReference cmsSessionRef; - if (sr.size() == 1) { - cmsSessionRef = sr.iterator().next(); - return (CmsSessionImpl) bc.getService(cmsSessionRef); - } else if (sr.size() == 0) { - return null; - } else - throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid); - - } - - public static void closeInvalidSessions() { - Collection> srs; - try { - srs = bc.getServiceReferences(CmsSession.class, null); - for (ServiceReference sr : srs) { - CmsSession cmsSession = bc.getService(sr); - if (!cmsSession.isValid()) { - ((CmsSessionImpl) cmsSession).close(); - if (log.isDebugEnabled()) - log.debug("Closed expired CMS session " + cmsSession); - } - } - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS sessions", e); - } - } +// public static CmsSessionImpl getByLocalId(String localId) { +// Collection> sr; +// try { +// sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_LOCAL_ID + "=" + localId + ")"); +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS session for id " + localId, e); +// } +// ServiceReference cmsSessionRef; +// if (sr.size() == 1) { +// cmsSessionRef = sr.iterator().next(); +// return (CmsSessionImpl) bc.getService(cmsSessionRef); +// } else if (sr.size() == 0) { +// return null; +// } else +// throw new IllegalStateException(sr.size() + " CMS sessions registered for " + localId); +// +// } +// +// public static CmsSessionImpl getByUuid(Object uuid) { +// Collection> sr; +// try { +// sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")"); +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e); +// } +// ServiceReference cmsSessionRef; +// if (sr.size() == 1) { +// cmsSessionRef = sr.iterator().next(); +// return (CmsSessionImpl) bc.getService(cmsSessionRef); +// } else if (sr.size() == 0) { +// return null; +// } else +// throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid); +// +// } +// +// public static void closeInvalidSessions() { +// Collection> srs; +// try { +// srs = bc.getServiceReferences(CmsSession.class, null); +// for (ServiceReference sr : srs) { +// CmsSession cmsSession = bc.getService(sr); +// if (!cmsSession.isValid()) { +// ((CmsSessionImpl) cmsSession).close(); +// if (log.isDebugEnabled()) +// log.debug("Closed expired CMS session " + cmsSession); +// } +// } +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS sessions", e); +// } +// } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java index fd51c597a..eb6c89d37 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java @@ -27,7 +27,7 @@ public class WebCmsSessionImpl extends CmsSessionImpl { return httpSession.isValid(); } - public static CmsSessionImpl getCmsSession(RemoteAuthRequest request) { - return CmsSessionImpl.getByLocalId(request.getSession().getId()); - } +// public static CmsSessionImpl getCmsSession(RemoteAuthRequest request) { +// return CmsSessionImpl.getByLocalId(request.getSession().getId()); +// } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java index 8e29f6673..ef9f0ec9a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java @@ -3,18 +3,25 @@ package org.argeo.cms.internal.runtime; import static java.util.Locale.ENGLISH; import java.lang.management.ManagementFactory; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import javax.security.auth.Subject; + import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsContext; import org.argeo.api.cms.CmsDeployment; import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsSession; +import org.argeo.api.cms.CmsSessionId; import org.argeo.api.cms.CmsState; import org.argeo.cms.LocaleUtils; -import org.argeo.cms.internal.osgi.NodeUserAdmin; +import org.argeo.cms.internal.auth.CmsSessionImpl; import org.ietf.jgss.GSSCredential; import org.osgi.service.useradmin.UserAdmin; @@ -35,6 +42,10 @@ public class CmsContextImpl implements CmsContext { private Long availableSince; + // CMS sessions + private Map cmsSessionsByUuid = new HashMap<>(); + private Map cmsSessionsByLocalId = new HashMap<>(); + // public CmsContextImpl() { // initTrackers(); // } @@ -164,20 +175,20 @@ public class CmsContextImpl implements CmsContext { * STATIC */ - public synchronized static CmsContext getCmsContext() { + public synchronized static CmsContextImpl getCmsContext() { return getInstance(); } - /** Required by USER login module. */ - public synchronized static UserAdmin getUserAdmin() { - return getInstance().userAdmin; - } +// /** Required by USER login module. */ +// public synchronized static UserAdmin getUserAdmin() { +// return getInstance().userAdmin; +// } /** Required by SPNEGO login module. */ @Deprecated public synchronized static GSSCredential getAcceptorCredentials() { // FIXME find a cleaner way - return ((NodeUserAdmin) getInstance().userAdmin).getAcceptorCredentials(); + return ((CmsUserAdmin) getInstance().userAdmin).getAcceptorCredentials(); } private synchronized static void setInstance(CmsContextImpl cmsContextImpl) { @@ -198,4 +209,45 @@ public class CmsContextImpl implements CmsContext { } } + public UserAdmin getUserAdmin() { + return userAdmin; + } + + /* + * CMS Sessions + */ + + @Override + public synchronized CmsSession getCmsSession(Subject subject) { + if (subject.getPrivateCredentials(CmsSessionId.class).isEmpty()) + return null; + CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next(); + return getCmsSessionByUuid(cmsSessionId.getUuid()); + } + + public synchronized void registerCmsSession(CmsSessionImpl cmsSession) { + if (cmsSessionsByUuid.containsKey(cmsSession.getUuid()) + || cmsSessionsByLocalId.containsKey(cmsSession.getLocalId())) + throw new IllegalStateException("CMS session " + cmsSession + " is already registered."); + cmsSessionsByUuid.put(cmsSession.getUuid(), cmsSession); + cmsSessionsByLocalId.put(cmsSession.getLocalId(), cmsSession); + } + + public synchronized void unregisterCmsSession(CmsSessionImpl cmsSession) { + if (!cmsSessionsByUuid.containsKey(cmsSession.getUuid()) + || !cmsSessionsByLocalId.containsKey(cmsSession.getLocalId())) + throw new IllegalStateException("CMS session " + cmsSession + " is not registered."); + CmsSession removed = cmsSessionsByUuid.remove(cmsSession.getUuid()); + assert removed == cmsSession; + cmsSessionsByLocalId.remove(cmsSession.getLocalId()); + } + + public synchronized CmsSessionImpl getCmsSessionByUuid(UUID uuid) { + return cmsSessionsByUuid.get(uuid); + } + + public synchronized CmsSessionImpl getCmsSessionByLocalId(String localId) { + return cmsSessionsByLocalId.get(localId); + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/CmsOsgiUtils.java b/org.argeo.cms/src/org/argeo/cms/osgi/CmsOsgiUtils.java deleted file mode 100644 index 424d62f68..000000000 --- a/org.argeo.cms/src/org/argeo/cms/osgi/CmsOsgiUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.argeo.cms.osgi; - -import java.util.Collection; - -import javax.security.auth.Subject; - -import org.argeo.api.cms.CmsSession; -import org.argeo.api.cms.CmsSessionId; -import org.osgi.framework.BundleContext; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; - -public class CmsOsgiUtils { - - /** @return The {@link CmsSession} for this {@link Subject} or null. */ - public static CmsSession getCmsSession(BundleContext bc, Subject subject) { - if (subject.getPrivateCredentials(CmsSessionId.class).isEmpty()) - return null; - CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next(); - String uuid = cmsSessionId.getUuid().toString(); - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")"); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e); - } - ServiceReference cmsSessionRef; - if (sr.size() == 1) { - cmsSessionRef = sr.iterator().next(); - return bc.getService(cmsSessionRef); - } else if (sr.size() == 0) { - return null; - } else - throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid); - } - - /** Singleton.*/ - private CmsOsgiUtils() { - } -} diff --git a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java index afc07c5b0..9b0ba4019 100644 --- a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java +++ b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java @@ -15,15 +15,14 @@ import javax.security.auth.login.LoginException; import org.argeo.api.cms.CmsApp; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsImageManager; +import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsSession; import org.argeo.api.cms.CmsUi; import org.argeo.api.cms.CmsView; -import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.UxContext; import org.argeo.cms.LocaleUtils; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.auth.RemoteAuthCallbackHandler; -import org.argeo.cms.osgi.CmsOsgiUtils; import org.argeo.cms.servlet.ServletHttpRequest; import org.argeo.cms.servlet.ServletHttpResponse; import org.argeo.cms.swt.CmsSwtUtils; @@ -265,7 +264,7 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL @Override public CmsSession getCmsSession() { - CmsSession cmsSession = CmsOsgiUtils.getCmsSession(cmsWebApp.getBundleContext(), getSubject()); + CmsSession cmsSession = cmsWebApp.getCmsApp().getCmsContext().getCmsSession(getSubject()); return cmsSession; } diff --git a/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java b/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java index 664d49d2b..ed019d706 100644 --- a/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java +++ b/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java @@ -20,7 +20,6 @@ import org.argeo.api.cms.CmsTheme; import org.argeo.api.cms.CmsUi; import org.argeo.api.cms.CmsView; import org.argeo.api.cms.UxContext; -import org.argeo.cms.osgi.CmsOsgiUtils; import org.argeo.cms.swt.CmsSwtUtils; import org.eclipse.e4.ui.css.core.engine.CSSEngine; import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler; @@ -158,7 +157,7 @@ public class CmsRcpApp implements CmsView { @Override public CmsSession getCmsSession() { - CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, getSubject()); + CmsSession cmsSession = cmsApp.getCmsContext().getCmsSession(getSubject()); return cmsSession; }