summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--migrations/0003_empty_matthew_murdock.sql7
-rw-r--r--migrations/meta/0003_snapshot.json225
-rw-r--r--migrations/meta/_journal.json7
-rw-r--r--src/db/schema.ts25
-rw-r--r--src/index.tsx24
5 files changed, 273 insertions, 15 deletions
diff --git a/migrations/0003_empty_matthew_murdock.sql b/migrations/0003_empty_matthew_murdock.sql
new file mode 100644
index 0000000..b626d41
--- /dev/null
+++ b/migrations/0003_empty_matthew_murdock.sql
@@ -0,0 +1,7 @@
+CREATE TABLE `users_groups` (
+ `user_id` integer,
+ `group_id` integer,
+ PRIMARY KEY(`user_id`, `group_id`),
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action,
+ FOREIGN KEY (`group_id`) REFERENCES `groups`(`id`) ON UPDATE no action ON DELETE no action
+);
diff --git a/migrations/meta/0003_snapshot.json b/migrations/meta/0003_snapshot.json
new file mode 100644
index 0000000..ab99d31
--- /dev/null
+++ b/migrations/meta/0003_snapshot.json
@@ -0,0 +1,225 @@
+{
+ "version": "6",
+ "dialect": "sqlite",
+ "id": "f580093e-f5b1-402a-8da5-ae2d5bd2611e",
+ "prevId": "29e91293-4ebe-4039-a781-8609bf9505d5",
+ "tables": {
+ "users_groups": {
+ "name": "users_groups",
+ "columns": {
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "users_groups_user_id_users_id_fk": {
+ "name": "users_groups_user_id_users_id_fk",
+ "tableFrom": "users_groups",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "users_groups_group_id_groups_id_fk": {
+ "name": "users_groups_group_id_groups_id_fk",
+ "tableFrom": "users_groups",
+ "tableTo": "groups",
+ "columnsFrom": [
+ "group_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "users_groups_user_id_group_id_pk": {
+ "columns": [
+ "user_id",
+ "group_id"
+ ],
+ "name": "users_groups_user_id_group_id_pk"
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "groups": {
+ "name": "groups",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "sessions": {
+ "name": "sessions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "last_use": {
+ "name": "last_use",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(unixepoch())"
+ }
+ },
+ "indexes": {
+ "sessions_uuid_unique": {
+ "name": "sessions_uuid_unique",
+ "columns": [
+ "uuid"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "users": {
+ "name": "users",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "passkey": {
+ "name": "passkey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "passkey_id": {
+ "name": "passkey_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "users_name_unique": {
+ "name": "users_name_unique",
+ "columns": [
+ "name"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "webauthn_challenges": {
+ "name": "webauthn_challenges",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "challenge": {
+ "name": "challenge",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "key": {
+ "name": "key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ }
+ },
+ "views": {},
+ "enums": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "indexes": {}
+ }
+} \ No newline at end of file
diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json
index a434ab9..d3e9407 100644
--- a/migrations/meta/_journal.json
+++ b/migrations/meta/_journal.json
@@ -22,6 +22,13 @@
"when": 1755543983317,
"tag": "0002_red_morlun",
"breakpoints": true
+ },
+ {
+ "idx": 3,
+ "version": "6",
+ "when": 1755548102668,
+ "tag": "0003_empty_matthew_murdock",
+ "breakpoints": true
}
]
} \ No newline at end of file
diff --git a/src/db/schema.ts b/src/db/schema.ts
index 339dfc0..affe19f 100644
--- a/src/db/schema.ts
+++ b/src/db/schema.ts
@@ -1,11 +1,15 @@
import { relations, sql } from "drizzle-orm";
-import { text, sqliteTable, integer } from "drizzle-orm/sqlite-core";
+import { text, sqliteTable, integer, primaryKey } from "drizzle-orm/sqlite-core";
export const groupTable = sqliteTable("groups", {
id: integer().primaryKey(),
name: text().notNull(),
});
+export const groupRelations = relations(groupTable, ({ many }) => ({
+ members: many(groupMembershipTable),
+}));
+
export const userTable = sqliteTable("users", {
id: integer().primaryKey(),
name: text().unique().notNull(),
@@ -13,6 +17,20 @@ export const userTable = sqliteTable("users", {
passkeyId: text("passkey_id").notNull(),
});
+export const userRelations = relations(userTable, ({ many }) => ({
+ groups: many(groupMembershipTable),
+}));
+
+export const groupMembershipTable = sqliteTable("users_groups", {
+ userId: integer("user_id").notNull().references(() => userTable.id),
+ groupId: integer("group_id").notNull().references(() => groupTable.id),
+}, table => [primaryKey({ columns: [table.userId, table.groupId] })]);
+
+export const groupMembershipRelations = relations(groupMembershipTable, ({ one }) => ({
+ group: one(groupTable, { fields: [groupMembershipTable.groupId], references: [groupTable.id] }),
+ user: one(userTable, { fields: [groupMembershipTable.userId], references: [userTable.id] }),
+}));
+
export const sessionTable = sqliteTable("sessions", {
id: integer().primaryKey(),
uuid: text().unique().notNull(),
@@ -21,10 +39,7 @@ export const sessionTable = sqliteTable("sessions", {
});
export const sessionRelations = relations(sessionTable, ({ one }) => ({
- user: one(userTable, {
- fields: [sessionTable.userId],
- references: [userTable.id],
- }),
+ user: one(userTable, { fields: [sessionTable.userId], references: [userTable.id] }),
}));
export const webauthnChallenges = sqliteTable("webauthn_challenges", {
diff --git a/src/index.tsx b/src/index.tsx
index 5975284..ea79902 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,22 +2,26 @@ import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { createClient } from "@libsql/client";
import { drizzle } from "drizzle-orm/libsql";
-import { groupTable } from "./db/schema.js";
+import * as schema from "./db/schema.js";
import authRouter, { getSession, LoginForm } from "./auth.js";
+import { eq } from "drizzle-orm";
export const RP_ID = "localhost"; // "uneven.0m.nu";
export const ORIGIN = `http://${RP_ID}`;
let app = new Hono();
-export let db = drizzle(createClient({ url: "file:data.db" }));
+export let db = drizzle(createClient({ url: "file:data.db" }), { schema });
-async function Groups() {
- let result = await db.select().from(groupTable).all();
+app.get("/groups", async c => {
+ let session = await getSession(c);
+ if (!session) return c.html("Must be logged in");
+ let user = await db.query.userTable.findFirst({ where: user => eq(user.id, session.user.id), with: { groups: { with: { group: true } } } });
+ if (!user) return c.html("Huh?");
- return <ul>{
- result.map(group => <li>{group.name}</li>)
- }</ul>;
-}
+ return c.html(<ul>{
+ user.groups.map(group => <li>{group.group.name}</li>)
+ }</ul>);
+});
app.get("/", c => c.html(
<html lang="en">
@@ -31,8 +35,8 @@ app.get("/", c => c.html(
</head>
<body>
<LoginForm />
- <Groups />
<button hx-get="/button" hx-swap="outerHTML">click me!</button>
+ <div hx-on-load="/groups" hx-swap="outerHTML" />
</body>
</html>
));
@@ -45,7 +49,7 @@ app.get("/button", async c => {
hx-get="/button"
hx-swap="outerHTML"
style={{ backgroundColor: colors[Math.floor(Math.random() * colors.length)] }}
- >disco button! {session.user.name}</button>
+ >disco button! {session?.user.name}</button>
);
});