UNPKG

@ibenvandeveire/ngx-authentication

Version:

A library of core authentication functionality used with @ibenvandeveire/types-auth.

584 lines (564 loc) 23.2 kB
import { AuthenticationResponse, AuthenticatedUserSession } from '@ibenvandeveire/types-authentication'; import { Observable, Subject } from 'rxjs'; import * as i0 from '@angular/core'; import { Type, OnDestroy, TemplateRef, InputSignal, PipeTransform, Provider, EnvironmentProviders } from '@angular/core'; import { Route, CanActivateFn } from '@angular/router'; import { HttpInterceptorFn, HttpRequest, HttpClient, HttpContext } from '@angular/common/http'; /** * An interface for the routes used in an application that has uses the NgxAuthenticationAbstractService */ interface NgxAuthenticatedRoute<FeatureType extends string = string, PermissionType extends string = string> extends Route { data?: { /** * The features for the NgxHasFeatureGuard */ feature?: FeatureType | FeatureType[]; /** * Whether all features should be provided, by default true, for the NgxHasFeatureGuard */ shouldHaveAllFeatures?: boolean; /** * The permissions for the NgxHasPermissionGuard */ permission?: PermissionType | PermissionType[]; /** * Whether all permissions should be provided, by default true, for the NgxHasPermissionGuard */ shouldHaveAllPermissions?: boolean; /** * Whether the user should be authenticated, for the NgxIsAuthenticatedGuard */ shouldBeAuthenticated?: boolean; /** * The location to redirect to if one of the guards conditions isn't met */ redirect?: string[]; /** * Remaining additional properties */ [key: string]: unknown; }; } type NgxAuthenticatedRoutes = NgxAuthenticatedRoute[]; type NgxAuthenticationStatus = 'unset' | 'signed-in' | 'signed-out'; type NgxAuthenticationResponseFeature<AuthenticationResponseType extends AuthenticationResponse<unknown>> = AuthenticationResponseType['session']['features'] extends (infer FeatureKey)[] ? FeatureKey : never; /** * The configuration of the authentication handlers */ interface NgxAuthenticationConfiguration { /** * The provided implementation of the NgxAuthenticationAbstractService */ service: Type<NgxAuthenticationAbstractService>; /** * An optional set of configuration to provide when the NgxAuthenticatedHttpClient needs to be used */ httpClientConfiguration?: NgxAuthenticatedHttpClientConfiguration; } interface NgxAuthenticatedHttpClientConfiguration { /** * An optional list of interceptors that will be provided to the HttpClient */ interceptors?: HttpInterceptorFn[]; /** * A base url generator function that will be run at injection time used by any request made by the NgxAuthenticatedHttpClient */ baseUrl?: () => string; /** * An optional handler for each authenticated API request made by the NgxAuthenticatedHttpClient */ authenticatedCallHandler?: (request: HttpRequest<unknown>) => HttpRequest<unknown>; } /** * An abstract service used by the directives, guards and other components of @ibenvandeveire/ngx-auth * * @template AuthenticationResponseType - The type of authentication response * @template SignInDataType - The data type used to sign in a user * @template SignoutDataType - The data type used to sign out a user * @template SignOutResponseType - The data type you get when signing out a user */ declare abstract class NgxAuthenticationAbstractService<AuthenticationResponseType extends AuthenticationResponse<unknown> = AuthenticationResponse<any>, SignInDataType = any, SignoutDataType = any, SignOutResponseType = void> { /** * A subject to store the authentication response if no other state implementation was provided */ private readonly authenticationResponseSubject; /** * A subject to store whether we've authenticated already */ private readonly authenticationStatusSubject; /** * A subject to store global features that are available for all users, regardless of their authenticated state */ private readonly globalFeaturesSubject; /** * Whether an authentication attempt has been made */ readonly hasAuthenticated$: Observable<boolean>; /** * Whether the user is authenticated */ readonly isAuthenticated$: Observable<boolean>; /** * The call required to sign in a user * * @param signInData - The data needed to sign in a user */ protected abstract signInUser(signInData: SignInDataType): Observable<AuthenticationResponseType>; /** * The call required to sign out a user * * @param signoutDataType - Optional data needed to sign out a user */ protected abstract signOutUser(signoutDataType?: SignoutDataType): Observable<SignOutResponseType>; /** * Stores the authentication response in the state * * @param response - The authentication response */ protected storeAuthenticationResponse(response: AuthenticationResponseType): void; /** * Returns the authentication response from the state */ protected getAuthenticationResponse(): Observable<AuthenticationResponseType>; /** * The authenticated user */ get user$(): Observable<AuthenticationResponseType['user']>; /** * The session of the authenticated user */ get session$(): Observable<AuthenticationResponseType['session']>; /** * The metadata of the authenticated user */ get metadata$(): Observable<AuthenticationResponseType['metadata']>; /** * Signs in a user and stores the authentication response * * @param signInData - The data needed to sign in a user */ signIn(signInData: SignInDataType): Observable<void>; /** * Signs out a user and removes the stored authentication response * * @param signoutDataType - Optional data needed to sign out a use */ signOut(signoutDataType?: SignoutDataType): Observable<SignOutResponseType>; /** * Returns whether the user has the required features. * * @param requiredFeatures - An array of required features * @param shouldHaveAllFeatures - Whether all features in the array are required, by default true */ hasFeature(requiredFeatures: NgxAuthenticationResponseFeature<AuthenticationResponseType>[], shouldHaveAllFeatures?: boolean): Observable<boolean>; /** * Sets a set of global features that are always present, regardless of the authenticated state of the user * * @param features - A list of features */ setGlobalFeatures(features: NgxAuthenticationResponseFeature<AuthenticationResponseType>[]): void; /** * Returns whether the user has the required permissions. * * @param requiredPermissions - An array of required permissions * @param shouldHaveAllPermissions - Whether all permissions in the array are required, by default true */ hasPermission(requiredPermissions: AuthenticationResponseType['session']['permissions'], shouldHaveAllPermissions?: boolean): Observable<boolean>; /** * Returns a session or an empty session depending on the authenticated state */ private getSession; } /** * A directive that will render a part of the template based on whether the required feature(s) are provided. * * Based upon `*ngIf`. See https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts */ declare class NgxHasFeatureDirective<FeatureType extends string> implements OnDestroy { /** * The provided template ref */ templateRef: TemplateRef<any>; /** * The provided ViewContainerRef */ private viewContainer; /** * The provided AuthenticationService implementation */ private readonly authenticationService; /** * The provided ChangeDetectorRef */ private readonly cdRef; /** * The destroyed state of the directive */ private destroyed$; /** * The needed templateRefs */ private thenTemplateRef; private thenViewRef; private elseTemplateRef; private elseViewRef; /** * The (list of) feature(s) we need to check */ private feature; /** * Whether the feature should be enabled */ private shouldHaveFeature; /** * Whether all features should be enabled */ private shouldHaveAllFeatures; /** * A feature or list of features the item should have */ ngxHasFeature: InputSignal<FeatureType | FeatureType[]>; /** * The else template in case the feature is not enabled */ ngxHasFeatureElse: InputSignal<TemplateRef<any>>; /** * Whether the feature should be enabled, by default this is true */ ngxHasFeatureShouldHaveFeature: InputSignal<boolean>; /** * Whether all features should be enabled, by default this is true */ ngxHasFeatureShouldHaveAllFeatures: InputSignal<boolean>; constructor(); ngOnDestroy(): void; /** * Updates the view and hides/renders the template as needed */ private updateView; /** * Dispose the current subscription */ private dispose; static ɵfac: i0.ɵɵFactoryDeclaration<NgxHasFeatureDirective<any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<NgxHasFeatureDirective<any>, "[ngxHasFeature]", never, { "ngxHasFeature": { "alias": "ngxHasFeature"; "required": false; "isSignal": true; }; "ngxHasFeatureElse": { "alias": "ngxHasFeatureElse"; "required": false; "isSignal": true; }; "ngxHasFeatureShouldHaveFeature": { "alias": "ngxHasFeatureShouldHaveFeature"; "required": false; "isSignal": true; }; "ngxHasFeatureShouldHaveAllFeatures": { "alias": "ngxHasFeatureShouldHaveAllFeatures"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>; } /** * A directive that will render a part of the template based on whether the required permissions(s) are provided. * * Based upon `*ngIf`. See https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts */ declare class NgxHasPermissionDirective<PermissionType extends string> implements OnDestroy { private viewContainer; private readonly authenticationService; private readonly cdRef; /** * The destroyed state of the directive */ private destroyed$; /** * The needed templateRefs */ private thenTemplateRef; private thenViewRef; private elseTemplateRef; private elseViewRef; /** * The (list of) permission(s) we need to check */ private permission; /** * Whether the permission should be enabled */ private shouldHavePermission; /** * Whether all permissions should be enabled */ private shouldHaveAllPermissions; /** * A permission or list of permissions the item should have */ ngxHasPermission: InputSignal<PermissionType | PermissionType[]>; /** * The else template in case the permission is not enabled */ ngxHasPermissionElse: InputSignal<TemplateRef<any>>; /** * Whether the permission should be enabled, by default this is true */ ngxHasPermissionShouldHavePermission: InputSignal<boolean>; /** * Whether all permissions should be enabled, by default this is true */ ngxHasPermissionShouldHaveAllPermissions: InputSignal<boolean>; constructor(); ngOnDestroy(): void; /** * Updates the view and hides/renders the template as needed */ private updateView; /** * Dispose the current subscription */ private dispose; static ɵfac: i0.ɵɵFactoryDeclaration<NgxHasPermissionDirective<any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<NgxHasPermissionDirective<any>, "[ngxHasPermission]", never, { "ngxHasPermission": { "alias": "ngxHasPermission"; "required": false; "isSignal": true; }; "ngxHasPermissionElse": { "alias": "ngxHasPermissionElse"; "required": false; "isSignal": true; }; "ngxHasPermissionShouldHavePermission": { "alias": "ngxHasPermissionShouldHavePermission"; "required": false; "isSignal": true; }; "ngxHasPermissionShouldHaveAllPermissions": { "alias": "ngxHasPermissionShouldHaveAllPermissions"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>; } /** * * A directive that will render a part of the template based on whether the user is authenticated. * * Based upon `*ngIf`. See https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts */ declare class NgxIsAuthenticatedDirective implements OnDestroy { private readonly authenticationService; private viewContainer; /** * The destroyed state of the directive */ private destroyed$; /** * The needed templateRefs */ private thenTemplateRef; private thenViewRef; private elseTemplateRef; private elseViewRef; /** * Whether the user has to be authenticated */ private shouldBeAuthenticated; constructor(); /** * Whether the user has to be authenticated */ ngxIsAuthenticated: InputSignal<boolean>; /** * The else template in case the condition is not matched */ ngxIsAuthenticatedElse: InputSignal<TemplateRef<any>>; ngOnDestroy(): void; private updateView; /** * Dispose the current subscription */ private dispose; static ɵfac: i0.ɵɵFactoryDeclaration<NgxIsAuthenticatedDirective, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<NgxIsAuthenticatedDirective, "[ngxIsAuthenticated]", never, { "ngxIsAuthenticated": { "alias": "ngxIsAuthenticated"; "required": false; "isSignal": true; }; "ngxIsAuthenticatedElse": { "alias": "ngxIsAuthenticatedElse"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>; } /** * Check if we can route to this route based on the provided feature * * @param routeSnapshot - The provided route snapshot */ declare const NgxHasFeatureGuard: CanActivateFn; /** * Check if we can route to this route based on the provided permission * * @param routeSnapshot - The provided route snapshot */ declare const NgxHasPermissionGuard: CanActivateFn; /** * Check if we can route to this route based on the provided permission * * @param routeSnapshot - The provided route snapshot */ declare const NgxIsAuthenticatedGuard: CanActivateFn; /** * A pipe that returns whether a (list of) feature(s) has been provided */ declare class NgxHasFeaturePipe<FeatureType extends string> implements PipeTransform, OnDestroy { private readonly authenticationService; private readonly cdRef; /** * Subject to hold the destroyed state of the current observable */ private destroyed$; /** * The latest value of the Observable, whether or not the feature is provided */ private hasFeature; /** * Instance of the change detector ref, implemented like this according to the async pipe implementation * https://github.com/angular/angular/blob/main/packages/common/src/pipes/async_pipe.ts */ private changeDetectorRef; constructor(); ngOnDestroy(): void; /** * Returns whether or not a feature is provided for the environment * * @param feature - The provided feature */ transform(feature: FeatureType | FeatureType[]): boolean; /** * Handles the changeDetection, latest value and dispose of the hasFeature observable * * @param observable - The hasFeature observable */ private subscribe; /** * Dispose of the feature observable when existing */ private dispose; static ɵfac: i0.ɵɵFactoryDeclaration<NgxHasFeaturePipe<any>, never>; static ɵpipe: i0.ɵɵPipeDeclaration<NgxHasFeaturePipe<any>, "ngxHasFeature", true>; } /** * A pipe that returns whether a (list of) permission(s) has been provided */ declare class NgxHasPermissionPipe<PermissionType extends string> implements PipeTransform, OnDestroy { private readonly authenticationService; private readonly cdRef; /** * Subject to hold the destroyed state of the current observable */ private destroyed$; /** * The latest value of the Observable, whether or not the permission is provided */ private hasPermission; /** * Instance of the change detector ref, implemented like this according to the async pipe implementation * https://github.com/angular/angular/blob/main/packages/common/src/pipes/async_pipe.ts */ private changeDetectorRef; constructor(); ngOnDestroy(): void; /** * Returns whether or not a permission is provided for the environment * * @param permission - The provided permission */ transform(permission: PermissionType | PermissionType[]): boolean; /** * Handles the changeDetection, latest value and dispose of the hasPermission observable * * @param observable - The hasPermission observable */ private subscribe; /** * Dispose of the permission observable when existing */ private dispose; static ɵfac: i0.ɵɵFactoryDeclaration<NgxHasPermissionPipe<any>, never>; static ɵpipe: i0.ɵɵPipeDeclaration<NgxHasPermissionPipe<any>, "ngxHasPermission", true>; } /** * Configures the provided implementation of the NgxAuthenticationAbstract service to the application * * @param configuration - The configuration with the provided service implementation */ declare const provideNgxAuthenticationConfiguration: (configuration: NgxAuthenticationConfiguration) => Provider | EnvironmentProviders[]; /** * Returns a mock version of the authentication service * * @param configuration - The configuration of the mock */ declare const NgxAuthenticationServiceMock: <AuthenticationResponseType extends AuthenticationResponse<any> = AuthenticationResponse<any>>(configuration: { hasFeatureSpy: unknown; hasPermissionSpy: unknown; signInSpy: unknown; signOutSpy: unknown; authenticationResponse: Subject<AuthenticationResponseType>; hasAuthenticated: Subject<NgxAuthenticationStatus>; }) => any; /** * Returns a mock authentication response */ declare const NgxAuthenticationResponseMock: AuthenticationResponse<{ name: string; }, AuthenticatedUserSession<'A' | 'B', 'Admin' | 'User'>, { requestPassword: boolean; }>; declare const NgxMockAuthenticatedHttpClient: (configuration: { download?: unknown; get?: unknown; patch?: unknown; put?: unknown; delete?: unknown; post?: unknown; }) => { get: unknown; download: unknown; delete: unknown; patch: unknown; post: unknown; put: unknown; }; /** * An opinionated wrapper of the HttpClient providing easy ways to make authenticated and unauthenticated calls */ declare class NgxAuthenticatedHttpClient { private readonly httpClient; private baseUrl; constructor(); /** * Adds a base-url to every request * @param {string} url - The url of the request */ private handleUrl; /** * Constructs a GET request to the provided API * * @param url - The url of the API * @param params - An optional set of params we wish to send to the API * @param withCredentials - Whether the call is made by an authenticated user, by default true * @param context - An optional HTTPContext */ get<DataType = unknown>(url: string, params?: Parameters<HttpClient['get']>[1]['params'], withCredentials?: boolean, context?: HttpContext): Observable<DataType>; /** * Constructs a GET request tailored to downloading to the provided API * * @param url - The url of the API * @param params - An optional set of params we wish to send to the API * @param withCredentials - Whether the call is made by an authenticated user, by default true * @param context - An optional HTTPContext */ download(url: string, params?: Parameters<HttpClient['get']>[1]['params'], withCredentials?: boolean, context?: HttpContext): Observable<{ fileType: string; blob: Blob; }>; /** * Constructs a DELETE request to the provided API * * @param url - The url of the API * @param params - An optional set of params we wish to send to the API * @param withCredentials - Whether the call is made by an authenticated user, by default true * @param context - An optional HTTPContext */ delete<DataType = void>(url: string, params?: Parameters<HttpClient['delete']>[1]['params'], withCredentials?: boolean, context?: HttpContext): Observable<DataType>; /** * Constructs a POST request to the provided API * * @param url - The url of the API * @param body - The body we wish to send * @param params - An optional set of params we wish to send to the API * @param withCredentials - Whether the call is made by an authenticated user, by default true * @param context - An optional HTTPContext */ post<DataType = void>(url: string, body: any, params?: Parameters<HttpClient['post']>[1]['params'], withCredentials?: boolean, context?: HttpContext): Observable<DataType>; /** * Constructs a PUT request to the provided API * * @param url - The url of the API * @param body - The body we wish to send * @param params - An optional set of params we wish to send to the API * @param withCredentials - Whether the call is made by an authenticated user, by default true * @param context - An optional HTTPContext */ put<DataType = void>(url: string, body?: any, params?: Parameters<HttpClient['put']>[1]['params'], withCredentials?: boolean, context?: HttpContext): Observable<DataType>; /** * Constructs a PATCH request to the provided API * * @param url - The url of the API * @param body - The body we wish to send * @param params - An optional set of params we wish to send to the API * @param withCredentials - Whether the call is made by an authenticated user, by default true * @param context - An optional HTTPContext */ patch<DataType = void>(url: string, body: any, params?: Parameters<HttpClient['patch']>[1]['params'], withCredentials?: boolean, context?: HttpContext): Observable<DataType>; static ɵfac: i0.ɵɵFactoryDeclaration<NgxAuthenticatedHttpClient, never>; static ɵprov: i0.ɵɵInjectableDeclaration<NgxAuthenticatedHttpClient>; } export { NgxAuthenticatedHttpClient, NgxAuthenticationAbstractService, NgxAuthenticationResponseMock, NgxAuthenticationServiceMock, NgxHasFeatureDirective, NgxHasFeatureGuard, NgxHasFeaturePipe, NgxHasPermissionDirective, NgxHasPermissionGuard, NgxHasPermissionPipe, NgxIsAuthenticatedDirective, NgxIsAuthenticatedGuard, NgxMockAuthenticatedHttpClient, provideNgxAuthenticationConfiguration }; export type { NgxAuthenticatedHttpClientConfiguration, NgxAuthenticatedRoute, NgxAuthenticatedRoutes, NgxAuthenticationConfiguration, NgxAuthenticationResponseFeature, NgxAuthenticationStatus };