Skip to content

Commit 043b208

Browse files
committed
Add hard delete using recursive
1 parent a834f92 commit 043b208

10 files changed

Lines changed: 89 additions & 61 deletions

File tree

OpenFlow/src/DBHelper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ export class DBHelper {
550550
if (role !== null && (role._id === id || NoderedUtil.IsNullEmpty(id))) { return role; }
551551
if (role !== null && !NoderedUtil.IsNullEmpty(role._id)) {
552552
Logger.instanse.warn("DBHelper", "EnsureRole", `Deleting ${name} with ${role._id} not matcing expected id ${id}`);
553-
await Config.db.DeleteOne(role._id, "users", jwt, span);
553+
await Config.db.DeleteOne(role._id, "users", false, jwt, span);
554554
}
555555
role = new Role(); role.name = name; role._id = id;
556556
Logger.instanse.verbose("DBHelper", "EnsureRole", `Adding new role ${name}`);
@@ -583,7 +583,7 @@ export class DBHelper {
583583
if (user !== null && id !== null) {
584584
span?.addEvent("Deleting");
585585
Logger.instanse.warn("DBHelper", "EnsureUser", `Deleting ${name} with ${user._id} not matcing expected id ${id}`);
586-
await Config.db.DeleteOne(user._id, "users", jwt, span);
586+
await Config.db.DeleteOne(user._id, "users", false, jwt, span);
587587
}
588588
user = new User();
589589
if (!NoderedUtil.IsNullUndefinded(extraoptions)) user = Object.assign(user, extraoptions);

OpenFlow/src/DatabaseConnection.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,7 +2566,7 @@ export class DatabaseConnection extends events.EventEmitter {
25662566
* @param {string} jwt JWT of user who is doing the delete, ensuring rights
25672567
* @returns Promise<void>
25682568
*/
2569-
async DeleteOne(id: string | any, collectionname: string, jwt: string, parent: Span): Promise<void> {
2569+
async DeleteOne(id: string | any, collectionname: string, recursive: boolean, jwt: string, parent: Span): Promise<void> {
25702570
if (id === null || id === undefined || id === "") { throw Error("id cannot be null"); }
25712571
const span: Span = Logger.otel.startSubSpan("db.DeleteOne", parent);
25722572
try {
@@ -2613,11 +2613,11 @@ export class DatabaseConnection extends events.EventEmitter {
26132613
if (usagedocs.length > 0) throw new Error("Access Denied, cannot delete customer with active resourceusage");
26142614
let userdocs = await this.db.collection("users").find({ "customerid": doc._id }).toArray();
26152615
if (doc.userid != user._id) {
2616-
if (userdocs.length > 0 && !Config.cleanup_on_delete_customer) {
2616+
if (userdocs.length > 0 && !Config.cleanup_on_delete_customer && !recursive) {
26172617
let defaulttest = userdocs.filter(x => x._id != doc.users && x._id != doc.admins && x._id != doc.userid)
26182618
if (defaulttest.length > 0) throw new Error("Access Denied, cannot delete customer with active user or roles");
26192619
}
2620-
if (Config.cleanup_on_delete_customer) {
2620+
if (Config.cleanup_on_delete_customer || recursive) {
26212621
Logger.instanse.warn("DatabaseConnection", "DeleteOne", "[" + user.username + "] Cleaning up after up after company " + doc.name);
26222622
// let queries = [];
26232623
// for (var y = 0; y < userdocs.length; y++) {
@@ -2642,7 +2642,7 @@ export class DatabaseConnection extends events.EventEmitter {
26422642
// }
26432643
}
26442644
for (let i = 0; i < userdocs.length; i++) {
2645-
await this.DeleteOne(userdocs[i]._id, "users", jwt, span);
2645+
await this.DeleteOne(userdocs[i]._id, "users", recursive, jwt, span);
26462646
}
26472647
} else {
26482648
if (userdocs.length > 0) throw new Error("Access Denied, cannot delete customer with active user or roles");
@@ -2680,9 +2680,9 @@ export class DatabaseConnection extends events.EventEmitter {
26802680
names.push(doc.name + "noderedadmins"); names.push(doc.name + "noderedusers"); names.push(doc.name + "nodered api users")
26812681
const subdocs = await this.db.collection("users").find({ "name": { "$in": names }, "_type": "role" }).toArray();
26822682
for (var r of subdocs) {
2683-
this.DeleteOne(r._id, "users", jwt, span);
2683+
this.DeleteOne(r._id, "users", false, jwt, span);
26842684
}
2685-
if (Config.cleanup_on_delete_user) {
2685+
if (Config.cleanup_on_delete_user || recursive) {
26862686
let skip_collections = [];
26872687
if (!NoderedUtil.IsNullEmpty(Config.housekeeping_skip_collections)) skip_collections = Config.housekeeping_skip_collections.split(",")
26882688

@@ -2715,7 +2715,7 @@ export class DatabaseConnection extends events.EventEmitter {
27152715
if (collectionname == "users" && doc._type == "customer") {
27162716
const subdocs = await this.db.collection("config").find({ "customerid": doc._id }).toArray();
27172717
for (var r of subdocs) {
2718-
this.DeleteOne(r._id, "config", jwt, span);
2718+
this.DeleteOne(r._id, "config", false, jwt, span);
27192719
}
27202720
}
27212721
if (collectionname == "users" && doc._type == "role") {

OpenFlow/src/Messages/Message.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,7 @@ export class Message {
15631563
}
15641564

15651565
}
1566-
await Config.db.DeleteOne(msg.id, msg.collectionname, msg.jwt, span);
1566+
await Config.db.DeleteOne(msg.id, msg.collectionname, msg.recursive, msg.jwt, span);
15671567
} catch (error) {
15681568
if (NoderedUtil.IsNullUndefinded(msg)) { (msg as any) = {}; }
15691569
if (msg !== null && msg !== undefined) msg.error = error.message ? error.message : error;
@@ -2643,7 +2643,7 @@ export class Message {
26432643
if (usage.quantity > 0) {
26442644
await Config.db._UpdateOne(null, usage, "config", 1, false, Crypt.rootToken(), span);
26452645
} else {
2646-
await Config.db.DeleteOne(usage._id, "config", Crypt.rootToken(), span);
2646+
await Config.db.DeleteOne(usage._id, "config", false, Crypt.rootToken(), span);
26472647
}
26482648
} catch (error) {
26492649
span?.recordException(error);
@@ -3428,14 +3428,14 @@ export class Message {
34283428
await Config.db._UpdateOne(null, usage, "config", 1, false, rootjwt, span);
34293429
} else {
34303430
// Clean up old buy attempts
3431-
await Config.db.DeleteOne(usage._id, "config", rootjwt, span);
3431+
await Config.db.DeleteOne(usage._id, "config", false, rootjwt, span);
34323432
}
34333433
}
34343434
} else {
34353435
msg.customer.subscriptionid = null;
34363436
const total_usage = await Config.db.query<ResourceUsage>({ query: { "_type": "resourceusage", "customerid": msg.customer._id, "$or": [{ "siid": { "$exists": false } }, { "siid": "" }, { "siid": null }] }, top: 1000, collectionname: "config", jwt: msg.jwt }, span);
34373437
for (let usage of total_usage) {
3438-
await Config.db.DeleteOne(usage._id, "config", rootjwt, span);
3438+
await Config.db.DeleteOne(usage._id, "config", false, rootjwt, span);
34393439
}
34403440
}
34413441
if (msg.customer.vatnumber) {
@@ -4685,7 +4685,7 @@ export class Message {
46854685
var exists = wi.files.filter(x => x.name == file.filename);
46864686
if (exists.length > 0) {
46874687
try {
4688-
await Config.db.DeleteOne(exists[0]._id, "fs.files", jwt, parent);
4688+
await Config.db.DeleteOne(exists[0]._id, "fs.files", false, jwt, parent);
46894689
} catch (error) {
46904690
Logger.instanse.error("Message", "UpdateWorkitem", msg.error);
46914691
}
@@ -4874,14 +4874,14 @@ export class Message {
48744874

48754875
var files = await Config.db.query({ query: { "wi": wi._id }, collectionname: "fs.files", jwt }, parent);
48764876
for (var i = 0; i < files.length; i++) {
4877-
await Config.db.DeleteOne(files[i]._id, "fs.files", jwt, parent);
4877+
await Config.db.DeleteOne(files[i]._id, "fs.files", false, jwt, parent);
48784878
}
48794879
var files = await Config.db.query({ query: { "metadata.wi": wi._id }, collectionname: "fs.files", jwt }, parent);
48804880
for (var i = 0; i < files.length; i++) {
4881-
await Config.db.DeleteOne(files[i]._id, "fs.files", jwt, parent);
4881+
await Config.db.DeleteOne(files[i]._id, "fs.files", false, jwt, parent);
48824882
}
48834883

4884-
await Config.db.DeleteOne(wi._id, "workitems", jwt, parent);
4884+
await Config.db.DeleteOne(wi._id, "workitems", false, jwt, parent);
48854885
} catch (error) {
48864886
await handleError(null, error);
48874887
if (NoderedUtil.IsNullUndefinded(msg)) { (msg as any) = {}; }
@@ -5102,9 +5102,9 @@ export class Message {
51025102
}
51035103
}
51045104

5105-
await Config.db.DeleteOne(wiq._id, "mq", jwt, parent);
5105+
await Config.db.DeleteOne(wiq._id, "mq", false, jwt, parent);
51065106
if (wiq.usersrole) {
5107-
await Config.db.DeleteOne(wiq.usersrole, "users", jwt, parent);
5107+
await Config.db.DeleteOne(wiq.usersrole, "users", false, jwt, parent);
51085108
}
51095109
} catch (error) {
51105110
await handleError(null, error);

OpenFlow/src/public/CommonControllers.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ export class entitiesCtrl<T> {
533533
public errormessage: string = "";
534534
public skipcustomerfilter: boolean = false;
535535
public page: number = 0;
536+
public _onKeyDown: any;
537+
public _onKeyUp: any;
536538

537539
public static $inject = [
538540
"$rootScope",
@@ -554,6 +556,15 @@ export class entitiesCtrl<T> {
554556
public api: api,
555557
public userdata: userdata
556558
) {
559+
this._onKeyDown = this.onKeyDown.bind(this);
560+
this._onKeyUp = this.onKeyUp.bind(this);
561+
document.addEventListener('keydown', this._onKeyDown);
562+
document.addEventListener('keyup', this._onKeyUp);
563+
$scope.$on('$destroy', () => {
564+
console.log('ondestroy');
565+
document.removeEventListener('keydown', this._onKeyDown);
566+
document.removeEventListener('keyup', this._onKeyUp);
567+
})
557568
if (this.userdata.data != null && this.userdata.data) {
558569
if (this.userdata.data.basequery != null) {
559570
this.basequery = this.userdata.data.basequery;
@@ -575,6 +586,29 @@ export class entitiesCtrl<T> {
575586
});
576587

577588
}
589+
public controldown: boolean = false;
590+
public shiftdown: boolean = false;
591+
public onKeyDown(e) {
592+
// console.log(`${e.code}`, e);
593+
if ((e.code == 'ControlLeft' || e.code == 'ControlRight') && !this.controldown) {
594+
this.controldown = true;
595+
console.debug("Control down");
596+
}
597+
if ((e.code == 'ShiftLeft' || e.code == 'ShiftRight') && !this.shiftdown) {
598+
this.shiftdown = true;
599+
console.debug("Shift down");
600+
}
601+
}
602+
public onKeyUp(e) {
603+
if ((e.code == 'ControlLeft' || e.code == 'ControlRight') && this.controldown) {
604+
this.controldown = false;
605+
console.debug("Control up");
606+
}
607+
if ((e.code == 'ShiftLeft' || e.code == 'ShiftRight') && this.shiftdown) {
608+
this.shiftdown = false;
609+
console.debug("Shift up");
610+
}
611+
}
578612
public static parseJson(txt, reviver, context) {
579613
context = context || 20
580614
try {
@@ -767,8 +801,21 @@ export class entitiesCtrl<T> {
767801
this.errormessage = "";
768802
if (!this.$scope.$$phase) { this.$scope.$apply(); }
769803
try {
770-
await NoderedUtil.DeleteOne({ collectionname: this.collection, id: model._id });
804+
let recursive: boolean = false;
805+
if (this.collection == "users" && (model._type == "user" || model._type == "customer")) {
806+
if (this.shiftdown == true) {
807+
if (confirm("Confirm you want to HARD delete " + model.name + "\nWill delete all associated data") == true) {
808+
recursive = true;
809+
}
810+
}
811+
}
812+
await NoderedUtil.DeleteOne({ collectionname: this.collection, id: model._id, recursive });
813+
var oldcount = this.models.length;
771814
this.models = this.models.filter(function (m: any): boolean { return m._id !== model._id; });
815+
if (this.models.length < oldcount && oldcount < 5) {
816+
this.loading = false;
817+
this.loadData();
818+
}
772819
} catch (error) {
773820
this.errormessage = error.message ? error.message : error;
774821
}

OpenFlow/src/public/Controllers.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ export class MenuCtrl {
236236
toggleDarkMode() {
237237
this.halfmoon.toggleDarkMode();
238238
}
239+
toggleSidebar() {
240+
this.halfmoon.toggleSidebar();
241+
}
239242
Search() {
240243
this.$rootScope.$broadcast("search", this.searchstring);
241244
}
@@ -2327,28 +2330,6 @@ export class UsersCtrl extends entitiesCtrl<TokenUser> {
23272330
this.loading = false;
23282331
if (!this.$scope.$$phase) { this.$scope.$apply(); }
23292332
}
2330-
async DeleteOneUser(model: TokenUser): Promise<any> {
2331-
try {
2332-
this.errormessage = "";
2333-
this.loading = true;
2334-
await NoderedUtil.DeleteOne({ collectionname: this.collection, id: model._id });
2335-
this.models = this.models.filter(function (m: any): boolean { return m._id !== model._id; });
2336-
this.loading = false;
2337-
let name = model.username;
2338-
name = name.split("@").join("").split(".").join("");
2339-
name = name.toLowerCase();
2340-
2341-
var query = { _type: "role", "$or": [{ name: name + "noderedadmins" }, { name: name + "nodered api users" }] }
2342-
const list = await NoderedUtil.Query({ collectionname: "users", query, top: 4 });
2343-
for (var i = 0; i < list.length; i++) {
2344-
console.debug("Deleting " + list[i].name)
2345-
await NoderedUtil.DeleteOne({ collectionname: "users", id: list[i]._id });
2346-
}
2347-
} catch (error) {
2348-
this.errormessage = error;
2349-
}
2350-
if (!this.$scope.$$phase) { this.$scope.$apply(); }
2351-
}
23522333
public Resources: Resource[];
23532334
public Assigned: ResourceUsage[];
23542335
public user: TokenUser;

OpenFlow/src/public/Users.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ <h1 translate lib="web">users</h1>
8080
<a class="btn" ng-href="#/User/{{model._id}}">
8181
<em class="fas fa-edit"></em>
8282
</a>
83-
<a href ng-click="ctrl.DeleteOneUser(model)" class="btn" ng-disabled="ctrl.loading==true"><em
83+
<a href ng-click="ctrl.DeleteOne(model)" class="btn" ng-disabled="ctrl.loading==true"><em
8484
class="fas fa-trash"></em></a>
8585
</div>
8686
</td>

OpenFlowNodeRED/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

OpenFlowNodeRED/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
},
2626
"dependencies": {
2727
"@nodemailer/mailparser2": "^1.0.3",
28-
"@openiap/openflow-api": "^2.0.11",
28+
"@openiap/openflow-api": "^2.0.13",
2929
"@opentelemetry/api": "1.0.0-rc.3",
3030
"@opentelemetry/core": "0.19.0",
3131
"@opentelemetry/exporter-collector-grpc": "0.19.0",
@@ -55,4 +55,4 @@
5555
"@types/compression": "^1.7.2",
5656
"@types/node": "^16.11.4"
5757
}
58-
}
58+
}

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
},
3333
"dependencies": {
3434
"@kubernetes/client-node": "0.14.3",
35-
"@openiap/openflow-api": "^2.0.11",
35+
"@openiap/openflow-api": "^2.0.13",
3636
"@opentelemetry/api": "1.0.0-rc.3",
3737
"@opentelemetry/core": "0.19.0",
3838
"@opentelemetry/exporter-collector-grpc": "0.19.0",
@@ -122,4 +122,4 @@
122122
"watchify": "^4.0.0",
123123
"wtfnode": "^0.9.1"
124124
}
125-
}
125+
}

0 commit comments

Comments
 (0)