feur
This commit is contained in:
parent
8b6a86f17a
commit
3aea126342
14 changed files with 205 additions and 67 deletions
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Twifeur
|
||||
|
||||
Feur
|
||||
|
||||
## Feur
|
||||
|
||||
Feur feur.
|
15
api/login.ts
15
api/login.ts
|
@ -1,7 +1,16 @@
|
|||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { Env } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { login, set_user } from "../lib/auth.ts";
|
||||
|
||||
export function login_route(context: Context<Env, string, BlankInput>) {
|
||||
return context.text("E");
|
||||
export async function login_route(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const data = await context.req.formData();
|
||||
let username = data.get("login"), pass = data.get("password");
|
||||
if (username === null || pass === null) return context.redirect("/login");
|
||||
username = username.toString(), pass = pass.toString();
|
||||
const logged = await login(username, pass);
|
||||
if (logged === null) return context.redirect("/login");
|
||||
console.log("Logged in", { username });
|
||||
set_user(context, logged);
|
||||
return context.redirect("/user");
|
||||
}
|
||||
|
|
9
api/logout.ts
Normal file
9
api/logout.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { set_user } from "../lib/auth.ts";
|
||||
|
||||
export function logout_route(context: Context<FeurEnv, string, BlankInput>) {
|
||||
set_user(context, null);
|
||||
return context.redirect("/");
|
||||
}
|
51
deno.lock
generated
51
deno.lock
generated
|
@ -2,21 +2,42 @@
|
|||
"version": "3",
|
||||
"packages": {
|
||||
"specifiers": {
|
||||
"npm:@types/node": "npm:@types/node@18.16.19"
|
||||
"npm:@types/node": "npm:@types/node@18.16.19",
|
||||
"npm:hono@^4.0.0": "npm:hono@4.4.0",
|
||||
"npm:iron-webcrypto@0.10.1": "npm:iron-webcrypto@0.10.1"
|
||||
},
|
||||
"npm": {
|
||||
"@types/node@18.16.19": {
|
||||
"integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"hono@4.4.0": {
|
||||
"integrity": "sha512-Bb2GHk8jmlLIuxc3U+7UBGOoA5lByJTAFnRdH2N2fqEVy9TEQzJ9saIJUQ/ZqBvEvgEFe7UjPFNSFi8cyeU+3Q==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"iron-webcrypto@0.10.1": {
|
||||
"integrity": "sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA==",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"redirects": {
|
||||
"https://deno.land/x/deno_dom/deno-dom-wasm.ts": "https://deno.land/x/deno_dom@v0.1.45/deno-dom-wasm.ts",
|
||||
"https://deno.land/x/hono/middleware.ts": "https://deno.land/x/hono@v4.3.10/middleware.ts",
|
||||
"https://deno.land/x/hono_sessions/mod.ts": "https://deno.land/x/hono_sessions@v0.5.8/mod.ts",
|
||||
"https://esm.sh/v135/@types/css@latest/index.d.ts": "https://esm.sh/v135/@types/css@0.0.37/index.d.ts"
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8",
|
||||
"https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c",
|
||||
"https://deno.land/std@0.224.0/path/_common/dirname.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
|
||||
"https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a",
|
||||
"https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15",
|
||||
"https://deno.land/std@0.224.0/path/dirname.ts": "85bd955bf31d62c9aafdd7ff561c4b5fb587d11a9a5a45e2b01aedffa4238a7c",
|
||||
"https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d",
|
||||
"https://deno.land/std@0.224.0/path/posix/dirname.ts": "76cd348ffe92345711409f88d4d8561d8645353ac215c8e9c80140069bf42f00",
|
||||
"https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808",
|
||||
"https://deno.land/std@0.224.0/path/windows/dirname.ts": "33e421be5a5558a1346a48e74c330b8e560be7424ed7684ea03c12c21b627bc9",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/build/deno-wasm/deno-wasm.js": "d6841a06342eb6a2798ef28de79ad69c0f2fa349fa04d3ca45e5fcfbf50a9340",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/deno-dom-wasm.ts": "a33d160421bbb6e3104285ea5ebf33352b7ad50d82ea8765e3cf65f972b25119",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/api.ts": "0ff5790f0a3eeecb4e00b7d8fbfa319b165962cf6d0182a65ba90f158d74f7d7",
|
||||
|
@ -125,6 +146,27 @@
|
|||
"https://deno.land/x/hono@v4.3.10/utils/url.ts": "855169632c61d03703bd08cafb27664ba3fdb352892f01687d5cce8fd49e3cb1",
|
||||
"https://deno.land/x/hono@v4.3.10/validator/index.ts": "6c986e8b91dcf857ecc8164a506ae8eea8665792a4ff7215471df669c632ae7c",
|
||||
"https://deno.land/x/hono@v4.3.10/validator/validator.ts": "53f3d2ad442e22f0bc2d85b7d8d90320d4e5ecf5fdd58882f906055d33a18e13",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/deps.ts": "a86ee9f6d96c0dcc80380eaa3d1cef13ff972a56003d8e1d7f461cc32554fa34",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/mod.ts": "67e89aebb3c0e87e7e6065aefb56606d2f1017dd8ed030ef742f5bb73398abda",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/Crypto.ts": "dcbf1dc60d5c67426f3a25bcd56a38012336c2418ab1291550f2fa1f76b66e25",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/Middleware.ts": "05879181e4f649098c05800a47c12c21649dde41f8d21aceefc7b2dbb91b261b",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/Session.ts": "9de1c3661a9b713a4eded0457a60432a96118be59741cb32e43c39a437da33cd",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/store/CookieStore.ts": "9175f9da3e555c0e07928db03bb26ad40b6b0c1f661bfccd9aeddad0a615ccc2",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/store/MemoryStore.ts": "f702d81a948a775207f047b60e2dd6c903a4b25b041c827309486055be3103fd",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/store/Store.ts": "8f26b96fa22c330846ccb318cb90d3d1135aec9078c0faa7b5dc39ceb49a0da4",
|
||||
"https://deno.land/x/zod@v3.22.4/ZodError.ts": "4de18ff525e75a0315f2c12066b77b5c2ae18c7c15ef7df7e165d63536fdf2ea",
|
||||
"https://deno.land/x/zod@v3.22.4/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef",
|
||||
"https://deno.land/x/zod@v3.22.4/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/parseUtil.ts": "f791e6e65a0340d85ad37d26cd7a3ba67126cd9957eac2b7163162155283abb1",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/util.ts": "8baf19b19b2fca8424380367b90364b32503b6b71780269a6e3e67700bb02774",
|
||||
"https://deno.land/x/zod@v3.22.4/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268",
|
||||
"https://deno.land/x/zod@v3.22.4/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c",
|
||||
"https://deno.land/x/zod@v3.22.4/mod.ts": "64e55237cb4410e17d968cd08975566059f27638ebb0b86048031b987ba251c4",
|
||||
"https://deno.land/x/zod@v3.22.4/types.ts": "724185522fafe43ee56a52333958764c8c8cd6ad4effa27b42651df873fc151e",
|
||||
"https://esm.sh/jsdom@22.1.0": "2efb54a90536dc0f4bb00f442c32fcedb2224af5aad5c87db87660f15c013170",
|
||||
"https://esm.sh/v128/@tootallnate/once@2.0.0/denonext/once.mjs": "2c69d53dd1de1d7e5f9a78d46041f5d869f7d058f22d72e7f25821e61dddd147",
|
||||
"https://esm.sh/v128/abab@2.0.6/denonext/abab.mjs": "7101c07a728882d686222e5f5c5a6fa956a558e4f406c521f1c0b61bc60cd07d",
|
||||
|
@ -171,6 +213,11 @@
|
|||
"https://esm.sh/v128/xml-name-validator@4.0.0/denonext/xml-name-validator.mjs": "69af66c891312f304a8be720961ad5cce5c49c85a3bba03275b56a70dec7a21e",
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xml/1.0/ed5.js": "60f8f018eb1d79d69a41324155b7d9f52f1058b37060b28acc1dfc49446e549d",
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xml/1.1/ed2.js": "ba7d1fe5694f62469c4b293a1fadad332c637cbcfbc74147a296475c2ff8ad3d",
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xmlns/1.0/ed3.js": "929d15ffc72d56c8909f87e7df8288f060bda0256622e8e95c24f0decb06adc7"
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xmlns/1.0/ed3.js": "929d15ffc72d56c8909f87e7df8288f060bda0256622e8e95c24f0decb06adc7",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/mod.ts": "bc9436bcf45f3204ebcd0b2559f53e5d38162195fc48ac6d435cf8ca38c77ae3",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/entry.ts": "243a53b27e494c01e944331e2b71dfbe96ff906921aca8870603eb19bbce8235",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/lib.ts": "76973ce240e2bcadaf13e43115d050dee70b92dc5cd7cd726cdd5d9adf4c1ad6",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/store.ts": "ff6cdb0c045818d8e4ab6eb2bb304db8ac387ef05514af09e6c731bb65815a10",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/typing.ts": "cb0d315461aab883ddd2396f5a5ce2a88615257b402d5a5cd06c10dc44ffa453"
|
||||
}
|
||||
}
|
||||
|
|
24
lib/auth.ts
Normal file
24
lib/auth.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { db, User } from "./storage.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
|
||||
export async function login(login: string, password: string) {
|
||||
for await (const user of db.all("user")) {
|
||||
if (await user.get("username") !== login) continue;
|
||||
if (await user.get("password") === password) return user;
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function get_user(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const id = context.get("session").get("user");
|
||||
if (typeof id !== "string") return null;
|
||||
return await db.get("user", id);
|
||||
}
|
||||
|
||||
export function set_user(context: Context<FeurEnv, string, BlankInput>, user: User | null) {
|
||||
if (user === null) context.get("session").set("user", "");
|
||||
else context.get("session").set("user", user.id);
|
||||
}
|
|
@ -1,45 +1,36 @@
|
|||
import { z } from "https://deno.land/x/zod@v3.23.8/mod.ts";
|
||||
import {
|
||||
EntryFor,
|
||||
Schema,
|
||||
Store,
|
||||
} from "https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/mod.ts";
|
||||
import { project_root } from "./utils.ts";
|
||||
|
||||
class Store<D, Schema> {
|
||||
kv;
|
||||
|
||||
private constructor(kv: Deno.Kv) {
|
||||
this.kv = kv;
|
||||
}
|
||||
}
|
||||
|
||||
class Schema<T extends TablesDescriptor<T>> {
|
||||
descriptor;
|
||||
|
||||
constructor(descriptor: T) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
type SchemaDescriptor<T extends TablesDescriptor<T>> = {
|
||||
tables: T;
|
||||
};
|
||||
|
||||
type TablesDescriptor<Self extends TablesDescriptor<Self>> = {
|
||||
[name: string]: TableDescr<Self, typeof name, { [key: string]: z.ZodType }>;
|
||||
};
|
||||
|
||||
type TableDescr<Tables extends TablesDescriptor<Tables>, Name extends keyof Tables, S extends z.ZodRawShape> = {
|
||||
structure: z.ZodObject<S>;
|
||||
relations: Relations<Tables, Name, S>;
|
||||
};
|
||||
|
||||
type Relations<Tables extends TablesDescriptor<Tables>, Name extends keyof Tables, S extends z.ZodRawShape> = {
|
||||
[name in Exclude<keyof Tables, Name>]?: [keyof S, keyof z.infer<Tables[name]["structure"]>];
|
||||
};
|
||||
|
||||
const store = new Schema({
|
||||
"user": {
|
||||
structure: z.object({ feur_id: z.string() }),
|
||||
relations: { "feur": ["_feur_id", "id"] },
|
||||
export const db = await Store.open(
|
||||
new Schema({
|
||||
user: {
|
||||
username: "string",
|
||||
password: "string",
|
||||
upvoted_posts: ["many", "post"],
|
||||
upvoted_comments: ["many", "comment"],
|
||||
posts: ["many", "post"],
|
||||
},
|
||||
"feur": {
|
||||
structure: z.object({ id: z.string(), content: z.string() }),
|
||||
relations: {},
|
||||
post: {
|
||||
title: "string",
|
||||
content: "string",
|
||||
upvotes: "number",
|
||||
author: ["one", "user"],
|
||||
comments: ["many", "comment"],
|
||||
},
|
||||
});
|
||||
comment: {
|
||||
content: "string",
|
||||
upvotes: "number",
|
||||
author: ["one", "user"],
|
||||
post: ["one", "post"],
|
||||
},
|
||||
}),
|
||||
`${project_root()}/local/db.kv`,
|
||||
);
|
||||
|
||||
export type User = EntryFor<typeof db, "user">;
|
||||
export type Post = EntryFor<typeof db, "post">;
|
||||
export type Comment = EntryFor<typeof db, "comment">;
|
||||
|
|
11
lib/utils.ts
11
lib/utils.ts
|
@ -1,9 +1,14 @@
|
|||
import { dirname } from "https://deno.land/std@0.224.0/path/dirname.ts";
|
||||
|
||||
import { CSSProperties } from "https://deno.land/std@0.40.0/types/react.d.ts";
|
||||
|
||||
export function _css(prop: CSSProperties) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
// type wizardry
|
||||
|
||||
export type KeysOfType<T, V> = keyof { [P in keyof T as T[P] extends V ? P : never]: P };
|
||||
export function project_root() {
|
||||
const this_url = new URL(import.meta.url);
|
||||
const this_abs_path = Deno.realPathSync(this_url.pathname);
|
||||
const lib_path = dirname(this_abs_path);
|
||||
return dirname(lib_path);
|
||||
}
|
||||
|
|
2
local/.gitignore
vendored
Normal file
2
local/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!/.gitignore
|
21
main.ts
21
main.ts
|
@ -1,17 +1,22 @@
|
|||
#!/bin/env -S deno run --allow-net --unstable-kv --watch --allow-read=./pages
|
||||
#!/bin/env -S deno run --allow-net --unstable-kv --watch --allow-read=./pages,./local,./lib,. --allow-write=./local
|
||||
|
||||
import { Hono } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { basicAuth, serveStatic } from "https://deno.land/x/hono@v4.3.10/middleware.ts";
|
||||
import { serveStatic } from "https://deno.land/x/hono@v4.3.10/middleware.ts";
|
||||
import { CookieStore, Session, sessionMiddleware } from "https://deno.land/x/hono_sessions@v0.5.8/mod.ts";
|
||||
|
||||
const app = new Hono();
|
||||
export type FeurEnv = { Variables: { session: Session } };
|
||||
const app = new Hono<FeurEnv>();
|
||||
|
||||
app.use("/static/*", serveStatic({ root: "./pages/" }));
|
||||
app.use("/user", basicAuth({ username: "feur", password: "feur" })); // todo : transition to verify_user
|
||||
|
||||
const store = new CookieStore();
|
||||
const encryptionKey = "FeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeur";
|
||||
app.use("*", sessionMiddleware({ store, encryptionKey }));
|
||||
|
||||
app.get("/", (c) => c.redirect("/home"));
|
||||
|
||||
import HomePage from "./pages/home.tsx";
|
||||
app.get("/home", (c) => c.html(HomePage()));
|
||||
app.get("/home", (c) => c.html(HomePage(c)));
|
||||
|
||||
import LoginPage from "./pages/login.tsx";
|
||||
app.get("/login", (c) => c.html(LoginPage()));
|
||||
|
@ -19,4 +24,10 @@ app.get("/login", (c) => c.html(LoginPage()));
|
|||
import { login_route } from "./api/login.ts";
|
||||
app.post("/api/login", (c) => login_route(c));
|
||||
|
||||
import { logout_route } from "./api/logout.ts";
|
||||
app.get("/api/logout", (c) => logout_route(c));
|
||||
|
||||
import UserPage from "./pages/user.tsx";
|
||||
app.get("/user", async (c) => await UserPage(c));
|
||||
|
||||
Deno.serve(app.fetch);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { PropsWithChildren, jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { _css } from "../../lib/utils.ts";
|
||||
import { User } from "../../lib/storage.ts";
|
||||
|
||||
export default function Heading() {
|
||||
//
|
||||
export default function Heading({ username }: PropsWithChildren<{username: string | null}>) {
|
||||
return (
|
||||
<header style={_css({
|
||||
width: "100vw",
|
||||
|
@ -32,6 +34,7 @@ export default function Heading() {
|
|||
<MenuItem name="Content" location="/home"/>
|
||||
<MenuItem name="About" location="/about"/>
|
||||
<MenuItem name="User" location="/user"/>
|
||||
{(username !== null) && <MenuItem name={`Logout (${username})`} location="/api/logout" />}
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ export default function Login() {
|
|||
<form action="/api/login" method="post">
|
||||
<input type="text" name="login"/>
|
||||
<input type="password" name="password"/>
|
||||
<input type="submit" value="login" />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,16 @@ import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
|||
import { BasePage } from "./components/base.tsx"
|
||||
import Main from "./components/main.tsx";
|
||||
import Heading from "./components/heading.tsx";
|
||||
import { get_user } from "../lib/auth.ts";
|
||||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
|
||||
export default function HomePage() {
|
||||
export default async function HomePage(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const user = await get_user(context);
|
||||
return (
|
||||
<BasePage name="Home">
|
||||
<Heading></Heading>
|
||||
<Heading username={await user?.get("username") ?? null}></Heading>
|
||||
<Main>Main</Main>
|
||||
</BasePage>
|
||||
)
|
||||
|
|
24
pages/user.tsx
Normal file
24
pages/user.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { BasePage } from "./components/base.tsx";
|
||||
import Heading from "./components/heading.tsx";
|
||||
import Main from "./components/main.tsx";
|
||||
import Login from "./components/login.tsx";
|
||||
import { User } from "../lib/storage.ts";
|
||||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
import { get_user } from "../lib/auth.ts";
|
||||
|
||||
export default async function UserPage(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const user = await get_user(context);
|
||||
if (user === null) return context.text("Must be logged.", 401);
|
||||
return context.html(
|
||||
<BasePage name="Login">
|
||||
<Main>
|
||||
<h1>Logged as {await user.get("username")}</h1>
|
||||
</Main>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue