46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import { index, pgTable, text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
|
|
import { users } from './identity';
|
|
|
|
/**
|
|
* A Notion grant belongs to the person who completed OAuth. Credentials are a
|
|
* single authenticated-encryption envelope so no token-shaped value is ever
|
|
* queryable, searchable, or accidentally selected as ordinary metadata.
|
|
*/
|
|
export const notionConnections = pgTable(
|
|
'notion_connections',
|
|
{
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
|
workspaceId: text('workspace_id').notNull(),
|
|
workspaceName: text('workspace_name'),
|
|
workspaceIcon: text('workspace_icon'),
|
|
botId: text('bot_id'),
|
|
credentialsEncrypted: text('credentials_encrypted').notNull(),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
},
|
|
(table) => [
|
|
uniqueIndex('notion_connections_user_workspace_key').on(table.userId, table.workspaceId),
|
|
index('notion_connections_user_idx').on(table.userId),
|
|
],
|
|
);
|
|
|
|
/**
|
|
* OAuth attempts survive multiple API processes but not replay. Only hashes
|
|
* are durable; the browser verifier is an HttpOnly, short-lived cookie.
|
|
*/
|
|
export const notionOauthStates = pgTable(
|
|
'notion_oauth_states',
|
|
{
|
|
stateHash: text('state_hash').primaryKey(),
|
|
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
|
verifierHash: text('verifier_hash').notNull(),
|
|
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
},
|
|
(table) => [index('notion_oauth_states_expiry_idx').on(table.expiresAt)],
|
|
);
|
|
|
|
export type NotionConnection = typeof notionConnections.$inferSelect;
|
|
export type NotionOauthState = typeof notionOauthStates.$inferSelect;
|