From d2d29ad3de45aae265e1b79779647533d699d071 Mon Sep 17 00:00:00 2001 From: Danilo Alonso Date: Fri, 9 Aug 2024 15:09:27 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20accurate=20auth=20typings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously would resolve to `any`, they now pickup the generic and the ref overrides. --- lib/types/request.d.ts | 30 +++++++++++++++++-------- lib/types/response.d.ts | 24 ++++++++++---------- test/types/index.ts | 50 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 22 deletions(-) diff --git a/lib/types/request.d.ts b/lib/types/request.d.ts index c987216db..969f6a19f 100644 --- a/lib/types/request.d.ts +++ b/lib/types/request.d.ts @@ -27,23 +27,24 @@ export interface AppCredentials { * User-extensible type for request.auth credentials. */ export interface AuthCredentials< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, + AuthUser = UserCredentials, + AuthApp = AppCredentials > { /** * The application scopes to be granted. * [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsauthaccessscope) */ scope?: string[] | undefined; + /** * If set, will only work with routes that set `access.entity` to `user`. */ - user?: MergeType | undefined; + user?: AuthUser /** * If set, will only work with routes that set `access.entity` to `app`. */ - app?: MergeType | undefined; + app?: AuthApp; } export interface AuthArtifacts { @@ -65,15 +66,20 @@ export type AuthMode = 'required' | 'optional' | 'try'; * [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-requestauth) */ export interface RequestAuth< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, - CredentialsExtra extends object = Record, + AuthUser = UserCredentials, + AuthApp = AppCredentials, + CredentialsExtra = Record, ArtifactsExtra = Record > { /** an artifact object received from the authentication strategy and used in authentication-related actions. */ artifacts: ArtifactsExtra; /** the credential object received during the authentication process. The presence of an object does not mean successful authentication. */ - credentials: MergeType>; + credentials: ( + + AuthCredentials & + CredentialsExtra + ); + /** the authentication error is failed and mode set to 'try'. */ error: Error; /** true if the request has been successfully authenticated, otherwise false. */ @@ -89,6 +95,7 @@ export interface RequestAuth< strategy: string; } + /** * 'peek' - emitted for each chunk of payload data read from the client connection. The event method signature is function(chunk, encoding). * 'finish' - emitted when the request payload finished reading. The event method signature is function (). @@ -296,7 +303,12 @@ export type ReqRef = Partial>; /** * Utilities for merging request refs and other things */ -export type MergeType = Omit & U; +export type MergeType = { + [K in keyof T]: K extends keyof U + ? U[K] + : T[K]; +} & U; + export type MergeRefs = MergeType; /** diff --git a/lib/types/response.d.ts b/lib/types/response.d.ts index 4b19ebc31..0489e3fae 100644 --- a/lib/types/response.d.ts +++ b/lib/types/response.d.ts @@ -386,9 +386,9 @@ export type ResponseValue = string | object; export interface AuthenticationData< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, - CredentialsExtra extends object = Record, + AuthUser = UserCredentials, + AuthApp = AppCredentials, + CredentialsExtra = Record, ArtifactsExtra = AuthArtifacts > { credentials: MergeType>; @@ -396,9 +396,9 @@ export interface AuthenticationData< } export interface Auth< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, - CredentialsExtra extends object = Record, + AuthUser = UserCredentials, + AuthApp = AppCredentials, + CredentialsExtra = Record, ArtifactsExtra = AuthArtifacts > { readonly isAuth: true; @@ -459,9 +459,9 @@ export interface ResponseToolkit { * @return Return value: an internal authentication object. */ authenticated < - AuthUser extends object = MergeRefs['AuthUser'], - AuthApp extends object = MergeRefs['AuthApp'], - CredentialsExtra extends object = MergeRefs['AuthCredentialsExtra'], + AuthUser = MergeRefs['AuthUser'], + AuthApp = MergeRefs['AuthApp'], + CredentialsExtra = MergeRefs['AuthCredentialsExtra'], ArtifactsExtra = MergeRefs['AuthArtifactsExtra'] >( data: ( @@ -537,9 +537,9 @@ export interface ResponseToolkit { * [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-hunauthenticatederror-data) */ unauthenticated < - AuthUser extends object = MergeRefs['AuthUser'], - AuthApp extends object = MergeRefs['AuthApp'], - CredentialsExtra extends object = MergeRefs['AuthCredentialsExtra'], + AuthUser = MergeRefs['AuthUser'], + AuthApp = MergeRefs['AuthApp'], + CredentialsExtra = MergeRefs['AuthCredentialsExtra'], ArtifactsExtra = MergeRefs['AuthArtifactsExtra'] >( error: Error, diff --git a/test/types/index.ts b/test/types/index.ts index 988edffb0..c5d7b2031 100644 --- a/test/types/index.ts +++ b/test/types/index.ts @@ -10,11 +10,18 @@ import { Server, ServerRoute, server as createServer, - ServerRegisterPluginObject + UserCredentials } from '../..'; const { expect: check } = lab; +declare module '../..' { + interface UserCredentials { + someId: string; + someName: string; + } +} + interface ServerAppSpace { multi?: number; } @@ -27,6 +34,19 @@ check.type(server); server.app.multi = 10; +const genericRoute: ServerRoute = { + method: 'GET', + path: '/', + handler: (request, h) => { + + check.type(request.auth.credentials!.user!); + + return 'hello!'; + } +} + +server.route(genericRoute); + interface RequestDecorations { Server: MyServer; RequestApp: { @@ -34,6 +54,22 @@ interface RequestDecorations { }, RouteApp: { prefix: string[]; + }, + AuthUser: { + id: string, + name: string + email: string + }, + AuthCredentialsExtra: { + test: number + } + AuthApp: { + key: string + name: string + }, + AuthArtifactsExtra: { + some: string + thing: number } } @@ -61,6 +97,18 @@ const route: ServerRoute = { check.type(request.server.app.multi!); check.type(request.route.settings.app!.prefix); + check.type(request.auth.credentials!.test); + + check.type(request.auth.credentials!.user!.email); + check.type(request.auth.credentials!.user!.id); + check.type(request.auth.credentials!.user!.name); + + check.type(request.auth.credentials!.app!.name); + check.type(request.auth.credentials!.app!.key); + + check.type(request.auth.artifacts.some); + check.type(request.auth.artifacts.thing); + return 'hello!' } };