diff options
| author | Frank <[email protected]> | 2025-10-02 13:58:38 -0400 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-10-02 13:58:40 -0400 |
| commit | a45fa7a93c7864ef7eed792949755b334a9b2524 (patch) | |
| tree | 00fedb5631806de856ecf9e5b49c997521d9d31d /packages/console/app/src | |
| parent | ae15c914556a51c042f37284d52945d6c480b37f (diff) | |
| download | opencode-a45fa7a93c7864ef7eed792949755b334a9b2524.tar.gz opencode-a45fa7a93c7864ef7eed792949755b334a9b2524.zip | |
wip: zen
Diffstat (limited to 'packages/console/app/src')
| -rw-r--r-- | packages/console/app/src/context/auth.ts | 1 | ||||
| -rw-r--r-- | packages/console/app/src/routes/workspace/[id].tsx | 18 | ||||
| -rw-r--r-- | packages/console/app/src/routes/workspace/member-section.tsx | 127 |
3 files changed, 28 insertions, 118 deletions
diff --git a/packages/console/app/src/context/auth.ts b/packages/console/app/src/context/auth.ts index 7097787fb..079f05c9c 100644 --- a/packages/console/app/src/context/auth.ts +++ b/packages/console/app/src/context/auth.ts @@ -79,7 +79,6 @@ export const getActor = async (workspace?: string): Promise<Actor.Info> => { properties: { userID: result.user.id, workspaceID: result.user.workspaceID, - role: result.user.role, }, } } diff --git a/packages/console/app/src/routes/workspace/[id].tsx b/packages/console/app/src/routes/workspace/[id].tsx index df05b14b1..ad1f47bd4 100644 --- a/packages/console/app/src/routes/workspace/[id].tsx +++ b/packages/console/app/src/routes/workspace/[id].tsx @@ -10,24 +10,14 @@ import { Show } from "solid-js" import { createAsync, query, useParams } from "@solidjs/router" import { Actor } from "@opencode/console-core/actor.js" import { withActor } from "~/context/auth.withActor" -import { and, Database, eq } from "@opencode/console-core/drizzle/index.js" -import { UserTable } from "@opencode/console-core/schema/user.sql.js" +import { User } from "@opencode/console-core/user.js" const getUser = query(async (workspaceID: string) => { "use server" return withActor(async () => { - const actor = Actor.use() - const isAdmin = await (async () => { - if (actor.type !== "user") return false - const role = await Database.use((tx) => - tx - .select({ role: UserTable.role }) - .from(UserTable) - .where(and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.id, actor.properties.userID))), - ).then((x) => x[0]?.role) - return role === "admin" - })() - return { isAdmin } + const actor = Actor.assert("user") + const user = await User.fromID(actor.properties.userID) + return { isAdmin: user?.role === "admin" } }, workspaceID) }, "user.get") diff --git a/packages/console/app/src/routes/workspace/member-section.tsx b/packages/console/app/src/routes/workspace/member-section.tsx index 0e3a101fd..7dc893346 100644 --- a/packages/console/app/src/routes/workspace/member-section.tsx +++ b/packages/console/app/src/routes/workspace/member-section.tsx @@ -3,46 +3,18 @@ import { createEffect, createSignal, For, Show } from "solid-js" import { withActor } from "~/context/auth.withActor" import { createStore } from "solid-js/store" import styles from "./member-section.module.css" -import { and, Database, eq, isNull, sql } from "@opencode/console-core/drizzle/index.js" -import { UserTable, UserRole } from "@opencode/console-core/schema/user.sql.js" -import { Identifier } from "@opencode/console-core/identifier.js" +import { UserRole } from "@opencode/console-core/schema/user.sql.js" import { Actor } from "@opencode/console-core/actor.js" -import { AWS } from "@opencode/console-core/aws.js" - -const assertAdmin = async (workspaceID: string) => { - const actor = Actor.use() - if (actor.type !== "user") throw new Error(`Expected admin user, got ${actor.type}`) - const user = await Database.use((tx) => - tx - .select() - .from(UserTable) - .where(and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.id, actor.properties.userID))), - ).then((x) => x[0]) - if (user?.role !== "admin") throw new Error(`Expected admin user, got ${user?.role}`) - return actor -} - -const assertNotSelf = (id: string) => { - const actor = Actor.use() - if (actor.type === "user" && actor.properties.userID === id) { - throw new Error(`Expected not self actor, got self actor`) - } - return actor -} +import { User } from "@opencode/console-core/user.js" const listMembers = query(async (workspaceID: string) => { "use server" return withActor(async () => { - const actor = await assertAdmin(workspaceID) - return Database.use((tx) => - tx - .select() - .from(UserTable) - .where(and(eq(UserTable.workspaceID, workspaceID), isNull(UserTable.timeDeleted))), - ).then((members) => ({ - members, + const actor = Actor.assert("user") + return { + members: await User.list(), currentUserID: actor.properties.userID, - })) + } }, workspaceID) }, "member.list") @@ -55,43 +27,13 @@ const inviteMember = action(async (form: FormData) => { const role = form.get("role")?.toString() as (typeof UserRole)[number] if (!role) return { error: "Role is required" } return json( - await withActor(async () => { - await assertAdmin(workspaceID) - return Database.use((tx) => - tx - .insert(UserTable) - .values({ - id: Identifier.create("user"), - name: "", - email, - workspaceID, - role, - }) + await withActor( + () => + User.invite({ email, role }) .then((data) => ({ error: undefined, data })) - .then(async (data) => { - const { render } = await import("@jsx-email/render") - const { InviteEmail } = await import("@opencode/console-mail/InviteEmail.jsx") - await AWS.sendEmail({ - to: email, - subject: `You've been invited to join the ${workspaceID} workspace on OpenCode Zen`, - body: render( - // @ts-ignore - InviteEmail({ - assetsUrl: `https://opencode.ai/email`, - workspace: workspaceID, - }), - ), - }) - return data - }) - .catch((e) => { - let error = e.message - if (error.match(/Duplicate entry '.*' for key 'user.user_email'/)) - error = "A user with this email has already been invited." - return { error } - }), - ) - }, workspaceID), + .catch((e) => ({ error: e.message as string })), + workspaceID, + ), { revalidate: listMembers.key }, ) }, "member.create") @@ -103,29 +45,13 @@ const removeMember = action(async (form: FormData) => { const workspaceID = form.get("workspaceID")?.toString() if (!workspaceID) return { error: "Workspace ID is required" } return json( - await withActor(async () => { - await assertAdmin(workspaceID) - assertNotSelf(id) - return Database.transaction(async (tx) => { - const email = await tx - .select({ email: UserTable.email }) - .from(UserTable) - .where(and(eq(UserTable.id, id), eq(UserTable.workspaceID, workspaceID))) - .execute() - .then((rows) => rows[0].email) - if (!email) return { error: "User not found" } - await tx - .update(UserTable) - .set({ - oldEmail: email, - email: null, - timeDeleted: sql`now()`, - }) - .where(and(eq(UserTable.id, id), eq(UserTable.workspaceID, workspaceID))) - }) - .then(() => ({ error: undefined })) - .catch((e) => ({ error: e.message as string })) - }, workspaceID), + await withActor( + () => + User.remove(id) + .then((data) => ({ error: undefined, data })) + .catch((e) => ({ error: e.message as string })), + workspaceID, + ), { revalidate: listMembers.key }, ) }, "member.remove") @@ -139,18 +65,13 @@ const updateMemberRole = action(async (form: FormData) => { const role = form.get("role")?.toString() as (typeof UserRole)[number] if (!role) return { error: "Role is required" } return json( - await withActor(async () => { - await assertAdmin(workspaceID) - if (role === "member") assertNotSelf(id) - return Database.use((tx) => - tx - .update(UserTable) - .set({ role }) - .where(and(eq(UserTable.id, id), eq(UserTable.workspaceID, workspaceID))) + await withActor( + () => + User.updateRole({ id, role }) .then((data) => ({ error: undefined, data })) .catch((e) => ({ error: e.message as string })), - ) - }, workspaceID), + workspaceID, + ), { revalidate: listMembers.key }, ) }, "member.updateRole") |
