@nmnmcc/ability 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +322 -469
- package/dist/Authorizer.d.ts +216 -0
- package/dist/Authorizer.d.ts.map +1 -0
- package/dist/Authorizer.js +55 -0
- package/dist/Authorizer.js.map +1 -0
- package/dist/Condition.d.ts +536 -0
- package/dist/Condition.d.ts.map +1 -0
- package/dist/Condition.js +141 -0
- package/dist/Condition.js.map +1 -0
- package/dist/Decision.d.ts +131 -0
- package/dist/Decision.d.ts.map +1 -0
- package/dist/Decision.js +83 -0
- package/dist/Decision.js.map +1 -0
- package/dist/Domain.d.ts +148 -0
- package/dist/Domain.d.ts.map +1 -0
- package/dist/Domain.js +34 -0
- package/dist/Domain.js.map +1 -0
- package/dist/HttpApi.d.ts +129 -0
- package/dist/HttpApi.d.ts.map +1 -0
- package/dist/HttpApi.js +95 -0
- package/dist/HttpApi.js.map +1 -0
- package/dist/Policy.d.ts +429 -0
- package/dist/Policy.d.ts.map +1 -0
- package/dist/Policy.js +162 -0
- package/dist/Policy.js.map +1 -0
- package/dist/Principal.d.ts +35 -0
- package/dist/Principal.d.ts.map +1 -0
- package/dist/Principal.js +37 -0
- package/dist/Principal.js.map +1 -0
- package/dist/Resource.d.ts +213 -0
- package/dist/Resource.d.ts.map +1 -0
- package/dist/Resource.js +71 -0
- package/dist/Resource.js.map +1 -0
- package/dist/Rule.d.ts +189 -0
- package/dist/Rule.d.ts.map +1 -0
- package/dist/Rule.js +50 -0
- package/dist/Rule.js.map +1 -0
- package/dist/_virtual/_rolldown/runtime.js +1 -2
- package/dist/index.d.ts +9 -3
- package/dist/index.js +9 -3
- package/dist/internal/authorizer.d.ts +28 -0
- package/dist/internal/authorizer.d.ts.map +1 -0
- package/dist/internal/authorizer.js +153 -0
- package/dist/internal/authorizer.js.map +1 -0
- package/dist/internal/condition.d.ts +11 -0
- package/dist/internal/condition.d.ts.map +1 -0
- package/dist/internal/condition.js +393 -0
- package/dist/internal/condition.js.map +1 -0
- package/dist/internal/domain.js +34 -0
- package/dist/internal/domain.js.map +1 -0
- package/dist/internal/httpApi.js +41 -0
- package/dist/internal/httpApi.js.map +1 -0
- package/dist/internal/policy.js +524 -0
- package/dist/internal/policy.js.map +1 -0
- package/dist/internal/resource.js +66 -0
- package/dist/internal/resource.js.map +1 -0
- package/dist/internal/rule.js +131 -0
- package/dist/internal/rule.js.map +1 -0
- package/package.json +61 -72
- package/src/Authorizer.ts +330 -0
- package/src/Condition.ts +706 -0
- package/src/Decision.ts +117 -0
- package/src/Domain.ts +189 -0
- package/src/HttpApi.ts +148 -0
- package/src/Policy.ts +575 -0
- package/src/Principal.ts +41 -0
- package/src/Resource.ts +290 -0
- package/src/Rule.ts +265 -0
- package/src/index.ts +57 -0
- package/src/internal/authorizer.ts +271 -0
- package/src/internal/condition.ts +607 -0
- package/src/internal/domain.ts +56 -0
- package/src/internal/httpApi.ts +84 -0
- package/src/internal/policy.ts +815 -0
- package/src/internal/resource.ts +98 -0
- package/src/internal/rule.ts +203 -0
- package/dist/Ability.d.ts +0 -491
- package/dist/Ability.js +0 -207
- package/dist/AbilityExtra.d.ts +0 -79
- package/dist/AbilityExtra.js +0 -187
- package/dist/internal/ability.d.ts +0 -90
- package/dist/internal/ability.js +0 -550
- package/dist/internal/serializable.js +0 -22
package/dist/Rule.d.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { Kind } from "./Resource.js";
|
|
2
|
+
import { Any as Any$1, Ast, Builder as Builder$1, Condition, Error as Error$1, FieldPath, OpaqueOf as OpaqueOf$1, Services as Services$1, Variance } from "./Condition.js";
|
|
3
|
+
import { ActionOf, Any as Any$2, AnyAction, AnyValue, DataOf, Kind as Kind$1, Meta, Principal, Resources, ValueOf } from "./Domain.js";
|
|
4
|
+
import * as Equal from "effect/Equal";
|
|
5
|
+
import * as Inspectable from "effect/Inspectable";
|
|
6
|
+
import * as Pipeable from "effect/Pipeable";
|
|
7
|
+
declare namespace Rule_d_exports {
|
|
8
|
+
export { ActionFor, Any, Builder, DataFor, Error, FieldFor, KindOf, OpaqueOf, Options, Rule, Services, Target, TypeId, ValueFor, builder, isRule, matchesField };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @stability stable
|
|
12
|
+
* @category type IDs
|
|
13
|
+
* @since 0.3.0
|
|
14
|
+
*/
|
|
15
|
+
export declare const TypeId: "~@nmnmcc/ability/Rule";
|
|
16
|
+
/**
|
|
17
|
+
* @stability stable
|
|
18
|
+
* @category type IDs
|
|
19
|
+
* @since 0.3.0
|
|
20
|
+
*/
|
|
21
|
+
export type TypeId = typeof TypeId;
|
|
22
|
+
/**
|
|
23
|
+
* A rule. `E`, `R` and `O` come from its condition. See
|
|
24
|
+
* `Condition.Condition`.
|
|
25
|
+
*
|
|
26
|
+
* @stability stable
|
|
27
|
+
* @category models
|
|
28
|
+
* @since 0.3.0
|
|
29
|
+
*/
|
|
30
|
+
export interface Rule<E = never, R = never, O = never> extends Equal.Equal, Inspectable.Inspectable, Pipeable.Pipeable {
|
|
31
|
+
readonly [TypeId]: TypeId;
|
|
32
|
+
readonly _tag: "Allow" | "Deny";
|
|
33
|
+
readonly actions: ReadonlyArray<string>;
|
|
34
|
+
readonly resources: ReadonlyArray<string>;
|
|
35
|
+
readonly when?: Ast;
|
|
36
|
+
readonly fields?: ReadonlyArray<string>;
|
|
37
|
+
readonly reason?: string;
|
|
38
|
+
readonly id?: string;
|
|
39
|
+
readonly meta?: unknown;
|
|
40
|
+
readonly "~Rule"?: Variance<E, R, O>;
|
|
41
|
+
[Symbol.iterator](): Generator<Rule<E, R, O>, Rule<E, R, O>, unknown>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Any rule.
|
|
45
|
+
*
|
|
46
|
+
* @stability stable
|
|
47
|
+
* @category models
|
|
48
|
+
* @since 0.3.0
|
|
49
|
+
*/
|
|
50
|
+
export type Any = Rule<any, any, any>;
|
|
51
|
+
/**
|
|
52
|
+
* The error type of a rule.
|
|
53
|
+
*
|
|
54
|
+
* @stability stable
|
|
55
|
+
* @category utility types
|
|
56
|
+
* @since 0.3.0
|
|
57
|
+
*/
|
|
58
|
+
export type Error<A> = A extends {
|
|
59
|
+
readonly "~Rule"?: Variance<infer E, infer _R, infer _O>;
|
|
60
|
+
} ? E : never;
|
|
61
|
+
/**
|
|
62
|
+
* The service type of a rule.
|
|
63
|
+
*
|
|
64
|
+
* @stability stable
|
|
65
|
+
* @category utility types
|
|
66
|
+
* @since 0.3.0
|
|
67
|
+
*/
|
|
68
|
+
export type Services<A> = A extends {
|
|
69
|
+
readonly "~Rule"?: Variance<infer _E, infer R, infer _O>;
|
|
70
|
+
} ? R : never;
|
|
71
|
+
/**
|
|
72
|
+
* `Condition.Opaque` when a rule has a predicate.
|
|
73
|
+
*
|
|
74
|
+
* @stability stable
|
|
75
|
+
* @category utility types
|
|
76
|
+
* @since 0.3.0
|
|
77
|
+
*/
|
|
78
|
+
export type OpaqueOf<A> = A extends {
|
|
79
|
+
readonly "~Rule"?: Variance<infer _E, infer _R, infer O>;
|
|
80
|
+
} ? O : never;
|
|
81
|
+
/**
|
|
82
|
+
* A resource in a rule: a kind name, a resource of the domain, or `"*"`.
|
|
83
|
+
*
|
|
84
|
+
* @stability stable
|
|
85
|
+
* @category models
|
|
86
|
+
* @since 0.3.0
|
|
87
|
+
*/
|
|
88
|
+
export type Target<D> = Kind$1<D> | Resources<D> | "*";
|
|
89
|
+
/**
|
|
90
|
+
* The kind name of a target.
|
|
91
|
+
*
|
|
92
|
+
* @stability stable
|
|
93
|
+
* @category utility types
|
|
94
|
+
* @since 0.3.0
|
|
95
|
+
*/
|
|
96
|
+
export type KindOf<T> = T extends string ? T : Kind<T>;
|
|
97
|
+
/**
|
|
98
|
+
* The actions that a rule may use for the kinds `K`.
|
|
99
|
+
*
|
|
100
|
+
* @stability stable
|
|
101
|
+
* @category utility types
|
|
102
|
+
* @since 0.3.0
|
|
103
|
+
*/
|
|
104
|
+
export type ActionFor<D, K> = "*" | ("*" extends K ? AnyAction<D> : ActionOf<D, Extract<K, string>>);
|
|
105
|
+
/**
|
|
106
|
+
* The data type of the kinds `K`. For `"*"` it has no fields.
|
|
107
|
+
*
|
|
108
|
+
* @stability stable
|
|
109
|
+
* @category utility types
|
|
110
|
+
* @since 0.3.0
|
|
111
|
+
*/
|
|
112
|
+
export type DataFor<D, K> = "*" extends K ? {} : DataOf<D, Extract<K, string>>;
|
|
113
|
+
/**
|
|
114
|
+
* The value type of the kinds `K`.
|
|
115
|
+
*
|
|
116
|
+
* @stability stable
|
|
117
|
+
* @category utility types
|
|
118
|
+
* @since 0.3.0
|
|
119
|
+
*/
|
|
120
|
+
export type ValueFor<D, K> = "*" extends K ? AnyValue<D> : ValueOf<D, Extract<K, string>>;
|
|
121
|
+
/**
|
|
122
|
+
* A field name or a field pattern of the kinds `K`.
|
|
123
|
+
*
|
|
124
|
+
* @stability stable
|
|
125
|
+
* @category models
|
|
126
|
+
* @since 0.3.0
|
|
127
|
+
*/
|
|
128
|
+
export type FieldFor<D, K> = FieldPath<DataFor<D, K>> | `${string}*${string}`;
|
|
129
|
+
/**
|
|
130
|
+
* The options of a rule.
|
|
131
|
+
*
|
|
132
|
+
* @stability stable
|
|
133
|
+
* @category models
|
|
134
|
+
* @since 0.3.0
|
|
135
|
+
*/
|
|
136
|
+
export interface Options<D, K, C extends Any$1> {
|
|
137
|
+
/** The condition. It gets a builder with the types of the resource. */
|
|
138
|
+
readonly when?: (builder: Builder$1<DataFor<D, K>, ValueFor<D, K>, Principal<D>>) => C;
|
|
139
|
+
readonly fields?: ReadonlyArray<FieldFor<D, K>>;
|
|
140
|
+
readonly reason?: string;
|
|
141
|
+
readonly id?: string;
|
|
142
|
+
readonly meta?: Meta<D>;
|
|
143
|
+
}
|
|
144
|
+
type SingleOrArray<A> = A | ReadonlyArray<A>;
|
|
145
|
+
/**
|
|
146
|
+
* Makes rules with the types of a domain.
|
|
147
|
+
*
|
|
148
|
+
* @stability stable
|
|
149
|
+
* @category models
|
|
150
|
+
* @since 0.3.0
|
|
151
|
+
*/
|
|
152
|
+
export interface Builder<D> {
|
|
153
|
+
readonly allow: <const T extends Target<D>, const A extends ActionFor<D, KindOf<T>>, const C extends Any$1 = Condition>(action: SingleOrArray<A>, resource: SingleOrArray<T>, options?: Options<D, KindOf<T>, C>) => Rule<Error$1<C>, Services$1<C>, OpaqueOf$1<C>>;
|
|
154
|
+
readonly deny: <const T extends Target<D>, const A extends ActionFor<D, KindOf<T>>, const C extends Any$1 = Condition>(action: SingleOrArray<A>, resource: SingleOrArray<T>, options?: Options<D, KindOf<T>, C>) => Rule<Error$1<C>, Services$1<C>, OpaqueOf$1<C>>;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Makes a rule builder for a domain.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* const _ = Rule.builder(App)
|
|
162
|
+
* const rule = _.allow("read", Bot, {
|
|
163
|
+
* when: ($) => $.eq("ownerUserId", $.principal("userId")),
|
|
164
|
+
* })
|
|
165
|
+
* ```
|
|
166
|
+
*
|
|
167
|
+
* @stability stable
|
|
168
|
+
* @category constructors
|
|
169
|
+
* @since 0.3.0
|
|
170
|
+
*/
|
|
171
|
+
export declare const builder: <D extends Any$2>(domain: D) => Builder<D>;
|
|
172
|
+
/**
|
|
173
|
+
* Tests if a value is a rule.
|
|
174
|
+
*
|
|
175
|
+
* @stability stable
|
|
176
|
+
* @category guards
|
|
177
|
+
* @since 0.3.0
|
|
178
|
+
*/
|
|
179
|
+
export declare const isRule: (u: unknown) => u is Any;
|
|
180
|
+
/**
|
|
181
|
+
* Tests if a field name matches a field name or a field pattern of a rule.
|
|
182
|
+
*
|
|
183
|
+
* @stability stable
|
|
184
|
+
* @category predicates
|
|
185
|
+
* @since 0.3.0
|
|
186
|
+
*/
|
|
187
|
+
export declare const matchesField: (pattern: string, field: string) => boolean;
|
|
188
|
+
export { Rule_d_exports };
|
|
189
|
+
//# sourceMappingURL=Rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Rule.d.ts","names":["Condition.Ast","Condition.Variance","Domain.Kind","Domain.Resources","Resource.Kind","Domain.AnyAction","Domain.ActionOf","Domain.DataOf","Domain.AnyValue","Domain.ValueOf","Condition.FieldPath","Condition.Any","Domain.Principal","Condition.Builder","Domain.Meta","Condition.Condition","Condition.Error","Condition.Services","Condition.OpaqueOf","Domain.Any"],"sources":["../src/Rule.ts"],"mappings":";;;;;;;;;;;;;;qBAkCa;;;;;;YAOD,gBAAgB;;;;;;;;;iBAUX,KAAK,WAAW,WAAW,mBACnC,MAAM,OAAO,YAAY,aAAa,SAAS;YAC7C,SAAS;WACV;WACA,SAAS;WACT,WAAW;WACX,OAAOA;WACP,SAAS;WACT;WACA;WACA;WACA,UAAUC,SAAmB,GAAG,GAAG;GAC3C,OAAO,aAAa,UAAU,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG;;;;;;;;;YAU9C,MAAM;;;;;;;;YASN,MAAM,KAAK;WACb,UAAUA,eAAyB,SAAS,UAAU;IAE7D;;;;;;;;YAUS,SAAS,KAAK;WAChB,UAAUA,eAAyB,UAAU,SAAS;IAE7D;;;;;;;;YAUS,SAAS,KAAK;WAChB,UAAUA,eAAyB,UAAU,UAAU;IAE9D;;;;;;;;YAUS,OAAO,KAAKC,OAAY,KAAKC,UAAiB;;;;;;;;YAS9C,OAAO,KAAK,mBAAmB,IAAIC,KAAc;;;;;;;;YASjD,UAAU,GAAG,wBAET,IACXC,UAAiB,KACjBC,SAAgB,GAAG,QAAQ;;;;;;;;YASpB,QAAQ,GAAG,iBAAiB,SAErCC,OAAc,GAAG,QAAQ;;;;;;;;YAShB,SAAS,GAAG,iBAAiB,IACtCC,SAAgB,KAChBC,QAAe,GAAG,QAAQ;;;;;;;;YASjB,SAAS,GAAG,KACvBC,UAAoB,QAAQ,GAAG;;;;;;;;iBASf,QAAQ,GAAG,GAAG,UAAUC;;WAE/B,QACR,SAASE,UACR,QAAQ,GAAG,IACX,SAAS,GAAG,IACZD,UAAiB,QAEd;WACI,SAAS,cAAc,SAAS,GAAG;WACnC;WACA;WACA,OAAOE,KAAY;;KAGxB,cAAc,KAAK,IAAI,cAAc;;;;;;;;iBASzB,QAAQ;WACf,cACF,UAAU,OAAO,UACjB,UAAU,UAAU,GAAG,OAAO,WAC9B,UAAUH,QAAgBI,WAEhC,QAAQ,cAAc,IACtB,UAAU,cAAc,IACxB,UAAU,QAAQ,GAAG,OAAO,IAAI,OAC5B,KAAKC,QAAgB,IAAIC,WAAmB,IAAIC,WAAmB;WAC/D,aACF,UAAU,OAAO,UACjB,UAAU,UAAU,GAAG,OAAO,WAC9B,UAAUP,QAAgBI,WAEhC,QAAQ,cAAc,IACtB,UAAU,cAAc,IACxB,UAAU,QAAQ,GAAG,OAAO,IAAI,OAC5B,KAAKC,QAAgB,IAAIC,WAAmB,IAAIC,WAAmB;;;;;;;;;;;;;;;;;qBAkB5D,UAAU,UAAUC,OAAY,QAAQ,MAAM,QAAQ;;;;;;;;qBAUtD,SAAS,eAAe,KAAK;;;;;;;;qBAS7B,eAAe,iBAAiB"}
|
package/dist/Rule.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { TypeId as TypeId$1, builder as builder$1, isRule as isRule$1, matchesFieldPattern } from "./internal/rule.js";
|
|
3
|
+
// src/Rule.ts
|
|
4
|
+
var Rule_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
TypeId: () => TypeId,
|
|
6
|
+
builder: () => builder,
|
|
7
|
+
isRule: () => isRule,
|
|
8
|
+
matchesField: () => matchesField
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* @stability stable
|
|
12
|
+
* @category type IDs
|
|
13
|
+
* @since 0.3.0
|
|
14
|
+
*/
|
|
15
|
+
const TypeId = TypeId$1;
|
|
16
|
+
/**
|
|
17
|
+
* Makes a rule builder for a domain.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const _ = Rule.builder(App)
|
|
22
|
+
* const rule = _.allow("read", Bot, {
|
|
23
|
+
* when: ($) => $.eq("ownerUserId", $.principal("userId")),
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @stability stable
|
|
28
|
+
* @category constructors
|
|
29
|
+
* @since 0.3.0
|
|
30
|
+
*/
|
|
31
|
+
const builder = builder$1;
|
|
32
|
+
/**
|
|
33
|
+
* Tests if a value is a rule.
|
|
34
|
+
*
|
|
35
|
+
* @stability stable
|
|
36
|
+
* @category guards
|
|
37
|
+
* @since 0.3.0
|
|
38
|
+
*/
|
|
39
|
+
const isRule = isRule$1;
|
|
40
|
+
/**
|
|
41
|
+
* Tests if a field name matches a field name or a field pattern of a rule.
|
|
42
|
+
*
|
|
43
|
+
* @stability stable
|
|
44
|
+
* @category predicates
|
|
45
|
+
* @since 0.3.0
|
|
46
|
+
*/
|
|
47
|
+
const matchesField = matchesFieldPattern;
|
|
48
|
+
export { Rule_exports, TypeId, builder, isRule, matchesField };
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=Rule.js.map
|
package/dist/Rule.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Rule.js","names":["internal.TypeId","internal.builder","internal.isRule","internal.matchesFieldPattern"],"sources":["../src/Rule.ts"],"sourcesContent":["/**\n * A rule says that a principal may (`Allow`) or may not (`Deny`) do some\n * actions on some resources. A rule may have:\n * - a condition, which must be true for the rule to apply;\n * - a list of fields, for rules about parts of a resource;\n * - a reason, an id, and extra data (`meta`).\n *\n * Rules do not change, and two rules with the same data are equal. A rule\n * works in a generator, so you can write `yield* _.allow(...)` inside\n * `Policy.define`.\n *\n * The action `\"*\"` means every action. The resource `\"*\"` means every\n * resource.\n *\n * Field names in a rule may have patterns. `*` stands for any part of one\n * field name, and `**` stands for any number of parts. So `address.*` covers\n * `address.city`, and `**` covers every field.\n *\n * @stability stable\n * @since 0.3.0\n */\nimport type * as Equal from \"effect/Equal\"\nimport type * as Inspectable from \"effect/Inspectable\"\nimport type * as Pipeable from \"effect/Pipeable\"\nimport type * as Condition from \"./Condition.ts\"\nimport type * as Domain from \"./Domain.ts\"\nimport * as internal from \"./internal/rule.ts\"\nimport type * as Resource from \"./Resource.ts\"\n\n/**\n * @stability stable\n * @category type IDs\n * @since 0.3.0\n */\nexport const TypeId: \"~@nmnmcc/ability/Rule\" = internal.TypeId\n\n/**\n * @stability stable\n * @category type IDs\n * @since 0.3.0\n */\nexport type TypeId = typeof TypeId\n\n/**\n * A rule. `E`, `R` and `O` come from its condition. See\n * `Condition.Condition`.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Rule<E = never, R = never, O = never>\n\textends Equal.Equal, Inspectable.Inspectable, Pipeable.Pipeable {\n\treadonly [TypeId]: TypeId\n\treadonly _tag: \"Allow\" | \"Deny\"\n\treadonly actions: ReadonlyArray<string>\n\treadonly resources: ReadonlyArray<string>\n\treadonly when?: Condition.Ast\n\treadonly fields?: ReadonlyArray<string>\n\treadonly reason?: string\n\treadonly id?: string\n\treadonly meta?: unknown\n\treadonly \"~Rule\"?: Condition.Variance<E, R, O>\n\t[Symbol.iterator](): Generator<Rule<E, R, O>, Rule<E, R, O>, unknown>\n}\n\n/**\n * Any rule.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type Any = Rule<any, any, any>\n\n/**\n * The error type of a rule.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Error<A> = A extends {\n\treadonly \"~Rule\"?: Condition.Variance<infer E, infer _R, infer _O>\n}\n\t? E\n\t: never\n\n/**\n * The service type of a rule.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Services<A> = A extends {\n\treadonly \"~Rule\"?: Condition.Variance<infer _E, infer R, infer _O>\n}\n\t? R\n\t: never\n\n/**\n * `Condition.Opaque` when a rule has a predicate.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type OpaqueOf<A> = A extends {\n\treadonly \"~Rule\"?: Condition.Variance<infer _E, infer _R, infer O>\n}\n\t? O\n\t: never\n\n/**\n * A resource in a rule: a kind name, a resource of the domain, or `\"*\"`.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type Target<D> = Domain.Kind<D> | Domain.Resources<D> | \"*\"\n\n/**\n * The kind name of a target.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type KindOf<T> = T extends string ? T : Resource.Kind<T>\n\n/**\n * The actions that a rule may use for the kinds `K`.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type ActionFor<D, K> =\n\t| \"*\"\n\t| (\"*\" extends K\n\t\t\t? Domain.AnyAction<D>\n\t\t\t: Domain.ActionOf<D, Extract<K, string>>)\n\n/**\n * The data type of the kinds `K`. For `\"*\"` it has no fields.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type DataFor<D, K> = \"*\" extends K\n\t? {}\n\t: Domain.DataOf<D, Extract<K, string>>\n\n/**\n * The value type of the kinds `K`.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type ValueFor<D, K> = \"*\" extends K\n\t? Domain.AnyValue<D>\n\t: Domain.ValueOf<D, Extract<K, string>>\n\n/**\n * A field name or a field pattern of the kinds `K`.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type FieldFor<D, K> =\n\tCondition.FieldPath<DataFor<D, K>> | `${string}*${string}`\n\n/**\n * The options of a rule.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Options<D, K, C extends Condition.Any> {\n\t/** The condition. It gets a builder with the types of the resource. */\n\treadonly when?: (\n\t\tbuilder: Condition.Builder<\n\t\t\tDataFor<D, K>,\n\t\t\tValueFor<D, K>,\n\t\t\tDomain.Principal<D>\n\t\t>,\n\t) => C\n\treadonly fields?: ReadonlyArray<FieldFor<D, K>>\n\treadonly reason?: string\n\treadonly id?: string\n\treadonly meta?: Domain.Meta<D>\n}\n\ntype SingleOrArray<A> = A | ReadonlyArray<A>\n\n/**\n * Makes rules with the types of a domain.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Builder<D> {\n\treadonly allow: <\n\t\tconst T extends Target<D>,\n\t\tconst A extends ActionFor<D, KindOf<T>>,\n\t\tconst C extends Condition.Any = Condition.Condition,\n\t>(\n\t\taction: SingleOrArray<A>,\n\t\tresource: SingleOrArray<T>,\n\t\toptions?: Options<D, KindOf<T>, C>,\n\t) => Rule<Condition.Error<C>, Condition.Services<C>, Condition.OpaqueOf<C>>\n\treadonly deny: <\n\t\tconst T extends Target<D>,\n\t\tconst A extends ActionFor<D, KindOf<T>>,\n\t\tconst C extends Condition.Any = Condition.Condition,\n\t>(\n\t\taction: SingleOrArray<A>,\n\t\tresource: SingleOrArray<T>,\n\t\toptions?: Options<D, KindOf<T>, C>,\n\t) => Rule<Condition.Error<C>, Condition.Services<C>, Condition.OpaqueOf<C>>\n}\n\n/**\n * Makes a rule builder for a domain.\n *\n * @example\n * ```ts\n * const _ = Rule.builder(App)\n * const rule = _.allow(\"read\", Bot, {\n * when: ($) => $.eq(\"ownerUserId\", $.principal(\"userId\")),\n * })\n * ```\n *\n * @stability stable\n * @category constructors\n * @since 0.3.0\n */\nexport const builder: <D extends Domain.Any>(domain: D) => Builder<D> =\n\tinternal.builder\n\n/**\n * Tests if a value is a rule.\n *\n * @stability stable\n * @category guards\n * @since 0.3.0\n */\nexport const isRule: (u: unknown) => u is Any = internal.isRule\n\n/**\n * Tests if a field name matches a field name or a field pattern of a rule.\n *\n * @stability stable\n * @category predicates\n * @since 0.3.0\n */\nexport const matchesField: (pattern: string, field: string) => boolean =\n\tinternal.matchesFieldPattern\n"],"mappings":";;;;;;;;;;;;;;AAkCA,MAAa,SAAkCA;;;;;;;;;;;;;;;;AAkN/C,MAAa,UACZC;;;;;;;;AASD,MAAa,SAAmCC;;;;;;;;AAShD,MAAa,eACZC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// \0rolldown/runtime.js
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __exportAll = (all, no_symbols) => {
|
|
4
4
|
let target = {};
|
|
@@ -9,5 +9,4 @@ var __exportAll = (all, no_symbols) => {
|
|
|
9
9
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
10
|
return target;
|
|
11
11
|
};
|
|
12
|
-
//#endregion
|
|
13
12
|
export { __exportAll };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { Resource_d_exports } from "./Resource.js";
|
|
2
|
+
import { Condition_d_exports } from "./Condition.js";
|
|
3
|
+
import { Principal_d_exports } from "./Principal.js";
|
|
4
|
+
import { Domain_d_exports } from "./Domain.js";
|
|
5
|
+
import { Rule_d_exports } from "./Rule.js";
|
|
6
|
+
import { Decision_d_exports } from "./Decision.js";
|
|
7
|
+
import { Policy_d_exports } from "./Policy.js";
|
|
8
|
+
import { Authorizer_d_exports } from "./Authorizer.js";
|
|
9
|
+
export { Authorizer_d_exports as Authorizer, Condition_d_exports as Condition, Decision_d_exports as Decision, Domain_d_exports as Domain, Policy_d_exports as Policy, Principal_d_exports as Principal, Resource_d_exports as Resource, Rule_d_exports as Rule };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { Decision_exports } from "./Decision.js";
|
|
2
|
+
import { Authorizer_exports } from "./Authorizer.js";
|
|
3
|
+
import { Condition_exports } from "./Condition.js";
|
|
4
|
+
import { Domain_exports } from "./Domain.js";
|
|
5
|
+
import { Policy_exports } from "./Policy.js";
|
|
6
|
+
import { Principal_exports } from "./Principal.js";
|
|
7
|
+
import { Resource_exports } from "./Resource.js";
|
|
8
|
+
import { Rule_exports } from "./Rule.js";
|
|
9
|
+
export { Authorizer_exports as Authorizer, Condition_exports as Condition, Decision_exports as Decision, Domain_exports as Domain, Policy_exports as Policy, Principal_exports as Principal, Resource_exports as Resource, Rule_exports as Rule };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import "../Domain.js";
|
|
2
|
+
import "../Decision.js";
|
|
3
|
+
import "../Policy.js";
|
|
4
|
+
import "../Authorizer.js";
|
|
5
|
+
import "effect/Effect";
|
|
6
|
+
import "effect/Layer";
|
|
7
|
+
import * as Schema from "effect/Schema";
|
|
8
|
+
declare const Forbidden_base: Schema.Class<Forbidden, Schema.TaggedStruct<"Forbidden", {
|
|
9
|
+
readonly action: Schema.String;
|
|
10
|
+
readonly kind: Schema.String;
|
|
11
|
+
readonly field: Schema.optionalKey<Schema.String>;
|
|
12
|
+
readonly reason: Schema.optionalKey<Schema.String>;
|
|
13
|
+
}>, import("effect/Cause").YieldableError>;
|
|
14
|
+
/** @internal */
|
|
15
|
+
export declare class Forbidden extends Forbidden_base {}
|
|
16
|
+
declare const PolicyUnavailable_base: Schema.Class<PolicyUnavailable, Schema.TaggedStruct<"PolicyUnavailable", {
|
|
17
|
+
readonly cause: Schema.Defect;
|
|
18
|
+
}>, import("effect/Cause").YieldableError>;
|
|
19
|
+
/** @internal */
|
|
20
|
+
export declare class PolicyUnavailable extends PolicyUnavailable_base {}
|
|
21
|
+
declare const Pending_base: Schema.Class<Pending, Schema.TaggedStruct<"Pending", {
|
|
22
|
+
readonly ticket: Schema.String;
|
|
23
|
+
readonly reason: Schema.optionalKey<Schema.String>;
|
|
24
|
+
}>, import("effect/Cause").YieldableError>;
|
|
25
|
+
/** @internal */
|
|
26
|
+
export declare class Pending extends Pending_base {}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=authorizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorizer.d.ts","names":[],"sources":["../../src/internal/authorizer.ts"],"mappings":";;;;;;;;;;;;;;qBAqBa,kBAAkB;;;;;qBAUlB,0BAA0B;;;;;;qBAK1B,gBAAgB"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Allow, Deny, NotApplicable, reason } from "../Decision.js";
|
|
2
|
+
import { kindOf } from "./domain.js";
|
|
3
|
+
import { decideOf, permittedFieldsOf, residualOf, residualPair } from "./policy.js";
|
|
4
|
+
import * as Cache from "effect/Cache";
|
|
5
|
+
import * as Context from "effect/Context";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as Equal from "effect/Equal";
|
|
8
|
+
import * as Hash from "effect/Hash";
|
|
9
|
+
import * as Layer from "effect/Layer";
|
|
10
|
+
import * as Schema from "effect/Schema";
|
|
11
|
+
// src/internal/authorizer.ts
|
|
12
|
+
/** @internal */
|
|
13
|
+
var Forbidden = class extends Schema.TaggedError("@nmnmcc/ability/Authorizer/Forbidden")("Forbidden", {
|
|
14
|
+
action: Schema.String,
|
|
15
|
+
kind: Schema.String,
|
|
16
|
+
field: Schema.optionalKey(Schema.String),
|
|
17
|
+
reason: Schema.optionalKey(Schema.String)
|
|
18
|
+
}) {};
|
|
19
|
+
/** @internal */
|
|
20
|
+
var PolicyUnavailable = class extends Schema.TaggedError("@nmnmcc/ability/Authorizer/PolicyUnavailable")("PolicyUnavailable", { cause: Schema.Defect() }) {};
|
|
21
|
+
/** @internal */
|
|
22
|
+
var Pending = class extends Schema.TaggedError("@nmnmcc/ability/Authorizer/Pending")("Pending", {
|
|
23
|
+
ticket: Schema.String,
|
|
24
|
+
reason: Schema.optionalKey(Schema.String)
|
|
25
|
+
}) {};
|
|
26
|
+
/** @internal */
|
|
27
|
+
const Service = () => (id, domain) => {
|
|
28
|
+
const Base = Context.Service()(id);
|
|
29
|
+
return class extends Base {
|
|
30
|
+
static domain = domain;
|
|
31
|
+
static decide = (target) => this.use((service) => service.decide(target));
|
|
32
|
+
static check = (target) => this.use((service) => service.check(target));
|
|
33
|
+
static guard = (target, options) => this.use((service) => service.guard(target, options));
|
|
34
|
+
static filter = (target) => this.use((service) => service.filter(target));
|
|
35
|
+
static permittedFields = (target) => this.use((service) => service.permittedFields(target));
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A cache key for a principal. Two principals with the same encoded value are
|
|
40
|
+
* the same key.
|
|
41
|
+
*/
|
|
42
|
+
var PrincipalKey = class PrincipalKey {
|
|
43
|
+
principal;
|
|
44
|
+
json;
|
|
45
|
+
constructor(principal, json) {
|
|
46
|
+
this.principal = principal;
|
|
47
|
+
this.json = json;
|
|
48
|
+
}
|
|
49
|
+
[Equal.symbol](that) {
|
|
50
|
+
return that instanceof PrincipalKey && that.json === this.json;
|
|
51
|
+
}
|
|
52
|
+
[Hash.symbol]() {
|
|
53
|
+
return Hash.string(this.json);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const forbidden = (target, kind, reason) => Forbidden.make({
|
|
57
|
+
action: target.action,
|
|
58
|
+
kind,
|
|
59
|
+
...target.field === void 0 ? {} : { field: target.field },
|
|
60
|
+
...reason === void 0 ? {} : { reason }
|
|
61
|
+
});
|
|
62
|
+
/** @internal */
|
|
63
|
+
const layer = (service, options) => {
|
|
64
|
+
const domain = service.domain;
|
|
65
|
+
const encode = Schema.encodeUnknownSync(domain.principal);
|
|
66
|
+
const keyOf = (principal) => new PrincipalKey(principal, JSON.stringify(encode(principal)));
|
|
67
|
+
return Layer.effect(service, Effect.gen(function* () {
|
|
68
|
+
const services = yield* Effect.context();
|
|
69
|
+
const load = (principal) => options.policy(principal).pipe(Effect.provideContext(services), Effect.mapError((cause) => PolicyUnavailable.make({ cause })));
|
|
70
|
+
const cache = options.cache === false ? void 0 : yield* Cache.make({
|
|
71
|
+
capacity: options.cache?.capacity ?? 1e3,
|
|
72
|
+
timeToLive: options.cache?.timeToLive ?? "30 seconds",
|
|
73
|
+
lookup: (key) => load(key.principal)
|
|
74
|
+
});
|
|
75
|
+
const policyFor = (principal) => {
|
|
76
|
+
if (cache === void 0) return load(principal);
|
|
77
|
+
const key = keyOf(principal);
|
|
78
|
+
return Cache.get(cache, key).pipe(Effect.tapError(() => Cache.invalidate(cache, key)));
|
|
79
|
+
};
|
|
80
|
+
const withServices = (effect) => Effect.provideContext(effect, services);
|
|
81
|
+
const current = Effect.gen(function* () {
|
|
82
|
+
const principal = yield* options.principal;
|
|
83
|
+
return {
|
|
84
|
+
principal,
|
|
85
|
+
policy: yield* policyFor(principal)
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
const decide = Effect.fnUntraced(function* (target) {
|
|
89
|
+
const { principal, policy: value } = yield* current;
|
|
90
|
+
return yield* withServices(decideOf(value, {
|
|
91
|
+
...target,
|
|
92
|
+
principal
|
|
93
|
+
}));
|
|
94
|
+
});
|
|
95
|
+
const kindDecision = (value, principal, target) => {
|
|
96
|
+
const pair = residualPair(value, {
|
|
97
|
+
...target,
|
|
98
|
+
principal
|
|
99
|
+
});
|
|
100
|
+
if (pair.allow._tag === "True") return Allow({});
|
|
101
|
+
if (pair.deny._tag === "True") return Deny({});
|
|
102
|
+
return NotApplicable;
|
|
103
|
+
};
|
|
104
|
+
const check = Effect.fnUntraced(function* (target) {
|
|
105
|
+
const { principal, policy: value } = yield* current;
|
|
106
|
+
const kind = target.resource === void 0 ? target.kind ?? "" : kindOf(target.resource) ?? "";
|
|
107
|
+
let decision = target.resource === void 0 ? kindDecision(value, principal, target) : yield* withServices(decideOf(value, {
|
|
108
|
+
...target,
|
|
109
|
+
principal
|
|
110
|
+
}));
|
|
111
|
+
if (decision._tag === "NotApplicable" && options.decider !== void 0) decision = yield* options.decider({
|
|
112
|
+
...target,
|
|
113
|
+
principal
|
|
114
|
+
});
|
|
115
|
+
if (decision._tag !== "Allow") return yield* forbidden(target, kind, reason(decision));
|
|
116
|
+
});
|
|
117
|
+
const guard = Effect.fnUntraced(function* (target, guardOptions) {
|
|
118
|
+
const read = guardOptions.read ?? "read";
|
|
119
|
+
const { field: _field, ...rest } = target;
|
|
120
|
+
if ((yield* decide({
|
|
121
|
+
...rest,
|
|
122
|
+
action: read
|
|
123
|
+
}))._tag !== "Allow") return yield* Effect.fail(guardOptions.hide());
|
|
124
|
+
if (target.action !== read || target.field !== void 0) yield* check(target);
|
|
125
|
+
});
|
|
126
|
+
const filter = (target) => Effect.map(current, ({ principal, policy: value }) => residualOf(value, {
|
|
127
|
+
...target,
|
|
128
|
+
principal
|
|
129
|
+
}));
|
|
130
|
+
const permittedFields = Effect.fnUntraced(function* (target) {
|
|
131
|
+
const { principal, policy: value } = yield* current;
|
|
132
|
+
return yield* withServices(permittedFieldsOf(value, {
|
|
133
|
+
...target,
|
|
134
|
+
principal
|
|
135
|
+
}));
|
|
136
|
+
});
|
|
137
|
+
const invalidate = (principal) => cache === void 0 ? Effect.void : principal === void 0 ? Cache.invalidateAll(cache) : Cache.invalidate(cache, keyOf(principal));
|
|
138
|
+
return {
|
|
139
|
+
domain,
|
|
140
|
+
principal: options.principal,
|
|
141
|
+
policy: Effect.map(current, ({ policy: value }) => value),
|
|
142
|
+
decide,
|
|
143
|
+
check,
|
|
144
|
+
guard,
|
|
145
|
+
filter,
|
|
146
|
+
permittedFields,
|
|
147
|
+
invalidate
|
|
148
|
+
};
|
|
149
|
+
}));
|
|
150
|
+
};
|
|
151
|
+
export { Forbidden, Pending, PolicyUnavailable, Service, layer };
|
|
152
|
+
|
|
153
|
+
//# sourceMappingURL=authorizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorizer.js","names":["policy.decideOf","policy.residualPair","Decision.Allow","Decision.Deny","Decision.NotApplicable","Decision.reason","policy.residualOf","policy.permittedFieldsOf"],"sources":["../../src/internal/authorizer.ts"],"sourcesContent":["// The service erases the error type and the service type of predicates,\n// principals and deciders to `unknown`. The public types in\n// `src/Authorizer.ts` keep them, so the language service check for `unknown`\n// in an Effect is off here.\n// @effect-diagnostics anyUnknownInErrorContext:off\nimport * as Cache from \"effect/Cache\"\nimport * as Context from \"effect/Context\"\nimport * as Effect from \"effect/Effect\"\nimport * as Equal from \"effect/Equal\"\nimport * as Hash from \"effect/Hash\"\nimport * as Layer from \"effect/Layer\"\nimport * as Schema from \"effect/Schema\"\nimport type * as Authorizer from \"../Authorizer.ts\"\nimport type * as Condition from \"../Condition.ts\"\nimport * as Decision from \"../Decision.ts\"\nimport type * as Domain from \"../Domain.ts\"\nimport type * as Policy from \"../Policy.ts\"\nimport { kindOf } from \"./domain.ts\"\nimport * as policy from \"./policy.ts\"\n\n/** @internal */\nexport class Forbidden extends Schema.TaggedError<Forbidden>(\n\t\"@nmnmcc/ability/Authorizer/Forbidden\",\n)(\"Forbidden\", {\n\taction: Schema.String,\n\tkind: Schema.String,\n\tfield: Schema.optionalKey(Schema.String),\n\treason: Schema.optionalKey(Schema.String),\n}) {}\n\n/** @internal */\nexport class PolicyUnavailable extends Schema.TaggedError<PolicyUnavailable>(\n\t\"@nmnmcc/ability/Authorizer/PolicyUnavailable\",\n)(\"PolicyUnavailable\", { cause: Schema.Defect() }) {}\n\n/** @internal */\nexport class Pending extends Schema.TaggedError<Pending>(\n\t\"@nmnmcc/ability/Authorizer/Pending\",\n)(\"Pending\", {\n\tticket: Schema.String,\n\treason: Schema.optionalKey(Schema.String),\n}) {}\n\ntype AnyTarget = {\n\treadonly action: string\n\treadonly resource?: object\n\treadonly kind?: string\n\treadonly field?: string\n}\n\n/** @internal */\nexport const Service =\n\t() =>\n\t(id: string, domain: Domain.Any): Authorizer.AnyServiceClass => {\n\t\tconst Base = Context.Service<any, any>()(id)\n\t\treturn class extends Base {\n\t\t\tstatic readonly domain = domain\n\t\t\tstatic readonly decide = (target: AnyTarget) =>\n\t\t\t\tthis.use((service: any) => service.decide(target))\n\t\t\tstatic readonly check = (target: AnyTarget) =>\n\t\t\t\tthis.use((service: any) => service.check(target))\n\t\t\tstatic readonly guard = (target: AnyTarget, options: unknown) =>\n\t\t\t\tthis.use((service: any) => service.guard(target, options))\n\t\t\tstatic readonly filter = (target: AnyTarget) =>\n\t\t\t\tthis.use((service: any) => service.filter(target))\n\t\t\tstatic readonly permittedFields = (target: AnyTarget) =>\n\t\t\t\tthis.use((service: any) => service.permittedFields(target))\n\t\t} as never\n\t}\n\n/**\n * A cache key for a principal. Two principals with the same encoded value are\n * the same key.\n */\nclass PrincipalKey implements Equal.Equal {\n\treadonly principal: object\n\treadonly json: string\n\tconstructor(principal: object, json: string) {\n\t\tthis.principal = principal\n\t\tthis.json = json\n\t}\n\t[Equal.symbol](that: unknown): boolean {\n\t\treturn that instanceof PrincipalKey && that.json === this.json\n\t}\n\t[Hash.symbol](): number {\n\t\treturn Hash.string(this.json)\n\t}\n}\n\nconst forbidden = (\n\ttarget: AnyTarget,\n\tkind: string,\n\treason: string | undefined,\n): Forbidden =>\n\tForbidden.make({\n\t\taction: target.action,\n\t\tkind,\n\t\t...(target.field === undefined ? {} : { field: target.field }),\n\t\t...(reason === undefined ? {} : { reason }),\n\t})\n\n/** @internal */\nexport const layer = (\n\tservice: Authorizer.AnyServiceClass,\n\toptions: {\n\t\treadonly principal: Effect.Effect<object, unknown, unknown>\n\t\treadonly policy: (\n\t\t\tprincipal: object,\n\t\t) => Effect.Effect<Policy.Any, unknown, unknown>\n\t\treadonly decider?: (\n\t\t\trequest: object,\n\t\t) => Effect.Effect<Decision.Decision, unknown, unknown>\n\t\treadonly cache?:\n\t\t\t{ readonly capacity?: number; readonly timeToLive?: any } | false\n\t},\n) => {\n\tconst domain: Domain.Any = service.domain\n\tconst encode = Schema.encodeUnknownSync(\n\t\tdomain.principal as unknown as Schema.Codec<unknown, unknown>,\n\t)\n\tconst keyOf = (principal: object) =>\n\t\tnew PrincipalKey(principal, JSON.stringify(encode(principal)))\n\treturn Layer.effect(\n\t\tservice,\n\t\tEffect.gen(function* () {\n\t\t\t// The services of the policy loader and of the predicates come from the\n\t\t\t// layer, so a check does not need them.\n\t\t\tconst services = yield* Effect.context<never>()\n\n\t\t\tconst load = (principal: object) =>\n\t\t\t\toptions.policy(principal).pipe(\n\t\t\t\t\tEffect.provideContext(services),\n\t\t\t\t\tEffect.mapError((cause) => PolicyUnavailable.make({ cause })),\n\t\t\t\t)\n\n\t\t\tconst cache =\n\t\t\t\toptions.cache === false\n\t\t\t\t\t? undefined\n\t\t\t\t\t: yield* Cache.make({\n\t\t\t\t\t\t\tcapacity: options.cache?.capacity ?? 1000,\n\t\t\t\t\t\t\ttimeToLive: options.cache?.timeToLive ?? \"30 seconds\",\n\t\t\t\t\t\t\tlookup: (key: PrincipalKey) => load(key.principal),\n\t\t\t\t\t\t})\n\n\t\t\tconst policyFor = (principal: object) => {\n\t\t\t\tif (cache === undefined) {\n\t\t\t\t\treturn load(principal)\n\t\t\t\t}\n\t\t\t\tconst key = keyOf(principal)\n\t\t\t\t// A failed lookup is kept in the cache. Remove it, so the next check\n\t\t\t\t// tries again.\n\t\t\t\treturn Cache.get(cache, key).pipe(\n\t\t\t\t\tEffect.tapError(() => Cache.invalidate(cache, key)),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst withServices = <A, E>(\n\t\t\t\teffect: Effect.Effect<A, E, unknown>,\n\t\t\t): Effect.Effect<A, E, unknown> => Effect.provideContext(effect, services)\n\n\t\t\tconst current = Effect.gen(function* () {\n\t\t\t\tconst principal = yield* options.principal\n\t\t\t\tconst value = yield* policyFor(principal)\n\t\t\t\treturn { principal, policy: value }\n\t\t\t})\n\n\t\t\tconst decide = Effect.fnUntraced(function* (target: AnyTarget) {\n\t\t\t\tconst { principal, policy: value } = yield* current\n\t\t\t\tconst decision: Decision.Decision = yield* withServices(\n\t\t\t\t\tpolicy.decideOf(value, { ...target, principal } as never),\n\t\t\t\t)\n\t\t\t\treturn decision\n\t\t\t})\n\n\t\t\tconst kindDecision = (\n\t\t\t\tvalue: Policy.Any,\n\t\t\t\tprincipal: object,\n\t\t\t\ttarget: AnyTarget,\n\t\t\t): Decision.Decision => {\n\t\t\t\tconst pair = policy.residualPair(value, {\n\t\t\t\t\t...target,\n\t\t\t\t\tprincipal,\n\t\t\t\t} as never)\n\t\t\t\tif (pair.allow._tag === \"True\") {\n\t\t\t\t\treturn Decision.Allow({})\n\t\t\t\t}\n\t\t\t\tif (pair.deny._tag === \"True\") {\n\t\t\t\t\treturn Decision.Deny({})\n\t\t\t\t}\n\t\t\t\treturn Decision.NotApplicable\n\t\t\t}\n\n\t\t\tconst check = Effect.fnUntraced(function* (target: AnyTarget) {\n\t\t\t\tconst { principal, policy: value } = yield* current\n\t\t\t\tconst kind =\n\t\t\t\t\ttarget.resource === undefined\n\t\t\t\t\t\t? (target.kind ?? \"\")\n\t\t\t\t\t\t: (kindOf(target.resource) ?? \"\")\n\t\t\t\tlet decision: Decision.Decision =\n\t\t\t\t\ttarget.resource === undefined\n\t\t\t\t\t\t? kindDecision(value, principal, target)\n\t\t\t\t\t\t: yield* withServices(\n\t\t\t\t\t\t\t\tpolicy.decideOf(value, { ...target, principal } as never),\n\t\t\t\t\t\t\t)\n\t\t\t\tif (\n\t\t\t\t\tdecision._tag === \"NotApplicable\" &&\n\t\t\t\t\toptions.decider !== undefined\n\t\t\t\t) {\n\t\t\t\t\tdecision = yield* options.decider({ ...target, principal })\n\t\t\t\t}\n\t\t\t\tif (decision._tag !== \"Allow\") {\n\t\t\t\t\treturn yield* forbidden(target, kind, Decision.reason(decision))\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tconst guard = Effect.fnUntraced(function* (\n\t\t\t\ttarget: AnyTarget,\n\t\t\t\tguardOptions: {\n\t\t\t\t\treadonly read?: string\n\t\t\t\t\treadonly hide: () => unknown\n\t\t\t\t},\n\t\t\t) {\n\t\t\t\tconst read = guardOptions.read ?? \"read\"\n\t\t\t\tconst { field: _field, ...rest } = target\n\t\t\t\tconst visible: Decision.Decision = yield* decide({\n\t\t\t\t\t...rest,\n\t\t\t\t\taction: read,\n\t\t\t\t})\n\t\t\t\tif (visible._tag !== \"Allow\") {\n\t\t\t\t\treturn yield* Effect.fail(guardOptions.hide())\n\t\t\t\t}\n\t\t\t\tif (target.action !== read || target.field !== undefined) {\n\t\t\t\t\tyield* check(target)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tconst filter = (\n\t\t\t\ttarget: AnyTarget,\n\t\t\t): Effect.Effect<Condition.Ast, unknown, unknown> =>\n\t\t\t\tEffect.map(current, ({ principal, policy: value }) =>\n\t\t\t\t\tpolicy.residualOf(value, { ...target, principal } as never),\n\t\t\t\t)\n\n\t\t\tconst permittedFields = Effect.fnUntraced(function* (target: AnyTarget) {\n\t\t\t\tconst { principal, policy: value } = yield* current\n\t\t\t\treturn yield* withServices(\n\t\t\t\t\tpolicy.permittedFieldsOf(value, { ...target, principal } as never),\n\t\t\t\t)\n\t\t\t})\n\n\t\t\tconst invalidate = (principal?: object) =>\n\t\t\t\tcache === undefined\n\t\t\t\t\t? Effect.void\n\t\t\t\t\t: principal === undefined\n\t\t\t\t\t\t? Cache.invalidateAll(cache)\n\t\t\t\t\t\t: Cache.invalidate(cache, keyOf(principal))\n\n\t\t\treturn {\n\t\t\t\tdomain,\n\t\t\t\tprincipal: options.principal,\n\t\t\t\tpolicy: Effect.map(current, ({ policy: value }) => value),\n\t\t\t\tdecide,\n\t\t\t\tcheck,\n\t\t\t\tguard,\n\t\t\t\tfilter,\n\t\t\t\tpermittedFields,\n\t\t\t\tinvalidate,\n\t\t\t} as never\n\t\t}),\n\t)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "../Resource.js";
|
|
2
|
+
import "../Condition.js";
|
|
3
|
+
import "effect/Effect";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
5
|
+
declare const Untranslatable_base: Schema.Class<Untranslatable, Schema.TaggedStruct<"Untranslatable", {
|
|
6
|
+
readonly reason: Schema.String;
|
|
7
|
+
}>, import("effect/Cause").YieldableError>;
|
|
8
|
+
/** @internal */
|
|
9
|
+
export declare class Untranslatable extends Untranslatable_base {}
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=condition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"condition.d.ts","names":[],"sources":["../../src/internal/condition.ts"],"mappings":";;;;;;;;qBAwda,uBAAuB"}
|