@ibenvandeveire/ngx-authentication
Version:
A library of core authentication functionality used with @ibenvandeveire/types-auth.
584 lines (564 loc) • 23.2 kB
TypeScript
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 };