@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/src/Resource.ts
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A resource is a kind of thing that a person may act on, such as a Bot or a
|
|
3
|
+
* document. Each resource has a kind name, a list of actions, a Schema for its
|
|
4
|
+
* data, and an optional path.
|
|
5
|
+
*
|
|
6
|
+
* Make a resource in one of two ways:
|
|
7
|
+
* - {@link Class} makes a Schema class, in the same way as
|
|
8
|
+
* `Schema.TaggedClass`. The class is a Schema, a constructor, and a resource
|
|
9
|
+
* at the same time.
|
|
10
|
+
* - {@link make} makes a resource from plain fields. Its values are plain
|
|
11
|
+
* objects with a `_tag` field.
|
|
12
|
+
*
|
|
13
|
+
* Every value of a resource has a `_tag` field with the kind name. The library
|
|
14
|
+
* uses this field to find the resource of a value. It does not guess from the
|
|
15
|
+
* constructor name.
|
|
16
|
+
*
|
|
17
|
+
* A path puts a resource inside a tree, such as
|
|
18
|
+
* `["org", organizationId, "user", ownerUserId, "bot", id]`. A condition can
|
|
19
|
+
* then ask if a value is under a part of the tree. See `Condition.under`.
|
|
20
|
+
*
|
|
21
|
+
* @stability stable
|
|
22
|
+
* @since 0.3.0
|
|
23
|
+
*/
|
|
24
|
+
import * as Schema from "effect/Schema"
|
|
25
|
+
import * as internal from "./internal/resource.ts"
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @stability stable
|
|
29
|
+
* @category type IDs
|
|
30
|
+
* @since 0.3.0
|
|
31
|
+
*/
|
|
32
|
+
export const TypeId: "~@nmnmcc/ability/Resource" = internal.TypeId
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @stability stable
|
|
36
|
+
* @category type IDs
|
|
37
|
+
* @since 0.3.0
|
|
38
|
+
*/
|
|
39
|
+
export type TypeId = typeof TypeId
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* One part of a resource path. A string is a fixed part. A field reference
|
|
43
|
+
* takes the part from a field of the value.
|
|
44
|
+
*
|
|
45
|
+
* @stability stable
|
|
46
|
+
* @category models
|
|
47
|
+
* @since 0.3.0
|
|
48
|
+
*/
|
|
49
|
+
export type PathSegment = string | FieldRef<string>
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A reference to a top-level field of a resource, used in a path.
|
|
53
|
+
*
|
|
54
|
+
* @stability stable
|
|
55
|
+
* @category models
|
|
56
|
+
* @since 0.3.0
|
|
57
|
+
*/
|
|
58
|
+
export interface FieldRef<Name extends string> {
|
|
59
|
+
readonly _tag: "Field"
|
|
60
|
+
readonly field: Name
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The runtime data of a resource.
|
|
65
|
+
*
|
|
66
|
+
* @stability stable
|
|
67
|
+
* @category models
|
|
68
|
+
* @since 0.3.0
|
|
69
|
+
*/
|
|
70
|
+
export interface Descriptor {
|
|
71
|
+
readonly kind: string
|
|
72
|
+
readonly actions: ReadonlyArray<string>
|
|
73
|
+
readonly path: ReadonlyArray<PathSegment> | undefined
|
|
74
|
+
/** The paths of the data fields, with dots for nested fields. */
|
|
75
|
+
readonly fieldPaths: ReadonlyArray<string>
|
|
76
|
+
/** The Schema of the values, with the `_tag` field. */
|
|
77
|
+
readonly schema: Schema.Top
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A resource. `Kind` is its name, `Action` is the union of its actions, `Data`
|
|
82
|
+
* is the type of its Schema fields, and `Value` is the type of its values.
|
|
83
|
+
*
|
|
84
|
+
* @stability stable
|
|
85
|
+
* @category models
|
|
86
|
+
* @since 0.3.0
|
|
87
|
+
*/
|
|
88
|
+
export interface Resource<
|
|
89
|
+
Kind extends string,
|
|
90
|
+
Action extends string,
|
|
91
|
+
Data extends object,
|
|
92
|
+
Value extends { readonly _tag: Kind },
|
|
93
|
+
> {
|
|
94
|
+
readonly [TypeId]: Descriptor
|
|
95
|
+
readonly "~Resource"?: {
|
|
96
|
+
readonly Kind: Kind
|
|
97
|
+
readonly Action: Action
|
|
98
|
+
readonly Data: Data
|
|
99
|
+
readonly Value: Value
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Any resource.
|
|
105
|
+
*
|
|
106
|
+
* @stability stable
|
|
107
|
+
* @category models
|
|
108
|
+
* @since 0.3.0
|
|
109
|
+
*/
|
|
110
|
+
export type Any = Resource<string, string, object, { readonly _tag: string }>
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The kind name of a resource.
|
|
114
|
+
*
|
|
115
|
+
* @stability stable
|
|
116
|
+
* @category utility types
|
|
117
|
+
* @since 0.3.0
|
|
118
|
+
*/
|
|
119
|
+
export type Kind<R> = R extends Resource<infer K, any, any, any> ? K : never
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The actions of a resource.
|
|
123
|
+
*
|
|
124
|
+
* @stability stable
|
|
125
|
+
* @category utility types
|
|
126
|
+
* @since 0.3.0
|
|
127
|
+
*/
|
|
128
|
+
export type Action<R> = R extends Resource<any, infer A, any, any> ? A : never
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The type of the Schema fields of a resource, without `_tag`.
|
|
132
|
+
*
|
|
133
|
+
* @stability stable
|
|
134
|
+
* @category utility types
|
|
135
|
+
* @since 0.3.0
|
|
136
|
+
*/
|
|
137
|
+
export type Data<R> = R extends Resource<any, any, infer D, any> ? D : never
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The type of the values of a resource.
|
|
141
|
+
*
|
|
142
|
+
* @stability stable
|
|
143
|
+
* @category utility types
|
|
144
|
+
* @since 0.3.0
|
|
145
|
+
*/
|
|
146
|
+
export type Value<R> = R extends Resource<any, any, any, infer V> ? V : never
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The options of a resource.
|
|
150
|
+
*
|
|
151
|
+
* @stability stable
|
|
152
|
+
* @category models
|
|
153
|
+
* @since 0.3.0
|
|
154
|
+
*/
|
|
155
|
+
export interface Options<
|
|
156
|
+
Actions extends ReadonlyArray<string>,
|
|
157
|
+
Fields extends Schema.Struct.Fields,
|
|
158
|
+
> {
|
|
159
|
+
readonly actions: Actions
|
|
160
|
+
readonly fields: Fields
|
|
161
|
+
/**
|
|
162
|
+
* Gives the path of the resource. The function gets one reference for each
|
|
163
|
+
* top-level field.
|
|
164
|
+
*/
|
|
165
|
+
readonly path?: (fields: {
|
|
166
|
+
readonly [K in keyof Fields & string]: FieldRef<K>
|
|
167
|
+
}) => ReadonlyArray<PathSegment>
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The type of a class made by {@link Class}.
|
|
172
|
+
*
|
|
173
|
+
* @stability stable
|
|
174
|
+
* @category models
|
|
175
|
+
* @since 0.3.0
|
|
176
|
+
*/
|
|
177
|
+
export type Class<
|
|
178
|
+
Self,
|
|
179
|
+
Kind extends string,
|
|
180
|
+
Actions extends ReadonlyArray<string>,
|
|
181
|
+
Fields extends Schema.Struct.Fields,
|
|
182
|
+
> = Schema.Class<Self, Schema.TaggedStruct<Kind, Fields>, {}> &
|
|
183
|
+
Resource<
|
|
184
|
+
Kind,
|
|
185
|
+
Actions[number],
|
|
186
|
+
Schema.Struct.Type<Fields>,
|
|
187
|
+
Self & { readonly _tag: Kind }
|
|
188
|
+
> & {
|
|
189
|
+
readonly kind: Kind
|
|
190
|
+
readonly actions: Actions
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Makes a resource as a Schema class. Use it in the same way as
|
|
195
|
+
* `Schema.TaggedClass`.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* import { Schema } from "effect"
|
|
200
|
+
* import { Resource } from "@nmnmcc/ability"
|
|
201
|
+
*
|
|
202
|
+
* class Bot extends Resource.Class<Bot>()("Bot", {
|
|
203
|
+
* actions: ["read", "update"],
|
|
204
|
+
* fields: {
|
|
205
|
+
* id: Schema.String,
|
|
206
|
+
* ownerUserId: Schema.NullOr(Schema.String),
|
|
207
|
+
* },
|
|
208
|
+
* path: (f) => ["user", f.ownerUserId, "bot", f.id],
|
|
209
|
+
* }) {}
|
|
210
|
+
*
|
|
211
|
+
* const bot = new Bot({ id: "b1", ownerUserId: "u1" })
|
|
212
|
+
* ```
|
|
213
|
+
*
|
|
214
|
+
* @stability stable
|
|
215
|
+
* @category constructors
|
|
216
|
+
* @since 0.3.0
|
|
217
|
+
*/
|
|
218
|
+
export const Class: <Self = never>(
|
|
219
|
+
identifier?: string,
|
|
220
|
+
) => <
|
|
221
|
+
const Kind extends string,
|
|
222
|
+
const Actions extends ReadonlyArray<string>,
|
|
223
|
+
const Fields extends Schema.Struct.Fields,
|
|
224
|
+
>(
|
|
225
|
+
kind: Kind,
|
|
226
|
+
options: Options<Actions, Fields>,
|
|
227
|
+
) => [Self] extends [never]
|
|
228
|
+
? "Missing `Self` type: use Resource.Class<Self>()(...)"
|
|
229
|
+
: Class<Self, Kind, Actions, Fields> = internal.Class as never
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* A resource made by {@link make}. Its values are plain objects.
|
|
233
|
+
*
|
|
234
|
+
* @stability stable
|
|
235
|
+
* @category models
|
|
236
|
+
* @since 0.3.0
|
|
237
|
+
*/
|
|
238
|
+
export interface Struct<
|
|
239
|
+
Kind extends string,
|
|
240
|
+
Actions extends ReadonlyArray<string>,
|
|
241
|
+
Fields extends Schema.Struct.Fields,
|
|
242
|
+
> extends Resource<
|
|
243
|
+
Kind,
|
|
244
|
+
Actions[number],
|
|
245
|
+
Schema.Struct.Type<Fields>,
|
|
246
|
+
Schema.Struct.Type<Fields> & { readonly _tag: Kind }
|
|
247
|
+
> {
|
|
248
|
+
readonly kind: Kind
|
|
249
|
+
readonly actions: Actions
|
|
250
|
+
readonly schema: Schema.TaggedStruct<Kind, Fields>
|
|
251
|
+
/** Makes a value. It puts the `_tag` field on the value for you. */
|
|
252
|
+
readonly make: (
|
|
253
|
+
input: Schema.Struct.Type<Fields>,
|
|
254
|
+
) => Schema.Struct.Type<Fields> & { readonly _tag: Kind }
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Makes a resource from plain fields. Its values are plain objects with a
|
|
259
|
+
* `_tag` field.
|
|
260
|
+
*
|
|
261
|
+
* @stability stable
|
|
262
|
+
* @category constructors
|
|
263
|
+
* @since 0.3.0
|
|
264
|
+
*/
|
|
265
|
+
export const make: <
|
|
266
|
+
const Kind extends string,
|
|
267
|
+
const Actions extends ReadonlyArray<string>,
|
|
268
|
+
const Fields extends Schema.Struct.Fields,
|
|
269
|
+
>(
|
|
270
|
+
kind: Kind,
|
|
271
|
+
options: Options<Actions, Fields>,
|
|
272
|
+
) => Struct<Kind, Actions, Fields> = internal.make as never
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Tests if a value is a resource.
|
|
276
|
+
*
|
|
277
|
+
* @stability stable
|
|
278
|
+
* @category guards
|
|
279
|
+
* @since 0.3.0
|
|
280
|
+
*/
|
|
281
|
+
export const isResource: (u: unknown) => u is Any = internal.isResource
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Gets the runtime data of a resource.
|
|
285
|
+
*
|
|
286
|
+
* @stability stable
|
|
287
|
+
* @category getters
|
|
288
|
+
* @since 0.3.0
|
|
289
|
+
*/
|
|
290
|
+
export const descriptor: (resource: Any) => Descriptor = internal.descriptor
|
package/src/Rule.ts
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rule says that a principal may (`Allow`) or may not (`Deny`) do some
|
|
3
|
+
* actions on some resources. A rule may have:
|
|
4
|
+
* - a condition, which must be true for the rule to apply;
|
|
5
|
+
* - a list of fields, for rules about parts of a resource;
|
|
6
|
+
* - a reason, an id, and extra data (`meta`).
|
|
7
|
+
*
|
|
8
|
+
* Rules do not change, and two rules with the same data are equal. A rule
|
|
9
|
+
* works in a generator, so you can write `yield* _.allow(...)` inside
|
|
10
|
+
* `Policy.define`.
|
|
11
|
+
*
|
|
12
|
+
* The action `"*"` means every action. The resource `"*"` means every
|
|
13
|
+
* resource.
|
|
14
|
+
*
|
|
15
|
+
* Field names in a rule may have patterns. `*` stands for any part of one
|
|
16
|
+
* field name, and `**` stands for any number of parts. So `address.*` covers
|
|
17
|
+
* `address.city`, and `**` covers every field.
|
|
18
|
+
*
|
|
19
|
+
* @stability stable
|
|
20
|
+
* @since 0.3.0
|
|
21
|
+
*/
|
|
22
|
+
import type * as Equal from "effect/Equal"
|
|
23
|
+
import type * as Inspectable from "effect/Inspectable"
|
|
24
|
+
import type * as Pipeable from "effect/Pipeable"
|
|
25
|
+
import type * as Condition from "./Condition.ts"
|
|
26
|
+
import type * as Domain from "./Domain.ts"
|
|
27
|
+
import * as internal from "./internal/rule.ts"
|
|
28
|
+
import type * as Resource from "./Resource.ts"
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @stability stable
|
|
32
|
+
* @category type IDs
|
|
33
|
+
* @since 0.3.0
|
|
34
|
+
*/
|
|
35
|
+
export const TypeId: "~@nmnmcc/ability/Rule" = internal.TypeId
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @stability stable
|
|
39
|
+
* @category type IDs
|
|
40
|
+
* @since 0.3.0
|
|
41
|
+
*/
|
|
42
|
+
export type TypeId = typeof TypeId
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A rule. `E`, `R` and `O` come from its condition. See
|
|
46
|
+
* `Condition.Condition`.
|
|
47
|
+
*
|
|
48
|
+
* @stability stable
|
|
49
|
+
* @category models
|
|
50
|
+
* @since 0.3.0
|
|
51
|
+
*/
|
|
52
|
+
export interface Rule<E = never, R = never, O = never>
|
|
53
|
+
extends Equal.Equal, Inspectable.Inspectable, Pipeable.Pipeable {
|
|
54
|
+
readonly [TypeId]: TypeId
|
|
55
|
+
readonly _tag: "Allow" | "Deny"
|
|
56
|
+
readonly actions: ReadonlyArray<string>
|
|
57
|
+
readonly resources: ReadonlyArray<string>
|
|
58
|
+
readonly when?: Condition.Ast
|
|
59
|
+
readonly fields?: ReadonlyArray<string>
|
|
60
|
+
readonly reason?: string
|
|
61
|
+
readonly id?: string
|
|
62
|
+
readonly meta?: unknown
|
|
63
|
+
readonly "~Rule"?: Condition.Variance<E, R, O>
|
|
64
|
+
[Symbol.iterator](): Generator<Rule<E, R, O>, Rule<E, R, O>, unknown>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Any rule.
|
|
69
|
+
*
|
|
70
|
+
* @stability stable
|
|
71
|
+
* @category models
|
|
72
|
+
* @since 0.3.0
|
|
73
|
+
*/
|
|
74
|
+
export type Any = Rule<any, any, any>
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The error type of a rule.
|
|
78
|
+
*
|
|
79
|
+
* @stability stable
|
|
80
|
+
* @category utility types
|
|
81
|
+
* @since 0.3.0
|
|
82
|
+
*/
|
|
83
|
+
export type Error<A> = A extends {
|
|
84
|
+
readonly "~Rule"?: Condition.Variance<infer E, infer _R, infer _O>
|
|
85
|
+
}
|
|
86
|
+
? E
|
|
87
|
+
: never
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The service type of a rule.
|
|
91
|
+
*
|
|
92
|
+
* @stability stable
|
|
93
|
+
* @category utility types
|
|
94
|
+
* @since 0.3.0
|
|
95
|
+
*/
|
|
96
|
+
export type Services<A> = A extends {
|
|
97
|
+
readonly "~Rule"?: Condition.Variance<infer _E, infer R, infer _O>
|
|
98
|
+
}
|
|
99
|
+
? R
|
|
100
|
+
: never
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* `Condition.Opaque` when a rule has a predicate.
|
|
104
|
+
*
|
|
105
|
+
* @stability stable
|
|
106
|
+
* @category utility types
|
|
107
|
+
* @since 0.3.0
|
|
108
|
+
*/
|
|
109
|
+
export type OpaqueOf<A> = A extends {
|
|
110
|
+
readonly "~Rule"?: Condition.Variance<infer _E, infer _R, infer O>
|
|
111
|
+
}
|
|
112
|
+
? O
|
|
113
|
+
: never
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A resource in a rule: a kind name, a resource of the domain, or `"*"`.
|
|
117
|
+
*
|
|
118
|
+
* @stability stable
|
|
119
|
+
* @category models
|
|
120
|
+
* @since 0.3.0
|
|
121
|
+
*/
|
|
122
|
+
export type Target<D> = Domain.Kind<D> | Domain.Resources<D> | "*"
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The kind name of a target.
|
|
126
|
+
*
|
|
127
|
+
* @stability stable
|
|
128
|
+
* @category utility types
|
|
129
|
+
* @since 0.3.0
|
|
130
|
+
*/
|
|
131
|
+
export type KindOf<T> = T extends string ? T : Resource.Kind<T>
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The actions that a rule may use for the kinds `K`.
|
|
135
|
+
*
|
|
136
|
+
* @stability stable
|
|
137
|
+
* @category utility types
|
|
138
|
+
* @since 0.3.0
|
|
139
|
+
*/
|
|
140
|
+
export type ActionFor<D, K> =
|
|
141
|
+
| "*"
|
|
142
|
+
| ("*" extends K
|
|
143
|
+
? Domain.AnyAction<D>
|
|
144
|
+
: Domain.ActionOf<D, Extract<K, string>>)
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The data type of the kinds `K`. For `"*"` it has no fields.
|
|
148
|
+
*
|
|
149
|
+
* @stability stable
|
|
150
|
+
* @category utility types
|
|
151
|
+
* @since 0.3.0
|
|
152
|
+
*/
|
|
153
|
+
export type DataFor<D, K> = "*" extends K
|
|
154
|
+
? {}
|
|
155
|
+
: Domain.DataOf<D, Extract<K, string>>
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The value type of the kinds `K`.
|
|
159
|
+
*
|
|
160
|
+
* @stability stable
|
|
161
|
+
* @category utility types
|
|
162
|
+
* @since 0.3.0
|
|
163
|
+
*/
|
|
164
|
+
export type ValueFor<D, K> = "*" extends K
|
|
165
|
+
? Domain.AnyValue<D>
|
|
166
|
+
: Domain.ValueOf<D, Extract<K, string>>
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* A field name or a field pattern of the kinds `K`.
|
|
170
|
+
*
|
|
171
|
+
* @stability stable
|
|
172
|
+
* @category models
|
|
173
|
+
* @since 0.3.0
|
|
174
|
+
*/
|
|
175
|
+
export type FieldFor<D, K> =
|
|
176
|
+
Condition.FieldPath<DataFor<D, K>> | `${string}*${string}`
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The options of a rule.
|
|
180
|
+
*
|
|
181
|
+
* @stability stable
|
|
182
|
+
* @category models
|
|
183
|
+
* @since 0.3.0
|
|
184
|
+
*/
|
|
185
|
+
export interface Options<D, K, C extends Condition.Any> {
|
|
186
|
+
/** The condition. It gets a builder with the types of the resource. */
|
|
187
|
+
readonly when?: (
|
|
188
|
+
builder: Condition.Builder<
|
|
189
|
+
DataFor<D, K>,
|
|
190
|
+
ValueFor<D, K>,
|
|
191
|
+
Domain.Principal<D>
|
|
192
|
+
>,
|
|
193
|
+
) => C
|
|
194
|
+
readonly fields?: ReadonlyArray<FieldFor<D, K>>
|
|
195
|
+
readonly reason?: string
|
|
196
|
+
readonly id?: string
|
|
197
|
+
readonly meta?: Domain.Meta<D>
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
type SingleOrArray<A> = A | ReadonlyArray<A>
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Makes rules with the types of a domain.
|
|
204
|
+
*
|
|
205
|
+
* @stability stable
|
|
206
|
+
* @category models
|
|
207
|
+
* @since 0.3.0
|
|
208
|
+
*/
|
|
209
|
+
export interface Builder<D> {
|
|
210
|
+
readonly allow: <
|
|
211
|
+
const T extends Target<D>,
|
|
212
|
+
const A extends ActionFor<D, KindOf<T>>,
|
|
213
|
+
const C extends Condition.Any = Condition.Condition,
|
|
214
|
+
>(
|
|
215
|
+
action: SingleOrArray<A>,
|
|
216
|
+
resource: SingleOrArray<T>,
|
|
217
|
+
options?: Options<D, KindOf<T>, C>,
|
|
218
|
+
) => Rule<Condition.Error<C>, Condition.Services<C>, Condition.OpaqueOf<C>>
|
|
219
|
+
readonly deny: <
|
|
220
|
+
const T extends Target<D>,
|
|
221
|
+
const A extends ActionFor<D, KindOf<T>>,
|
|
222
|
+
const C extends Condition.Any = Condition.Condition,
|
|
223
|
+
>(
|
|
224
|
+
action: SingleOrArray<A>,
|
|
225
|
+
resource: SingleOrArray<T>,
|
|
226
|
+
options?: Options<D, KindOf<T>, C>,
|
|
227
|
+
) => Rule<Condition.Error<C>, Condition.Services<C>, Condition.OpaqueOf<C>>
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Makes a rule builder for a domain.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* const _ = Rule.builder(App)
|
|
236
|
+
* const rule = _.allow("read", Bot, {
|
|
237
|
+
* when: ($) => $.eq("ownerUserId", $.principal("userId")),
|
|
238
|
+
* })
|
|
239
|
+
* ```
|
|
240
|
+
*
|
|
241
|
+
* @stability stable
|
|
242
|
+
* @category constructors
|
|
243
|
+
* @since 0.3.0
|
|
244
|
+
*/
|
|
245
|
+
export const builder: <D extends Domain.Any>(domain: D) => Builder<D> =
|
|
246
|
+
internal.builder
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Tests if a value is a rule.
|
|
250
|
+
*
|
|
251
|
+
* @stability stable
|
|
252
|
+
* @category guards
|
|
253
|
+
* @since 0.3.0
|
|
254
|
+
*/
|
|
255
|
+
export const isRule: (u: unknown) => u is Any = internal.isRule
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Tests if a field name matches a field name or a field pattern of a rule.
|
|
259
|
+
*
|
|
260
|
+
* @stability stable
|
|
261
|
+
* @category predicates
|
|
262
|
+
* @since 0.3.0
|
|
263
|
+
*/
|
|
264
|
+
export const matchesField: (pattern: string, field: string) => boolean =
|
|
265
|
+
internal.matchesFieldPattern
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed, composable authorization policies for Effect programs.
|
|
3
|
+
*
|
|
4
|
+
* The HTTP API tools are in a separate entry point,
|
|
5
|
+
* `@nmnmcc/ability/HttpApi`, because `effect/http-api` is not stable yet.
|
|
6
|
+
*
|
|
7
|
+
* @stability stable
|
|
8
|
+
* @since 0.3.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @stability stable
|
|
13
|
+
* @since 0.3.0
|
|
14
|
+
*/
|
|
15
|
+
export * as Authorizer from "./Authorizer.ts"
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @stability stable
|
|
19
|
+
* @since 0.3.0
|
|
20
|
+
*/
|
|
21
|
+
export * as Condition from "./Condition.ts"
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @stability stable
|
|
25
|
+
* @since 0.3.0
|
|
26
|
+
*/
|
|
27
|
+
export * as Decision from "./Decision.ts"
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @stability stable
|
|
31
|
+
* @since 0.3.0
|
|
32
|
+
*/
|
|
33
|
+
export * as Domain from "./Domain.ts"
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @stability stable
|
|
37
|
+
* @since 0.3.0
|
|
38
|
+
*/
|
|
39
|
+
export * as Policy from "./Policy.ts"
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @stability stable
|
|
43
|
+
* @since 0.3.0
|
|
44
|
+
*/
|
|
45
|
+
export * as Principal from "./Principal.ts"
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @stability stable
|
|
49
|
+
* @since 0.3.0
|
|
50
|
+
*/
|
|
51
|
+
export * as Resource from "./Resource.ts"
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @stability stable
|
|
55
|
+
* @since 0.3.0
|
|
56
|
+
*/
|
|
57
|
+
export * as Rule from "./Rule.ts"
|