jinaga-server 1.1.4 → 2.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/README.md +12 -0
- package/dist/authentication/authentication-device.d.ts +3 -2
- package/dist/authentication/authentication-device.js +6 -0
- package/dist/authentication/authentication-device.js.map +1 -1
- package/dist/authentication/authentication-impl.d.ts +3 -2
- package/dist/authentication/authentication-impl.js +6 -0
- package/dist/authentication/authentication-impl.js.map +1 -1
- package/dist/authentication/authentication-noop.d.ts +20 -0
- package/dist/authentication/authentication-noop.js +52 -0
- package/dist/authentication/authentication-noop.js.map +1 -0
- package/dist/authentication/authentication-session.d.ts +3 -2
- package/dist/authentication/authentication-session.js +6 -0
- package/dist/authentication/authentication-session.js.map +1 -1
- package/dist/authentication.d.ts +3 -2
- package/dist/authentication.js +6 -0
- package/dist/authentication.js.map +1 -1
- package/dist/authorization/authorization-keystore.d.ts +3 -4
- package/dist/authorization/authorization-keystore.js +9 -4
- package/dist/authorization/authorization-keystore.js.map +1 -1
- package/dist/debug.d.ts +1 -0
- package/dist/debug.js +30 -0
- package/dist/debug.js.map +1 -0
- package/dist/http/router.js.map +1 -1
- package/dist/jinaga-server.js +15 -7
- package/dist/jinaga-server.js.map +1 -1
- package/dist/memory/memory-keystore.js +0 -6
- package/dist/memory/memory-keystore.js.map +1 -1
- package/dist/postgres/connection.js +1 -0
- package/dist/postgres/connection.js.map +1 -1
- package/dist/postgres/maps.d.ts +7 -6
- package/dist/postgres/maps.js +9 -1
- package/dist/postgres/maps.js.map +1 -1
- package/dist/postgres/postgres-keystore.js +0 -6
- package/dist/postgres/postgres-keystore.js.map +1 -1
- package/dist/postgres/postgres-store.d.ts +1 -2
- package/dist/postgres/postgres-store.js +29 -24
- package/dist/postgres/postgres-store.js.map +1 -1
- package/dist/postgres/specification-result-sql.d.ts +4 -4
- package/dist/postgres/specification-result-sql.js +34 -24
- package/dist/postgres/specification-result-sql.js.map +1 -1
- package/dist/postgres/specification-sql.js.map +1 -1
- package/dist/postgres/sql.d.ts +1 -1
- package/dist/postgres/sql.js +15 -7
- package/dist/postgres/sql.js.map +1 -1
- package/dist/util/maps.d.ts +0 -0
- package/dist/util/maps.js +2 -0
- package/dist/util/maps.js.map +1 -0
- package/docs/sql/SQL Generator (projection).png +0 -0
- package/docs/sql/SQLFromSpecification.md +2 -0
- package/integration-test/jinaga-test/Dockerfile +2 -2
- package/integration-test/jinaga-test/jinaga.test.js +3 -3
- package/integration-test/jinaga-test/package-lock.json +745 -3484
- package/integration-test/jinaga-test/package.json +2 -0
- package/integration-test/run.sh +3 -3
- package/package.json +5 -6
- package/replicator/index.ts +31 -0
- package/replicator/package-lock.json +855 -0
- package/replicator/package.json +27 -0
- package/replicator/tsconfig.json +15 -0
- package/src/authentication/authentication-device.ts +11 -1
- package/src/authentication/authentication-impl.ts +9 -2
- package/src/authentication/authentication-noop.ts +65 -0
- package/src/authentication/authentication-session.ts +11 -1
- package/src/authentication.ts +12 -2
- package/src/authorization/authorization-keystore.ts +12 -7
- package/src/debug.ts +30 -0
- package/src/http/router.ts +2 -2
- package/src/jinaga-server.ts +18 -8
- package/src/memory/memory-keystore.ts +0 -6
- package/src/postgres/connection.ts +2 -1
- package/src/postgres/maps.ts +8 -0
- package/src/postgres/postgres-keystore.ts +2 -8
- package/src/postgres/postgres-store.ts +37 -30
- package/src/postgres/specification-result-sql.ts +56 -45
- package/src/postgres/specification-sql.ts +1 -1
- package/src/postgres/sql.ts +23 -12
- package/src/util/maps.ts +0 -0
- package/test/postgres/postgresReadSpec.ts +4 -1
- package/test/postgres/postgresSpec.ts +31 -31
- package/test/postgres/postgresSpecificationSpec.ts +1 -1
- package/tsconfig.json +1 -0
- package/tsconfig.test.json +26 -0
- package/docs/specification.txt +0 -41
- package/interactive/index.js +0 -56
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jinaga-replicator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A unit of fact storage and distribution within a Jinaga network",
|
|
5
|
+
"main": "dist/replicator/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
|
+
"start": "node dist/replicator"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"Jinaga",
|
|
13
|
+
"CRDT"
|
|
14
|
+
],
|
|
15
|
+
"author": "Michael L Perry",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"cors": "^2.8.5",
|
|
19
|
+
"express": "^4.18.1",
|
|
20
|
+
"pg": "^8.7.3"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/cors": "^2.8.12",
|
|
24
|
+
"@types/express": "^4.17.13",
|
|
25
|
+
"typescript": "^4.7.4"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es6",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"sourceMap": true,
|
|
6
|
+
"baseUrl": "./dist",
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"paths": {
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Channel,
|
|
3
3
|
FactEnvelope,
|
|
4
|
+
FactFeed,
|
|
4
5
|
FactRecord,
|
|
5
6
|
FactReference,
|
|
6
7
|
Feed,
|
|
7
8
|
Fork,
|
|
8
9
|
LoginResponse,
|
|
9
10
|
Observable,
|
|
11
|
+
ProjectedResult,
|
|
10
12
|
Query,
|
|
11
13
|
Specification,
|
|
14
|
+
SpecificationListener,
|
|
12
15
|
UserIdentity,
|
|
13
16
|
} from "jinaga";
|
|
14
|
-
import { FactFeed } from "jinaga/dist/storage";
|
|
15
17
|
|
|
16
18
|
import { Keystore } from "../keystore";
|
|
17
19
|
import { Authentication } from "./authentication";
|
|
@@ -40,6 +42,14 @@ export class AuthenticationDevice implements Authentication {
|
|
|
40
42
|
return this.inner.from(fact, query);
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
addSpecificationListener(specification: Specification, onResult: (results: ProjectedResult[]) => Promise<void>): SpecificationListener {
|
|
46
|
+
return this.inner.addSpecificationListener(specification, onResult);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
removeSpecificationListener(listener: SpecificationListener): void {
|
|
50
|
+
this.inner.removeSpecificationListener(listener);
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
save(envelopes: FactEnvelope[]): Promise<FactEnvelope[]> {
|
|
44
54
|
return this.inner.save(envelopes);
|
|
45
55
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Channel, FactEnvelope, FactRecord, FactReference, Feed, Fork, Observable, Query, Specification, WebClient } from "jinaga";
|
|
2
|
-
import { FactFeed } from "jinaga/dist/storage";
|
|
1
|
+
import { Channel, FactEnvelope, FactFeed, FactRecord, FactReference, Feed, Fork, Observable, ProjectedResult, Query, Specification, SpecificationListener, WebClient } from "jinaga";
|
|
3
2
|
|
|
4
3
|
import { Authentication } from "./authentication";
|
|
5
4
|
|
|
@@ -52,6 +51,14 @@ export class AuthenticationImpl implements Authentication {
|
|
|
52
51
|
return this.inner.from(fact, query);
|
|
53
52
|
}
|
|
54
53
|
|
|
54
|
+
addSpecificationListener(specification: Specification, onResult: (results: ProjectedResult[]) => Promise<void>): SpecificationListener {
|
|
55
|
+
return this.inner.addSpecificationListener(specification, onResult);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
removeSpecificationListener(listener: SpecificationListener): void {
|
|
59
|
+
this.inner.removeSpecificationListener(listener);
|
|
60
|
+
}
|
|
61
|
+
|
|
55
62
|
addChannel(fact: FactReference, query: Query): Channel {
|
|
56
63
|
return this.inner.addChannel(fact, query);
|
|
57
64
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Channel, FactEnvelope, FactFeed, FactPath, FactRecord, FactReference, Feed, Fork, LoginResponse, Observable, ObservableSource, ProjectedResult, Query, Specification, SpecificationListener } from "jinaga";
|
|
2
|
+
import { Authentication } from "./authentication";
|
|
3
|
+
|
|
4
|
+
export class AuthenticationNoOp implements Authentication {
|
|
5
|
+
|
|
6
|
+
constructor(
|
|
7
|
+
private inner: ObservableSource
|
|
8
|
+
) { }
|
|
9
|
+
|
|
10
|
+
login(): Promise<LoginResponse> {
|
|
11
|
+
throw new Error("No keystore is configured.");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
local(): Promise<FactRecord> {
|
|
15
|
+
throw new Error("No keystore is configured.");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
addChannel(fact: FactReference, query: Query): Channel {
|
|
19
|
+
throw new Error("No keystore is configured.");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
removeChannel(channel: Channel): void {
|
|
23
|
+
throw new Error("No keystore is configured.");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
from(fact: FactReference, query: Query): Observable {
|
|
27
|
+
return this.inner.from(fact, query);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
addSpecificationListener(specification: Specification, onResult: (results: ProjectedResult[]) => Promise<void>): SpecificationListener {
|
|
31
|
+
return this.inner.addSpecificationListener(specification, onResult);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
removeSpecificationListener(listener: SpecificationListener): void {
|
|
35
|
+
return this.inner.removeSpecificationListener(listener);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
close(): Promise<void> {
|
|
39
|
+
return this.inner.close();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
save(envelopes: FactEnvelope[]): Promise<FactEnvelope[]> {
|
|
43
|
+
return this.inner.save(envelopes);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
query(start: FactReference, query: Query): Promise<FactPath[]> {
|
|
47
|
+
return this.inner.query(start, query);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
read(start: FactReference[], specification: Specification): Promise<ProjectedResult[]> {
|
|
51
|
+
return this.inner.read(start, specification);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
feed(feed: Feed, bookmark: string): Promise<FactFeed> {
|
|
55
|
+
return this.inner.feed(feed, bookmark);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
whichExist(references: FactReference[]): Promise<FactReference[]> {
|
|
59
|
+
return this.inner.whichExist(references);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
load(references: FactReference[]): Promise<FactRecord[]> {
|
|
63
|
+
return this.inner.load(references);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -3,17 +3,19 @@ import {
|
|
|
3
3
|
AuthorizationRules,
|
|
4
4
|
Channel,
|
|
5
5
|
FactEnvelope,
|
|
6
|
+
FactFeed,
|
|
6
7
|
FactRecord,
|
|
7
8
|
FactReference,
|
|
8
9
|
Feed,
|
|
9
10
|
LoginResponse,
|
|
10
11
|
Observable,
|
|
11
12
|
ObservableSource,
|
|
13
|
+
ProjectedResult,
|
|
12
14
|
Query,
|
|
13
15
|
Specification,
|
|
16
|
+
SpecificationListener,
|
|
14
17
|
UserIdentity,
|
|
15
18
|
} from "jinaga";
|
|
16
|
-
import { FactFeed } from "jinaga/dist/storage";
|
|
17
19
|
|
|
18
20
|
import { Keystore } from "../keystore";
|
|
19
21
|
import { Authentication } from "./authentication";
|
|
@@ -64,6 +66,14 @@ export class AuthenticationSession implements Authentication {
|
|
|
64
66
|
return this.inner.from(fact, query);
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
addSpecificationListener(specification: Specification, onResult: (results: ProjectedResult[]) => Promise<void>): SpecificationListener {
|
|
70
|
+
return this.inner.addSpecificationListener(specification, onResult);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
removeSpecificationListener(listener: SpecificationListener): void {
|
|
74
|
+
this.inner.removeSpecificationListener(listener);
|
|
75
|
+
}
|
|
76
|
+
|
|
67
77
|
async save(envelopes: FactEnvelope[]): Promise<FactEnvelope[]> {
|
|
68
78
|
const userFact = await this.keystore.getUserFact(this.userIdentity);
|
|
69
79
|
const facts = envelopes.map(envelope => envelope.fact);
|
package/src/authentication.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FactEnvelope,
|
|
3
|
+
FactFeed,
|
|
3
4
|
FactRecord,
|
|
4
5
|
FactReference,
|
|
5
6
|
Feed,
|
|
6
7
|
Observable,
|
|
7
8
|
ObservableSource,
|
|
9
|
+
ProjectedResult,
|
|
8
10
|
Query,
|
|
9
11
|
Specification,
|
|
10
|
-
|
|
12
|
+
SpecificationListener,
|
|
13
|
+
WebClient
|
|
11
14
|
} from "jinaga";
|
|
12
|
-
import { FactFeed } from "jinaga/dist/storage";
|
|
13
15
|
|
|
14
16
|
export class Principal {
|
|
15
17
|
|
|
@@ -55,4 +57,12 @@ export class Authentication implements ObservableSource {
|
|
|
55
57
|
from(fact: FactReference, query: Query): Observable {
|
|
56
58
|
return this.inner.from(fact, query);
|
|
57
59
|
}
|
|
60
|
+
|
|
61
|
+
addSpecificationListener(specification: Specification, onResult: (results: ProjectedResult[]) => Promise<void>): SpecificationListener {
|
|
62
|
+
return this.inner.addSpecificationListener(specification, onResult);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
removeSpecificationListener(listener: SpecificationListener): void {
|
|
66
|
+
this.inner.removeSpecificationListener(listener);
|
|
67
|
+
}
|
|
58
68
|
}
|
|
@@ -3,15 +3,15 @@ import {
|
|
|
3
3
|
AuthorizationEngine,
|
|
4
4
|
AuthorizationRules,
|
|
5
5
|
FactEnvelope,
|
|
6
|
+
FactFeed,
|
|
6
7
|
FactRecord,
|
|
7
8
|
FactReference,
|
|
8
9
|
Feed,
|
|
9
10
|
ObservableSource,
|
|
10
11
|
Query,
|
|
11
12
|
Specification,
|
|
12
|
-
UserIdentity
|
|
13
|
+
UserIdentity
|
|
13
14
|
} from "jinaga";
|
|
14
|
-
import { FactFeed } from "jinaga/dist/storage";
|
|
15
15
|
|
|
16
16
|
import { Keystore } from "../keystore";
|
|
17
17
|
|
|
@@ -55,7 +55,7 @@ export class AuthorizationKeystore implements Authorization {
|
|
|
55
55
|
return this.observableSource.load(references);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
async save(userIdentity: UserIdentity, facts: FactRecord[]) {
|
|
58
|
+
async save(userIdentity: UserIdentity | null, facts: FactRecord[]) {
|
|
59
59
|
if (!this.authorizationEngine) {
|
|
60
60
|
const envelopes = await this.observableSource.save(facts.map(fact => ({
|
|
61
61
|
fact,
|
|
@@ -64,10 +64,15 @@ export class AuthorizationKeystore implements Authorization {
|
|
|
64
64
|
return envelopes.map(envelope => envelope.fact);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
const userFact = await this.keystore.getUserFact(userIdentity);
|
|
67
|
+
const userFact = userIdentity ? await this.keystore.getUserFact(userIdentity) : null;
|
|
68
68
|
const authorizedFacts = await this.authorizationEngine.authorizeFacts(facts, userFact);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
if (userIdentity) {
|
|
70
|
+
const signedFacts = await this.keystore.signFacts(userIdentity, authorizedFacts);
|
|
71
|
+
const envelopes = await this.observableSource.save(signedFacts);
|
|
72
|
+
return envelopes.map(envelope => envelope.fact);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
return authorizedFacts;
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
78
|
}
|
package/src/debug.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import http from "http";
|
|
3
|
+
import { JinagaServer } from "./jinaga-server";
|
|
4
|
+
import process from "process";
|
|
5
|
+
|
|
6
|
+
process.on('SIGINT', () => {
|
|
7
|
+
console.log("\n\nStopping replicator\n");
|
|
8
|
+
process.exit(0);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const app = express();
|
|
12
|
+
const server = http.createServer(app);
|
|
13
|
+
|
|
14
|
+
app.set('port', process.env.PORT || 8080);
|
|
15
|
+
app.use(express.json());
|
|
16
|
+
app.use(express.text());
|
|
17
|
+
|
|
18
|
+
const pgConnection = process.env.JINAGA_POSTGRESQL ||
|
|
19
|
+
'postgresql://appuser:apppw@localhost:5432/appdb';
|
|
20
|
+
//'postgresql://repl:replpw@localhost:5432/replicator';
|
|
21
|
+
const { handler } = JinagaServer.create({
|
|
22
|
+
pgStore: pgConnection
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
app.use('/jinaga', handler);
|
|
26
|
+
|
|
27
|
+
server.listen(app.get('port'), () => {
|
|
28
|
+
console.log(` Replicator is running at http://localhost:${app.get('port')} in ${app.get('env')} mode`);
|
|
29
|
+
console.log(' Press CTRL-C to stop\n');
|
|
30
|
+
});
|
package/src/http/router.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { FeedCache } from "./feed-cache";
|
|
|
26
26
|
|
|
27
27
|
interface ParsedQs { [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[] }
|
|
28
28
|
|
|
29
|
-
function get<U>(method: ((req: RequestUser, params
|
|
29
|
+
function get<U>(method: ((req: RequestUser, params: { [key: string]: string }, query: ParsedQs) => Promise<U>)): Handler {
|
|
30
30
|
return (req, res, next) => {
|
|
31
31
|
const user = <RequestUser>req.user;
|
|
32
32
|
method(user, req.params, req.query)
|
|
@@ -197,7 +197,7 @@ function postStringCreate(method: (user: RequestUser, message: string) => Promis
|
|
|
197
197
|
};
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
function serializeUserIdentity(user: RequestUser) : UserIdentity {
|
|
200
|
+
function serializeUserIdentity(user: RequestUser) : UserIdentity | null {
|
|
201
201
|
if (!user) {
|
|
202
202
|
return null;
|
|
203
203
|
}
|
package/src/jinaga-server.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "jinaga";
|
|
19
19
|
|
|
20
20
|
import { AuthenticationDevice } from "./authentication/authentication-device";
|
|
21
|
+
import { AuthenticationNoOp } from "./authentication/authentication-noop";
|
|
21
22
|
import { AuthenticationSession } from "./authentication/authentication-session";
|
|
22
23
|
import { AuthorizationKeystore } from "./authorization/authorization-keystore";
|
|
23
24
|
import { NodeHttpConnection } from "./http/node-http";
|
|
@@ -54,17 +55,18 @@ export class JinagaServer {
|
|
|
54
55
|
const store = createStore(config);
|
|
55
56
|
const source = new ObservableSourceImpl(store);
|
|
56
57
|
const fork = createFork(config, source, syncStatusNotifier);
|
|
57
|
-
const keystore =
|
|
58
|
+
const keystore = createKeystore(config);
|
|
58
59
|
const authorizationRules = config.authorization ? config.authorization(new AuthorizationRules()) : null;
|
|
59
60
|
const authorization = createAuthorization(authorizationRules, fork, keystore);
|
|
60
61
|
const feedCache = new MemoryFeedCache();
|
|
61
62
|
const router = new HttpRouter(authorization, feedCache);
|
|
62
|
-
const authentication =
|
|
63
|
-
const
|
|
64
|
-
const j: Jinaga = new Jinaga(authentication, memory, syncStatusNotifier);
|
|
63
|
+
const authentication = createAuthentication(keystore, fork);
|
|
64
|
+
const j: Jinaga = new Jinaga(authentication, syncStatusNotifier);
|
|
65
65
|
|
|
66
66
|
async function close() {
|
|
67
|
-
|
|
67
|
+
if (keystore) {
|
|
68
|
+
await keystore.close();
|
|
69
|
+
}
|
|
68
70
|
await store.close();
|
|
69
71
|
}
|
|
70
72
|
return {
|
|
@@ -104,6 +106,10 @@ function createFork(config: JinagaServerConfig, feed: ObservableSource, syncStat
|
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
109
|
+
function createKeystore(config: JinagaServerConfig) {
|
|
110
|
+
return config.pgKeystore ? new PostgresKeystore(config.pgKeystore) : null;
|
|
111
|
+
}
|
|
112
|
+
|
|
107
113
|
function createAuthorization(authorizationRules: AuthorizationRules | null, feed: ObservableSource, keystore: Keystore | null): Authorization {
|
|
108
114
|
if (keystore) {
|
|
109
115
|
const authorization = new AuthorizationKeystore(feed, keystore, authorizationRules);
|
|
@@ -114,14 +120,18 @@ function createAuthorization(authorizationRules: AuthorizationRules | null, feed
|
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
|
|
117
|
-
|
|
123
|
+
function createAuthentication(keystore: PostgresKeystore | null, fork: Fork) {
|
|
124
|
+
return keystore ? new AuthenticationDevice(fork, keystore, localDeviceIdentity) : new AuthenticationNoOp(fork);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function withSession(feed: ObservableSource, keystore: Keystore | null, authorizationRules: AuthorizationRules | null, req: Request, callback: ((j: Jinaga) => Promise<void>)) {
|
|
118
128
|
const user = <RequestUser>req.user;
|
|
119
129
|
const userIdentity: UserIdentity = {
|
|
120
130
|
provider: user.provider,
|
|
121
131
|
id: user.id
|
|
122
132
|
}
|
|
123
|
-
const authentication = new AuthenticationSession(feed, keystore, authorizationRules, userIdentity, user.profile.displayName, localDeviceIdentity);
|
|
133
|
+
const authentication = keystore ? new AuthenticationSession(feed, keystore, authorizationRules, userIdentity, user.profile.displayName, localDeviceIdentity) : new AuthenticationNoOp(feed);
|
|
124
134
|
const syncStatusNotifier = new SyncStatusNotifier();
|
|
125
|
-
const j = new Jinaga(authentication,
|
|
135
|
+
const j = new Jinaga(authentication, syncStatusNotifier);
|
|
126
136
|
await callback(j);
|
|
127
137
|
}
|
|
@@ -36,9 +36,6 @@ export class MemoryKeystore implements Keystore {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
private getOrCreateIdentityFact(type: string, identity: UserIdentity): FactRecord {
|
|
39
|
-
if (!identity) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
39
|
const publicKey = this.getOrCreatePublicKey(identity);
|
|
43
40
|
const predecessors: PredecessorCollection = {};
|
|
44
41
|
const fields = {
|
|
@@ -49,9 +46,6 @@ export class MemoryKeystore implements Keystore {
|
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
private getIdentityFact(type: string, identity: UserIdentity): FactRecord {
|
|
52
|
-
if (!identity) {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
49
|
const publicKey = this.getPublicKey(identity);
|
|
56
50
|
const predecessors: PredecessorCollection = {};
|
|
57
51
|
const fields = {
|
|
@@ -31,7 +31,7 @@ export class ConnectionFactory {
|
|
|
31
31
|
})
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
async with<T>(callback: (connection: PoolClient) => Promise<T>) {
|
|
34
|
+
async with<T>(callback: (connection: PoolClient) => Promise<T>) : Promise<T> {
|
|
35
35
|
let attempt = 0;
|
|
36
36
|
const pause = [0, 0, 1000, 5000, 15000, 30000];
|
|
37
37
|
while (attempt < pause.length) {
|
|
@@ -57,6 +57,7 @@ export class ConnectionFactory {
|
|
|
57
57
|
await delay(pause[attempt]);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
throw new Error("Number of attempts exceeded");
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
private async createClient() {
|
package/src/postgres/maps.ts
CHANGED
|
@@ -16,6 +16,14 @@ export function getFactTypeId(map: FactTypeMap, name: string) {
|
|
|
16
16
|
return map.get(name);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export function ensureGetFactTypeId(factTypes: FactTypeMap, name: string): number {
|
|
20
|
+
const factTypeId = getFactTypeId(factTypes, name);
|
|
21
|
+
if (factTypeId === undefined) {
|
|
22
|
+
throw new Error(`Unknown fact type ${name}`);
|
|
23
|
+
}
|
|
24
|
+
return factTypeId;
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
export function mergeFactTypes(map1: FactTypeMap, map2: FactTypeMap) {
|
|
20
28
|
return new Map<string, number>([...map1, ...map2]);
|
|
21
29
|
}
|
|
@@ -50,9 +50,6 @@ export class PostgresKeystore implements Keystore {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
private async getOrCreateIdentityFact(type: string, identity: UserIdentity): Promise<FactRecord> {
|
|
53
|
-
if (!identity) {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
53
|
const { publicPem } = await this.getOrGenerateKeyPair(identity);
|
|
57
54
|
const predecessors: PredecessorCollection = {};
|
|
58
55
|
const fields = {
|
|
@@ -63,9 +60,6 @@ export class PostgresKeystore implements Keystore {
|
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
private async getIdentityFact(type: string, identity: UserIdentity): Promise<FactRecord> {
|
|
66
|
-
if (!identity) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
63
|
const { publicPem } = await this.getKeyPair(identity);
|
|
70
64
|
const predecessors: PredecessorCollection = {};
|
|
71
65
|
const fields = {
|
|
@@ -78,7 +72,7 @@ export class PostgresKeystore implements Keystore {
|
|
|
78
72
|
private async getKeyPair(userIdentity: UserIdentity): Promise<KeyPair> {
|
|
79
73
|
const key = getUserIdentityKey(userIdentity);
|
|
80
74
|
if (this.cache.has(key)) {
|
|
81
|
-
return this.cache.get(key)
|
|
75
|
+
return this.cache.get(key)!;
|
|
82
76
|
}
|
|
83
77
|
const keyPair = await this.connectionFactory.with(connection =>
|
|
84
78
|
this.selectKeyPair(connection, userIdentity));
|
|
@@ -105,7 +99,7 @@ export class PostgresKeystore implements Keystore {
|
|
|
105
99
|
private async getOrGenerateKeyPair(userIdentity: UserIdentity): Promise<KeyPair> {
|
|
106
100
|
const key = getUserIdentityKey(userIdentity);
|
|
107
101
|
if (this.cache.has(key)) {
|
|
108
|
-
return this.cache.get(key)
|
|
102
|
+
return this.cache.get(key)!;
|
|
109
103
|
}
|
|
110
104
|
const keyPair = await this.connectionFactory.withTransaction(connection =>
|
|
111
105
|
this.selectOrInsertKeyPair(connection, userIdentity));
|