@peerbit/identity-access-controller 1.0.2

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 dao.xyz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # "Chain agnostic" Access Controller
2
+ ## 🚧 Experimental state 🚧
3
+
4
+ An access controller that supports different layers of controll and fallbacks.
5
+
6
+ - A store containing ACL information, for example what public key can read and write
7
+ - A distributed relation store that lets you use linked devices to get access
8
+ - A fallback trusted network access controller that lets you have access if you are trusted by the root trust identity
9
+
10
+
11
+ As of know, go through the test for documentation
@@ -0,0 +1,20 @@
1
+ import { AccessCondition } from "./condition";
2
+ export declare enum AccessType {
3
+ Any = 0,
4
+ Read = 1,
5
+ Write = 2
6
+ }
7
+ export declare class AccessData {
8
+ }
9
+ export declare class Access extends AccessData {
10
+ id: string;
11
+ accessTypes: AccessType[];
12
+ accessCondition: AccessCondition<any>;
13
+ constructor(options?: {
14
+ accessTypes: AccessType[];
15
+ accessCondition: AccessCondition<any>;
16
+ });
17
+ calculateId(): string;
18
+ initialize(): Access;
19
+ assertId(): void;
20
+ }
@@ -0,0 +1,74 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var Access_1;
11
+ import { field, option, variant, vec } from "@dao-xyz/borsh";
12
+ import { serialize } from "@dao-xyz/borsh";
13
+ import { AccessCondition } from "./condition";
14
+ import { toBase64 } from "@peerbit/crypto";
15
+ export var AccessType;
16
+ (function (AccessType) {
17
+ AccessType[AccessType["Any"] = 0] = "Any";
18
+ AccessType[AccessType["Read"] = 1] = "Read";
19
+ AccessType[AccessType["Write"] = 2] = "Write";
20
+ })(AccessType || (AccessType = {}));
21
+ export let AccessData = class AccessData {
22
+ };
23
+ AccessData = __decorate([
24
+ variant(0)
25
+ ], AccessData);
26
+ export let Access = Access_1 = class Access extends AccessData {
27
+ id;
28
+ accessTypes;
29
+ accessCondition;
30
+ constructor(options) {
31
+ super();
32
+ if (options) {
33
+ this.accessTypes = options.accessTypes;
34
+ this.accessCondition = options.accessCondition;
35
+ this.initialize();
36
+ }
37
+ }
38
+ calculateId() {
39
+ if (!this.accessTypes || !this.accessCondition) {
40
+ throw new Error("Not initialized");
41
+ }
42
+ const a = new Access_1();
43
+ a.accessCondition = this.accessCondition;
44
+ a.accessTypes = this.accessTypes;
45
+ return toBase64(serialize(a));
46
+ }
47
+ initialize() {
48
+ this.id = this.calculateId();
49
+ return this;
50
+ }
51
+ assertId() {
52
+ const calculatedId = this.calculateId();
53
+ if (this.id !== calculatedId) {
54
+ throw new Error(`Invalid id, got ${this.id} but expected ${calculatedId}`);
55
+ }
56
+ }
57
+ };
58
+ __decorate([
59
+ field({ type: option("string") }),
60
+ __metadata("design:type", String)
61
+ ], Access.prototype, "id", void 0);
62
+ __decorate([
63
+ field({ type: vec("u8") }),
64
+ __metadata("design:type", Array)
65
+ ], Access.prototype, "accessTypes", void 0);
66
+ __decorate([
67
+ field({ type: AccessCondition }),
68
+ __metadata("design:type", AccessCondition)
69
+ ], Access.prototype, "accessCondition", void 0);
70
+ Access = Access_1 = __decorate([
71
+ variant(0),
72
+ __metadata("design:paramtypes", [Object])
73
+ ], Access);
74
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/access.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACrB,yCAAO,CAAA;IACP,2CAAQ,CAAA;IACR,6CAAS,CAAA;AACV,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAGM,WAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,UAAU;IADtB,OAAO,CAAC,CAAC,CAAC;GACE,UAAU,CAAG;AAGnB,WAAM,MAAM,cAAZ,MAAM,MAAO,SAAQ,UAAU;IAErC,EAAE,CAAS;IAGX,WAAW,CAAe;IAG1B,eAAe,CAAuB;IAEtC,YAAY,OAGX;QACA,KAAK,EAAE,CAAC;QACR,IAAI,OAAO,EAAE;YACZ,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;YACvC,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;YAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;SAClB;IACF,CAAC;IAED,WAAW;QACV,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;YAC/C,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;SACnC;QACD,MAAM,CAAC,GAAG,IAAI,QAAM,EAAE,CAAC;QACvB,CAAC,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QACzC,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACjC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,UAAU;QACT,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,QAAQ;QACP,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,EAAE,KAAK,YAAY,EAAE;YAC7B,MAAM,IAAI,KAAK,CACd,mBAAmB,IAAI,CAAC,EAAE,iBAAiB,YAAY,EAAE,CACzD,CAAC;SACF;IACF,CAAC;CACD,CAAA;AA3CA;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;;kCACvB;AAGX;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;;2CACD;AAG1B;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;8BAChB,eAAe;+CAAM;AAR1B,MAAM;IADlB,OAAO,CAAC,CAAC,CAAC;;GACE,MAAM,CA6ClB"}
@@ -0,0 +1,23 @@
1
+ import { Documents } from "@peerbit/document";
2
+ import { TrustedNetwork, IdentityGraph } from "@peerbit/trusted-network";
3
+ import { Access } from "./access";
4
+ import { Entry } from "@peerbit/log";
5
+ import { PublicSignKey } from "@peerbit/crypto";
6
+ import { Program } from "@peerbit/program";
7
+ import { PeerId } from "@libp2p/interface-peer-id";
8
+ import { SubscriptionType } from "@peerbit/shared-log";
9
+ export declare class IdentityAccessController extends Program {
10
+ access: Documents<Access>;
11
+ identityGraphController: IdentityGraph;
12
+ trustedNetwork: TrustedNetwork;
13
+ constructor(opts: {
14
+ id?: Uint8Array;
15
+ rootTrust: PublicSignKey | PeerId;
16
+ trustedNetwork?: TrustedNetwork;
17
+ });
18
+ canRead(s: PublicSignKey | undefined): Promise<boolean>;
19
+ canAppend(entry: Entry<any>): Promise<boolean>;
20
+ open(properties?: {
21
+ role?: SubscriptionType;
22
+ }): Promise<void>;
23
+ }
@@ -0,0 +1,150 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { field, variant } from "@dao-xyz/borsh";
11
+ import { Documents, DocumentIndex } from "@peerbit/document";
12
+ import { getPathGenerator, TrustedNetwork, getFromByTo, IdentityGraph, createIdentityGraphStore, } from "@peerbit/trusted-network";
13
+ import { Access, AccessType } from "./access";
14
+ import { sha256Sync } from "@peerbit/crypto";
15
+ import { Program } from "@peerbit/program";
16
+ import { RPC } from "@peerbit/rpc";
17
+ import { concat } from "uint8arrays";
18
+ export let IdentityAccessController = class IdentityAccessController extends Program {
19
+ access;
20
+ identityGraphController;
21
+ trustedNetwork;
22
+ constructor(opts) {
23
+ super();
24
+ if (!opts.trustedNetwork && !opts.rootTrust) {
25
+ throw new Error("Expecting either TrustedNetwork or rootTrust");
26
+ }
27
+ this.access = new Documents({
28
+ id: opts.id && sha256Sync(concat([opts.id, new Uint8Array([0])])),
29
+ index: new DocumentIndex({
30
+ query: new RPC(),
31
+ }),
32
+ });
33
+ this.trustedNetwork = opts.trustedNetwork
34
+ ? opts.trustedNetwork
35
+ : new TrustedNetwork({
36
+ id: opts.id && sha256Sync(concat([opts.id, new Uint8Array([1])])),
37
+ rootTrust: opts.rootTrust,
38
+ });
39
+ this.identityGraphController = new IdentityGraph({
40
+ relationGraph: createIdentityGraphStore(opts.id && sha256Sync(concat([opts.id, new Uint8Array([2])]))),
41
+ });
42
+ }
43
+ // allow anyone write to the ACL db, but assume entry is invalid until a verifier verifies
44
+ // can append will be anyone who has peformed some proof of work
45
+ // or
46
+ // custom can append
47
+ async canRead(s) {
48
+ // TODO, improve, caching etc
49
+ if (!s) {
50
+ return false;
51
+ }
52
+ // Check whether it is trusted by trust web
53
+ if (await this.trustedNetwork.isTrusted(s)) {
54
+ return true;
55
+ }
56
+ // Else check whether its trusted by this access controller
57
+ const canReadCheck = async (key) => {
58
+ for (const value of this.access.index.index.values()) {
59
+ const access = value.value;
60
+ if (access instanceof Access) {
61
+ if (access.accessTypes.find((x) => x === AccessType.Any || x === AccessType.Read) !== undefined) {
62
+ // check condition
63
+ if (await access.accessCondition.allowed(key)) {
64
+ return true;
65
+ }
66
+ continue;
67
+ }
68
+ }
69
+ }
70
+ };
71
+ if (await canReadCheck(s)) {
72
+ return true;
73
+ }
74
+ for await (const trustedByKey of getPathGenerator(s, this.identityGraphController.relationGraph, getFromByTo)) {
75
+ if (await canReadCheck(trustedByKey.from)) {
76
+ return true;
77
+ }
78
+ }
79
+ return false;
80
+ }
81
+ async canAppend(entry) {
82
+ // TODO, improve, caching etc
83
+ // Check whether it is trusted by trust web
84
+ const canAppendByKey = async (key) => {
85
+ if (await this.trustedNetwork.isTrusted(key)) {
86
+ return true;
87
+ }
88
+ // Else check whether its trusted by this access controller
89
+ const canWriteCheck = async (key) => {
90
+ for (const value of this.access.index.index.values()) {
91
+ const access = value.value;
92
+ if (access instanceof Access) {
93
+ if (access.accessTypes.find((x) => x === AccessType.Any || x === AccessType.Write) !== undefined) {
94
+ // check condition
95
+ if (await access.accessCondition.allowed(key)) {
96
+ return true;
97
+ }
98
+ continue;
99
+ }
100
+ }
101
+ }
102
+ };
103
+ if (await canWriteCheck(key)) {
104
+ return true;
105
+ }
106
+ for await (const trustedByKey of getPathGenerator(key, this.identityGraphController.relationGraph, getFromByTo)) {
107
+ if (await canWriteCheck(trustedByKey.from)) {
108
+ return true;
109
+ }
110
+ }
111
+ return false;
112
+ };
113
+ for (const key of await entry.getPublicKeys()) {
114
+ if (await canAppendByKey(key)) {
115
+ return true;
116
+ }
117
+ }
118
+ return false;
119
+ }
120
+ async open(properties) {
121
+ await this.identityGraphController.open({
122
+ role: properties?.role,
123
+ canRead: this.canRead.bind(this),
124
+ });
125
+ await this.access.open({
126
+ role: properties?.role,
127
+ type: Access,
128
+ canAppend: this.canAppend.bind(this),
129
+ canRead: this.canRead.bind(this),
130
+ });
131
+ await this.trustedNetwork.open(properties);
132
+ }
133
+ };
134
+ __decorate([
135
+ field({ type: Documents }),
136
+ __metadata("design:type", Documents)
137
+ ], IdentityAccessController.prototype, "access", void 0);
138
+ __decorate([
139
+ field({ type: IdentityGraph }),
140
+ __metadata("design:type", IdentityGraph)
141
+ ], IdentityAccessController.prototype, "identityGraphController", void 0);
142
+ __decorate([
143
+ field({ type: TrustedNetwork }),
144
+ __metadata("design:type", TrustedNetwork)
145
+ ], IdentityAccessController.prototype, "trustedNetwork", void 0);
146
+ IdentityAccessController = __decorate([
147
+ variant("identity_acl"),
148
+ __metadata("design:paramtypes", [Object])
149
+ ], IdentityAccessController);
150
+ //# sourceMappingURL=acl-db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acl-db.js","sourceRoot":"","sources":["../../src/acl-db.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,aAAa,EACb,wBAAwB,GACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,EAAiB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI9B,WAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,OAAO;IAEpD,MAAM,CAAoB;IAG1B,uBAAuB,CAAgB;IAGvC,cAAc,CAAiB;IAE/B,YAAY,IAIX;QACA,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAC5C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;SAChE;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC;YAC3B,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,KAAK,EAAE,IAAI,aAAa,CAAC;gBACxB,KAAK,EAAE,IAAI,GAAG,EAAE;aAChB,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc;YACxC,CAAC,CAAC,IAAI,CAAC,cAAc;YACrB,CAAC,CAAC,IAAI,cAAc,CAAC;gBACnB,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjE,SAAS,EAAE,IAAI,CAAC,SAAS;aACxB,CAAC,CAAC;QACN,IAAI,CAAC,uBAAuB,GAAG,IAAI,aAAa,CAAC;YAChD,aAAa,EAAE,wBAAwB,CACtC,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC7D;SACD,CAAC,CAAC;IACJ,CAAC;IAED,0FAA0F;IAC1F,gEAAgE;IAEhE,KAAK;IAEL,oBAAoB;IAEpB,KAAK,CAAC,OAAO,CAAC,CAA4B;QACzC,6BAA6B;QAE7B,IAAI,CAAC,CAAC,EAAE;YACP,OAAO,KAAK,CAAC;SACb;QAED,2CAA2C;QAC3C,IAAI,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YAC3C,OAAO,IAAI,CAAC;SACZ;QAED,2DAA2D;QAC3D,MAAM,YAAY,GAAG,KAAK,EAAE,GAAkB,EAAE,EAAE;YACjD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE;gBACrD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;gBAC3B,IAAI,MAAM,YAAY,MAAM,EAAE;oBAC7B,IACC,MAAM,CAAC,WAAW,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,UAAU,CAAC,IAAI,CACpD,KAAK,SAAS,EACd;wBACD,kBAAkB;wBAClB,IAAI,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;4BAC9C,OAAO,IAAI,CAAC;yBACZ;wBACD,SAAS;qBACT;iBACD;aACD;QACF,CAAC,CAAC;QAEF,IAAI,MAAM,YAAY,CAAC,CAAC,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC;SACZ;QACD,IAAI,KAAK,EAAE,MAAM,YAAY,IAAI,gBAAgB,CAChD,CAAC,EACD,IAAI,CAAC,uBAAuB,CAAC,aAAa,EAC1C,WAAW,CACX,EAAE;YACF,IAAI,MAAM,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE;gBAC1C,OAAO,IAAI,CAAC;aACZ;SACD;QAED,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAiB;QAChC,6BAA6B;QAE7B,2CAA2C;QAC3C,MAAM,cAAc,GAAG,KAAK,EAAE,GAAkB,EAAoB,EAAE;YACrE,IAAI,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE;gBAC7C,OAAO,IAAI,CAAC;aACZ;YACD,2DAA2D;YAC3D,MAAM,aAAa,GAAG,KAAK,EAAE,GAAkB,EAAE,EAAE;gBAClD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE;oBACrD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;oBAC3B,IAAI,MAAM,YAAY,MAAM,EAAE;wBAC7B,IACC,MAAM,CAAC,WAAW,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,CACrD,KAAK,SAAS,EACd;4BACD,kBAAkB;4BAClB,IAAI,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gCAC9C,OAAO,IAAI,CAAC;6BACZ;4BACD,SAAS;yBACT;qBACD;iBACD;YACF,CAAC,CAAC;YACF,IAAI,MAAM,aAAa,CAAC,GAAG,CAAC,EAAE;gBAC7B,OAAO,IAAI,CAAC;aACZ;YACD,IAAI,KAAK,EAAE,MAAM,YAAY,IAAI,gBAAgB,CAChD,GAAG,EACH,IAAI,CAAC,uBAAuB,CAAC,aAAa,EAC1C,WAAW,CACX,EAAE;gBACF,IAAI,MAAM,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE;oBAC3C,OAAO,IAAI,CAAC;iBACZ;aACD;YAED,OAAO,KAAK,CAAC;QACd,CAAC,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,MAAM,KAAK,CAAC,aAAa,EAAE,EAAE;YAC9C,IAAI,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE;gBAC9B,OAAO,IAAI,CAAC;aACZ;SACD;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,UAAwC;QAClD,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC;YACvC,IAAI,EAAE,UAAU,EAAE,IAAI;YACtB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;SAChC,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,UAAU,EAAE,IAAI;YACtB,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YACpC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;SAChC,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;CACD,CAAA;AA5JA;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;8BACnB,SAAS;wDAAS;AAG1B;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACN,aAAa;yEAAC;AAGvC;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;8BAChB,cAAc;gEAAC;AARnB,wBAAwB;IADpC,OAAO,CAAC,cAAc,CAAC;;GACX,wBAAwB,CA8JpC"}
@@ -0,0 +1,20 @@
1
+ import { PublicSignKey } from "@peerbit/crypto";
2
+ import { PeerId } from "@libp2p/interface-peer-id";
3
+ export declare class Network {
4
+ type: string;
5
+ rpc: string;
6
+ }
7
+ export declare class AccessCondition<T> {
8
+ allowed(_key: PublicSignKey): Promise<boolean>;
9
+ }
10
+ export declare class AnyAccessCondition<T> extends AccessCondition<T> {
11
+ constructor();
12
+ allowed(_key: PublicSignKey): Promise<boolean>;
13
+ }
14
+ export declare class PublicKeyAccessCondition<T> extends AccessCondition<T> {
15
+ key: PublicSignKey;
16
+ constructor(options: {
17
+ key: PublicSignKey | PeerId;
18
+ });
19
+ allowed(identity: PublicSignKey): Promise<boolean>;
20
+ }
@@ -0,0 +1,113 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { field, variant } from "@dao-xyz/borsh";
11
+ import { PublicSignKey, getPublicKeyFromPeerId } from "@peerbit/crypto";
12
+ const coercePublicKey = (publicKey) => {
13
+ return publicKey instanceof PublicSignKey
14
+ ? publicKey
15
+ : getPublicKeyFromPeerId(publicKey);
16
+ };
17
+ export let Network = class Network {
18
+ type;
19
+ rpc;
20
+ };
21
+ __decorate([
22
+ field({ type: "string" }),
23
+ __metadata("design:type", String)
24
+ ], Network.prototype, "type", void 0);
25
+ __decorate([
26
+ field({ type: "string" }),
27
+ __metadata("design:type", String)
28
+ ], Network.prototype, "rpc", void 0);
29
+ Network = __decorate([
30
+ variant(0)
31
+ ], Network);
32
+ export class AccessCondition {
33
+ async allowed(_key) {
34
+ throw new Error("Not implemented");
35
+ }
36
+ }
37
+ export let AnyAccessCondition = class AnyAccessCondition extends AccessCondition {
38
+ constructor() {
39
+ super();
40
+ }
41
+ async allowed(_key) {
42
+ return true;
43
+ }
44
+ };
45
+ AnyAccessCondition = __decorate([
46
+ variant([0, 0]),
47
+ __metadata("design:paramtypes", [])
48
+ ], AnyAccessCondition);
49
+ export let PublicKeyAccessCondition = class PublicKeyAccessCondition extends AccessCondition {
50
+ key;
51
+ constructor(options) {
52
+ super();
53
+ this.key = coercePublicKey(options.key);
54
+ }
55
+ async allowed(identity) {
56
+ return this.key.equals(identity);
57
+ }
58
+ };
59
+ __decorate([
60
+ field({ type: PublicSignKey }),
61
+ __metadata("design:type", PublicSignKey)
62
+ ], PublicKeyAccessCondition.prototype, "key", void 0);
63
+ PublicKeyAccessCondition = __decorate([
64
+ variant([0, 1]),
65
+ __metadata("design:paramtypes", [Object])
66
+ ], PublicKeyAccessCondition);
67
+ /* Not yet :)
68
+
69
+ @variant([0, 2])
70
+ export class TokenAccessCondition extends AccessCondition {
71
+
72
+ @field({ type: Network })
73
+ network: Network
74
+
75
+ @field({ type: 'string' })
76
+ token: string
77
+
78
+ @field({ type: 'u64' })
79
+ amount: bigint
80
+
81
+ constructor() {
82
+ super();
83
+ }
84
+ }
85
+
86
+
87
+ @variant(0)
88
+ export class NFTPropertyCondition {
89
+ @field({ type: 'string' })
90
+ field: string
91
+
92
+ @field({ type: 'string' })
93
+ value: string;
94
+ }
95
+
96
+ @variant([0, 3]) // distinguish between ERC-721, ERC-1155, Solana Metaplex?
97
+ export class NFTAccessCondition extends AccessCondition {
98
+
99
+ @field({ type: Network })
100
+ network: Network
101
+
102
+ @field({ type: 'string' })
103
+ id: string
104
+
105
+ @field({ type: option(vec(NFTPropertyCondition)) })
106
+ properties: NFTPropertyCondition
107
+
108
+ constructor() {
109
+ super();
110
+ }
111
+ }
112
+ */
113
+ //# sourceMappingURL=condition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"condition.js","sourceRoot":"","sources":["../../src/condition.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGxE,MAAM,eAAe,GAAG,CAAC,SAAiC,EAAE,EAAE;IAC7D,OAAO,SAAS,YAAY,aAAa;QACxC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;AACtC,CAAC,CAAC;AAGK,WAAM,OAAO,GAAb,MAAM,OAAO;IAEnB,IAAI,CAAS;IAGb,GAAG,CAAS;CACZ,CAAA;AAJA;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;qCACb;AAGb;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;oCACd;AALA,OAAO;IADnB,OAAO,CAAC,CAAC,CAAC;GACE,OAAO,CAMnB;AAED,MAAM,OAAO,eAAe;IAC3B,KAAK,CAAC,OAAO,CAAC,IAAmB;QAChC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;CACD;AAGM,WAAM,kBAAkB,GAAxB,MAAM,kBAAsB,SAAQ,eAAkB;IAC5D;QACC,KAAK,EAAE,CAAC;IACT,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAmB;QAChC,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAA;AAPY,kBAAkB;IAD9B,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;GACH,kBAAkB,CAO9B;AAGM,WAAM,wBAAwB,GAA9B,MAAM,wBAA4B,SAAQ,eAAkB;IAElE,GAAG,CAAgB;IAEnB,YAAY,OAAwC;QACnD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAuB;QACpC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;CACD,CAAA;AAVA;IADC,KAAK,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BAC1B,aAAa;qDAAC;AAFP,wBAAwB;IADpC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;GACH,wBAAwB,CAYpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG"}
@@ -0,0 +1,3 @@
1
+ export * from "./access.js";
2
+ export * from "./acl-db.js";
3
+ export * from "./condition.js";
@@ -0,0 +1,4 @@
1
+ export * from "./access.js";
2
+ export * from "./acl-db.js";
3
+ export * from "./condition.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@peerbit/identity-access-controller",
3
+ "version": "1.0.2",
4
+ "description": "Access controller that operates on a DB",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "module": "lib/esm/index.js",
8
+ "types": "lib/esm/index.d.ts",
9
+ "exports": {
10
+ "import": "./lib/esm/index.js",
11
+ "require": "./lib/cjs/index.js"
12
+ },
13
+ "files": [
14
+ "lib",
15
+ "src",
16
+ "!src/**/__tests__",
17
+ "!lib/**/__tests__",
18
+ "LICENSE"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "scripts": {
24
+ "clean": "shx rm -rf lib/*",
25
+ "build": "yarn clean && tsc -p tsconfig.json",
26
+ "postbuild": "echo '{\"type\":\"module\"} ' | node ../../../../node_modules/.bin/json > lib/esm/package.json",
27
+ "test": "node ../../../../node_modules/.bin/jest test -c ../../../../jest.config.ts --runInBand --forceExit",
28
+ "test:unit": "node ../../../../node_modules/.bin/jest test -c ../../../../jest.config.unit.ts --runInBand --forceExit",
29
+ "test:integration": "node ../node_modules/.bin/jest test -c ../../../../jest.config.integration.ts --runInBand --forceExit"
30
+ },
31
+ "author": "dao.xyz",
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@dao-xyz/borsh": "^5.1.5",
35
+ "@peerbit/document": "1.0.2",
36
+ "@peerbit/trusted-network": "1.0.2"
37
+ },
38
+ "devDependencies": {
39
+ "@peerbit/test-utils": "^1.0.2",
40
+ "@peerbit/time": "^1.0.0"
41
+ },
42
+ "gitHead": "595db9f1efebf604393eddfff5f678f5d8f16142"
43
+ }
package/src/access.ts ADDED
@@ -0,0 +1,61 @@
1
+ import { field, option, variant, vec } from "@dao-xyz/borsh";
2
+ import { serialize } from "@dao-xyz/borsh";
3
+ import { AccessCondition } from "./condition";
4
+ import { toBase64 } from "@peerbit/crypto";
5
+
6
+ export enum AccessType {
7
+ Any = 0,
8
+ Read = 1,
9
+ Write = 2,
10
+ }
11
+
12
+ @variant(0)
13
+ export class AccessData {}
14
+
15
+ @variant(0)
16
+ export class Access extends AccessData {
17
+ @field({ type: option("string") })
18
+ id: string;
19
+
20
+ @field({ type: vec("u8") })
21
+ accessTypes: AccessType[];
22
+
23
+ @field({ type: AccessCondition })
24
+ accessCondition: AccessCondition<any>;
25
+
26
+ constructor(options?: {
27
+ accessTypes: AccessType[];
28
+ accessCondition: AccessCondition<any>;
29
+ }) {
30
+ super();
31
+ if (options) {
32
+ this.accessTypes = options.accessTypes;
33
+ this.accessCondition = options.accessCondition;
34
+ this.initialize();
35
+ }
36
+ }
37
+
38
+ calculateId(): string {
39
+ if (!this.accessTypes || !this.accessCondition) {
40
+ throw new Error("Not initialized");
41
+ }
42
+ const a = new Access();
43
+ a.accessCondition = this.accessCondition;
44
+ a.accessTypes = this.accessTypes;
45
+ return toBase64(serialize(a));
46
+ }
47
+
48
+ initialize(): Access {
49
+ this.id = this.calculateId();
50
+ return this;
51
+ }
52
+
53
+ assertId() {
54
+ const calculatedId = this.calculateId();
55
+ if (this.id !== calculatedId) {
56
+ throw new Error(
57
+ `Invalid id, got ${this.id} but expected ${calculatedId}`
58
+ );
59
+ }
60
+ }
61
+ }
package/src/acl-db.ts ADDED
@@ -0,0 +1,178 @@
1
+ import { field, variant } from "@dao-xyz/borsh";
2
+ import { Documents, DocumentIndex } from "@peerbit/document";
3
+ import {
4
+ getPathGenerator,
5
+ TrustedNetwork,
6
+ getFromByTo,
7
+ IdentityGraph,
8
+ createIdentityGraphStore,
9
+ } from "@peerbit/trusted-network";
10
+ import { Access, AccessType } from "./access";
11
+ import { Entry } from "@peerbit/log";
12
+ import { PublicSignKey, sha256Sync } from "@peerbit/crypto";
13
+ import { Program } from "@peerbit/program";
14
+ import { RPC } from "@peerbit/rpc";
15
+ import { PeerId } from "@libp2p/interface-peer-id";
16
+ import { concat } from "uint8arrays";
17
+ import { SubscriptionType } from "@peerbit/shared-log";
18
+
19
+ @variant("identity_acl")
20
+ export class IdentityAccessController extends Program {
21
+ @field({ type: Documents })
22
+ access: Documents<Access>;
23
+
24
+ @field({ type: IdentityGraph })
25
+ identityGraphController: IdentityGraph;
26
+
27
+ @field({ type: TrustedNetwork })
28
+ trustedNetwork: TrustedNetwork;
29
+
30
+ constructor(opts: {
31
+ id?: Uint8Array;
32
+ rootTrust: PublicSignKey | PeerId;
33
+ trustedNetwork?: TrustedNetwork;
34
+ }) {
35
+ super();
36
+ if (!opts.trustedNetwork && !opts.rootTrust) {
37
+ throw new Error("Expecting either TrustedNetwork or rootTrust");
38
+ }
39
+ this.access = new Documents({
40
+ id: opts.id && sha256Sync(concat([opts.id, new Uint8Array([0])])),
41
+ index: new DocumentIndex({
42
+ query: new RPC(),
43
+ }),
44
+ });
45
+
46
+ this.trustedNetwork = opts.trustedNetwork
47
+ ? opts.trustedNetwork
48
+ : new TrustedNetwork({
49
+ id: opts.id && sha256Sync(concat([opts.id, new Uint8Array([1])])),
50
+ rootTrust: opts.rootTrust,
51
+ });
52
+ this.identityGraphController = new IdentityGraph({
53
+ relationGraph: createIdentityGraphStore(
54
+ opts.id && sha256Sync(concat([opts.id, new Uint8Array([2])]))
55
+ ),
56
+ });
57
+ }
58
+
59
+ // allow anyone write to the ACL db, but assume entry is invalid until a verifier verifies
60
+ // can append will be anyone who has peformed some proof of work
61
+
62
+ // or
63
+
64
+ // custom can append
65
+
66
+ async canRead(s: PublicSignKey | undefined): Promise<boolean> {
67
+ // TODO, improve, caching etc
68
+
69
+ if (!s) {
70
+ return false;
71
+ }
72
+
73
+ // Check whether it is trusted by trust web
74
+ if (await this.trustedNetwork.isTrusted(s)) {
75
+ return true;
76
+ }
77
+
78
+ // Else check whether its trusted by this access controller
79
+ const canReadCheck = async (key: PublicSignKey) => {
80
+ for (const value of this.access.index.index.values()) {
81
+ const access = value.value;
82
+ if (access instanceof Access) {
83
+ if (
84
+ access.accessTypes.find(
85
+ (x) => x === AccessType.Any || x === AccessType.Read
86
+ ) !== undefined
87
+ ) {
88
+ // check condition
89
+ if (await access.accessCondition.allowed(key)) {
90
+ return true;
91
+ }
92
+ continue;
93
+ }
94
+ }
95
+ }
96
+ };
97
+
98
+ if (await canReadCheck(s)) {
99
+ return true;
100
+ }
101
+ for await (const trustedByKey of getPathGenerator(
102
+ s,
103
+ this.identityGraphController.relationGraph,
104
+ getFromByTo
105
+ )) {
106
+ if (await canReadCheck(trustedByKey.from)) {
107
+ return true;
108
+ }
109
+ }
110
+
111
+ return false;
112
+ }
113
+
114
+ async canAppend(entry: Entry<any>): Promise<boolean> {
115
+ // TODO, improve, caching etc
116
+
117
+ // Check whether it is trusted by trust web
118
+ const canAppendByKey = async (key: PublicSignKey): Promise<boolean> => {
119
+ if (await this.trustedNetwork.isTrusted(key)) {
120
+ return true;
121
+ }
122
+ // Else check whether its trusted by this access controller
123
+ const canWriteCheck = async (key: PublicSignKey) => {
124
+ for (const value of this.access.index.index.values()) {
125
+ const access = value.value;
126
+ if (access instanceof Access) {
127
+ if (
128
+ access.accessTypes.find(
129
+ (x) => x === AccessType.Any || x === AccessType.Write
130
+ ) !== undefined
131
+ ) {
132
+ // check condition
133
+ if (await access.accessCondition.allowed(key)) {
134
+ return true;
135
+ }
136
+ continue;
137
+ }
138
+ }
139
+ }
140
+ };
141
+ if (await canWriteCheck(key)) {
142
+ return true;
143
+ }
144
+ for await (const trustedByKey of getPathGenerator(
145
+ key,
146
+ this.identityGraphController.relationGraph,
147
+ getFromByTo
148
+ )) {
149
+ if (await canWriteCheck(trustedByKey.from)) {
150
+ return true;
151
+ }
152
+ }
153
+
154
+ return false;
155
+ };
156
+
157
+ for (const key of await entry.getPublicKeys()) {
158
+ if (await canAppendByKey(key)) {
159
+ return true;
160
+ }
161
+ }
162
+ return false;
163
+ }
164
+
165
+ async open(properties?: { role?: SubscriptionType }) {
166
+ await this.identityGraphController.open({
167
+ role: properties?.role,
168
+ canRead: this.canRead.bind(this),
169
+ });
170
+ await this.access.open({
171
+ role: properties?.role,
172
+ type: Access,
173
+ canAppend: this.canAppend.bind(this),
174
+ canRead: this.canRead.bind(this),
175
+ });
176
+ await this.trustedNetwork.open(properties);
177
+ }
178
+ }
@@ -0,0 +1,96 @@
1
+ import { field, variant } from "@dao-xyz/borsh";
2
+ import { PublicSignKey, getPublicKeyFromPeerId } from "@peerbit/crypto";
3
+ import { PeerId } from "@libp2p/interface-peer-id";
4
+
5
+ const coercePublicKey = (publicKey: PublicSignKey | PeerId) => {
6
+ return publicKey instanceof PublicSignKey
7
+ ? publicKey
8
+ : getPublicKeyFromPeerId(publicKey);
9
+ };
10
+
11
+ @variant(0)
12
+ export class Network {
13
+ @field({ type: "string" })
14
+ type: string;
15
+
16
+ @field({ type: "string" })
17
+ rpc: string;
18
+ }
19
+
20
+ export class AccessCondition<T> {
21
+ async allowed(_key: PublicSignKey): Promise<boolean> {
22
+ throw new Error("Not implemented");
23
+ }
24
+ }
25
+
26
+ @variant([0, 0])
27
+ export class AnyAccessCondition<T> extends AccessCondition<T> {
28
+ constructor() {
29
+ super();
30
+ }
31
+ async allowed(_key: PublicSignKey): Promise<boolean> {
32
+ return true;
33
+ }
34
+ }
35
+
36
+ @variant([0, 1])
37
+ export class PublicKeyAccessCondition<T> extends AccessCondition<T> {
38
+ @field({ type: PublicSignKey })
39
+ key: PublicSignKey;
40
+
41
+ constructor(options: { key: PublicSignKey | PeerId }) {
42
+ super();
43
+ this.key = coercePublicKey(options.key);
44
+ }
45
+
46
+ async allowed(identity: PublicSignKey): Promise<boolean> {
47
+ return this.key.equals(identity);
48
+ }
49
+ }
50
+
51
+ /* Not yet :)
52
+
53
+ @variant([0, 2])
54
+ export class TokenAccessCondition extends AccessCondition {
55
+
56
+ @field({ type: Network })
57
+ network: Network
58
+
59
+ @field({ type: 'string' })
60
+ token: string
61
+
62
+ @field({ type: 'u64' })
63
+ amount: bigint
64
+
65
+ constructor() {
66
+ super();
67
+ }
68
+ }
69
+
70
+
71
+ @variant(0)
72
+ export class NFTPropertyCondition {
73
+ @field({ type: 'string' })
74
+ field: string
75
+
76
+ @field({ type: 'string' })
77
+ value: string;
78
+ }
79
+
80
+ @variant([0, 3]) // distinguish between ERC-721, ERC-1155, Solana Metaplex?
81
+ export class NFTAccessCondition extends AccessCondition {
82
+
83
+ @field({ type: Network })
84
+ network: Network
85
+
86
+ @field({ type: 'string' })
87
+ id: string
88
+
89
+ @field({ type: option(vec(NFTPropertyCondition)) })
90
+ properties: NFTPropertyCondition
91
+
92
+ constructor() {
93
+ super();
94
+ }
95
+ }
96
+ */
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./access.js";
2
+ export * from "./acl-db.js";
3
+ export * from "./condition.js";