finished with auth (besides oauth)

This commit is contained in:
Chad Freeman 2024-08-17 16:20:57 -04:00
parent cd7f487b53
commit 0845eb1bbb
10 changed files with 134 additions and 21 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -1,21 +1,13 @@
{ {
"name": "talkomatic", "name": "talkomatic",
"version": "0.0.1", "version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check ."
},
"devDependencies": { "devDependencies": {
"@deno/kv": "^0.8.1", "@deno/kv": "^0.8.1",
"@hono/zod-validator": "^0.2.2",
"@olli/kvdex": "npm:@jsr/olli__kvdex", "@olli/kvdex": "npm:@jsr/olli__kvdex",
"@oxi/option": "npm:@jsr/oxi__option", "@oxi/option": "npm:@jsr/oxi__option",
"@oxi/result": "npm:@jsr/oxi__result", "@oxi/result": "npm:@jsr/oxi__result",
"@petamoriken/float16": "^3.8.7",
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@ts-rex/argon2": "npm:@jsr/ts-rex__argon2", "@ts-rex/argon2": "npm:@jsr/ts-rex__argon2",
@ -35,11 +27,20 @@
"tailwindcss": "^3.4.10", "tailwindcss": "^3.4.10",
"typescript": "^5.0.0", "typescript": "^5.0.0",
"vite": "^5.0.3", "vite": "^5.0.3",
"zod": "^3.23.8", "zod": "^3.23.8"
"@petamoriken/float16": "^3.8.7" },
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check ."
}, },
"type": "module",
"trustedDependencies": [ "trustedDependencies": [
"svelte-preprocess" "svelte-preprocess"
] ],
"type": "module"
} }

View file

@ -55,6 +55,6 @@ export const cookieController = new CookieController('auth_session', {
httpOnly: true, httpOnly: true,
secure: true, secure: true,
sameSite: "lax", sameSite: "lax",
path: ".", path: "/",
}, { expiresIn: cookieExpiration }) }, { expiresIn: cookieExpiration })
export { createSessionForUser, deleteSession, getUserAndSession } export { createSessionForUser, deleteSession, getUserAndSession }

View file

@ -19,6 +19,12 @@ export const session = z.object({
userId: z.string(), userId: z.string(),
}) })
export const chat = z.object({
name: z.string(),
creator: z.string().describe('id'),
createdAt: z.date()
})
export const kv = await openKv() export const kv = await openKv()
export const db = kvdex(kv, { export const db = kvdex(kv, {
user: collection(user, { user: collection(user, {
@ -35,9 +41,10 @@ export const db = kvdex(kv, {
userId: 'secondary' userId: 'secondary'
} }
}), }),
pfp: collection(model<Uint8Array>()),
chat: { chat: {
boxes: collection(model<{ userID: string, text: string }>()), boxes: collection(model<{ roomID: string, userID: string, text: string }>()),
users: collection(publicUser) users: collection(publicUser),
updatekey: collection(model<true>()),
data: collection(chat)
} }
}) })

View file

@ -1,10 +1,32 @@
import { Hono } from "hono" import { Hono } from "hono"
import { zValidator } from "@hono/zod-validator"
import z from "zod"
import { HTTPException } from 'hono/http-exception'
import { db } from "./db"
import { alphabet, generateRandomString } from "oslo/crypto"
import { text } from "@sveltejs/kit"
type Bindings = { type Bindings = {
locals: App.Locals locals: App.Locals
} }
const api = new Hono<{ Bindings: Bindings }>() const api = new Hono<{ Bindings: Bindings }>()
.use(async (ctx, next) => {
if(!ctx.env.locals.session) throw new HTTPException(401)
await next()
})
.post('/rooms/create', zValidator('json', z.object({
name: z.string()
})), async ({ req, env: { locals: { user } } }) => {
const body = req.valid('json')
const roomId = generateRandomString(10, alphabet('0-9', 'a-z'))
await db.chat.data.set(roomId, {
createdAt: new Date(),
creator: user?.id!,
name: body.name
})
return text(roomId)
})
export type api = typeof api export type api = typeof api
export const hono = new Hono<{ Bindings: Bindings }>().route('/api', api) export const hono = new Hono<{ Bindings: Bindings }>().route('/api', api)

View file

@ -1,7 +1,12 @@
import { publicUser } from '$lib/db.js';
import { redirect } from '@sveltejs/kit'; import { redirect } from '@sveltejs/kit';
export async function load({ locals }) { export async function load({ locals }) {
if(!locals.session) { if(!locals.session) {
return redirect(302, "/auth") return redirect(302, "/auth")
} }
return publicUser.safeParse(locals.user).data!
} }
export const csr = true;
export const ssr = false;

View file

@ -0,0 +1,71 @@
<script>
const { data, children } = $props()
let dropdownOpen = $state(false)
$inspect(dropdownOpen)
</script>
<div class="h-[100vh] w-[100vw] flex flex-col">
<div class="px-4">
<div class="navbar bg-base-200 rounded-b-xl">
<div class="flex-1">
<button class="btn btn-ghost text-xl">spiel.place</button>
</div>
<div class="flex-none">
<details
class="dropdown dropdown-end"
ontoggle={({ newState }) => (dropdownOpen = newState === 'open')}>
<summary class="btn btn-circle btn-ghost m-1 swap swap-rotate">
<input type="checkbox" bind:checked={dropdownOpen} />
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="size-5 swap-off">
<path
fill-rule="evenodd"
d="M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Zm0 5.25a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1-.75-.75Z"
clip-rule="evenodd"></path>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-5 swap-on stroke-2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"></path>
</svg>
</summary>
<ul class="menu dropdown-content bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
<li><a href="/app/settings">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
{data.displayName}
</a></li>
<li>
<a href="/auth/signout">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-6">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"
></path>
</svg>
sign out</a>
</li>
</ul>
</details>
</div>
</div>
</div>
<div class="flex-grow">
{@render children()}
</div>
</div>

View file

@ -1,3 +1,7 @@
<script> <script>
const { data } = $props()
</script> </script>
<div class="">
</div>

View file

@ -0,0 +1,3 @@
<script>
const { data } = $props()
</script>