ldn-inbox-server 1.4.4 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,7 +55,35 @@ npx ldn-inbox-server handler @outbox -hn ./handler/send_notification_handler.js
55
55
  - `LDN_SERVER_JSON_SCHEMA` : notification JSON validation schema
56
56
  - `LDN_SERVER_BASEURL` : baseurl of the LDN inbox server
57
57
  - `LDN_SERVER_INBOX_GLOB` : glob of files to process in inbox directory
58
- - `LDN_SERVER_HAS_PUBLIC_INBOX` : if true, then public read access is allowed on inbox
58
+ - `LDN_SERVER_HAS_PUBLIC_INBOX` : if true, then public read access is allowed on the inbox
59
+ - `LDN_SERVER_HAS_WRITABLE_INBOX` : if true, then public write access is allowed on the inbox
60
+
61
+ ## Multiple inboxes
62
+
63
+ Instead of a single inbox, multiple inboxes can be configured by adding a JSON configuration file to the installation. The JSON file should contain a `registry` entry with contains an array of inbox configuration. An example:
64
+
65
+ ```
66
+ {
67
+ "registry": [
68
+ { "path": "inbox/.*" ,
69
+ "with": {
70
+ "url": "inbox/",
71
+ "inbox": "./inbox",
72
+ "inboxPublic": 1,
73
+ "inboxWritable": 1,
74
+ "schema": "./config/schema1.json"
75
+ }},
76
+ { "path": "inbox2/.*" ,
77
+ "with": {
78
+ "url": "inbox2/",
79
+ "inbox": "./inbox2",
80
+ "inboxPublic": 1,
81
+ "inboxWritable": 0,
82
+ "schema": "./config/schema2.json"
83
+ }}
84
+ ]
85
+ }
86
+ ```
59
87
 
60
88
  ## Extend
61
89
 
@@ -115,7 +143,7 @@ A handler can be started on any directory. E.g. a workflow might be:
115
143
 
116
144
  A handler that creates for an incoming notification an `Accept` notification in the `@outbox`.
117
145
 
118
- ### Evenlog handler
146
+ ### Eventlog handler
119
147
 
120
148
  A handler that updates an event log with the incoming notification.
121
149
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const { program } = require('commander');
5
- const { inbox_server } = require('../lib/index');
5
+ const { start_server } = require('mellon-server');
6
+ const { doInbox } = require('../lib/index');
6
7
  const { handle_inbox } = require('../lib/handler');
7
8
  require('dotenv').config();
8
9
 
@@ -20,6 +21,8 @@ const JSON_SCHEMA_PATH = process.env.LDN_SERVER_JSON_SCHEMA ?? './config/notific
20
21
  const INBOX_CONFIG = process.env.LDN_SERVER_INBOX_CONFIG;
21
22
  const OUTBOX_CONFIG = process.env.LDN_SERVER_OUTBOX_CONFIG;
22
23
  const HAS_PUBLIC = process.env.LDN_SERVER_HAS_PUBLIC_INBOX ?? 0;
24
+ const HAS_WRITE = process.env.LDN_SERVER_HAS_WRITABLE_INBOX ?? 1;
25
+ const OTHER_CONFIG = process.env.LDN_SERVER_OTHER_CONFIG;
23
26
 
24
27
  program
25
28
  .name('lnd-inbox-server')
@@ -29,6 +32,7 @@ program
29
32
  .command('start-server')
30
33
  .option('--host <host>','host',HOST)
31
34
  .option('--port <port>','port',PORT)
35
+ .option('--config <config>','config',OTHER_CONFIG)
32
36
  .option('--url <path>','path',INBOX_URL)
33
37
  .option('--base <url>','base url',INBOX_BASE_URL)
34
38
  .option('--inbox <inbox>','inbox',INBOX_PATH)
@@ -36,8 +40,45 @@ program
36
40
  .option('--schema <schema>','json schema',JSON_SCHEMA_PATH)
37
41
  .option('--registry <registry>','registry',null)
38
42
  .option('--inbox-public','public readable inbox',HAS_PUBLIC)
43
+ .option('--inbox-writeable','public writable inbox',HAS_WRITE)
39
44
  .action( (options) => {
40
- inbox_server(options);
45
+ let registry = [];
46
+
47
+ // Add other (external defined) registry parts
48
+ if (options['registry']) {
49
+ const path = options['registry'];
50
+ let registry2;
51
+ if (typeof path === 'string' || path instanceof String) {
52
+ registry2 = JSON.parse(fs.readFileSync(path,{ encoding: 'utf-8'}));
53
+ }
54
+ else {
55
+ registry2 = path;
56
+ }
57
+ registry = registry.concat(registry2);
58
+ }
59
+
60
+ if (options['config'] && fs.existsSync(options['config'])) {
61
+ const config = JSON.parse(fs.readFileSync(options['config'], { encoding: 'utf-8'}));
62
+ if (config.registry) {
63
+ for (let i = 0 ; i < config.registry.length ; i++) {
64
+ const registry_item = config.registry[i];
65
+ registry_item['do'] = doInbox;
66
+ registry_item['with'] = {...options,...registry_item['with']};
67
+ registry = registry.concat(registry_item);
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ registry = registry.concat({ path : `${options['url']}.*` , do: doInbox , with: options});
73
+ }
74
+
75
+ start_server({
76
+ host: options['host'],
77
+ port: options['port'],
78
+ base: options['base'],
79
+ public: options['public'],
80
+ registry: registry
81
+ });
41
82
  });
42
83
 
43
84
  program
@@ -1,4 +1,12 @@
1
1
  {
2
+ "registry": [
3
+ { "path": "inbox2/.*" , "with": {
4
+ "url": "inbox2/",
5
+ "inbox": "./inbox2",
6
+ "inboxPublic": 1,
7
+ "inboxWritable": 0
8
+ }}
9
+ ],
2
10
  "notification_handler": {
3
11
  "multi": {
4
12
  "handlers": [
@@ -11,22 +11,22 @@ async function handle({path,options,config}) {
11
11
  logger.info(`parsing notification ${path}`);
12
12
 
13
13
  if (! config) {
14
- logger.error('no configuration found for offer_memento_notification_handler');
14
+ logger.error('no configuration found for offer_memento');
15
15
  return { path, options, success: false };
16
16
  }
17
17
 
18
18
  if (!config['actor'] || !config['target']) {
19
- logger.error('no actor/target entry for notification_handler.eventlog configuration');
19
+ logger.error('no actor/target entry');
20
20
  return { path, options, success: false };
21
21
  }
22
22
 
23
23
  if (!options['artifact']) {
24
- logger.info(`no artifact found (ignonring this request)`);
24
+ logger.info(`no artifact found (ignoring this request)`);
25
25
  return { path, options, success: true };
26
26
  }
27
27
 
28
28
  if (!options['eventlog']) {
29
- logger.info(`no artifact found (ignonring this request)`);
29
+ logger.info(`no artifact found (ignoring this request)`);
30
30
  return { path, options, success: true };
31
31
  }
32
32
 
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const { start_server } = require('mellon-server');
1
+
2
2
  const Validator = require('jsonschema').Validator;
3
3
  const fs = require('fs');
4
4
  const md5 = require('md5');
@@ -7,56 +7,21 @@ const {
7
7
  fetchOriginal,
8
8
  backOff_fetch,
9
9
  sendNotification,
10
- moveTo
10
+ moveTo,
11
+ parseAsJSON
11
12
  } = require('../lib/util');
12
13
  const { handle_inbox } = require('../lib/handler');
13
14
  const logger = getLogger();
14
15
 
15
- let INBOX_URL = 'inbox/';
16
- let INBOX_PATH = './inbox';
17
- let INBOX_BASE_URL = 'http://localhost:8000';
18
- let INBOX_PUBLIC_READABLE = 0;
19
- let JSON_SCHEMA = '';
20
-
21
- function inbox_server(options) {
22
- INBOX_URL = options['url'];
23
- INBOX_PATH = options['inbox'];
24
- INBOX_BASE_URL = options['base'];
25
- INBOX_PUBLIC_READABLE = options['inboxPublic'];
26
- JSON_SCHEMA = JSON.parse(fs.readFileSync(options['schema'], { encoding: 'utf-8'}));
27
- let registry = [{ path : `${INBOX_URL}.*` , do: doInbox }];
28
-
29
- // Add other (external defined) registry parts
30
- if (options['registry']) {
31
- const path = options['registry'];
32
- let registry2;
33
- if (typeof path === 'string' || path instanceof String) {
34
- registry2 = JSON.parse(fs.readFileSync(path,{ encoding: 'utf-8'}));
35
- }
36
- else {
37
- registry2 = path;
38
- }
39
- registry = registry.concat(registry2);
40
- }
41
-
42
- start_server({
43
- host: options['host'],
44
- port: options['port'],
45
- base: options['base'],
46
- public: options['public'],
47
- registry: registry
48
- });
49
- }
50
-
51
- function doInbox(req,res) {
52
- if (req.method === 'GET' && INBOX_PUBLIC_READABLE == 1) {
53
- doInboxGET(req,res);
16
+ function doInbox(req,res,opts) {
17
+ if (req.method === 'GET' && opts['inboxPublic'] == 1) {
18
+ doInboxGET(req,res,opts);
54
19
  }
55
- else if (req.method == 'HEAD' && INBOX_PUBLIC_READABLE == 1) {
56
- doInboxHEAD(req,res);
20
+ else if (req.method == 'HEAD' && opts['inboxPublic'] == 1) {
21
+ doInboxHEAD(req,res,opts);
57
22
  }
58
- else if (req.method === 'POST') {
59
- doInboxPOST(req,res);
23
+ else if (req.method === 'POST' && opts['inboxWriteable'] == 1) {
24
+ doInboxPOST(req,res,opts);
60
25
  }
61
26
  else {
62
27
  logger.error(`tried method ${req.method} on inbox : forbidden`);
@@ -65,16 +30,16 @@ function doInbox(req,res) {
65
30
  }
66
31
  }
67
32
 
68
- function doInboxGET(req,res) {
69
- const pathItem = req.url.substring(INBOX_URL.length);
33
+ function doInboxGET(req,res,opts) {
34
+ const pathItem = req.url.substring(opts['url'].length);
70
35
 
71
36
  logger.debug(`doInboxGET (for ${pathItem})`);
72
37
 
73
38
  if (pathItem === '/') {
74
- doInboxGET_Index(req,res);
39
+ doInboxGET_Index(req,res,opts);
75
40
  }
76
41
  else if (pathItem.match(/^\/[A-Za-z0-9_-]+\.jsonld$/)) {
77
- doInboxGET_Read(req,res);
42
+ doInboxGET_Read(req,res,opts);
78
43
  }
79
44
  else {
80
45
  res.writeHead(403);
@@ -82,14 +47,14 @@ function doInboxGET(req,res) {
82
47
  }
83
48
  }
84
49
 
85
- function doInboxHEAD(req,res) {
86
- const pathItem = req.url.substring(INBOX_URL.length);
50
+ function doInboxHEAD(req,res,opts) {
51
+ const pathItem = req.url.substring(opts['url'].length);
87
52
  const id = pathItem.substring(1);
88
53
 
89
54
  logger.debug(`doInboxHEAD (for ${pathItem})`);
90
55
 
91
56
  if (pathItem === '/') {
92
- const meta = getBody(`${id}.meta`);
57
+ const meta = getBody(`${id}.meta`,opts);
93
58
 
94
59
  if (meta) {
95
60
  const metadata = JSON.parse(meta);
@@ -106,7 +71,7 @@ function doInboxHEAD(req,res) {
106
71
  }
107
72
 
108
73
  if (pathItem.match(/^\/[A-Za-z0-9_-]+\.jsonld$/)) {
109
- const result = getBody(id);
74
+ const result = getBody(id,opts);
110
75
 
111
76
  if (! result) {
112
77
  res.writeHead(403);
@@ -114,7 +79,7 @@ function doInboxHEAD(req,res) {
114
79
  return;
115
80
  }
116
81
 
117
- const meta = getBody(`${id}.meta`);
82
+ const meta = getBody(`${id}.meta`,opts);
118
83
 
119
84
  if (meta) {
120
85
  const metadata = JSON.parse(meta);
@@ -137,18 +102,18 @@ function doInboxHEAD(req,res) {
137
102
  }
138
103
  }
139
104
 
140
- function doInboxGET_Index(req,res) {
141
- const notifications = listInbox().map( (e) => {
142
- return INBOX_BASE_URL + '/' + INBOX_URL + e;
105
+ function doInboxGET_Index(req,res,opts) {
106
+ const notifications = listInbox(opts).map( (e) => {
107
+ return opts['base'] + '/' + opts['url'] + e;
143
108
  });
144
109
 
145
110
  const result = {
146
111
  "@context": "http://www.w3.org/ns/ldp",
147
- "@id": INBOX_BASE_URL + '/' + INBOX_URL,
112
+ "@id": opts['base'] + '/' + opts['url'],
148
113
  "contains": notifications
149
114
  };
150
115
 
151
- const meta = getBody(`.meta`);
116
+ const meta = getBody(`.meta`,opts);
152
117
 
153
118
  if (meta) {
154
119
  const metadata = JSON.parse(meta);
@@ -164,13 +129,13 @@ function doInboxGET_Index(req,res) {
164
129
  res.end(JSON.stringify(result,null,2));
165
130
  }
166
131
 
167
- function doInboxGET_Read(req,res) {
168
- const pathItem = req.url.substring(INBOX_URL.length);
132
+ function doInboxGET_Read(req,res,opts) {
133
+ const pathItem = req.url.substring(opts['url'].length);
169
134
  const id = pathItem.substring(1);
170
- const result = getBody(id);
135
+ const result = getBody(id,opts);
171
136
 
172
137
  if (result) {
173
- const meta = getBody(`${id}.meta`);
138
+ const meta = getBody(`${id}.meta`,opts);
174
139
 
175
140
  if (meta) {
176
141
  const metadata = JSON.parse(meta);
@@ -191,8 +156,8 @@ function doInboxGET_Read(req,res) {
191
156
  }
192
157
  }
193
158
 
194
- function doInboxPOST(req,res) {
195
- const pathItem = req.url.substring(INBOX_URL.length);
159
+ function doInboxPOST(req,res,opts) {
160
+ const pathItem = req.url.substring(opts['url'].length);
196
161
 
197
162
  if (pathItem !== '/') {
198
163
  req.writeHead(403);
@@ -222,8 +187,8 @@ function doInboxPOST(req,res) {
222
187
  });
223
188
  req.on('end',() => {
224
189
  logger.debug(postData);
225
- if (checkBody(postData)) {
226
- const id = storeBody(postData);
190
+ if (checkBody(postData,opts)) {
191
+ const id = storeBody(postData,opts);
227
192
  logger.debug(`accepted ${req.url}${id}`);
228
193
  res.setHeader('Location',`${req.url}${id}`);
229
194
  res.writeHead(201);
@@ -237,13 +202,13 @@ function doInboxPOST(req,res) {
237
202
  });
238
203
  }
239
204
 
240
- function listInbox() {
205
+ function listInbox(opts) {
241
206
  const glob = new RegExp("^.*\\.jsonld$");
242
207
 
243
208
  logger.debug(`listInbox()`);
244
209
 
245
210
  try {
246
- const entries = fs.readdirSync(INBOX_PATH).filter( (file) => {
211
+ const entries = fs.readdirSync(opts['inbox']).filter( (file) => {
247
212
  return file.match(glob);
248
213
  });
249
214
  return entries;
@@ -254,21 +219,21 @@ function listInbox() {
254
219
  }
255
220
  }
256
221
 
257
- function getBody(id) {
222
+ function getBody(id,opts) {
258
223
  logger.debug(`getBody(${id})`);
259
224
 
260
225
  try {
261
- return fs.readFileSync(INBOX_PATH + '/' + id, {encoding : 'utf-8'});
226
+ return fs.readFileSync(opts['inbox'] + '/' + id, {encoding : 'utf-8'});
262
227
  }
263
228
  catch(e) {
264
229
  return null;
265
230
  }
266
231
  }
267
232
 
268
- function storeBody(data) {
233
+ function storeBody(data,opts) {
269
234
  try {
270
235
  const id = md5(data);
271
- const newpath = `${INBOX_PATH}/${id}.jsonld`;
236
+ const newpath = `${opts['inbox']}/${id}.jsonld`;
272
237
 
273
238
  if (! fs.existsSync(newpath)) {
274
239
  logger.debug(`storing ${newpath}`);
@@ -285,12 +250,13 @@ function storeBody(data) {
285
250
  }
286
251
  }
287
252
 
288
- function checkBody(data) {
289
- if (! JSON_SCHEMA && ! fs.existsSync(JSON_SCHEMA)) {
253
+ function checkBody(data,opts) {
254
+ if (! (opts['schema'] && fs.existsSync(opts['schema']))) {
290
255
  logger.debug(`no JSON_SCHEMA found`);
291
256
  return true;
292
257
  }
293
258
  try {
259
+ const JSON_SCHEMA = JSON.parse(fs.readFileSync(opts['schema'], { encoding: 'utf-8'}));
294
260
  const json = JSON.parse(data);
295
261
  const v = new Validator();
296
262
  const res = v.validate(json,JSON_SCHEMA);
@@ -310,8 +276,9 @@ function checkBody(data) {
310
276
  }
311
277
 
312
278
  module.exports = {
313
- inbox_server ,
279
+ doInbox,
314
280
  getLogger ,
281
+ parseAsJSON ,
315
282
  backOff_fetch ,
316
283
  fetchOriginal ,
317
284
  moveTo ,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ldn-inbox-server",
3
- "version": "1.4.4",
3
+ "version": "1.4.6",
4
4
  "description": "A demonstration Event Notifications Inbox server",
5
5
  "main": "lib/index.js",
6
6
  "author": "Patrick Hochstenbach <Patrick.Hochstenbach@UGent.be>",
@@ -28,7 +28,7 @@
28
28
  "jsonpath": "^1.1.1",
29
29
  "jsonschema": "^1.4.1",
30
30
  "md5": "^2.3.0",
31
- "mellon-server": "^1.0.8",
31
+ "mellon-server": "^1.0.9",
32
32
  "node-fetch": "1.7.3",
33
33
  "piscina": "^4.4.0",
34
34
  "proper-lockfile": "^4.1.2",