How to manage permissions with Raspberry PLC and Node-RED

Create a Node-RED flow to control and manage user permissions
November 21, 2022 by
How to manage permissions with Raspberry PLC and Node-RED
Boot & Work Corp. S.L., Bernat Brunet Pedra

Introduction

Authorisations management is key to help system administrators control all users and their access rights to read, write and modify files on a system. The visibility of some files is also controlled by permissions, so a good tool to manage them is essential.

Node-RED offers an easy way to control permissions with Dashboard nodes, so let's get into it.

How to manage permissions with Raspberry PLC and Node-RED

Requirements


Initial configuration

What you are going to do first is to create users with their passwords and their access level number. In the example 0 is used for administrators and 1 for common users.

Drag an inject node and set it to inject one after 0.1 seconds. Then use a function node that will set the initial configuration for all users. You can use the code below and modify it at your own preferences:

flow.set("permissions",[
    {show: ["Dashboard_Vars","Dashboard_Temperature","Dashboard_Logout"],hide: ["Dashboard_Login"]},
    {show: ["Dashboard_Temperature","Dashboard_Logout"],hide: ["Dashboard_Login"]}
]);
flow.set("all_credentials",[
    {user: "admin", password: "admin", access: 0},
    {user: "is", password: "is", access: 1},
]);
msg.payload = {group: {
    show: ["Dashboard_Login"],
    hide: ["Dashboard_Vars","Dashboard_Temperature","Dashboard_Logout"]
}};
return msg;

The variable "permissions" is to set which tabs the users are allowed to see when they log in the Dashboard. The position 0 of the array will be for access level 0 and position 1 for access level 1...

The "all_credential" variable will be used to create all usernames, passwords and access levels. Remember that there must be as many access levels as elements in the "permissions" array.

Finally, the msg.payload will take the user to the Login screen and hide all other tabs to make the user login.

Attach a ui control node with the Output: "Connect, lost, change tab or group events". After configuring the system, add a form node and set it like this:

Form node

Then, add another function node to grant access based on the credentials entered by the user:

var all_credentials = flow.get("all_credentials");
var input_credentials = msg.payload;
msg.payload = -1;
all_credentials.forEach(function(credential) {
    if (input_credentials.user == credential.user) {
        if (input_credentials.password == credential.password) {
            msg.payload = credential.access;
        }
    }
});
return msg;

The msg.payload returned by this function is the access level of the user. If the user is not in the "all_credential" array, then msg.payload is -1.

Following the function node add a switch node with these parameters:

Switch node
It will filter out the wrong and the good users. In the first output, use another function node with:

msg.payload = "Invalid user / password";
return msg;

Use a notification node to warn the user that the credentials are incorrect, adding it to the previous node. In the second output, add a function node with the following code:

msg.payload = {group: flow.get("permissions")[msg.payload]};
return msg;

If you try to log in with a wrong username or password, you will see a message like this:

Invalid user / password message

Finally, attach a ui control node to the last function node with "Connect, lost, change tabs or group events" as output. The resultant flow should look like this:

Resultant flow


Additional tabs and logout button

Now let's add some tabs and a logout button. To implement the logout button, drag a button node from Node-RED Dashboard and attach a function node to it. Paste this code into it:

msg.payload = {group: {
    show: ["Dashboard_Login"],
    hide: ["Dashboard_Vars","Dashboard_Temperature","Dashboard_Logout"]
    }
};
return msg;

Thanks to this code, all tabs will be hidden and only the Login tab will be shown as desired. Remember to add another ui control node with the same configuration as the other to update the Dashboard tab. 

To create more tabs, use gauge nodes with their own groups but with the same tab. To follow the example add 2 groups named "Temperature" and "Vars". 

The final flow is:

Final flow

The upper tab tab of the dashboard is for "admin" user, and the second one is for the "is" user.

Dashboard

[{"id":"6547582a85d1894c","type":"ui_form","z":"d532948a1b537967","name":"","label":"","group":"b82da486.9fc8d8","order":0,"width":"6","height":"3","options":[{"label":"user","value":"user","type":"text","required":true,"rows":null},{"label":"password","value":"password","type":"password","required":true,"rows":null}],"formValue":{"user":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":110,"y":120,"wires":[["9980ef1cf3df35b5"]]},{"id":"9980ef1cf3df35b5","type":"function","z":"d532948a1b537967","name":"Account Verification","func":"var all_credentials = flow.get(\"all_credentials\");\n\nvar input_credentials = msg.payload;\nmsg.payload = -1;\n\nall_credentials.forEach(function(credential) {\n    if (input_credentials.user == credential.user) {\n        if (input_credentials.password == credential.password) {\n            msg.payload = credential.access;\n        }\n    }\n});\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":150,"y":160,"wires":[["50287406ab04691e"]]},{"id":"50287406ab04691e","type":"switch","z":"d532948a1b537967","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"-1","vt":"num"},{"t":"gte","v":"0","vt":"num"}],"checkall":"false","repair":false,"outputs":2,"x":310,"y":160,"wires":[["f2ef4626d978c8cb"],["207c81ac6aebbb41"]]},{"id":"162f94c223714e02","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"512","payloadType":"str","x":130,"y":260,"wires":[["09d75f205b9edbd4"]]},{"id":"734ecddc359a8af0","type":"ui_ui_control","z":"d532948a1b537967","name":"Go ","events":"all","x":690,"y":180,"wires":[[]]},{"id":"e36877220f4e7c54","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"244","payloadType":"str","x":130,"y":300,"wires":[["09d75f205b9edbd4"]]},{"id":"f4c81ab4d6293ced","type":"function","z":"d532948a1b537967","name":"Initial Configuration","func":"flow.set(\"permissions\",[\n    {show : [\"Dashboard_Vars\", \"Dashboard_Temperature\",\"Dashboard_Logout\"],hide : [\"Dashboard_Login\"]},\n    {show : [\"Dashboard_Temperature\",\"Dashboard_Logout\"], hide : [\"Dashboard_Login\", \"Dashboard_Vars\"]}\n]);\n\nflow.set(\"all_credentials\", [\n    { user: \"admin\", password: \"admin\", access: 0 },\n    { user: \"is\", password: \"is\", access: 1}\n]);\n\n// by default\nmsg.payload = { group: {\n    show : [\"Dashboard_Login\"],\n    hide : [\"Dashboard_Vars\", \"Dashboard_Temperature\",\"Dashboard_Logout\"]\n    }\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":150,"y":80,"wires":[["d48a4bbd999acef4"]]},{"id":"b6dbac06073c8839","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.1","topic":"","payload":"","payloadType":"date","x":130,"y":40,"wires":[["f4c81ab4d6293ced"]]},{"id":"fffe467df4191656","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"str","x":130,"y":220,"wires":[["09d75f205b9edbd4"]]},{"id":"d48a4bbd999acef4","type":"ui_ui_control","z":"d532948a1b537967","name":"Init Signin","events":"all","x":320,"y":80,"wires":[["6547582a85d1894c"]]},{"id":"c94db67dcaca1b9c","type":"ui_toast","z":"d532948a1b537967","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"Try again","cancel":"","raw":false,"className":"","topic":"","name":"Error credentials","x":680,"y":140,"wires":[[]]},{"id":"f2ef4626d978c8cb","type":"function","z":"d532948a1b537967","name":"Redirection group -1","func":"msg.payload = \"Invalid user / password\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":140,"wires":[["c94db67dcaca1b9c"]]},{"id":"54e408d40f9e356c","type":"ui_gauge","z":"d532948a1b537967","name":"","group":"890b942dcf34b138","order":1,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"units","format":"{{value}}","min":0,"max":"1024","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","className":"","x":270,"y":400,"wires":[]},{"id":"b3e190aceb4cf92a","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"512","payloadType":"str","x":130,"y":400,"wires":[["54e408d40f9e356c"]]},{"id":"dde730b3fd21156a","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"244","payloadType":"str","x":130,"y":440,"wires":[["54e408d40f9e356c"]]},{"id":"bdd6d7fa5e3ff1fa","type":"inject","z":"d532948a1b537967","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"str","x":130,"y":360,"wires":[["54e408d40f9e356c"]]},{"id":"207c81ac6aebbb41","type":"function","z":"d532948a1b537967","name":"Redirection of other groups","func":"msg.payload = { group : flow.get(\"permissions\")[msg.payload] };\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":180,"wires":[["734ecddc359a8af0"]]},{"id":"46f0f1db5cda4bdd","type":"ui_button","z":"d532948a1b537967","name":"","group":"7d39d06cc1795486","order":1,"width":0,"height":0,"passthru":false,"label":"Exit","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"true","payloadType":"bool","topic":"topic","topicType":"msg","x":270,"y":340,"wires":[["5ac4584ceed46916"]]},{"id":"5ac4584ceed46916","type":"function","z":"d532948a1b537967","name":"Logout Button","func":"msg.payload = { group: {\n    show : [\"Dashboard_Login\"],\n    hide : [\"Dashboard_Vars\", \"Dashboard_Temperature\",\"Dashboard_Logout\"]\n    }\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":340,"wires":[["a36f37eab1a6a3e7"]]},{"id":"a36f37eab1a6a3e7","type":"ui_ui_control","z":"d532948a1b537967","name":"Go ","events":"all","x":570,"y":340,"wires":[[]]},{"id":"09d75f205b9edbd4","type":"ui_gauge","z":"d532948a1b537967","name":"","group":"6c6ab64226fafc58","order":1,"width":0,"height":0,"gtype":"gage","title":"Vars","label":"units","format":"{{value}}","min":0,"max":"1024","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","className":"","x":250,"y":260,"wires":[]},{"id":"b82da486.9fc8d8","type":"ui_group","name":"Login","tab":"d65502b1.ee517","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"890b942dcf34b138","type":"ui_group","name":"Temperature","tab":"d65502b1.ee517","order":3,"disp":true,"width":"6","collapse":false,"className":""},{"id":"7d39d06cc1795486","type":"ui_group","name":"Logout","tab":"d65502b1.ee517","order":4,"disp":true,"width":"6","collapse":false,"className":""},{"id":"6c6ab64226fafc58","type":"ui_group","name":"Vars","tab":"d65502b1.ee517","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"d65502b1.ee517","type":"ui_tab","name":"Dashboard","icon":"dashboard","order":1}]

To add more groups remember that you will have to change the "Initial Settings" node and change the names, access levels or permission values as you wish.

Create a Node-RED flow to control and manage user permissions

And that's it!

With this blog you have learned the basics of permissions management and how to work with them.

Now you are ready to manage permissions and work with them.


​Search in our Blog

How to manage permissions with Raspberry PLC and Node-RED
Boot & Work Corp. S.L., Bernat Brunet Pedra November 21, 2022
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.


Industrial PLC comparison >>>