clone

a personal forge on plain git: static pages, stacked-diff reviews, signed local ci, repo sites and releases

main
forge / site / _includes / login.njk
login.njk 3.7K
1{#- /login/, which lib/private-server.ts renders on request (it isn't built):2 sign in with a passkey, add one from the link that ssh <host> passkey3 prints (/login/#enroll=<code>; login.ts does both), join from the link4 forge user invite prints (/login/#invite=<code>: an SSH key, then a5 passkey), and, signed in, sign out. Each step is a panel named in6 lowercase for the forge (FORGE_NAME), not its domain; ssh commands show7 the real host, to copy. Data: forge, p (title), user (or ''), csrf,8 signal (JSON or ''), next, ready (sign-in is set up: FORGE_BASE_URL). -#}9{% extends "base.njk" %}10{% import "ui.njk" as ui %}11{% block scripts %}12<script src="{{ assets.webauthn }}" defer></script>13<script src="{{ assets.login }}" defer></script>14{% endblock %}15{% block head %}<meta name="robots" content="noindex">16{% endblock %}17{% block content %}18{% css %}19/* the sign-in page: a panel for each step, the status and the help under them */20.login { max-width: 40em; }21.login-status { min-height: 1.4em; margin: var(--space-3) 0 0; }22.login-status.bad { color: var(--fail); }23.login form { display: inline; }24.login .input { max-width: 36em; }25{% endcss %}26<div class="login" id="login" data-next="{{ next }}"{% if signal %} data-signal="{{ signal }}"{% endif %}>27{% if user %}28{% set head %}<h2>signed in as <b>{{ user }}</b></h2>{% endset %}29{% call ui.panel(head) %}<div class="panel-body">30<p>You see the pages of the private repos you can read: <a href="/private/">your private repos</a>.</p>31<form method="post" action="/login/logout"><input type="hidden" name="csrf" value="{{ csrf }}">{{ ui.button('sign out', false, 'id="signout"', 'submit') }}</form>32</div>{% endcall %}33{% elif not ready %}34{% call ui.panel('<h2>sign in</h2>') %}<div class="panel-body">35<p>Sign-in isn't set up here: the forge needs <code>FORGE_BASE_URL</code>, the origin passkeys belong to.</p>36</div>{% endcall %}37{% else %}38{% call ui.panel('<h2>sign in</h2>', '', 'id="signin-part"') %}<div class="panel-body">39<p>Private repos show their pages to their readers. Sign in with a passkey you have added to see them.</p>40<p>{{ ui.button('sign in with a passkey', true, 'id="signin"') }}</p>41</div>{% endcall %}42{% set head %}<h2>join {{ forge.config.name }}</h2>{% endset %}43{% call ui.panel(head, '', 'id="invite-part" hidden') %}<div class="panel-body" id="invite-form">44<p>You are invited as <b id="invite-user">you</b><span id="invite-grant"></span>. Your SSH key is how you get in: paste the public half, the one line of a <code>.pub</code> file such as <code>~/.ssh/id_ed25519.pub</code>. None yet? <code>ssh-keygen -t ed25519</code> makes one.</p>45<p>{{ ui.textarea('ssh public key', 'ssh-ed25519 AAAA... you@laptop', 'id="invite-key" rows="3" spellcheck="false" autocomplete="off" autocapitalize="off" maxlength="8192"', true) }}</p>46<p>{{ ui.button('join', true, 'id="invite-join"') }}</p>47</div>{% endcall %}48{% call ui.panel('<h2>add a passkey for <b id="enroll-user">you</b></h2>', '', 'id="enroll-part" hidden') %}<div class="panel-body">49<p id="joined" hidden>You are in: <code>ssh {{ forge.config.ssh }} help</code> says what you can do over ssh. A passkey signs you in on the web as well, to see the pages of private repos you may read. Not now? <code>ssh {{ forge.config.ssh }} passkey</code> prints a link for one later.</p>50<p>Your browser, phone or password manager keeps it, and signs you in with it from now on.</p>51<p>{{ ui.button('add a passkey', true, 'id="enroll"') }}</p>52</div>{% endcall %}53<p class="login-status" id="login-status" role="status"></p>54<p class="desc" id="login-help">No passkey yet, or lost them all? <code>ssh {{ forge.config.ssh }} passkey</code> prints a link that adds one: your ssh key is how you get in.</p>55{% endif %}56</div>57{% endblock %}