From 7a5f43d799e533f2288470aff77f9f18fee8ec16 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Wed, 9 Aug 2023 15:58:36 +0200 Subject: [PATCH] feat: redirect to same url on login/logout --- islands/KMenu/commands.ts | 16 ++++++++++++++-- islands/Search.tsx | 4 +++- routes/api/auth/callback.ts | 16 ++++++++++------ routes/api/auth/login.ts | 17 ++++++++++++----- routes/api/auth/logout.ts | 9 +++++++-- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/islands/KMenu/commands.ts b/islands/KMenu/commands.ts index bd75c12..9e9756c 100644 --- a/islands/KMenu/commands.ts +++ b/islands/KMenu/commands.ts @@ -29,7 +29,13 @@ export const menus: Record = { title: "Login", icon: "IconLogin", cb: () => { - window.location.pathname = "/api/auth/login"; + const url = new URL(window.location.href); + url.pathname = "/api/auth/login"; + url.searchParams.set( + "redirect", + encodeURIComponent(window.location.pathname), + ); + window.location.href = url.href; }, visible: () => { return !getCookie("session_cookie"); @@ -49,7 +55,13 @@ export const menus: Record = { title: "Logout", icon: "IconLogout", cb: () => { - window.location.pathname = "/api/auth/logout"; + const url = new URL(window.location.href); + url.pathname = "/api/auth/logout"; + url.searchParams.set( + "redirect", + encodeURIComponent(window.location.pathname), + ); + window.location.href = url.href; }, visible: () => { return !!getCookie("session_cookie"); diff --git a/islands/Search.tsx b/islands/Search.tsx index 3cd0c2b..2c93f8b 100644 --- a/islands/Search.tsx +++ b/islands/Search.tsx @@ -4,7 +4,7 @@ import { IconGhost, IconLoader2, IconSearch } from "@components/icons.tsx"; import { useEventListener } from "@lib/hooks/useEventListener.ts"; import { SearchResult } from "@lib/types.ts"; import { resources } from "@lib/resources.ts"; -import { isLocalImage } from "@lib/string.ts"; +import { getCookie, isLocalImage } from "@lib/string.ts"; import { IS_BROWSER } from "$fresh/runtime.ts"; import Checkbox from "@components/Checkbox.tsx"; import { Rating } from "@components/Rating.tsx"; @@ -13,6 +13,8 @@ import Image from "@components/Image.tsx"; import { Emoji } from "@components/Emoji.tsx"; export const RedirectSearchHandler = () => { + if (!getCookie("session_cookie")) return; + useEventListener("keydown", (e: KeyboardEvent) => { if (e?.target?.nodeName == "INPUT") return; if ( diff --git a/routes/api/auth/callback.ts b/routes/api/auth/callback.ts index c744a94..2c35d70 100644 --- a/routes/api/auth/callback.ts +++ b/routes/api/auth/callback.ts @@ -1,10 +1,7 @@ import { Handlers } from "$fresh/server.ts"; import { create, getNumericDate } from "https://deno.land/x/djwt@v2.2/mod.ts"; import { oauth2Client } from "@lib/auth.ts"; -import { - getCookies, - setCookie, -} from "https://deno.land/std@0.197.0/http/cookie.ts"; +import { getCookies, setCookie } from "$std/http/cookie.ts"; import { codeChallengeMap } from "./login.ts"; import { GITEA_SERVER, JWT_SECRET, SESSION_DURATION } from "@lib/env.ts"; import { userDB } from "@lib/db.ts"; @@ -20,7 +17,12 @@ export const handler: Handlers = { // Exchange the authorization code for an access token const cookies = getCookies(request.headers); - const codeVerifier = codeChallengeMap.get(cookies["code_challenge"]); + const stored = codeChallengeMap.get(cookies["code_challenge"]); + if (!stored) { + throw new BadRequestError(); + } + + const { codeVerifier, redirect } = stored; const tokens = await oauth2Client.code.getToken(request.url, { codeVerifier, @@ -53,8 +55,10 @@ export const handler: Handlers = { exp: getNumericDate(SESSION_DURATION), }, JWT_SECRET); + console.log({ redirect }); + const headers = new Headers({ - location: "/", + location: redirect || "/", }); setCookie(headers, { diff --git a/routes/api/auth/login.ts b/routes/api/auth/login.ts index 303de2f..fde929f 100644 --- a/routes/api/auth/login.ts +++ b/routes/api/auth/login.ts @@ -1,18 +1,25 @@ import { Handlers } from "$fresh/server.ts"; import { oauth2Client } from "@lib/auth.ts"; -import { sha256 } from "@lib/string.ts"; -import { setCookie } from "https://deno.land/std@0.197.0/http/cookie.ts"; +import { setCookie } from "$std/http/cookie.ts"; -export const codeChallengeMap = new Map(); +export const codeChallengeMap = new Map< + string, + { codeVerifier: string; redirect?: string } +>(); export const handler: Handlers = { - async GET() { + async GET(req) { + const url = new URL(req.url); + const { codeVerifier, uri } = await oauth2Client.code.getAuthorizationUri(); const codeChallenge = uri.searchParams.get("code_challenge"); if (!codeChallenge) return new Response(); - codeChallengeMap.set(codeChallenge, codeVerifier); + codeChallengeMap.set(codeChallenge, { + codeVerifier, + redirect: decodeURIComponent(url.searchParams.get("redirect") || ""), + }); const headers = new Headers(); setCookie(headers, { diff --git a/routes/api/auth/logout.ts b/routes/api/auth/logout.ts index 3a4cbca..5bbbde4 100644 --- a/routes/api/auth/logout.ts +++ b/routes/api/auth/logout.ts @@ -2,9 +2,14 @@ import { deleteCookie } from "https://deno.land/std@0.197.0/http/cookie.ts"; import { Handlers } from "$fresh/server.ts"; export const handler: Handlers = { - GET() { + GET(req) { + const url = new URL(req.url); + + const redirect = decodeURIComponent(url.searchParams.get("redirect") || ""); + const headers = new Headers(); - headers.append("location", "/"); + headers.append("location", redirect || "/"); + deleteCookie(headers, "session_cookie", { path: "/", });