Introduce form submission listener.
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 30 Nov 2020 12:12:00 +0000 (13:12 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 30 Nov 2020 12:12:00 +0000 (13:12 +0100)
knowledge/org.argeo.support.odk/OSGI-INF/odkSubmissionServlet.xml
knowledge/org.argeo.support.odk/pom.xml
knowledge/org.argeo.support.odk/src/org/argeo/support/odk/servlet/OdkSubmissionServlet.java
knowledge/org.argeo.support.xforms/src/org/argeo/support/xforms/FormSubmissionListener.java [new file with mode: 0644]
org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java
org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java
org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java

index 1e1bcb1277143346cead26d6d7f73fbc64ae429d..bce66c41457f9c1f13078588ed4a2de1077923a9 100644 (file)
@@ -8,4 +8,5 @@
    <property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=odkServletContext)"/>
    <property name="osgi.http.whiteboard.servlet.multipart.enabled" type="String" value="true"/>
    <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="static" target="(cn=odk)"/>
    <property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=odkServletContext)"/>
    <property name="osgi.http.whiteboard.servlet.multipart.enabled" type="String" value="true"/>
    <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="static" target="(cn=odk)"/>
+   <reference bind="addSubmissionListener" cardinality="0..n" interface="org.argeo.support.xforms.FormSubmissionListener" name="FormSubmissionListener" policy="dynamic" unbind="removeSubmissionListener"/>
 </scr:component>
 </scr:component>
index 69cc95e7c4827d1ae5dfaaa7e938c6585e463a2d..36861fe9c2847780bf3800a5c04fc37e3779a66a 100644 (file)
                        <artifactId>org.argeo.suite.core</artifactId>
                        <version>2.1.16-SNAPSHOT</version>
                </dependency>
                        <artifactId>org.argeo.suite.core</artifactId>
                        <version>2.1.16-SNAPSHOT</version>
                </dependency>
+               <dependency>
+                       <groupId>org.argeo.suite</groupId>
+                       <artifactId>org.argeo.support.xforms</artifactId>
+                       <version>2.1.16-SNAPSHOT</version>
+               </dependency>
        </dependencies>
 </project>
        </dependencies>
 </project>
index f1a1d843389eb76193bc6ad159eec5a11465e74d..23317c8df4eb9410662ca6a73a7f9527653f8dc6 100644 (file)
@@ -5,6 +5,8 @@ import java.time.Instant;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.jcr.ImportUUIDBehavior;
 import javax.jcr.Node;
 
 import javax.jcr.ImportUUIDBehavior;
 import javax.jcr.Node;
@@ -21,12 +23,14 @@ import javax.servlet.http.Part;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.NodeUtils;
+import org.argeo.cms.auth.CmsSession;
 import org.argeo.cms.servlet.ServletAuthUtils;
 import org.argeo.cms.servlet.ServletAuthUtils;
-import org.argeo.entity.EntityNames;
-import org.argeo.entity.EntityType;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrUtils;
+import org.argeo.suite.SuiteUtils;
 import org.argeo.support.odk.OrxType;
 import org.argeo.support.odk.OrxType;
+import org.argeo.support.xforms.FormSubmissionListener;
 
 /** Receives a form submission. */
 public class OdkSubmissionServlet extends HttpServlet {
 
 /** Receives a form submission. */
 public class OdkSubmissionServlet extends HttpServlet {
@@ -40,6 +44,8 @@ public class OdkSubmissionServlet extends HttpServlet {
 
        private Repository repository;
 
 
        private Repository repository;
 
+       private Set<FormSubmissionListener> submissionListeners = new HashSet<>();
+
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                resp.setContentType("text/xml; charset=utf-8");
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                resp.setContentType("text/xml; charset=utf-8");
@@ -50,9 +56,24 @@ public class OdkSubmissionServlet extends HttpServlet {
                Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, null), req);
 
                try {
                Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, null), req);
 
                try {
-                       Node submissions = JcrUtils.mkdirs(session,
-                                       "/" + EntityType.form.get() + "/" + EntityNames.SUBMISSIONS_BASE);
-                       Node submission = submissions.addNode(submissionNameFormatter.format(Instant.now()),
+//                     Node submissions = JcrUtils.mkdirs(session,
+//                                     "/" + EntityType.form.get() + "/" + EntityNames.SUBMISSIONS_BASE);
+                       CmsSession cmsSession = ServletAuthUtils.getCmsSession(req);
+
+                       ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
+                       Thread.currentThread().setContextClassLoader(ServletAuthUtils.class.getClassLoader());
+                       Session adminSession = null;
+                       try {
+                               // TODO centralise at a deeper level
+                               adminSession = NodeUtils.openDataAdminSession(repository, null);
+                               SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
+                       } finally {
+                               Jcr.logout(adminSession);
+                               Thread.currentThread().setContextClassLoader(currentContextCl);
+                       }
+
+                       Node cmsSessionNode = SuiteUtils.getCmsSessionNode(session, cmsSession);
+                       Node submission = cmsSessionNode.addNode(submissionNameFormatter.format(Instant.now()),
                                        OrxType.submission.get());
                        for (Part part : req.getParts()) {
                                if (log.isDebugEnabled())
                                        OrxType.submission.get());
                        for (Part part : req.getParts()) {
                                if (log.isDebugEnabled())
@@ -77,6 +98,9 @@ public class OdkSubmissionServlet extends HttpServlet {
                                }
                        }
                        session.save();
                                }
                        }
                        session.save();
+                       for (FormSubmissionListener submissionListener : submissionListeners) {
+                               submissionListener.formSubmissionReceived(submission);
+                       }
                } catch (RepositoryException e) {
                        e.printStackTrace();
                        resp.setStatus(503);
                } catch (RepositoryException e) {
                        e.printStackTrace();
                        resp.setStatus(503);
@@ -93,4 +117,11 @@ public class OdkSubmissionServlet extends HttpServlet {
                this.repository = repository;
        }
 
                this.repository = repository;
        }
 
+       public synchronized void addSubmissionListener(FormSubmissionListener listener) {
+               submissionListeners.add(listener);
+       }
+
+       public synchronized void removeSubmissionListener(FormSubmissionListener listener) {
+               submissionListeners.remove(listener);
+       }
 }
 }
diff --git a/knowledge/org.argeo.support.xforms/src/org/argeo/support/xforms/FormSubmissionListener.java b/knowledge/org.argeo.support.xforms/src/org/argeo/support/xforms/FormSubmissionListener.java
new file mode 100644 (file)
index 0000000..e23ef36
--- /dev/null
@@ -0,0 +1,10 @@
+package org.argeo.support.xforms;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+/** Called when a user has received a new form submission. */
+public interface FormSubmissionListener {
+       /** Called after a form submission has been stored in the user area. */
+       void formSubmissionReceived(Node node) throws RepositoryException;
+}
index f264bdf3bdd83cb81aac7747c0013cfdfffbe30b..18c91a179a7bd0e090ff338d1d1313e5844015ba 100644 (file)
@@ -6,9 +6,11 @@ import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.security.Privilege;
 import javax.naming.ldap.LdapName;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.security.Privilege;
 import javax.naming.ldap.LdapName;
+import javax.security.auth.x500.X500Principal;
 
 import org.argeo.cms.auth.CmsSession;
 import org.argeo.entity.EntityType;
 
 import org.argeo.cms.auth.CmsSession;
 import org.argeo.entity.EntityType;
+import org.argeo.jackrabbit.security.JackrabbitSecurityUtils;
 import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.naming.LdapAttrs;
 import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.naming.LdapAttrs;
@@ -33,6 +35,10 @@ public class SuiteUtils {
                                userNode.setProperty(LdapAttrs.distinguishedName.property(), userDn.toString());
                                userNode.setProperty(LdapAttrs.uid.property(), uid);
                                adminSession.save();
                                userNode.setProperty(LdapAttrs.distinguishedName.property(), userDn.toString());
                                userNode.setProperty(LdapAttrs.uid.property(), uid);
                                adminSession.save();
+                               JackrabbitSecurityUtils.denyPrivilege(adminSession, userNode.getPath(), SuiteRole.coworker.dn(),
+                                               Privilege.JCR_READ);
+                               JcrUtils.addPrivilege(adminSession, userNode.getPath(), new X500Principal(userDn.toString()).getName(),
+                                               Privilege.JCR_ALL);
                        } else {
                                userNode = usersBase.getNode(uid);
                        }
                        } else {
                                userNode = usersBase.getNode(uid);
                        }
@@ -42,7 +48,15 @@ public class SuiteUtils {
                }
        }
 
                }
        }
 
-       public static Node getOrCreateSessionDir(Session adminSession, CmsSession cmsSession) {
+       public static Node getCmsSessionNode(Session session, CmsSession cmsSession) {
+               try {
+                       return session.getNode(getUserNodePath(cmsSession.getUserDn()) + '/' + cmsSession.getUuid().toString());
+               } catch (RepositoryException e) {
+                       throw new JcrException("Cannot get session dir for " + cmsSession, e);
+               }
+       }
+
+       public static Node getOrCreateCmsSessionNode(Session adminSession, CmsSession cmsSession) {
                try {
                        LdapName userDn = cmsSession.getUserDn();
 //                     String uid = userDn.get(userDn.size() - 1);
                try {
                        LdapName userDn = cmsSession.getUserDn();
 //                     String uid = userDn.get(userDn.size() - 1);
@@ -58,17 +72,17 @@ public class SuiteUtils {
 //                             userNode = usersBase.getNode(uid);
 //                     }
                        String cmsSessionUuid = cmsSession.getUuid().toString();
 //                             userNode = usersBase.getNode(uid);
 //                     }
                        String cmsSessionUuid = cmsSession.getUuid().toString();
-                       Node userDir;
+                       Node cmsSessionNode;
                        if (!userNode.hasNode(cmsSessionUuid)) {
                        if (!userNode.hasNode(cmsSessionUuid)) {
-                               userDir = userNode.addNode(cmsSessionUuid, NodeType.NT_UNSTRUCTURED);
-                               userDir.addMixin(NodeType.MIX_CREATED);
+                               cmsSessionNode = userNode.addNode(cmsSessionUuid, NodeType.NT_UNSTRUCTURED);
+                               cmsSessionNode.addMixin(NodeType.MIX_CREATED);
                                adminSession.save();
                                adminSession.save();
-                               JcrUtils.addPrivilege(adminSession, userDir.getPath(), cmsSession.getUserDn().toString(),
+                               JcrUtils.addPrivilege(adminSession, cmsSessionNode.getPath(), cmsSession.getUserRole(),
                                                Privilege.JCR_ALL);
                        } else {
                                                Privilege.JCR_ALL);
                        } else {
-                               userDir = userNode.getNode(cmsSessionUuid);
+                               cmsSessionNode = userNode.getNode(cmsSessionUuid);
                        }
                        }
-                       return userDir;
+                       return cmsSessionNode;
                } catch (RepositoryException e) {
                        throw new JcrException("Cannot create session dir for " + cmsSession, e);
                }
                } catch (RepositoryException e) {
                        throw new JcrException("Cannot create session dir for " + cmsSession, e);
                }
index db6ac913422a5118db5428dbef8fa0b6966ef5bd..685e9939cdb860f0c9003ba90e4ec4fef2fcd386 100644 (file)
@@ -12,6 +12,7 @@ import org.argeo.api.NodeConstants;
 import org.argeo.entity.EntityType;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.maintenance.AbstractMaintenanceService;
 import org.argeo.entity.EntityType;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.maintenance.AbstractMaintenanceService;
+import org.argeo.suite.SuiteRole;
 
 /** Initialises an Argeo Suite backend. */
 public class SuiteMaintenanceService extends AbstractMaintenanceService {
 
 /** Initialises an Argeo Suite backend. */
 public class SuiteMaintenanceService extends AbstractMaintenanceService {
@@ -33,6 +34,7 @@ public class SuiteMaintenanceService extends AbstractMaintenanceService {
        public void configurePrivileges(Session adminSession) throws RepositoryException {
                JcrUtils.addPrivilege(adminSession, EntityType.user.basePath(), NodeConstants.ROLE_USER_ADMIN,
                                Privilege.JCR_ALL);
        public void configurePrivileges(Session adminSession) throws RepositoryException {
                JcrUtils.addPrivilege(adminSession, EntityType.user.basePath(), NodeConstants.ROLE_USER_ADMIN,
                                Privilege.JCR_ALL);
+               JcrUtils.addPrivilege(adminSession, "/", SuiteRole.coworker.dn(), Privilege.JCR_READ);
        }
 
 }
        }
 
 }
index e363a62ff23d0b7ec325f5093a18701a61d2fbf9..31763fe7c736788487029a035841a9ab8b2a3ff2 100644 (file)
@@ -136,7 +136,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
                                        Session adminSession = null;
                                        try {
                                                adminSession = NodeUtils.openDataAdminSession(getRepository(), null);
                                        Session adminSession = null;
                                        try {
                                                adminSession = NodeUtils.openDataAdminSession(getRepository(), null);
-                                               Node userDir = SuiteUtils.getOrCreateSessionDir(adminSession, cmsSession);
+                                               Node userDir = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
                                                ui.initSessions(getRepository(), userDir.getPath());
                                        } finally {
                                                Jcr.logout(adminSession);
                                                ui.initSessions(getRepository(), userDir.getPath());
                                        } finally {
                                                Jcr.logout(adminSession);