diff --git a/types/index.d.ts b/types/index.d.ts index d9ad5b3..eaf5c93 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,18 +1,21 @@ import { ContextConfigDefault, - RouteGenericInterface, FastifyInstance, FastifyPluginCallback, FastifyReply, FastifyRequest, FastifySchema, + RouteGenericInterface, preHandlerHookHandler } from 'fastify'; declare module 'fastify' { interface FastifyInstance { - auth( - functions: fastifyAuth.FastifyAuthFunction[] | (fastifyAuth.FastifyAuthFunction | fastifyAuth.FastifyAuthFunction[])[], + auth< + Request extends FastifyRequest = FastifyRequest, + Reply extends FastifyReply = FastifyReply + >( + functions: fastifyAuth.FastifyAuthFunction[] | (fastifyAuth.FastifyAuthFunction | fastifyAuth.FastifyAuthFunction[])[], options?: { relation?: fastifyAuth.FastifyAuthRelation; run?: 'all'; @@ -26,10 +29,13 @@ type FastifyAuth = FastifyPluginCallback declare namespace fastifyAuth { export type FastifyAuthRelation = 'and' | 'or' - export type FastifyAuthFunction = ( + export type FastifyAuthFunction< + Request extends FastifyRequest = FastifyRequest, + Reply extends FastifyReply = FastifyReply + > = ( this: FastifyInstance, - request: FastifyRequest, - reply: FastifyReply, + request: Request, + reply: Reply, done: (error?: Error) => void ) => void; diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 6772575..3ab1adb 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -1,4 +1,4 @@ -import fastify, { FastifyRequest, FastifyReply, preHandlerHookHandler, FastifyInstance } from 'fastify'; +import fastify, { FastifyInstance, FastifyReply, FastifyRequest, preHandlerHookHandler } from 'fastify'; import fastifyAuth from '..' import { expectType } from 'tsd'; import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' @@ -57,4 +57,61 @@ jsonSchemaToTS.route({ url: '/', preHandler: jsonSchemaToTS.auth([]), handler: () => {} -}) \ No newline at end of file +}) + +declare module "fastify" { + interface FastifyRequest { + identity: {actorId: string}; + } + + interface FastifyInstance { + authenticate: (request: FastifyRequest) => Promise; + } +} + +export const usersMutationAccessPolicy = + (fastify: FastifyInstance) => + async ( + request: FastifyRequest<{ + Params: { userId: string } + }>, + ): Promise => { + const { actorId } = request.identity; + const isOwner = actorId === request.params.userId; + + if (isOwner) { + return; + } + + fastify.log.warn("Actor should not be able to see this route"); + + throw new Error(request.params.userId); + }; + +async function usersController(fastify: FastifyInstance): Promise { + fastify.patch<{ + Params: { userId: string }; + Body: { name: string }; + }>( + "/:userId", + { + onRequest: fastify.auth([ + usersMutationAccessPolicy(fastify), + ]), + }, + async (req, res) => ({ success: true }), + ); +} + +async function usersControllerV2(fastify: FastifyInstance): Promise { + fastify.patch<{ + Params: { userId: string }; + Body: { name: string }; + }>( + "/:userId", + { + onRequest: usersMutationAccessPolicy(fastify), + }, + async (req, res) => ({ success: true }), + ); +} \ No newline at end of file