62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { AuthSchema } from "@money/shared/auth";
|
|
import { Context, Effect, Schema, Console } from "effect";
|
|
import { Authorization } from "../auth/context";
|
|
import { HttpLayerRouter, HttpServerRequest } from "@effect/platform";
|
|
|
|
export class CurrentSession extends Context.Tag("CurrentSession")<
|
|
CurrentSession,
|
|
{ readonly auth: Schema.Schema.Type<typeof AuthSchema> | null }
|
|
>() {}
|
|
|
|
export const SessionMiddleware = HttpLayerRouter.middleware<{
|
|
provides: CurrentSession;
|
|
}>()(
|
|
Effect.gen(function* () {
|
|
const auth = yield* Authorization;
|
|
|
|
return (httpEffect) =>
|
|
Effect.gen(function* () {
|
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
const headers = { ...request.headers };
|
|
|
|
const token = yield* HttpServerRequest.schemaHeaders(
|
|
Schema.Struct({
|
|
authorization: Schema.optional(Schema.String),
|
|
}),
|
|
).pipe(
|
|
Effect.tap(Console.debug),
|
|
Effect.flatMap(({ authorization }) =>
|
|
authorization != undefined
|
|
? parseAuthorization(authorization)
|
|
: Effect.succeed(undefined),
|
|
),
|
|
);
|
|
if (token) {
|
|
headers["cookie"] = token;
|
|
}
|
|
|
|
const session = yield* auth
|
|
.use((auth) => auth.api.getSession({ headers }))
|
|
.pipe(
|
|
Effect.flatMap((s) =>
|
|
s == null ? Effect.succeed(null) : Schema.decode(AuthSchema)(s),
|
|
),
|
|
// Effect.tap((s) => Console.debug("Auth result", s)),
|
|
);
|
|
|
|
return yield* Effect.provideService(httpEffect, CurrentSession, {
|
|
auth: session,
|
|
});
|
|
});
|
|
}),
|
|
);
|
|
|
|
const parseAuthorization = (input: string) =>
|
|
Effect.gen(function* () {
|
|
const m = /^Bearer\s+(.+)$/.exec(input);
|
|
if (!m) {
|
|
return yield* Effect.fail(new Error("Invalid token"));
|
|
}
|
|
return m[1];
|
|
});
|