node-red-contrib-redis-variable 1.0.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.
- package/LICENSE +21 -0
- package/README.md +769 -0
- package/examples/example.json +427 -0
- package/package.json +46 -0
- package/redis-variable-config.html +731 -0
- package/redis-variable-config.js +363 -0
- package/redis-variable.html +284 -0
- package/redis-variable.js +621 -0
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType("redis-variable-config", {
|
|
3
|
+
category: "config",
|
|
4
|
+
defaults: {
|
|
5
|
+
name: { value: "" },
|
|
6
|
+
cluster: { value: false },
|
|
7
|
+
host: { value: "localhost" },
|
|
8
|
+
hostType: { value: "str" },
|
|
9
|
+
hostContext: { value: "" },
|
|
10
|
+
port: { value: 6379 },
|
|
11
|
+
portType: { value: "str" },
|
|
12
|
+
portContext: { value: "" },
|
|
13
|
+
database: { value: 0 },
|
|
14
|
+
databaseType: { value: "str" },
|
|
15
|
+
databaseContext: { value: "" },
|
|
16
|
+
passwordType: { value: "str" },
|
|
17
|
+
passwordContext: { value: "" },
|
|
18
|
+
usernameType: { value: "str" },
|
|
19
|
+
usernameContext: { value: "" },
|
|
20
|
+
// SSL Configuration
|
|
21
|
+
enableTLS: { value: false },
|
|
22
|
+
tlsRejectUnauthorized: { value: true },
|
|
23
|
+
tlsCertType: { value: "str" },
|
|
24
|
+
tlsCertContext: { value: "" },
|
|
25
|
+
tlsKeyType: { value: "str" },
|
|
26
|
+
tlsKeyContext: { value: "" },
|
|
27
|
+
tlsCaType: { value: "str" },
|
|
28
|
+
tlsCaContext: { value: "" },
|
|
29
|
+
options: { value: "{}" },
|
|
30
|
+
optionsType: { value: "json" },
|
|
31
|
+
optionsContext: { value: "" }
|
|
32
|
+
},
|
|
33
|
+
credentials: {
|
|
34
|
+
password: { type: "password" },
|
|
35
|
+
username: { type: "text" },
|
|
36
|
+
tlsCert: { type: "password" },
|
|
37
|
+
tlsKey: { type: "password" },
|
|
38
|
+
tlsCa: { type: "password" }
|
|
39
|
+
},
|
|
40
|
+
label: function () {
|
|
41
|
+
return this.name || "Redis Config (" + (this.host || "localhost") + ":" + (this.port || 6379) + ")";
|
|
42
|
+
},
|
|
43
|
+
oneditprepare: function() {
|
|
44
|
+
var stdTypes = ['str', 'flow', 'global', 'env'];
|
|
45
|
+
var numTypes = ['str', 'flow', 'global', 'env', 'num'];
|
|
46
|
+
var jsonTypes = ['str', 'flow', 'global', 'env', 'json'];
|
|
47
|
+
|
|
48
|
+
// Initialize typedInput for Host
|
|
49
|
+
$("#node-config-input-host-typed").typedInput({
|
|
50
|
+
default: 'str',
|
|
51
|
+
types: stdTypes,
|
|
52
|
+
typeField: "#node-config-input-hostType"
|
|
53
|
+
});
|
|
54
|
+
$("#node-config-input-host-typed").typedInput('type', this.hostType || 'str');
|
|
55
|
+
|
|
56
|
+
if (this.hostType === 'str') {
|
|
57
|
+
$("#node-config-input-host-typed").typedInput('value', this.host || 'localhost');
|
|
58
|
+
} else {
|
|
59
|
+
$("#node-config-input-host-typed").typedInput('value', this.hostContext || '');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Initialize typedInput for Port
|
|
63
|
+
$("#node-config-input-port-typed").typedInput({
|
|
64
|
+
default: 'str',
|
|
65
|
+
types: numTypes,
|
|
66
|
+
typeField: "#node-config-input-portType"
|
|
67
|
+
});
|
|
68
|
+
$("#node-config-input-port-typed").typedInput('type', this.portType || 'str');
|
|
69
|
+
|
|
70
|
+
if (this.portType === 'str') {
|
|
71
|
+
$("#node-config-input-port-typed").typedInput('value', this.port || 6379);
|
|
72
|
+
} else {
|
|
73
|
+
$("#node-config-input-port-typed").typedInput('value', this.portContext || '');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Initialize typedInput for Database
|
|
77
|
+
$("#node-config-input-database-typed").typedInput({
|
|
78
|
+
default: 'str',
|
|
79
|
+
types: numTypes,
|
|
80
|
+
typeField: "#node-config-input-databaseType"
|
|
81
|
+
});
|
|
82
|
+
$("#node-config-input-database-typed").typedInput('type', this.databaseType || 'str');
|
|
83
|
+
|
|
84
|
+
if (this.databaseType === 'str') {
|
|
85
|
+
$("#node-config-input-database-typed").typedInput('value', this.database || 0);
|
|
86
|
+
} else {
|
|
87
|
+
$("#node-config-input-database-typed").typedInput('value', this.databaseContext || '');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Initialize typedInput for Options
|
|
91
|
+
$("#node-config-input-options-typed").typedInput({
|
|
92
|
+
default: 'json',
|
|
93
|
+
types: jsonTypes,
|
|
94
|
+
typeField: "#node-config-input-optionsType"
|
|
95
|
+
});
|
|
96
|
+
$("#node-config-input-options-typed").typedInput('type', this.optionsType || 'json');
|
|
97
|
+
|
|
98
|
+
if (this.optionsType === 'json') {
|
|
99
|
+
$("#node-config-input-options-typed").typedInput('value', this.options || '{}');
|
|
100
|
+
} else {
|
|
101
|
+
$("#node-config-input-options-typed").typedInput('value', this.optionsContext || '');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Password type selection
|
|
105
|
+
if (this.passwordType && this.passwordType !== 'str') {
|
|
106
|
+
$("#node-config-input-password-type").val(this.passwordType);
|
|
107
|
+
$("#node-config-input-password-context").val(this.passwordContext || '');
|
|
108
|
+
} else {
|
|
109
|
+
$("#node-config-input-password-type").val('str');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Username type selection
|
|
113
|
+
if (this.usernameType && this.usernameType !== 'str') {
|
|
114
|
+
$("#node-config-input-username-type").val(this.usernameType);
|
|
115
|
+
$("#node-config-input-username-context").val(this.usernameContext || '');
|
|
116
|
+
} else {
|
|
117
|
+
$("#node-config-input-username-type").val('str');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Password field visibility logic
|
|
121
|
+
var updatePasswordFieldVisibility = function() {
|
|
122
|
+
var passwordType = $("#node-config-input-password-type").val();
|
|
123
|
+
|
|
124
|
+
if (passwordType === 'str') {
|
|
125
|
+
$("#password-str-row").show();
|
|
126
|
+
$("#password-context-row").hide();
|
|
127
|
+
} else {
|
|
128
|
+
$("#password-str-row").hide();
|
|
129
|
+
$("#password-context-row").show();
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Username field visibility logic
|
|
134
|
+
var updateUsernameFieldVisibility = function() {
|
|
135
|
+
var usernameType = $("#node-config-input-username-type").val();
|
|
136
|
+
|
|
137
|
+
if (usernameType === 'str') {
|
|
138
|
+
$("#username-str-row").show();
|
|
139
|
+
$("#username-context-row").hide();
|
|
140
|
+
} else {
|
|
141
|
+
$("#username-str-row").hide();
|
|
142
|
+
$("#username-context-row").show();
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
$("#node-config-input-password-type").on("change", updatePasswordFieldVisibility);
|
|
147
|
+
$("#node-config-input-username-type").on("change", updateUsernameFieldVisibility);
|
|
148
|
+
|
|
149
|
+
// Call immediately to set initial state
|
|
150
|
+
updatePasswordFieldVisibility();
|
|
151
|
+
updateUsernameFieldVisibility();
|
|
152
|
+
|
|
153
|
+
// Load existing credentials if available
|
|
154
|
+
if (this.credentials && this.credentials.password) {
|
|
155
|
+
$("#node-config-input-password-visible").val(this.credentials.password);
|
|
156
|
+
$("#node-config-input-password").val(this.credentials.password);
|
|
157
|
+
} else if (this.credentials && this.credentials.has_password) {
|
|
158
|
+
$("#node-config-input-password-visible").attr('placeholder', '••••••••••••••••••••••••••••••••••••••••');
|
|
159
|
+
$("#node-config-input-password-visible").val('');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (this.credentials && this.credentials.username) {
|
|
163
|
+
$("#node-config-input-username-visible").val(this.credentials.username);
|
|
164
|
+
$("#node-config-input-username").val(this.credentials.username);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Sync visible fields with hidden credentials fields
|
|
168
|
+
$("#node-config-input-password-visible").on("input", function() {
|
|
169
|
+
$("#node-config-input-password").val($(this).val());
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
$("#node-config-input-username-visible").on("input", function() {
|
|
173
|
+
$("#node-config-input-username").val($(this).val());
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Set cluster checkbox
|
|
177
|
+
$("#node-config-input-cluster").prop('checked', this.cluster === true);
|
|
178
|
+
|
|
179
|
+
// SSL Configuration
|
|
180
|
+
$("#node-config-input-enableTLS").prop('checked', this.enableTLS === true);
|
|
181
|
+
$("#node-config-input-tlsRejectUnauthorized").prop('checked', this.tlsRejectUnauthorized !== false);
|
|
182
|
+
|
|
183
|
+
// TLS Certificate type selection
|
|
184
|
+
if (this.tlsCertType && this.tlsCertType !== 'str') {
|
|
185
|
+
$("#node-config-input-tlsCert-type").val(this.tlsCertType);
|
|
186
|
+
$("#node-config-input-tlsCert-context").val(this.tlsCertContext || '');
|
|
187
|
+
} else {
|
|
188
|
+
$("#node-config-input-tlsCert-type").val('str');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// TLS Key type selection
|
|
192
|
+
if (this.tlsKeyType && this.tlsKeyType !== 'str') {
|
|
193
|
+
$("#node-config-input-tlsKey-type").val(this.tlsKeyType);
|
|
194
|
+
$("#node-config-input-tlsKey-context").val(this.tlsKeyContext || '');
|
|
195
|
+
} else {
|
|
196
|
+
$("#node-config-input-tlsKey-type").val('str');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// TLS CA type selection
|
|
200
|
+
if (this.tlsCaType && this.tlsCaType !== 'str') {
|
|
201
|
+
$("#node-config-input-tlsCa-type").val(this.tlsCaType);
|
|
202
|
+
$("#node-config-input-tlsCa-context").val(this.tlsCaContext || '');
|
|
203
|
+
} else {
|
|
204
|
+
$("#node-config-input-tlsCa-type").val('str');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// SSL field visibility logic
|
|
208
|
+
var updateSSLFieldsVisibility = function() {
|
|
209
|
+
var enableTLS = $("#node-config-input-enableTLS").is(':checked');
|
|
210
|
+
|
|
211
|
+
if (enableTLS) {
|
|
212
|
+
$("#ssl-config-section").show();
|
|
213
|
+
} else {
|
|
214
|
+
$("#ssl-config-section").hide();
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
var updateTLSCertFieldVisibility = function() {
|
|
219
|
+
var certType = $("#node-config-input-tlsCert-type").val();
|
|
220
|
+
|
|
221
|
+
if (certType === 'str') {
|
|
222
|
+
$("#tlsCert-str-row").show();
|
|
223
|
+
$("#tlsCert-context-row").hide();
|
|
224
|
+
} else {
|
|
225
|
+
$("#tlsCert-str-row").hide();
|
|
226
|
+
$("#tlsCert-context-row").show();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
var updateTLSKeyFieldVisibility = function() {
|
|
231
|
+
var keyType = $("#node-config-input-tlsKey-type").val();
|
|
232
|
+
|
|
233
|
+
if (keyType === 'str') {
|
|
234
|
+
$("#tlsKey-str-row").show();
|
|
235
|
+
$("#tlsKey-context-row").hide();
|
|
236
|
+
} else {
|
|
237
|
+
$("#tlsKey-str-row").hide();
|
|
238
|
+
$("#tlsKey-context-row").show();
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
var updateTLSCaFieldVisibility = function() {
|
|
243
|
+
var caType = $("#node-config-input-tlsCa-type").val();
|
|
244
|
+
|
|
245
|
+
if (caType === 'str') {
|
|
246
|
+
$("#tlsCa-str-row").show();
|
|
247
|
+
$("#tlsCa-context-row").hide();
|
|
248
|
+
} else {
|
|
249
|
+
$("#tlsCa-str-row").hide();
|
|
250
|
+
$("#tlsCa-context-row").show();
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
$("#node-config-input-enableTLS").on("change", updateSSLFieldsVisibility);
|
|
255
|
+
$("#node-config-input-tlsCert-type").on("change", updateTLSCertFieldVisibility);
|
|
256
|
+
$("#node-config-input-tlsKey-type").on("change", updateTLSKeyFieldVisibility);
|
|
257
|
+
$("#node-config-input-tlsCa-type").on("change", updateTLSCaFieldVisibility);
|
|
258
|
+
|
|
259
|
+
// Call immediately to set initial state
|
|
260
|
+
updateSSLFieldsVisibility();
|
|
261
|
+
updateTLSCertFieldVisibility();
|
|
262
|
+
updateTLSKeyFieldVisibility();
|
|
263
|
+
updateTLSCaFieldVisibility();
|
|
264
|
+
|
|
265
|
+
// Load existing TLS credentials if available
|
|
266
|
+
if (this.credentials && this.credentials.tlsCert) {
|
|
267
|
+
$("#node-config-input-tlsCert-visible").val(this.credentials.tlsCert);
|
|
268
|
+
$("#node-config-input-tlsCert").val(this.credentials.tlsCert);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (this.credentials && this.credentials.tlsKey) {
|
|
272
|
+
$("#node-config-input-tlsKey-visible").val(this.credentials.tlsKey);
|
|
273
|
+
$("#node-config-input-tlsKey").val(this.credentials.tlsKey);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (this.credentials && this.credentials.tlsCa) {
|
|
277
|
+
$("#node-config-input-tlsCa-visible").val(this.credentials.tlsCa);
|
|
278
|
+
$("#node-config-input-tlsCa").val(this.credentials.tlsCa);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Sync visible TLS fields with hidden credentials fields
|
|
282
|
+
$("#node-config-input-tlsCert-visible").on("input", function() {
|
|
283
|
+
$("#node-config-input-tlsCert").val($(this).val());
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
$("#node-config-input-tlsKey-visible").on("input", function() {
|
|
287
|
+
$("#node-config-input-tlsKey").val($(this).val());
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
$("#node-config-input-tlsCa-visible").on("input", function() {
|
|
291
|
+
$("#node-config-input-tlsCa").val($(this).val());
|
|
292
|
+
});
|
|
293
|
+
},
|
|
294
|
+
oneditsave: function() {
|
|
295
|
+
// Save basic configuration
|
|
296
|
+
this.name = $("#node-config-input-name").val();
|
|
297
|
+
this.cluster = $("#node-config-input-cluster").is(':checked');
|
|
298
|
+
|
|
299
|
+
// Handle Host (TypedInput logic)
|
|
300
|
+
var hostType = $("#node-config-input-hostType").val();
|
|
301
|
+
var hostValue = $("#node-config-input-host-typed").typedInput('value');
|
|
302
|
+
|
|
303
|
+
this.hostType = hostType;
|
|
304
|
+
if (hostType === 'str') {
|
|
305
|
+
this.host = hostValue || 'localhost';
|
|
306
|
+
this.hostContext = '';
|
|
307
|
+
} else {
|
|
308
|
+
this.host = 'localhost';
|
|
309
|
+
this.hostContext = hostValue || '';
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Handle Port (TypedInput logic)
|
|
313
|
+
var portType = $("#node-config-input-portType").val();
|
|
314
|
+
var portValue = $("#node-config-input-port-typed").typedInput('value');
|
|
315
|
+
|
|
316
|
+
this.portType = portType;
|
|
317
|
+
if (portType === 'str') {
|
|
318
|
+
this.port = portValue || 6379;
|
|
319
|
+
this.portContext = '';
|
|
320
|
+
} else {
|
|
321
|
+
this.port = 6379;
|
|
322
|
+
this.portContext = portValue || '';
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Handle Database (TypedInput logic)
|
|
326
|
+
var databaseType = $("#node-config-input-databaseType").val();
|
|
327
|
+
var databaseValue = $("#node-config-input-database-typed").typedInput('value');
|
|
328
|
+
|
|
329
|
+
this.databaseType = databaseType;
|
|
330
|
+
if (databaseType === 'str') {
|
|
331
|
+
this.database = databaseValue || 0;
|
|
332
|
+
this.databaseContext = '';
|
|
333
|
+
} else {
|
|
334
|
+
this.database = 0;
|
|
335
|
+
this.databaseContext = databaseValue || '';
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Handle Options (TypedInput logic)
|
|
339
|
+
var optionsType = $("#node-config-input-optionsType").val();
|
|
340
|
+
var optionsValue = $("#node-config-input-options-typed").typedInput('value');
|
|
341
|
+
|
|
342
|
+
this.optionsType = optionsType;
|
|
343
|
+
if (optionsType === 'json') {
|
|
344
|
+
this.options = optionsValue || '{}';
|
|
345
|
+
this.optionsContext = '';
|
|
346
|
+
} else {
|
|
347
|
+
this.options = '{}';
|
|
348
|
+
this.optionsContext = optionsValue || '';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Handle Password based on type
|
|
352
|
+
var passwordType = $("#node-config-input-password-type").val();
|
|
353
|
+
this.passwordType = passwordType;
|
|
354
|
+
|
|
355
|
+
if (passwordType === 'str') {
|
|
356
|
+
this.passwordContext = '';
|
|
357
|
+
var visiblePassword = $("#node-config-input-password-visible").val();
|
|
358
|
+
if (visiblePassword) {
|
|
359
|
+
$("#node-config-input-password").val(visiblePassword);
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
var passwordValue = $("#node-config-input-password-context").val();
|
|
363
|
+
this.passwordContext = passwordValue || '';
|
|
364
|
+
$("#node-config-input-password").val('');
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Handle Username based on type
|
|
368
|
+
var usernameType = $("#node-config-input-username-type").val();
|
|
369
|
+
this.usernameType = usernameType;
|
|
370
|
+
|
|
371
|
+
if (usernameType === 'str') {
|
|
372
|
+
this.usernameContext = '';
|
|
373
|
+
var visibleUsername = $("#node-config-input-username-visible").val();
|
|
374
|
+
if (visibleUsername) {
|
|
375
|
+
$("#node-config-input-username").val(visibleUsername);
|
|
376
|
+
}
|
|
377
|
+
} else {
|
|
378
|
+
var usernameValue = $("#node-config-input-username-context").val();
|
|
379
|
+
this.usernameContext = usernameValue || '';
|
|
380
|
+
$("#node-config-input-username").val('');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Handle SSL Configuration
|
|
384
|
+
this.enableTLS = $("#node-config-input-enableTLS").is(':checked');
|
|
385
|
+
this.tlsRejectUnauthorized = $("#node-config-input-tlsRejectUnauthorized").is(':checked');
|
|
386
|
+
|
|
387
|
+
// Handle TLS Certificate based on type
|
|
388
|
+
var tlsCertType = $("#node-config-input-tlsCert-type").val();
|
|
389
|
+
this.tlsCertType = tlsCertType;
|
|
390
|
+
|
|
391
|
+
if (tlsCertType === 'str') {
|
|
392
|
+
this.tlsCertContext = '';
|
|
393
|
+
var visibleTlsCert = $("#node-config-input-tlsCert-visible").val();
|
|
394
|
+
if (visibleTlsCert) {
|
|
395
|
+
$("#node-config-input-tlsCert").val(visibleTlsCert);
|
|
396
|
+
}
|
|
397
|
+
} else {
|
|
398
|
+
var tlsCertValue = $("#node-config-input-tlsCert-context").val();
|
|
399
|
+
this.tlsCertContext = tlsCertValue || '';
|
|
400
|
+
$("#node-config-input-tlsCert").val('');
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Handle TLS Key based on type
|
|
404
|
+
var tlsKeyType = $("#node-config-input-tlsKey-type").val();
|
|
405
|
+
this.tlsKeyType = tlsKeyType;
|
|
406
|
+
|
|
407
|
+
if (tlsKeyType === 'str') {
|
|
408
|
+
this.tlsKeyContext = '';
|
|
409
|
+
var visibleTlsKey = $("#node-config-input-tlsKey-visible").val();
|
|
410
|
+
if (visibleTlsKey) {
|
|
411
|
+
$("#node-config-input-tlsKey").val(visibleTlsKey);
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
var tlsKeyValue = $("#node-config-input-tlsKey-context").val();
|
|
415
|
+
this.tlsKeyContext = tlsKeyValue || '';
|
|
416
|
+
$("#node-config-input-tlsKey").val('');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Handle TLS CA based on type
|
|
420
|
+
var tlsCaType = $("#node-config-input-tlsCa-type").val();
|
|
421
|
+
this.tlsCaType = tlsCaType;
|
|
422
|
+
|
|
423
|
+
if (tlsCaType === 'str') {
|
|
424
|
+
this.tlsCaContext = '';
|
|
425
|
+
var visibleTlsCa = $("#node-config-input-tlsCa-visible").val();
|
|
426
|
+
if (visibleTlsCa) {
|
|
427
|
+
$("#node-config-input-tlsCa").val(visibleTlsCa);
|
|
428
|
+
}
|
|
429
|
+
} else {
|
|
430
|
+
var tlsCaValue = $("#node-config-input-tlsCa-context").val();
|
|
431
|
+
this.tlsCaContext = tlsCaValue || '';
|
|
432
|
+
$("#node-config-input-tlsCa").val('');
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
</script>
|
|
437
|
+
|
|
438
|
+
<script type="text/html" data-template-name="redis-variable-config">
|
|
439
|
+
<div class="form-row">
|
|
440
|
+
<label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
441
|
+
<input type="text" id="node-config-input-name" placeholder="Configuration Name" style="width: 70%;">
|
|
442
|
+
</div>
|
|
443
|
+
|
|
444
|
+
<div class="form-row">
|
|
445
|
+
<label for="node-config-input-cluster"><i class="fa fa-sitemap"></i> Cluster Mode</label>
|
|
446
|
+
<input type="checkbox" id="node-config-input-cluster" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
447
|
+
<span style="margin-left: 5px; vertical-align: middle;">Enable Redis Cluster mode</span>
|
|
448
|
+
</div>
|
|
449
|
+
|
|
450
|
+
<div class="form-row">
|
|
451
|
+
<label for="node-config-input-host-typed"><i class="fa fa-server"></i> Host</label>
|
|
452
|
+
<input type="text" id="node-config-input-host-typed" style="width: 70%;">
|
|
453
|
+
<input type="hidden" id="node-config-input-hostType">
|
|
454
|
+
</div>
|
|
455
|
+
|
|
456
|
+
<div class="form-row">
|
|
457
|
+
<label for="node-config-input-port-typed"><i class="fa fa-plug"></i> Port</label>
|
|
458
|
+
<input type="text" id="node-config-input-port-typed" style="width: 70%;">
|
|
459
|
+
<input type="hidden" id="node-config-input-portType">
|
|
460
|
+
</div>
|
|
461
|
+
|
|
462
|
+
<div class="form-row">
|
|
463
|
+
<label for="node-config-input-database-typed"><i class="fa fa-database"></i> Database</label>
|
|
464
|
+
<input type="text" id="node-config-input-database-typed" style="width: 70%;">
|
|
465
|
+
<input type="hidden" id="node-config-input-databaseType">
|
|
466
|
+
</div>
|
|
467
|
+
|
|
468
|
+
<div class="form-row">
|
|
469
|
+
<label for="node-config-input-username-type"><i class="fa fa-user"></i> Username Type</label>
|
|
470
|
+
<select id="node-config-input-username-type" style="width: 70%;">
|
|
471
|
+
<option value="str">Direct Username (secure)</option>
|
|
472
|
+
<option value="flow">Flow Context</option>
|
|
473
|
+
<option value="global">Global Context</option>
|
|
474
|
+
<option value="env">Environment Variable</option>
|
|
475
|
+
</select>
|
|
476
|
+
</div>
|
|
477
|
+
|
|
478
|
+
<div class="form-row" id="username-str-row">
|
|
479
|
+
<label for="node-config-input-username-visible"><i class="fa fa-user"></i> Username</label>
|
|
480
|
+
<input type="text" id="node-config-input-username-visible" style="width: 70%;" placeholder="Redis username (optional)">
|
|
481
|
+
</div>
|
|
482
|
+
|
|
483
|
+
<div class="form-row" id="username-context-row" style="display: none;">
|
|
484
|
+
<label for="node-config-input-username-context"><i class="fa fa-code"></i> Username Variable</label>
|
|
485
|
+
<input type="text" id="node-config-input-username-context" style="width: 70%;" placeholder="Variable name for username">
|
|
486
|
+
</div>
|
|
487
|
+
|
|
488
|
+
<div class="form-row">
|
|
489
|
+
<label for="node-config-input-password-type"><i class="fa fa-key"></i> Password Type</label>
|
|
490
|
+
<select id="node-config-input-password-type" style="width: 70%;">
|
|
491
|
+
<option value="str">Direct Password (secure)</option>
|
|
492
|
+
<option value="flow">Flow Context</option>
|
|
493
|
+
<option value="global">Global Context</option>
|
|
494
|
+
<option value="env">Environment Variable</option>
|
|
495
|
+
</select>
|
|
496
|
+
</div>
|
|
497
|
+
|
|
498
|
+
<div class="form-row" id="password-str-row">
|
|
499
|
+
<label for="node-config-input-password-visible"><i class="fa fa-key"></i> Password</label>
|
|
500
|
+
<input type="password" id="node-config-input-password-visible" style="width: 70%;" placeholder="Redis password (optional)">
|
|
501
|
+
</div>
|
|
502
|
+
|
|
503
|
+
<div class="form-row" id="password-context-row" style="display: none;">
|
|
504
|
+
<label for="node-config-input-password-context"><i class="fa fa-code"></i> Password Variable</label>
|
|
505
|
+
<input type="text" id="node-config-input-password-context" style="width: 70%;" placeholder="Variable name for password">
|
|
506
|
+
</div>
|
|
507
|
+
|
|
508
|
+
<!-- SSL/TLS Configuration -->
|
|
509
|
+
<div class="form-row">
|
|
510
|
+
<label for="node-config-input-enableTLS"><i class="fa fa-lock"></i> Enable SSL/TLS</label>
|
|
511
|
+
<input type="checkbox" id="node-config-input-enableTLS" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
512
|
+
<span style="margin-left: 5px; vertical-align: middle;">Enable secure SSL/TLS connection</span>
|
|
513
|
+
</div>
|
|
514
|
+
|
|
515
|
+
<div id="ssl-config-section" style="display: none;">
|
|
516
|
+
<div class="form-row">
|
|
517
|
+
<label for="node-config-input-tlsRejectUnauthorized"><i class="fa fa-shield"></i> Verify Certificate</label>
|
|
518
|
+
<input type="checkbox" id="node-config-input-tlsRejectUnauthorized" style="display: inline-block; width: auto; vertical-align: middle;" checked>
|
|
519
|
+
<span style="margin-left: 5px; vertical-align: middle;">Reject unauthorized certificates (recommended)</span>
|
|
520
|
+
</div>
|
|
521
|
+
|
|
522
|
+
<div class="form-row">
|
|
523
|
+
<label for="node-config-input-tlsCert-type"><i class="fa fa-certificate"></i> Client Certificate Type</label>
|
|
524
|
+
<select id="node-config-input-tlsCert-type" style="width: 70%;">
|
|
525
|
+
<option value="str">Direct Certificate (secure)</option>
|
|
526
|
+
<option value="flow">Flow Context</option>
|
|
527
|
+
<option value="global">Global Context</option>
|
|
528
|
+
<option value="env">Environment Variable</option>
|
|
529
|
+
</select>
|
|
530
|
+
</div>
|
|
531
|
+
|
|
532
|
+
<div class="form-row" id="tlsCert-str-row">
|
|
533
|
+
<label for="node-config-input-tlsCert-visible"><i class="fa fa-certificate"></i> Client Certificate</label>
|
|
534
|
+
<textarea id="node-config-input-tlsCert-visible" style="width: 70%; height: 80px;" placeholder="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----"></textarea>
|
|
535
|
+
</div>
|
|
536
|
+
|
|
537
|
+
<div class="form-row" id="tlsCert-context-row" style="display: none;">
|
|
538
|
+
<label for="node-config-input-tlsCert-context"><i class="fa fa-code"></i> Certificate Variable</label>
|
|
539
|
+
<input type="text" id="node-config-input-tlsCert-context" style="width: 70%;" placeholder="Variable name for client certificate">
|
|
540
|
+
</div>
|
|
541
|
+
|
|
542
|
+
<div class="form-row">
|
|
543
|
+
<label for="node-config-input-tlsKey-type"><i class="fa fa-key"></i> Private Key Type</label>
|
|
544
|
+
<select id="node-config-input-tlsKey-type" style="width: 70%;">
|
|
545
|
+
<option value="str">Direct Key (secure)</option>
|
|
546
|
+
<option value="flow">Flow Context</option>
|
|
547
|
+
<option value="global">Global Context</option>
|
|
548
|
+
<option value="env">Environment Variable</option>
|
|
549
|
+
</select>
|
|
550
|
+
</div>
|
|
551
|
+
|
|
552
|
+
<div class="form-row" id="tlsKey-str-row">
|
|
553
|
+
<label for="node-config-input-tlsKey-visible"><i class="fa fa-key"></i> Private Key</label>
|
|
554
|
+
<textarea id="node-config-input-tlsKey-visible" style="width: 70%; height: 80px;" placeholder="-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----"></textarea>
|
|
555
|
+
</div>
|
|
556
|
+
|
|
557
|
+
<div class="form-row" id="tlsKey-context-row" style="display: none;">
|
|
558
|
+
<label for="node-config-input-tlsKey-context"><i class="fa fa-code"></i> Private Key Variable</label>
|
|
559
|
+
<input type="text" id="node-config-input-tlsKey-context" style="width: 70%;" placeholder="Variable name for private key">
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
<div class="form-row">
|
|
563
|
+
<label for="node-config-input-tlsCa-type"><i class="fa fa-shield"></i> CA Certificate Type</label>
|
|
564
|
+
<select id="node-config-input-tlsCa-type" style="width: 70%;">
|
|
565
|
+
<option value="str">Direct CA Certificate (secure)</option>
|
|
566
|
+
<option value="flow">Flow Context</option>
|
|
567
|
+
<option value="global">Global Context</option>
|
|
568
|
+
<option value="env">Environment Variable</option>
|
|
569
|
+
</select>
|
|
570
|
+
</div>
|
|
571
|
+
|
|
572
|
+
<div class="form-row" id="tlsCa-str-row">
|
|
573
|
+
<label for="node-config-input-tlsCa-visible"><i class="fa fa-shield"></i> CA Certificate</label>
|
|
574
|
+
<textarea id="node-config-input-tlsCa-visible" style="width: 70%; height: 80px;" placeholder="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- (optional)"></textarea>
|
|
575
|
+
</div>
|
|
576
|
+
|
|
577
|
+
<div class="form-row" id="tlsCa-context-row" style="display: none;">
|
|
578
|
+
<label for="node-config-input-tlsCa-context"><i class="fa fa-code"></i> CA Certificate Variable</label>
|
|
579
|
+
<input type="text" id="node-config-input-tlsCa-context" style="width: 70%;" placeholder="Variable name for CA certificate">
|
|
580
|
+
</div>
|
|
581
|
+
</div>
|
|
582
|
+
|
|
583
|
+
<div class="form-row">
|
|
584
|
+
<label for="node-config-input-options-typed"><i class="fa fa-cogs"></i> Advanced Options</label>
|
|
585
|
+
<input type="text" id="node-config-input-options-typed" style="width: 70%;">
|
|
586
|
+
<input type="hidden" id="node-config-input-optionsType">
|
|
587
|
+
</div>
|
|
588
|
+
|
|
589
|
+
<!-- Hidden fields for Node-RED credentials system -->
|
|
590
|
+
<input type="text" id="node-config-input-username" style="display: none;">
|
|
591
|
+
<input type="password" id="node-config-input-password" style="display: none;">
|
|
592
|
+
<input type="text" id="node-config-input-usernameContext" style="display: none;">
|
|
593
|
+
<input type="text" id="node-config-input-passwordContext" style="display: none;">
|
|
594
|
+
<input type="password" id="node-config-input-tlsCert" style="display: none;">
|
|
595
|
+
<input type="password" id="node-config-input-tlsKey" style="display: none;">
|
|
596
|
+
<input type="password" id="node-config-input-tlsCa" style="display: none;">
|
|
597
|
+
<input type="text" id="node-config-input-tlsCertContext" style="display: none;">
|
|
598
|
+
<input type="text" id="node-config-input-tlsKeyContext" style="display: none;">
|
|
599
|
+
<input type="text" id="node-config-input-tlsCaContext" style="display: none;">
|
|
600
|
+
</script>
|
|
601
|
+
|
|
602
|
+
<script type="text/x-red" data-help-name="redis-variable-config">
|
|
603
|
+
<p>Redis configuration node with flexible connection management:</p>
|
|
604
|
+
|
|
605
|
+
<h3>Connection Settings</h3>
|
|
606
|
+
<ul>
|
|
607
|
+
<li><b>Host</b>: Redis server hostname or IP address</li>
|
|
608
|
+
<li><b>Port</b>: Redis server port (default: 6379)</li>
|
|
609
|
+
<li><b>Database</b>: Redis database number (default: 0)</li>
|
|
610
|
+
<li><b>Cluster Mode</b>: Enable for Redis Cluster deployments</li>
|
|
611
|
+
</ul>
|
|
612
|
+
|
|
613
|
+
<h3>Authentication</h3>
|
|
614
|
+
<ul>
|
|
615
|
+
<li><b>Username</b>: Redis username (Redis 6.0+ ACL support)</li>
|
|
616
|
+
<li><b>Password</b>: Redis password for authentication</li>
|
|
617
|
+
</ul>
|
|
618
|
+
|
|
619
|
+
<h3>Credential Sources</h3>
|
|
620
|
+
<p>All connection parameters support multiple input types:</p>
|
|
621
|
+
<ul>
|
|
622
|
+
<li><b>String</b>: Direct value stored securely in Node-RED credentials</li>
|
|
623
|
+
<li><b>Flow Context</b>: Retrieved from flow context variables</li>
|
|
624
|
+
<li><b>Global Context</b>: Retrieved from global context variables</li>
|
|
625
|
+
<li><b>Environment Variable</b>: Retrieved from environment variables</li>
|
|
626
|
+
</ul>
|
|
627
|
+
|
|
628
|
+
<h3>Advanced Options</h3>
|
|
629
|
+
<p>JSON object with additional ioredis connection options:</p>
|
|
630
|
+
<pre>{
|
|
631
|
+
"connectTimeout": 10000,
|
|
632
|
+
"lazyConnect": true,
|
|
633
|
+
"keepAlive": 30000,
|
|
634
|
+
"family": 4,
|
|
635
|
+
"retryDelayOnFailover": 100
|
|
636
|
+
}</pre>
|
|
637
|
+
|
|
638
|
+
<h3>SSL/TLS Configuration</h3>
|
|
639
|
+
<ul>
|
|
640
|
+
<li><b>Enable SSL/TLS</b>: Enable secure connection to Redis server</li>
|
|
641
|
+
<li><b>Verify Certificate</b>: Validate server certificates (recommended for production)</li>
|
|
642
|
+
<li><b>Client Certificate</b>: Client certificate for mutual TLS authentication</li>
|
|
643
|
+
<li><b>Private Key</b>: Private key corresponding to client certificate</li>
|
|
644
|
+
<li><b>CA Certificate</b>: Certificate Authority certificate for custom CAs</li>
|
|
645
|
+
</ul>
|
|
646
|
+
|
|
647
|
+
<h3>SSL Examples</h3>
|
|
648
|
+
<p><b>Basic SSL (server verification only):</b></p>
|
|
649
|
+
<ul>
|
|
650
|
+
<li>Enable SSL/TLS: ✓</li>
|
|
651
|
+
<li>Verify Certificate: ✓</li>
|
|
652
|
+
<li>Client Certificate: (empty)</li>
|
|
653
|
+
</ul>
|
|
654
|
+
|
|
655
|
+
<p><b>Mutual TLS (client + server authentication):</b></p>
|
|
656
|
+
<ul>
|
|
657
|
+
<li>Enable SSL/TLS: ✓</li>
|
|
658
|
+
<li>Verify Certificate: ✓</li>
|
|
659
|
+
<li>Client Certificate: Your client certificate</li>
|
|
660
|
+
<li>Private Key: Your private key</li>
|
|
661
|
+
<li>CA Certificate: Custom CA if needed</li>
|
|
662
|
+
</ul>
|
|
663
|
+
|
|
664
|
+
<p><b>Self-signed certificates:</b></p>
|
|
665
|
+
<ul>
|
|
666
|
+
<li>Enable SSL/TLS: ✓</li>
|
|
667
|
+
<li>Verify Certificate: ✗ (disable for self-signed)</li>
|
|
668
|
+
<li>CA Certificate: Your self-signed CA</li>
|
|
669
|
+
</ul>
|
|
670
|
+
|
|
671
|
+
<h3>Security Notes</h3>
|
|
672
|
+
<ul>
|
|
673
|
+
<li>String credentials are stored encrypted in Node-RED's credentials store</li>
|
|
674
|
+
<li>Context types only store variable names, actual credentials retrieved at runtime</li>
|
|
675
|
+
<li>Use environment variables for containerized deployments</li>
|
|
676
|
+
<li>Enable Redis AUTH and use strong passwords</li>
|
|
677
|
+
<li>Consider using Redis ACLs for fine-grained access control</li>
|
|
678
|
+
<li><b>SSL/TLS is highly recommended for production environments</b></li>
|
|
679
|
+
<li>Always verify certificates in production unless using trusted self-signed CAs</li>
|
|
680
|
+
<li>Store certificates and keys securely, preferably in environment variables</li>
|
|
681
|
+
</ul>
|
|
682
|
+
|
|
683
|
+
<h3>Examples</h3>
|
|
684
|
+
<p><b>Environment-based configuration:</b></p>
|
|
685
|
+
<ul>
|
|
686
|
+
<li>Host: Environment Variable → <code>REDIS_HOST</code></li>
|
|
687
|
+
<li>Password: Environment Variable → <code>REDIS_PASSWORD</code></li>
|
|
688
|
+
</ul>
|
|
689
|
+
|
|
690
|
+
<p><b>Context-based configuration:</b></p>
|
|
691
|
+
<ul>
|
|
692
|
+
<li>Host: Global Context → <code>redis_config.host</code></li>
|
|
693
|
+
<li>Port: Global Context → <code>redis_config.port</code></li>
|
|
694
|
+
</ul>
|
|
695
|
+
</script>
|
|
696
|
+
|
|
697
|
+
<style>
|
|
698
|
+
.form-row {
|
|
699
|
+
margin-bottom: 10px;
|
|
700
|
+
}
|
|
701
|
+
.form-row label {
|
|
702
|
+
display: inline-block;
|
|
703
|
+
width: 120px;
|
|
704
|
+
vertical-align: top;
|
|
705
|
+
margin-top: 6px;
|
|
706
|
+
}
|
|
707
|
+
.form-row input[type="text"],
|
|
708
|
+
.form-row input[type="password"],
|
|
709
|
+
.form-row select {
|
|
710
|
+
width: 70%;
|
|
711
|
+
}
|
|
712
|
+
.form-row input[type="checkbox"] {
|
|
713
|
+
width: auto;
|
|
714
|
+
margin: 0;
|
|
715
|
+
vertical-align: middle;
|
|
716
|
+
}
|
|
717
|
+
.help-text {
|
|
718
|
+
font-size: 0.8em;
|
|
719
|
+
color: #666;
|
|
720
|
+
margin-top: 4px;
|
|
721
|
+
margin-left: 125px;
|
|
722
|
+
}
|
|
723
|
+
.error-text {
|
|
724
|
+
color: #d00;
|
|
725
|
+
font-size: 0.8em;
|
|
726
|
+
margin-top: 4px;
|
|
727
|
+
}
|
|
728
|
+
.input-error {
|
|
729
|
+
border-color: #d00 !important;
|
|
730
|
+
}
|
|
731
|
+
</style>
|