Skip to content

Commit

Permalink
feat(cloud): Add qscloud-user node
Browse files Browse the repository at this point in the history
Implements #70
  • Loading branch information
mountaindude committed Sep 14, 2023
1 parent cdeb96a commit 9554917
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 1 deletion.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
"qscloud-app": "src/qscloud/qscloud-app-nr.js",
"qscloud-license": "src/qscloud/qscloud-license-nr.js",
"qscloud-reload": "src/qscloud/qscloud-reload-nr.js",
"qscloud-reload-status": "src/qscloud/qscloud-reload-status-nr.js"
"qscloud-reload-status": "src/qscloud/qscloud-reload-status-nr.js",
"qscloud-user": "src/qscloud/qscloud-user-nr.js"
}
}
}
32 changes: 32 additions & 0 deletions src/lib/cloud/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable no-await-in-loop */

// Function to get all users and their associated metadata
// Parameters:
// node: node object
// qlik: authentication object
//
// Return
// Success: An array of user objects
// Failure: false
async function getUsers(node, qlik) {
let allItems = [];
try {
const items = await qlik.users.getUsers({ limit: 100 });

// eslint-disable-next-line no-restricted-syntax
for await (const item of items.pagination) {
allItems.push(item);
}
} catch (error) {
node.log(`Error getting users: ${error}`);
allItems = false;
}

// Return the spaces' metadata
return allItems;
}

// Make the function available to other files
module.exports = {
getUsers,
};
71 changes: 71 additions & 0 deletions src/qscloud/qscloud-user-nr.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script type="text/javascript">
// eslint-disable-next-line no-undef
RED.nodes.registerType('qscloud-user', {
category: 'Qlik Sense Cloud',
color: '#6BC46D',
defaults: {
name: { value: '' },
tenant: { value: '', type: 'qscloud-tenant' },
op: { value: 'r', options: ['r'], required: true },
},
inputs: 1,
outputs: 1,
outputLabels: ['One message containing metadata for all matching users'],
icon: 'file.png',
label() {
return this.name || 'qscloud-user';
},
oneditprepare() {
// eslint-disable-next-line no-unused-vars
const node = this;
},
});
</script>

<script type="text/html" data-template-name="qscloud-user">
<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>
<div class="form-row">
<label for="node-input-tenant"><i class="fa fa-server"></i> Qlik Sense Cloud tenant</label>
<input type="text" id="node-input-tenant" placeholder="Select tenant" readonly />
</div>
<div class="form-row">
<label for="node-input-op"><i class="fa fa-cog"></i> Operation</label>
<select id="node-input-op">
<option value="r">Read</option>
</select>
</div>
</script>

<script type="text/html" data-help-name="qscloud-user">
<p>A node that performas operations on Qlik Sense Cloud users.</p>

<h2>Shared properties</h2>
<ul>
<li><b>Name</b> - Name of the node.</li>
<li><b>Qlik Sense Cloud tenant</b> - The Qlik Sense Cloud tenant to use.</li>
<li><b>Operation</b> - The operation to perform.</li>
<ul>
<li><b>Read</b> - Get user metadata.</li>
</ul>
</ul>
</ul>


<h2>Input and output messages, per operation</h2>

<h3>Read</h3>
<p>Get metadata for users in Qlik Sense Cloud.</p>
<p>In current version data for all users in the tenant will be returned.</p>

<h4>Input message</h4>
<p>Content of the input message is ignored - the messge is only used to trigger the retrieval of user metadata.</p>

<p>Output message</p>
<p>The output message has the following properties:</p>
<ul>
<li><strong>payload.user:</strong> Array of user objects, one for each user in the tenant.</li>
</ul>
</script>
83 changes: 83 additions & 0 deletions src/qscloud/qscloud-user-nr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint-disable no-await-in-loop */
const { authenticate } = require('../lib/cloud/auth');
const { getUsers } = require('../lib/cloud/user');

// eslint-disable-next-line func-names
module.exports = function (RED) {
function QlikSenseCloudUser(config) {
RED.nodes.createNode(this, config);
const node = this;

// Get data from node configuration
node.tenant = RED.nodes.getNode(config.tenant);
node.op = config.op || 'r';

node.on('input', async (msg, send, done) => {
try {
const outMsg = {
payload: {},
};

// Get auth object
const { auth, qlik } = await authenticate(node, done);

if (!auth) {
// Error when authenticating
node.status({ fill: 'red', shape: 'ring', text: 'error authenticating' });
done('Error authenticating');
return false;
}

// Which operation to perform?
if (node.op === 'c') {
// Create users
} else if (node.op === 'r') {
// Read users
node.log('Getting users from Qlik Sense Cloud...');
node.status({ fill: 'yellow', shape: 'dot', text: 'getting users' });

// Add app arrays to out message
outMsg.payload.user = [];

// Get user information from Qlik Sense Cloud
const users = await getUsers(node, qlik);

// Add users to out message
users.forEach((user) => {
outMsg.payload.user.push(user);
});

// Log success
node.log(`Found ${outMsg.payload.user.length} matching users on Qlik Sense Cloud.`);
node.status({ fill: 'green', shape: 'dot', text: 'users retrieved' });
} else if (node.op === 'u') {
// Update users
} else if (node.op === 'd') {
// Delete users
} else {
// Invalid operation. Log error and return
node.status({ fill: 'red', shape: 'ring', text: 'invalid operation' });
node.log(`Invalid operation: ${node.op}`);
done(`Invalid operation: ${node.op}`);
return false;
}

// Send message to output 1
send(outMsg);

done();
} catch (err) {
node.error(err);
done(err);
}

return true;
});
}

RED.nodes.registerType('qscloud-user', QlikSenseCloudUser, {
defaults: {
tenant: { value: '', type: 'qscloud-tenant', required: true },
},
});
};

0 comments on commit 9554917

Please sign in to comment.