@@ -28,6 +28,10 @@ type CompiledFns<TContext> = {
2828 explain ( ctx : TContext ) : ParsedPolicyStatement [ ] ;
2929} ;
3030
31+ type ApplyOptions = {
32+ onContextMissing : boolean ;
33+ } ;
34+
3135function hasAllPaths ( statement : ParsedPolicyStatement , ctx : unknown ) {
3236 if ( statement . contextPaths . length === 0 ) {
3337 return true ;
@@ -140,26 +144,38 @@ export class PolicyResolver {
140144
141145 const explain = ( ctx : TContext ) : ParsedPolicyStatement [ ] => {
142146 return [
143- ...deny . filter ( ( statement ) => this . #apply( statement , ctx ) ) ,
144- ...allow . filter ( ( statement ) => this . #apply( statement , ctx ) ) ,
147+ ...deny . filter ( ( statement ) =>
148+ this . #apply( statement , ctx , { onContextMissing : true } )
149+ ) ,
150+ ...allow . filter ( ( statement ) =>
151+ this . #apply( statement , ctx , { onContextMissing : false } )
152+ ) ,
145153 ] ;
146154 } ;
147155
148156 const can = ( ctx : TContext ) : boolean => {
149- const isDenied = deny . some ( ( statement ) => this . #apply( statement , ctx ) ) ;
157+ const isDenied = deny . some ( ( statement ) =>
158+ this . #apply( statement , ctx , { onContextMissing : true } )
159+ ) ;
150160 if ( isDenied ) {
151161 return false ;
152162 }
153163
154- return allow . some ( ( statement ) => this . #apply( statement , ctx ) ) ;
164+ return allow . some ( ( statement ) =>
165+ this . #apply( statement , ctx , { onContextMissing : false } )
166+ ) ;
155167 } ;
156168
157169 return { can, explain } ;
158170 }
159171
160- #apply< TContext > ( statement : ParsedPolicyStatement , ctx : TContext ) : boolean {
172+ #apply< TContext > (
173+ statement : ParsedPolicyStatement ,
174+ ctx : TContext ,
175+ opts : ApplyOptions
176+ ) : boolean {
161177 if ( ! hasAllPaths ( statement , ctx ) ) {
162- return false ;
178+ return opts . onContextMissing ;
163179 }
164180
165181 return this . #parser. apply ( statement . constraint , ctx ) === true ;
0 commit comments