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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
import { useSession } from "vinxi/http"
import { createClient } from "@openauthjs/openauth/client"
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 { query, redirect } from "@solidjs/router"
import { AccountTable } from "@opencode/cloud-core/schema/account.sql.js"
import { Actor } from "@opencode/cloud-core/actor.js"
export async function withActor<T>(fn: () => T) {
const actor = await getActor()
return Actor.provide(actor.type, actor.properties, fn)
}
export const getActor = query(async (): Promise<Actor.Info> => {
"use server"
const evt = getRequestEvent()
const url = new URL(evt!.request.headers.get("referer") ?? evt!.request.url)
const auth = await useAuthSession()
const [workspaceHint] = url.pathname.split("/").filter((x) => x.length > 0)
if (!workspaceHint) {
if (auth.data.current) {
const current = auth.data.account[auth.data.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 accounts = Object.keys(auth.data.account)
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")
}, "actor")
export const AuthClient = createClient({
clientID: "app",
issuer: import.meta.env.VITE_AUTH_URL,
})
export interface AuthSession {
account: Record<string, {
id: string
email: string
}>
current?: string
}
export function useAuthSession() {
return useSession<AuthSession>({
password: "0".repeat(32),
name: "auth"
})
}
export function AuthProvider() {
}
|