Skip to content

Commit 012724b

Browse files
authored
Merge pull request openiap#204 from skadefro/master
close 1.4.7
2 parents 36df9d1 + 006fe4d commit 012724b

25 files changed

Lines changed: 385 additions & 302 deletions

.vscode/launch.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"runtimeArgs": [
3535
"--nolazy",
3636
"--trace-warnings",
37-
"--inspect"
37+
"--inspect",
38+
"--preserve-symlinks"
3839
],
3940
"showAsyncStacks": true,
4041
"trace": true,

OpenFlow/src/Config.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { fetch, toPassportConfig } from "passport-saml-metadata";
22
import * as fs from "fs";
33
import * as path from "path";
4-
import * as retry from "async-retry";
54
import { DatabaseConnection } from "./DatabaseConnection";
65
// import { Logger } from "./Logger";
76
import { NoderedUtil } from "@openiap/openflow-api";
7+
import { promiseRetry } from "./Logger";
88
export class Config {
99
public static getversion(): string {
1010
let versionfile: string = path.join(__dirname, "VERSION");
@@ -428,22 +428,16 @@ export class Config {
428428
}
429429
public static async parse_federation_metadata(url: string): Promise<any> {
430430
// if anything throws, we retry
431-
return retry(async bail => {
431+
return promiseRetry(async () => {
432432
const reader: any = await fetch({ url });
433-
if (NoderedUtil.IsNullUndefinded(reader)) { bail(new Error("Failed getting result")); return; }
433+
if (NoderedUtil.IsNullUndefinded(reader)) { throw new Error("Failed getting result"); return; }
434434
const config: any = toPassportConfig(reader);
435435
// we need this, for Office 365 :-/
436436
if (reader.signingCerts && reader.signingCerts.length > 1) {
437437
config.cert = reader.signingCerts;
438438
}
439439
return config;
440-
}, {
441-
retries: 50,
442-
onRetry: function (error: Error, count: number): void {
443-
console.log("retry " + count + " error " + error.message + " getting " + url);
444-
// Logger.instanse.warn("retry " + count + " error " + error.message + " getting " + url);
445-
}
446-
});
440+
}, 10, 1000);
447441
}
448442
public static parseArray(s: string): string[] {
449443
let arr = s.split(",");

OpenFlow/src/Crypt.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ export class Crypt {
126126
throw new Error('jwt must be provided');
127127
}
128128
const o: any = jsonwebtoken.verify(token, Crypt.encryption_key);
129+
let impostor: string = null;
130+
if (!NoderedUtil.IsNullUndefinded(o) && !NoderedUtil.IsNullUndefinded(o.data) && !NoderedUtil.IsNullEmpty(o.data._id)) {
131+
if (!NoderedUtil.IsNullEmpty(o.data.impostor)) {
132+
impostor = o.data.impostor;
133+
}
134+
}
129135
if (!NoderedUtil.IsNullUndefinded(o) && !NoderedUtil.IsNullUndefinded(o.data) && !NoderedUtil.IsNullEmpty(o.data._id) && o.data._id != WellknownIds.root) {
130136
var id = o.data._id;
131137
o.data = await DBHelper.FindById(o.data._id, token, null);
@@ -136,6 +142,7 @@ export class Crypt {
136142
var b = true;
137143
}
138144
}
145+
if (!NoderedUtil.IsNullEmpty(impostor)) o.data.impostor = impostor;
139146
return TokenUser.assign(o.data);
140147

141148
}

OpenFlow/src/DBHelper.ts

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,30 @@ import { LoginProvider } from "./LoginProvider";
1010
import * as cacheManager from "cache-manager";
1111
// var cacheManager = require('cache-manager');
1212
var redisStore = require('cache-manager-ioredis');
13+
var mongoStore = require('@skadefro/cache-manager-mongodb');
1314

1415
export class DBHelper {
1516

1617
public static memoryCache: any;
18+
public static mongoCache: any;
1719
public static async init() {
1820
if (!NoderedUtil.IsNullUndefinded(this.memoryCache)) return;
19-
if (Config.cache_store_type == "redis") {
21+
22+
this.mongoCache = cacheManager.caching({
23+
store: mongoStore,
24+
uri: Config.mongodb_url,
25+
options: {
26+
collection: "_cache",
27+
compression: false,
28+
poolSize: 5
29+
}
30+
});
31+
32+
if (Config.cache_store_type == "mongodb") {
33+
this.memoryCache = this.mongoCache;
34+
DBHelper.ensureotel();
35+
return;
36+
} else if (Config.cache_store_type == "redis") {
2037
this.memoryCache = cacheManager.caching({
2138
store: redisStore,
2239
host: Config.cache_store_redis_host,
@@ -32,6 +49,7 @@ export class DBHelper {
3249
redisClient.on('error', (error) => {
3350
console.log(error);
3451
});
52+
3553
DBHelper.ensureotel();
3654
return;
3755
}
@@ -45,8 +63,6 @@ export class DBHelper {
4563
}
4664
public static async clearCache(reason: string) {
4765
this.init();
48-
// Auth.ensureotel();
49-
// this.memoryCache.reset();
5066
var keys: string[];
5167
if (Config.cache_store_type == "redis") {
5268
keys = await this.memoryCache.keys('*');
@@ -71,16 +87,6 @@ export class DBHelper {
7187
DBHelper.item_cache = Logger.otel.meter.createValueObserver("openflow_item_cache_count", {
7288
description: 'Total number of cached items'
7389
}, async (res) => {
74-
// let keys: string[] = Object.keys(this.authorizationCache);
75-
// let types = {};
76-
// for (let i = keys.length - 1; i >= 0; i--) {
77-
// if (!types[this.authorizationCache[keys[i]].type]) types[this.authorizationCache[keys[i]].type] = 0;
78-
// types[this.authorizationCache[keys[i]].type]++;
79-
// }
80-
// keys = Object.keys(types);
81-
// for (let i = keys.length - 1; i >= 0; i--) {
82-
// res.observe(types[keys[i]], { ...Logger.otel.defaultlabels, type: keys[i] })
83-
// }
8490
var keys: any = null;
8591
try {
8692
if (Config.cache_store_type == "redis") {
@@ -105,7 +111,6 @@ export class DBHelper {
105111
try {
106112
if (NoderedUtil.IsNullEmpty(_id)) return null;
107113
let item = await this.memoryCache.wrap("users" + _id, () => {
108-
// if (jwt === null || jwt == undefined || jwt == "") { jwt = Crypt.rootToken(); }
109114
if (Config.log_cache) Logger.instanse.debug("Add user to cache : " + _id);
110115
return Config.db.getbyid<User>(_id, "users", Crypt.rootToken(), true, span);
111116
});
@@ -120,36 +125,48 @@ export class DBHelper {
120125
Logger.otel.endSpan(span);
121126
}
122127
}
123-
public static async FindRequestTokenID(key: string, parent: Span): Promise<any> {
128+
public static async FindRequestTokenID(key: string, parent: Span): Promise<TokenRequest> {
124129
this.init();
125130
const span: Span = Logger.otel.startSubSpan("dbhelper.FindRequestTokenID", parent);
126131
try {
127132
if (NoderedUtil.IsNullEmpty(key)) return null;
128-
return await this.memoryCache.get("requesttoken" + key);
133+
if (Config.cache_store_type == "redis") {
134+
return await this.memoryCache.get("requesttoken" + key);
135+
} else {
136+
return await this.mongoCache.get("requesttoken" + key);
137+
}
129138
} catch (error) {
130139
span?.recordException(error);
131140
throw error;
132141
} finally {
133142
Logger.otel.endSpan(span);
134143
}
135144
}
136-
public static async AdddRequestTokenID(key: string, data: any, parent: Span): Promise<any> {
145+
public static async AdddRequestTokenID(key: string, data: any, parent: Span): Promise<TokenRequest> {
137146
this.init();
138147
const span: Span = Logger.otel.startSubSpan("dbhelper.FindRequestTokenID", parent);
139148
try {
140-
return await this.memoryCache.set("requesttoken" + key, data);
149+
if (Config.cache_store_type == "redis") {
150+
return await this.memoryCache.set("requesttoken" + key, data);
151+
} else {
152+
return await this.mongoCache.set("requesttoken" + key, data);
153+
}
141154
} catch (error) {
142155
span?.recordException(error);
143156
throw error;
144157
} finally {
145158
Logger.otel.endSpan(span);
146159
}
147160
}
148-
public static async RemoveRequestTokenID(key: string, parent: Span): Promise<any> {
161+
public static async RemoveRequestTokenID(key: string, parent: Span): Promise<TokenRequest> {
149162
this.init();
150163
const span: Span = Logger.otel.startSubSpan("dbhelper.FindRequestTokenID", parent);
151164
try {
152-
return await this.memoryCache.del("requesttoken" + key);
165+
if (Config.cache_store_type == "redis") {
166+
return await this.memoryCache.del("requesttoken" + key);
167+
} else {
168+
return await this.mongoCache.del("requesttoken" + key);
169+
}
153170
} catch (error) {
154171
span?.recordException(error);
155172
throw error;
@@ -598,4 +615,13 @@ export class DBHelper {
598615
return { $set: updatedoc };
599616
}
600617
}
618+
}
619+
export class TokenRequest extends Base {
620+
constructor(code: string) {
621+
super();
622+
this._type = "tokenrequest";
623+
if (NoderedUtil.IsNullEmpty(code)) this.code = "";
624+
}
625+
public code: string;
626+
public jwt: string;
601627
}

OpenFlow/src/DatabaseConnection.ts

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,6 @@ const jsondiffpatch = require('jsondiffpatch').create({
2828
});
2929

3030

31-
Object.defineProperty(Promise, 'retry', {
32-
configurable: true,
33-
writable: true,
34-
value: function retry(retries, executor) {
35-
// console.warn(`${retries} retries left!`)
36-
if (typeof retries !== 'number') {
37-
throw new TypeError('retries is not a number')
38-
}
39-
return new Promise(executor).catch(error => retries > 0
40-
? (Promise as any).retry(retries - 1, executor)
41-
: Promise.reject(error)
42-
)
43-
}
44-
})
4531
export type GetDocumentVersionOptions = {
4632
collectionname: string,
4733
id: string,
@@ -159,18 +145,22 @@ export class DatabaseConnection extends events.EventEmitter {
159145
}
160146
const span: Span = Logger.otel.startSubSpan("db.connect", parent);
161147
this.streams = [];
162-
this.cli = await (Promise as any).retry(100, (resolve, reject) => {
163-
const options: MongoClientOptions = { minPoolSize: Config.mongodb_minpoolsize, autoReconnect: false, useNewUrlParser: true, useUnifiedTopology: true };
164-
MongoClient.connect(this.mongodburl, options).then((cli) => {
165-
this.replicat = (cli as any).s.options.replicaSet;
166-
resolve(cli);
167-
span?.addEvent("Connected to mongodb");
168-
}).catch((reason) => {
169-
span?.recordException(reason);
170-
console.error(reason);
171-
reject(reason);
172-
});
173-
});
148+
// this.cli = await (Promise as any).retry(100, (resolve, reject) => {
149+
// const options: MongoClientOptions = { minPoolSize: Config.mongodb_minpoolsize, autoReconnect: false, useNewUrlParser: true, useUnifiedTopology: true };
150+
// MongoClient.connect(this.mongodburl, options).then((cli) => {
151+
// this.replicat = (cli as any).s.options.replicaSet;
152+
// resolve(cli);
153+
// span?.addEvent("Connected to mongodb");
154+
// }).catch((reason) => {
155+
// span?.recordException(reason);
156+
// console.error(reason);
157+
// reject(reason);
158+
// });
159+
// });
160+
span?.addEvent("connecting to mongodb");
161+
const options: MongoClientOptions = { minPoolSize: Config.mongodb_minpoolsize, autoReconnect: false, useNewUrlParser: true, useUnifiedTopology: true };
162+
this.cli = await MongoClient.connect(this.mongodburl, options);
163+
span?.addEvent("Connected to mongodb");
174164

175165
Logger.instanse.silly(`Really connected to mongodb`);
176166
const errEvent = (error) => {

OpenFlow/src/Logger.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ import { i_license_file, i_nodered_driver, i_otel } from "./commoninterfaces";
44
import { Config } from "./Config";
55
import { dockerdriver } from "./dockerdriver";
66
const path = require('path');
7+
8+
const MAX_RETRIES_DEFAULT = 5
9+
export async function promiseRetry<T>(
10+
fn: () => Promise<T>,
11+
retries = MAX_RETRIES_DEFAULT,
12+
retryIntervalMillis: number,
13+
previousError?: Error
14+
): Promise<T> {
15+
return !retries
16+
? Promise.reject(previousError)
17+
: fn().catch(async (error) => {
18+
await new Promise((resolve) => setTimeout(resolve, retryIntervalMillis))
19+
return promiseRetry(fn, retries - 1, retryIntervalMillis, error)
20+
})
21+
}
22+
723
export class Logger {
824
public static otel: i_otel;
925
public static License: i_license_file;

OpenFlow/src/LoginProvider.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const multer = require('multer');
1313
// const GridFsStorage = require('multer-gridfs-storage');
1414
import { GridFsStorage } from "multer-gridfs-storage";
1515
import { GridFSBucket, ObjectID, Binary } from "mongodb";
16-
import { Base, User, NoderedUtil, TokenUser, WellknownIds, Rights, Role } from "@openiap/openflow-api";
17-
import { DBHelper } from "./DBHelper";
16+
import { Base, User, NoderedUtil, TokenUser, WellknownIds, Rights, Role, InsertOrUpdateOneMessage } from "@openiap/openflow-api";
17+
import { DBHelper, TokenRequest } from "./DBHelper";
1818
import { Span } from "@opentelemetry/api";
1919
import { Logger } from "./Logger";
2020
import { DatabaseConnection } from "./DatabaseConnection";
@@ -409,7 +409,7 @@ export class LoginProvider {
409409
const span: Span = Logger.otel.startSpan("LoginProvider.login");
410410
try {
411411
const key = req.body.key;
412-
var exists = await DBHelper.FindRequestTokenID(key, span);
412+
let exists: TokenRequest = await DBHelper.FindRequestTokenID(key, span);
413413
if (!NoderedUtil.IsNullUndefinded(exists)) return res.status(500).send({ message: "Illegal key" });
414414
await DBHelper.AdddRequestTokenID(key, {}, span);
415415
res.status(200).send({ message: "ok" });
@@ -424,11 +424,11 @@ export class LoginProvider {
424424
const span: Span = Logger.otel.startSpan("LoginProvider.login");
425425
try {
426426
const key = req.query.key;
427-
var exists = await DBHelper.FindRequestTokenID(key, span);
427+
let exists: TokenRequest = null;
428+
exists = await DBHelper.FindRequestTokenID(key, span);
428429
if (NoderedUtil.IsNullUndefinded(exists)) {
429430
res.status(200).send({ message: "Illegal key" });
430431
return;
431-
// return res.status(500).send({ message: "Illegal key" });
432432
}
433433

434434
if (!NoderedUtil.IsNullEmpty(exists.jwt)) {
@@ -478,7 +478,7 @@ export class LoginProvider {
478478
if (!NoderedUtil.IsNullEmpty(key)) {
479479
if (req.user) {
480480
const user: User = await DBHelper.FindById(req.user._id, undefined, span);
481-
var exists = await DBHelper.FindRequestTokenID(key, span);
481+
var exists: TokenRequest = await DBHelper.FindRequestTokenID(key, span);
482482
if (!NoderedUtil.IsNullUndefinded(exists)) {
483483
await DBHelper.AdddRequestTokenID(key, { jwt: Crypt.createToken(user, Config.longtoken_expires_in) }, span);
484484
res.cookie("requesttoken", "", { expires: new Date(0) });
@@ -523,7 +523,10 @@ export class LoginProvider {
523523
} catch (error) {
524524
span?.recordException(error);
525525
console.error(error.message ? error.message : error);
526-
return res.status(500).send({ message: error.message ? error.message : error });
526+
try {
527+
return res.status(500).send({ message: error.message ? error.message : error });
528+
} catch (error) {
529+
}
527530
}
528531
Logger.otel.endSpan(span);
529532
});

0 commit comments

Comments
 (0)