javascript-solid-server 0.0.141 → 0.0.143

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javascript-solid-server",
3
- "version": "0.0.141",
3
+ "version": "0.0.143",
4
4
  "description": "A minimal, fast Solid server",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/idp/index.js CHANGED
@@ -183,7 +183,7 @@ export async function idpPlugin(fastify, options) {
183
183
  // Pairs with the /idp/auth guard above so a human visitor lands here
184
184
  // rather than on a raw OIDC error.
185
185
  fastify.get('/idp', async (request, reply) => {
186
- return reply.type('text/html').send(landingPage({ baseUri: issuer }));
186
+ return reply.type('text/html').send(landingPage({ baseUri: issuer, singleUser }));
187
187
  });
188
188
 
189
189
  // Token sub-paths
package/src/idp/views.js CHANGED
@@ -555,12 +555,15 @@ export function errorPage(title, message) {
555
555
  *
556
556
  * The OIDC authorization endpoint (/idp/auth) requires a client_id; opening
557
557
  * /idp manually used to drop the user into a raw OIDC error. This page is
558
- * the human-navigable entry point — Create Account is wired up; Sign In is
559
- * intentionally a description for now (PR-B / #286 will introduce a
560
- * standalone /idp/login form).
558
+ * the human-navigable entry point.
559
+ *
560
+ * In single-user mode (`ctx.singleUser`) the Create Account button is
561
+ * suppressed — pod creation is disabled and the button would lead to a
562
+ * 403. The sign-in note still names pilot as the example client.
561
563
  */
562
564
  export function landingPage(ctx = {}) {
563
565
  const issuer = ctx.baseUri || '';
566
+ const singleUser = !!ctx.singleUser;
564
567
  return `
565
568
  <!DOCTYPE html>
566
569
  <html lang="en">
@@ -592,6 +595,8 @@ export function landingPage(ctx = {}) {
592
595
  line-height: 1.55;
593
596
  }
594
597
  .landing .signin-note strong { color: #1e293b; }
598
+ .landing .signin-note a { color: #4f46e5; text-decoration: none; font-weight: 500; }
599
+ .landing .signin-note a:hover { text-decoration: underline; }
595
600
  .landing .issuer {
596
601
  margin-top: 18px;
597
602
  text-align: center;
@@ -605,13 +610,17 @@ export function landingPage(ctx = {}) {
605
610
  <div class="container landing">
606
611
  <div class="landing-header">
607
612
  <h1>Solid Pod Server</h1>
608
- <p class="subtitle">Create an account, then sign in from any Solid app.</p>
613
+ <p class="subtitle">${singleUser
614
+ ? 'Single-user pod — sign in from any Solid app.'
615
+ : 'Create an account, then sign in from any Solid app.'}</p>
609
616
  </div>
610
617
 
611
- <a href="/idp/register" class="btn btn-primary" style="text-decoration: none;">Create Account</a>
618
+ ${singleUser
619
+ ? '' /* Registration is disabled in single-user mode; suppress the dead-end button. */
620
+ : '<a href="/idp/register" class="btn btn-primary" style="text-decoration: none;">Create Account</a>'}
612
621
 
613
622
  <div class="signin-note">
614
- <strong>Already have an account?</strong> Sign in from inside the Solid app you want to use the app will redirect here when authentication is needed.
623
+ <strong>${singleUser ? 'Sign in' : 'Already have an account?'}</strong> ${singleUser ? 'from' : 'Sign in from'} a Solid app — for example, <a href="https://solid-apps.github.io/pilot/" target="_blank" rel="noopener">pilot</a> is a minimal console you can open right now. Point it at this server and click Sign In.
615
624
  </div>
616
625
 
617
626
  ${issuer ? `<div class="issuer">Issuer: ${escapeHtml(issuer.replace(/\/$/, ''))}</div>` : ''}
package/test/idp.test.js CHANGED
@@ -192,6 +192,8 @@ describe('Identity Provider', () => {
192
192
  assert.match(body, /Solid Pod Server/);
193
193
  assert.match(body, /Create Account/);
194
194
  assert.match(body, /href="\/idp\/register"/);
195
+ // Sign-in note names pilot as the example client (#288).
196
+ assert.match(body, /solid-apps\.github\.io\/pilot/);
195
197
  });
196
198
 
197
199
  it('GET /idp/auth without client_id redirects to /idp', async () => {
@@ -354,6 +356,59 @@ describe('Identity Provider - Subdomain mode register validation', () => {
354
356
  });
355
357
  });
356
358
 
359
+ // Single-user mode: registration is disabled, so the /idp landing must
360
+ // suppress the "Create Account" button rather than ship a known 403 trap.
361
+ // Regression coverage for #290.
362
+ describe('Identity Provider - Single-user mode landing', () => {
363
+ let server;
364
+ let baseUrl;
365
+ const SINGLE_USER_DATA_DIR = './test-data-idp-single-user';
366
+
367
+ before(async () => {
368
+ await fs.remove(SINGLE_USER_DATA_DIR);
369
+ await fs.ensureDir(SINGLE_USER_DATA_DIR);
370
+
371
+ const port = await getAvailablePort();
372
+ baseUrl = `http://${TEST_HOST}:${port}`;
373
+
374
+ server = createServer({
375
+ logger: false,
376
+ root: SINGLE_USER_DATA_DIR,
377
+ idp: true,
378
+ idpIssuer: baseUrl,
379
+ singleUser: true,
380
+ singleUserName: 'me',
381
+ forceCloseConnections: true,
382
+ });
383
+
384
+ await server.listen({ port, host: TEST_HOST });
385
+ });
386
+
387
+ after(async () => {
388
+ await server.close();
389
+ await fs.remove(SINGLE_USER_DATA_DIR);
390
+ });
391
+
392
+ it('GET /idp omits the Create Account button', async () => {
393
+ const res = await fetch(`${baseUrl}/idp`);
394
+ assert.strictEqual(res.status, 200);
395
+ const body = await res.text();
396
+ // Sanity: the landing still rendered.
397
+ assert.match(body, /Solid Pod Server/);
398
+ // Button + register link must be absent — those would 403 in single-user mode.
399
+ assert.doesNotMatch(body, /Create Account/);
400
+ assert.doesNotMatch(body, /href="\/idp\/register"/);
401
+ // Sign-in note should still mention pilot as the example client.
402
+ assert.match(body, /solid-apps\.github\.io\/pilot/);
403
+ });
404
+
405
+ it('subtitle reflects the single-user shape', async () => {
406
+ const res = await fetch(`${baseUrl}/idp`);
407
+ const body = await res.text();
408
+ assert.match(body, /Single-user pod/);
409
+ });
410
+ });
411
+
357
412
  describe('Identity Provider - Accounts', () => {
358
413
  let server;
359
414
  let accountsUrl;