auth.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { getRequestEvent } from "solid-js/web"
  2. import { and, Database, eq, inArray } from "@opencode/cloud-core/drizzle/index.js"
  3. import { WorkspaceTable } from "@opencode/cloud-core/schema/workspace.sql.js"
  4. import { UserTable } from "@opencode/cloud-core/schema/user.sql.js"
  5. import { query, redirect } from "@solidjs/router"
  6. import { AccountTable } from "@opencode/cloud-core/schema/account.sql.js"
  7. import { Actor } from "@opencode/cloud-core/actor.js"
  8. import { createClient } from "@openauthjs/openauth/client"
  9. import { useAuthSession } from "./auth.session"
  10. export const AuthClient = createClient({
  11. clientID: "app",
  12. issuer: import.meta.env.VITE_AUTH_URL,
  13. })
  14. export const getActor = query(async (): Promise<Actor.Info> => {
  15. "use server"
  16. const evt = getRequestEvent()
  17. if (!evt) throw new Error("No request event")
  18. const url = new URL(evt.request.headers.has("x-server-id") ? evt.request.headers.get("referer")! : evt.request.url)
  19. const auth = await useAuthSession()
  20. const splits = url.pathname.split("/").filter(Boolean)
  21. if (splits[0] !== "workspace") {
  22. if (auth.data.current) {
  23. const current = auth.data.account[auth.data.current]
  24. return {
  25. type: "account",
  26. properties: {
  27. email: current.email,
  28. accountID: current.id,
  29. },
  30. }
  31. }
  32. if (Object.keys(auth.data.account ?? {}).length > 0) {
  33. const current = Object.values(auth.data.account)[0]
  34. await auth.update((val) => ({
  35. ...val,
  36. current: current.id,
  37. }))
  38. return {
  39. type: "account",
  40. properties: {
  41. email: current.email,
  42. accountID: current.id,
  43. },
  44. }
  45. }
  46. return {
  47. type: "public",
  48. properties: {},
  49. }
  50. }
  51. const workspaceHint = splits[1]
  52. const accounts = Object.keys(auth.data.account ?? {})
  53. const result = await Database.transaction(async (tx) => {
  54. return await tx
  55. .select({
  56. user: UserTable,
  57. })
  58. .from(AccountTable)
  59. .innerJoin(UserTable, and(eq(UserTable.email, AccountTable.email)))
  60. .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, UserTable.workspaceID))
  61. .where(and(inArray(AccountTable.id, accounts), eq(WorkspaceTable.id, workspaceHint)))
  62. .limit(1)
  63. .execute()
  64. .then((x) => x[0])
  65. })
  66. if (result) {
  67. return {
  68. type: "user",
  69. properties: {
  70. userID: result.user.id,
  71. workspaceID: result.user.workspaceID,
  72. },
  73. }
  74. }
  75. throw redirect("/auth/authorize")
  76. }, "actor")