Skip to content

Commit 6d9c656

Browse files
committed
Fix redirect issue for pasive / Add aggregate
1 parent 30930e5 commit 6d9c656

8 files changed

Lines changed: 271 additions & 14 deletions

File tree

OpenFlow/src/DatabaseConnection.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,16 @@ export class DatabaseConnection {
207207
*/
208208
async aggregate<T extends Base>(aggregates: object[], collectionname: string, jwt: string): Promise<T[]> {
209209
await this.connect();
210-
aggregates.unshift(this.getbasequery(jwt, "_acl", [Rights.read]));
210+
211+
if (typeof aggregates === "string" || aggregates instanceof String) {
212+
aggregates = JSON.parse((aggregates as any));
213+
}
214+
var base = this.getbasequery(jwt, "_acl", [Rights.read]);
215+
if (Array.isArray(aggregates)) {
216+
aggregates.unshift({ $match: base });
217+
} else {
218+
aggregates = [{ $match: base }, aggregates];
219+
}
211220
// todo: add permissions check on aggregates
212221
// aggregates.unshift(this.getbasequery(jwt, [Rights.read]));
213222
var items: T[] = await this.db.collection(collectionname).aggregate(aggregates).toArray();

OpenFlow/src/LoginProvider.ts

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -443,20 +443,58 @@ export class LoginProvider {
443443
});
444444
passport.use("local", strategy);
445445
// http://www.passportjs.org/docs/authenticate/#custom-callback
446+
// app.use("/local",
447+
// bodyParser.urlencoded({ extended: false }),
448+
// //passport.authenticate("local", { failureRedirect: "/login?failed=true", failureFlash: true }),
449+
// passport.authenticate("local", { failureRedirect: "/" }),
450+
// function (req: any, res: any): void {
451+
// var originalUrl: any = req.cookies.originalUrl;
452+
// if (!Util.IsNullEmpty(originalUrl)) {
453+
// res.cookie("originalUrl", "", { expires: new Date(0) });
454+
// LoginProvider.redirect(res, originalUrl);
455+
// } else {
456+
// res.redirect("/");
457+
// }
458+
// }
459+
// );
446460
app.use("/local",
447461
bodyParser.urlencoded({ extended: false }),
448-
//passport.authenticate("local", { failureRedirect: "/login?failed=true", failureFlash: true }),
449-
passport.authenticate("local", { failureRedirect: "/" }),
450-
function (req: any, res: any): void {
451-
var originalUrl: any = req.cookies.originalUrl;
452-
if (!Util.IsNullEmpty(originalUrl)) {
453-
res.cookie("originalUrl", "", { expires: new Date(0) });
454-
LoginProvider.redirect(res, originalUrl);
455-
} else {
456-
res.redirect("/");
457-
}
462+
function (req: any, res: any, next: any): void {
463+
passport.authenticate("local", function (err, user, info) {
464+
var originalUrl: any = req.cookies.originalUrl;
465+
if (!err && user) {
466+
req.logIn(user, function (err: any) {
467+
if (err) { }
468+
// if (err) { return next(err); }
469+
if (!Util.IsNullEmpty(originalUrl)) {
470+
try {
471+
res.cookie("originalUrl", "", { expires: new Date(0) });
472+
} catch (error) {
473+
}
474+
LoginProvider.redirect(res, originalUrl);
475+
} else {
476+
res.redirect("/");
477+
}
478+
});
479+
}
480+
if (!Util.IsNullEmpty(originalUrl)) {
481+
if (originalUrl.indexOf("?") == -1) {
482+
originalUrl = originalUrl + "?error=1"
483+
} else if (originalUrl.indexOf("error=1") == -1) {
484+
originalUrl = originalUrl + "&error=1"
485+
}
486+
try {
487+
res.cookie("originalUrl", "", { expires: new Date(0) });
488+
} catch (error) {
489+
}
490+
LoginProvider.redirect(res, originalUrl);
491+
} else {
492+
res.redirect("/");
493+
}
494+
})(req, res, next);
458495
}
459496
);
497+
460498
return strategy;
461499
}
462500
static async samlverify(profile: any, done: IVerifyFunction): Promise<void> {

OpenFlow/src/public/PassiveLogin.html

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,32 @@
1717
</head>
1818

1919
<script>
20+
function getCookieValue(a) {
21+
console.log(document.cookie);
22+
var b = document.cookie.match('(^|[^;]+)\\s*' + a + '\\s*=\\s*([^;]+)');
23+
return b ? b.pop() : '';
24+
}
25+
function parse_query_string(query) {
26+
var vars = query.split("&");
27+
var query_string = {};
28+
for (var i = 0; i < vars.length; i++) {
29+
var pair = vars[i].split("=");
30+
var key = decodeURIComponent(pair[0]);
31+
var value = decodeURIComponent(pair[1]);
32+
// If first entry with this name
33+
if (typeof query_string[key] === "undefined") {
34+
query_string[key] = decodeURIComponent(value);
35+
// If second entry with this name
36+
} else if (typeof query_string[key] === "string") {
37+
var arr = [query_string[key], decodeURIComponent(value)];
38+
query_string[key] = arr;
39+
// If third or later entry with this name
40+
} else {
41+
query_string[key].push(decodeURIComponent(value));
42+
}
43+
}
44+
return query_string;
45+
}
2046
function getJSON(url, callback) {
2147
var xhr = new XMLHttpRequest();
2248
xhr.open("GET", url, true);
@@ -39,9 +65,25 @@
3965
function SettingsController2($scope, $http) {
4066
this.user = null;
4167
this.name = 'John Smith';
68+
this.message = '';
4269
// this.domain = "Donald duck";
4370
this.localenabled = false;
4471
this.domain = window.location.hostname;
72+
var cerror = getCookieValue("error");
73+
74+
// var url_string = window.location.href;
75+
// var url = new URL(url_string);
76+
// var cerror = url.searchParams.get("error");
77+
78+
var query = window.location.search.substring(1);
79+
var qs = parse_query_string(query);
80+
var cerror = qs.error;
81+
console.log(query);
82+
console.log(qs);
83+
console.log(cerror);
84+
if (cerror !== null && cerror !== undefined && cerror != "") {
85+
this.message = "Unknown user or bad password";
86+
}
4587
this.process = function (error, data) {
4688
console.log(data);
4789
this.providers = data;
@@ -98,6 +140,10 @@ <h5 class="card-title text-center"><span translate lib="web">signin</span> {{ctr
98140
placeholder="Password" required autocomplete="current-password">
99141
<label for="password" translate lib="web">password</label>
100142
</div>
143+
<div class="mb-3">
144+
145+
<label class="text-danger">{{ctrl.message}}</label>
146+
</div>
101147
<button class="btn btn-lg btn-primary btn-block text-uppercase" type="submit" ng-show="ctrl.localenabled"
102148
translate lib="web">signin</button>
103149
<hr class="my-4" ng-show="ctrl.localenabled">

OpenFlowNodeRED/src/nodered/nodes/NoderedUtil.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Red } from "node-red";
2-
import { QueryMessage, Message, InsertOneMessage, UpdateOneMessage, DeleteOneMessage, InsertOrUpdateOneMessage, SigninMessage, TokenUser, mapFunc, reduceFunc, finalizeFunc, MapReduceMessage, JSONfn, UpdateManyMessage, GetFileMessage, SaveFileMessage } from "../../Message";
2+
import { QueryMessage, Message, InsertOneMessage, UpdateOneMessage, DeleteOneMessage, InsertOrUpdateOneMessage, SigninMessage, TokenUser, mapFunc, reduceFunc, finalizeFunc, MapReduceMessage, JSONfn, UpdateManyMessage, GetFileMessage, SaveFileMessage, AggregateMessage } from "../../Message";
33
import { WebSocketClient } from "../../WebSocketClient";
44
import { Crypt } from "../../Crypt";
55
import { Config } from "../../Config";
@@ -152,6 +152,15 @@ export class NoderedUtil {
152152
return result.result;
153153
}
154154

155+
public static async Aggregate(collection: string, aggregates: object[], jwt: string): Promise<any> {
156+
var q: AggregateMessage = new AggregateMessage();
157+
q.collectionname = collection; q.aggregates = aggregates; q.jwt = jwt;
158+
var msg: Message = new Message(); msg.command = "aggregate";
159+
msg.data = JSONfn.stringify(q);
160+
var result: QueryMessage = await WebSocketClient.instance.Send<QueryMessage>(msg);
161+
return result.result;
162+
}
163+
155164
public static async GetFile(filename: string, id: string, jwt: string): Promise<GetFileMessage> {
156165
var q: GetFileMessage = new GetFileMessage(); q.filename = filename;
157166
q.id = id; q.jwt = jwt;

OpenFlowNodeRED/src/nodered/nodes/api.html

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,14 +1052,15 @@
10521052
clearInterval: false
10531053
}
10541054
});
1055+
var that = this;
10551056
$("#node-function-expand-js-updatedocument").click(function (e) {
10561057
e.preventDefault();
10571058
var value = that.updatedocumenteditor.getValue();
10581059
RED.editor.editJavaScript({
10591060
value: value,
10601061
width: "Infinity",
10611062
cursor: that.updatedocumenteditor.getCursorPosition(),
1062-
mode: "ace/mode/nrjavascript",
1063+
mode: "ace/mode/json",
10631064
complete: function (v, cursor) {
10641065
that.updatedocumenteditor.setValue(v, -1);
10651066
that.updatedocumenteditor.gotoLine(cursor.row + 1, cursor.column, false);
@@ -1099,6 +1100,119 @@
10991100

11001101

11011102

1103+
1104+
1105+
1106+
<script type="text/x-red" data-template-name="api aggregate">
1107+
<div class="form-row" style="margin-bottom: 0px;">
1108+
<label for="node-input-aggregates"><i class="fa fa-wrench"></i> Aggregates</label>
1109+
<input type="hidden" id="node-input-aggregates" autofocus="autofocus">
1110+
<input type="hidden" id="node-input-noerr-aggregates">
1111+
</div>
1112+
<div class="form-row node-text-editor-row" style="position:relative">
1113+
<div style="position: absolute; right:0; bottom:calc(100% + 3px);"><button id="node-function-expand-js-aggregates" class="editor-button editor-button-small"><i class="fa fa-expand"></i></button></div>
1114+
<div style="height: 100px; min-height:100px;" class="node-text-editor" id="node-input-aggregates-editor" ></div>
1115+
</div>
1116+
<div class="form-row">
1117+
<label><i class="fa fa-tag"></i> Collection</label>
1118+
<input type="text" id="node-input-collection" placeholder="Collection">
1119+
</div>
1120+
<div class="form-row">
1121+
<label><i class="fa fa-tag"></i> Name</label>
1122+
<input type="text" id="node-input-name" placeholder="Name">
1123+
</div>
1124+
</script>
1125+
<script type="text/x-red" data-help-name="api aggregate">
1126+
<p>Send an aggregate request to an collection
1127+
read more about the
1128+
<a tagret="_blank" href="https://docs.mongodb.com/manual/reference/command/aggregate/index.html/">
1129+
aggregate here</a> and the <a tagret="_blank" href="https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline//">aggregation-pipeline</a>
1130+
</p>
1131+
</script>
1132+
<script type="text/javascript">
1133+
RED.nodes.registerType('api aggregate', {
1134+
category: 'api',
1135+
color: "#a6bbcf",
1136+
defaults: {
1137+
name: { value: "" },
1138+
aggregates: { value: "[ {\"$group\" : {\"_id\":\"$_type\", \"count\":{\"$sum\":1}} } ]", required: true },
1139+
collection: { value: "entities", required: true }
1140+
},
1141+
inputs: 1,
1142+
outputs: 1,
1143+
icon: "bridge.png",
1144+
label: function () {
1145+
return this.name || "api aggregate";
1146+
},
1147+
labelStyle: function () {
1148+
return this.name ? "node_label_italic" : "";
1149+
},
1150+
oneditprepare: function () {
1151+
this.aggregateseditor = RED.editor.createEditor({
1152+
id: 'node-input-aggregates-editor',
1153+
mode: 'ace/mode/json',
1154+
value: $("#node-input-aggregates").val(),
1155+
globals: {
1156+
msg: false,
1157+
context: false,
1158+
RED: false,
1159+
util: false,
1160+
flow: false,
1161+
global: false,
1162+
console: false,
1163+
Buffer: false,
1164+
setTimeout: false,
1165+
clearTimeout: false,
1166+
setInterval: false,
1167+
clearInterval: false
1168+
}
1169+
});
1170+
var that = this;
1171+
$("#node-function-expand-js-aggregates").click(function (e) {
1172+
e.preventDefault();
1173+
var value = that.aggregateseditor.getValue();
1174+
RED.editor.editJavaScript({
1175+
value: value,
1176+
width: "Infinity",
1177+
cursor: that.aggregateseditor.getCursorPosition(),
1178+
mode: "ace/mode/json",
1179+
complete: function (v, cursor) {
1180+
that.aggregateseditor.setValue(v, -1);
1181+
that.aggregateseditor.gotoLine(cursor.row + 1, cursor.column, false);
1182+
setTimeout(function () {
1183+
that.aggregateseditor.focus();
1184+
}, 300);
1185+
}
1186+
})
1187+
});
1188+
1189+
},
1190+
oneditcancel: function () {
1191+
this.aggregateseditor.destroy();
1192+
delete this.aggregateseditor;
1193+
},
1194+
oneditsave: function () {
1195+
annot = this.aggregateseditor.getSession().getAnnotations();
1196+
$("#node-input-noerr-aggregates").val(0);
1197+
for (var k = 0; k < annot.length; k++) {
1198+
if (annot[k].type === "error") {
1199+
$("#node-input-noerr-aggregates").val(annot.length);
1200+
this.noerr = annot.length;
1201+
}
1202+
}
1203+
1204+
$("#node-input-aggregates").val(this.aggregateseditor.getValue());
1205+
this.aggregateseditor.destroy();
1206+
delete this.aggregateseditor;
1207+
}
1208+
1209+
});
1210+
1211+
</script>
1212+
1213+
1214+
1215+
11021216
<script type="text/x-red" data-template-name="api download file">
11031217
<div class="form-row">
11041218
<label><i class="fa fa-tag"></i> fileid</label>

OpenFlowNodeRED/src/nodered/nodes/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export = function (RED: Red) {
2020

2121
RED.nodes.registerType("map reduce", api.api_map_reduce);
2222
RED.nodes.registerType("api updatedocument", api.api_updatedocument);
23+
RED.nodes.registerType("api aggregate", api.api_aggregate);
2324

2425
RED.nodes.registerType("grant permission", api.grant_permission);
2526
RED.nodes.registerType("revoke permission", api.revoke_permission);

OpenFlowNodeRED/src/nodered/nodes/api_nodes.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,3 +802,43 @@ export class upload_file {
802802
onclose() {
803803
}
804804
}
805+
806+
807+
808+
809+
810+
811+
export interface Iapi_aggregate {
812+
collection: string;
813+
aggregates: object[];
814+
}
815+
export class api_aggregate {
816+
public node: Red = null;
817+
818+
constructor(public config: Iapi_aggregate) {
819+
RED.nodes.createNode(this, config);
820+
this.node = this;
821+
this.node.status({});
822+
this.node.on("input", this.oninput);
823+
this.node.on("close", this.onclose);
824+
}
825+
async oninput(msg: any) {
826+
try {
827+
this.node.status({});
828+
// if (NoderedUtil.IsNullEmpty(msg.jwt)) { return NoderedUtil.HandleError(this, "Missing jwt token"); }
829+
830+
if (!NoderedUtil.IsNullEmpty(msg.collection)) { this.config.collection = msg.collection; }
831+
if (!NoderedUtil.IsNullUndefinded(msg.aggregates)) { this.config.aggregates = msg.aggregates; }
832+
833+
this.node.status({ fill: "blue", shape: "dot", text: "Running mapreduce" });
834+
var result = await NoderedUtil.Aggregate(this.config.collection, this.config.aggregates, msg.jwt);
835+
msg.payload = result;
836+
this.node.send(msg);
837+
this.node.status({});
838+
} catch (error) {
839+
NoderedUtil.HandleError(this, error);
840+
}
841+
}
842+
onclose() {
843+
}
844+
}

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.347
1+
0.0.348

0 commit comments

Comments
 (0)