diff options
| author | Frank <[email protected]> | 2025-10-16 22:27:28 -0400 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-10-16 22:28:34 -0400 |
| commit | 1947580b08b04fc8d81841fa6017f721dec6a3da (patch) | |
| tree | 5c157189a344ca22d49dac396261182d45251f65 /packages/console | |
| parent | ca9b13e8a2626aca3bb28882cff395c18e0a215c (diff) | |
| download | opencode-1947580b08b04fc8d81841fa6017f721dec6a3da.tar.gz opencode-1947580b08b04fc8d81841fa6017f721dec6a3da.zip | |
wip: zen
Diffstat (limited to 'packages/console')
| -rw-r--r-- | packages/console/app/src/routes/workspace.tsx | 2 | ||||
| -rw-r--r-- | packages/console/app/src/routes/workspace/[id]/members/member-section.tsx | 2 | ||||
| -rw-r--r-- | packages/console/core/migrations/0035_narrow_blindfold.sql | 3 | ||||
| -rw-r--r-- | packages/console/core/migrations/meta/0035_snapshot.json | 955 | ||||
| -rw-r--r-- | packages/console/core/migrations/meta/_journal.json | 7 | ||||
| -rw-r--r-- | packages/console/core/src/account.ts | 13 | ||||
| -rw-r--r-- | packages/console/core/src/billing.ts | 2 | ||||
| -rw-r--r-- | packages/console/core/src/key.ts | 7 | ||||
| -rw-r--r-- | packages/console/core/src/schema/account.sql.ts | 13 | ||||
| -rw-r--r-- | packages/console/core/src/schema/auth.sql.ts | 4 | ||||
| -rw-r--r-- | packages/console/core/src/user.ts | 37 | ||||
| -rw-r--r-- | packages/console/function/src/auth.ts | 25 |
12 files changed, 1014 insertions, 56 deletions
diff --git a/packages/console/app/src/routes/workspace.tsx b/packages/console/app/src/routes/workspace.tsx index c979336e2..74c3edb83 100644 --- a/packages/console/app/src/routes/workspace.tsx +++ b/packages/console/app/src/routes/workspace.tsx @@ -12,7 +12,7 @@ const getUserEmail = query(async (workspaceID: string) => { "use server" return withActor(async () => { const actor = Actor.assert("user") - const email = await User.getAccountEmail(actor.properties.userID) + const email = await User.getAuthEmail(actor.properties.userID) return email }, workspaceID) }, "userEmail") diff --git a/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx b/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx index 1dca8d0d1..60d2daa6d 100644 --- a/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx @@ -139,7 +139,7 @@ function MemberRow(props: { member: any; workspaceID: string; actorID: string; a return ( <tr> - <td data-slot="member-email">{props.member.accountEmail ?? props.member.email}</td> + <td data-slot="member-email">{props.member.authEmail ?? props.member.email}</td> <td data-slot="member-role"> <Show when={store.editing && !isCurrentUser()} fallback={<span>{props.member.role}</span>}> <RoleDropdown diff --git a/packages/console/core/migrations/0035_narrow_blindfold.sql b/packages/console/core/migrations/0035_narrow_blindfold.sql new file mode 100644 index 000000000..c62f01f4e --- /dev/null +++ b/packages/console/core/migrations/0035_narrow_blindfold.sql @@ -0,0 +1,3 @@ +ALTER TABLE `account` DROP INDEX `email`;--> statement-breakpoint +CREATE INDEX `account_id` ON `auth` (`account_id`);--> statement-breakpoint +ALTER TABLE `account` DROP COLUMN `email`;
\ No newline at end of file diff --git a/packages/console/core/migrations/meta/0035_snapshot.json b/packages/console/core/migrations/meta/0035_snapshot.json new file mode 100644 index 000000000..7478337b5 --- /dev/null +++ b/packages/console/core/migrations/meta/0035_snapshot.json @@ -0,0 +1,955 @@ +{ + "version": "5", + "dialect": "mysql", + "id": "10169105-4545-4894-838b-004c0a42c584", + "prevId": "34706440-26d7-43f5-9b39-815aa912e5ef", + "tables": { + "account": { + "name": "account", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "auth": { + "name": "auth", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "enum('email','github','google')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject": { + "name": "subject", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "provider": { + "name": "provider", + "columns": [ + "provider", + "subject" + ], + "isUnique": true + }, + "account_id": { + "name": "account_id", + "columns": [ + "account_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "billing": { + "name": "billing", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "customer_id": { + "name": "customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_method_id": { + "name": "payment_method_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_method_type": { + "name": "payment_method_type", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_method_last4": { + "name": "payment_method_last4", + "type": "varchar(4)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "balance": { + "name": "balance", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "monthly_limit": { + "name": "monthly_limit", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "monthly_usage": { + "name": "monthly_usage", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_monthly_usage_updated": { + "name": "time_monthly_usage_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reload": { + "name": "reload", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reload_error": { + "name": "reload_error", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_reload_error": { + "name": "time_reload_error", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_reload_locked_till": { + "name": "time_reload_locked_till", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "global_customer_id": { + "name": "global_customer_id", + "columns": [ + "customer_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "billing_workspace_id_id_pk": { + "name": "billing_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "payment": { + "name": "payment", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "customer_id": { + "name": "customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "invoice_id": { + "name": "invoice_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_id": { + "name": "payment_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "amount": { + "name": "amount", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_refunded": { + "name": "time_refunded", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "payment_workspace_id_id_pk": { + "name": "payment_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "usage": { + "name": "usage", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model": { + "name": "model", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cache_read_tokens": { + "name": "cache_read_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cache_write_5m_tokens": { + "name": "cache_write_5m_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cache_write_1h_tokens": { + "name": "cache_write_1h_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cost": { + "name": "cost", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key_id": { + "name": "key_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "usage_workspace_id_id_pk": { + "name": "usage_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "key": { + "name": "key", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_used": { + "name": "time_used", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "global_key": { + "name": "global_key", + "columns": [ + "key" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "key_workspace_id_id_pk": { + "name": "key_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "model": { + "name": "model", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model": { + "name": "model", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "model_workspace_model": { + "name": "model_workspace_model", + "columns": [ + "workspace_id", + "model" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "model_workspace_id_id_pk": { + "name": "model_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "provider": { + "name": "provider", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "credentials": { + "name": "credentials", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "workspace_provider": { + "name": "workspace_provider", + "columns": [ + "workspace_id", + "provider" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "provider_workspace_id_id_pk": { + "name": "provider_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_seen": { + "name": "time_seen", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "enum('admin','member')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "monthly_limit": { + "name": "monthly_limit", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "monthly_usage": { + "name": "monthly_usage", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_monthly_usage_updated": { + "name": "time_monthly_usage_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "user_account_id": { + "name": "user_account_id", + "columns": [ + "workspace_id", + "account_id" + ], + "isUnique": true + }, + "user_email": { + "name": "user_email", + "columns": [ + "workspace_id", + "email" + ], + "isUnique": true + }, + "global_account_id": { + "name": "global_account_id", + "columns": [ + "account_id" + ], + "isUnique": false + }, + "global_email": { + "name": "global_email", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "user_workspace_id_id_pk": { + "name": "user_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "workspace": { + "name": "workspace", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "slug": { + "name": "slug", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "workspace_id": { + "name": "workspace_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + } + }, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "tables": {}, + "indexes": {} + } +}
\ No newline at end of file diff --git a/packages/console/core/migrations/meta/_journal.json b/packages/console/core/migrations/meta/_journal.json index ca9806054..7197b8038 100644 --- a/packages/console/core/migrations/meta/_journal.json +++ b/packages/console/core/migrations/meta/_journal.json @@ -246,6 +246,13 @@ "when": 1760651120251, "tag": "0034_short_bulldozer", "breakpoints": true + }, + { + "idx": 35, + "version": "5", + "when": 1760666253896, + "tag": "0035_narrow_blindfold", + "breakpoints": true } ] }
\ No newline at end of file diff --git a/packages/console/core/src/account.ts b/packages/console/core/src/account.ts index f246c8e1a..c7e096586 100644 --- a/packages/console/core/src/account.ts +++ b/packages/console/core/src/account.ts @@ -8,7 +8,6 @@ import { AccountTable } from "./schema/account.sql" export namespace Account { export const create = fn( z.object({ - email: z.string().email(), id: z.string().optional(), }), async (input) => @@ -16,7 +15,6 @@ export namespace Account { const id = input.id ?? Identifier.create("account") await tx.insert(AccountTable).values({ id, - email: input.email, }) return id }), @@ -32,15 +30,4 @@ export namespace Account { .then((rows) => rows[0]) }), ) - - export const fromEmail = fn(z.string().email(), async (email) => - Database.transaction(async (tx) => { - return tx - .select() - .from(AccountTable) - .where(eq(AccountTable.email, email)) - .execute() - .then((rows) => rows[0]) - }), - ) } diff --git a/packages/console/core/src/billing.ts b/packages/console/core/src/billing.ts index 297edebd0..ec7df7e36 100644 --- a/packages/console/core/src/billing.ts +++ b/packages/console/core/src/billing.ts @@ -173,7 +173,7 @@ export namespace Billing { const user = Actor.assert("user") const { successUrl, cancelUrl } = input - const email = await User.getAccountEmail(user.properties.userID) + const email = await User.getAuthEmail(user.properties.userID) const customer = await Billing.get() const session = await Billing.stripe().checkout.sessions.create({ mode: "payment", diff --git a/packages/console/core/src/key.ts b/packages/console/core/src/key.ts index e2d5c5eff..688f19b3d 100644 --- a/packages/console/core/src/key.ts +++ b/packages/console/core/src/key.ts @@ -4,9 +4,8 @@ import { Actor } from "./actor" import { and, Database, eq, isNull, sql } from "./drizzle" import { Identifier } from "./identifier" import { KeyTable } from "./schema/key.sql" -import { AccountTable } from "./schema/account.sql" import { UserTable } from "./schema/user.sql" -import { User } from "./user" +import { AuthTable } from "./schema/auth.sql" export namespace Key { export const list = fn(z.void(), async () => { @@ -18,11 +17,11 @@ export namespace Key { key: KeyTable.key, timeUsed: KeyTable.timeUsed, userID: KeyTable.userID, - email: AccountTable.email, + email: AuthTable.subject, }) .from(KeyTable) .innerJoin(UserTable, and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID))) - .innerJoin(AccountTable, eq(UserTable.accountID, AccountTable.id)) + .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) .where( and( ...[ diff --git a/packages/console/core/src/schema/account.sql.ts b/packages/console/core/src/schema/account.sql.ts index 4d9937114..7bbbe68f9 100644 --- a/packages/console/core/src/schema/account.sql.ts +++ b/packages/console/core/src/schema/account.sql.ts @@ -1,12 +1,7 @@ import { mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core" import { id, timestamps } from "../drizzle/types" -export const AccountTable = mysqlTable( - "account", - { - id: id(), - ...timestamps, - email: varchar("email", { length: 255 }).notNull(), - }, - (table) => [uniqueIndex("email").on(table.email)], -) +export const AccountTable = mysqlTable("account", { + id: id(), + ...timestamps, +}) diff --git a/packages/console/core/src/schema/auth.sql.ts b/packages/console/core/src/schema/auth.sql.ts index be2244ef3..1e12f98d4 100644 --- a/packages/console/core/src/schema/auth.sql.ts +++ b/packages/console/core/src/schema/auth.sql.ts @@ -1,4 +1,4 @@ -import { mysqlEnum, mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core" +import { index, mysqlEnum, mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core" import { id, timestamps, ulid } from "../drizzle/types" export const AuthProvider = ["email", "github", "google"] as const @@ -12,5 +12,5 @@ export const AuthTable = mysqlTable( subject: varchar("subject", { length: 255 }).notNull(), accountID: ulid("account_id").notNull(), }, - (table) => [uniqueIndex("provider").on(table.provider, table.subject)], + (table) => [uniqueIndex("provider").on(table.provider, table.subject), index("account_id").on(table.accountID)], ) diff --git a/packages/console/core/src/user.ts b/packages/console/core/src/user.ts index 89148a7cd..8b7a96f44 100644 --- a/packages/console/core/src/user.ts +++ b/packages/console/core/src/user.ts @@ -7,11 +7,10 @@ import { Actor } from "./actor" import { Identifier } from "./identifier" import { render } from "@jsx-email/render" import { AWS } from "./aws" -import { Account } from "./account" -import { AccountTable } from "./schema/account.sql" import { Key } from "./key" import { KeyTable } from "./schema/key.sql" import { WorkspaceTable } from "./schema/workspace.sql" +import { AuthTable } from "./schema/auth.sql" export namespace User { const assertNotSelf = (id: string) => { @@ -24,10 +23,10 @@ export namespace User { tx .select({ ...getTableColumns(UserTable), - accountEmail: AccountTable.email, + authEmail: AuthTable.subject, }) .from(UserTable) - .leftJoin(AccountTable, eq(UserTable.accountID, AccountTable.id)) + .leftJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) .where(and(eq(UserTable.workspaceID, Actor.workspace()), isNull(UserTable.timeDeleted))), ), ) @@ -42,14 +41,14 @@ export namespace User { ), ) - export const getAccountEmail = fn(z.string(), (id) => + export const getAuthEmail = fn(z.string(), (id) => Database.use((tx) => tx .select({ - email: AccountTable.email, + email: AuthTable.subject, }) .from(UserTable) - .leftJoin(AccountTable, eq(UserTable.accountID, AccountTable.id)) + .leftJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) .where(and(eq(UserTable.workspaceID, Actor.workspace()), eq(UserTable.id, id))) .then((rows) => rows[0]?.email), ), @@ -66,16 +65,24 @@ export namespace User { const workspaceID = Actor.workspace() // create user - const account = await Account.fromEmail(email) + const accountID = await Database.use((tx) => + tx + .select({ + accountID: AuthTable.accountID, + }) + .from(AuthTable) + .where(and(eq(AuthTable.provider, "email"), eq(AuthTable.subject, email))) + .then((rows) => rows[0]?.accountID), + ) await Database.use((tx) => tx .insert(UserTable) .values({ id: Identifier.create("user"), name: "", - ...(account + ...(accountID ? { - accountID: account.id, + accountID, } : { email, @@ -94,12 +101,12 @@ export namespace User { ) // create api key - if (account) { + if (accountID) { await Database.use(async (tx) => { const user = await tx .select() .from(UserTable) - .where(and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.accountID, account.id))) + .where(and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.accountID, accountID))) .then((rows) => rows[0]) const key = await tx @@ -119,11 +126,11 @@ export namespace User { const emailInfo = await Database.use((tx) => tx .select({ - email: AccountTable.email, + inviterEmail: AuthTable.subject, workspaceName: WorkspaceTable.name, }) .from(UserTable) - .innerJoin(AccountTable, eq(UserTable.accountID, AccountTable.id)) + .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, workspaceID)) .where( and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.id, Actor.assert("user").properties.userID)), @@ -138,7 +145,7 @@ export namespace User { body: render( // @ts-ignore InviteEmail({ - inviter: emailInfo.email, + inviter: emailInfo.inviterEmail, assetsUrl: `https://opencode.ai/email`, workspaceID: workspaceID, workspaceName: emailInfo.workspaceName, diff --git a/packages/console/function/src/auth.ts b/packages/console/function/src/auth.ts index 590608884..eb31015ed 100644 --- a/packages/console/function/src/auth.ts +++ b/packages/console/function/src/auth.ts @@ -12,7 +12,7 @@ import { Workspace } from "@opencode-ai/console-core/workspace.js" import { Actor } from "@opencode-ai/console-core/actor.js" import { Resource } from "@opencode-ai/console-resource" import { User } from "@opencode-ai/console-core/user.js" -import { and, Database, eq, isNull } from "@opencode-ai/console-core/drizzle/index.js" +import { and, Database, eq, isNull, or } from "@opencode-ai/console-core/drizzle/index.js" import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js" import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js" import { AuthTable } from "@opencode-ai/console-core/schema/auth.sql.js" @@ -134,28 +134,33 @@ export default { if (!subject) throw new Error("No subject found") if (Resource.App.stage !== "production" && !email.endsWith("@anoma.ly")) { - throw new Error("Invalid email") } // Get account const accountID = await (async () => { - // check provider mapping - const idByProvider = await Database.use(async (tx) => + const matches = await Database.use(async (tx) => tx - .select({ accountID: AuthTable.accountID }) + .select({ + provider: AuthTable.provider, + accountID: AuthTable.accountID, + }) .from(AuthTable) - .where(and(eq(AuthTable.provider, response.provider), eq(AuthTable.subject, subject))) - .then((rows) => rows[0]?.accountID), + .where( + or( + and(eq(AuthTable.provider, response.provider), eq(AuthTable.subject, subject)), + and(eq(AuthTable.provider, "email"), eq(AuthTable.subject, email)), + ), + ), ) - // check email mapping - const idByEmail = await Account.fromEmail(email).then((x) => x?.id) + const idByProvider = matches.find((x) => x.provider === response.provider)?.accountID + const idByEmail = matches.find((x) => x.provider === "email")?.accountID if (idByProvider && idByEmail) return idByProvider // create account if not found let accountID = idByProvider ?? idByEmail if (!accountID) { console.log("creating account for", email) - accountID = await Account.create({ email: email! }) + accountID = await Account.create({}) } await Database.use(async (tx) => |
