From b0e7eb017dc0077928fff5ea422348e9f5d9caeb Mon Sep 17 00:00:00 2001 From: Rahul Gupta Date: Thu, 10 Oct 2024 22:43:12 +0530 Subject: [PATCH] feat: Add Flag to disable PREP PREP can be disabled when the server is started with the `--no-prep` flag. --- README.md | 11 ++++++----- bin/lib/options.js | 6 ++++++ lib/create-app.js | 10 +++++++--- lib/handlers/delete.js | 3 ++- lib/handlers/get.js | 5 +++-- lib/handlers/patch.js | 3 ++- lib/handlers/post.js | 5 +++-- lib/handlers/put.js | 3 ++- lib/ldp-middleware.js | 17 ++++++++++++----- test/integration/prep-test.js | 3 ++- 10 files changed, 45 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 24f92251e..514c44ebf 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Your users will have a dedicated folder under `./data` at `./data/. To use Gmail you may need to configure ["Allow Less Secure Apps"](https://www.google.com/settings/security/lesssecureapps) in your Gmail account unless you are using 2FA in which case you would have to create an [Application Specific](https://security.google.com/settings/security/apppasswords) password. You also may need to unlock your account with ["Allow access to your Google account"](https://accounts.google.com/DisplayUnlockCaptcha) to use SMTP. also add to `config.json` -``` +``` "useEmail": true, "emailHost": "smtp.gmail.com", "emailPort": "465", @@ -206,6 +206,7 @@ $ solid start --help --multiuser Enable multi-user mode --idp [value] Obsolete; use --multiuser --no-live Disable live support through WebSockets + --no-prep Disable Per Resource Events --proxy [value] Obsolete; use --corsProxy --cors-proxy [value] Serve the CORS proxy on this path --suppress-data-browser Suppress provision of a data browser @@ -271,7 +272,7 @@ docker run -p 8443:8443 --name solid node-solid-server This will enable you to login to solid on https://localhost:8443 and then create a new account -but not yet use that account. After a new account is made you will need to create an entry for +but not yet use that account. After a new account is made you will need to create an entry for it in your local (/etc/)hosts file in line with the account and subdomain, i.e. -- ```pre @@ -280,16 +281,16 @@ it in your local (/etc/)hosts file in line with the account and subdomain, i.e. You can modify the config within the docker container as follows: - - Copy the `config.json` to the current directory with: + - Copy the `config.json` to the current directory with: ```bash docker cp solid:/usr/src/app/config.json . ``` - Edit the `config.json` file - - Copy the file back with + - Copy the file back with ```bash docker cp config.json solid:/usr/src/app/ ``` - - Restart the server with + - Restart the server with ```bash docker restart solid ``` diff --git a/bin/lib/options.js b/bin/lib/options.js index 630dd8199..bcb7d468a 100644 --- a/bin/lib/options.js +++ b/bin/lib/options.js @@ -143,6 +143,12 @@ module.exports = [ flag: true, default: false }, + { + name: 'no-prep', + help: 'Disable Per Resource Events', + flag: true, + default: false + }, // { // full: 'default-app', // help: 'URI to use as a default app for resources (default: https://linkeddata.github.io/warp/#/list/)' diff --git a/lib/create-app.js b/lib/create-app.js index d98d884e0..805695f3e 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -67,7 +67,10 @@ function createApp (argv = {}) { const app = express() // Add PREP support - app.use(acceptEvents, events, eventID, prep) + if (argv.prep) { + app.use(eventID) + app.use(acceptEvents, events, prep) + } initAppLocals(app, argv, ldp) initHeaders(app) @@ -123,7 +126,7 @@ function createApp (argv = {}) { } // Attach the LDP middleware - app.use('/', LdpMiddleware(corsSettings)) + app.use('/', LdpMiddleware(corsSettings, argv.prep)) // https://stackoverflow.com/questions/51741383/nodejs-express-return-405-for-un-supported-method app.use(function (req, res, next) { @@ -176,6 +179,7 @@ function initAppLocals (app, argv, ldp) { app.locals.enforceToc = argv.enforceToc app.locals.tocUri = argv.tocUri app.locals.disablePasswordChecks = argv.disablePasswordChecks + app.locals.prep = argv.prep if (argv.email && argv.email.host) { app.locals.emailService = new EmailService(argv.templates.email, argv.email) @@ -295,7 +299,7 @@ function initWebId (argv, app, ldp) { initAuthentication(app, argv) if (argv.multiuser) { - app.use(vhost('*', LdpMiddleware(corsSettings))) + app.use(vhost('*', LdpMiddleware(corsSettings, argv.prep))) } } diff --git a/lib/handlers/delete.js b/lib/handlers/delete.js index c267cd266..438bfe65c 100644 --- a/lib/handlers/delete.js +++ b/lib/handlers/delete.js @@ -6,11 +6,12 @@ async function handler (req, res, next) { debug('DELETE -- Request on' + req.originalUrl) const ldp = req.app.locals.ldp + const prep = req.app.locals.prep try { await ldp.delete(req) debug('DELETE -- Ok.') // Add event-id for notifications - res.setHeader('Event-ID', res.setEventID()) + prep && res.setHeader('Event-ID', res.setEventID()) res.sendStatus(200) next() } catch (err) { diff --git a/lib/handlers/get.js b/lib/handlers/get.js index af29a741d..3e11b3e53 100644 --- a/lib/handlers/get.js +++ b/lib/handlers/get.js @@ -23,6 +23,7 @@ const prepConfig = 'accept=("message/rfc822" "application/ld+json" "text/turtle" async function handler (req, res, next) { const ldp = req.app.locals.ldp + const prep = req.app.locals.prep const includeBody = req.method === 'GET' const negotiator = new Negotiator(req) const baseUri = ldp.resourceMapper.resolveUrl(req.hostname, req.path) @@ -138,7 +139,7 @@ async function handler (req, res, next) { res.statusCode = 206 } - if (isRdf(contentType) && !res.sendEvents({ + if (prep & isRdf(contentType) && !res.sendEvents({ config: { prep: prepConfig }, body: stream, isBodyStream: true, @@ -160,7 +161,7 @@ async function handler (req, res, next) { const headers = { 'Content-Type': possibleRDFType } - if (isRdf(contentType) && !res.sendEvents({ + if (prep && isRdf(contentType) && !res.sendEvents({ config: { prep: prepConfig }, body: data, headers diff --git a/lib/handlers/patch.js b/lib/handlers/patch.js index c98e1470e..d9469e750 100644 --- a/lib/handlers/patch.js +++ b/lib/handlers/patch.js @@ -39,6 +39,7 @@ function contentForNew (contentType) { // Handles a PATCH request async function patchHandler (req, res, next) { debug(`PATCH -- ${req.originalUrl}`) + const prep = req.app.locals.prep try { // Obtain details of the target resource const ldp = req.app.locals.ldp @@ -92,7 +93,7 @@ async function patchHandler (req, res, next) { }) // Add event-id for notifications - res.setHeader('Event-ID', res.setEventID()) + prep && res.setHeader('Event-ID', res.setEventID()) // Send the status and result to the client res.status(resourceExists ? 200 : 201) res.send(result) diff --git a/lib/handlers/post.js b/lib/handlers/post.js index cd136bd9b..dd16700d3 100644 --- a/lib/handlers/post.js +++ b/lib/handlers/post.js @@ -11,6 +11,7 @@ const getContentType = require('../utils').getContentType async function handler (req, res, next) { const ldp = req.app.locals.ldp + const prep = req.app.locals.prep const contentType = getContentType(req.headers) debug('content-type is ', contentType) // Handle SPARQL(-update?) query @@ -73,7 +74,7 @@ async function handler (req, res, next) { busboy.on('finish', function () { debug('Done storing files') // Add event-id for notifications - res.setHeader('Event-ID', res.setEventID()) + prep && res.setHeader('Event-ID', res.setEventID()) res.sendStatus(200) next() }) @@ -94,7 +95,7 @@ async function handler (req, res, next) { header.addLinks(res, links) res.set('Location', resourcePath) // Add event-id for notifications - res.setHeader('Event-ID', res.setEventID()) + prep && res.setHeader('Event-ID', res.setEventID()) res.sendStatus(201) next() }, diff --git a/lib/handlers/put.js b/lib/handlers/put.js index d6b984b66..5c2e1f677 100644 --- a/lib/handlers/put.js +++ b/lib/handlers/put.js @@ -59,6 +59,7 @@ async function checkPermission (request, resourceExists) { // TODO could be renamed as putResource (it now covers container and non-container) async function putStream (req, res, next, stream = req) { const ldp = req.app.locals.ldp + const prep = req.app.locals.prep // try { // Obtain details of the target resource let resourceExists = true @@ -78,7 +79,7 @@ async function putStream (req, res, next, stream = req) { if (!req.originalUrl.endsWith('.acl')) await checkPermission(req, resourceExists) await ldp.put(req, stream, getContentType(req.headers)) // Add event-id for notifications - res.setHeader('Event-ID', res.setEventID()) + prep && res.setHeader('Event-ID', res.setEventID()) res.sendStatus(resourceExists ? 204 : 201) return next() } catch (err) { diff --git a/lib/ldp-middleware.js b/lib/ldp-middleware.js index 53eb90c27..996286d4c 100644 --- a/lib/ldp-middleware.js +++ b/lib/ldp-middleware.js @@ -12,7 +12,7 @@ const index = require('./handlers/index') const copy = require('./handlers/copy') const notify = require('./handlers/notify') -function LdpMiddleware (corsSettings) { +function LdpMiddleware (corsSettings, prep) { const router = express.Router('/') // Add Link headers @@ -24,10 +24,17 @@ function LdpMiddleware (corsSettings) { router.copy('/*', allow('Write'), copy) router.get('/*', index, allow('Read'), header.addPermissions, get) - router.post('/*', allow('Append'), post, notify) - router.patch('/*', allow('Append'), patch, notify) - router.put('/*', allow('Append'), put, notify) - router.delete('/*', allow('Write'), del, notify) + router.post('/*', allow('Append'), post) + router.patch('/*', allow('Append'), patch) + router.put('/*', allow('Append'), put) + router.delete('/*', allow('Write'), del) + + if (prep) { + router.post('/*', notify) + router.patch('/*', notify) + router.put('/*', notify) + router.delete('/*', notify) + } return router } diff --git a/test/integration/prep-test.js b/test/integration/prep-test.js index dceb5a2bd..6db1b03ab 100644 --- a/test/integration/prep-test.js +++ b/test/integration/prep-test.js @@ -17,7 +17,8 @@ describe('Per Resource Events Protocol', function () { dataBrowserPath: 'default', root: path.join(__dirname, '../resources'), auth: 'oidc', - webid: false + webid: false, + prep: true }) server.listen(8443, done) })