Skip to content
File

Blob: src/worker/db/d1/schema/personalAccessTokens.ts

typescript31 lines
1import { desc } from "drizzle-orm";
2import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
3 
4import { users } from "./users";
5 
6// Personal Access Token. The plaintext token has the shape
7// `goc_<8 hex prefix>_<32 base32 secret>`. We index on the public prefix to
8// look up by the leading bytes presented over Basic auth, then verify the
9// SHA-256 hex of the full plaintext against `hash`. Plaintext is shown to
10// the user once at creation and never stored.
11export const personalAccessTokens = sqliteTable(
12 "personal_access_tokens",
13 {
14 id: text("id").primaryKey(),
15 userId: text("user_id")
16 .notNull()
17 .references(() => users.id, { onDelete: "cascade" }),
18 name: text("name").notNull(),
19 prefix: text("prefix").notNull().unique(),
20 hash: text("hash").notNull(),
21 createdAt: integer("created_at").notNull(),
22 expiresAt: integer("expires_at"),
23 revokedAt: integer("revoked_at"),
24 lastUsedAt: integer("last_used_at"),
25 },
26 (table) => [index("idx_pats_user_created").on(table.userId, desc(table.createdAt))]
27);
28 
29export type PersonalAccessTokenRow = typeof personalAccessTokens.$inferSelect;
30export type NewPersonalAccessTokenRow = typeof personalAccessTokens.$inferInsert;