diff --git a/packages/console/app/src/context/auth.ts b/packages/console/app/src/context/auth.ts index 079f05c9..eff005c5 100644 --- a/packages/console/app/src/context/auth.ts +++ b/packages/console/app/src/context/auth.ts @@ -1,9 +1,7 @@ import { getRequestEvent } from "solid-js/web" import { and, Database, eq, inArray, sql } from "@opencode/console-core/drizzle/index.js" -import { WorkspaceTable } from "@opencode/console-core/schema/workspace.sql.js" import { UserTable } from "@opencode/console-core/schema/user.sql.js" import { redirect } from "@solidjs/router" -import { AccountTable } from "@opencode/console-core/schema/account.sql.js" import { Actor } from "@opencode/console-core/actor.js" import { createClient } from "@openauthjs/openauth/client" @@ -54,31 +52,27 @@ export const getActor = async (workspace?: string): Promise => { } const accounts = Object.keys(auth.data.account ?? {}) if (accounts.length) { - const result = await Database.use((tx) => + const user = await Database.use((tx) => tx - .select({ - user: UserTable, - }) - .from(AccountTable) - .innerJoin(UserTable, and(eq(UserTable.email, AccountTable.email))) - .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, UserTable.workspaceID)) - .where(and(inArray(AccountTable.id, accounts), eq(WorkspaceTable.id, workspace))) + .select() + .from(UserTable) + .where(and(eq(UserTable.workspaceID, workspace), inArray(UserTable.accountID, accounts))) .limit(1) .execute() .then((x) => x[0]), ) - if (result) { + if (user) { await Database.use((tx) => tx .update(UserTable) .set({ timeSeen: sql`now()` }) - .where(eq(UserTable.id, result.user.id)), + .where(and(eq(UserTable.workspaceID, workspace), eq(UserTable.id, user.id))), ) return { type: "user", properties: { - userID: result.user.id, - workspaceID: result.user.workspaceID, + userID: user.id, + workspaceID: user.workspaceID, }, } } diff --git a/packages/console/app/src/entry-server.tsx b/packages/console/app/src/entry-server.tsx index d5fca6aa..e0513314 100644 --- a/packages/console/app/src/entry-server.tsx +++ b/packages/console/app/src/entry-server.tsx @@ -9,7 +9,7 @@ export default createHandler( - + {assets} diff --git a/packages/console/app/src/routes/index.tsx b/packages/console/app/src/routes/index.tsx index 95a24268..281cec09 100644 --- a/packages/console/app/src/routes/index.tsx +++ b/packages/console/app/src/routes/index.tsx @@ -56,7 +56,7 @@ export default function Home() {
OpenCode | The AI coding agent built for the terminal - +
diff --git a/packages/console/app/src/routes/workspace.tsx b/packages/console/app/src/routes/workspace.tsx index 3aa3f20d..9a90fb9a 100644 --- a/packages/console/app/src/routes/workspace.tsx +++ b/packages/console/app/src/routes/workspace.tsx @@ -38,7 +38,7 @@ const logout = action(async () => { event!.locals.actor = undefined return val }) - throw redirect("/") + throw redirect("/zen") }) export default function WorkspaceLayout(props: RouteSectionProps) { diff --git a/packages/console/app/src/routes/workspace/member-section.tsx b/packages/console/app/src/routes/workspace/member-section.tsx index 7dc89334..4bd45a15 100644 --- a/packages/console/app/src/routes/workspace/member-section.tsx +++ b/packages/console/app/src/routes/workspace/member-section.tsx @@ -169,7 +169,7 @@ function MemberRow(props: { member: any; workspaceID: string; currentUserID: str when={editing()} fallback={ - {props.member.email} + {props.member.accountEmail ?? props.member.email} {props.member.role} }> invited @@ -192,7 +192,7 @@ function MemberRow(props: { member: any; workspaceID: string; currentUserID: str
-
{props.member.email}
+
{props.member.accountEmail ?? props.member.email}
Role: {props.member.role}
}> diff --git a/packages/console/core/src/account.ts b/packages/console/core/src/account.ts index 3bed2bef..cd1eed4b 100644 --- a/packages/console/core/src/account.ts +++ b/packages/console/core/src/account.ts @@ -54,7 +54,7 @@ export namespace Account { .select(getTableColumns(WorkspaceTable)) .from(WorkspaceTable) .innerJoin(UserTable, eq(UserTable.workspaceID, WorkspaceTable.id)) - .where(and(eq(UserTable.email, actor.properties.email), isNull(WorkspaceTable.timeDeleted))) + .where(and(eq(UserTable.accountID, actor.properties.accountID), isNull(WorkspaceTable.timeDeleted))) .execute(), ) } diff --git a/packages/console/core/src/schema/user.sql.ts b/packages/console/core/src/schema/user.sql.ts index e1da69ee..861c14b4 100644 --- a/packages/console/core/src/schema/user.sql.ts +++ b/packages/console/core/src/schema/user.sql.ts @@ -1,6 +1,7 @@ -import { mysqlTable, uniqueIndex, varchar, int, mysqlEnum } from "drizzle-orm/mysql-core" +import { mysqlTable, uniqueIndex, varchar, int, mysqlEnum, foreignKey } from "drizzle-orm/mysql-core" import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types" import { workspaceIndexes } from "./workspace.sql" +import { AccountTable } from "./account.sql" export const UserRole = ["admin", "member"] as const @@ -22,5 +23,10 @@ export const UserTable = mysqlTable( ...workspaceIndexes(table), uniqueIndex("user_account_id").on(table.workspaceID, table.accountID), uniqueIndex("user_email").on(table.workspaceID, table.email), + foreignKey({ + columns: [table.accountID], + foreignColumns: [AccountTable.id], + name: "global_account_id", + }), ], ) diff --git a/packages/console/core/src/user.ts b/packages/console/core/src/user.ts index ecf59229..8f00722e 100644 --- a/packages/console/core/src/user.ts +++ b/packages/console/core/src/user.ts @@ -1,5 +1,5 @@ import { z } from "zod" -import { and, eq, isNull, sql } from "drizzle-orm" +import { and, eq, getTableColumns, isNull, sql } from "drizzle-orm" import { fn } from "./util/fn" import { Database } from "./drizzle" import { UserRole, UserTable } from "./schema/user.sql" @@ -9,6 +9,7 @@ import { render } from "@jsx-email/render" import { InviteEmail } from "@opencode/console-mail/InviteEmail.jsx" import { AWS } from "./aws" import { Account } from "./account" +import { AccountTable } from "./schema/account.sql" export namespace User { const assertAdmin = async () => { @@ -29,8 +30,12 @@ export namespace User { export const list = fn(z.void(), () => Database.use((tx) => tx - .select() + .select({ + ...getTableColumns(UserTable), + accountEmail: AccountTable.email, + }) .from(UserTable) + .leftJoin(AccountTable, eq(UserTable.accountID, AccountTable.id)) .where(and(eq(UserTable.workspaceID, Actor.workspace()), isNull(UserTable.timeDeleted))), ), ) @@ -159,19 +164,22 @@ export namespace User { await assertAdmin() assertNotSelf(id) - return await Database.use(async (tx) => { - const email = await tx - .select({ email: UserTable.email }) - .from(UserTable) - .where(and(eq(UserTable.id, id), eq(UserTable.workspaceID, Actor.workspace()))) - .then((rows) => rows[0]?.email) - if (!email) throw new Error("User not found") + return await Database.transaction(async (tx) => { + const user = await fromID(id) + if (!user) throw new Error("User not found") await tx .update(UserTable) .set({ - oldEmail: email, - email: null, + ...(user.email + ? { + oldEmail: user.email, + email: null, + } + : { + oldAccountID: user.accountID, + accountID: null, + }), timeDeleted: sql`now()`, }) .where(and(eq(UserTable.id, id), eq(UserTable.workspaceID, Actor.workspace()))) diff --git a/packages/console/core/src/workspace.ts b/packages/console/core/src/workspace.ts index e6356e49..6119f51d 100644 --- a/packages/console/core/src/workspace.ts +++ b/packages/console/core/src/workspace.ts @@ -1,7 +1,7 @@ import { z } from "zod" import { fn } from "./util/fn" import { Actor } from "./actor" -import { Database, sql } from "./drizzle" +import { Database } from "./drizzle" import { Identifier } from "./identifier" import { UserTable } from "./schema/user.sql" import { BillingTable } from "./schema/billing.sql" @@ -20,7 +20,6 @@ export namespace Workspace { workspaceID, id: Identifier.create("user"), accountID: account.properties.accountID, - email: account.properties.email, name: "", role: "admin", }) @@ -35,9 +34,7 @@ export namespace Workspace { { workspaceID, }, - async () => { - await Key.create({ name: "Default API Key" }) - }, + () => Key.create({ name: "Default API Key" }), ) return workspaceID }) diff --git a/packages/console/function/src/auth.ts b/packages/console/function/src/auth.ts index 77199fef..09e3f372 100644 --- a/packages/console/function/src/auth.ts +++ b/packages/console/function/src/auth.ts @@ -29,7 +29,7 @@ export const subjects = createSubjects({ const MY_THEME: Theme = { ...THEME_OPENAUTH, - logo: "https://opencode.ai/favicon.svg", + logo: "https://opencode.ai/favicon-zen.svg", } export default {