javascript-solid-server 0.0.124 → 0.0.126
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/.claude/settings.local.json +4 -1
- package/package.json +1 -1
- package/src/auth/middleware.js +4 -2
- package/src/wac/checker.js +16 -5
- package/test/wac.test.js +24 -0
|
@@ -335,7 +335,10 @@
|
|
|
335
335
|
"Bash(TORRENT=/home/melvin/.claude/projects/-home-melvin-remote-github-com-JavaScriptSolidServer-JavaScriptSolidServer/a05da419-92b7-4056-93b8-e97b2035d4ae/tool-results/webfetch-1774004425803-fce7mx.bin npx -y parse-torrent $TORRENT)",
|
|
336
336
|
"Bash(gh issue:*)",
|
|
337
337
|
"Bash(sed -i 's|Settings/|settings/|g' src/server.js src/handlers/container.js src/webid/profile.js)",
|
|
338
|
-
"Bash(sed -i 's|// Settings folder|// settings folder|' src/handlers/container.js)"
|
|
338
|
+
"Bash(sed -i 's|// Settings folder|// settings folder|' src/handlers/container.js)",
|
|
339
|
+
"WebFetch(domain:www.x402.org)",
|
|
340
|
+
"Bash(jss start:*)",
|
|
341
|
+
"Read(//tmp/**)"
|
|
339
342
|
]
|
|
340
343
|
}
|
|
341
344
|
}
|
package/package.json
CHANGED
package/src/auth/middleware.js
CHANGED
|
@@ -24,6 +24,8 @@ import { generateDatabrowserHtml, generateModuleDatabrowserHtml } from '../mashl
|
|
|
24
24
|
* @returns {string} Normalized resource URL
|
|
25
25
|
*/
|
|
26
26
|
function buildResourceUrl(request, urlPath) {
|
|
27
|
+
// Use request.headers.host (includes port) instead of request.hostname (strips port)
|
|
28
|
+
const host = request.headers.host || request.hostname;
|
|
27
29
|
if (request.subdomainsEnabled && request.baseDomain &&
|
|
28
30
|
request.hostname === request.baseDomain && !request.podName) {
|
|
29
31
|
const pathMatch = urlPath.match(/^\/([^/]+)(\/.*)?$/);
|
|
@@ -33,7 +35,7 @@ function buildResourceUrl(request, urlPath) {
|
|
|
33
35
|
return `${request.protocol}://${podName}.${request.baseDomain}${remainder}`;
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
|
-
return `${request.protocol}://${
|
|
38
|
+
return `${request.protocol}://${host}${urlPath}`;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -180,7 +182,7 @@ function getErrorPage(statusCode, isAuthenticated, request) {
|
|
|
180
182
|
? "This resource is protected. You'll need to sign in to continue."
|
|
181
183
|
: "You're signed in, but you don't have permission to view this resource.";
|
|
182
184
|
|
|
183
|
-
const baseUrl = `${request.protocol}://${request.hostname}`;
|
|
185
|
+
const baseUrl = `${request.protocol}://${request.headers.host || request.hostname}`;
|
|
184
186
|
|
|
185
187
|
return `<!DOCTYPE html>
|
|
186
188
|
<html lang="en">
|
package/src/wac/checker.js
CHANGED
|
@@ -163,15 +163,26 @@ async function checkAuthorizations(authorizations, targetUrl, agentWebId, requir
|
|
|
163
163
|
c.type === 'PaymentCondition' || c.type === 'https://webacl.org/ns#PaymentCondition'
|
|
164
164
|
);
|
|
165
165
|
if (paymentCondition) {
|
|
166
|
-
|
|
167
|
-
const cost =
|
|
166
|
+
const parsed = parseInt(paymentCondition.amount, 10);
|
|
167
|
+
const cost = Number.isNaN(parsed) ? -1 : parsed;
|
|
168
168
|
const currency = paymentCondition.currency || 'sat';
|
|
169
|
-
|
|
169
|
+
|
|
170
|
+
// Skip invalid amounts
|
|
171
|
+
if (cost < 0) continue;
|
|
172
|
+
|
|
173
|
+
if (agentWebId) {
|
|
170
174
|
try {
|
|
171
175
|
const ledger = await readLedger();
|
|
176
|
+
|
|
177
|
+
// Zero-cost gate: verify they have a ledger entry (have deposited at some point)
|
|
178
|
+
if (cost === 0) {
|
|
179
|
+
const hasEntry = ledger.entries?.some(e => e.url === agentWebId);
|
|
180
|
+
if (hasEntry) return { allowed: true };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Paid access: check balance and deduct
|
|
172
184
|
const balance = getBalance(ledger, agentWebId);
|
|
173
|
-
if (balance >= cost) {
|
|
174
|
-
// Deduct and grant access
|
|
185
|
+
if (cost > 0 && balance >= cost) {
|
|
175
186
|
debit(ledger, agentWebId, cost, currency === 'sats' ? 'sat' : currency);
|
|
176
187
|
const { writeLedger } = await import('../webledger.js');
|
|
177
188
|
await writeLedger(ledger);
|
package/test/wac.test.js
CHANGED
|
@@ -428,6 +428,30 @@ describe('WAC Conditions', () => {
|
|
|
428
428
|
assert.strictEqual(auths[0].conditions[0].type, 'UnknownFutureCondition');
|
|
429
429
|
});
|
|
430
430
|
|
|
431
|
+
it('should parse zero-cost PaymentCondition', async () => {
|
|
432
|
+
const acl = {
|
|
433
|
+
'@context': { 'acl': 'http://www.w3.org/ns/auth/acl#' },
|
|
434
|
+
'@graph': [{
|
|
435
|
+
'@id': '#gate',
|
|
436
|
+
'@type': 'acl:Authorization',
|
|
437
|
+
'acl:agentClass': { '@id': 'acl:AuthenticatedAgent' },
|
|
438
|
+
'acl:accessTo': { '@id': 'https://alice.example/members/' },
|
|
439
|
+
'acl:mode': [{ '@id': 'acl:Read' }],
|
|
440
|
+
'acl:condition': {
|
|
441
|
+
'@type': 'PaymentCondition',
|
|
442
|
+
'amount': '0',
|
|
443
|
+
'currency': 'sats'
|
|
444
|
+
}
|
|
445
|
+
}]
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const auths = await parseAcl(JSON.stringify(acl), 'https://alice.example/members/.acl');
|
|
449
|
+
const condition = auths[0].conditions[0];
|
|
450
|
+
|
|
451
|
+
assert.strictEqual(condition.type, 'PaymentCondition');
|
|
452
|
+
assert.strictEqual(condition.amount, '0');
|
|
453
|
+
});
|
|
454
|
+
|
|
431
455
|
it('should parse PaymentCondition with all fields', async () => {
|
|
432
456
|
const acl = {
|
|
433
457
|
'@context': { 'acl': 'http://www.w3.org/ns/auth/acl#' },
|