first commit
This commit is contained in:
123
frontend/src/router/index.js
Normal file
123
frontend/src/router/index.js
Normal file
@@ -0,0 +1,123 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import { useAuthStore } from "../stores/authStore";
|
||||
import { useSettingsStore } from "../stores/settingsStore";
|
||||
import LoginPage from "../pages/Login.vue";
|
||||
import RegisterPage from "../pages/Register.vue";
|
||||
|
||||
const decodeBase64UrlUTF8 = (value) => {
|
||||
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
||||
const padding = normalized.length % 4;
|
||||
const padded = padding === 0 ? normalized : `${normalized}${"=".repeat(4 - padding)}`;
|
||||
const binary = atob(padded);
|
||||
const bytes = Uint8Array.from(binary, (ch) => ch.charCodeAt(0));
|
||||
return new TextDecoder().decode(bytes);
|
||||
};
|
||||
const restoreOAuthSessionFromQuery = (query, authStore) => {
|
||||
// Merge router query with URLSearchParams for full coverage
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const accessToken = query.access_token || query.accessToken || query.token || params.get("access_token") || params.get("accessToken") || params.get("token");
|
||||
|
||||
if (!accessToken) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const plainUserJSON = query.user_json || params.get("user_json");
|
||||
const encodedUser = query.user || params.get("user");
|
||||
const user = plainUserJSON ? JSON.parse(plainUserJSON) : encodedUser ? JSON.parse(decodeBase64UrlUTF8(encodedUser)) : null;
|
||||
|
||||
if (!user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
authStore.setSession({ access_token: accessToken, user });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
component: LoginPage,
|
||||
},
|
||||
{
|
||||
path: "/register",
|
||||
name: "Register",
|
||||
component: RegisterPage,
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
name: "Home",
|
||||
component: () => import("../pages/Home.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "/admin",
|
||||
name: "Admin",
|
||||
component: () => import("../pages/Admin.vue"),
|
||||
meta: { requiresAuth: true, requiresAdminPermission: true },
|
||||
},
|
||||
{
|
||||
path: "/s/:spaceId",
|
||||
name: "PublicSpace",
|
||||
component: () => import("../pages/PublicSpace.vue"),
|
||||
},
|
||||
{
|
||||
path: "/s/:spaceId/n/:noteId",
|
||||
name: "PublicNote",
|
||||
component: () => import("../pages/PublicSpace.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const authStore = useAuthStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
|
||||
// Only attempt OAuth callback restoration if actual OAuth query params are present
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const hasOAuthParams = to.query.access_token || to.query.accessToken || to.query.token || params.get("access_token") || params.get("accessToken") || params.get("token");
|
||||
|
||||
if (to.path === "/login") {
|
||||
if (hasOAuthParams) {
|
||||
const restored = restoreOAuthSessionFromQuery(to.query, authStore);
|
||||
if (restored) {
|
||||
next({ path: "/", replace: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow login page to be viewed regardless of auth state if no OAuth callback
|
||||
if (!hasOAuthParams) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (to.path === "/register") {
|
||||
await settingsStore.loadFeatureFlags();
|
||||
if (!settingsStore.registrationEnabled) {
|
||||
next({ path: "/login", query: { message: "Registration is currently disabled." } });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
|
||||
next("/login");
|
||||
} else if (to.meta.requiresAdminPermission && !authStore.isAdmin) {
|
||||
next("/");
|
||||
} else if ((to.path === "/login" || to.path === "/register") && authStore.isAuthenticated) {
|
||||
next("/");
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user