auth code changes / misc
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 = "/";
|
||||
}
|
||||
Reference in New Issue
Block a user