import {route, Route} from "../routes"; import {WithSecurity} from "./withSecurity"; import {isFailure, success} from "@http4t/result"; import {BaseRequestLens, RequestLens, RoutingResult} from "../lenses"; import {HttpRequest} from "@http4t/core/contract"; import {SecuredRoutes} from "./"; export class TokenToClaimsLens extends BaseRequestLens> { constructor(private readonly clientSideLens: RequestLens>, private readonly tokenToClaims: (token: TToken) => Promise>) { super(); } async get(from: HttpRequest): Promise>> { const tokenResult = await this.clientSideLens.get(from); if (isFailure(tokenResult)) return tokenResult; const claimsResult = await this.tokenToClaims(tokenResult.value.security); if (isFailure(claimsResult)) return claimsResult; return success({ security: claimsResult.value, value: tokenResult.value.value }); } async setRequest(into: HttpRequest, value: WithSecurity): Promise { throw new Error(`${Object.getPrototypeOf(this).name} is not intended to be used by clients, only on the server`) } } export function tokenToClaimsRoute( unsecuredRoute: Route, Out>, tokenToClaims: (token: TToken) => Promise>) : Route, Out> { return route( new TokenToClaimsLens(unsecuredRoute.request, tokenToClaims), unsecuredRoute.response); } export function tokenToClaimsRoutes, TToken, TClaims>( tokenSecuredRoutes: TRoutes, tokenToClaims: (token: TToken) => Promise>) : SecuredRoutes { return Object.entries(tokenSecuredRoutes) .reduce( (routes, [k, r]) => { routes[k as keyof TRoutes] = tokenToClaimsRoute( r as Route, any>, tokenToClaims); return routes; }, {} as SecuredRoutes); }