ldn-inbox-server 1.4.5 → 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,12 +11,12 @@ 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
 
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');
@@ -13,51 +13,15 @@ const {
13
13
  const { handle_inbox } = require('../lib/handler');
14
14
  const logger = getLogger();
15
15
 
16
- let INBOX_URL = 'inbox/';
17
- let INBOX_PATH = './inbox';
18
- let INBOX_BASE_URL = 'http://localhost:8000';
19
- let INBOX_PUBLIC_READABLE = 0;
20
- let JSON_SCHEMA = '';
21
-
22
- function inbox_server(options) {
23
- INBOX_URL = options['url'];
24
- INBOX_PATH = options['inbox'];
25
- INBOX_BASE_URL = options['base'];
26
- INBOX_PUBLIC_READABLE = options['inboxPublic'];
27
- JSON_SCHEMA = JSON.parse(fs.readFileSync(options['schema'], { encoding: 'utf-8'}));
28
- let registry = [{ path : `${INBOX_URL}.*` , do: doInbox }];
29
-
30
- // Add other (external defined) registry parts
31
- if (options['registry']) {
32
- const path = options['registry'];
33
- let registry2;
34
- if (typeof path === 'string' || path instanceof String) {
35
- registry2 = JSON.parse(fs.readFileSync(path,{ encoding: 'utf-8'}));
36
- }
37
- else {
38
- registry2 = path;
39
- }
40
- registry = registry.concat(registry2);
41
- }
42
-
43
- start_server({
44
- host: options['host'],
45
- port: options['port'],
46
- base: options['base'],
47
- public: options['public'],
48
- registry: registry
49
- });
50
- }
51
-
52
- function doInbox(req,res) {
53
- if (req.method === 'GET' && INBOX_PUBLIC_READABLE == 1) {
54
- doInboxGET(req,res);
16
+ function doInbox(req,res,opts) {
17
+ if (req.method === 'GET' && opts['inboxPublic'] == 1) {
18
+ doInboxGET(req,res,opts);
55
19
  }
56
- else if (req.method == 'HEAD' && INBOX_PUBLIC_READABLE == 1) {
57
- doInboxHEAD(req,res);
20
+ else if (req.method == 'HEAD' && opts['inboxPublic'] == 1) {
21
+ doInboxHEAD(req,res,opts);
58
22
  }
59
- else if (req.method === 'POST') {
60
- doInboxPOST(req,res);
23
+ else if (req.method === 'POST' && opts['inboxWriteable'] == 1) {
24
+ doInboxPOST(req,res,opts);
61
25
  }
62
26
  else {
63
27
  logger.error(`tried method ${req.method} on inbox : forbidden`);
@@ -66,16 +30,16 @@ function doInbox(req,res) {
66
30
  }
67
31
  }
68
32
 
69
- function doInboxGET(req,res) {
70
- const pathItem = req.url.substring(INBOX_URL.length);
33
+ function doInboxGET(req,res,opts) {
34
+ const pathItem = req.url.substring(opts['url'].length);
71
35
 
72
36
  logger.debug(`doInboxGET (for ${pathItem})`);
73
37
 
74
38
  if (pathItem === '/') {
75
- doInboxGET_Index(req,res);
39
+ doInboxGET_Index(req,res,opts);
76
40
  }
77
41
  else if (pathItem.match(/^\/[A-Za-z0-9_-]+\.jsonld$/)) {
78
- doInboxGET_Read(req,res);
42
+ doInboxGET_Read(req,res,opts);
79
43
  }
80
44
  else {
81
45
  res.writeHead(403);
@@ -83,14 +47,14 @@ function doInboxGET(req,res) {
83
47
  }
84
48
  }
85
49
 
86
- function doInboxHEAD(req,res) {
87
- const pathItem = req.url.substring(INBOX_URL.length);
50
+ function doInboxHEAD(req,res,opts) {
51
+ const pathItem = req.url.substring(opts['url'].length);
88
52
  const id = pathItem.substring(1);
89
53
 
90
54
  logger.debug(`doInboxHEAD (for ${pathItem})`);
91
55
 
92
56
  if (pathItem === '/') {
93
- const meta = getBody(`${id}.meta`);
57
+ const meta = getBody(`${id}.meta`,opts);
94
58
 
95
59
  if (meta) {
96
60
  const metadata = JSON.parse(meta);
@@ -107,7 +71,7 @@ function doInboxHEAD(req,res) {
107
71
  }
108
72
 
109
73
  if (pathItem.match(/^\/[A-Za-z0-9_-]+\.jsonld$/)) {
110
- const result = getBody(id);
74
+ const result = getBody(id,opts);
111
75
 
112
76
  if (! result) {
113
77
  res.writeHead(403);
@@ -115,7 +79,7 @@ function doInboxHEAD(req,res) {
115
79
  return;
116
80
  }
117
81
 
118
- const meta = getBody(`${id}.meta`);
82
+ const meta = getBody(`${id}.meta`,opts);
119
83
 
120
84
  if (meta) {
121
85
  const metadata = JSON.parse(meta);
@@ -138,18 +102,18 @@ function doInboxHEAD(req,res) {
138
102
  }
139
103
  }
140
104
 
141
- function doInboxGET_Index(req,res) {
142
- const notifications = listInbox().map( (e) => {
143
- 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;
144
108
  });
145
109
 
146
110
  const result = {
147
111
  "@context": "http://www.w3.org/ns/ldp",
148
- "@id": INBOX_BASE_URL + '/' + INBOX_URL,
112
+ "@id": opts['base'] + '/' + opts['url'],
149
113
  "contains": notifications
150
114
  };
151
115
 
152
- const meta = getBody(`.meta`);
116
+ const meta = getBody(`.meta`,opts);
153
117
 
154
118
  if (meta) {
155
119
  const metadata = JSON.parse(meta);
@@ -165,13 +129,13 @@ function doInboxGET_Index(req,res) {
165
129
  res.end(JSON.stringify(result,null,2));
166
130
  }
167
131
 
168
- function doInboxGET_Read(req,res) {
169
- const pathItem = req.url.substring(INBOX_URL.length);
132
+ function doInboxGET_Read(req,res,opts) {
133
+ const pathItem = req.url.substring(opts['url'].length);
170
134
  const id = pathItem.substring(1);
171
- const result = getBody(id);
135
+ const result = getBody(id,opts);
172
136
 
173
137
  if (result) {
174
- const meta = getBody(`${id}.meta`);
138
+ const meta = getBody(`${id}.meta`,opts);
175
139
 
176
140
  if (meta) {
177
141
  const metadata = JSON.parse(meta);
@@ -192,8 +156,8 @@ function doInboxGET_Read(req,res) {
192
156
  }
193
157
  }
194
158
 
195
- function doInboxPOST(req,res) {
196
- const pathItem = req.url.substring(INBOX_URL.length);
159
+ function doInboxPOST(req,res,opts) {
160
+ const pathItem = req.url.substring(opts['url'].length);
197
161
 
198
162
  if (pathItem !== '/') {
199
163
  req.writeHead(403);
@@ -223,8 +187,8 @@ function doInboxPOST(req,res) {
223
187
  });
224
188
  req.on('end',() => {
225
189
  logger.debug(postData);
226
- if (checkBody(postData)) {
227
- const id = storeBody(postData);
190
+ if (checkBody(postData,opts)) {
191
+ const id = storeBody(postData,opts);
228
192
  logger.debug(`accepted ${req.url}${id}`);
229
193
  res.setHeader('Location',`${req.url}${id}`);
230
194
  res.writeHead(201);
@@ -238,13 +202,13 @@ function doInboxPOST(req,res) {
238
202
  });
239
203
  }
240
204
 
241
- function listInbox() {
205
+ function listInbox(opts) {
242
206
  const glob = new RegExp("^.*\\.jsonld$");
243
207
 
244
208
  logger.debug(`listInbox()`);
245
209
 
246
210
  try {
247
- const entries = fs.readdirSync(INBOX_PATH).filter( (file) => {
211
+ const entries = fs.readdirSync(opts['inbox']).filter( (file) => {
248
212
  return file.match(glob);
249
213
  });
250
214
  return entries;
@@ -255,21 +219,21 @@ function listInbox() {
255
219
  }
256
220
  }
257
221
 
258
- function getBody(id) {
222
+ function getBody(id,opts) {
259
223
  logger.debug(`getBody(${id})`);
260
224
 
261
225
  try {
262
- return fs.readFileSync(INBOX_PATH + '/' + id, {encoding : 'utf-8'});
226
+ return fs.readFileSync(opts['inbox'] + '/' + id, {encoding : 'utf-8'});
263
227
  }
264
228
  catch(e) {
265
229
  return null;
266
230
  }
267
231
  }
268
232
 
269
- function storeBody(data) {
233
+ function storeBody(data,opts) {
270
234
  try {
271
235
  const id = md5(data);
272
- const newpath = `${INBOX_PATH}/${id}.jsonld`;
236
+ const newpath = `${opts['inbox']}/${id}.jsonld`;
273
237
 
274
238
  if (! fs.existsSync(newpath)) {
275
239
  logger.debug(`storing ${newpath}`);
@@ -286,12 +250,13 @@ function storeBody(data) {
286
250
  }
287
251
  }
288
252
 
289
- function checkBody(data) {
290
- if (! JSON_SCHEMA && ! fs.existsSync(JSON_SCHEMA)) {
253
+ function checkBody(data,opts) {
254
+ if (! (opts['schema'] && fs.existsSync(opts['schema']))) {
291
255
  logger.debug(`no JSON_SCHEMA found`);
292
256
  return true;
293
257
  }
294
258
  try {
259
+ const JSON_SCHEMA = JSON.parse(fs.readFileSync(opts['schema'], { encoding: 'utf-8'}));
295
260
  const json = JSON.parse(data);
296
261
  const v = new Validator();
297
262
  const res = v.validate(json,JSON_SCHEMA);
@@ -311,7 +276,7 @@ function checkBody(data) {
311
276
  }
312
277
 
313
278
  module.exports = {
314
- inbox_server ,
279
+ doInbox,
315
280
  getLogger ,
316
281
  parseAsJSON ,
317
282
  backOff_fetch ,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ldn-inbox-server",
3
- "version": "1.4.5",
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",