User management improvements.

Ylian Saint-Hilaire committed May 27, 2020 at 18:26 UTC 8443416afa713cd03d8ea1af54c0f7796aa3abd7
4 files changed +183 -17
meshuser.js
+36 -4
@@ -1433,8 +1433,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1433 }
1434 case 'deleteuser':
1435 {
1436 - console.log(command);
1437 -
1436 // Delete a user account
1437 var err = null, delusersplit, deluserid, deluser, deluserdomain;
1438 try {
@@ -1494,12 +1492,23 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1492 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
1493 parent.parent.DispatchEvent(parent.CreateNodeDispatchTargets(node.meshid, node._id), obj, event);
1494 });
1495 + } else if (i.startsWith('ugrp/')) {
1496 + // Get the device group
1497 + var ugroup = parent.userGroups[i];
1498 + if (ugroup) {
1499 + // Remove user from the user group
1500 + if (ugroup.links[deluser._id] != null) { delete ugroup.links[deluser._id]; parent.db.Set(ugroup); }
1501 +
1502 + // Notify user group change
1503 + change = 'Removed user ' + deluser.name + ' from user group ' + ugroup.name;
1504 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Removed user ' + deluser.name + ' from user group ' + ugroup.name, addUserDomain: deluserdomain.id };
1505 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
1506 + parent.parent.DispatchEvent(['*', ugroup._id, user._id, deluser._id], obj, event);
1507 + }
1508 }
1509 }
1510 }
1511
1501 - // TODO (UserGroups): Remove user groups??
1502 -
1512 db.Remove('ws' + deluser._id); // Remove user web state
1513 db.Remove('nt' + deluser._id); // Remove notes for this user
1514
@@ -1707,6 +1716,29 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1716 if (command.resetNextLogin === true) { newuser.passchange = -1; } else { newuser.passchange = Math.floor(Date.now() / 1000); }
1717 if (user.groups) { newuser.groups = user.groups; } // New accounts are automatically part of our groups (Realms).
1718
1719 + // Auto-join any user groups
1720 + if (typeof newuserdomain.newaccountsusergroups == 'object') {
1721 + for (var i in newuserdomain.newaccountsusergroups) {
1722 + var ugrpid = newuserdomain.newaccountsusergroups[i];
1723 + if (ugrpid.indexOf('/') < 0) { ugrpid = 'ugrp/' + newuserdomain.id + '/' + ugrpid; }
1724 + var ugroup = parent.userGroups[ugrpid];
1725 + if (ugroup != null) {
1726 + // Add group to the user
1727 + if (newuser.links == null) { newuser.links = {}; }
1728 + newuser.links[ugroup._id] = { rights: 1 };
1729 +
1730 + // Add user to the group
1731 + ugroup.links[newuser._id] = { userid: newuser._id, name: newuser.name, rights: 1 };
1732 + db.Set(ugroup);
1733 +
1734 + // Notify user group change
1735 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Added user ' + newuser.name + ' to user group ' + ugroup.name, addUserDomain: newuserdomain.id };
1736 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
1737 + parent.parent.DispatchEvent(['*', ugroup._id, user._id, newuser._id], obj, event);
1738 + }
1739 + }
1740 + }
1741 +
1742 parent.users[newuserid] = newuser;
1743
1744 // Create a user, generate a salt and hash the password
public/scripts/amt-wsman-0.2.0-min.js
+1 -1
@@ -1 +1 @@
1 -var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,d,c){var m="",i="";null!=d&&null!=c&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+d+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+c+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var d in s)l+="<g:"+d+">"+s[d]+"</g:"+d+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var d in r)if(null!=r[d])if(Array.isArray(r[d]))for(var c in r[d])l+="<r:"+d+">"+r[d][c]+"</r:"+d+">";else l+="<r:"+d+">"+r[d]+"</r:"+d+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];return(n=n||s.getElementsByTagName("a:Body")[0])?(0<n.childNodes.length&&((e=n.childNodes[0].localName).indexOf("_OUTPUT")==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])),r):null}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
1 +var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,c,d){var m="",i="";null!=c&&null!=d&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+c+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+d+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var c in s)l+="<g:"+c+">"+s[c]+"</g:"+c+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var c in r)if(null!=r[c])if(Array.isArray(r[c]))for(var d in r[c])l+="<r:"+c+">"+r[c][d]+"</r:"+c+">";else l+="<r:"+c+">"+r[c]+"</r:"+c+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];return(n=n||s.getElementsByTagName("a:Body")[0])?(0<n.childNodes.length&&((e=n.childNodes[0].localName).indexOf("_OUTPUT")==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])),r):null}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
views/default.handlebars
+2 -2
@@ -10663,7 +10663,7 @@
10663
10664 var x = '<div style=min-height:80px><table style=width:100%>';
10665 if ((args.hide & 8) != 0) { x += '<br />' + addDeviceAttribute("Name", gname); } // If title bar is hidden, display the user group name here
10666 - if (serverinfo.crossDomain != null) {
10666 + if ((serverinfo.crossDomain != null) || (debugmode != 0)) {
10667 var d = group._id.split('/')[1];
10668 x += addDeviceAttribute("Domain", (d != '')?EscapeHtml(d):('<i>' + "Default" + '</i>'));
10669 x += addDeviceAttribute("Group Identifier", EscapeHtml(group._id));
@@ -10972,7 +10972,7 @@
10972 var email = user.email?EscapeHtml(user.email):'<i>' + "Not set" + '</i>', everify = '';
10973 if (serverinfo.emailcheck) { everify = ((user.emailVerified == true) ? '<b style=color:green;cursor:pointer title="' + "Email is verified" + '">&#x2713</b> ' : '<b style=color:red;cursor:pointer title="' + "Email not verified" + '">&#x2717;</b> '); }
10974
10975 - if (serverinfo.crossDomain) {
10975 + if ((serverinfo.crossDomain) || (debugmode != 0)) {
10976 var d = user._id.split('/')[1];
10977 x += addDeviceAttribute("Domain", ((d != '')?EscapeHtml(d):('<i>' + "Default" + '</i>')));
10978 x += addDeviceAttribute("User Identifier", EscapeHtml(user._id));
webserver.js
+144 -10
@@ -385,15 +385,36 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
385 if (user == null) {
386 // Create a new user
387 var user = { type: 'user', _id: userid, name: username, creation: Math.floor(Date.now() / 1000), login: Math.floor(Date.now() / 1000), domain: domain.id };
388 - if (email) {
389 - user['email'] = email;
390 - user['emailVerified'] = true;
391 - }
388 + if (email) { user['email'] = email; user['emailVerified'] = true; }
389 if (domain.newaccountsrights) { user.siteadmin = domain.newaccountsrights; }
390 if (obj.common.validateStrArray(domain.newaccountrealms)) { user.groups = domain.newaccountrealms; }
391 var usercount = 0;
392 for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
393 if (usercount == 0) { user.siteadmin = 4294967295; /*if (domain.newaccounts === 2) { delete domain.newaccounts; }*/ } // If this is the first user, give the account site admin.
394 +
395 + // Auto-join any user groups
396 + if (typeof domain.newaccountsusergroups == 'object') {
397 + for (var i in domain.newaccountsusergroups) {
398 + var ugrpid = domain.newaccountsusergroups[i];
399 + if (ugrpid.indexOf('/') < 0) { ugrpid = 'ugrp/' + domain.id + '/' + ugrpid; }
400 + var ugroup = obj.userGroups[ugrpid];
401 + if (ugroup != null) {
402 + // Add group to the user
403 + if (user.links == null) { user.links = {}; }
404 + user.links[ugroup._id] = { rights: 1 };
405 +
406 + // Add user to the group
407 + ugroup.links[user._id] = { userid: user._id, name: user.name, rights: 1 };
408 + db.Set(ugroup);
409 +
410 + // Notify user group change
411 + var event = { etype: 'ugrp', ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Added user ' + user.name + ' to user group ' + ugroup.name, addUserDomain: domain.id };
412 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
413 + parent.DispatchEvent(['*', ugroup._id, user._id], obj, event);
414 + }
415 + }
416 + }
417 +
418 obj.users[user._id] = user;
419 obj.db.SetUser(user);
420 var event = { etype: 'user', userid: userid, username: username, account: obj.CloneSafeUser(user), action: 'accountcreate', msg: 'Account created, name is ' + name, domain: domain.id };
@@ -483,6 +504,30 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
504 var usercount = 0;
505 for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
506 if (usercount == 0) { user.siteadmin = 4294967295; /*if (domain.newaccounts === 2) { delete domain.newaccounts; }*/ } // If this is the first user, give the account site admin.
507 +
508 + // Auto-join any user groups
509 + if (typeof domain.newaccountsusergroups == 'object') {
510 + for (var i in domain.newaccountsusergroups) {
511 + var ugrpid = domain.newaccountsusergroups[i];
512 + if (ugrpid.indexOf('/') < 0) { ugrpid = 'ugrp/' + domain.id + '/' + ugrpid; }
513 + var ugroup = obj.userGroups[ugrpid];
514 + if (ugroup != null) {
515 + // Add group to the user
516 + if (user.links == null) { user.links = {}; }
517 + user.links[ugroup._id] = { rights: 1 };
518 +
519 + // Add user to the group
520 + ugroup.links[user._id] = { userid: user._id, name: user.name, rights: 1 };
521 + db.Set(ugroup);
522 +
523 + // Notify user group change
524 + var event = { etype: 'ugrp', ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Added user ' + user.name + ' to user group ' + ugroup.name, addUserDomain: domain.id };
525 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
526 + parent.DispatchEvent(['*', ugroup._id, user._id], obj, event);
527 + }
528 + }
529 + }
530 +
531 obj.users[user._id] = user;
532 obj.db.SetUser(user);
533 var event = { etype: 'user', userid: user._id, username: user.name, account: obj.CloneSafeUser(user), action: 'accountcreate', msg: 'Account created, name is ' + name, domain: domain.id };
@@ -1147,6 +1192,30 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1192 if (obj.common.validateStrArray(domain.newaccountrealms)) { user.groups = domain.newaccountrealms; }
1193 if ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true) && (req.body.apasswordhint)) { var hint = req.body.apasswordhint; if (hint.length > 250) { hint = hint.substring(0, 250); } user.passhint = hint; }
1194 if (domainUserCount == 0) { user.siteadmin = 4294967295; /*if (domain.newaccounts === 2) { delete domain.newaccounts; }*/ } // If this is the first user, give the account site admin.
1195 +
1196 + // Auto-join any user groups
1197 + if (typeof domain.newaccountsusergroups == 'object') {
1198 + for (var i in domain.newaccountsusergroups) {
1199 + var ugrpid = domain.newaccountsusergroups[i];
1200 + if (ugrpid.indexOf('/') < 0) { ugrpid = 'ugrp/' + domain.id + '/' + ugrpid; }
1201 + var ugroup = obj.userGroups[ugrpid];
1202 + if (ugroup != null) {
1203 + // Add group to the user
1204 + if (user.links == null) { user.links = {}; }
1205 + user.links[ugroup._id] = { rights: 1 };
1206 +
1207 + // Add user to the group
1208 + ugroup.links[user._id] = { userid: user._id, name: user.name, rights: 1 };
1209 + db.Set(ugroup);
1210 +
1211 + // Notify user group change
1212 + var event = { etype: 'ugrp', ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Added user ' + user.name + ' to user group ' + ugroup.name, addUserDomain: domain.id };
1213 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
1214 + parent.DispatchEvent(['*', ugroup._id, user._id], obj, event);
1215 + }
1216 + }
1217 + }
1218 +
1219 obj.users[user._id] = user;
1220 req.session.userid = user._id;
1221 req.session.domainid = domain.id;
@@ -1619,20 +1688,20 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1688 for (var i in deluser.links) {
1689 if (i.startsWith('mesh/')) {
1690 // Get the device group
1622 - mesh = parent.meshes[i];
1691 + var mesh = obj.meshes[i];
1692 if (mesh) {
1693 // Remove user from the mesh
1694 if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; parent.db.Set(mesh); }
1695
1696 // Notify mesh change
1628 - change = 'Removed user ' + deluser.name + ' from group ' + mesh.name;
1697 + var change = 'Removed user ' + deluser.name + ' from group ' + mesh.name;
1698 var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite };
1699 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
1631 - parent.parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, event);
1700 + parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, event);
1701 }
1702 } else if (i.startsWith('node/')) {
1703 // Get the node and the rights for this node
1635 - parent.GetNodeWithRights(domain, deluser, i, function (node, rights, visible) {
1704 + obj.GetNodeWithRights(domain, deluser, i, function (node, rights, visible) {
1705 if ((node == null) || (node.links == null) || (node.links[deluser._id] == null)) return;
1706
1707 // Remove the link and save the node to the database
@@ -1641,10 +1710,23 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1710 db.Set(obj.cleanDevice(node));
1711
1712 // Event the node change
1644 - var event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id, msg: (command.rights == 0) ? ('Removed user device rights for ' + node.name) : ('Changed user device rights for ' + node.name), node: parent.CloneSafeNode(node) }
1713 + var event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id, msg: ('Removed user device rights for ' + node.name), node: obj.CloneSafeNode(node) }
1714 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
1646 - parent.parent.DispatchEvent(['*', node.meshid, node._id], obj, event);
1715 + parent.DispatchEvent(['*', node.meshid, node._id], obj, event);
1716 });
1717 + } else if (i.startsWith('ugrp/')) {
1718 + // Get the device group
1719 + var ugroup = obj.userGroups[i];
1720 + if (ugroup) {
1721 + // Remove user from the user group
1722 + if (ugroup.links[deluser._id] != null) { delete ugroup.links[deluser._id]; parent.db.Set(ugroup); }
1723 +
1724 + // Notify user group change
1725 + var change = 'Removed user ' + deluser.name + ' from user group ' + ugroup.name;
1726 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Removed user ' + deluser.name + ' from user group ' + ugroup.name, addUserDomain: domain.id };
1727 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
1728 + parent.DispatchEvent(['*', ugroup._id, user._id, deluser._id], obj, event);
1729 + }
1730 }
1731 }
1732 }
@@ -1765,6 +1847,34 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1847 if (domain.newaccountsrights) { user.siteadmin = domain.newaccountsrights; } // New accounts automatically assigned server rights.
1848 if (newAccountRealms) { user.groups = newAccountRealms; } // New accounts automatically part of some groups (Realms).
1849 obj.users[userid] = user;
1850 +
1851 + // Auto-join any user groups
1852 + var newaccountsusergroups = null;
1853 + if (typeof domain.newaccountsusergroups == 'object') { newaccountsusergroups = domain.newaccountsusergroups; }
1854 + if (typeof domain.authstrategies[req.user.strategy].newaccountsusergroups == 'object') { newaccountsusergroups = domain.authstrategies[req.user.strategy].newaccountsusergroups; }
1855 + if (newaccountsusergroups) {
1856 + for (var i in newaccountsusergroups) {
1857 + var ugrpid = newaccountsusergroups[i];
1858 + if (ugrpid.indexOf('/') < 0) { ugrpid = 'ugrp/' + domain.id + '/' + ugrpid; }
1859 + var ugroup = obj.userGroups[ugrpid];
1860 + if (ugroup != null) {
1861 + // Add group to the user
1862 + if (user.links == null) { user.links = {}; }
1863 + user.links[ugroup._id] = { rights: 1 };
1864 +
1865 + // Add user to the group
1866 + ugroup.links[user._id] = { userid: user._id, name: user.name, rights: 1 };
1867 + db.Set(ugroup);
1868 +
1869 + // Notify user group change
1870 + var event = { etype: 'ugrp', ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Added user ' + user.name + ' to user group ' + ugroup.name, addUserDomain: domain.id };
1871 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
1872 + parent.DispatchEvent(['*', ugroup._id, user._id], obj, event);
1873 + }
1874 + }
1875 + }
1876 +
1877 + // Save the user
1878 obj.db.SetUser(user);
1879
1880 // Event user creation
@@ -1914,6 +2024,30 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2024 if (obj.common.validateStrArray(domain.newaccountrealms)) { user2.groups = domain.newaccountrealms; }
2025 for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
2026 if (usercount == 0) { user2.siteadmin = 4294967295; } // If this is the first user, give the account site admin.
2027 +
2028 + // Auto-join any user groups
2029 + if (typeof domain.newaccountsusergroups == 'object') {
2030 + for (var i in domain.newaccountsusergroups) {
2031 + var ugrpid = domain.newaccountsusergroups[i];
2032 + if (ugrpid.indexOf('/') < 0) { ugrpid = 'ugrp/' + domain.id + '/' + ugrpid; }
2033 + var ugroup = obj.userGroups[ugrpid];
2034 + if (ugroup != null) {
2035 + // Add group to the user
2036 + if (user2.links == null) { user2.links = {}; }
2037 + user2.links[ugroup._id] = { rights: 1 };
2038 +
2039 + // Add user to the group
2040 + ugroup.links[user2._id] = { userid: user2._id, name: user2.name, rights: 1 };
2041 + db.Set(ugroup);
2042 +
2043 + // Notify user group change
2044 + var event = { etype: 'ugrp', ugrpid: ugroup._id, name: ugroup.name, desc: ugroup.desc, action: 'usergroupchange', links: ugroup.links, msg: 'Added user ' + user2.name + ' to user group ' + ugroup.name, addUserDomain: domain.id };
2045 + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
2046 + parent.DispatchEvent(['*', ugroup._id, user2._id], obj, event);
2047 + }
2048 + }
2049 + }
2050 +
2051 obj.users[req.session.userid] = user2;
2052 obj.db.SetUser(user2);
2053 var event = { etype: 'user', userid: req.session.userid, username: req.connection.user, account: obj.CloneSafeUser(user2), action: 'accountcreate', msg: 'Domain account created, user ' + req.connection.user, domain: domain.id };