waridrox / ep_sciencemesh

An etherpad-lite plugin to support sync and share collaboration leveraging CS3 WOPI server
https://www.npmjs.com/package/ep_sciencemesh
Apache License 2.0
0 stars 1 forks source link

Block access to pad when wopi webhook responds with HTTP 400 or 500 #2

Open glpatcern opened 2 years ago

glpatcern commented 2 years ago

Reposting here as this contains implementation details:

A possible solution would be to set a sessionID for the editing author once we receive the metadata contents from the setefssmetadata endpoint, then subsequently remove this sessionID on occurrence of the errors.

Maybe something like -

--- a/index.js
+++ b/index.js

+let globalSessionID = null;

 const setNotificationData = (padID, message) => {
   let padId = padID
@@ -38,10 +30,28 @@ const setNotificationData = (padID, message) => {
   padMessageHandler.handleCustomObjectMessage(msg, false)
 }

+const setSessionId = (param) => {
+  globalSessionID = param;
+}
+
 const getMetadata = async (context) => {
   const getMetadata = await db.get(`efssmetadata:${context.pad.id}:${context.author}`).catch((err) => { console.error(JSON.stringify(err.message)) });

   if (getMetadata) {
+    let groupId = await db.get(`mapper2group:1`);
+    const sessionID = await api.createSession(groupId, context.author, Math.floor((Date.now()/1000)+5*60)).catch((err) => { if (err.name === 'apierror') return null; });
+    
+    setSessionId(sessionID.sessionID);
+
     const queryParams = getMetadata.split(':');
     const wopiSrc = decodeURIComponent(queryParams[0]);
     const wopiHost = new URL(wopiSrc).origin;
@@ -82,6 +92,9 @@ const wopiCall = async (wopiHost, wopiSrc, accessToken, padID, close=false) => {
   })
   .catch((error) => {
     if (error.status === 400 || error.status === 500) { 
       let errorStatusText = error.statusText;

       if (error.data.message) {
@@ -90,8 +103,19 @@ 
+
+      // delete the session
+      await api.deleteSession(globalSessionID);

     }
waridrox commented 2 years ago

Thoughts from etherpad discord community (etherpad maintainers):

deleteSession is only usable when using group pads, but iirc group pads don't have a notion of r/w - always writeable. A ugly "hack" would be to dynamically block access to /p/. with the exception of `/p/r..and redirect your users to the readonly pad. If you are using authentication plugins at the moment, then you can make use of theauthorizehook. If not, I'd try out pluginep_guest- afaik theuserssection insettings.jsoncan be changed at runtime, enablerequireAuthentication(but notrequireAuthorization) and configureep_guestso that all users can write in a pad (readOnly: false`). Then, if you want to make all pads readonly, dynamically set this to true. Sorry in case it does not work because users is populated at start up, but iirc I successfully changed this during runtime some time ago.

Ref - https://www.npmjs.com/package/ep_guest