solid-server 5.8.2 → 5.8.3
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/.github/workflows/ci.yml +1 -1
- package/lib/handlers/delete.js +0 -3
- package/lib/handlers/notify.js +30 -12
- package/lib/handlers/patch.js +0 -4
- package/lib/handlers/post.js +0 -5
- package/lib/handlers/put.js +0 -3
- package/lib/rdf-notification-template.js +22 -10
- package/package.json +3 -3
package/.github/workflows/ci.yml
CHANGED
package/lib/handlers/delete.js
CHANGED
|
@@ -6,12 +6,9 @@ async function handler (req, res, next) {
|
|
|
6
6
|
debug('DELETE -- Request on' + req.originalUrl)
|
|
7
7
|
|
|
8
8
|
const ldp = req.app.locals.ldp
|
|
9
|
-
const prep = req.app.locals.prep
|
|
10
9
|
try {
|
|
11
10
|
await ldp.delete(req)
|
|
12
11
|
debug('DELETE -- Ok.')
|
|
13
|
-
// Add event-id for notifications
|
|
14
|
-
prep && res.setHeader('Event-ID', res.setEventID())
|
|
15
12
|
res.sendStatus(200)
|
|
16
13
|
next()
|
|
17
14
|
} catch (err) {
|
package/lib/handlers/notify.js
CHANGED
|
@@ -38,18 +38,32 @@ function getParentActivity (method, status) {
|
|
|
38
38
|
return 'Update'
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function filterMillseconds (isoDate) {
|
|
42
|
+
return `${isoDate.substring(0, 19)}${isoDate.substring(23)}`
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getDate (date) {
|
|
46
|
+
if (date) {
|
|
47
|
+
const eventDate = new Date(date)
|
|
48
|
+
if (!isNaN(eventDate.valueOf())) {
|
|
49
|
+
return filterMillseconds(eventDate.toISOString())
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const now = new Date()
|
|
53
|
+
return filterMillseconds(now.toISOString())
|
|
54
|
+
}
|
|
55
|
+
|
|
41
56
|
function handler (req, res, next) {
|
|
42
57
|
const { trigger, defaultNotification } = res.events.prep
|
|
43
58
|
|
|
44
59
|
const { method, path } = req
|
|
45
60
|
const { statusCode } = res
|
|
46
|
-
const eventID = res.
|
|
61
|
+
const eventID = res.setEventID()
|
|
47
62
|
const fullUrl = new URL(path, `${req.protocol}://${req.hostname}/`)
|
|
48
63
|
|
|
49
64
|
// Date is a hack since node does not seem to provide access to send date.
|
|
50
65
|
// Date needs to be shared with parent notification
|
|
51
|
-
const eventDate = res._header.match(/^Date: (.*?)$/m)?.[1]
|
|
52
|
-
new Date().toUTCString()
|
|
66
|
+
const eventDate = getDate(res._header.match(/^Date: (.*?)$/m)?.[1])
|
|
53
67
|
|
|
54
68
|
// If the resource itself newly created,
|
|
55
69
|
// it could not have been subscribed for notifications already
|
|
@@ -61,18 +75,19 @@ function handler (req, res, next) {
|
|
|
61
75
|
) {
|
|
62
76
|
const mediaType = negotiatedFields['content-type']
|
|
63
77
|
const activity = getActivity(method, path)
|
|
64
|
-
const
|
|
78
|
+
const object = activity === 'Add'
|
|
65
79
|
? res.getHeader('location')
|
|
80
|
+
: String(fullUrl)
|
|
81
|
+
const target = activity === 'Add'
|
|
82
|
+
? String(fullUrl)
|
|
66
83
|
: undefined
|
|
67
84
|
if (ALLOWED_RDF_MIME_TYPES.includes(mediaType?.[0])) {
|
|
68
85
|
return `${headerTemplate(negotiatedFields)}\r\n${solidRDFTemplate({
|
|
69
86
|
activity,
|
|
70
87
|
eventID,
|
|
71
|
-
object
|
|
88
|
+
object,
|
|
72
89
|
target,
|
|
73
90
|
date: eventDate,
|
|
74
|
-
// We use eTag as a proxy for state for now
|
|
75
|
-
state: res.getHeader('ETag'),
|
|
76
91
|
mediaType
|
|
77
92
|
})}`
|
|
78
93
|
} else {
|
|
@@ -93,7 +108,10 @@ function handler (req, res, next) {
|
|
|
93
108
|
// POST in Solid creates a child resource
|
|
94
109
|
const parent = getParent(path)
|
|
95
110
|
if (parent && method !== 'POST') {
|
|
96
|
-
|
|
111
|
+
res.setEventID({
|
|
112
|
+
path: parent,
|
|
113
|
+
id: eventID
|
|
114
|
+
})
|
|
97
115
|
const parentUrl = new URL(parent, fullUrl)
|
|
98
116
|
try {
|
|
99
117
|
trigger({
|
|
@@ -103,15 +121,15 @@ function handler (req, res, next) {
|
|
|
103
121
|
) {
|
|
104
122
|
const mediaType = negotiatedFields['content-type']
|
|
105
123
|
const activity = getParentActivity(method, statusCode)
|
|
106
|
-
const
|
|
124
|
+
const object = activity === 'Update' ? String(parentUrl) : String(fullUrl)
|
|
125
|
+
const target = activity === 'Update' ? undefined : String(parentUrl)
|
|
107
126
|
if (ALLOWED_RDF_MIME_TYPES.includes(mediaType?.[0])) {
|
|
108
127
|
return `${headerTemplate(negotiatedFields)}\r\n${solidRDFTemplate({
|
|
109
128
|
activity,
|
|
110
|
-
eventID
|
|
129
|
+
eventID,
|
|
111
130
|
date: eventDate,
|
|
112
|
-
object
|
|
131
|
+
object,
|
|
113
132
|
target,
|
|
114
|
-
eTag: undefined,
|
|
115
133
|
mediaType
|
|
116
134
|
})}`
|
|
117
135
|
}
|
package/lib/handlers/patch.js
CHANGED
|
@@ -39,7 +39,6 @@ function contentForNew (contentType) {
|
|
|
39
39
|
// Handles a PATCH request
|
|
40
40
|
async function patchHandler (req, res, next) {
|
|
41
41
|
debug(`PATCH -- ${req.originalUrl}`)
|
|
42
|
-
const prep = req.app.locals.prep
|
|
43
42
|
try {
|
|
44
43
|
// Obtain details of the target resource
|
|
45
44
|
const ldp = req.app.locals.ldp
|
|
@@ -91,9 +90,6 @@ async function patchHandler (req, res, next) {
|
|
|
91
90
|
await applyPatch(patchObject, graph, url)
|
|
92
91
|
return writeGraph(graph, resource, ldp.resourceMapper.resolveFilePath(req.hostname), ldp.serverUri)
|
|
93
92
|
})
|
|
94
|
-
|
|
95
|
-
// Add event-id for notifications
|
|
96
|
-
prep && res.setHeader('Event-ID', res.setEventID())
|
|
97
93
|
// Send the status and result to the client
|
|
98
94
|
res.status(resourceExists ? 200 : 201)
|
|
99
95
|
res.send(result)
|
package/lib/handlers/post.js
CHANGED
|
@@ -11,7 +11,6 @@ const getContentType = require('../utils').getContentType
|
|
|
11
11
|
|
|
12
12
|
async function handler (req, res, next) {
|
|
13
13
|
const ldp = req.app.locals.ldp
|
|
14
|
-
const prep = req.app.locals.prep
|
|
15
14
|
const contentType = getContentType(req.headers)
|
|
16
15
|
debug('content-type is ', contentType)
|
|
17
16
|
// Handle SPARQL(-update?) query
|
|
@@ -73,8 +72,6 @@ async function handler (req, res, next) {
|
|
|
73
72
|
// Handled by backpressure of streams!
|
|
74
73
|
busboy.on('finish', function () {
|
|
75
74
|
debug('Done storing files')
|
|
76
|
-
// Add event-id for notifications
|
|
77
|
-
prep && res.setHeader('Event-ID', res.setEventID())
|
|
78
75
|
res.sendStatus(200)
|
|
79
76
|
next()
|
|
80
77
|
})
|
|
@@ -94,8 +91,6 @@ async function handler (req, res, next) {
|
|
|
94
91
|
debug('File stored in ' + resourcePath)
|
|
95
92
|
header.addLinks(res, links)
|
|
96
93
|
res.set('Location', resourcePath)
|
|
97
|
-
// Add event-id for notifications
|
|
98
|
-
prep && res.setHeader('Event-ID', res.setEventID())
|
|
99
94
|
res.sendStatus(201)
|
|
100
95
|
next()
|
|
101
96
|
},
|
package/lib/handlers/put.js
CHANGED
|
@@ -59,7 +59,6 @@ async function checkPermission (request, resourceExists) {
|
|
|
59
59
|
// TODO could be renamed as putResource (it now covers container and non-container)
|
|
60
60
|
async function putStream (req, res, next, stream = req) {
|
|
61
61
|
const ldp = req.app.locals.ldp
|
|
62
|
-
const prep = req.app.locals.prep
|
|
63
62
|
// try {
|
|
64
63
|
// Obtain details of the target resource
|
|
65
64
|
let resourceExists = true
|
|
@@ -78,8 +77,6 @@ async function putStream (req, res, next, stream = req) {
|
|
|
78
77
|
// Fails with Append on existing resource
|
|
79
78
|
if (!req.originalUrl.endsWith('.acl')) await checkPermission(req, resourceExists)
|
|
80
79
|
await ldp.put(req, stream, getContentType(req.headers))
|
|
81
|
-
// Add event-id for notifications
|
|
82
|
-
prep && res.setHeader('Event-ID', res.setEventID())
|
|
83
80
|
res.sendStatus(resourceExists ? 204 : 201)
|
|
84
81
|
return next()
|
|
85
82
|
} catch (err) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
const uuid = require('uuid')
|
|
2
|
+
|
|
1
3
|
const CONTEXT_ACTIVITYSTREAMS = 'https://www.w3.org/ns/activitystreams'
|
|
2
4
|
const CONTEXT_NOTIFICATION = 'https://www.w3.org/ns/solid/notification/v1'
|
|
3
5
|
const CONTEXT_XML_SCHEMA = 'http://www.w3.org/2001/XMLSchema'
|
|
4
6
|
|
|
5
7
|
function generateJSONNotification ({
|
|
6
8
|
activity: type,
|
|
7
|
-
|
|
9
|
+
eventID,
|
|
8
10
|
date: published,
|
|
9
11
|
object,
|
|
10
12
|
target,
|
|
@@ -13,30 +15,40 @@ function generateJSONNotification ({
|
|
|
13
15
|
return {
|
|
14
16
|
published,
|
|
15
17
|
type,
|
|
16
|
-
id
|
|
18
|
+
id: `urn:uuid:${uuid.v4()}`,
|
|
19
|
+
...(eventID) && { state: eventID },
|
|
17
20
|
object,
|
|
18
21
|
...(type === 'Add') && { target },
|
|
19
|
-
...(type === 'Remove') && { origin: target }
|
|
20
|
-
...(state) && { state }
|
|
22
|
+
...(type === 'Remove') && { origin: target }
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
function generateTurtleNotification ({
|
|
25
27
|
activity,
|
|
26
|
-
|
|
28
|
+
eventID,
|
|
27
29
|
date,
|
|
28
30
|
object,
|
|
29
|
-
target
|
|
30
|
-
state = undefined
|
|
31
|
+
target
|
|
31
32
|
}) {
|
|
32
|
-
|
|
33
|
+
let targetLine = ''
|
|
34
|
+
let stateLine = ''
|
|
35
|
+
|
|
36
|
+
if (activity === 'Add') {
|
|
37
|
+
targetLine = `\n as:target <${target}> ;`
|
|
38
|
+
}
|
|
39
|
+
if (activity === 'Remove') {
|
|
40
|
+
targetLine = `\n as:origin <${target}> ;`
|
|
41
|
+
}
|
|
42
|
+
if (eventID) {
|
|
43
|
+
stateLine = `\n notify:state "${eventID}" ;`
|
|
44
|
+
}
|
|
33
45
|
|
|
34
46
|
return `@prefix as: <${CONTEXT_ACTIVITYSTREAMS}#> .
|
|
35
47
|
@prefix notify: <${CONTEXT_NOTIFICATION}#> .
|
|
36
48
|
@prefix xsd: <${CONTEXT_XML_SCHEMA}#> .
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
as:object
|
|
50
|
+
<urn:uuid:${uuid.v4()}> a as:${activity} ;
|
|
51
|
+
as:object <${object}> ;${targetLine}${stateLine}
|
|
40
52
|
as:published "${date}"^^xsd:dateTime .`.replaceAll('\n', '\r\n')
|
|
41
53
|
}
|
|
42
54
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solid-server",
|
|
3
3
|
"description": "Solid server on top of the file-system",
|
|
4
|
-
"version": "5.8.
|
|
4
|
+
"version": "5.8.3",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Tim Berners-Lee",
|
|
7
7
|
"email": "timbl@w3.org"
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"express-accept-events": "^0.3.0",
|
|
78
78
|
"express-handlebars": "^5.3.5",
|
|
79
79
|
"express-negotiate-events": "^0.3.0",
|
|
80
|
-
"express-prep": "^0.6.
|
|
80
|
+
"express-prep": "^0.6.4",
|
|
81
81
|
"express-session": "^1.18.0",
|
|
82
82
|
"extend": "^3.0.2",
|
|
83
83
|
"from2": "^2.3.0",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"ip-range-check": "0.2.0",
|
|
93
93
|
"is-ip": "^3.1.0",
|
|
94
94
|
"li": "^1.3.0",
|
|
95
|
-
"mashlib": "^1.
|
|
95
|
+
"mashlib": "^1.10.2",
|
|
96
96
|
"mime-types": "^2.1.35",
|
|
97
97
|
"negotiator": "^0.6.3",
|
|
98
98
|
"node-fetch": "^2.7.0",
|