Three different Dashboard users

#1

Hi, I would like to use the Node-Red Dashboard with three different tablets. One for me, I see all the settings. The other for my sister she only sees her attitudes. The last one for my parents these see everything except my settings. For this I need three different users who can access the dashboard at the same time but only see their settings.

With this flow, I get three users who can only see what they should see. But if I go to the dashboard with two tablets at the same time <localhost: 1880 / ui>, then I am already logged in with the same user as with the first tablet.

[{"id":"90a1ecc2.35b05","type":"tab","label":"Benutzerverwaltung1","disabled":false,"info":""},{"id":"accd76ae.00fbf8","type":"debug","z":"90a1ecc2.35b05","name":"Debug Account Log ","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":580,"y":20,"wires":[]},{"id":"57109659.074708","type":"comment","z":"90a1ecc2.35b05","name":"Sign-In Section","info":"","x":120,"y":40,"wires":[]},{"id":"2ebf5309.33213c","type":"function","z":"90a1ecc2.35b05","name":"Account Log","func":"var accountlog =  flow.get(\"accountlog\") || [] ; \n\naccountlog.push({ accessAt : new Date(), username : msg.payload.username})\n\nflow.set(\"accountlog\", accountlog);\n\nmsg.payload = accountlog;\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":100,"wires":[["accd76ae.00fbf8"]]},{"id":"7411c315.c6e96c","type":"function","z":"90a1ecc2.35b05","name":"Account Verification","func":"var accounts =  flow.get(\"accounts\") || [ { username : \"I\", password1 : \"hello\"},{ username : \"parents\", password2 : \"123\"}, {username : \"Sister\", password3 : \"456\"}] ; \n\nvar username = msg.payload.username ;\nvar password = msg.payload.password ; \n\n\n\nvar newMsg = {}; newMsg.payload = 4;\n\naccounts.forEach(function ( account ){\n    if ( account.username == username ) {\n       newMsg.payload = 3;\n       if ( account.password1 == password ) {\n           newMsg.payload = 0;\n       } \n       if ( account.password2 == password ) {\n           newMsg.payload = 1;\n       }\n       if ( account.password3 == password ) {\n           newMsg.payload = 2;\n       }\n    }\n   \n});\n\nreturn newMsg;","outputs":1,"noerr":0,"x":400,"y":240,"wires":[["bcc6e54b.ac4a98","908b07b2.ee51f8","df6265ef.019638"]]},{"id":"a786beac.157e6","type":"comment","z":"90a1ecc2.35b05","name":"Sensor Data Collection","info":"","x":239.5,"y":1797.9999990463257,"wires":[]},{"id":"cc6ac924.6ac188","type":"inject","z":"90a1ecc2.35b05","name":"Timer","topic":"","payload":"","payloadType":"date","repeat":"2","crontab":"","once":false,"onceDelay":0.1,"x":211.99999237060547,"y":1875.0000066757202,"wires":[["c8272fdb.2787b"]]},{"id":"ddbc614e.5dc5c","type":"comment","z":"90a1ecc2.35b05","name":"MQTT ? CoAP?","info":"Expecting data from the actaul sensors.","x":387,"y":1834.9999914169312,"wires":[]},{"id":"8beb0508.15ed78","type":"ui_text","z":"90a1ecc2.35b05","group":"47c6f7e8.038ee8","order":0,"width":0,"height":0,"name":"Label Display","label":"","format":"{{msg.payload}}","layout":"row-spread","x":1125.0000076293945,"y":1958.0000982284546,"wires":[]},{"id":"c8272fdb.2787b","type":"function","z":"90a1ecc2.35b05","name":"Decode MySensor Message","func":"\nvar mySensorsMessage = {}\nvar newPayload = {};\nvar timestamp = new Date();\n\nnewPayload.nodeId  =  3;\nnewPayload.type =  Math.floor( Math.random() * Math.floor(2));  // 0 or 1\nif ( newPayload.type === 0 /* temperature */ ) newPayload.value   =  Math.floor( Math.random() * Math.floor(30)) + 10; // 10 - 39\nelse newPayload.value   =  Math.floor( Math.random() * Math.floor(40)) + 40; // 40 - 79\n\nmsg.payload = newPayload; \n\nreturn msg;","outputs":1,"noerr":0,"x":408,"y":1876.0000143051147,"wires":[["839a3291.eefe8","1c20f291.fc5b1d"]]},{"id":"839a3291.eefe8","type":"function","z":"90a1ecc2.35b05","name":"Filter : temperature","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 0) {\n    var msg;\n    msg.payload = msg.payload.value;\n    msg.topic = \"Temperature\"\n    return msg;\n}    ","outputs":1,"noerr":0,"x":613.0000762939453,"y":1820,"wires":[["e38219ae.5ebb78","4a230a3c.3a44d4","bae43624.14c7f8"]]},{"id":"e38219ae.5ebb78","type":"ui_gauge","z":"90a1ecc2.35b05","name":"Gauge : Temperature","group":"47c6f7e8.038ee8","order":0,"width":0,"height":0,"gtype":"gage","title":"Temperature DHT22","label":"MySensors v2","format":"{{value}}°C","min":0,"max":"50","colors":["#66ccff","#ff8000","#ca3838"],"seg1":"","seg2":"","x":876.0000228881836,"y":1813.9999799728394,"wires":[]},{"id":"1c20f291.fc5b1d","type":"function","z":"90a1ecc2.35b05","name":"Filter : humidity","func":"if (msg.payload.nodeId == 3 && msg.payload.type === 1) {\n    var msg;\n    msg.payload = msg.payload.value;\n    msg.topic = \"Humidity\"\n    return msg;\n}    ","outputs":1,"noerr":0,"x":600.0000839233398,"y":1938.000002861023,"wires":[["80e5aa8b.7678a8","4a230a3c.3a44d4","bae43624.14c7f8"]]},{"id":"80e5aa8b.7678a8","type":"ui_gauge","z":"90a1ecc2.35b05","name":"Gauge : Humidity","group":"47c6f7e8.038ee8","order":0,"width":"0","height":"0","gtype":"gage","title":"Humidity DHT22","label":"MySensors v2","format":"{{value}}%","min":0,"max":"100","colors":["#1a25ab","#e6e600","#ca3838"],"seg1":"","seg2":"","x":867.0000648498535,"y":1855.0000257492065,"wires":[]},{"id":"4a230a3c.3a44d4","type":"function","z":"90a1ecc2.35b05","name":"Attention : temperature & humidity","func":"context.data = context.data || new Object();\n\nswitch (msg.topic) {\n    case \"Temperature\":\n        context.data.temperature = msg.payload;\n        msg = null;\n        break;\n    case \"Humidity\":\n        context.data.humidity = msg.payload;\n        msg = null;\n        break;\n    default:\n        msg = null;\n    \tbreak;\n\n}\n\nif(context.data.temperature !== null && context.data.humidity !== null && context.data.temperature !== undefined && context.data.humidity !== undefined) {\n\tmsgOut = \"\"; //new Object();\n    msgOut = \"Temerature : \" \n    msgOut += context.data.temperature.toString(); \n    msgOut+= \"°C - Humidity : \"; \n    msgOut+= context.data.humidity.toString();\n    msgOut+= \"%\";\n    context.data=null;\n    var msg = {};\n    msg.payload = msgOut;\n\treturn msg;\n} \n//else return msg;","outputs":1,"noerr":0,"x":888.9999694824219,"y":1958.0000314712524,"wires":[["8beb0508.15ed78"]]},{"id":"bae43624.14c7f8","type":"ui_chart","z":"90a1ecc2.35b05","name":"History : Temperature & Humidity","group":"3b187810.3b8238","order":0,"width":"6","height":"9","label":"Temperature & Humidity","chartType":"line","legend":"true","xformat":"%H:%M","interpolate":"linear","nodata":"No Data Yet","dot":false,"ymin":"0","ymax":"80","removeOlder":"12","removeOlderPoints":"","removeOlderUnit":"3600","cutout":"","useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":true,"x":917.0000495910645,"y":1896.0000762939453,"wires":[[],[]]},{"id":"2bc9b9cf.4b1206","type":"debug","z":"90a1ecc2.35b05","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":350,"y":20,"wires":[]},{"id":"88ccd5eb.6e01a8","type":"ui_ui_control","z":"90a1ecc2.35b05","name":"","x":1180,"y":100,"wires":[[]]},{"id":"bcc6e54b.ac4a98","type":"debug","z":"90a1ecc2.35b05","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":650,"y":80,"wires":[]},{"id":"b8b818d7.2c8448","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"4d3ac8b2.b8c4b8","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":160,"wires":[["2ebf5309.33213c","7411c315.c6e96c","2bc9b9cf.4b1206"]]},{"id":"a33011c4.b0006","type":"function","z":"90a1ecc2.35b05","name":"I ","func":"    msg.payload = { group: {\n    hide : [\"Ausgänge_Signin\",\"Dashboard_Signin\",\"Test_Signin\",\"Status_Signin\",\"Handbuch_Signin\",\"Alarm_Signin\",\"eShop_Signin\",\"ButtonPanel_Signin\"],\n    show : [\"Ausgänge_Buttons\",\"Ausgänge_IQ1\",\"Ausgänge_Q4\",\"Ausgänge_Q3\",\"Ausgänge_Q2\",\"Ausgänge_Q1-Not-Halt\",\"Ausgänge_Platzhalter\",\"Ausgänge_Platzhalter2\",\n            \"Dashboard_SensorData\",\"Dashboard_History\",\n            \"Test_Buttons\",\"Test_PH\",\"Test_Group5\",\"Test_hallo\",\"Test_Group1\",\"Test_PH2\",\n            \"Status_Buttons\",\"Status_Placeholder\",\"Status_Modulstatus\",\"Status_Überstrom\",\"Status_A/BStatus\",\n            \"Handbuch_Handbuch\",\n            \"Alarm_Alarm\",\n            \"eShop_www\",\n            \"ButtonPanel_ControlPanel\",\"ButtonPanel_Group1\",\"ButtonPanel_Group2\", \"ButtonPanel_Starter\",\"ButtonPanel_Keypad\"]\n    }\n    };\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":20,"wires":[["88ccd5eb.6e01a8"]]},{"id":"908b07b2.ee51f8","type":"switch","z":"90a1ecc2.35b05","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"2","vt":"str"},{"t":"eq","v":"3","vt":"str"},{"t":"eq","v":"4","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":610,"y":160,"wires":[["a33011c4.b0006","d014333c.a87d6"],["d333eb68.1ad558","d014333c.a87d6"],["eea9a9cf.8badd8","d014333c.a87d6"],["156a562f.02214a"],["b986869f.b8c198"]]},{"id":"6a628b03.96fc24","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"b9cbf4d9.a73cb8","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":200,"wires":[["7411c315.c6e96c"]]},{"id":"fa10e3bf.334bd","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"6cbf0a99.1c6704","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":240,"wires":[["7411c315.c6e96c"]]},{"id":"4c5d9273.682c3c","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"27b6c358.fccdac","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":280,"wires":[["7411c315.c6e96c"]]},{"id":"6ef7b1bd.b0a4","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"2413ab2e.0dead4","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":320,"wires":[["7411c315.c6e96c"]]},{"id":"77f76ed2.b25ab","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"32fe23b6.7a559c","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":360,"wires":[["7411c315.c6e96c"]]},{"id":"22efa9ea.1675b6","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"e4f2c1b4.57872","order":0,"width":"6","height":"6","options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":400,"wires":[["7411c315.c6e96c"]]},{"id":"e411f288.22fd6","type":"ui_ui_control","z":"90a1ecc2.35b05","name":"Go to Signin Group","x":670,"y":780,"wires":[[]]},{"id":"e4ef4538.3fd098","type":"function","z":"90a1ecc2.35b05","name":"Sign-In Redirection","func":"var msg = {};\nmsg.payload = { group: {\n    show : [\"Ausgänge_Signin\",\"Dashboard_Signin\",\"Test_Signin\",\"Status_Signin\",\"Handbuch_Signin\",\"Alarm_Signin\",\"eShop_Signin\",\"ButtonPanel_Signin\"],\n    hide : [\"Ausgänge_Buttons\",\"Ausgänge_IQ1\",\"Ausgänge_Q4\",\"Ausgänge_Q3\",\"Ausgänge_Q2\",\"Ausgänge_Q1-Not-Halt\",\"Ausgänge_Platzhalter\",\"Ausgänge_Platzhalter2\",\n            \"Dashboard_SensorData\",\"Dashboard_History\",\n            \"Test_Buttons\",\"Test_PH\",\"Test_Group5\",\"Test_hallo\",\"Test_Group1\",\"Test_PH2\",\n            \"Status_Buttons\",\"Status_Placeholder\",\"Status_Modulstatus\",\"Status_Überstrom\",\"Status_A/BStatus\",\n            \"Handbuch_Handbuch\",\n            \"Alarm_Alarm\",\n            \"eShop_www\",\n            \"ButtonPanel_ControlPanel\",\"ButtonPanel_Group1\",\"ButtonPanel_Group2\", \"ButtonPanel_Starter\",\"ButtonPanel_Keypad\"]\n    }\n    };\n\nreturn msg;\n","outputs":1,"noerr":0,"x":410,"y":780,"wires":[["e411f288.22fd6","46eb4f11.e2d5f"]]},{"id":"bb4c7010.8010e","type":"ui_button","z":"90a1ecc2.35b05","name":"","group":"a041ee0b.507a6","order":6,"width":0,"height":0,"passthru":false,"label":"Logout","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":190,"y":780,"wires":[["e4ef4538.3fd098"]]},{"id":"bc2b863.de37f78","type":"ui_form","z":"90a1ecc2.35b05","name":"Dashboard Sign-In","label":"","group":"8316001e.d7f92","order":0,"width":0,"height":0,"options":[{"label":"username","value":"username","type":"text","required":true},{"label":"password","value":"password","type":"password","required":true}],"formValue":{"username":"","password":""},"payload":"","submit":"Login","cancel":"cancel","topic":"","x":110,"y":100,"wires":[["2ebf5309.33213c","2bc9b9cf.4b1206","7411c315.c6e96c"]]},{"id":"f8b69160.67adb","type":"link in","z":"90a1ecc2.35b05","name":"","links":["31f01a83.d06e36"],"x":220,"y":660,"wires":[["e4ef4538.3fd098","46eb4f11.e2d5f"]]},{"id":"94a5b677.0442f8","type":"link in","z":"90a1ecc2.35b05","name":"","links":["17ec9239.a430be"],"x":295,"y":880,"wires":[["e4ef4538.3fd098"]]},{"id":"46eb4f11.e2d5f","type":"debug","z":"90a1ecc2.35b05","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":690,"y":680,"wires":[]},{"id":"156a562f.02214a","type":"function","z":"90a1ecc2.35b05","name":"= 3 : Wrong Password","func":"msg.payload = \"Falsches Passwort\";\nreturn msg;","outputs":1,"noerr":0,"x":920,"y":180,"wires":[["d710cd68.a97ca"]]},{"id":"b986869f.b8c198","type":"function","z":"90a1ecc2.35b05","name":"= 4 : Unknown User","func":"msg.payload = \"Unbekannter Benutzer!!!\"\nreturn msg;","outputs":1,"noerr":0,"x":910,"y":220,"wires":[["d710cd68.a97ca"]]},{"id":"d710cd68.a97ca","type":"ui_toast","z":"90a1ecc2.35b05","position":"dialog","displayTime":"3","highlight":"","outputs":1,"ok":"OK","cancel":"","topic":"Authentication Failed","name":"Authentication Failure Dialog","x":1180,"y":200,"wires":[[]]},{"id":"df6265ef.019638","type":"debug","z":"90a1ecc2.35b05","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":610,"y":280,"wires":[]},{"id":"d333eb68.1ad558","type":"function","z":"90a1ecc2.35b05","name":"Parents Sicht","func":"    msg.payload = { group: {\n    hide : [\"Ausgänge_Signin\",\"Dashboard_Signin\",\"Test_Signin\",\"Status_Signin\",\"Handbuch_Signin\",\"Alarm_Signin\",\"eShop_Signin\",\"ButtonPanel_Signin\",\n            \"Status_Buttons\",\"Status_Placeholder\",\"Status_Modulstatus\",\"Status_Überstrom\",\"Status_A/BStatus\"],\n    show : [\"Ausgänge_Buttons\",\"Ausgänge_IQ1\",\"Ausgänge_Q4\",\"Ausgänge_Q3\",\"Ausgänge_Q2\",\"Ausgänge_Q1-Not-Halt\",\"Ausgänge_Platzhalter\",\"Ausgänge_Platzhalter2\",\n            \"Dashboard_SensorData\",\"Dashboard_History\",\n            \"Test_Buttons\",\"Test_PH\",\"Test_Group5\",\"Test_hallo\",\"Test_Group1\",\"Test_PH2\",\n            \"Handbuch_Handbuch\",\n            \"Alarm_Alarm\",\n            \"eShop_www\",\n            \"ButtonPanel_ControlPanel\",\"ButtonPanel_Group1\",\"ButtonPanel_Group2\", \"ButtonPanel_Starter\",\"ButtonPanel_Keypad\"]\n    }\n    };\nreturn msg;","outputs":1,"noerr":0,"x":910,"y":60,"wires":[["88ccd5eb.6e01a8"]]},{"id":"d014333c.a87d6","type":"link out","z":"90a1ecc2.35b05","name":"user","links":["fd7fb802.da30a8"],"x":955,"y":300,"wires":[]},{"id":"7d88afe1.58a93","type":"debug","z":"90a1ecc2.35b05","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"user","x":1030,"y":400,"wires":[]},{"id":"9b78893.2dd1d78","type":"comment","z":"90a1ecc2.35b05","name":"Logout","info":"","x":230,"y":600,"wires":[]},{"id":"c3d3080c.000718","type":"inject","z":"90a1ecc2.35b05","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":190,"y":720,"wires":[["e4ef4538.3fd098"]]},{"id":"eea9a9cf.8badd8","type":"function","z":"90a1ecc2.35b05","name":"sister","func":"    msg.payload = { group: {\n    hide : [\"Ausgänge_Signin\",\"Dashboard_Signin\",\"Test_Signin\",\"Status_Signin\",\"Handbuch_Signin\",\"Alarm_Signin\",\"eShop_Signin\",\"ButtonPanel_Signin\",\n            \"Status_Buttons\",\"Status_Placeholder\",\"Status_Modulstatus\",\"Status_Überstrom\",\"Status_A/BStatus\",\n            \"Dashboard_SensorData\",\"Dashboard_History\",\n            \"Test_Buttons\",\"Test_PH\",\"Test_Group5\",\"Test_hallo\",\"Test_Group1\",\"Test_PH2\",\n            \"Handbuch_Handbuch\",\n            \"Alarm_Alarm\",\n            \"eShop_www\",\n            \"ButtonPanel_ControlPanel\",\"ButtonPanel_Group1\",\"ButtonPanel_Group2\", \"ButtonPanel_Starter\",\"ButtonPanel_Keypad\"],\n    show : [\"Ausgänge_Buttons\",\"Ausgänge_IQ1\",\"Ausgänge_Q4\",\"Ausgänge_Q3\",\"Ausgänge_Q2\",\"Ausgänge_Q1-Not-Halt\",\"Ausgänge_Platzhalter\",\"Ausgänge_Platzhalter2\"]\n    }\n    };\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":120,"wires":[["88ccd5eb.6e01a8"]]},{"id":"47c6f7e8.038ee8","type":"ui_group","z":"","name":"SensorData","tab":"d551d644.a07008","order":2,"disp":true,"width":"6","collapse":false},{"id":"3b187810.3b8238","type":"ui_group","z":"","name":"History","tab":"d551d644.a07008","order":3,"disp":true,"width":"6","collapse":false},{"id":"4d3ac8b2.b8c4b8","type":"ui_group","z":"","name":"Signin","tab":"ddc3c08a.7faa7","order":2,"disp":true,"width":"6","collapse":false},{"id":"b9cbf4d9.a73cb8","type":"ui_group","z":"","name":"Signin","tab":"720743be.18865c","disp":true,"width":"6","collapse":false},{"id":"6cbf0a99.1c6704","type":"ui_group","z":"","name":"Signin","tab":"77d80d5a.0bac04","disp":true,"width":"6","collapse":false},{"id":"27b6c358.fccdac","type":"ui_group","z":"","name":"Signin","tab":"9a80d0ae.20c4b","disp":true,"width":"6","collapse":false},{"id":"2413ab2e.0dead4","type":"ui_group","z":"","name":"Signin","tab":"3d09908b.59c7f","disp":true,"width":"6","collapse":false},{"id":"32fe23b6.7a559c","type":"ui_group","z":"","name":"Signin","tab":"7ac7cf4c.b21d5","disp":true,"width":"6","collapse":false},{"id":"e4f2c1b4.57872","type":"ui_group","z":"","name":"Signin","tab":"bd7267ac.afc628","order":6,"disp":true,"width":"6","collapse":false},{"id":"a041ee0b.507a6","type":"ui_group","z":"","name":"Buttons","tab":"ddc3c08a.7faa7","order":1,"disp":true,"width":"6","collapse":false},{"id":"8316001e.d7f92","type":"ui_group","z":"","name":"Signin","tab":"d551d644.a07008","disp":true,"width":"6","collapse":false},{"id":"d551d644.a07008","type":"ui_tab","z":"","name":"Dashboard","icon":"dashboard","order":2},{"id":"ddc3c08a.7faa7","type":"ui_tab","z":"","name":"Ausgänge","icon":"<i class=\"fa fa-lightbulb-o\" aria-hidden=\"true\"></i>","order":1},{"id":"720743be.18865c","type":"ui_tab","z":"","name":"Test","icon":"dashboard","order":3},{"id":"77d80d5a.0bac04","type":"ui_tab","z":"","name":"Status","icon":"dashboard","order":4},{"id":"9a80d0ae.20c4b","type":"ui_tab","z":"","name":"Handbuch","icon":"dashboard","order":5},{"id":"3d09908b.59c7f","type":"ui_tab","z":"","name":"Alarm","icon":"dashboard","order":6},{"id":"7ac7cf4c.b21d5","type":"ui_tab","z":"","name":"eShop","icon":"dashboard","order":8},{"id":"bd7267ac.afc628","type":"ui_tab","z":"","name":"ButtonPanel","icon":"dashboard","order":10}]

Anyone have an idea how to solve this problem?

#2

Have you read the ReadMe for the dashboard?

1 Like
#3

You could have 3 instances of Node-Red running on different ports and have 3 Dashboards, 1 for each user.

#4

It may be a "problem" for you, but it is working as designed. All connected users/clients have access to a single runtime instance of node-red -- so there is no multi-tenant solution readily available.

As mentioned, you would have to have 3 instances of node-red installed, with different subsets of your master flow running for each other user. Another option is to not use the dashboard, but that means you'd have to build your own web pages using something like node-red-contrib-uibuilder.

One other technique I've used is to have the navigation between the pages determined by sending msgs to a central ui_control node. That way, you can redirect someone away from pages they should not see, until they have entered some "password" or "keycode" that allows them to get to that page. If that would work for you, there is more information posted in this discussion thread. There is also another post that shows a simple keypad implementation that might be useful for you.

2 Likes
#5

Thanks Shirckus, i will try it!

#6

What about using cookies to manage the different users?

#7

Since there is only one runtime server that is both single-threaded and single-tenant, I don't see how cookies will help...

This is not a traditional web application, with pages rendered dynamically for each end user -- it's a single page app that all users can see and interact with, while sending events back to the node-red server. Any new data that is sent to the dashboard widget nodes, on the back-end server, is passed to all the connected users to update their view of the dashboard in the front-end browser.

#8

Another solution would be to do it entirely in 1 big ui_template. It is not currently secure as passwords would be visible on the source client-side but multiple users can all log-on with their passwords and only see what is intended for them :

<div ng-init="msg.password = ''">
<div>
    <label for="pass">Password</label>
    <input type="text" ng-model="msg.password" id="pass" required>
</div>
</div>
<div ng-if="msg.password == 'hello'">
    Page1 - Qty of silly hats
  <input type="number" ng-model="msg.payload.data1" name="quantity" min="0" max="1000">
  <md-button ng-click="send(msg)">Send</md-button>
  <md-button ng-click="msg.password = ''">Logout</md-button>
</div>
<div ng-if="msg.password == '123'">
        Page2 - Sister stuff 
  <input type="number" ng-model="msg.payload.data2" name="quantity" min="0" max="1000">
  <md-button ng-click="send(msg)">Send</md-button>
  <md-button ng-click="msg.password = ''">Logout</md-button>
</div>
<div ng-if="msg.password == '456'">
        Page3 - Parents page
  <input type="number" ng-model="msg.payload.data3" name="quantity" min="0" max="1000">
  <md-button ng-click="send(msg)">Send</md-button>
  <md-button ng-click="msg.password = ''">Logout</md-button>
</div>
#9

Hey Steve (@shrickus),

But for another pull request you are hiding tabs based on a checkbox. So in that case data is also pushed (via dashboard widget nodes) to tabsheets that are not visible in the dashboard. Or does it not work that way?

So I'm wondering if you cannot do something similar: hide tabs based on a username instead of a checkbox? I have bet with my wife for 10 eur (which is my total monthly pocket money that I get from her) that you are able to implement such a pull request... So please don't let me down :pleading_face:
Bart

1 Like
#10

What username? The dashboard doesn't know anything about users.

#11

I was in fact referring to the username that I need to enter in the popup at login, but of course when the dashboard is not secured you don't have a username...

#12

The dashboard can only be secured using httpNodeAuth which only supports one hardcoded username/password. You cannot have multiple users.

#13

Damn, that is so true what you say. This really hurts ...

#14

looks like your wife is going shopping !!! :wink:

#15

... and i'm off the hook!

well, except i've still not been able to finish the PR :*(

#16

Here's an update to the solution that I had proposed without showing the passwords in the source, it's still not secure as the passwords are sent to the client in msg.payload and could be viewed with an angular scope watching plugin. But since it's for your family, I'm guessing this is acceptable.

[
    {
        "id": "2dbd64d.dab389c",
        "type": "ui_template",
        "z": "dc84661.55bfb98",
        "group": "5625d033.1d56f",
        "name": "",
        "order": 0,
        "width": "6",
        "height": "5",
        "format": "<div ng-init=\"msg.password = ''\">\n<div>\n    <label for=\"pass\">Password</label>\n    <input type=\"text\" ng-model=\"msg.password\" id=\"pass\" required>\n</div>\n</div>\n<div ng-if=\"msg.password == msg.payload.pw1\">\n    Page1 - Qty of silly hats\n  <input type=\"number\" ng-model=\"msg.payload.data1\" name=\"quantity\" min=\"0\" max=\"1000\">\n  <md-button ng-click=\"send(msg)\">Send</md-button>\n  <md-button ng-click=\"msg.password = ''\">Logout</md-button>\n</div>\n<div ng-if=\"msg.password == msg.payload.pw2\">\n        Page2 - Sister stuff \n  <input type=\"number\" ng-model=\"msg.payload.data2\" name=\"quantity\" min=\"0\" max=\"1000\">\n  <md-button ng-click=\"send(msg)\">Send</md-button>\n  <md-button ng-click=\"msg.password = ''\">Logout</md-button>\n</div>\n<div ng-if=\"msg.password == msg.payload.pw3\">\n        Page3 - Parents page\n  <input type=\"number\" ng-model=\"msg.payload.data3\" name=\"quantity\" min=\"0\" max=\"1000\">\n  <md-button ng-click=\"send(msg)\">Send</md-button>\n  <md-button ng-click=\"msg.password = ''\">Logout</md-button>\n</div>",
        "storeOutMessages": false,
        "fwdInMessages": true,
        "templateScope": "local",
        "x": 700,
        "y": 660,
        "wires": [
            []
        ]
    },
    {
        "id": "cada3873.7413c8",
        "type": "inject",
        "z": "dc84661.55bfb98",
        "name": "",
        "topic": "",
        "payload": "{\"pw1\":\"hello\",\"pw2\":\"123\",\"pw3\":\"456\"}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "x": 530,
        "y": 660,
        "wires": [
            [
                "2dbd64d.dab389c"
            ]
        ]
    },
    {
        "id": "5625d033.1d56f",
        "type": "ui_group",
        "z": "",
        "name": "test",
        "tab": "9a95bc09.40d37",
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "9a95bc09.40d37",
        "type": "ui_tab",
        "z": "",
        "name": "test25",
        "icon": "dashboard"
    }
]
#17

@hugobox
how does it work with the three instances? what do I have to do to get this?

#18

My trick is to have all the pages inside the ui-template and only show at first a password field. If the password matches one, then show the page. Have you tried importing my flow above? The passwords are 123, 456 and hello

Just make sure that the ui_template option: Add output messages to stored state is not selected as that would sync the dashboards which would defeat the trick.

#19

Hi,
I would really like to know why authentication with the Node-RED Dashboard is not possible. Can anyone explain that to me ?

Thanks

Georg

#20

To quote a very recent post to the slack channel by @dceejay

The dashboard is a plugin set of nodes for Node-RED so uses the same authentication as that. By default just a simple basic auth, but other schemes are possible to add via middleware.

Add Authentification via middleware