Sessions!
This commit is contained in:
parent
f34ead505b
commit
7af220de2e
8 changed files with 60 additions and 25 deletions
23
db/mod.ts
23
db/mod.ts
|
@ -159,6 +159,12 @@ export async function createToken(
|
|||
if (!(digest instanceof Uint8Array)) throw "token digest was non-brinary";
|
||||
intermediateToken.digest = digest;
|
||||
}
|
||||
log.debug(
|
||||
`intermediateToken bytes: ${base64.encode(intermediateToken.bytes)}`,
|
||||
);
|
||||
log.debug(
|
||||
`intermediateToken digest: ${base64.encode(intermediateToken.digest)}`,
|
||||
);
|
||||
if (!intermediateToken.data) intermediateToken.data = null;
|
||||
const result = singleRow(
|
||||
await queryObject<Token>(
|
||||
|
@ -174,8 +180,20 @@ export async function createToken(
|
|||
return null;
|
||||
}
|
||||
|
||||
export async function deleteToken(
|
||||
token: TokenDigest,
|
||||
) {
|
||||
const digest = sha256(base64.decode(token));
|
||||
return await queryObject(
|
||||
`
|
||||
delete from user_token where digest = $1
|
||||
`,
|
||||
[digest],
|
||||
);
|
||||
}
|
||||
|
||||
export async function getToken(token: TokenDigest): Promise<Token | null> {
|
||||
const digest = base64.decode(token);
|
||||
const digest = sha256(base64.decode(token));
|
||||
return singleRow(
|
||||
await queryObject(
|
||||
`
|
||||
|
@ -202,6 +220,7 @@ export async function getUser(
|
|||
export async function getUserFromNonExpiredLoginToken(
|
||||
token: TokenDigest,
|
||||
): Promise<User | null> {
|
||||
// TODO: if the token has expired, return a specific error?
|
||||
const digest = sha256(base64.decode(token));
|
||||
return singleRow(
|
||||
await queryObject<User>(
|
||||
|
@ -210,7 +229,7 @@ export async function getUserFromNonExpiredLoginToken(
|
|||
left join "user" u on u.id = ut.user_id
|
||||
where ut."digest" = $1
|
||||
and ut."data"->>'type' = 'login'
|
||||
and now() < (ut.created_at + '7 days'::interval)
|
||||
and now() < (ut.created_at + '14 days'::interval)
|
||||
`,
|
||||
[digest],
|
||||
),
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as $0 from "./routes/[name].tsx";
|
|||
import * as $1 from "./routes/_404.tsx";
|
||||
import * as $2 from "./routes/_500.tsx";
|
||||
import * as $3 from "./routes/_app.tsx";
|
||||
import * as $4 from "./routes/_middleware.ts";
|
||||
import * as $4 from "./routes/_middleware.tsx";
|
||||
import * as $5 from "./routes/about.tsx";
|
||||
import * as $6 from "./routes/api/joke.ts";
|
||||
import * as $7 from "./routes/api/random-uuid.ts";
|
||||
|
@ -33,7 +33,7 @@ const manifest = {
|
|||
"./routes/_404.tsx": $1,
|
||||
"./routes/_500.tsx": $2,
|
||||
"./routes/_app.tsx": $3,
|
||||
"./routes/_middleware.ts": $4,
|
||||
"./routes/_middleware.tsx": $4,
|
||||
"./routes/about.tsx": $5,
|
||||
"./routes/api/joke.ts": $6,
|
||||
"./routes/api/random-uuid.ts": $7,
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"imports": {
|
||||
"@/": "./",
|
||||
"$std/": "https://deno.land/std@0.158.0/",
|
||||
"$fresh/": "https://deno.land/x/fresh@1.1.2/",
|
||||
"$freshbranch/": "https://raw.githubusercontent.com/lytedev/fresh/v1.1.2-df/",
|
||||
"$fresh/": "../fresh/",
|
||||
"preact": "https://esm.sh/preact@10.11.0",
|
||||
"preact/": "https://esm.sh/preact@10.11.0/",
|
||||
"preact-render-to-string": "https://esm.sh/*preact-render-to-string@5.2.4",
|
||||
|
|
|
@ -2,18 +2,6 @@ import { type AppProps, Handlers } from "$fresh/server.ts";
|
|||
import { type PublicUser } from "@/types.ts";
|
||||
import { type ContextState } from "@/types.ts";
|
||||
|
||||
interface MyAppProps extends AppProps {
|
||||
user?: PublicUser;
|
||||
}
|
||||
|
||||
export const handler: Handlers<MyAppProps, ContextState> = {
|
||||
async GET(request: Request, context) {
|
||||
console.error("\n\nYO\n\n");
|
||||
console.log("AppHandler:", request, context);
|
||||
return await context.render({ user: context.state.user });
|
||||
},
|
||||
};
|
||||
|
||||
const NAV_ITEM_CLASSES =
|
||||
"flex justify-center items-center px-4 py-2 hover:bg-gray-300 dark:hover:bg-gray-700";
|
||||
|
||||
|
@ -50,8 +38,9 @@ export function UserNavItems() {
|
|||
);
|
||||
}
|
||||
|
||||
export default function App({ Component, ...props }: MyAppProps) {
|
||||
console.log("AppProps:", props);
|
||||
export default function App(
|
||||
{ Component, contextState }: AppProps<ContextState>,
|
||||
) {
|
||||
return (
|
||||
<div class="relative min-h-screen flex flex-col">
|
||||
<header class="flex justify-start items-center">
|
||||
|
@ -64,11 +53,11 @@ export default function App({ Component, ...props }: MyAppProps) {
|
|||
<h1 class="text-2xl">LyricScreen</h1>
|
||||
</a>
|
||||
<a tabIndex={11} href="/note" class={NAV_ITEM_CLASSES}>Notes</a>
|
||||
{props.user ? UserNavItems() : LoginNavItems()}
|
||||
{contextState.user ? UserNavItems() : LoginNavItems()}
|
||||
</nav>
|
||||
</header>
|
||||
<main class="p-2">
|
||||
<Component></Component>
|
||||
<Component />
|
||||
</main>
|
||||
<footer class={`p-2 w-full mt-auto ${HEADER_CLASSES}`}>
|
||||
"It's a bit much, really..."
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { MiddlewareHandlerContext } from "$fresh/server.ts";
|
||||
import { LayoutProps, MiddlewareHandlerContext } from "$fresh/server.ts";
|
||||
import { deleteCookie, getCookies } from "$std/http/cookie.ts";
|
||||
import { getUserFromNonExpiredLoginToken } from "@/db/mod.ts";
|
||||
import { type ContextState, type PublicUser, type User } from "@/types.ts";
|
||||
|
@ -14,10 +14,22 @@ function toPublicUser(user: User): PublicUser {
|
|||
return publicUser;
|
||||
}
|
||||
|
||||
function Layout({ state, Component }: LayoutProps<ContextState>) {
|
||||
return (
|
||||
<>
|
||||
{state.something
|
||||
? <p>Oh my! You said something!</p>
|
||||
: <p>You aren't saying anything.</p>}
|
||||
<Component />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function currentUser(
|
||||
request: Request,
|
||||
context: MiddlewareHandlerContext<ContextState>,
|
||||
) {
|
||||
context.layout = Layout;
|
||||
let hasBadAuthCookie = false;
|
||||
const { lsauth } = getCookies(request.headers);
|
||||
log.debug("lsauth cookie:", lsauth);
|
||||
|
@ -46,7 +58,16 @@ export async function serverHeader(
|
|||
return resp;
|
||||
}
|
||||
|
||||
export async function someState(
|
||||
_request: Request,
|
||||
context: MiddlewareHandlerContext<ContextState>,
|
||||
) {
|
||||
context.state.something = "I said something!";
|
||||
return await context.next();
|
||||
}
|
||||
|
||||
export const handler = [
|
||||
someState,
|
||||
currentUser,
|
||||
serverHeader,
|
||||
];
|
|
@ -10,7 +10,6 @@ export const handler: Handlers<unknown, ContextState> = {
|
|||
};
|
||||
|
||||
export default function Dashboard({ data }: PageProps) {
|
||||
console.log(data);
|
||||
if (data) {
|
||||
return You(data);
|
||||
} else {
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import { Handlers } from "$fresh/server.ts";
|
||||
// import { getToken, getUser } from "@/db/mod.ts";
|
||||
// import * as base64 from "$std/encoding/base64.ts";
|
||||
import { deleteCookie } from "$std/http/cookie.ts";
|
||||
import { deleteCookie, getCookies } from "$std/http/cookie.ts";
|
||||
import { deleteToken } from "@/db/mod.ts";
|
||||
|
||||
export const handler: Handlers<unknown> = {
|
||||
async GET(_request: Request, context) {
|
||||
async GET(request: Request, context) {
|
||||
const { lsauth } = getCookies(request.headers);
|
||||
if (lsauth) {
|
||||
console.log("deleteToken:", await deleteToken(lsauth));
|
||||
}
|
||||
const response = await context.render();
|
||||
deleteCookie(response.headers, "lsauth");
|
||||
return response;
|
||||
|
|
1
types.ts
1
types.ts
|
@ -50,4 +50,5 @@ export type TokenDigest = string;
|
|||
|
||||
export interface ContextState {
|
||||
user?: PublicUser;
|
||||
something?: string;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue