auth code changes / misc

This commit is contained in:
2025-11-25 05:56:46 -05:00
parent fb64a0f99a
commit 05aa48af14
7 changed files with 65 additions and 57 deletions

View File

@@ -2,6 +2,17 @@ import React, { useState, useRef, useEffect } from "react";
import { toast } from "react-toastify";
import { API_URL } from "@/config";
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return decodeURIComponent(parts.pop().split(';').shift());
return null;
}
function clearCookie(name) {
document.cookie = `${name}=; Max-Age=0; path=/;`;
}
export default function LoginPage() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
@@ -20,32 +31,24 @@ export default function LoginPage() {
setLoading(true);
try {
if (!username) {
if (!username || !password) {
setLoading(false);
if (!toast.isActive("login-username-required-toast")) {
return toast.error("Username and password are required",
{
toastId: "login-missing-data-toast",
});
}
}
if (!password) {
setLoading(false);
if (!toast.isActive("login-password-required-toast")) {
return toast.error("Username and password are required",
{
toastId: "login-missing-data-toast",
});
if (!toast.isActive("login-missing-data-toast")) {
toast.error("Username and password are required", {
toastId: "login-missing-data-toast",
});
}
return;
}
const formData = new URLSearchParams();
formData.append("username", username);
formData.append("password", password);
formData.append("grant_type", "password");
formData.append("scope", "");
formData.append("client_id", "");
formData.append("client_secret", "");
const formData = new URLSearchParams({
username,
password,
grant_type: "password",
scope: "",
client_id: "",
client_secret: "",
});
const resp = await fetch(`${API_URL}/auth/login`, {
method: "POST",
@@ -55,52 +58,40 @@ export default function LoginPage() {
});
if (resp.status === 401) {
if (!toast.isActive("login-error-invalid-toast")) {
toast.error("Invalid username or password", {
toastId: "login-error-invalid-toast",
});
}
toast.error("Invalid username or password", {
toastId: "login-error-invalid-toast",
});
setLoading(false);
return;
}
if (!resp.ok) {
const data = await resp.json().catch(() => ({}));
if (!toast.isActive("login-error-failed-toast")) {
toast.error(data.detail ? `Login failed: ${data.detail}` : "Login failed",
{
toastId: "login-error-failed-toast",
});
}
toast.error(data.detail ? `Login failed: ${data.detail}` : "Login failed", {
toastId: "login-error-failed-toast",
});
setLoading(false);
return;
}
const data = await resp.json();
if (data.access_token) {
if (!toast.isActive("login-success-toast")) {
toast.success("Login successful!",
{
toastId: "login-success-toast",
});
}
window.location.href = "/TRip"; // TODO: fix, hardcoded
toast.success("Login successful!", {
toastId: "login-success-toast",
});
const returnTo = getCookie("returnTo") || "/TRip";
clearCookie("returnTo");
window.location.href = returnTo;
} else {
if (!toast.isActive("login-error-no-token-toast")) {
toast.error("Login failed: no access token received",
{
toastId: "login-error-no-token-toast",
});
setLoading(false);
}
toast.error("Login failed: no access token received", {
toastId: "login-error-no-token-toast",
});
setLoading(false);
}
} catch (error) {
if (!toast.isActive("login-error-network-toast")) {
toast.error("Network error during login",
{
toastId: "login-error-network-toast",
});
}
toast.error("Network error during login", {
toastId: "login-error-network-toast",
});
console.error("Login error:", error);
setLoading(false);
}

View File

@@ -283,7 +283,9 @@ export default function MediaRequestForm() {
link.href = url;
const sanitize = (str) => str.replace(/[\\/:*?"<>|]/g, "_");
const filename = `${sanitize(artist)} - ${sanitize(title)}.flac`;
const urlPath = new URL(data.stream_url).pathname;
const extension = urlPath.split('.').pop().split('?')[0] || 'flac';
const filename = `${sanitize(artist)} - ${sanitize(title)}.${extension}`;
link.download = filename;
document.body.appendChild(link);

View File

@@ -3,6 +3,8 @@ import { metaData } from "../config";
import { Icon } from "astro-icon/components";
import ExitToApp from '@mui/icons-material/ExitToApp';
const isLoggedIn = Astro.cookies.get('access_token') || Astro.cookies.get('refresh_token');
const navItems = [
{ label: "Home", href: "/" },
{ label: "Radio", href: "/radio" },
@@ -11,6 +13,7 @@ const navItems = [
{ label: "TRip", href: "/TRip", auth: true },
{ label: "Status", href: "https://status.boatson.boats", icon: ExitToApp },
{ label: "Git", href: "https://kode.boatson.boats", icon: ExitToApp },
// ...(isLoggedIn ? [{ label: "Logout", href: "#", onClick: "handleLogout()" }] : []), # todo
];
const currentPath = Astro.url.pathname;

View File

@@ -3,10 +3,11 @@ import Base from "@/layouts/Base.astro";
import Root from "@/components/AppLayout.jsx";
import { requireAuthHook } from "@/hooks/requireAuthHook";
const user = await requireAuthHook(Astro);
if (!user) {
const decodedUrl = decodeURIComponent(Astro.url.pathname + Astro.url.search);
Astro.cookies.set('returnTo', decodedUrl, { path: '/' });
return Astro.redirect('/login');
}

View File

@@ -6,6 +6,8 @@ import { requireAuthHook } from "@/hooks/requireAuthHook";
const user = await requireAuthHook(Astro);
if (!user) {
const decodedUrl = decodeURIComponent(Astro.url.pathname + Astro.url.search);
Astro.cookies.set('returnTo', decodedUrl, { path: '/' });
return Astro.redirect('/login');
}

View File

@@ -5,10 +5,11 @@ import { requireAuthHook } from "@/hooks/requireAuthHook";
const user = await requireAuthHook(Astro);
if (!user) {
if (!user || !user.roles.includes('lighting')) {
const decodedUrl = decodeURIComponent(Astro.url.pathname + Astro.url.search);
Astro.cookies.set('returnTo', decodedUrl, { path: '/' });
return Astro.redirect('/login');
}
---
<Base>

View File

@@ -50,3 +50,11 @@ export async function refreshAccessToken(cookieHeader) {
return null;
}
}
export function handleLogout() {
document.cookie.split(";").forEach((cookie) => {
const name = cookie.split("=")[0].trim();
document.cookie = `${name}=; Max-Age=0; path=/;`;
});
window.location.href = "/";
}