UNPKG

@httpc/kit

Version:

httpc toolbox for building function-based API with minimal code and end-to-end type safety

112 lines (111 loc) 4.02 kB
import { ForbiddenError, useContextProperty, UnauthorizedError, useContext } from "@httpc/server"; import { KEY, RESOLVE, useContainer } from "../di"; import { useLogger } from "../logging"; import { Authorization, Assertion } from "../permissions"; export function useUser(mode) { const { user } = useContext(); if (!user && mode !== "optional") { throw new UnauthorizedError(); } return user; } export function useIsAuthenticated() { return !!useUser("optional"); } export function useAuthentication(user) { useContextProperty("user", user || undefined); useLogger().verbose("Authentication: %o", user || "Anonymous"); return user; } export function useAuthorization(action, auth) { if (arguments.length === 1) { auth = action; action = "set"; } let { authorization } = useContext(); if (action && auth) { // check if an authz service is registered const service = getAuthorizationService(); if (service) { if (action === "merge" && authorization) { authorization = authorization.merge(auth); } authorization = service.createAuthorization(auth); } else { // no service --> use raw authorization management if (action === "merge" && authorization) { authorization = authorization.merge(auth); } else if (auth instanceof Authorization) { authorization = auth; } else { authorization = Authorization.parse(auth); } } useContextProperty("authorization", authorization); const logger = useLogger(); if (logger.isLevelEnabled("verbose")) { logger.verbose("Authorization: %s", authorization.toString()); } } return authorization; } export function useAuthorize(permissions) { const logger = useLogger(); if (!permissions) { logger.warn("Authorized: no permission provided"); return; } const authorization = useAuthorization(); if (!authorization) { logger.warn("Not Authorized: missing authorization"); throw new UnauthorizedError(); } // check if an authz service is registered const service = getAuthorizationService(); if (service) { service.assert(authorization, permissions); } else { // no service --> use raw assert const assertion = typeof permissions === "string" ? Assertion.parse(permissions) : permissions; if (!assertion.test(authorization).success) { logger.warn("Not Authorized: %s", assertion); throw new ForbiddenError(); } } logger.verbose("Authorized: %s", permissions); } export function useIsAuthorized(permissions) { const logger = useLogger(); if (!permissions) { logger.warn("IsAuthorized(OK): no permission provided"); return true; } const authorization = useAuthorization(); if (!authorization) { logger.warn("IsAuthorized(KO): missing authorization"); return false; } let isAuthorized; // check if an authz service is registered const service = getAuthorizationService(); if (service) { isAuthorized = service.check(authorization, permissions); } else { // no service --> use raw assert const assertion = typeof permissions === "string" ? Assertion.parse(permissions) : permissions; isAuthorized = assertion.test(authorization).success; } logger.verbose("IsAuthorized(%s): %s", isAuthorized ? "OK" : "KO", permissions); return isAuthorized; } function getAuthorizationService() { const container = useContainer(); if (container.isRegistered(KEY("IAuthorizationService"), true)) { return RESOLVE(container, "IAuthorizationService"); } }