Adapt CMS Web to new assembly approach.
[lgpl/argeo-commons.git] / org.argeo.cms.ui / src / org / argeo / cms / ui / AbstractCmsEntryPoint.java
index 99989db19c0cdb58835d1b3ac218a864f3e53415..2cd86ce08edc115300b1e9cda9d0309b4d8626bc 100644 (file)
@@ -1,5 +1,8 @@
 package org.argeo.cms.ui;
 
+import static org.argeo.naming.SharedSecret.X_SHARED_SECRET;
+
+import java.io.IOException;
 import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
@@ -12,6 +15,8 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 import javax.servlet.http.HttpServletRequest;
@@ -20,10 +25,12 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.auth.HttpRequestCallback;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.cms.auth.CmsAuthenticated;
 import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.jcr.JcrUtils;
+import org.argeo.naming.AuthPassword;
+import org.argeo.naming.SharedSecret;
 import org.argeo.node.NodeConstants;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.AbstractEntryPoint;
@@ -55,7 +62,6 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        private Node node;
        private String nodePath;// useful when changing auth
        private String state;
-       private String page;
        private Throwable exception;
 
        // Client services
@@ -110,7 +116,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
 
        @Override
        protected final void createContents(final Composite parent) {
-               UiContext.setData(CmsAuthenticated.KEY, this);
+               UiContext.setData(CmsView.KEY, this);
                Subject.doAs(getSubject(), new PrivilegedAction<Void>() {
                        @Override
                        public Void run() {
@@ -134,17 +140,17 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
         * The node to return when no node was found (for authenticated users and
         * anonymous)
         */
-       protected Node getDefaultNode(Session session) throws RepositoryException {
-               if (!session.hasPermission(defaultPath, "read")) {
-                       String userId = session.getUserID();
-                       if (userId.equals(NodeConstants.ROLE_ANONYMOUS))
-                               // TODO throw a special exception
-                               throw new CmsException("Login required");
-                       else
-                               throw new CmsException("Unauthorized");
-               }
-               return session.getNode(defaultPath);
-       }
+//     private Node getDefaultNode(Session session) throws RepositoryException {
+//             if (!session.hasPermission(defaultPath, "read")) {
+//                     String userId = session.getUserID();
+//                     if (userId.equals(NodeConstants.ROLE_ANONYMOUS))
+//                             // TODO throw a special exception
+//                             throw new CmsException("Login required");
+//                     else
+//                             throw new CmsException("Unauthorized");
+//             }
+//             return session.getNode(defaultPath);
+//     }
 
        protected String getBaseTitle() {
                return factoryProperties.get(WebClient.PAGE_TITLE);
@@ -167,10 +173,15 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        // public LoginContext getLoginContext() {
        // return loginContext;
        // }
-       public Subject getSubject() {
+       protected Subject getSubject() {
                return loginContext.getSubject();
        }
 
+       @Override
+       public boolean isAnonymous() {
+               return CurrentUser.isAnonymous(getSubject());
+       }
+
        @Override
        public synchronized void logout() {
                if (loginContext == null)
@@ -244,8 +255,8 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        protected synchronized String setState(String newState) {
                String previousState = this.state;
 
-               Node node = null;
-               page = null;
+               String newNodePath = null;
+               String prefix = null;
                this.state = newState;
                if (newState.equals("~"))
                        this.state = "";
@@ -253,25 +264,54 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                try {
                        int firstSlash = state.indexOf('/');
                        if (firstSlash == 0) {
-                               node = session.getNode(state);
-                               page = "";
+                               newNodePath = state;
+                               prefix = "";
                        } else if (firstSlash > 0) {
-                               String prefix = state.substring(0, firstSlash);
-                               String path = state.substring(firstSlash);
-                               if (session.nodeExists(path))
-                                       node = session.getNode(path);
-                               else
-                                       throw new CmsException("Data " + path + " does not exist");
-                               page = prefix;
+                               prefix = state.substring(0, firstSlash);
+                               newNodePath = state.substring(firstSlash);
                        } else {
-                               node = getDefaultNode(session);
-                               page = state;
+                               newNodePath = defaultPath;
+                               prefix = state;
+
+                       }
+
+                       // auth
+                       int colonIndex = prefix.indexOf('$');
+                       if (colonIndex > 0) {
+                               SharedSecret token = new SharedSecret(new AuthPassword(X_SHARED_SECRET + '$' + prefix)) {
+
+                                       @Override
+                                       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                                               super.handle(callbacks);
+                                               // handle HTTP context
+                                               for (Callback callback : callbacks) {
+                                                       if (callback instanceof HttpRequestCallback) {
+                                                               ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
+                                                               ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse());
+                                                       }
+                                               }
+                                       }
+                               };
+                               LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token);
+                               lc.login();
+                               authChange(lc);// sets the node as well
+                               // } else {
+                               // // TODO check consistency
+                               // }
+                       } else {
+                               Node newNode = null;
+                               if (session.nodeExists(newNodePath))
+                                       newNode = session.getNode(newNodePath);
+                               else {
+//                                     throw new CmsException("Data " + newNodePath + " does not exist");
+                                       newNode = null;
+                               }
+                               setNode(newNode);
                        }
-                       setNode(node);
-                       String title = publishMetaData(node);
+                       String title = publishMetaData(getNode());
 
                        if (log.isTraceEnabled())
-                               log.trace("node=" + node + ", state=" + state + " (page=" + page + ")");
+                               log.trace("node=" + newNodePath + ", state=" + state + " (prefix=" + prefix + ")");
 
                        return title;
                } catch (Exception e) {
@@ -288,7 +328,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        private String publishMetaData(Node node) throws RepositoryException {
                // Title
                String title;
-               if (node.isNodeType(NodeType.MIX_TITLE) && node.hasProperty(Property.JCR_TITLE))
+               if (node != null && node.isNodeType(NodeType.MIX_TITLE) && node.hasProperty(Property.JCR_TITLE))
                        title = node.getProperty(Property.JCR_TITLE).getString() + " - " + getBaseTitle();
                else
                        title = getBaseTitle();
@@ -298,6 +338,8 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                        return null;
 
                StringBuilder js = new StringBuilder();
+               if (title == null)
+                       title = "";
                title = title.replace("'", "\\'");// sanitize
                js.append("document.title = '" + title + "';");
                jsExecutor.execute(js.toString());
@@ -341,7 +383,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                @Override
                public void navigated(BrowserNavigationEvent event) {
                        setState(event.getState());
-                       refresh();
+                       doRefresh();
                }
        }
 }
\ No newline at end of file