node-red-contrib-tdn-eventsub 0.1.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.
@@ -0,0 +1,120 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('tdn-rest-server', {
3
+ category: 'config',
4
+ defaults: {
5
+ name: { value: '' },
6
+ url: { value: '', required: true },
7
+ port: { value: 8904, required: true, validate: RED.validators.number() },
8
+ authScheme: { value: '', validate: function (v) { return !v || /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(String(v).trim()); } },
9
+ fingerprint: {
10
+ value: '',
11
+ validate: function (v) {
12
+ if (!v) return true;
13
+ var h = String(v).replace(/[^0-9a-f]/gi, '');
14
+ return h.length === 40 || h.length === 64;
15
+ }
16
+ },
17
+ rejectUnauthorized: { value: true },
18
+ rewriteHrefs: { value: true },
19
+ timeout: { value: 30000, validate: RED.validators.number() },
20
+ certPath: { value: '' },
21
+ keyPath: { value: '' },
22
+ pfxPath: { value: '' }
23
+ },
24
+ credentials: {
25
+ apiKey: { type: 'password', required: true },
26
+ passphrase: { type: 'password' }
27
+ },
28
+ label: function () {
29
+ return this.name || ((this.url || 'rest-server') + ':' + (this.port || 8904));
30
+ }
31
+ });
32
+ </script>
33
+
34
+ <script type="text/html" data-template-name="tdn-rest-server">
35
+ <div class="form-row">
36
+ <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
37
+ <input type="text" id="node-config-input-name" placeholder="REST Server">
38
+ </div>
39
+ <div class="form-row">
40
+ <label for="node-config-input-url"><i class="fa fa-globe"></i> URL / host</label>
41
+ <input type="text" id="node-config-input-url" placeholder="https://rest-server or 192.168.1.10">
42
+ </div>
43
+ <div class="form-row">
44
+ <label for="node-config-input-port"><i class="fa fa-plug"></i> Port</label>
45
+ <input type="text" id="node-config-input-port" placeholder="8904" style="width:100px">
46
+ </div>
47
+ <div class="form-row">
48
+ <label for="node-config-input-apiKey"><i class="fa fa-key"></i> API key</label>
49
+ <input type="password" id="node-config-input-apiKey" placeholder="XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX">
50
+ </div>
51
+ <div class="form-row">
52
+ <label for="node-config-input-authScheme"><i class="fa fa-lock"></i> Auth scheme</label>
53
+ <input type="text" id="node-config-input-authScheme" placeholder="blank = Basic (server v9.0+)">
54
+ </div>
55
+ <div class="form-row">
56
+ <label for="node-config-input-fingerprint"><i class="fa fa-certificate"></i> Cert fingerprint</label>
57
+ <input type="text" id="node-config-input-fingerprint" placeholder="optional SHA-256 or SHA-1 of server cert">
58
+ </div>
59
+ <div class="form-row">
60
+ <label>&nbsp;</label>
61
+ <input type="checkbox" id="node-config-input-rejectUnauthorized" style="display:inline-block;width:auto;vertical-align:top">
62
+ <label for="node-config-input-rejectUnauthorized" style="width:auto">Verify server certificate against CA (ignored when a fingerprint is set)</label>
63
+ </div>
64
+ <div class="form-row">
65
+ <label>&nbsp;</label>
66
+ <input type="checkbox" id="node-config-input-rewriteHrefs" style="display:inline-block;width:auto;vertical-align:top">
67
+ <label for="node-config-input-rewriteHrefs" style="width:auto">Force returned links back onto this host:port</label>
68
+ </div>
69
+ <div class="form-row">
70
+ <label for="node-config-input-timeout"><i class="fa fa-clock-o"></i> Timeout (ms)</label>
71
+ <input type="text" id="node-config-input-timeout" placeholder="30000" style="width:100px">
72
+ </div>
73
+ <hr>
74
+ <div class="form-tips">Client certificate &mdash; only if the REST Client item on the server has a thumbprint set. Use PEM cert + key, <i>or</i> a PFX.</div>
75
+ <div class="form-row">
76
+ <label for="node-config-input-certPath">Cert (PEM)</label>
77
+ <input type="text" id="node-config-input-certPath" placeholder="/path/client.crt">
78
+ </div>
79
+ <div class="form-row">
80
+ <label for="node-config-input-keyPath">Key (PEM)</label>
81
+ <input type="text" id="node-config-input-keyPath" placeholder="/path/client.key">
82
+ </div>
83
+ <div class="form-row">
84
+ <label for="node-config-input-pfxPath">PFX / P12</label>
85
+ <input type="text" id="node-config-input-pfxPath" placeholder="/path/client.pfx">
86
+ </div>
87
+ <div class="form-row">
88
+ <label for="node-config-input-passphrase">Passphrase</label>
89
+ <input type="password" id="node-config-input-passphrase">
90
+ </div>
91
+ </script>
92
+
93
+ <script type="text/html" data-help-name="tdn-rest-server">
94
+ <p>Connection to a REST Server API endpoint, shared by all TDN REST nodes.</p>
95
+ <h3>Properties</h3>
96
+ <dl class="message-properties">
97
+ <dt>URL / host <span class="property-type">string</span></dt>
98
+ <dd>Server hostname, IP, or URL. <code>https://</code> is assumed. A path (e.g. <code>/api</code>) is optional.</dd>
99
+ <dt>Port <span class="property-type">number</span></dt>
100
+ <dd>REST port, default <code>8904</code>.</dd>
101
+ <dt>API key <span class="property-type">credential</span></dt>
102
+ <dd>Stored as a Node-RED credential and treated as opaque.</dd>
103
+ <dt class="optional">Auth scheme <span class="property-type">string</span></dt>
104
+ <dd>Blank (default): the key is sent as <code>Authorization: Basic base64(":" + key)</code>, accepted by server v9.0+.
105
+ For older servers, enter the API-key scheme token from your server's REST API documentation;
106
+ the key is then sent as <code>Authorization: &lt;scheme&gt; &lt;key&gt;</code>.</dd>
107
+ <dt class="optional">Cert fingerprint <span class="property-type">string</span></dt>
108
+ <dd>SHA-256 (64 hex) or SHA-1 (40 hex) of the <b>server</b> certificate, colons optional.
109
+ When set, the connection is accepted only if the presented certificate matches, even if it is self-signed.
110
+ The check happens before any request (and therefore the API key) is sent.
111
+ A mismatch error reports the actual fingerprint so you can copy it.</dd>
112
+ <dt>Verify server certificate</dt>
113
+ <dd>Normal CA verification when no fingerprint is set. Untick only for lab use.</dd>
114
+ <dt>Force returned links back onto this host:port</dt>
115
+ <dd>The server builds <code>href</code>s from its own machine name, which may not resolve from Node-RED.
116
+ When ticked, followed links keep their path and query but use the configured host and port.</dd>
117
+ <dt class="optional">Client certificate</dt>
118
+ <dd>Needed only when the REST Client item has a thumbprint configured.</dd>
119
+ </dl>
120
+ </script>
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+ const { RestClient } = require('../lib/client');
3
+
4
+ module.exports = function (RED) {
5
+ function RestServerNode(config) {
6
+ RED.nodes.createNode(this, config);
7
+ this.name = config.name;
8
+ this.url = config.url;
9
+ this.port = config.port;
10
+ this.fingerprint = config.fingerprint;
11
+ this.authScheme = (config.authScheme || '').trim();
12
+ this.rejectUnauthorized = config.rejectUnauthorized !== false;
13
+ this.rewriteHrefs = config.rewriteHrefs !== false;
14
+ this.timeout = parseInt(config.timeout, 10) || 30000;
15
+ this.certPath = config.certPath;
16
+ this.keyPath = config.keyPath;
17
+ this.pfxPath = config.pfxPath;
18
+
19
+ const creds = this.credentials || {};
20
+ this.client = null;
21
+ this.clientError = null;
22
+ try {
23
+ this.client = new RestClient({
24
+ url: this.url,
25
+ port: this.port,
26
+ apiKey: creds.apiKey,
27
+ authScheme: this.authScheme,
28
+ fingerprint: this.fingerprint,
29
+ rejectUnauthorized: this.rejectUnauthorized,
30
+ rewriteHrefs: this.rewriteHrefs,
31
+ timeoutMs: this.timeout,
32
+ certPath: this.certPath,
33
+ keyPath: this.keyPath,
34
+ pfxPath: this.pfxPath,
35
+ passphrase: creds.passphrase
36
+ });
37
+ if (!creds.apiKey) this.clientError = new Error('No API key configured');
38
+ if (this.client.base.protocol === 'http:') this.warn('REST server URL is http:// - the API key will be sent unencrypted');
39
+ } catch (e) {
40
+ this.clientError = e;
41
+ this.error('REST server config: ' + e.message);
42
+ }
43
+
44
+ /** Returns the client or throws the configuration error. */
45
+ this.getClient = () => {
46
+ if (this.clientError) throw this.clientError;
47
+ return this.client;
48
+ };
49
+ }
50
+
51
+ RED.nodes.registerType('tdn-rest-server', RestServerNode, {
52
+ credentials: {
53
+ apiKey: { type: 'password' },
54
+ passphrase: { type: 'password' }
55
+ }
56
+ });
57
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "node-red-contrib-tdn-eventsub",
3
+ "version": "0.1.0",
4
+ "description": "Node-RED nodes for an access-control REST Server API: access groups, cardholders and items lists to global context, plus continuous item status subscriptions.",
5
+ "main": "lib/client.js",
6
+ "scripts": {
7
+ "test": "node test/run.js"
8
+ },
9
+ "keywords": [
10
+ "node-red",
11
+ "access control",
12
+ "rest",
13
+ "rest api",
14
+ "tdn"
15
+ ],
16
+ "author": "Stephen",
17
+ "license": "MIT",
18
+ "engines": {
19
+ "node": ">=16.0.0"
20
+ },
21
+ "files": [
22
+ "lib",
23
+ "nodes",
24
+ "examples",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "node-red": {
29
+ "version": ">=3.0.0",
30
+ "nodes": {
31
+ "tdn-rest-server": "nodes/rest-server.js",
32
+ "tdn-rest-lists": "nodes/rest-lists.js",
33
+ "tdn-rest-item-status": "nodes/rest-item-status.js"
34
+ }
35
+ }
36
+ }