So, I’m working on a custom node with a lot of options for configuration. Not terribly complex, just busy. One of the things that I’ve been wracking my brain about is handling credentials – basically given four different options in two different sets.
The first choice users get is whether credentials are “hard coded” as a credential object (based on a .credentials.ts definition) or dynamically provided in the node’s properties (defined in the .node.ts file), for cases where a single pipeline might be used in a mutli-site setting (allowing the credentials to be passed dynamically from a secure source; the “from where” is beyond my scope of influence, so this seemed to be the most rational approach).
The second choice is whether they provide an API token directly or provide a password that is used to retrieve a token. If the user provides a token, it’s just encoded and plopped into an Auth header for whatever request – no problem. But if they provide a password, the node needs make a “special” request, first, with a custom Auth header containing a base64-encoded string built from the username and password, and the token is returned from that.
After getting part of the way through implementing this, I realized I had to handle a lot of this manually, so the .credentials.ts file just collects data (if the user is going that route) – just like the inputs for the node. I’ve got an apiRequest() function defined and exported from a separate file that handles making the API requests, themselves, and a getApiToken() function in that same file (not exported – it’s only used by apiRequest() (at the moment) that specifically handles the request for the token.
Users can choose either/or for either/or. Regardless, the inputs are the same: username, site URL, and password or API token. I had already had all this working without the option to use a password, but I took up that quest today, and I’ve gotten it working with the dynamic credentials option, but this seems to have broken any ability to pull the credentials from the .credentials.ts-based configuration.
I’ve narrowed the problem down to a block of code in the .node.ts file, which is just a series of conditional assignments.
First, it declares a variable – credentials – and tries to use getCredentials() to pull them from the .credentials.ts configuration. If they’re not present, there’s an error catch that just defaults credentials to undefined. Immediately afterwards, there’s a constant declared – dynamicConnection – that uses getNodeParamter() to get the inputs from the node’s properties input (each property is type-safe, specified as a string) – so if nothing’s in there, they’re just null. Next, a connection object is created where each of the four properties are assigned based on conditional checks of the credentials and dynamicConnection objects’ properties. For each one, we check to see if the credentials.<prop> object contains a string; if it does it gets assigned, and if not we do the same for dynamicConnection. If neither contains a string value, it defaults to undefined. Finally, an if() condition checks to make sure we have (a) a username, (b) an instance URL, and (c) either a password or a token; if any of those conditions are not met, it throws an error. That if() condition is read as “if NOT username -OR- NOT site URL -OR- ( NOT api token -AND- NOT password): throw an error.”
This works fine for the dynamic input of credentials, but if I try to do this with saved credentials, they kick back the error from that if() block, as if something was missing, even though I know all the fields are there. Critically – this worked fine before I added the password property to connection, so I genuinely don’t think it’s an assignment problem or I would expect it to have failed prior to implementing the password field.
I feel like I’m missing something absolutely stupid, but I’m hoping someone here has more insight to this than I do on my own. Or that you can at least confirm that I’m not crazy? Please and thank you!