# Credentials & Editable Lists

**URL:** https://discourse.nodered.org/t/credentials-editable-lists/84018
**Category:** Developing Nodes
**Created:** [25 December 2023 09:20 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018 "2023-12-25T09:20:10Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)
#### Post date: [25 December 2023 09:20 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/1 "2023-12-25T09:20:10Z")

</div>

Thx to @marcus-j-davies and @Steve-Mcl I got [sufficient understanding](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/10) of editable lists to update my [CLoudflare DDNS Node](https://www.npmjs.com/package/@insectos/node-red-cloudflare-ddns).

One challenge remains:

Currently I store the values in `this.spokes`, an array of objects. Ideally I would like to save them as credentials (e.g. JSON String). When I define a credential as `type: 'text'` and use an accordingly named input field, the value shows up.

I understand valyes of type password are not available in the UI, but I use text here.

However I can't seem to get hold of the value in `oneditprepare` or `oneditsave`.

What do I miss?

Clarification (Dec26):  
The challenge is onEditPrepare of an existing node. The this.credentials.token object doesn’t carry the values, so when you had 10 tokens, you would need to reenter all 10 token values

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [25 December 2023 09:40 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/2 "2023-12-25T09:40:28Z")

</div>

The password type will never be.

I'd probably store the hosts in a regular array (setup in the defaults) and the store the passwords (in the credentials object) using the host name as the key to the value part which would be the password.

---

<div class="post-metadata">

### Author: ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)
#### Post date: [25 December 2023 10:57 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/3 "2023-12-25T10:57:57Z")

</div>

> [@Stwissel](#):
>
> However I can't seem to get hold of the value in `oneditprepare` or `oneditsave`.

Did you use something like `this.credentials.spokes`?

Credentials objects are stored in `this.credentials`

---

<div class="post-metadata">

### Author: ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)
#### Post date: [25 December 2023 15:00 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/4 "2023-12-25T15:00:34Z")

</div>

this.credentials has the credentials in the js file as expected. In the html file it only has some Boolean flags. But there must be a mechanism since an input element gets populated when it is type text

---

<div class="post-metadata">

### Author: ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)
#### Post date: [25 December 2023 15:17 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/5 "2023-12-25T15:17:52Z")

</div>

That’s the part I struggle with details. The “password” (token in my case) are not too sensitive, so if I get to the point where they are not stored in the flow, I’m good.

The challenge: I might have multiple hosts but I only want to change one of the passwords. Something like

```auto
let hosts = this.hosts ?? ['one’:’two’];
let tokens = this.credentials.token ?? {};
editableList.forEach(item => { tokens[item.getHost()] = item.getToken()});
this.credentials.token = tokens;

```

token is defined as credentials type text (skipped JSON.parse/string parts and the item functions).

But I must be missing something ?

P.S I really appreciate your time spent helping me

---

<div class="post-metadata">

### Author: ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)
#### Post date: [25 December 2023 16:04 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/6 "2023-12-25T16:04:58Z")

</div>

Something like:

```js
function saveList() {
    const items = $('#node-input-spokes-container').editableList('items');
    const node = this;
    node.spokes = [];
    node.credentials.token = {};

    items.each(function () {
        // Or use id instead of class
        const index = $(this).data("data")?.index;
        const curHost = $(this).find('.datahost').val(); // -> `#host${index}`
        const curToken = $(this).find('.datatoken').val();
        node.spokes.push(curHost);
        node.credentials.token[curHost] = curToken;
    }
}

```

---

<div class="post-metadata">

### Author: ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)
#### Post date: [26 December 2023 06:01 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/7 "2023-12-26T06:01:12Z")

</div>

That works for initial collection (or when you deal with a non-credential property. It doesn’t work in oneditprepsre when updating

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [26 December 2023 07:33 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/8 "2023-12-26T07:33:33Z")

</div>

It won't work because as we already know, credentials are never passed back - only a placeholder value of `_PASSWD_` (or something similar) is ever sent back to the client.

1. Don't initialise `token` to and empty object.

2. Dont update any token that where its value would become the placeholder value.

TIP.  
In your existing code, put a `debugger` statement before the update of token & inspect it in the browsers console to see what the value of `curToken` is for unaltered passwords. Then alter your code to skip setting that entry if the `curToken` is that placeholder value.

---

<div class="post-metadata">

### Author: ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)
#### Post date: [26 December 2023 09:34 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/9 "2023-12-26T09:34:41Z")

</div>

You want to use `text` cred type, so the value is real - it is not hidden by ` __PWRD__ `  
Use the debugger to see the value of `this.credentials` in `oneditprepare`

---

<div class="post-metadata">

### Author: ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)
#### Post date: [26 December 2023 09:51 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/10 "2023-12-26T09:51:39Z")

</div>

Hmmm. When I set credentials: { test: {type = „text“ }} I get clear text back when linking it to an input field. Only type=password gets the placeholder. I shall take your pointers and debug a little more and report back.

Thx for chipping in!

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [26 December 2023 10:22 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/11 "2023-12-26T10:22:31Z")

</div>

Sorry, I'm late to this party.  
I think reading all the comments above, would this work?

**Add a new / update host (during `oneditsave`)**

1. only add to creds if not existing already

```js
if(!this.credentials.token[item.host]){
  this.credentials.token[item.host] = item.token
}

```

1. Update only if not ` __PWRD__ ` (or do it based on it being updated in the DOM, as per @Steve-Mcl I think?)

```auto
if(item.token !== ' __PWRD__'){
  this.credentials.token[item.host] = item.token
}

```

**Removing a token from creds**

1. Employ the `removeItem` callback in the `editableList` initialiser

```auto
removeItem: RemoveItem

```

1. Remove Entry from Creds

```auto
function RemoveItem(item) {
    delete this.credentials.token[item.host]
}

```

I may have this wrong with what you are trying to do, but hopefully may help in finding an answer.

**EDIT**  
Probably not actually, as `this.credentials.token` will be retuned as ` __PWRD__ ` when opening it up 😔

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [26 December 2023 12:32 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/12 "2023-12-26T12:32:55Z")

</div>

> [@marcus-j-davies](#):
>
> Probably not actually, as `this.credentials.token` will be retuned as ` __PWRD__ ` when opening it up

Yeah. Will need to go back to my original suggestion...

> [@Steve-Mcl](#):
>
> and the store the passwords (in the credentials object) using the host name as the key to the value part which would be the password

For this pattern to work.

---

<div class="post-metadata">

### Author: ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)
#### Post date: [27 December 2023 10:04 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/13 "2023-12-27T10:04:45Z")

</div>

# Investigation results

So I did some experiments:

## token as text credential

```js
{
   credentials: { token: {type: 'text'} },
   oneditprepare: loadList,
   oneditsave: saveList
}

```

Treating the credentials as a JSON string to be parsed/stringified

```js
  function loadList() {
    $('#node-input-spokes-container')
      .css('min-height', '150px')
      .css('min-width', '450px')
      .editableList({
        removable: true,
        header: $('<div>').append('<p>Configured host list</p>'),
        addButton: 'Add Spoke',
        addItem: addSpoke
      });
    debugger;
    let candidate;
    try {
      candidate = JSON.parse(this.credentials.token);
    } catch (e) {
      console.error(e);
      candidate = [];
    }
    candidate.forEach((spoke) =>
      $('#node-input-spokes-container').editableList('addItem', spoke)
    );
  }

  function saveList() {
    const items = $('#node-input-spokes-container').editableList('items');
    debugger;
    const newSpokes = [];
    for (const element of items) {
      const El = $(element);
      const curHost = El.find('.datahost')[0].value;
      const curToken = El.find('.datatoken')[0].value;
      newSpokes.push({ host: curHost, token: curToken });
    }
    this.credentials.token = JSON.stringify(newSpokes);
  }

```

### Observed outcome

- kinda works
- didn't trigger the "dirty" marker. only can deploy if any other value is updated

## token as text credential - take two

added some html

```html
  <div class="form-row">
    <label for="node-input-token"> Token</label>
    <input type="text" id="node-input-token">
  </div>

```

and amended the js

```js
$('#node-input-token')[0].value = JSON.stringify(newSpokes);

```

### Observed outcome

- JSON string shows up in edit field
- Dirty indicator works

I'll run with this for now and shall test the other proposed approaches at a later time and report back

Thx for all contributions and pointers

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [27 December 2023 12:07 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/14 "2023-12-27T12:07:50Z")

</div>

You can set the dirty indicator manually if you need to.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [25 February 2024 12:08 UTC](https://discourse.nodered.org/t/credentials-editable-lists/84018/15 "2024-02-25T12:08:03Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
