feature: remember if someone has logged in and default to a login screen

fix: some includes needed updating
feature: some more overrides
This commit is contained in:
Andy Burke 2026-01-30 18:39:03 -08:00
parent ebf0e4428e
commit 7b3494cc32
12 changed files with 90 additions and 55 deletions

View file

@ -6,10 +6,11 @@ import { SESSION, SESSIONS } from '../../../models/session.ts';
import { TOTP_ENTRIES } from '../../../models/totp_entry.ts';
import { encodeBase64 } from '@std/encoding/base64';
import parse_body from '../../../utils/bodyparser.ts';
import { get_session, get_user, PRECHECK_TABLE, require_user, SESSION_ID_TOKEN, SESSION_SECRET_TOKEN } from '../../../utils/prechecks.ts';
import { AUTHED_BEFORE_COOKIE_ID, get_session, get_user, PRECHECK_TABLE, require_user, SESSION_ID_TOKEN, SESSION_SECRET_TOKEN } from '../../../utils/prechecks.ts';
import * as bcrypt from '@da/bcrypt';
import { verifyTotp } from '../../../utils/totp.ts';
const AUTHED_BEFORE_EXPIRATION: number = 399 * (24 * (60 * (60 * 1_000))); // 399 days
const DEFAULT_SESSION_TIME: number = 365 * (24 * (60 * (60 * 1_000))); // 365 days
export const PRECHECKS: PRECHECK_TABLE = {};
@ -206,6 +207,7 @@ export async function create_new_session(session_settings: SESSION_INFO): Promis
const headers = new Headers();
const expires_in_utc = new Date(session.timestamps.expires).toUTCString();
headers.append('Set-Cookie', `${AUTHED_BEFORE_COOKIE_ID}=1; Path=/; Secure; Expires=${new Date(new Date(now).valueOf() + AUTHED_BEFORE_EXPIRATION).toUTCString()}`);
headers.append('Set-Cookie', `${SESSION_ID_TOKEN}=${session.id}; Path=/; Secure; Expires=${expires_in_utc}`);
headers.append(`x-${SESSION_ID_TOKEN}`, session.id);

View file

@ -169,6 +169,15 @@ body {
/* fixed height? */
}
#background-container {
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: -1;
}
main {
position: relative;
width: 100%;

View file

@ -3,13 +3,14 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>autonomous.contact</title>
<title><!-- #include "./files/settings/title.txt" or "./title.txt" --></title>
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png" ></link>
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png" ></link>
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png" ></link>
<link rel="stylesheet" href="/base.css"></link>
<link rel="stylesheet" href="/files/custom.css"></link>
<!-- inlining these to force them to be scoped for everything else -->
<script type="text/javascript"><!-- #include "./js/_utils.js" --></script>
@ -45,6 +46,8 @@
</head>
<body>
<div id="background-container"></div>
<!-- #include "./signup_login_wall.html" -->
<main>

View file

@ -5,10 +5,13 @@ const api = {
...__options,
};
// FIXME: this will break with different server settings
// TODO: we need the cookie names here to match any configured on the server
const session_id = (document.cookie.match(
/^(?:.*;)?\s*session_id\s*=\s*([^;]+)(?:.*)?$/,
) || [, null])[1];
// FIXME: this will break with different server settings
// TODO: this wasn't really intended to be persisted in a cookie
const session_secret = (document.cookie.match(
/^(?:.*;)?\s*session_secret\s*=\s*([^;]+)(?:.*)?$/,

View file

@ -14,7 +14,19 @@
background: var(--bg);
visibility: visible;
opacity: 1;
transition: all 0.33s;
transition: all 0.33s ease;
animation: slideIn 0.4s ease;
}
@keyframes slideIn {
from {
opacity: 0;
transform: scale(1.2);
}
to {
opacity: 1;
transform: scale(1.0);
}
}
#login-tab .tab-content {
@ -49,52 +61,17 @@
}
</style>
<!-- #include "./files/settings/signup_pitch.md" or "./signup_pitch.default.md" -->
<!-- #include "./files/settings/signup_pitch.html" or "./files/settings/signup_pitch.md" or "./signup_pitch.default.md" -->
<div class="limiter">
<div class="tabs">
<div id="login-tab" class="tab">
<input
type="radio"
name="signup-login-tabs"
id="login-tab-input"
class="tab-switch"
checked="checked"
/>
<label for="login-tab-input" class="tab-label">
<div class="label">Log In</div>
</label>
<div class="tab-content">
<form data-smart="true" data-method="POST" id="login-form" action="/api/auth">
<script>
{
const form = document.currentScript.closest("form");
form.on_reply = (response) => {
const user = response.user;
APP.login( user );
};
}
</script>
<div>
<input id="login-username" type="text" name="username" required />
<label class="placeholder" for="login-username">username</label>
</div>
<div>
<input id="login-password" type="password" name="password" required />
<label class="placeholder" for="login-password">password</label>
</div>
<div>
<button id="login-submit" type="submit" class="primary">Log In</button>
</div>
</form>
</div>
</div>
<div id="signup-tab" class="tab">
<input
type="radio"
name="signup-login-tabs"
id="signup-tab-input"
class="tab-switch"
checked="checked"
/>
<label for="signup-tab-input" class="tab-label">
<div class="label">Sign Up</div>
@ -136,6 +113,7 @@
id="signup-invite-code"
type="text"
name="invite_code"
required
/>
<label class="placeholder" for="signup-invite-code">invite code</label>
</div>
@ -143,6 +121,53 @@
</form>
</div>
</div>
<div id="login-tab" class="tab">
<input
type="radio"
name="signup-login-tabs"
id="login-tab-input"
class="tab-switch"
/>
<label for="login-tab-input" class="tab-label">
<div class="label">Log In</div>
</label>
<div class="tab-content">
<form data-smart="true" data-method="POST" id="login-form" action="/api/auth">
<script>
{
const form = document.currentScript.closest("form");
form.on_reply = (response) => {
const user = response.user;
APP.login( user );
};
}
</script>
<div>
<input id="login-username" type="text" name="username" required />
<label class="placeholder" for="login-username">username</label>
</div>
<div>
<input id="login-password" type="password" name="password" required />
<label class="placeholder" for="login-password">password</label>
</div>
<div>
<button id="login-submit" type="submit" class="primary">Log In</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
document.addEventListener( 'DOMContentLoaded', () => {
const authed_before = (document.cookie.match(
/^(?:.*;)?\s*authed_before\s*=\s*([^;]+)(?:.*)?$/,
) || [, null])[1];
if ( authed_before ) {
document.getElementById("login-tab-input").checked = true;
}
});
</script>
</div>

View file

@ -11,6 +11,6 @@
<div class="label">Calendar</div></label
>
<div class="tab-content">
<!-- #include file="./README.md" -->
<!-- #include "./README.md" -->
</div>
</div>

View file

@ -11,6 +11,6 @@
<div class="label">Exchange</div></label
>
<div class="tab-content">
<!-- #include file="./README.md" -->
<!-- #include "./README.md" -->
</div>
</div>

View file

@ -12,6 +12,6 @@
<div class="label">Home</div>
</label>
<div class="tab-content">
<!-- #include file="./README.md" -->
<!-- #include "./README.md" -->
</div>
</div>

View file

@ -10,5 +10,5 @@
><div class="icon resources"></div>
<div class="label">Resources</div></label
>
<div class="tab-content"><!-- #include file="./README.md" --></div>
<div class="tab-content"><!-- #include "./README.md" --></div>
</div>

View file

@ -111,21 +111,13 @@
@media screen and (max-width: 800px) {
.tab-label {
width: 3rem;
}
.tab-label .label {
font-size: small;
width: 4rem;
}
}
@media screen and (max-width: 400px) {
.tab-label {
width: 2.5rem;
}
.tab-label .label {
font-size: 8px;
width: 3rem;
}
}
</style>

View file

@ -10,5 +10,5 @@
><div class="icon work"></div>
<div class="label">Work</div>
</label>
<div class="tab-content"><!-- #include file="./README.md" --></div>
<div class="tab-content"><!-- #include "./README.md" --></div>
</div>