jinaga-server 1.0.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/LICENSE +22 -0
- package/dist/authentication/authentication-device.d.ts +20 -0
- package/dist/authentication/authentication-device.js +61 -0
- package/dist/authentication/authentication-device.js.map +1 -0
- package/dist/authentication/authentication-impl.d.ts +21 -0
- package/dist/authentication/authentication-impl.js +61 -0
- package/dist/authentication/authentication-impl.js.map +1 -0
- package/dist/authentication/authentication-session.d.ts +23 -0
- package/dist/authentication/authentication-session.js +85 -0
- package/dist/authentication/authentication-session.js.map +1 -0
- package/dist/authentication/authentication.d.ts +5 -0
- package/dist/authentication/authentication.js +3 -0
- package/dist/authentication/authentication.js.map +1 -0
- package/dist/authentication.d.ts +17 -0
- package/dist/authentication.js +52 -0
- package/dist/authentication.js.map +1 -0
- package/dist/authorization/authorization-keystore.d.ts +13 -0
- package/dist/authorization/authorization-keystore.js +61 -0
- package/dist/authorization/authorization-keystore.js.map +1 -0
- package/dist/http/node-http.d.ts +7 -0
- package/dist/http/node-http.js +126 -0
- package/dist/http/node-http.js.map +1 -0
- package/dist/http/router.d.ts +20 -0
- package/dist/http/router.js +223 -0
- package/dist/http/router.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/jinaga-server.d.ts +18 -0
- package/dist/jinaga-server.js +101 -0
- package/dist/jinaga-server.js.map +1 -0
- package/dist/keystore.d.ts +9 -0
- package/dist/keystore.js +3 -0
- package/dist/keystore.js.map +1 -0
- package/dist/memory/memory-keystore.d.ts +16 -0
- package/dist/memory/memory-keystore.js +86 -0
- package/dist/memory/memory-keystore.js.map +1 -0
- package/dist/postgres/connection.d.ts +12 -0
- package/dist/postgres/connection.js +83 -0
- package/dist/postgres/connection.js.map +1 -0
- package/dist/postgres/edge-record.d.ts +9 -0
- package/dist/postgres/edge-record.js +30 -0
- package/dist/postgres/edge-record.js.map +1 -0
- package/dist/postgres/maps.d.ts +21 -0
- package/dist/postgres/maps.js +86 -0
- package/dist/postgres/maps.js.map +1 -0
- package/dist/postgres/postgres-keystore.d.ts +20 -0
- package/dist/postgres/postgres-keystore.js +168 -0
- package/dist/postgres/postgres-keystore.js.map +1 -0
- package/dist/postgres/postgres-store.d.ts +20 -0
- package/dist/postgres/postgres-store.js +717 -0
- package/dist/postgres/postgres-store.js.map +1 -0
- package/dist/postgres/query-description-builder.d.ts +13 -0
- package/dist/postgres/query-description-builder.js +104 -0
- package/dist/postgres/query-description-builder.js.map +1 -0
- package/dist/postgres/query-description.d.ts +71 -0
- package/dist/postgres/query-description.js +256 -0
- package/dist/postgres/query-description.js.map +1 -0
- package/dist/postgres/specification-result-sql.d.ts +41 -0
- package/dist/postgres/specification-result-sql.js +260 -0
- package/dist/postgres/specification-result-sql.js.map +1 -0
- package/dist/postgres/specification-sql.d.ts +3 -0
- package/dist/postgres/specification-sql.js +119 -0
- package/dist/postgres/specification-sql.js.map +1 -0
- package/dist/postgres/sql.d.ts +10 -0
- package/dist/postgres/sql.js +396 -0
- package/dist/postgres/sql.js.map +1 -0
- package/dist/util/fn.d.ts +6 -0
- package/dist/util/fn.js +81 -0
- package/dist/util/fn.js.map +1 -0
- package/dist/util/promise.d.ts +1 -0
- package/dist/util/promise.js +10 -0
- package/dist/util/promise.js.map +1 -0
- package/docs/registrations.sql +22 -0
- package/docs/specification.txt +41 -0
- package/docs/sql-generator.gv +25 -0
- package/integration-test/docker-compose.yaml +13 -0
- package/integration-test/jinaga-test/Dockerfile +12 -0
- package/integration-test/jinaga-test/jinaga.test.js +425 -0
- package/integration-test/jinaga-test/package-lock.json +6767 -0
- package/integration-test/jinaga-test/package.json +25 -0
- package/integration-test/postgres/0-init-app-db.sh +16 -0
- package/integration-test/postgres/1-setup.sql +219 -0
- package/integration-test/postgres/2-grant.sh +17 -0
- package/integration-test/postgres/Dockerfile +5 -0
- package/integration-test/run.sh +17 -0
- package/integration-test/start_db.sh +2 -0
- package/integration-test/stop_db.sh +3 -0
- package/integration-test/test.sh +8 -0
- package/interactive/index.js +56 -0
- package/jest.config.js +12 -0
- package/package.json +51 -0
- package/scripts/combined.sql +46 -0
- package/scripts/cte.sql +55 -0
- package/scripts/separate.sql +27 -0
- package/setup.sh +34 -0
- package/setup.sql +329 -0
- package/src/authentication/authentication-device.ts +68 -0
- package/src/authentication/authentication-impl.ts +59 -0
- package/src/authentication/authentication-session.ts +95 -0
- package/src/authentication/authentication.ts +6 -0
- package/src/authentication.ts +45 -0
- package/src/authorization/authorization-keystore.ts +67 -0
- package/src/http/node-http.ts +106 -0
- package/src/http/router.ts +237 -0
- package/src/index.ts +1 -0
- package/src/jinaga-server.ts +125 -0
- package/src/keystore.ts +10 -0
- package/src/memory/memory-keystore.ts +93 -0
- package/src/postgres/connection.ts +73 -0
- package/src/postgres/edge-record.ts +36 -0
- package/src/postgres/maps.ts +89 -0
- package/src/postgres/postgres-keystore.ts +167 -0
- package/src/postgres/postgres-store.ts +874 -0
- package/src/postgres/query-description-builder.ts +116 -0
- package/src/postgres/query-description.ts +385 -0
- package/src/postgres/specification-result-sql.ts +362 -0
- package/src/postgres/specification-sql.ts +138 -0
- package/src/postgres/sql.ts +482 -0
- package/src/util/fn.ts +63 -0
- package/src/util/promise.ts +5 -0
- package/test/authorization/authorizationSpec.ts +209 -0
- package/test/postgres/postgresSpec.ts +385 -0
- package/test/postgres/postgresSpecificationSpec.ts +742 -0
- package/test/reporter.js +25 -0
- package/tsconfig.json +25 -0
- package/upgrade.sh +21 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { encode } from "@stablelib/base64";
|
|
2
|
+
|
|
3
|
+
import { ensure, Jinaga, JinagaServer } from "./jinaga";
|
|
4
|
+
|
|
5
|
+
const host = "db";
|
|
6
|
+
// const host = "localhost";
|
|
7
|
+
const connectionString = `postgresql://dev:devpw@${host}:5432/integrationtest`;
|
|
8
|
+
|
|
9
|
+
describe("Jinaga as a device", () => {
|
|
10
|
+
let j;
|
|
11
|
+
let close;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
({ j, close } = JinagaServer.create({
|
|
15
|
+
pgKeystore: connectionString,
|
|
16
|
+
pgStore: connectionString
|
|
17
|
+
}));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(async () => {
|
|
21
|
+
await close();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should save a fact", async () => {
|
|
25
|
+
const root = await j.fact(randomRoot());
|
|
26
|
+
|
|
27
|
+
expect(root.type).toEqual("IntegrationTest.Root");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should save a fact twice", async () => {
|
|
31
|
+
const root = randomRoot();
|
|
32
|
+
await j.fact(root);
|
|
33
|
+
await j.fact(root);
|
|
34
|
+
|
|
35
|
+
expect(root.type).toEqual("IntegrationTest.Root");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should save a successor fact", async () => {
|
|
39
|
+
const root = await j.fact(randomRoot());
|
|
40
|
+
|
|
41
|
+
const successor = await j.fact({
|
|
42
|
+
type: "IntegrationTest.Successor",
|
|
43
|
+
identifier: "test-successor",
|
|
44
|
+
predecessor: root
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(successor.identifier).toEqual("test-successor");
|
|
48
|
+
expect(successor.predecessor).toEqual(root);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should query a successor fact", async () => {
|
|
52
|
+
const root = await j.fact(randomRoot());
|
|
53
|
+
|
|
54
|
+
const successor = await j.fact({
|
|
55
|
+
type: "IntegrationTest.Successor",
|
|
56
|
+
identifier: "test-successor",
|
|
57
|
+
predecessor: root
|
|
58
|
+
});
|
|
59
|
+
const successors = await j.query(root, j.for(successorsOfRoot));
|
|
60
|
+
|
|
61
|
+
expect(successors).toEqual([successor]);
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it("should query a type that has never been seen", async () => {
|
|
65
|
+
const root = await j.fact(randomRoot());
|
|
66
|
+
const unknown = await j.query(root, j.for(unknownOfRoot));
|
|
67
|
+
|
|
68
|
+
expect(unknown).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should save a successor fact twice", async () => {
|
|
72
|
+
const root = await j.fact(randomRoot());
|
|
73
|
+
|
|
74
|
+
await j.fact({
|
|
75
|
+
type: "IntegrationTest.Successor",
|
|
76
|
+
identifier: "test-successor",
|
|
77
|
+
predecessor: root
|
|
78
|
+
});
|
|
79
|
+
const successor = await j.fact({
|
|
80
|
+
type: "IntegrationTest.Successor",
|
|
81
|
+
identifier: "test-successor",
|
|
82
|
+
predecessor: root
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(successor.identifier).toEqual("test-successor");
|
|
86
|
+
expect(successor.predecessor).toEqual(root);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
it("should save multiple facts", async () => {
|
|
91
|
+
const successor = await j.fact({
|
|
92
|
+
type: "IntegrationTest.Successor",
|
|
93
|
+
identifier: "test-successor",
|
|
94
|
+
predecessor: randomRoot()
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(successor.identifier).toEqual("test-successor");
|
|
98
|
+
expect(successor.predecessor.type).toEqual("IntegrationTest.Root");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("should get the device identity", async () => {
|
|
102
|
+
const device = await j.local();
|
|
103
|
+
|
|
104
|
+
expect(device.type).toEqual("Jinaga.Device");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("should get device information", async () => {
|
|
108
|
+
const device = await j.local();
|
|
109
|
+
|
|
110
|
+
await j.fact({
|
|
111
|
+
type: "Configuration",
|
|
112
|
+
from: device
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await check(async j => {
|
|
116
|
+
const checkDevice = await j.local();
|
|
117
|
+
expect(checkDevice).toEqual(device);
|
|
118
|
+
|
|
119
|
+
const configurations = await j.query(checkDevice, j.for(configurationFromDevice));
|
|
120
|
+
|
|
121
|
+
expect(configurations.length).toEqual(1);
|
|
122
|
+
expect(configurations[0].type).toEqual("Configuration");
|
|
123
|
+
expect(configurations[0].from.type).toEqual("Jinaga.Device");
|
|
124
|
+
expect(configurations[0].from.publicKey).toEqual(checkDevice.publicKey);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("Jinaga as a user", () => {
|
|
130
|
+
let j;
|
|
131
|
+
let jDevice;
|
|
132
|
+
let close;
|
|
133
|
+
let done;
|
|
134
|
+
let session;
|
|
135
|
+
|
|
136
|
+
beforeEach(() => {
|
|
137
|
+
const promise = new Promise((resolve) => {
|
|
138
|
+
done = resolve;
|
|
139
|
+
});
|
|
140
|
+
({ j: jDevice, close, withSession } = JinagaServer.create({
|
|
141
|
+
pgKeystore: connectionString,
|
|
142
|
+
pgStore: connectionString,
|
|
143
|
+
authorization
|
|
144
|
+
}));
|
|
145
|
+
session = withSession({ user: {
|
|
146
|
+
provider: "test",
|
|
147
|
+
id: "test-user",
|
|
148
|
+
profile: {
|
|
149
|
+
displayName: "Test User"
|
|
150
|
+
}
|
|
151
|
+
} }, async jUser => {
|
|
152
|
+
j = jUser;
|
|
153
|
+
await promise;
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
afterEach(async () => {
|
|
158
|
+
done();
|
|
159
|
+
await session;
|
|
160
|
+
await close();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("should get the user identity", async () => {
|
|
164
|
+
const user = await j.login();
|
|
165
|
+
|
|
166
|
+
expect(user.userFact.type).toEqual("Jinaga.User");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should not allow an unauthorized fact", async () => {
|
|
170
|
+
try {
|
|
171
|
+
await j.fact({
|
|
172
|
+
type: "IntegrationTest.Unauthorized",
|
|
173
|
+
identifier: "test-unauthorized"
|
|
174
|
+
});
|
|
175
|
+
throw new Error("Expected fact to be rejected");
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
expect(e.message).toEqual("Rejected 1 fact of type IntegrationTest.Unauthorized.");
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("should save user name", async () => {
|
|
183
|
+
const { userFact: user, profile } = await j.login();
|
|
184
|
+
|
|
185
|
+
const userName = {
|
|
186
|
+
type: "MyApplication.UserName",
|
|
187
|
+
value: profile.displayName,
|
|
188
|
+
from: user,
|
|
189
|
+
prior: []
|
|
190
|
+
};
|
|
191
|
+
await j.fact(userName);
|
|
192
|
+
|
|
193
|
+
const userNames = await jDevice.query(user, Jinaga.for(namesOfUser));
|
|
194
|
+
|
|
195
|
+
expect(userNames.length).toEqual(1);
|
|
196
|
+
expect(userNames[0].value).toEqual("Test User");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("should set default tenant", async () => {
|
|
200
|
+
const { userFact: user } = await j.login();
|
|
201
|
+
const device = await j.local();
|
|
202
|
+
|
|
203
|
+
const defaultTenant = await j.fact({
|
|
204
|
+
type: "MyApplication.DefaultTenant",
|
|
205
|
+
tenant: {
|
|
206
|
+
type: "MyApplication.Tenant",
|
|
207
|
+
identifier: "test-tenant",
|
|
208
|
+
creator: user
|
|
209
|
+
},
|
|
210
|
+
device
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const defaultTenants = await jDevice.query(device, Jinaga.for(defaultTenantsOfDevice));
|
|
214
|
+
expect(defaultTenants).toEqual([defaultTenant]);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("should find no memberships", async () => {
|
|
218
|
+
const { userFact: user } = await j.login();
|
|
219
|
+
|
|
220
|
+
const memberships = await j.query(user, Jinaga.for(membershipsForUser));
|
|
221
|
+
expect(memberships).toEqual([]);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("should find assigned membership", async () => {
|
|
225
|
+
const { userFact: user } = await j.login();
|
|
226
|
+
|
|
227
|
+
const membership = await j.fact({
|
|
228
|
+
type: "MyApplication.Membership",
|
|
229
|
+
tenant: {
|
|
230
|
+
type: "MyApplication.Tenant",
|
|
231
|
+
identifier: "test-tenant",
|
|
232
|
+
creator: user
|
|
233
|
+
},
|
|
234
|
+
user
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const memberships = await j.query(user, Jinaga.for(membershipsForUser));
|
|
238
|
+
expect(memberships).toEqual([membership]);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("should not find deleted membership", async () => {
|
|
242
|
+
const { userFact: user } = await j.login();
|
|
243
|
+
|
|
244
|
+
const membership = await j.fact({
|
|
245
|
+
type: "MyApplication.Membership",
|
|
246
|
+
tenant: {
|
|
247
|
+
type: "MyApplication.Tenant",
|
|
248
|
+
identifier: "test-tenant",
|
|
249
|
+
creator: user
|
|
250
|
+
},
|
|
251
|
+
user
|
|
252
|
+
});
|
|
253
|
+
await j.fact({
|
|
254
|
+
type: "MyApplication.Membership.Deleted",
|
|
255
|
+
membership
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const memberships = await j.query(user, Jinaga.for(membershipsForUser));
|
|
259
|
+
expect(memberships).toEqual([]);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should find restored membership", async () => {
|
|
263
|
+
const { userFact: user } = await j.login();
|
|
264
|
+
|
|
265
|
+
const membership = await j.fact({
|
|
266
|
+
type: "MyApplication.Membership",
|
|
267
|
+
tenant: {
|
|
268
|
+
type: "MyApplication.Tenant",
|
|
269
|
+
identifier: "test-tenant",
|
|
270
|
+
creator: user
|
|
271
|
+
},
|
|
272
|
+
user
|
|
273
|
+
});
|
|
274
|
+
const deleted = await j.fact({
|
|
275
|
+
type: "MyApplication.Membership.Deleted",
|
|
276
|
+
membership
|
|
277
|
+
});
|
|
278
|
+
await j.fact({
|
|
279
|
+
type: "MyApplication.Membership.Restored",
|
|
280
|
+
deleted
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const memberships = await j.query(user, Jinaga.for(membershipsForUser));
|
|
284
|
+
expect(memberships).toEqual([membership]);
|
|
285
|
+
});
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
function randomRoot() {
|
|
289
|
+
const num = Math.random();
|
|
290
|
+
const identifier = encode(num);
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
type: "IntegrationTest.Root",
|
|
294
|
+
identifier
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function successorsOfRoot(root) {
|
|
299
|
+
return Jinaga.match({
|
|
300
|
+
type: "IntegrationTest.Successor",
|
|
301
|
+
predecessor: root
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function unknownOfRoot(root) {
|
|
306
|
+
return Jinaga.match({
|
|
307
|
+
type: "IntegrationTest.UnknownType",
|
|
308
|
+
predecessor: root
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function configurationFromDevice(device) {
|
|
313
|
+
return Jinaga.match({
|
|
314
|
+
type: "Configuration",
|
|
315
|
+
from: device
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function namesOfUser(user) {
|
|
320
|
+
return Jinaga.match({
|
|
321
|
+
type: "MyApplication.UserName",
|
|
322
|
+
from: user
|
|
323
|
+
}).suchThat(nameIsCurrent);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function nameIsCurrent(name) {
|
|
327
|
+
return Jinaga.notExists({
|
|
328
|
+
type: "MyApplication.UserName",
|
|
329
|
+
prior: [name]
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function nameUser(name) {
|
|
334
|
+
ensure(name).has("from", "Jinaga.User");
|
|
335
|
+
return Jinaga.match(name.from);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function defaultTenantIsCurrent(defaultTenant) {
|
|
339
|
+
return Jinaga.notExists({
|
|
340
|
+
type: "MyApplication.DefaultTenant",
|
|
341
|
+
prior: [defaultTenant]
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function defaultTenantsOfDevice(device) {
|
|
346
|
+
return Jinaga.match({
|
|
347
|
+
type: "MyApplication.DefaultTenant",
|
|
348
|
+
device
|
|
349
|
+
}).suchThat(defaultTenantIsCurrent);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function tenantCreator(tenant) {
|
|
353
|
+
ensure(tenant).has("creator", "Jinaga.User");
|
|
354
|
+
return Jinaga.match(tenant.creator);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function defaultTenantCreator(defaultTenant) {
|
|
358
|
+
ensure(defaultTenant)
|
|
359
|
+
.has("tenant", "MyApplication.Tenant")
|
|
360
|
+
.has("creator", "Jinaga.User");
|
|
361
|
+
return Jinaga.match(defaultTenant.tenant.creator);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function membershipsForUser(user) {
|
|
365
|
+
return Jinaga.match({
|
|
366
|
+
type: "MyApplication.Membership",
|
|
367
|
+
user
|
|
368
|
+
}).suchThat(Jinaga.not(membershipIsDeleted));
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function membershipIsDeleted(membership) {
|
|
372
|
+
return Jinaga.exists({
|
|
373
|
+
type: "MyApplication.Membership.Deleted",
|
|
374
|
+
membership
|
|
375
|
+
}).suchThat(Jinaga.not(membershipIsRestored));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function membershipIsRestored(deleted) {
|
|
379
|
+
return Jinaga.exists({
|
|
380
|
+
type: "MyApplication.Membership.Restored",
|
|
381
|
+
deleted
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function tenantOfMembership(membership) {
|
|
386
|
+
ensure(membership).has("tenant", "MyApplication.Tenant");
|
|
387
|
+
return Jinaga.match(membership.tenant);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function deletedMembership(deleted) {
|
|
391
|
+
ensure(deleted).has("membership", "MyApplication.Membership");
|
|
392
|
+
return Jinaga.match(deleted.membership);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function restoredMembership(restored) {
|
|
396
|
+
ensure(restored)
|
|
397
|
+
.has("deleted", "MyApplication.Membership.Deleted")
|
|
398
|
+
.has("membership", "MyApplication.Membership");
|
|
399
|
+
return Jinaga.match(restored.deleted.membership);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async function check(callback) {
|
|
403
|
+
const { j, close } = JinagaServer.create({
|
|
404
|
+
pgKeystore: connectionString,
|
|
405
|
+
pgStore: connectionString
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
try {
|
|
409
|
+
await callback(j);
|
|
410
|
+
}
|
|
411
|
+
finally {
|
|
412
|
+
await close();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function authorization(a) {
|
|
417
|
+
return a
|
|
418
|
+
.type("MyApplication.UserName", Jinaga.for(nameUser))
|
|
419
|
+
.type("MyApplication.Tenant", Jinaga.for(tenantCreator))
|
|
420
|
+
.type("MyApplication.DefaultTenant", Jinaga.for(defaultTenantCreator))
|
|
421
|
+
.type("MyApplication.Membership", Jinaga.for(tenantOfMembership).then(tenantCreator))
|
|
422
|
+
.type("MyApplication.Membership.Deleted", Jinaga.for(deletedMembership).then(tenantOfMembership).then(tenantCreator))
|
|
423
|
+
.type("MyApplication.Membership.Restored", Jinaga.for(restoredMembership).then(tenantOfMembership).then(tenantCreator))
|
|
424
|
+
;
|
|
425
|
+
}
|