Skip to content

Commit

Permalink
fix: change how injectable definition is done
Browse files Browse the repository at this point in the history
  • Loading branch information
GerkinDev committed Mar 6, 2022
1 parent 9a8e084 commit efd306a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 26 deletions.
45 changes: 31 additions & 14 deletions src/policies.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,41 @@ export class PoliciesGuard<TAbility extends AnyAbilityLike = PureAbility<any, an
}

/**
* Check if the policy matches the current request's ability.
* Check if the given descriptor is injectable or a provider token, and return a real policy.
*
* @param policy - The policy descriptor.
* @param policyDescriptor - The descriptor to resolve.
* @returns the injected policy, or the policy value if it was not injectable.
*/
private _getPolicyFromDescriptor( policyDescriptor: PolicyDescriptor<TAbility> ){
if (
// Class providers
( typeof policyDescriptor === 'function' && isInjectable( policyDescriptor ) ) ||
// Token providers
typeof policyDescriptor === 'string' || typeof policyDescriptor === 'symbol'
) {
return this._moduleRef.get( policyDescriptor );
} else {
return policyDescriptor;
}
}

/**
* Check if the policy descriptor matches the current request's ability.
*
* @param policyDescriptor - The policy descriptor.
* @param ability - The request's ability.
* @returns `true` if allowed, `false` otherwise.
*/
private _execPolicyHandler( policy: PolicyDescriptor<TAbility>, ability: TAbility ) {
const injectedPolicy = ( typeof policy === 'function' && isInjectable( policy ) ) || typeof policy === 'string' || typeof policy === 'symbol' ?
this._moduleRef.get( policy ) :
policy;
if( typeof injectedPolicy === 'boolean' ) {
return injectedPolicy;
} else if( typeof injectedPolicy === 'function' ){
return injectedPolicy( ability );
} else if( injectedPolicy && 'action' in injectedPolicy && 'subject' in injectedPolicy ){
return ability.can( injectedPolicy.action, injectedPolicy.subject );
} else if( injectedPolicy && 'handle' in injectedPolicy ){
return injectedPolicy.handle( ability );
private _execPolicyHandler( policyDescriptor: PolicyDescriptor<TAbility>, ability: TAbility ) {
const policy = this._getPolicyFromDescriptor( policyDescriptor );
if( typeof policy === 'boolean' ) {
return policy;
} else if( typeof policy === 'function' ){
return policy( ability );
} else if( policy && 'action' in policy && 'subject' in policy ){
return ability.can( policy.action, policy.subject );
} else if( policy && 'handle' in policy ){
return policy.handle( ability );
} else {
throw new TypeError( 'Invalid handler type' );
}
Expand Down
14 changes: 2 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, Type } from '@nestjs/common';
import { Type } from '@nestjs/common';
import { isObject } from 'lodash';
import { Observable, lastValueFrom } from 'rxjs';

Expand All @@ -21,14 +21,4 @@ export const anyToPromise = <T>( fn: () => MaybeAsyncValue<T> ): Promise<T> => {
}
};

const SCOPE_OPTIONS_METADATA = ( () => {
@Injectable()
class FakeClass {}
const metaKeys = Reflect.getMetadataKeys( FakeClass );
if( metaKeys.length !== 1 ){
throw new Error( 'Your version of NestJS is incompatible with this package !' );
}
return metaKeys[0];
} )();

export const isInjectable = ( fn: Type<any> | ( ( ...args: any[] ) => any ) ): fn is Type<any> => Reflect.hasMetadata( SCOPE_OPTIONS_METADATA, fn );
export const isInjectable = ( fn: Type<any> | ( ( ...args: any[] ) => any ) ): fn is Type<any> => Reflect.hasMetadata( '__injectable__', fn );

0 comments on commit efd306a

Please sign in to comment.