Improve CMS session.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / auth / CurrentUser.java
index cce34cd1fb298c81fd01f98147d2710bd97c4275..2f6325d279ccf687f82370771c8b5237746e3e19 100644 (file)
@@ -17,21 +17,39 @@ package org.argeo.cms.auth;
 
 import java.security.AccessController;
 import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.security.acl.Group;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.UUID;
 
 import javax.security.auth.Subject;
 import javax.security.auth.x500.X500Principal;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.CmsView;
-import org.argeo.cms.util.CmsUtils;
+import org.argeo.cms.internal.auth.CmsSessionImpl;
+import org.argeo.eclipse.ui.specific.UiContext;
+import org.argeo.node.NodeConstants;
 import org.osgi.service.useradmin.Authorization;
 
-/** Static utilities */
+/**
+ * Programmatic access to the currently authenticated user, within a CMS
+ * context.
+ */
 public final class CurrentUser {
+       private final static Log log = LogFactory.getLog(CurrentUser.class);
+//     private final static BundleContext bc = FrameworkUtil.getBundle(CurrentUser.class).getBundleContext();
+       /*
+        * CURRENT USER API
+        */
+
        /**
+        * Technical username of the currently authenticated user.
+        * 
         * @return the authenticated username or null if not authenticated /
         *         anonymous
         */
@@ -39,68 +57,135 @@ public final class CurrentUser {
                return getUsername(currentSubject());
        }
 
+       /**
+        * Human readable name of the currently authenticated user (typically first
+        * name and last name).
+        */
        public static String getDisplayName() {
                return getDisplayName(currentSubject());
        }
 
+       /** Whether a user is currently authenticated. */
        public static boolean isAnonymous() {
                return isAnonymous(currentSubject());
        }
 
-       public static boolean isAnonymous(Subject subject) {
-               String username = getUsername(subject);
-               return username == null
-                               || username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS);
+       /** Roles of the currently logged-in user */
+       public final static Set<String> roles() {
+               return roles(currentSubject());
        }
 
-       private static Subject currentSubject() {
-               Subject subject = Subject.getSubject(AccessController.getContext());
-               if (subject != null)
-                       return subject;
-               if (subject == null) {
-                       CmsView cmsView = CmsUtils.getCmsView();
-                       if (cmsView != null)
-                               return cmsView.getSubject();
-               }
-               throw new CmsException("Cannot find related subject");
+       /** Returns true if the current user is in the specified role */
+       public static boolean isInRole(String role) {
+               Set<String> roles = roles();
+               return roles.contains(role);
+       }
+
+       /** Executes as the current user */
+       public final static <T> T doAs(PrivilegedAction<T> action) {
+               return Subject.doAs(currentSubject(), action);
+       }
+
+       /** Executes as the current user */
+       public final static <T> T tryAs(PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
+               return Subject.doAs(currentSubject(), action);
        }
 
+       /*
+        * WRAPPERS
+        */
+
        public final static String getUsername(Subject subject) {
-               // Subject subject = Subject.getSubject(AccessController.getContext());
-               // if (subject == null)
-               // return null;
+               if (subject == null)
+                       throw new CmsException("Subject cannot be null");
                if (subject.getPrincipals(X500Principal.class).size() != 1)
-                       return null;
-               Principal principal = subject.getPrincipals(X500Principal.class)
-                               .iterator().next();
+                       return NodeConstants.ROLE_ANONYMOUS;
+               Principal principal = subject.getPrincipals(X500Principal.class).iterator().next();
                return principal.getName();
-
        }
 
        public final static String getDisplayName(Subject subject) {
                return getAuthorization(subject).toString();
        }
 
-       private static Authorization getAuthorization(Subject subject) {
-               return subject.getPrivateCredentials(Authorization.class).iterator()
-                               .next();
-       }
-
-       public final static Set<String> roles() {
-               return roles(currentSubject());
-       }
-
        public final static Set<String> roles(Subject subject) {
                Set<String> roles = new HashSet<String>();
-               X500Principal userPrincipal = subject
-                               .getPrincipals(X500Principal.class).iterator().next();
-               roles.add(userPrincipal.getName());
+               roles.add(getUsername(subject));
                for (Principal group : subject.getPrincipals(Group.class)) {
                        roles.add(group.getName());
                }
                return roles;
        }
 
+       /** Whether this user is currently authenticated. */
+       public static boolean isAnonymous(Subject subject) {
+               if (subject == null)
+                       return true;
+               String username = getUsername(subject);
+               return username == null || username.equalsIgnoreCase(NodeConstants.ROLE_ANONYMOUS);
+       }
+       /*
+        * HELPERS
+        */
+
+       private static Subject currentSubject() {
+               CmsAuthenticated cmsView = getNodeAuthenticated();
+               if (cmsView != null)
+                       return cmsView.getSubject();
+               Subject subject = Subject.getSubject(AccessController.getContext());
+               if (subject != null)
+                       return subject;
+               throw new CmsException("Cannot find related subject");
+       }
+
+       /**
+        * The node authenticated component (typically a CMS view) related to this
+        * display, or null if none is available from this call. <b>Not API: Only
+        * for low-level access.</b>
+        */
+       private static CmsAuthenticated getNodeAuthenticated() {
+               return UiContext.getData(CmsAuthenticated.KEY);
+       }
+
+       private static Authorization getAuthorization(Subject subject) {
+               return subject.getPrivateCredentials(Authorization.class).iterator().next();
+       }
+
+       public static boolean logoutCmsSession(Subject subject) {
+               UUID nodeSessionId;
+               if (subject.getPrivateCredentials(CmsSessionId.class).size() == 1)
+                       nodeSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next().getUuid();
+               else
+                       return false;
+               CmsSessionImpl cmsSession = (CmsSessionImpl) CmsSessionImpl.getByUuid(nodeSessionId.toString());
+               cmsSession.close();
+               // Collection<ServiceReference<CmsSession>> srs;
+               // try {
+               // srs = bc.getServiceReferences(CmsSession.class, "(" +
+               // CmsSession.SESSION_UUID + "=" + nodeSessionId + ")");
+               // } catch (InvalidSyntaxException e) {
+               // throw new CmsException("Cannot retrieve CMS session #" +
+               // nodeSessionId, e);
+               // }
+               //
+               // if (srs.size() == 0) {
+               // // if (log.isTraceEnabled())
+               // // log.warn("No CMS web session found for http session " +
+               // // nodeSessionId);
+               // return false;
+               // } else if (srs.size() > 1)
+               // throw new CmsException(srs.size() + " CMS web sessions found for http
+               // session " + nodeSessionId);
+               //
+               // WebCmsSessionImpl cmsSession = (WebCmsSessionImpl)
+               // bc.getService(srs.iterator().next());
+//             cmsSession.cleanUp();
+               // subject.getPrivateCredentials().removeAll(subject.getPrivateCredentials(CmsSessionId.class));
+               if (log.isDebugEnabled())
+                       log.debug("Logged out CMS session " + cmsSession.getUuid());
+               return true;
+       }
+
        private CurrentUser() {
        }
 }