diff --git a/projects/frontegg-app/src/lib/frontegg-entitlements.service.ts b/projects/frontegg-app/src/lib/frontegg-entitlements.service.ts index 5a8a1aa5..eca295d8 100644 --- a/projects/frontegg-app/src/lib/frontegg-entitlements.service.ts +++ b/projects/frontegg-app/src/lib/frontegg-entitlements.service.ts @@ -1,16 +1,13 @@ import { Subscription, PartialObserver, BehaviorSubject } from 'rxjs'; import { AuthState } from '@frontegg/redux-store'; import { Injectable } from '@angular/core'; -import { Entitlement, LoadEntitlementsCallback, EntitledToOptions } from '@frontegg/types'; +import { Entitlement, LoadEntitlementsCallback, EntitledToOptions, CustomAttributes } from '@frontegg/types'; -import { - FronteggState, - getPermissionEntitlements, - getFeatureEntitlements, - getEntitlements, -} from '@frontegg/redux-store'; +import { FronteggState } from '@frontegg/redux-store'; import { FronteggAppService } from './frontegg-app.service'; +type User = FronteggState['auth']['user']; + /** * An entitlements service for: * 1. Managing state subscription. @@ -21,16 +18,16 @@ import { FronteggAppService } from './frontegg-app.service'; providedIn: 'root', }) export class FronteggEntitlementsService { - private entitlementsStateSubject = new BehaviorSubject(undefined); + private userStateSubject = new BehaviorSubject(undefined); constructor(private fronteggAppService: FronteggAppService) { const state = this.fronteggAppService.fronteggApp.store.getState() as FronteggState; - this.updateEntitlementsStateIfNeeded(state.auth); + this.updateUserStateIfNeeded(state.auth); // Memoized entitlements State this.fronteggAppService.fronteggApp.store.subscribe(() => { const newState = this.fronteggAppService.fronteggApp.store.getState() as FronteggState; - this.updateEntitlementsStateIfNeeded(newState.auth); + this.updateUserStateIfNeeded(newState.auth); }); } @@ -39,57 +36,58 @@ export class FronteggEntitlementsService { * No need for deep equal because we already check it internally * @param authState */ - private updateEntitlementsStateIfNeeded(authState: AuthState): void { - const entitlementsState = authState.user?.entitlements as any; - if (this.entitlementsStateSubject.value === entitlementsState) { + private updateUserStateIfNeeded(authState: AuthState): void { + const entitlementsState = authState.user as User; + if (this.userStateSubject.value === entitlementsState) { return; } - this.entitlementsStateSubject.next(entitlementsState); + this.userStateSubject.next(entitlementsState); } /** - * The function gives the ability to return a manipulated data of the entitlements state as a subscription. + * The function gives the ability to return a manipulated data of the user state as a subscription. * - * @param dataManipulator Manipulator function that receives entitlements state and returns a manipulated data + * @param dataManipulator Manipulator function that receives user state and returns a manipulated data * @param observer For receiving manipulated data result * @returns a subscription to be able to unsubscribe */ - private getEntitlementsManipulatorSubscription( - dataManipulator: (entitlements: any) => Result, + private getUserManipulatorSubscription( + dataManipulator: (user: User) => Result, observer: PartialObserver ): Subscription { // used for computing the entitlements result because we don't return the state itself, but a calculated one - const entitlementsSubject = new BehaviorSubject(undefined as unknown as Result); + const userSubject = new BehaviorSubject(undefined as unknown as Result); - const stateSubscription = this.entitlementsStateSubject.subscribe(entitlements => { - entitlementsSubject.next(dataManipulator(entitlements)); + const stateSubscription = this.userStateSubject.subscribe(user => { + userSubject.next(dataManipulator(user)); }); // subscribing the consumer observer - const entitlementsResultSubscription = entitlementsSubject.asObservable().subscribe(observer) + const userResultSubscription = userSubject.asObservable().subscribe(observer) - // monkey patched to manage both un-subscriptions: state and entitlements manipulated result - const originalUnsubscribe = entitlementsResultSubscription.unsubscribe.bind(entitlementsResultSubscription); + // monkey patched to manage both un-subscriptions: state and user manipulated result + const originalUnsubscribe = userResultSubscription.unsubscribe.bind(userResultSubscription); - entitlementsResultSubscription.unsubscribe = ()=>{ + userResultSubscription.unsubscribe = ()=>{ originalUnsubscribe(); stateSubscription.unsubscribe(); }; - return entitlementsResultSubscription; + return userResultSubscription; } /** * @param feature * @param observer For receiving the feature entitlements result including if the user is entitled to the given feature. * Attaching the justification if not entitled + * @param customAttributes consumer attributes * @returns a subscription to be able to unsubscribe * @throws when entitlement is not enabled via frontegg options */ - public featureEntitlements$(feature: string, observer: PartialObserver): Subscription { - return this.getEntitlementsManipulatorSubscription( - (entitlements) => getFeatureEntitlements(entitlements, feature), + public featureEntitlements$(feature: string, observer: PartialObserver, customAttributes?: CustomAttributes): Subscription { + return this.getUserManipulatorSubscription( + () => { return this.fronteggAppService.fronteggApp.getFeatureEntitlements(feature, customAttributes)}, observer ); } @@ -98,11 +96,12 @@ export class FronteggEntitlementsService { * @param permission * @param observer For receiving the permission entitlements result including if the user is entitled to the given permission. * Attaching the justification if not entitled + * @param customAttributes consumer attributes * @returns a subscription to be able to unsubscribe */ - public permissionEntitlements$(permission: string, observer: PartialObserver): Subscription { - return this.getEntitlementsManipulatorSubscription( - (entitlements) => getPermissionEntitlements(entitlements, permission), + public permissionEntitlements$(permission: string, observer: PartialObserver, customAttributes?: CustomAttributes): Subscription { + return this.getUserManipulatorSubscription( + () => this.fronteggAppService.fronteggApp.getPermissionEntitlements(permission, customAttributes), observer ); } @@ -111,11 +110,12 @@ export class FronteggEntitlementsService { * @param options permissionKey or featureKey in an options object * @param observer For receiving the permission entitlements result including if the user is entitled to the given permission. * Attaching the justification if not entitled + * @param customAttributes consumer attributes * @returns a subscription to be able to unsubscribe */ - public entitlements$(options: EntitledToOptions, observer: PartialObserver): Subscription { - return this.getEntitlementsManipulatorSubscription( - (entitlements) => getEntitlements(entitlements, options), + public entitlements$(options: EntitledToOptions, observer: PartialObserver, customAttributes?: CustomAttributes): Subscription { + return this.getUserManipulatorSubscription( + () => this.fronteggAppService.fronteggApp.getEntitlements(options, customAttributes), observer ); }