-
Notifications
You must be signed in to change notification settings - Fork 306
Expand file tree
/
Copy pathorganization-context.ts
More file actions
44 lines (40 loc) · 1.64 KB
/
organization-context.ts
File metadata and controls
44 lines (40 loc) · 1.64 KB
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
import { OrganizationRepository } from "@domain/organizations"
import { OrganizationId, PermissionError } from "@domain/shared"
import { OrganizationRepositoryLive, SqlClientLive } from "@platform/db-postgres"
import { BadRequestError } from "@repo/utils"
import { Effect } from "effect"
import type { Context, MiddlewareHandler, Next } from "hono"
/**
* Resolves and attaches the organization from a route parameter.
*
* The middleware validates that the organization ID param exists, enforces
* authenticated organization access when auth context is present, loads the
* organization from the repository, and stores it on `c.var.organization`.
*/
export const createOrganizationContextMiddleware = (): MiddlewareHandler => {
return async (c: Context, next: Next) => {
const organizationIdParam = c.req.param("organizationId")
if (!organizationIdParam) {
throw new BadRequestError({ httpMessage: "Organization ID is required" })
}
const auth = c.get("auth")
if (auth && auth.organizationId !== organizationIdParam) {
throw new PermissionError({
message: "You do not have access to this organization",
organizationId: organizationIdParam,
})
}
const organizationId = OrganizationId(organizationIdParam)
const organization = await Effect.runPromise(
Effect.gen(function* () {
const repo = yield* OrganizationRepository
return yield* repo.findById(organizationId)
}).pipe(
Effect.provide(OrganizationRepositoryLive),
Effect.provide(SqlClientLive(c.var.postgresClient, organizationId)),
),
)
c.set("organization", organization)
await next()
}
}