summaryrefslogtreecommitdiffhomepage
path: root/cloud/app/src/context/auth.ts
blob: ef81cccf1e9a1c866b0d1eca25d425f89bece161 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { getRequestEvent } from "solid-js/web"
import { and, Database, eq, inArray } from "@opencode/cloud-core/drizzle/index.js"
import { WorkspaceTable } from "@opencode/cloud-core/schema/workspace.sql.js"
import { UserTable } from "@opencode/cloud-core/schema/user.sql.js"
import { redirect } from "@solidjs/router"
import { AccountTable } from "@opencode/cloud-core/schema/account.sql.js"
import { Actor } from "@opencode/cloud-core/actor.js"

import { createClient } from "@openauthjs/openauth/client"
import { useAuthSession } from "./auth.session"

export const AuthClient = createClient({
  clientID: "app",
  issuer: import.meta.env.VITE_AUTH_URL,
})

export const getActor = async (): Promise<Actor.Info> => {
  "use server"
  const evt = getRequestEvent()
  if (!evt) throw new Error("No request event")
  const url = new URL(evt.request.headers.has("x-server-id") ? evt.request.headers.get("referer")! : evt.request.url)
  const auth = await useAuthSession()
  auth.data.account = auth.data.account ?? {}
  const splits = url.pathname.split("/").filter(Boolean)
  if (splits[0] !== "workspace") {
    const current = auth.data.account[auth.data.current ?? ""]
    if (current) {
      return {
        type: "account",
        properties: {
          email: current.email,
          accountID: current.id,
        },
      }
    }
    if (Object.keys(auth.data.account ?? {}).length > 0) {
      const current = Object.values(auth.data.account)[0]
      await auth.update((val) => ({
        ...val,
        current: current.id,
      }))
      return {
        type: "account",
        properties: {
          email: current.email,
          accountID: current.id,
        },
      }
    }
    return {
      type: "public",
      properties: {},
    }
  }
  const workspaceHint = splits[1]
  const accounts = Object.keys(auth.data.account ?? {})
  if (accounts.length) {
    const result = await Database.transaction(async (tx) => {
      return await 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, workspaceHint)))
        .limit(1)
        .execute()
        .then((x) => x[0])
    })
    if (result) {
      return {
        type: "user",
        properties: {
          userID: result.user.id,
          workspaceID: result.user.workspaceID,
        },
      }
    }
  }
  throw redirect("/auth/authorize")
}