mirror of
https://github.com/yuto-yuto/node-red-contrib-password-generator.git
synced 2026-03-10 02:31:21 +01:00
Implement
This commit is contained in:
28
lib/PasswordGenerator.ts
Normal file
28
lib/PasswordGenerator.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as crypto from "crypto";
|
||||
import { promisify } from "util";
|
||||
|
||||
const AsciiRange = {
|
||||
/** space */
|
||||
min: 32,
|
||||
/** childe mark ~ */
|
||||
max: 126,
|
||||
}
|
||||
|
||||
export async function generatePassword(size: number): Promise<string> {
|
||||
let result = "";
|
||||
while (true) {
|
||||
const bytes = await promisify(crypto.randomBytes)(size * 2);
|
||||
const byteArray = Array.from(bytes);
|
||||
const filtered = byteArray.filter(isInAsciiRange);
|
||||
result += String.fromCharCode(...filtered);
|
||||
if (result.length >= size) {
|
||||
result = result.slice(0, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function isInAsciiRange(value: number) {
|
||||
return AsciiRange.min <= value && value <= AsciiRange.max;
|
||||
}
|
||||
26
lib/PasswordGeneratorNode.html
Normal file
26
lib/PasswordGeneratorNode.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<script type="text/html" data-template-name="password-generator">
|
||||
<div class="form-row">
|
||||
<label for="node-input-key"><i class="fa fa-key"></i> Key prop</label>
|
||||
<input type="text" id="node-input-key" placeholder="payload.key">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-size"><i class="fa fa-database"></i> Size</label>
|
||||
<input type="text" id="node-input-size">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-to"><i class="fa fa-database"></i> to</label>
|
||||
<input type="text" id="node-input-to">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="password-generator">
|
||||
<p>Send incoming message only when the value of the specified key path changes.</p>
|
||||
|
||||
<h3>Configuration</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>size</dt>
|
||||
<dd> The output size of the string. </dd>
|
||||
<dt>to</dt>
|
||||
<dd> The property to set password. </dd>
|
||||
</dl>
|
||||
</script>
|
||||
26
lib/PasswordGeneratorNode.ts
Normal file
26
lib/PasswordGeneratorNode.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as nodered from "node-red";
|
||||
import { generatePassword } from "./PasswordGenerator";
|
||||
import { PasswordGeneratorNodeDef } from "./PasswordGeneratorNodeDef";
|
||||
import * as yutolity from "yutolity";
|
||||
|
||||
// it can't set to the input event listener now
|
||||
// using any is workaround but not good
|
||||
interface PayloadType extends nodered.NodeMessageInFlow {
|
||||
to: string;
|
||||
}
|
||||
|
||||
export = (RED: nodered.NodeAPI): void => {
|
||||
RED.nodes.registerType("password-generator",
|
||||
function (this: nodered.Node, config: PasswordGeneratorNodeDef): void {
|
||||
RED.nodes.createNode(this, config);
|
||||
|
||||
this.on("input", async (msg: any, send, done) => {
|
||||
const password = await generatePassword(config.size);
|
||||
|
||||
const valueSetPath = msg.to || config.setTo || "payload";
|
||||
yutolity.setValue(msg, valueSetPath, password);
|
||||
send(msg);
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
13
lib/PasswordGeneratorNodeDef.ts
Normal file
13
lib/PasswordGeneratorNodeDef.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as nodered from "node-red";
|
||||
|
||||
export interface PasswordGeneratorNodeDef
|
||||
extends nodered.NodeDef {
|
||||
size: number;
|
||||
setTo?: string;
|
||||
}
|
||||
|
||||
export interface PasswordGeneratorNodeProperties
|
||||
extends nodered.EditorNodeProperties {
|
||||
size: number;
|
||||
setTo?: string;
|
||||
}
|
||||
20
lib/PasswordGeneratorNodeInit.ts
Normal file
20
lib/PasswordGeneratorNodeInit.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as nodered from "node-red";
|
||||
import { PasswordGeneratorNodeProperties } from "./PasswordGeneratorNodeDef";
|
||||
|
||||
declare const RED: nodered.EditorRED;
|
||||
const nodeName = "password-generator";
|
||||
RED.nodes.registerType<PasswordGeneratorNodeProperties>(nodeName, {
|
||||
category: "function",
|
||||
color: "#a6bbcf",
|
||||
defaults: {
|
||||
name: { value: "" },
|
||||
size: { value: "", validate: RED.validators.number() },
|
||||
setTo: { value: "" },
|
||||
},
|
||||
inputs: 1,
|
||||
outputs: 1,
|
||||
icon: "fas fa-not-equal",
|
||||
label: function () {
|
||||
return this.name || nodeName;
|
||||
},
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
import isEqual from "fast-deep-equal";
|
||||
|
||||
interface KeyValue {
|
||||
key: unknown;
|
||||
value: unknown;
|
||||
}
|
||||
|
||||
export class ValueChangeDetector {
|
||||
private currentValues = new Map<string, unknown>();
|
||||
|
||||
public isUpdated(args: KeyValue): boolean {
|
||||
const current = this.currentValues.get(this.toString(args.key));
|
||||
if (current === undefined) {
|
||||
return true;
|
||||
}
|
||||
return !isEqual(current, args.value);
|
||||
}
|
||||
|
||||
public update(args: KeyValue): void {
|
||||
this.currentValues.set(this.toString(args.key), args.value);
|
||||
}
|
||||
|
||||
private toString(object: unknown): string {
|
||||
if (typeof object === "string") {
|
||||
return object;
|
||||
}
|
||||
return String(object);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('value-change-detector', {
|
||||
category: 'function',
|
||||
color: '#a6bbcf',
|
||||
defaults: {
|
||||
name: { value: "" },
|
||||
key: { value: "", required: true },
|
||||
value: { value: "", required: true },
|
||||
},
|
||||
inputs: 1,
|
||||
outputs: 1,
|
||||
icon: "file.png",
|
||||
label: function () {
|
||||
return this.name || "value-change-detector";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-template-name="value-change-detector">
|
||||
<div class="form-row">
|
||||
<label for="node-input-key"><i class="fa fa-tag"></i> Key prop</label>
|
||||
<input type="text" id="node-input-key" placeholder="payload.key">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-value"><i class="fa fa-tag"></i> Value prop</label>
|
||||
<input type="text" id="node-input-value" placeholder="payload.value">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="value-change-detector">
|
||||
<p>Send incoming message only when the value changes.</p>
|
||||
</script>
|
||||
@@ -1,20 +0,0 @@
|
||||
import * as nodered from "node-red";
|
||||
import * as yutolity from "yutolity";
|
||||
import { ValueChangeDetector } from "./ValueChangeDetector";
|
||||
import { ValueChangeDetectorNodeProperties } from "./ValueChangeDetectorNodeProperties";
|
||||
|
||||
export = (RED: nodered.NodeAPI) => {
|
||||
RED.nodes.registerType("value-change-detector",
|
||||
function (this: nodered.Node, config: ValueChangeDetectorNodeProperties): void {
|
||||
RED.nodes.createNode(this, config);
|
||||
|
||||
const detector = new ValueChangeDetector();
|
||||
|
||||
this.on('input', (msg: any) => {
|
||||
const targetValue = yutolity.getValueOf(msg.payload, config.key);
|
||||
this.send(msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import * as nodered from "node-red";
|
||||
|
||||
export interface ValueChangeDetectorNodeProperties extends nodered.NodeDef {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
Reference in New Issue
Block a user