jinaga-server 2.6.2 → 3.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/dist/authentication/authentication-device.js +27 -6
- package/dist/authentication/authentication-device.js.map +1 -1
- package/dist/authentication/authentication-session.js +27 -6
- package/dist/authentication/authentication-session.js.map +1 -1
- package/dist/authorization/authorization-keystore.d.ts +4 -5
- package/dist/authorization/authorization-keystore.js +42 -18
- package/dist/authorization/authorization-keystore.js.map +1 -1
- package/dist/http/router.d.ts +1 -2
- package/dist/http/router.js +13 -17
- package/dist/http/router.js.map +1 -1
- package/dist/jinaga-server.js +5 -6
- package/dist/jinaga-server.js.map +1 -1
- package/dist/postgres/postgres-store.d.ts +2 -5
- package/dist/postgres/postgres-store.js +44 -121
- package/dist/postgres/postgres-store.js.map +1 -1
- package/integration-test/jinaga-test/jinaga.test.js +247 -231
- package/integration-test/jinaga-test/package-lock.json +9 -52
- package/integration-test/jinaga-test/package.json +2 -5
- package/package.json +2 -3
- package/src/authentication/authentication-device.ts +29 -7
- package/src/authentication/authentication-session.ts +29 -7
- package/src/authorization/authorization-keystore.ts +42 -22
- package/src/http/router.ts +13 -23
- package/src/jinaga-server.ts +5 -6
- package/src/postgres/postgres-store.ts +63 -149
- package/test/authorization/authorizationSpec.ts +75 -89
- package/dist/postgres/sql.d.ts +0 -10
- package/dist/postgres/sql.js +0 -408
- package/dist/postgres/sql.js.map +0 -1
- package/src/postgres/sql.ts +0 -498
- package/test/postgres/postgresSpec.ts +0 -391
|
@@ -1,11 +1,217 @@
|
|
|
1
1
|
const { encode } = require("@stablelib/base64");
|
|
2
|
-
const {
|
|
2
|
+
const { buildModel, Device, User, UserName } = require("jinaga");
|
|
3
3
|
const { JinagaServer } = require("./jinaga-server");
|
|
4
4
|
|
|
5
5
|
const host = "db";
|
|
6
6
|
// const host = "localhost";
|
|
7
7
|
const connectionString = `postgresql://dev:devpw@${host}:5432/integrationtest`;
|
|
8
8
|
|
|
9
|
+
class Root {
|
|
10
|
+
static Type = "IntegrationTest.Root";
|
|
11
|
+
type = Root.Type;
|
|
12
|
+
|
|
13
|
+
constructor(identifier) {
|
|
14
|
+
this.identifier = identifier;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class Successor {
|
|
19
|
+
static Type = "IntegrationTest.Successor";
|
|
20
|
+
type = Successor.Type;
|
|
21
|
+
|
|
22
|
+
constructor(identifier, predecessor) {
|
|
23
|
+
this.identifier = identifier;
|
|
24
|
+
this.predecessor = predecessor;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class UnknownType {
|
|
29
|
+
static Type = "IntegrationTest.UnknownType";
|
|
30
|
+
type = UnknownType.Type;
|
|
31
|
+
|
|
32
|
+
constructor(predecessor) {
|
|
33
|
+
this.predecessor = predecessor;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class Configuration {
|
|
38
|
+
static Type = "Configuration";
|
|
39
|
+
type = Configuration.Type;
|
|
40
|
+
|
|
41
|
+
constructor(from) {
|
|
42
|
+
this.from = from;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class Tenant {
|
|
47
|
+
static Type = "MyApplication.Tenant";
|
|
48
|
+
type = Tenant.Type;
|
|
49
|
+
|
|
50
|
+
constructor(identifier, creator) {
|
|
51
|
+
this.identifier = identifier;
|
|
52
|
+
this.creator = creator;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class DefaultTenant {
|
|
57
|
+
static Type = "MyApplication.DefaultTenant";
|
|
58
|
+
type = DefaultTenant.Type;
|
|
59
|
+
|
|
60
|
+
constructor(tenant, device, prior) {
|
|
61
|
+
this.tenant = tenant;
|
|
62
|
+
this.device = device;
|
|
63
|
+
this.prior = prior;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class Membership {
|
|
68
|
+
static Type = "MyApplication.Membership";
|
|
69
|
+
type = Membership.Type;
|
|
70
|
+
|
|
71
|
+
constructor(tenant, creator) {
|
|
72
|
+
this.tenant = tenant;
|
|
73
|
+
this.creator = creator;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class MembershipDeleted {
|
|
78
|
+
static Type = "MyApplication.Membership.Deleted";
|
|
79
|
+
type = MembershipDeleted.Type;
|
|
80
|
+
|
|
81
|
+
constructor(membership) {
|
|
82
|
+
this.membership = membership;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
class MembershipRestored {
|
|
87
|
+
static Type = "MyApplication.Membership.Restored";
|
|
88
|
+
type = MembershipRestored.Type;
|
|
89
|
+
|
|
90
|
+
constructor(deleted) {
|
|
91
|
+
this.deleted = deleted;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const model = buildModel(b => b
|
|
96
|
+
.type(Root)
|
|
97
|
+
.type(Successor, m => m
|
|
98
|
+
.predecessor("predecessor", Root)
|
|
99
|
+
)
|
|
100
|
+
.type(UnknownType, m => m
|
|
101
|
+
.predecessor("predecessor", Root)
|
|
102
|
+
)
|
|
103
|
+
.type(User)
|
|
104
|
+
.type(UserName, m => m
|
|
105
|
+
.predecessor("user", User)
|
|
106
|
+
.predecessor("prior", UserName)
|
|
107
|
+
)
|
|
108
|
+
.type(Device)
|
|
109
|
+
.type(Configuration, m => m
|
|
110
|
+
.predecessor("from", Device)
|
|
111
|
+
)
|
|
112
|
+
.type(Tenant, m => m
|
|
113
|
+
.predecessor("creator", User)
|
|
114
|
+
)
|
|
115
|
+
.type(DefaultTenant, m => m
|
|
116
|
+
.predecessor("tenant", Tenant)
|
|
117
|
+
.predecessor("device", Device)
|
|
118
|
+
.predecessor("prior", DefaultTenant)
|
|
119
|
+
)
|
|
120
|
+
.type(Membership, m => m
|
|
121
|
+
.predecessor("tenant", Tenant)
|
|
122
|
+
.predecessor("creator", User)
|
|
123
|
+
)
|
|
124
|
+
.type(MembershipDeleted, m => m
|
|
125
|
+
.predecessor("membership", Membership)
|
|
126
|
+
)
|
|
127
|
+
.type(MembershipRestored, m => m
|
|
128
|
+
.predecessor("deleted", MembershipDeleted)
|
|
129
|
+
)
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
function randomIdentifier() {
|
|
133
|
+
const bytes = new Uint8Array(8);
|
|
134
|
+
for (let i = 0; i < 8; i++) {
|
|
135
|
+
bytes[i] = Math.random() * 0xFF;
|
|
136
|
+
}
|
|
137
|
+
return encode(bytes);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function randomRoot() {
|
|
141
|
+
return new Root(randomIdentifier());
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function randomTenant(creator) {
|
|
145
|
+
return new Tenant(randomIdentifier(), creator);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const successorsOfRoot = model.given(Root).match((root, facts) =>
|
|
149
|
+
facts.ofType(Successor)
|
|
150
|
+
.join(s => s.predecessor, root)
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const unknownOfRoot = model.given(Root).match((root, facts) =>
|
|
154
|
+
facts.ofType(UnknownType)
|
|
155
|
+
.join(s => s.predecessor, root)
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const configurationFromDevice = model.given(Device).match((device, facts) =>
|
|
159
|
+
facts.ofType(Configuration)
|
|
160
|
+
.join(s => s.from, device)
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const namesOfUser = model.given(User).match((user, facts) =>
|
|
164
|
+
facts.ofType(UserName)
|
|
165
|
+
.join(name => name.user, user)
|
|
166
|
+
.notExists(name => facts.ofType(UserName)
|
|
167
|
+
.join(next => next.prior, name)
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const defaultTenantsOfDevice = model.given(Device).match((device, facts) =>
|
|
172
|
+
facts.ofType(DefaultTenant)
|
|
173
|
+
.join(defaultTenant => defaultTenant.device, device)
|
|
174
|
+
.notExists(defaultTenant => facts.ofType(DefaultTenant)
|
|
175
|
+
.join(next => next.prior, defaultTenant)
|
|
176
|
+
)
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const membershipsForUser = model.given(User).match((user, facts) =>
|
|
180
|
+
facts.ofType(Membership)
|
|
181
|
+
.join(membership => membership.creator, user)
|
|
182
|
+
.notExists(membership => facts.ofType(MembershipDeleted)
|
|
183
|
+
.join(deleted => deleted.membership, membership)
|
|
184
|
+
.notExists(deleted => facts.ofType(MembershipRestored)
|
|
185
|
+
.join(restored => restored.deleted, deleted)
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
async function check(callback) {
|
|
191
|
+
const { j, close } = JinagaServer.create({
|
|
192
|
+
pgKeystore: connectionString,
|
|
193
|
+
pgStore: connectionString
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
await callback(j);
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
await close();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function authorization(a) {
|
|
205
|
+
return a
|
|
206
|
+
.type(UserName, n => n.user)
|
|
207
|
+
.type(Tenant, t => t.creator)
|
|
208
|
+
.type(DefaultTenant, t => t.tenant.creator)
|
|
209
|
+
.type(Membership, m => m.tenant.creator)
|
|
210
|
+
.type(MembershipDeleted, d => d.membership.tenant.creator)
|
|
211
|
+
.type(MembershipRestored, r => r.deleted.membership.tenant.creator)
|
|
212
|
+
;
|
|
213
|
+
}
|
|
214
|
+
|
|
9
215
|
describe("Jinaga as a device", () => {
|
|
10
216
|
let j;
|
|
11
217
|
let close;
|
|
@@ -39,11 +245,7 @@ describe("Jinaga as a device", () => {
|
|
|
39
245
|
it("should save a successor fact", async () => {
|
|
40
246
|
const root = await j.fact(randomRoot());
|
|
41
247
|
|
|
42
|
-
const successor = await j.fact(
|
|
43
|
-
type: "IntegrationTest.Successor",
|
|
44
|
-
identifier: "test-successor",
|
|
45
|
-
predecessor: root
|
|
46
|
-
});
|
|
248
|
+
const successor = await j.fact(new Successor("test-successor", root));
|
|
47
249
|
|
|
48
250
|
expect(successor.identifier).toEqual("test-successor");
|
|
49
251
|
expect(successor.predecessor).toEqual(root);
|
|
@@ -52,19 +254,15 @@ describe("Jinaga as a device", () => {
|
|
|
52
254
|
it("should query a successor fact", async () => {
|
|
53
255
|
const root = await j.fact(randomRoot());
|
|
54
256
|
|
|
55
|
-
const successor = await j.fact(
|
|
56
|
-
|
|
57
|
-
identifier: "test-successor",
|
|
58
|
-
predecessor: root
|
|
59
|
-
});
|
|
60
|
-
const successors = await j.query(root, j.for(successorsOfRoot));
|
|
257
|
+
const successor = await j.fact(new Successor("test-successor", root));
|
|
258
|
+
const successors = await j.query(successorsOfRoot, root);
|
|
61
259
|
|
|
62
260
|
expect(successors).toEqual([successor]);
|
|
63
261
|
})
|
|
64
262
|
|
|
65
263
|
it("should query a type that has never been seen", async () => {
|
|
66
264
|
const root = await j.fact(randomRoot());
|
|
67
|
-
const unknown = await j.query(
|
|
265
|
+
const unknown = await j.query(unknownOfRoot, root);
|
|
68
266
|
|
|
69
267
|
expect(unknown).toEqual([]);
|
|
70
268
|
});
|
|
@@ -72,16 +270,8 @@ describe("Jinaga as a device", () => {
|
|
|
72
270
|
it("should save a successor fact twice", async () => {
|
|
73
271
|
const root = await j.fact(randomRoot());
|
|
74
272
|
|
|
75
|
-
await j.fact(
|
|
76
|
-
|
|
77
|
-
identifier: "test-successor",
|
|
78
|
-
predecessor: root
|
|
79
|
-
});
|
|
80
|
-
const successor = await j.fact({
|
|
81
|
-
type: "IntegrationTest.Successor",
|
|
82
|
-
identifier: "test-successor",
|
|
83
|
-
predecessor: root
|
|
84
|
-
});
|
|
273
|
+
await j.fact(new Successor("test-successor", root));
|
|
274
|
+
const successor = await j.fact(new Successor("test-successor", root));
|
|
85
275
|
|
|
86
276
|
expect(successor.identifier).toEqual("test-successor");
|
|
87
277
|
expect(successor.predecessor).toEqual(root);
|
|
@@ -89,11 +279,7 @@ describe("Jinaga as a device", () => {
|
|
|
89
279
|
|
|
90
280
|
|
|
91
281
|
it("should save multiple facts", async () => {
|
|
92
|
-
const successor = await j.fact(
|
|
93
|
-
type: "IntegrationTest.Successor",
|
|
94
|
-
identifier: "test-successor",
|
|
95
|
-
predecessor: randomRoot()
|
|
96
|
-
});
|
|
282
|
+
const successor = await j.fact(new Successor("test-successor", randomRoot()));
|
|
97
283
|
|
|
98
284
|
expect(successor.identifier).toEqual("test-successor");
|
|
99
285
|
expect(successor.predecessor.type).toEqual("IntegrationTest.Root");
|
|
@@ -108,16 +294,13 @@ describe("Jinaga as a device", () => {
|
|
|
108
294
|
it("should get device information", async () => {
|
|
109
295
|
const device = await j.local();
|
|
110
296
|
|
|
111
|
-
await j.fact(
|
|
112
|
-
type: "Configuration",
|
|
113
|
-
from: device
|
|
114
|
-
});
|
|
297
|
+
await j.fact(new Configuration(device));
|
|
115
298
|
|
|
116
299
|
await check(async j => {
|
|
117
300
|
const checkDevice = await j.local();
|
|
118
301
|
expect(checkDevice).toEqual(device);
|
|
119
302
|
|
|
120
|
-
const configurations = await j.query(
|
|
303
|
+
const configurations = await j.query(configurationFromDevice, checkDevice);
|
|
121
304
|
|
|
122
305
|
expect(configurations.length).toEqual(1);
|
|
123
306
|
expect(configurations[0].type).toEqual("Configuration");
|
|
@@ -139,13 +322,14 @@ describe("Jinaga as a user", () => {
|
|
|
139
322
|
done = resolve;
|
|
140
323
|
});
|
|
141
324
|
({ j: jDevice, close, withSession } = JinagaServer.create({
|
|
325
|
+
model,
|
|
142
326
|
pgKeystore: connectionString,
|
|
143
327
|
pgStore: connectionString,
|
|
144
328
|
authorization
|
|
145
329
|
}));
|
|
146
330
|
session = withSession({ user: {
|
|
147
331
|
provider: "test",
|
|
148
|
-
id:
|
|
332
|
+
id: randomIdentifier(),
|
|
149
333
|
profile: {
|
|
150
334
|
displayName: "Test User"
|
|
151
335
|
}
|
|
@@ -168,6 +352,8 @@ describe("Jinaga as a user", () => {
|
|
|
168
352
|
});
|
|
169
353
|
|
|
170
354
|
it("should not allow an unauthorized fact", async () => {
|
|
355
|
+
await j.login();
|
|
356
|
+
|
|
171
357
|
try {
|
|
172
358
|
await j.fact({
|
|
173
359
|
type: "IntegrationTest.Unauthorized",
|
|
@@ -183,15 +369,10 @@ describe("Jinaga as a user", () => {
|
|
|
183
369
|
it("should save user name", async () => {
|
|
184
370
|
const { userFact: user, profile } = await j.login();
|
|
185
371
|
|
|
186
|
-
const userName =
|
|
187
|
-
type: "MyApplication.UserName",
|
|
188
|
-
value: profile.displayName,
|
|
189
|
-
from: user,
|
|
190
|
-
prior: []
|
|
191
|
-
};
|
|
372
|
+
const userName = new UserName([], user, profile.displayName);
|
|
192
373
|
await j.fact(userName);
|
|
193
374
|
|
|
194
|
-
const userNames = await jDevice.query(
|
|
375
|
+
const userNames = await jDevice.query(namesOfUser, user);
|
|
195
376
|
|
|
196
377
|
expect(userNames.length).toEqual(1);
|
|
197
378
|
expect(userNames[0].value).toEqual("Test User");
|
|
@@ -201,226 +382,61 @@ describe("Jinaga as a user", () => {
|
|
|
201
382
|
const { userFact: user } = await j.login();
|
|
202
383
|
const device = await j.local();
|
|
203
384
|
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
device
|
|
212
|
-
});
|
|
385
|
+
const prior = await jDevice.query(defaultTenantsOfDevice, device);
|
|
386
|
+
|
|
387
|
+
const defaultTenant = await j.fact(new DefaultTenant(
|
|
388
|
+
randomTenant(user),
|
|
389
|
+
device,
|
|
390
|
+
prior
|
|
391
|
+
));
|
|
213
392
|
|
|
214
|
-
const defaultTenants = await jDevice.query(
|
|
393
|
+
const defaultTenants = await jDevice.query(defaultTenantsOfDevice, device);
|
|
215
394
|
expect(defaultTenants).toEqual([defaultTenant]);
|
|
216
395
|
});
|
|
217
396
|
|
|
218
397
|
it("should find no memberships", async () => {
|
|
219
398
|
const { userFact: user } = await j.login();
|
|
220
399
|
|
|
221
|
-
const memberships = await j.query(
|
|
400
|
+
const memberships = await j.query(membershipsForUser, user);
|
|
222
401
|
expect(memberships).toEqual([]);
|
|
223
402
|
});
|
|
224
403
|
|
|
225
404
|
it("should find assigned membership", async () => {
|
|
226
405
|
const { userFact: user } = await j.login();
|
|
227
406
|
|
|
228
|
-
const membership = await j.fact(
|
|
229
|
-
|
|
230
|
-
tenant: {
|
|
231
|
-
type: "MyApplication.Tenant",
|
|
232
|
-
identifier: "test-tenant",
|
|
233
|
-
creator: user
|
|
234
|
-
},
|
|
407
|
+
const membership = await j.fact(new Membership(
|
|
408
|
+
randomTenant(user),
|
|
235
409
|
user
|
|
236
|
-
|
|
410
|
+
));
|
|
237
411
|
|
|
238
|
-
const memberships = await j.query(
|
|
412
|
+
const memberships = await j.query(membershipsForUser, user);
|
|
239
413
|
expect(memberships).toEqual([membership]);
|
|
240
414
|
});
|
|
241
415
|
|
|
242
416
|
it("should not find deleted membership", async () => {
|
|
243
417
|
const { userFact: user } = await j.login();
|
|
244
418
|
|
|
245
|
-
const membership = await j.fact(
|
|
246
|
-
|
|
247
|
-
tenant: {
|
|
248
|
-
type: "MyApplication.Tenant",
|
|
249
|
-
identifier: "test-tenant",
|
|
250
|
-
creator: user
|
|
251
|
-
},
|
|
419
|
+
const membership = await j.fact(new Membership(
|
|
420
|
+
randomTenant(user),
|
|
252
421
|
user
|
|
253
|
-
|
|
254
|
-
await j.fact(
|
|
255
|
-
type: "MyApplication.Membership.Deleted",
|
|
256
|
-
membership
|
|
257
|
-
});
|
|
422
|
+
));
|
|
423
|
+
await j.fact(new MembershipDeleted(membership));
|
|
258
424
|
|
|
259
|
-
const memberships = await j.query(
|
|
425
|
+
const memberships = await j.query(membershipsForUser, user);
|
|
260
426
|
expect(memberships).toEqual([]);
|
|
261
427
|
});
|
|
262
428
|
|
|
263
429
|
it("should find restored membership", async () => {
|
|
264
430
|
const { userFact: user } = await j.login();
|
|
265
431
|
|
|
266
|
-
const membership = await j.fact(
|
|
267
|
-
|
|
268
|
-
tenant: {
|
|
269
|
-
type: "MyApplication.Tenant",
|
|
270
|
-
identifier: "test-tenant",
|
|
271
|
-
creator: user
|
|
272
|
-
},
|
|
432
|
+
const membership = await j.fact(new Membership(
|
|
433
|
+
randomTenant(user),
|
|
273
434
|
user
|
|
274
|
-
|
|
275
|
-
const deleted = await j.fact(
|
|
276
|
-
|
|
277
|
-
membership
|
|
278
|
-
});
|
|
279
|
-
await j.fact({
|
|
280
|
-
type: "MyApplication.Membership.Restored",
|
|
281
|
-
deleted
|
|
282
|
-
});
|
|
435
|
+
));
|
|
436
|
+
const deleted = await j.fact(new MembershipDeleted(membership));
|
|
437
|
+
await j.fact(new MembershipRestored(deleted));
|
|
283
438
|
|
|
284
|
-
const memberships = await j.query(
|
|
439
|
+
const memberships = await j.query(membershipsForUser, user);
|
|
285
440
|
expect(memberships).toEqual([membership]);
|
|
286
441
|
});
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
function randomRoot() {
|
|
290
|
-
const num = Math.random();
|
|
291
|
-
const identifier = encode(num);
|
|
292
|
-
|
|
293
|
-
return {
|
|
294
|
-
type: "IntegrationTest.Root",
|
|
295
|
-
identifier
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function successorsOfRoot(root) {
|
|
300
|
-
return Jinaga.match({
|
|
301
|
-
type: "IntegrationTest.Successor",
|
|
302
|
-
predecessor: root
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function unknownOfRoot(root) {
|
|
307
|
-
return Jinaga.match({
|
|
308
|
-
type: "IntegrationTest.UnknownType",
|
|
309
|
-
predecessor: root
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function configurationFromDevice(device) {
|
|
314
|
-
return Jinaga.match({
|
|
315
|
-
type: "Configuration",
|
|
316
|
-
from: device
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function namesOfUser(user) {
|
|
321
|
-
return Jinaga.match({
|
|
322
|
-
type: "MyApplication.UserName",
|
|
323
|
-
from: user
|
|
324
|
-
}).suchThat(nameIsCurrent);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function nameIsCurrent(name) {
|
|
328
|
-
return Jinaga.notExists({
|
|
329
|
-
type: "MyApplication.UserName",
|
|
330
|
-
prior: [name]
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
function nameUser(name) {
|
|
335
|
-
ensure(name).has("from", "Jinaga.User");
|
|
336
|
-
return Jinaga.match(name.from);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function defaultTenantIsCurrent(defaultTenant) {
|
|
340
|
-
return Jinaga.notExists({
|
|
341
|
-
type: "MyApplication.DefaultTenant",
|
|
342
|
-
prior: [defaultTenant]
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function defaultTenantsOfDevice(device) {
|
|
347
|
-
return Jinaga.match({
|
|
348
|
-
type: "MyApplication.DefaultTenant",
|
|
349
|
-
device
|
|
350
|
-
}).suchThat(defaultTenantIsCurrent);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function tenantCreator(tenant) {
|
|
354
|
-
ensure(tenant).has("creator", "Jinaga.User");
|
|
355
|
-
return Jinaga.match(tenant.creator);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function defaultTenantCreator(defaultTenant) {
|
|
359
|
-
ensure(defaultTenant)
|
|
360
|
-
.has("tenant", "MyApplication.Tenant")
|
|
361
|
-
.has("creator", "Jinaga.User");
|
|
362
|
-
return Jinaga.match(defaultTenant.tenant.creator);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function membershipsForUser(user) {
|
|
366
|
-
return Jinaga.match({
|
|
367
|
-
type: "MyApplication.Membership",
|
|
368
|
-
user
|
|
369
|
-
}).suchThat(Jinaga.not(membershipIsDeleted));
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
function membershipIsDeleted(membership) {
|
|
373
|
-
return Jinaga.exists({
|
|
374
|
-
type: "MyApplication.Membership.Deleted",
|
|
375
|
-
membership
|
|
376
|
-
}).suchThat(Jinaga.not(membershipIsRestored));
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function membershipIsRestored(deleted) {
|
|
380
|
-
return Jinaga.exists({
|
|
381
|
-
type: "MyApplication.Membership.Restored",
|
|
382
|
-
deleted
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
function tenantOfMembership(membership) {
|
|
387
|
-
ensure(membership).has("tenant", "MyApplication.Tenant");
|
|
388
|
-
return Jinaga.match(membership.tenant);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
function deletedMembership(deleted) {
|
|
392
|
-
ensure(deleted).has("membership", "MyApplication.Membership");
|
|
393
|
-
return Jinaga.match(deleted.membership);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function restoredMembership(restored) {
|
|
397
|
-
ensure(restored)
|
|
398
|
-
.has("deleted", "MyApplication.Membership.Deleted")
|
|
399
|
-
.has("membership", "MyApplication.Membership");
|
|
400
|
-
return Jinaga.match(restored.deleted.membership);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
async function check(callback) {
|
|
404
|
-
const { j, close } = JinagaServer.create({
|
|
405
|
-
pgKeystore: connectionString,
|
|
406
|
-
pgStore: connectionString
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
try {
|
|
410
|
-
await callback(j);
|
|
411
|
-
}
|
|
412
|
-
finally {
|
|
413
|
-
await close();
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
function authorization(a) {
|
|
418
|
-
return a
|
|
419
|
-
.type("MyApplication.UserName", Jinaga.for(nameUser))
|
|
420
|
-
.type("MyApplication.Tenant", Jinaga.for(tenantCreator))
|
|
421
|
-
.type("MyApplication.DefaultTenant", Jinaga.for(defaultTenantCreator))
|
|
422
|
-
.type("MyApplication.Membership", Jinaga.for(tenantOfMembership).then(tenantCreator))
|
|
423
|
-
.type("MyApplication.Membership.Deleted", Jinaga.for(deletedMembership).then(tenantOfMembership).then(tenantCreator))
|
|
424
|
-
.type("MyApplication.Membership.Restored", Jinaga.for(restoredMembership).then(tenantOfMembership).then(tenantCreator))
|
|
425
|
-
;
|
|
426
|
-
}
|
|
442
|
+
})
|
|
@@ -13,12 +13,9 @@
|
|
|
13
13
|
"express": "^4.17.2",
|
|
14
14
|
"jest": "^29.7.0",
|
|
15
15
|
"jest-compact-reporter": "^1.2.9",
|
|
16
|
-
"jinaga": "^
|
|
16
|
+
"jinaga": "^6.0.0",
|
|
17
17
|
"node-forge": "^1.3.0",
|
|
18
|
-
"
|
|
19
|
-
"pg": "^8.11.3",
|
|
20
|
-
"tweetnacl": "^1.0.3",
|
|
21
|
-
"tweetnacl-util": "^0.15.1"
|
|
18
|
+
"pg": "^8.11.3"
|
|
22
19
|
}
|
|
23
20
|
},
|
|
24
21
|
"node_modules/@ampproject/remapping": {
|
|
@@ -1031,9 +1028,9 @@
|
|
|
1031
1028
|
}
|
|
1032
1029
|
},
|
|
1033
1030
|
"node_modules/@stablelib/utf8": {
|
|
1034
|
-
"version": "1.0.
|
|
1035
|
-
"resolved": "https://registry.npmjs.org/@stablelib/utf8/-/utf8-1.0.
|
|
1036
|
-
"integrity": "sha512-
|
|
1031
|
+
"version": "1.0.2",
|
|
1032
|
+
"resolved": "https://registry.npmjs.org/@stablelib/utf8/-/utf8-1.0.2.tgz",
|
|
1033
|
+
"integrity": "sha512-sDL1aB2U8FIpj7SjQJMxbOFIFkKvDKQGPHSrYejHZhtLNSK3qHe6ZIfa0woWkOiaJsdYslFzrc0VWXJZHmSIQQ=="
|
|
1037
1034
|
},
|
|
1038
1035
|
"node_modules/@stablelib/wipe": {
|
|
1039
1036
|
"version": "1.0.1",
|
|
@@ -2894,13 +2891,13 @@
|
|
|
2894
2891
|
}
|
|
2895
2892
|
},
|
|
2896
2893
|
"node_modules/jinaga": {
|
|
2897
|
-
"version": "
|
|
2898
|
-
"resolved": "https://registry.npmjs.org/jinaga/-/jinaga-
|
|
2899
|
-
"integrity": "sha512-
|
|
2894
|
+
"version": "6.0.0",
|
|
2895
|
+
"resolved": "https://registry.npmjs.org/jinaga/-/jinaga-6.0.0.tgz",
|
|
2896
|
+
"integrity": "sha512-LWUCAO5L3FQgM+SBVHQYlZ2ot1TkPgdDp3SzhfmhgPN9Vapv5l15zKtUs0ggPHECvAskRMmAZIDXWHC3rt0pmg==",
|
|
2900
2897
|
"dependencies": {
|
|
2901
2898
|
"@stablelib/base64": "^1.0.1",
|
|
2902
2899
|
"@stablelib/sha512": "^1.0.1",
|
|
2903
|
-
"@stablelib/utf8": "^1.0.
|
|
2900
|
+
"@stablelib/utf8": "^1.0.2"
|
|
2904
2901
|
},
|
|
2905
2902
|
"engines": {
|
|
2906
2903
|
"node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
|
|
@@ -3302,31 +3299,6 @@
|
|
|
3302
3299
|
"node": ">= 0.8"
|
|
3303
3300
|
}
|
|
3304
3301
|
},
|
|
3305
|
-
"node_modules/passport": {
|
|
3306
|
-
"version": "0.6.0",
|
|
3307
|
-
"resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz",
|
|
3308
|
-
"integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==",
|
|
3309
|
-
"dependencies": {
|
|
3310
|
-
"passport-strategy": "1.x.x",
|
|
3311
|
-
"pause": "0.0.1",
|
|
3312
|
-
"utils-merge": "^1.0.1"
|
|
3313
|
-
},
|
|
3314
|
-
"engines": {
|
|
3315
|
-
"node": ">= 0.4.0"
|
|
3316
|
-
},
|
|
3317
|
-
"funding": {
|
|
3318
|
-
"type": "github",
|
|
3319
|
-
"url": "https://github.com/sponsors/jaredhanson"
|
|
3320
|
-
}
|
|
3321
|
-
},
|
|
3322
|
-
"node_modules/passport-strategy": {
|
|
3323
|
-
"version": "1.0.0",
|
|
3324
|
-
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
|
|
3325
|
-
"integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==",
|
|
3326
|
-
"engines": {
|
|
3327
|
-
"node": ">= 0.4.0"
|
|
3328
|
-
}
|
|
3329
|
-
},
|
|
3330
3302
|
"node_modules/path-exists": {
|
|
3331
3303
|
"version": "4.0.0",
|
|
3332
3304
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
|
@@ -3361,11 +3333,6 @@
|
|
|
3361
3333
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
|
3362
3334
|
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
|
3363
3335
|
},
|
|
3364
|
-
"node_modules/pause": {
|
|
3365
|
-
"version": "0.0.1",
|
|
3366
|
-
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
|
|
3367
|
-
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
|
|
3368
|
-
},
|
|
3369
3336
|
"node_modules/pg": {
|
|
3370
3337
|
"version": "8.11.3",
|
|
3371
3338
|
"resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz",
|
|
@@ -3982,16 +3949,6 @@
|
|
|
3982
3949
|
"node": ">=0.6"
|
|
3983
3950
|
}
|
|
3984
3951
|
},
|
|
3985
|
-
"node_modules/tweetnacl": {
|
|
3986
|
-
"version": "1.0.3",
|
|
3987
|
-
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
|
3988
|
-
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
|
|
3989
|
-
},
|
|
3990
|
-
"node_modules/tweetnacl-util": {
|
|
3991
|
-
"version": "0.15.1",
|
|
3992
|
-
"resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
|
|
3993
|
-
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw=="
|
|
3994
|
-
},
|
|
3995
3952
|
"node_modules/type-detect": {
|
|
3996
3953
|
"version": "4.0.8",
|
|
3997
3954
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|