add client-side login
Some checks are pending
Deploy to Pages / Build (push) Waiting to run
Deploy to Pages / Deploy (push) Blocked by required conditions

This commit is contained in:
Henry Hiles 2025-06-19 16:44:08 -04:00
commit d1a6802852
No known key found for this signature in database
2 changed files with 70 additions and 18 deletions

View file

@ -6,12 +6,11 @@ import "../styles/login.css"
<StarlightPage <StarlightPage
frontmatter={{ title: "Sign In to Federated Nexus", template: "splash" }} frontmatter={{ title: "Sign In to Federated Nexus", template: "splash" }}
> >
<form method="post" action="http://auth.federated.nexus/login"> <form method="post" action="https://auth.federated.nexus/login">
<input type="hidden" name="nonce" />
<input type="hidden" name="scope" />
<input type="hidden" name="state" />
<input type="hidden" name="client_id" />
<input type="hidden" name="redirect_uri" /> <input type="hidden" name="redirect_uri" />
<input type="hidden" name="state" />
<input type="hidden" name="user_id" />
<input type="hidden" name="access_token" />
<label> <label>
Username Username
@ -22,9 +21,8 @@ import "../styles/login.css"
<input type="password" name="password" /> <input type="password" name="password" />
</label> </label>
<button class="sl-link-button astro-e5owd36c primary" type="submit"> <span id="error"></span>
Submit <button type="submit"><span>Submit</span></button>
</button>
<a href="/">Don't have an account? Apply at our home page.</a> <a href="/">Don't have an account? Apply at our home page.</a>
</form> </form>
@ -32,18 +30,57 @@ import "../styles/login.css"
<script> <script>
const params = new URLSearchParams(window.location.search) const params = new URLSearchParams(window.location.search)
for (const name of ["redirect_uri", "state"]) {
for (const name of [
"client_id",
"nonce",
"scope",
"redirect_uri",
"state",
]) {
const input = document.querySelector( const input = document.querySelector(
`input[name="${name}"]` `input[name="${name}"]`
) as HTMLInputElement ) as HTMLInputElement
if (input && params.has(name)) input.value = params.get(name)! if (input && params.has(name)) input.value = params.get(name)!
} }
const form = document.querySelector("form")!
const error = document.querySelector("#error")! as HTMLSpanElement
form.addEventListener("submit", async (e) => {
e.preventDefault()
error.style.display = "none"
const username = form.username.value
const password = form.password.value
try {
const res = await fetch(
"https://matrix.federated.nexus/_matrix/client/v3/login",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
type: "m.login.password",
identifier: { type: "m.id.user", user: username },
password,
}),
}
)
if (!res.ok) {
throw new Error((await res.json())["error"])
}
const data = await res.json()
const id = form.querySelector(
'input[name="user_id"]'
) as HTMLInputElement
id.value = data.user_id
const token = form.querySelector(
'input[name="access_token"]'
) as HTMLInputElement
token.value = "data.access_token"
form.submit()
} catch (err: any) {
error.textContent = err.message || "Login failed"
error.style.display = "block"
}
})
</script> </script>

View file

@ -19,8 +19,23 @@ body {
} }
& button { & button {
margin-top: 1.4rem; margin: 1.4rem 0;
cursor: pointer; cursor: pointer;
border: none;
border-radius: 999rem;
gap: 0.5em;
line-height: 1.2;
background: var(--sl-color-text-accent);
color: var(--sl-color-black);
font-size: var(--sl-text-base);
padding: 1rem 1.25rem;
}
& #error {
margin-top: 1rem;
color: var(--sl-color-red);
} }
} }
} }