javascript-solid-server 0.0.3 → 0.0.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/package.json +9 -3
- package/src/auth/middleware.js +99 -0
- package/src/auth/solid-oidc.js +260 -0
- package/src/auth/token.js +150 -0
- package/src/handlers/container.js +24 -4
- package/src/handlers/resource.js +19 -10
- package/src/ldp/headers.js +31 -6
- package/src/server.js +20 -0
- package/src/wac/checker.js +257 -0
- package/src/wac/parser.js +284 -0
- package/test/auth.test.js +175 -0
- package/test/helpers.js +38 -4
- package/test/ldp.test.js +61 -20
- package/test/pod.test.js +16 -23
- package/test/solid-oidc.test.js +211 -0
- package/test/wac.test.js +189 -0
- package/benchmark-report-2025-03-31T14-25-24.234Z.json +0 -44
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication and Authorization tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, before, after } from 'node:test';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
|
+
import {
|
|
8
|
+
startTestServer,
|
|
9
|
+
stopTestServer,
|
|
10
|
+
request,
|
|
11
|
+
createTestPod,
|
|
12
|
+
getPodToken,
|
|
13
|
+
getBaseUrl,
|
|
14
|
+
assertStatus,
|
|
15
|
+
assertHeader
|
|
16
|
+
} from './helpers.js';
|
|
17
|
+
|
|
18
|
+
describe('Authentication', () => {
|
|
19
|
+
before(async () => {
|
|
20
|
+
await startTestServer();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
after(async () => {
|
|
24
|
+
await stopTestServer();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('Token Authentication', () => {
|
|
28
|
+
it('should return token on pod creation', async () => {
|
|
29
|
+
const result = await createTestPod('authtest');
|
|
30
|
+
|
|
31
|
+
assert.ok(result.token, 'Should return a token');
|
|
32
|
+
assert.ok(result.token.includes('.'), 'Token should have signature');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should allow authenticated access to private resources', async () => {
|
|
36
|
+
await createTestPod('privatetest');
|
|
37
|
+
|
|
38
|
+
// Should succeed with auth
|
|
39
|
+
const res = await request('/privatetest/private/', { auth: 'privatetest' });
|
|
40
|
+
assertStatus(res, 200);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should deny unauthenticated access to private resources', async () => {
|
|
44
|
+
await createTestPod('denytest');
|
|
45
|
+
|
|
46
|
+
// Should fail without auth
|
|
47
|
+
const res = await request('/denytest/private/');
|
|
48
|
+
assertStatus(res, 401);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should return 403 for wrong user accessing private resources', async () => {
|
|
52
|
+
await createTestPod('user1');
|
|
53
|
+
await createTestPod('user2');
|
|
54
|
+
|
|
55
|
+
// User2 trying to access User1's private folder
|
|
56
|
+
const res = await request('/user1/private/', { auth: 'user2' });
|
|
57
|
+
assertStatus(res, 403);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should accept Bearer token format', async () => {
|
|
61
|
+
await createTestPod('bearertest');
|
|
62
|
+
const token = getPodToken('bearertest');
|
|
63
|
+
|
|
64
|
+
const res = await fetch(`${getBaseUrl()}/bearertest/private/`, {
|
|
65
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
66
|
+
});
|
|
67
|
+
assertStatus(res, 200);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should reject invalid tokens', async () => {
|
|
71
|
+
await createTestPod('invalidtest');
|
|
72
|
+
|
|
73
|
+
const res = await fetch(`${getBaseUrl()}/invalidtest/private/`, {
|
|
74
|
+
headers: { 'Authorization': 'Bearer invalid.token' }
|
|
75
|
+
});
|
|
76
|
+
assertStatus(res, 401);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('WAC Enforcement', () => {
|
|
81
|
+
it('should allow public read on pod root', async () => {
|
|
82
|
+
await createTestPod('publicread');
|
|
83
|
+
|
|
84
|
+
// Public folder should be readable without auth
|
|
85
|
+
const res = await request('/publicread/public/');
|
|
86
|
+
assertStatus(res, 200);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should allow public read on explicit public folders', async () => {
|
|
90
|
+
await createTestPod('explicitpublic');
|
|
91
|
+
|
|
92
|
+
// Root ACL has public read default
|
|
93
|
+
const res = await request('/explicitpublic/');
|
|
94
|
+
assertStatus(res, 200);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should allow authenticated write to owned resources', async () => {
|
|
98
|
+
await createTestPod('writetest');
|
|
99
|
+
|
|
100
|
+
const res = await request('/writetest/public/test.txt', {
|
|
101
|
+
method: 'PUT',
|
|
102
|
+
body: 'test content',
|
|
103
|
+
auth: 'writetest'
|
|
104
|
+
});
|
|
105
|
+
assertStatus(res, 201);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should deny unauthenticated write', async () => {
|
|
109
|
+
await createTestPod('nowrite');
|
|
110
|
+
|
|
111
|
+
const res = await request('/nowrite/public/test.txt', {
|
|
112
|
+
method: 'PUT',
|
|
113
|
+
body: 'test content'
|
|
114
|
+
});
|
|
115
|
+
assertStatus(res, 401);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should deny other user write to owned resources', async () => {
|
|
119
|
+
await createTestPod('owner1');
|
|
120
|
+
await createTestPod('attacker');
|
|
121
|
+
|
|
122
|
+
const res = await request('/owner1/public/test.txt', {
|
|
123
|
+
method: 'PUT',
|
|
124
|
+
body: 'malicious content',
|
|
125
|
+
auth: 'attacker'
|
|
126
|
+
});
|
|
127
|
+
assertStatus(res, 403);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should allow public append to inbox', async () => {
|
|
131
|
+
await createTestPod('inboxtest');
|
|
132
|
+
|
|
133
|
+
// POST to inbox should work for anyone (public append)
|
|
134
|
+
const res = await request('/inboxtest/inbox/', {
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers: {
|
|
137
|
+
'Content-Type': 'application/json',
|
|
138
|
+
'Slug': 'notification'
|
|
139
|
+
},
|
|
140
|
+
body: JSON.stringify({ type: 'notification' })
|
|
141
|
+
});
|
|
142
|
+
assertStatus(res, 201);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should deny public read on inbox', async () => {
|
|
146
|
+
await createTestPod('inboxread');
|
|
147
|
+
|
|
148
|
+
// GET inbox should fail for unauthenticated
|
|
149
|
+
const res = await request('/inboxread/inbox/');
|
|
150
|
+
assertStatus(res, 401);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('WAC-Allow Header', () => {
|
|
155
|
+
it('should include user permissions for authenticated requests', async () => {
|
|
156
|
+
await createTestPod('wacallow');
|
|
157
|
+
|
|
158
|
+
const res = await request('/wacallow/public/', { auth: 'wacallow' });
|
|
159
|
+
const wacAllow = res.headers.get('WAC-Allow');
|
|
160
|
+
|
|
161
|
+
assert.ok(wacAllow, 'Should have WAC-Allow header');
|
|
162
|
+
assert.ok(wacAllow.includes('user='), 'Should include user permissions');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('should include public permissions', async () => {
|
|
166
|
+
await createTestPod('wacpublic');
|
|
167
|
+
|
|
168
|
+
const res = await request('/wacpublic/public/');
|
|
169
|
+
const wacAllow = res.headers.get('WAC-Allow');
|
|
170
|
+
|
|
171
|
+
assert.ok(wacAllow, 'Should have WAC-Allow header');
|
|
172
|
+
assert.ok(wacAllow.includes('public='), 'Should include public permissions');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
package/test/helpers.js
CHANGED
|
@@ -11,6 +11,9 @@ const TEST_DATA_DIR = './data';
|
|
|
11
11
|
let server = null;
|
|
12
12
|
let baseUrl = null;
|
|
13
13
|
|
|
14
|
+
// Store tokens for pods by name
|
|
15
|
+
const podTokens = new Map();
|
|
16
|
+
|
|
14
17
|
/**
|
|
15
18
|
* Start a test server on a random available port
|
|
16
19
|
* @returns {Promise<{server: object, baseUrl: string}>}
|
|
@@ -39,6 +42,8 @@ export async function stopTestServer() {
|
|
|
39
42
|
}
|
|
40
43
|
// Clean up test data
|
|
41
44
|
await fs.emptyDir(TEST_DATA_DIR);
|
|
45
|
+
// Clear tokens
|
|
46
|
+
podTokens.clear();
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
/**
|
|
@@ -51,7 +56,7 @@ export function getBaseUrl() {
|
|
|
51
56
|
/**
|
|
52
57
|
* Create a pod for testing
|
|
53
58
|
* @param {string} name - Pod name
|
|
54
|
-
* @returns {Promise<{webId: string, podUri: string}>}
|
|
59
|
+
* @returns {Promise<{webId: string, podUri: string, token: string}>}
|
|
55
60
|
*/
|
|
56
61
|
export async function createTestPod(name) {
|
|
57
62
|
const res = await fetch(`${baseUrl}/.pods`, {
|
|
@@ -64,18 +69,47 @@ export async function createTestPod(name) {
|
|
|
64
69
|
throw new Error(`Failed to create pod: ${res.status}`);
|
|
65
70
|
}
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
const result = await res.json();
|
|
73
|
+
|
|
74
|
+
// Store the token for this pod
|
|
75
|
+
if (result.token) {
|
|
76
|
+
podTokens.set(name, result.token);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get token for a pod
|
|
84
|
+
* @param {string} name - Pod name
|
|
85
|
+
* @returns {string|null}
|
|
86
|
+
*/
|
|
87
|
+
export function getPodToken(name) {
|
|
88
|
+
return podTokens.get(name) || null;
|
|
68
89
|
}
|
|
69
90
|
|
|
70
91
|
/**
|
|
71
92
|
* Make a request to the test server
|
|
72
93
|
* @param {string} path - URL path
|
|
73
|
-
* @param {object} options - fetch options
|
|
94
|
+
* @param {object} options - fetch options (can include `auth: 'podname'` for authenticated requests)
|
|
74
95
|
* @returns {Promise<Response>}
|
|
75
96
|
*/
|
|
76
97
|
export async function request(urlPath, options = {}) {
|
|
77
98
|
const url = urlPath.startsWith('http') ? urlPath : `${baseUrl}${urlPath}`;
|
|
78
|
-
|
|
99
|
+
|
|
100
|
+
// Handle authentication
|
|
101
|
+
const { auth, ...fetchOptions } = options;
|
|
102
|
+
if (auth) {
|
|
103
|
+
const token = podTokens.get(auth);
|
|
104
|
+
if (token) {
|
|
105
|
+
fetchOptions.headers = {
|
|
106
|
+
...fetchOptions.headers,
|
|
107
|
+
'Authorization': `Bearer ${token}`
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return fetch(url, fetchOptions);
|
|
79
113
|
}
|
|
80
114
|
|
|
81
115
|
/**
|
package/test/ldp.test.js
CHANGED
|
@@ -41,11 +41,12 @@ describe('LDP CRUD Operations', () => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
it('should return resource content', async () => {
|
|
44
|
-
// Create resource first
|
|
44
|
+
// Create resource first (authenticated)
|
|
45
45
|
await request('/ldptest/public/test.json', {
|
|
46
46
|
method: 'PUT',
|
|
47
47
|
headers: { 'Content-Type': 'application/json' },
|
|
48
|
-
body: JSON.stringify({ hello: 'world' })
|
|
48
|
+
body: JSON.stringify({ hello: 'world' }),
|
|
49
|
+
auth: 'ldptest'
|
|
49
50
|
});
|
|
50
51
|
|
|
51
52
|
const res = await request('/ldptest/public/test.json');
|
|
@@ -58,7 +59,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
58
59
|
it('should return ETag header', async () => {
|
|
59
60
|
await request('/ldptest/public/etag-test.txt', {
|
|
60
61
|
method: 'PUT',
|
|
61
|
-
body: 'test content'
|
|
62
|
+
body: 'test content',
|
|
63
|
+
auth: 'ldptest'
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
const res = await request('/ldptest/public/etag-test.txt');
|
|
@@ -72,7 +74,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
72
74
|
it('should return headers without body', async () => {
|
|
73
75
|
await request('/ldptest/public/head-test.txt', {
|
|
74
76
|
method: 'PUT',
|
|
75
|
-
body: 'test content'
|
|
77
|
+
body: 'test content',
|
|
78
|
+
auth: 'ldptest'
|
|
76
79
|
});
|
|
77
80
|
|
|
78
81
|
const res = await request('/ldptest/public/head-test.txt', {
|
|
@@ -101,7 +104,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
101
104
|
const res = await request('/ldptest/public/new-resource.json', {
|
|
102
105
|
method: 'PUT',
|
|
103
106
|
headers: { 'Content-Type': 'application/json' },
|
|
104
|
-
body: JSON.stringify({ created: true })
|
|
107
|
+
body: JSON.stringify({ created: true }),
|
|
108
|
+
auth: 'ldptest'
|
|
105
109
|
});
|
|
106
110
|
|
|
107
111
|
assertStatus(res, 201);
|
|
@@ -112,13 +116,15 @@ describe('LDP CRUD Operations', () => {
|
|
|
112
116
|
// Create
|
|
113
117
|
await request('/ldptest/public/update-me.txt', {
|
|
114
118
|
method: 'PUT',
|
|
115
|
-
body: 'original'
|
|
119
|
+
body: 'original',
|
|
120
|
+
auth: 'ldptest'
|
|
116
121
|
});
|
|
117
122
|
|
|
118
123
|
// Update
|
|
119
124
|
const res = await request('/ldptest/public/update-me.txt', {
|
|
120
125
|
method: 'PUT',
|
|
121
|
-
body: 'updated'
|
|
126
|
+
body: 'updated',
|
|
127
|
+
auth: 'ldptest'
|
|
122
128
|
});
|
|
123
129
|
|
|
124
130
|
assertStatus(res, 204);
|
|
@@ -132,7 +138,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
132
138
|
it('should create parent containers', async () => {
|
|
133
139
|
const res = await request('/ldptest/public/nested/deep/file.txt', {
|
|
134
140
|
method: 'PUT',
|
|
135
|
-
body: 'nested content'
|
|
141
|
+
body: 'nested content',
|
|
142
|
+
auth: 'ldptest'
|
|
136
143
|
});
|
|
137
144
|
|
|
138
145
|
assertStatus(res, 201);
|
|
@@ -145,7 +152,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
145
152
|
it('should reject PUT to container path', async () => {
|
|
146
153
|
const res = await request('/ldptest/public/invalid/', {
|
|
147
154
|
method: 'PUT',
|
|
148
|
-
body: 'cannot put to container'
|
|
155
|
+
body: 'cannot put to container',
|
|
156
|
+
auth: 'ldptest'
|
|
149
157
|
});
|
|
150
158
|
|
|
151
159
|
assertStatus(res, 409);
|
|
@@ -160,7 +168,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
160
168
|
'Content-Type': 'application/json',
|
|
161
169
|
'Slug': 'posted-resource'
|
|
162
170
|
},
|
|
163
|
-
body: JSON.stringify({ posted: true })
|
|
171
|
+
body: JSON.stringify({ posted: true }),
|
|
172
|
+
auth: 'ldptest'
|
|
164
173
|
});
|
|
165
174
|
|
|
166
175
|
assertStatus(res, 201);
|
|
@@ -179,7 +188,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
179
188
|
'Content-Type': 'text/plain',
|
|
180
189
|
'Slug': 'my-custom-name.txt'
|
|
181
190
|
},
|
|
182
|
-
body: 'slug test'
|
|
191
|
+
body: 'slug test',
|
|
192
|
+
auth: 'ldptest'
|
|
183
193
|
});
|
|
184
194
|
|
|
185
195
|
const location = res.headers.get('Location');
|
|
@@ -192,7 +202,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
192
202
|
headers: {
|
|
193
203
|
'Slug': 'new-container',
|
|
194
204
|
'Link': '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"'
|
|
195
|
-
}
|
|
205
|
+
},
|
|
206
|
+
auth: 'ldptest'
|
|
196
207
|
});
|
|
197
208
|
|
|
198
209
|
assertStatus(res, 201);
|
|
@@ -208,12 +219,14 @@ describe('LDP CRUD Operations', () => {
|
|
|
208
219
|
it('should reject POST to non-container', async () => {
|
|
209
220
|
await request('/ldptest/public/file-not-container.txt', {
|
|
210
221
|
method: 'PUT',
|
|
211
|
-
body: 'just a file'
|
|
222
|
+
body: 'just a file',
|
|
223
|
+
auth: 'ldptest'
|
|
212
224
|
});
|
|
213
225
|
|
|
214
226
|
const res = await request('/ldptest/public/file-not-container.txt', {
|
|
215
227
|
method: 'POST',
|
|
216
|
-
body: 'trying to post'
|
|
228
|
+
body: 'trying to post',
|
|
229
|
+
auth: 'ldptest'
|
|
217
230
|
});
|
|
218
231
|
|
|
219
232
|
assertStatus(res, 405);
|
|
@@ -224,11 +237,13 @@ describe('LDP CRUD Operations', () => {
|
|
|
224
237
|
it('should delete resource', async () => {
|
|
225
238
|
await request('/ldptest/public/to-delete.txt', {
|
|
226
239
|
method: 'PUT',
|
|
227
|
-
body: 'delete me'
|
|
240
|
+
body: 'delete me',
|
|
241
|
+
auth: 'ldptest'
|
|
228
242
|
});
|
|
229
243
|
|
|
230
244
|
const res = await request('/ldptest/public/to-delete.txt', {
|
|
231
|
-
method: 'DELETE'
|
|
245
|
+
method: 'DELETE',
|
|
246
|
+
auth: 'ldptest'
|
|
232
247
|
});
|
|
233
248
|
|
|
234
249
|
assertStatus(res, 204);
|
|
@@ -240,7 +255,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
240
255
|
|
|
241
256
|
it('should return 404 for non-existent', async () => {
|
|
242
257
|
const res = await request('/ldptest/public/never-existed.txt', {
|
|
243
|
-
method: 'DELETE'
|
|
258
|
+
method: 'DELETE',
|
|
259
|
+
auth: 'ldptest'
|
|
244
260
|
});
|
|
245
261
|
|
|
246
262
|
assertStatus(res, 404);
|
|
@@ -253,11 +269,13 @@ describe('LDP CRUD Operations', () => {
|
|
|
253
269
|
headers: {
|
|
254
270
|
'Slug': 'container-to-delete',
|
|
255
271
|
'Link': '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"'
|
|
256
|
-
}
|
|
272
|
+
},
|
|
273
|
+
auth: 'ldptest'
|
|
257
274
|
});
|
|
258
275
|
|
|
259
276
|
const res = await request('/ldptest/public/container-to-delete/', {
|
|
260
|
-
method: 'DELETE'
|
|
277
|
+
method: 'DELETE',
|
|
278
|
+
auth: 'ldptest'
|
|
261
279
|
});
|
|
262
280
|
|
|
263
281
|
assertStatus(res, 204);
|
|
@@ -291,7 +309,8 @@ describe('LDP CRUD Operations', () => {
|
|
|
291
309
|
it('should return Link type header for resource', async () => {
|
|
292
310
|
await request('/ldptest/public/resource-link.txt', {
|
|
293
311
|
method: 'PUT',
|
|
294
|
-
body: 'test'
|
|
312
|
+
body: 'test',
|
|
313
|
+
auth: 'ldptest'
|
|
295
314
|
});
|
|
296
315
|
|
|
297
316
|
const res = await request('/ldptest/public/resource-link.txt');
|
|
@@ -318,5 +337,27 @@ describe('LDP CRUD Operations', () => {
|
|
|
318
337
|
|
|
319
338
|
assertHeader(res, 'Accept-Post');
|
|
320
339
|
});
|
|
340
|
+
|
|
341
|
+
it('should return acl Link header for resource', async () => {
|
|
342
|
+
await request('/ldptest/public/acl-test.txt', {
|
|
343
|
+
method: 'PUT',
|
|
344
|
+
body: 'test',
|
|
345
|
+
auth: 'ldptest'
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
const res = await request('/ldptest/public/acl-test.txt');
|
|
349
|
+
const link = res.headers.get('Link');
|
|
350
|
+
|
|
351
|
+
assert.ok(link.includes('rel="acl"'), 'Should have acl link relation');
|
|
352
|
+
assert.ok(link.includes('acl-test.txt.acl'), 'ACL should be resource.acl');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('should return acl Link header for container', async () => {
|
|
356
|
+
const res = await request('/ldptest/public/');
|
|
357
|
+
const link = res.headers.get('Link');
|
|
358
|
+
|
|
359
|
+
assert.ok(link.includes('rel="acl"'), 'Should have acl link relation');
|
|
360
|
+
assert.ok(link.includes('.acl'), 'Should link to .acl');
|
|
361
|
+
});
|
|
321
362
|
});
|
|
322
363
|
});
|
package/test/pod.test.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
startTestServer,
|
|
9
9
|
stopTestServer,
|
|
10
10
|
request,
|
|
11
|
+
createTestPod,
|
|
11
12
|
assertStatus,
|
|
12
13
|
assertHeader,
|
|
13
14
|
assertHeaderContains
|
|
@@ -80,46 +81,38 @@ describe('Pod Lifecycle', () => {
|
|
|
80
81
|
|
|
81
82
|
describe('Pod Structure', () => {
|
|
82
83
|
it('should create standard folders', async () => {
|
|
83
|
-
await
|
|
84
|
-
method: 'POST',
|
|
85
|
-
headers: { 'Content-Type': 'application/json' },
|
|
86
|
-
body: JSON.stringify({ name: 'carol' })
|
|
87
|
-
});
|
|
84
|
+
await createTestPod('carol');
|
|
88
85
|
|
|
89
|
-
// Check inbox exists
|
|
90
|
-
const inbox = await request('/carol/inbox/');
|
|
86
|
+
// Check inbox exists (needs auth - inbox only allows public append, not read)
|
|
87
|
+
const inbox = await request('/carol/inbox/', { auth: 'carol' });
|
|
91
88
|
assertStatus(inbox, 200);
|
|
92
89
|
|
|
93
|
-
// Check public exists
|
|
90
|
+
// Check public exists (public read via root ACL default)
|
|
94
91
|
const pub = await request('/carol/public/');
|
|
95
92
|
assertStatus(pub, 200);
|
|
96
93
|
|
|
97
|
-
// Check private exists
|
|
98
|
-
const priv = await request('/carol/private/');
|
|
94
|
+
// Check private exists (needs auth)
|
|
95
|
+
const priv = await request('/carol/private/', { auth: 'carol' });
|
|
99
96
|
assertStatus(priv, 200);
|
|
100
97
|
|
|
101
|
-
// Check settings exists
|
|
102
|
-
const settings = await request('/carol/settings/');
|
|
98
|
+
// Check settings exists (needs auth)
|
|
99
|
+
const settings = await request('/carol/settings/', { auth: 'carol' });
|
|
103
100
|
assertStatus(settings, 200);
|
|
104
101
|
});
|
|
105
102
|
|
|
106
103
|
it('should create settings files', async () => {
|
|
107
|
-
await
|
|
108
|
-
method: 'POST',
|
|
109
|
-
headers: { 'Content-Type': 'application/json' },
|
|
110
|
-
body: JSON.stringify({ name: 'dan' })
|
|
111
|
-
});
|
|
104
|
+
await createTestPod('dan');
|
|
112
105
|
|
|
113
|
-
// Check prefs
|
|
114
|
-
const prefs = await request('/dan/settings/prefs');
|
|
106
|
+
// Check prefs (needs auth - settings is private)
|
|
107
|
+
const prefs = await request('/dan/settings/prefs', { auth: 'dan' });
|
|
115
108
|
assertStatus(prefs, 200);
|
|
116
109
|
|
|
117
|
-
// Check public type index
|
|
118
|
-
const pubIndex = await request('/dan/settings/publicTypeIndex');
|
|
110
|
+
// Check public type index (needs auth)
|
|
111
|
+
const pubIndex = await request('/dan/settings/publicTypeIndex', { auth: 'dan' });
|
|
119
112
|
assertStatus(pubIndex, 200);
|
|
120
113
|
|
|
121
|
-
// Check private type index
|
|
122
|
-
const privIndex = await request('/dan/settings/privateTypeIndex');
|
|
114
|
+
// Check private type index (needs auth)
|
|
115
|
+
const privIndex = await request('/dan/settings/privateTypeIndex', { auth: 'dan' });
|
|
123
116
|
assertStatus(privIndex, 200);
|
|
124
117
|
});
|
|
125
118
|
});
|