forked from SolidOS/solid-logic
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaclLogic.js
More file actions
117 lines (117 loc) · 4 KB
/
Copy pathaclLogic.js
File metadata and controls
117 lines (117 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { graph, Namespace, serialize, sym } from 'rdflib';
import { ns as namespace } from '../util/ns';
export const ACL_LINK = sym('http://www.iana.org/assignments/link-relations/acl');
export function createAclLogic(store) {
const ns = namespace;
async function findAclDocUrl(url) {
await store.fetcher.load(url);
const docNode = store.any(url, ACL_LINK);
if (!docNode) {
throw new Error(`No ACL link discovered for ${url}`);
}
return docNode.value;
}
/**
* Simple Access Control
*
* This function sets up a simple default ACL for a resource, with
* RWC for the owner, and a specified access (default none) for the public.
* In all cases owner has read write control.
* Parameter lists modes allowed to public
*
* @param options
* @param options.public eg ['Read', 'Write']
*
* @returns Resolves with aclDoc uri on successful write
*/
function setACLUserPublic(docURI, me, options) {
const aclDoc = store.any(store.sym(docURI), ACL_LINK);
return Promise.resolve()
.then(() => {
if (aclDoc) {
return aclDoc;
}
return fetchACLRel(docURI).catch(err => {
throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`);
});
})
.then(aclDoc => {
const aclText = genACLText(docURI, me, aclDoc.uri, options);
if (!store.fetcher) {
throw new Error('Cannot PUT this, store has no fetcher');
}
return store.fetcher
.webOperation('PUT', aclDoc.uri, {
data: aclText,
contentType: 'text/turtle'
})
.then(result => {
if (!result.ok) {
throw new Error('Error writing ACL text: ' + result.error);
}
return aclDoc;
});
});
}
/**
* @param docURI
* @returns
*/
function fetchACLRel(docURI) {
const fetcher = store.fetcher;
if (!fetcher) {
throw new Error('Cannot fetch ACL rel, store has no fetcher');
}
return fetcher.load(docURI).then(result => {
if (!result.ok) {
throw new Error('fetchACLRel: While loading:' + result.error);
}
const aclDoc = store.any(store.sym(docURI), ACL_LINK);
if (!aclDoc) {
throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI);
}
return aclDoc;
});
}
/**
* @param docURI
* @param me
* @param aclURI
* @param options
*
* @returns Serialized ACL
*/
function genACLText(docURI, me, aclURI, options = {}) {
const optPublic = options.public || [];
const g = graph();
const auth = Namespace('http://www.w3.org/ns/auth/acl#');
let a = g.sym(`${aclURI}#a1`);
const acl = g.sym(aclURI);
const doc = g.sym(docURI);
g.add(a, ns.rdf('type'), auth('Authorization'), acl);
g.add(a, auth('accessTo'), doc, acl);
if (options.defaultForNew) {
g.add(a, auth('default'), doc, acl);
}
g.add(a, auth('agent'), me, acl);
g.add(a, auth('mode'), auth('Read'), acl);
g.add(a, auth('mode'), auth('Write'), acl);
g.add(a, auth('mode'), auth('Control'), acl);
if (optPublic.length) {
a = g.sym(`${aclURI}#a2`);
g.add(a, ns.rdf('type'), auth('Authorization'), acl);
g.add(a, auth('accessTo'), doc, acl);
g.add(a, auth('agentClass'), ns.foaf('Agent'), acl);
for (let p = 0; p < optPublic.length; p++) {
g.add(a, auth('mode'), auth(optPublic[p]), acl); // Like 'Read' etc
}
}
return serialize(acl, g, aclURI);
}
return {
findAclDocUrl,
setACLUserPublic,
genACLText
};
}
//# sourceMappingURL=aclLogic.js.map