Files
seasoned/src/routes.ts
Kevin Midboe e0ce0ea6da Fix: Add localStorage fallback for Plex authentication checks
Issue: ActivityPage and route guards showed "not authenticated"
even when Plex was linked via Settings page.

Root cause: Plex user data stored in localStorage but route guards
and ActivityPage only checked Vuex store (state.settings.plexUserId).

Changes:
- Update routes.ts hasPlexAccount() to check both:
  1. Vuex store (user/plexUserId)
  2. localStorage (plex_user_data) as fallback

- Update ActivityPage plexUserId computed to check both:
  1. Vuex store first
  2. localStorage plex_user_data.id as fallback

Why two sources?
- Vuex store: Set from JWT token (backend user settings)
- localStorage: Set immediately when linking Plex account
- localStorage persists across page reloads
- Provides seamless experience without backend round-trip

Now Activity page correctly shows data when Plex is linked ✓
2026-02-27 19:21:13 +01:00

153 lines
3.5 KiB
TypeScript

import { createRouter, createWebHistory } from "vue-router";
import type { RouteRecordRaw, RouteLocationNormalized } from "vue-router";
/* eslint-disable-next-line import-x/no-cycle */
import store from "./store";
declare global {
interface Window {
preventPushState: boolean;
}
}
const routes: RouteRecordRaw[] = [
{
name: "home",
path: "/",
component: () => import("./pages/HomePage.vue")
},
{
name: "activity",
path: "/activity",
meta: { requiresAuth: true, requiresPlexAccount: true },
component: () => import("./pages/ActivityPage.vue")
},
{
name: "profile",
path: "/profile",
meta: { requiresAuth: true },
component: () => import("./pages/ProfilePage.vue")
},
{
name: "requests-list",
path: "/list/requests",
component: () => import("./pages/RequestPage.vue")
},
{
name: "list",
path: "/list/:name",
component: () => import("./pages/ListPage.vue")
},
{
name: "search",
path: "/search",
component: () => import("./pages/SearchPage.vue")
},
{
name: "register",
path: "/register",
component: () => import("./pages/RegisterPage.vue")
},
{
name: "settings",
path: "/settings",
meta: { requiresAuth: true },
component: () => import("./pages/SettingsPage.vue")
},
{
name: "signin",
path: "/signin",
alias: "/login",
component: () => import("./pages/SigninPage.vue")
},
{
name: "torrents",
path: "/torrents",
meta: { requiresAuth: true },
component: () => import("./pages/TorrentsPage.vue")
},
// {
// name: 'user-requests',
// path: '/profile/requests',
// components: {
// 'user-requests-router-view': require('./components/MoviesList.vue')
// }
// },
{
name: "password-gen",
path: "/password",
component: () => import("./pages/GenPasswordPage.vue")
},
{
name: "admin",
path: "/admin",
meta: { requiresAuth: true },
component: () => import("./pages/AdminPage.vue")
}
// {
// path: "*",
// redirect: "/"
// },
// {
// path: "/request",
// redirect: "/"
// }
];
const router = createRouter({
history: createWebHistory("/"),
// base: "/",
routes,
linkActiveClass: "is-active"
});
const loggedIn = () => store.getters["user/loggedIn"];
const hasPlexAccount = () => {
// Check Vuex store first
if (store.getters["user/plexUserId"] !== null) return true;
// Fallback to localStorage
const userData = localStorage.getItem("plex_user_data");
if (userData) {
try {
const parsed = JSON.parse(userData);
return parsed.id !== null && parsed.id !== undefined;
} catch {
return false;
}
}
return false;
};
const hamburgerIsOpen = () => store.getters["hamburger/isOpen"];
router.beforeEach(
(to: RouteLocationNormalized, from: RouteLocationNormalized, next: any) => {
store.dispatch("documentTitle/updateTitle", to.name);
store.dispatch("popup/resetStateFromUrlQuery", to.query);
// Every route change we close hamburger if open
if (hamburgerIsOpen()) store.dispatch("hamburger/close");
// If pages has meta 'requiresAuth' and user not logged in
// send user to signin page.
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!loggedIn()) {
next({ path: "/signin" });
}
}
if (to.matched.some(record => record.meta.requiresPlexAccount)) {
if (!hasPlexAccount()) {
next({
path: "/settings",
query: { missingPlexAccount: true }
});
}
}
next();
}
);
export default router;