solid-logic 1.3.17-f7bdc345 → 2.0.0
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/.babelrc +0 -0
- package/.eslintrc.js +0 -0
- package/.github/workflows/ci.yml +0 -0
- package/.github/workflows/release.yml +0 -0
- package/.nvmrc +0 -0
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/jest.config.js +0 -0
- package/lib/acl/aclLogic.d.ts +3 -30
- package/lib/acl/aclLogic.d.ts.map +1 -1
- package/lib/acl/aclLogic.js +152 -119
- package/lib/acl/aclLogic.js.map +1 -1
- package/lib/authSession/authSession.d.ts +0 -0
- package/lib/authSession/authSession.d.ts.map +0 -0
- package/lib/authSession/authSession.js +0 -0
- package/lib/authSession/authSession.js.map +0 -0
- package/lib/authn/SolidAuthnLogic.d.ts +0 -0
- package/lib/authn/SolidAuthnLogic.d.ts.map +1 -1
- package/lib/authn/SolidAuthnLogic.js +2 -2
- package/lib/authn/SolidAuthnLogic.js.map +1 -1
- package/lib/authn/authUtil.d.ts +0 -0
- package/lib/authn/authUtil.d.ts.map +0 -0
- package/lib/authn/authUtil.js +0 -0
- package/lib/authn/authUtil.js.map +0 -0
- package/lib/chat/chatLogic.d.ts +3 -0
- package/lib/chat/chatLogic.d.ts.map +1 -0
- package/lib/chat/{ChatLogic.js → chatLogic.js} +82 -86
- package/lib/chat/chatLogic.js.map +1 -0
- package/lib/inbox/inboxLogic.d.ts +3 -0
- package/lib/inbox/inboxLogic.d.ts.map +1 -0
- package/lib/inbox/{InboxLogic.js → inboxLogic.js} +58 -64
- package/lib/inbox/inboxLogic.js.map +1 -0
- package/lib/index.d.ts +6 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -38
- package/lib/index.js.map +1 -1
- package/lib/issuer/issuerLogic.d.ts +0 -0
- package/lib/issuer/issuerLogic.d.ts.map +0 -0
- package/lib/issuer/issuerLogic.js +1 -1
- package/lib/issuer/issuerLogic.js.map +1 -1
- package/lib/logic/CustomError.d.ts +4 -0
- package/lib/logic/CustomError.d.ts.map +1 -1
- package/lib/logic/CustomError.js +17 -1
- package/lib/logic/CustomError.js.map +1 -1
- package/lib/logic/solidLogic.d.ts +6 -0
- package/lib/logic/solidLogic.d.ts.map +1 -0
- package/lib/logic/solidLogic.js +92 -0
- package/lib/logic/solidLogic.js.map +1 -0
- package/lib/logic/solidLogicSingleton.d.ts +1 -2
- package/lib/logic/solidLogicSingleton.d.ts.map +1 -1
- package/lib/logic/solidLogicSingleton.js +3 -3
- package/lib/logic/solidLogicSingleton.js.map +1 -1
- package/lib/profile/profileLogic.d.ts +3 -0
- package/lib/profile/profileLogic.d.ts.map +1 -0
- package/lib/profile/profileLogic.js +246 -0
- package/lib/profile/profileLogic.js.map +1 -0
- package/lib/typeIndex/typeIndexLogic.d.ts +2 -21
- package/lib/typeIndex/typeIndexLogic.d.ts.map +1 -1
- package/lib/typeIndex/typeIndexLogic.js +304 -296
- package/lib/typeIndex/typeIndexLogic.js.map +1 -1
- package/lib/types.d.ts +82 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +0 -0
- package/lib/types.js.map +0 -0
- package/lib/util/containerLogic.d.ts +11 -0
- package/lib/util/containerLogic.d.ts.map +1 -0
- package/lib/{profile/ProfileLogic.js → util/containerLogic.js} +53 -44
- package/lib/util/containerLogic.js.map +1 -0
- package/lib/util/debug.d.ts +0 -0
- package/lib/util/debug.d.ts.map +0 -0
- package/lib/util/debug.js +0 -0
- package/lib/util/debug.js.map +0 -0
- package/lib/util/ns.d.ts +2 -0
- package/lib/util/ns.d.ts.map +1 -0
- package/lib/util/ns.js +34 -0
- package/lib/util/ns.js.map +1 -0
- package/lib/util/utilityLogic.d.ts +15 -0
- package/lib/util/utilityLogic.d.ts.map +1 -0
- package/lib/util/utilityLogic.js +272 -0
- package/lib/util/utilityLogic.js.map +1 -0
- package/lib/util/utils.d.ts +8 -0
- package/lib/util/utils.d.ts.map +1 -0
- package/lib/util/utils.js +48 -0
- package/lib/util/utils.js.map +1 -0
- package/package.json +15 -15
- package/src/acl/aclLogic.ts +137 -118
- package/src/authSession/authSession.ts +0 -0
- package/src/authn/SolidAuthnLogic.ts +3 -2
- package/src/authn/authUtil.ts +0 -0
- package/src/chat/chatLogic.ts +225 -0
- package/src/inbox/inboxLogic.ts +58 -0
- package/src/index.ts +11 -42
- package/src/issuer/issuerLogic.ts +1 -1
- package/src/logic/CustomError.ts +5 -1
- package/src/logic/solidLogic.ts +75 -0
- package/src/logic/solidLogicSingleton.ts +3 -3
- package/src/profile/profileLogic.ts +126 -0
- package/src/typeIndex/typeIndexLogic.ts +175 -182
- package/src/types.ts +83 -4
- package/src/util/containerLogic.ts +54 -0
- package/src/util/debug.ts +0 -0
- package/src/util/ns.ts +5 -0
- package/src/util/utilityLogic.ts +155 -0
- package/src/util/utils.ts +52 -0
- package/test/aclLogic.test.ts +13 -4
- package/test/authUtil.test.ts +0 -0
- package/test/chatLogic.test.ts +70 -71
- package/test/container.test.ts +56 -0
- package/test/helpers/dataSetup.ts +134 -0
- package/test/helpers/setup.ts +4 -0
- package/test/inboxLogic.test.ts +39 -38
- package/test/logic.test.ts +10 -9
- package/test/profileLogic.test.ts +246 -0
- package/test/solidAuthLogic.test.ts +0 -0
- package/test/typeIndexLogic.test.ts +487 -30
- package/test/utilityLogic.test.ts +172 -126
- package/test/utils.test.ts +32 -0
- package/tsconfig.json +0 -0
- package/lib/chat/ChatLogic.d.ts +0 -26
- package/lib/chat/ChatLogic.d.ts.map +0 -1
- package/lib/chat/ChatLogic.js.map +0 -1
- package/lib/chat/determineChatContainer.d.ts +0 -3
- package/lib/chat/determineChatContainer.d.ts.map +0 -1
- package/lib/chat/determineChatContainer.js +0 -12
- package/lib/chat/determineChatContainer.js.map +0 -1
- package/lib/discovery/discoveryLogic.d.ts +0 -37
- package/lib/discovery/discoveryLogic.d.ts.map +0 -1
- package/lib/discovery/discoveryLogic.js +0 -502
- package/lib/discovery/discoveryLogic.js.map +0 -1
- package/lib/inbox/InboxLogic.d.ts +0 -18
- package/lib/inbox/InboxLogic.d.ts.map +0 -1
- package/lib/inbox/InboxLogic.js.map +0 -1
- package/lib/logic/SolidLogic.d.ts +0 -45
- package/lib/logic/SolidLogic.d.ts.map +0 -1
- package/lib/logic/SolidLogic.js +0 -320
- package/lib/logic/SolidLogic.js.map +0 -1
- package/lib/profile/ProfileLogic.d.ts +0 -13
- package/lib/profile/ProfileLogic.d.ts.map +0 -1
- package/lib/profile/ProfileLogic.js.map +0 -1
- package/lib/util/UtilityLogic.d.ts +0 -27
- package/lib/util/UtilityLogic.d.ts.map +0 -1
- package/lib/util/UtilityLogic.js +0 -216
- package/lib/util/UtilityLogic.js.map +0 -1
- package/lib/util/uri.d.ts +0 -3
- package/lib/util/uri.d.ts.map +0 -1
- package/lib/util/uri.js +0 -9
- package/lib/util/uri.js.map +0 -1
- package/src/chat/ChatLogic.ts +0 -244
- package/src/chat/determineChatContainer.ts +0 -14
- package/src/discovery/discoveryLogic.ts +0 -269
- package/src/inbox/InboxLogic.ts +0 -66
- package/src/logic/SolidLogic.ts +0 -259
- package/src/profile/ProfileLogic.ts +0 -44
- package/src/util/UtilityLogic.ts +0 -144
- package/src/util/uri.ts +0 -5
- package/test/discoveryLogic.test.ts +0 -712
package/src/logic/SolidLogic.ts
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { Session } from "@inrupt/solid-client-authn-browser";
|
|
2
|
-
import * as rdf from "rdflib";
|
|
3
|
-
import { NamedNode, Statement, LiveStore } from "rdflib";
|
|
4
|
-
import solidNamespace from "solid-namespace";
|
|
5
|
-
import { SolidAuthnLogic } from "../authn/SolidAuthnLogic";
|
|
6
|
-
import { ChatLogic } from "../chat/ChatLogic";
|
|
7
|
-
import { ProfileLogic } from "../profile/ProfileLogic";
|
|
8
|
-
import { AuthnLogic, SolidNamespace } from "../types";
|
|
9
|
-
import * as debug from "../util/debug";
|
|
10
|
-
import { UtilityLogic } from "../util/UtilityLogic";
|
|
11
|
-
import { CrossOriginForbiddenError, FetchError, NotFoundError, SameOriginForbiddenError, UnauthorizedError } from "./CustomError";
|
|
12
|
-
/*
|
|
13
|
-
** It is important to distinquish `fetch`, a function provided by the browser
|
|
14
|
-
** and `Fetcher`, a helper object for the rdflib Store which turns it
|
|
15
|
-
** into a `ConnectedStore` or a `LiveStore`. A Fetcher object is
|
|
16
|
-
** available at store.fetcher, and `fetch` function at `store.fetcher._fetch`,
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const ns: SolidNamespace = solidNamespace(rdf);
|
|
20
|
-
|
|
21
|
-
export class SolidLogic {
|
|
22
|
-
cache: {
|
|
23
|
-
profileDocument: {
|
|
24
|
-
[WebID: string]: NamedNode;
|
|
25
|
-
};
|
|
26
|
-
preferencesFile: {
|
|
27
|
-
[WebID: string]: NamedNode;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
store: LiveStore;
|
|
32
|
-
me: string | undefined;
|
|
33
|
-
chat: ChatLogic;
|
|
34
|
-
profile: ProfileLogic;
|
|
35
|
-
authn: AuthnLogic;
|
|
36
|
-
util: UtilityLogic;
|
|
37
|
-
|
|
38
|
-
constructor(specialFetch: { fetch: (url: any, requestInit: any) => any }, session: Session) {
|
|
39
|
-
// would xpect to be able to do it this way: but get TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation status: 999
|
|
40
|
-
// this.store = new rdf.LiveStore({})
|
|
41
|
-
// this.store.fetcher._fetch = fetch
|
|
42
|
-
console.log("SolidLogic: Unique instance created. There should only be one of these.")
|
|
43
|
-
this.store = rdf.graph() as LiveStore; // Make a Quad store
|
|
44
|
-
rdf.fetcher(this.store, { fetch: specialFetch.fetch}); // Attach a web I/O module, store.fetcher
|
|
45
|
-
this.store.updater = new rdf.UpdateManager(this.store); // Add real-time live updates store.updater
|
|
46
|
-
|
|
47
|
-
this.store.features = [] // disable automatic node merging on store load
|
|
48
|
-
this.cache = {
|
|
49
|
-
profileDocument: {},
|
|
50
|
-
preferencesFile: {},
|
|
51
|
-
};
|
|
52
|
-
this.authn = new SolidAuthnLogic(session);
|
|
53
|
-
debug.log('SolidAuthnLogic initialized')
|
|
54
|
-
this.profile = new ProfileLogic(this.store, ns, this.authn);
|
|
55
|
-
this.chat = new ChatLogic(this.store, ns, this.profile);
|
|
56
|
-
this.util = new UtilityLogic(this.store, ns);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
findAclDocUrl(url: string) {
|
|
60
|
-
return this.util.findAclDocUrl(url);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async loadProfile(me: NamedNode): Promise<NamedNode> {
|
|
64
|
-
/*
|
|
65
|
-
// console.log('loadProfile cache ', this.cache)
|
|
66
|
-
if (this.cache.profileDocument[me.value]) {
|
|
67
|
-
return this.cache.profileDocument[me.value];
|
|
68
|
-
} @@ just use the cache in the store
|
|
69
|
-
*/
|
|
70
|
-
console.log('loadProfile me ', me)
|
|
71
|
-
const profileDocument = me.doc()
|
|
72
|
-
try {
|
|
73
|
-
await this.store.fetcher.load(profileDocument);
|
|
74
|
-
return profileDocument;
|
|
75
|
-
} catch (err) {
|
|
76
|
-
const message = `Cannot load profile ${profileDocument} : ${err}`;
|
|
77
|
-
throw new Error(message);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async loadPreferences(me: NamedNode): Promise<NamedNode> {
|
|
82
|
-
console.log('loadPreferences cache ', this.cache)
|
|
83
|
-
if (this.cache.preferencesFile[me.value]) {
|
|
84
|
-
return this.cache.preferencesFile[me.value];
|
|
85
|
-
}
|
|
86
|
-
await this.loadProfile(me) // Load pointer to pref file
|
|
87
|
-
const preferencesFile = this.store.any(me, ns.space('preferencesFile'), null, me.doc());
|
|
88
|
-
|
|
89
|
-
// console.log('this.store.any()', this.store.any())
|
|
90
|
-
/**
|
|
91
|
-
* Are we working cross-origin?
|
|
92
|
-
* Returns True if we are in a webapp at an origin, and the file origin is different
|
|
93
|
-
*/
|
|
94
|
-
function differentOrigin(): boolean {
|
|
95
|
-
if (!preferencesFile) {
|
|
96
|
-
return true;
|
|
97
|
-
}
|
|
98
|
-
return (
|
|
99
|
-
`${window.location.origin}/` !== new URL(preferencesFile.value).origin
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (!preferencesFile) {
|
|
104
|
-
throw new Error(
|
|
105
|
-
`Can't find a preference file pointer in profile ${me.doc()}`
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// //// Load preference file
|
|
110
|
-
try {
|
|
111
|
-
await this.store.fetcher.load(preferencesFile as NamedNode, {
|
|
112
|
-
withCredentials: true,
|
|
113
|
-
});
|
|
114
|
-
} catch (err) {
|
|
115
|
-
// Really important to look at why
|
|
116
|
-
const status = err.status;
|
|
117
|
-
debug.log(`HTTP status ${status} for preference file ${preferencesFile}`);
|
|
118
|
-
if (status === 401) {
|
|
119
|
-
throw new UnauthorizedError();
|
|
120
|
-
}
|
|
121
|
-
if (status === 403) {
|
|
122
|
-
if (differentOrigin()) {
|
|
123
|
-
throw new CrossOriginForbiddenError();
|
|
124
|
-
}
|
|
125
|
-
throw new SameOriginForbiddenError();
|
|
126
|
-
}
|
|
127
|
-
if (status === 404) {
|
|
128
|
-
throw new NotFoundError(preferencesFile.value);
|
|
129
|
-
}
|
|
130
|
-
throw new FetchError(err.status, err.message);
|
|
131
|
-
}
|
|
132
|
-
return preferencesFile as NamedNode;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
getTypeIndex(
|
|
136
|
-
me: NamedNode | string,
|
|
137
|
-
preferencesFile: NamedNode | string,
|
|
138
|
-
isPublic: boolean
|
|
139
|
-
): NamedNode[] {
|
|
140
|
-
// console.log('getTypeIndex', this.store.each(me, undefined, undefined, preferencesFile), isPublic, preferencesFile)
|
|
141
|
-
return this.store.each(
|
|
142
|
-
me as NamedNode,
|
|
143
|
-
isPublic ? ns.solid("publicTypeIndex") : ns.solid("privateTypeIndex"),
|
|
144
|
-
undefined,
|
|
145
|
-
preferencesFile as NamedNode
|
|
146
|
-
) as NamedNode[];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
getRegistrations(instance, theClass) {
|
|
150
|
-
return this.store
|
|
151
|
-
.each(undefined, ns.solid("instance"), instance)
|
|
152
|
-
.filter((r) => {
|
|
153
|
-
return this.store.holds(r, ns.solid("forClass"), theClass);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
load(doc: NamedNode | NamedNode[] | string) {
|
|
158
|
-
return this.store.fetcher.load(doc);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
async loadIndexes(
|
|
162
|
-
me: NamedNode | string,
|
|
163
|
-
publicProfile: NamedNode | string | null,
|
|
164
|
-
preferencesFile: NamedNode | string | null,
|
|
165
|
-
onWarning = async (_err: Error) => {
|
|
166
|
-
return undefined;
|
|
167
|
-
}
|
|
168
|
-
): Promise<{
|
|
169
|
-
private: any;
|
|
170
|
-
public: any;
|
|
171
|
-
}> {
|
|
172
|
-
let privateIndexes: any[] = [];
|
|
173
|
-
let publicIndexes: any[] = [];
|
|
174
|
-
if (publicProfile) {
|
|
175
|
-
publicIndexes = this.getTypeIndex(me, publicProfile, true);
|
|
176
|
-
try {
|
|
177
|
-
await this.load(publicIndexes as NamedNode[]);
|
|
178
|
-
} catch (err) {
|
|
179
|
-
onWarning(new Error(`loadIndex: loading public type index(es) ${err}`));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (preferencesFile) {
|
|
183
|
-
privateIndexes = this.getTypeIndex(me, preferencesFile, false);
|
|
184
|
-
// console.log({ privateIndexes })
|
|
185
|
-
if (privateIndexes.length === 0) {
|
|
186
|
-
await onWarning(
|
|
187
|
-
new Error(
|
|
188
|
-
`Your preference file ${preferencesFile} does not point to a private type index.`
|
|
189
|
-
)
|
|
190
|
-
);
|
|
191
|
-
} else {
|
|
192
|
-
try {
|
|
193
|
-
await this.load(privateIndexes);
|
|
194
|
-
} catch (err) {
|
|
195
|
-
onWarning(
|
|
196
|
-
new Error(`loadIndex: loading private type index(es) ${err}`)
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
// } else {
|
|
201
|
-
// debug.log(
|
|
202
|
-
// 'We know your preference file is not available, so we are not bothering with private type indexes.'
|
|
203
|
-
// )
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return {
|
|
207
|
-
private: privateIndexes,
|
|
208
|
-
public: publicIndexes,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
async createEmptyRdfDoc(doc: NamedNode, comment: string) {
|
|
213
|
-
await this.store.fetcher.webOperation("PUT", doc.uri, {
|
|
214
|
-
data: `# ${new Date()} ${comment}
|
|
215
|
-
`,
|
|
216
|
-
contentType: "text/turtle",
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// @@@@ use the one in rdflib.js when it is available and delete this
|
|
221
|
-
updatePromise(
|
|
222
|
-
del: Array<Statement>,
|
|
223
|
-
ins: Array<Statement> = []
|
|
224
|
-
): Promise<void> {
|
|
225
|
-
return new Promise((resolve, reject) => {
|
|
226
|
-
this.store.updater.update(del, ins, function (_uri, ok, errorBody) {
|
|
227
|
-
if (!ok) {
|
|
228
|
-
reject(new Error(errorBody));
|
|
229
|
-
} else {
|
|
230
|
-
resolve();
|
|
231
|
-
}
|
|
232
|
-
}); // callback
|
|
233
|
-
}); // promise
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
isContainer(url: string) {
|
|
237
|
-
return this.util.isContainer(url);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
getContainerElements(containerNode: NamedNode): NamedNode[] {
|
|
241
|
-
return this.util.getContainerElements(containerNode);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
getContainerMembers(containerUrl: string): Promise<string[]> {
|
|
245
|
-
return this.util.getContainerMembers(containerUrl);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
async recursiveDelete(url: string) {
|
|
249
|
-
return this.util.recursiveDelete(url);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
clearStore() {
|
|
253
|
-
return this.util.clearStore();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
async fetch(url: string, options?: any) {
|
|
257
|
-
return this.store.fetcher._fetch(url, options);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { NamedNode, LiveStore } from "rdflib";
|
|
2
|
-
import { AuthnLogic, SolidNamespace } from "../types";
|
|
3
|
-
|
|
4
|
-
export class ProfileLogic {
|
|
5
|
-
store: LiveStore;
|
|
6
|
-
ns: SolidNamespace;
|
|
7
|
-
authn: AuthnLogic;
|
|
8
|
-
|
|
9
|
-
constructor(store: LiveStore, ns: SolidNamespace, authn: AuthnLogic) {
|
|
10
|
-
this.store = store;
|
|
11
|
-
this.ns = ns;
|
|
12
|
-
this.authn = authn;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async loadMe(): Promise<NamedNode> {
|
|
16
|
-
const me = this.authn.currentUser();
|
|
17
|
-
if (me === null) {
|
|
18
|
-
throw new Error("Current user not found! Not logged in?");
|
|
19
|
-
}
|
|
20
|
-
await this.store.fetcher?.load(me.doc());
|
|
21
|
-
return me;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
getPodRoot(user: NamedNode): NamedNode {
|
|
25
|
-
const podRoot = this.findStorage(user);
|
|
26
|
-
if (!podRoot) {
|
|
27
|
-
throw new Error("User pod root not found!");
|
|
28
|
-
}
|
|
29
|
-
return podRoot as NamedNode;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async getMainInbox(user: NamedNode): Promise<NamedNode> {
|
|
33
|
-
await this.store.fetcher?.load(user);
|
|
34
|
-
const mainInbox = this.store.any(user, this.ns.ldp("inbox"), undefined, user.doc());
|
|
35
|
-
if (!mainInbox) {
|
|
36
|
-
throw new Error("User main inbox not found!");
|
|
37
|
-
}
|
|
38
|
-
return mainInbox as NamedNode;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private findStorage(me: NamedNode) {
|
|
42
|
-
return this.store.any(me, this.ns.space("storage"), undefined, me.doc());
|
|
43
|
-
}
|
|
44
|
-
}
|
package/src/util/UtilityLogic.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { NamedNode, Statement, sym, LiveStore } from "rdflib";
|
|
2
|
-
import { SolidNamespace } from "../types";
|
|
3
|
-
|
|
4
|
-
export const ACL_LINK = sym(
|
|
5
|
-
"http://www.iana.org/assignments/link-relations/acl"
|
|
6
|
-
);
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Utility-related logic
|
|
10
|
-
*/
|
|
11
|
-
export class UtilityLogic {
|
|
12
|
-
store: LiveStore;
|
|
13
|
-
ns: SolidNamespace;
|
|
14
|
-
|
|
15
|
-
constructor(store: LiveStore, ns: SolidNamespace) {
|
|
16
|
-
this.store = store;
|
|
17
|
-
this.ns = ns;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async findAclDocUrl(url: string) {
|
|
21
|
-
const doc = this.store.sym(url);
|
|
22
|
-
await this.store.fetcher?.load(doc);
|
|
23
|
-
const docNode = this.store.any(doc, ACL_LINK);
|
|
24
|
-
if (!docNode) {
|
|
25
|
-
throw new Error(`No ACL link discovered for ${url}`);
|
|
26
|
-
}
|
|
27
|
-
return docNode.value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Copied from https://github.com/solidos/web-access-control-tests/blob/v3.0.0/test/surface/delete.test.ts#L5
|
|
31
|
-
async setSinglePeerAccess(options: {
|
|
32
|
-
ownerWebId: string,
|
|
33
|
-
peerWebId: string,
|
|
34
|
-
accessToModes?: string,
|
|
35
|
-
defaultModes?: string,
|
|
36
|
-
target: string
|
|
37
|
-
}) {
|
|
38
|
-
let str = [
|
|
39
|
-
'@prefix acl: <http://www.w3.org/ns/auth/acl#>.',
|
|
40
|
-
'',
|
|
41
|
-
`<#alice> a acl:Authorization;\n acl:agent <${options.ownerWebId}>;`,
|
|
42
|
-
` acl:accessTo <${options.target}>;`,
|
|
43
|
-
` acl:default <${options.target}>;`,
|
|
44
|
-
' acl:mode acl:Read, acl:Write, acl:Control.',
|
|
45
|
-
''
|
|
46
|
-
].join('\n')
|
|
47
|
-
if (options.accessToModes) {
|
|
48
|
-
str += [
|
|
49
|
-
'<#bobAccessTo> a acl:Authorization;',
|
|
50
|
-
` acl:agent <${options.peerWebId}>;`,
|
|
51
|
-
` acl:accessTo <${options.target}>;`,
|
|
52
|
-
` acl:mode ${options.accessToModes}.`,
|
|
53
|
-
''
|
|
54
|
-
].join('\n')
|
|
55
|
-
}
|
|
56
|
-
if (options.defaultModes) {
|
|
57
|
-
str += [
|
|
58
|
-
'<#bobDefault> a acl:Authorization;',
|
|
59
|
-
` acl:agent <${options.peerWebId}>;`,
|
|
60
|
-
` acl:default <${options.target}>;`,
|
|
61
|
-
` acl:mode ${options.defaultModes}.`,
|
|
62
|
-
''
|
|
63
|
-
].join('\n')
|
|
64
|
-
}
|
|
65
|
-
const aclDocUrl = await this.findAclDocUrl(options.target);
|
|
66
|
-
return this.store.fetcher._fetch(aclDocUrl, {
|
|
67
|
-
method: 'PUT',
|
|
68
|
-
body: str,
|
|
69
|
-
headers: [
|
|
70
|
-
[ 'Content-Type', 'text/turtle' ]
|
|
71
|
-
]
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
isContainer(url: string) {
|
|
76
|
-
return url.charAt(url.length-1) === "/";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async createContainer(url: string) {
|
|
80
|
-
if (!this.isContainer(url)) {
|
|
81
|
-
throw new Error(`Not a container URL ${url}`);
|
|
82
|
-
}
|
|
83
|
-
// Copied from https://github.com/solidos/solid-crud-tests/blob/v3.1.0/test/surface/create-container.test.ts#L56-L64
|
|
84
|
-
const result = await this.store.fetcher._fetch(url, {
|
|
85
|
-
method: "PUT",
|
|
86
|
-
headers: {
|
|
87
|
-
"Content-Type": "text/turtle",
|
|
88
|
-
"If-None-Match": "*",
|
|
89
|
-
Link: '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"', // See https://github.com/solidos/node-solid-server/issues/1465
|
|
90
|
-
},
|
|
91
|
-
body: " ", // work around https://github.com/michielbdejong/community-server/issues/4#issuecomment-776222863
|
|
92
|
-
});
|
|
93
|
-
if (result.status.toString()[0] !== '2') {
|
|
94
|
-
throw new Error(`Not OK: got ${result.status} response while creating container at ${url}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
getContainerElements(containerNode: NamedNode): NamedNode[] {
|
|
99
|
-
return this.store
|
|
100
|
-
.statementsMatching(
|
|
101
|
-
containerNode,
|
|
102
|
-
this.store.sym("http://www.w3.org/ns/ldp#contains"),
|
|
103
|
-
undefined,
|
|
104
|
-
containerNode.doc()
|
|
105
|
-
)
|
|
106
|
-
.map((st: Statement) => st.object as NamedNode);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async getContainerMembers(containerUrl: string): Promise<string[]> {
|
|
110
|
-
const containerNode = this.store.sym(containerUrl);
|
|
111
|
-
await this.store.fetcher?.load(containerNode);
|
|
112
|
-
const nodes = this.getContainerElements(containerNode);
|
|
113
|
-
return nodes.map(node => node.value);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async recursiveDelete(url: string) {
|
|
117
|
-
try {
|
|
118
|
-
if (this.isContainer(url)) {
|
|
119
|
-
const aclDocUrl = await this.findAclDocUrl(url);
|
|
120
|
-
await this.store.fetcher._fetch(aclDocUrl, { method: "DELETE" });
|
|
121
|
-
const containerMembers = await this.getContainerMembers(url);
|
|
122
|
-
await Promise.all(
|
|
123
|
-
containerMembers.map((url) => this.recursiveDelete(url))
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
return this.store.fetcher._fetch(url, { method: "DELETE" });
|
|
127
|
-
} catch (e) {
|
|
128
|
-
// console.log(`Please manually remove ${url} from your system under test.`, e);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
clearStore() {
|
|
133
|
-
this.store.statements.slice().forEach(this.store.remove.bind(this.store));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
getArchiveUrl(baseUrl: string, date: Date) {
|
|
137
|
-
const year = date.getUTCFullYear();
|
|
138
|
-
const month = ('0' + (date.getUTCMonth()+1)).slice(-2);
|
|
139
|
-
const day = ('0' + (date.getUTCDate())).slice(-2);
|
|
140
|
-
const parts = baseUrl.split('/');
|
|
141
|
-
const filename = parts[parts.length -1 ];
|
|
142
|
-
return new URL(`./archive/${year}/${month}/${day}/${filename}`, baseUrl).toString();
|
|
143
|
-
}
|
|
144
|
-
}
|