diff --git a/lib/create-app.js b/lib/create-app.js index 0cc00b6bb..3e5b71c15 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -27,6 +27,7 @@ const { routeResolvedFile } = require('./utils') const ResourceMapper = require('./resource-mapper') const aclCheck = require('@solid/acl-check') const { version } = require('../package.json') +const NotificationsManager = require('./models/notifications-manager') const corsSettings = cors({ methods: [ @@ -61,6 +62,9 @@ function createApp (argv = {}) { const app = express() + // something is wrong here. + console.log('argv.notMgr in create-app', argv.notMgr) + argv.notMgr = argv.notMgr ? new NotificationsManager() : argv.notMgr initAppLocals(app, argv, ldp) initHeaders(app) initViews(app, configPath) @@ -168,6 +172,7 @@ function initAppLocals (app, argv, ldp) { app.locals.enforceToc = argv.enforceToc app.locals.tocUri = argv.tocUri app.locals.disablePasswordChecks = argv.disablePasswordChecks + app.locals.notMgr = argv.notMgr if (argv.email && argv.email.host) { app.locals.emailService = new EmailService(argv.templates.email, argv.email) diff --git a/lib/create-server.js b/lib/create-server.js index d650fe45a..968dec258 100644 --- a/lib/create-server.js +++ b/lib/create-server.js @@ -14,6 +14,7 @@ function createServer (argv, app) { app = app || express() const ldpApp = createApp(argv) const ldp = ldpApp.locals.ldp || {} + const notMgr = ldpApp.locals.notMgr || {} let mount = argv.mount || '/' // Removing ending '/' if (mount.length > 1 && @@ -103,5 +104,11 @@ function createServer (argv, app) { ldpApp.locals.ldp.live = solidWs.publish.bind(solidWs) } + if (notMgr) { + // console.log('argv.notMgr in create-server') + server.notMgr = notMgr + // console.log('server.notMgr ' + server.notMgr) + } + return server } diff --git a/lib/handlers/delete.js b/lib/handlers/delete.js index 77eb7f05f..7014ef2c4 100644 --- a/lib/handlers/delete.js +++ b/lib/handlers/delete.js @@ -6,9 +6,24 @@ async function handler (req, res, next) { debug('DELETE -- Request on' + req.originalUrl) const ldp = req.app.locals.ldp + try { await ldp.delete(req) debug('DELETE -- Ok.') + + if (req.app.locals.notMgr) { + const message = { + req: res.req, + time: new Date().toUTCString() + } + const nm = req.app.locals.notMgr + // console.log('delete nm: ') + // console.log(nm) + nm.emit('delete', 'aasdf') + nm.emit('delete', message) + // nm.emit('delete', message) + } + res.sendStatus(200) next() } catch (err) { diff --git a/lib/handlers/options.js b/lib/handlers/options.js index 70d0eca17..e1e6a42f2 100644 --- a/lib/handlers/options.js +++ b/lib/handlers/options.js @@ -10,6 +10,12 @@ function handler (req, res, next) { linkAuthProvider(req, res) linkAcceptEndpoint(res) + // const nm = req.app.locals.notMgr + // const message = { + // req: res.req, + // time: new Date().toUTCString() + // } + // nm.emit('options', message) res.status(204) next() diff --git a/lib/handlers/patch.js b/lib/handlers/patch.js index 8001c9f5f..5fdbe979a 100644 --- a/lib/handlers/patch.js +++ b/lib/handlers/patch.js @@ -90,6 +90,14 @@ async function patchHandler (req, res, next) { await applyPatch(patchObject, graph, url) return writeGraph(graph, resource, ldp.resourceMapper.resolveFilePath(req.hostname), ldp.serverUri) }) + if (req.app.locals.notMgr) { + const nm = req.app.locals.notMgr + const message = { + req: res.req, + time: new Date().toUTCString() + } + nm.emit('patch', message) + } // Send the result to the client res.send(result) diff --git a/lib/handlers/post.js b/lib/handlers/post.js index 5942519f9..b9999a708 100644 --- a/lib/handlers/post.js +++ b/lib/handlers/post.js @@ -72,6 +72,11 @@ async function handler (req, res, next) { // Handled by backpressure of streams! busboy.on('finish', function () { debug('Done storing files') + const message = { + req: res.req, + time: new Date().toUTCString() + } + ldp.emit('post', message) res.sendStatus(200) next() }) @@ -91,6 +96,14 @@ async function handler (req, res, next) { debug('File stored in ' + resourcePath) header.addLinks(res, links) res.set('Location', resourcePath) + if (req.app.locals.notMgr) { + const nm = req.app.locals.notMgr + const message = { + req: res.req, + time: new Date().toUTCString() + } + nm.emit('post', message) + } res.sendStatus(201) next() }, diff --git a/lib/handlers/put.js b/lib/handlers/put.js index 740bf346a..2e6ebdbd2 100644 --- a/lib/handlers/put.js +++ b/lib/handlers/put.js @@ -78,6 +78,15 @@ 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)) res.sendStatus(201) + if (req.app.locals.notMgr) { + const nm = req.app.locals.notMgr + const message = { + req: res.req, + time: new Date().toUTCString() + } + nm.emit('put', message) + } + return next() } catch (err) { err.message = 'Can\'t write file/folder: ' + err.message diff --git a/lib/ldp.js b/lib/ldp.js index e3c261f6a..f26203516 100644 --- a/lib/ldp.js +++ b/lib/ldp.js @@ -23,6 +23,7 @@ const URL = require('url') const withLock = require('./lock') const utilPath = require('path') const { clearAclCache } = require('./acl-checker') +const EventEmitter = require('events') const RDF_MIME_TYPES = new Set([ 'text/turtle', // .ttl @@ -41,8 +42,9 @@ const suffixAcl = '.acl' const suffixMeta = '.meta' const AUXILIARY_RESOURCES = [suffixAcl, suffixMeta] -class LDP { +class LDP extends EventEmitter { constructor (argv = {}) { + super() extend(this, argv) // Suffixes diff --git a/lib/models/notifications-manager.js b/lib/models/notifications-manager.js new file mode 100644 index 000000000..2da84fac3 --- /dev/null +++ b/lib/models/notifications-manager.js @@ -0,0 +1,5 @@ +const EventEmitter = require('events') + +class NotificationsManager extends EventEmitter {} + +module.exports = NotificationsManager diff --git a/test/integration/http-test.js b/test/integration/http-test.js index 4e5d599fe..2cb160dcf 100644 --- a/test/integration/http-test.js +++ b/test/integration/http-test.js @@ -15,6 +15,17 @@ const server = setupSupertestServer({ webid: false }) const { assert, expect } = require('chai') +const NotificationsManager = require('../../lib/models/notifications-manager') + +const notMgr = new NotificationsManager() +const serverWithNotifs = setupSupertestServer({ + live: true, + dataBrowserPath: 'default', + root: path.join(__dirname, '../resources'), + auth: 'oidc', + webid: false, + notMgr: notMgr +}) /** * Creates a new turtle test resource via an LDP PUT @@ -693,6 +704,28 @@ describe('HTTP APIs', function () { }) }) + describe('DELETE API with notifications', () => { + before(() => { + return Promise.all([ + createTestResource('/put-notif-resource.ttl') + ]) + }) + + it('should delete the resource', (done) => { + serverWithNotifs.notMgr.on('delete', (message) => { + console.log('emitted') + console.log(message) + }) + serverWithNotifs.delete('/put-notif-resource.ttl') + .expect(200, done) + }) + + after(function () { + // Clean up after DELETE API tests + rm('/put-notif-resource.ttl') + }) + }) + describe('DELETE API', function () { before(function () { // Ensure all these are finished before running tests diff --git a/test/utils.js b/test/utils.js index 33db7783f..b4b953224 100644 --- a/test/utils.js +++ b/test/utils.js @@ -92,5 +92,10 @@ function createServer (options) { exports.setupSupertestServer = setupSuperServer function setupSuperServer (options) { const ldpServer = createServer(options) + if (ldpServer.notMgr) { + const stServer = supertest(ldpServer) + stServer.notMgr = ldpServer.notMgr + return stServer + } return supertest(ldpServer) }