diff options
author | sgiehl <stefan@matomo.org> | 2022-07-29 10:47:39 +0300 |
---|---|---|
committer | sgiehl <stefan@matomo.org> | 2022-07-29 11:27:35 +0300 |
commit | d19b1da6f30ca4be57eeffaa74b0e39044d3a0cf (patch) | |
tree | 6799c27d0484c8f3a81672330adf321004b8240c | |
parent | 04c1149d81bd5e48671f212f9a1cbd12fa10ef85 (diff) | |
parent | c7294b3c6cf693abfcdf2096bf910ac9e36fcb6f (diff) |
Merge branch 'next_release' into 4.x-devmergetest
-rw-r--r-- | js/piwik.js | 5 | ||||
-rw-r--r-- | js/piwik.min.js | 10 | ||||
-rw-r--r-- | matomo.js | 10 | ||||
-rw-r--r-- | piwik.js | 10 | ||||
-rw-r--r-- | plugins/Login/tests/Integration/PasswordResetterTest.php | 7 | ||||
-rw-r--r-- | plugins/UsersManager/API.php | 19 | ||||
-rw-r--r-- | plugins/UsersManager/Repository/UserRepository.php | 11 | ||||
-rw-r--r-- | plugins/UsersManager/tests/Integration/APITest.php | 807 | ||||
-rw-r--r-- | plugins/UsersManager/tests/Integration/UserInviteTest.php | 2 | ||||
-rw-r--r-- | plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_rows_in_search.png | 4 | ||||
-rw-r--r-- | plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_edit.png | 4 | ||||
-rw-r--r-- | plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_user_created.png | 4 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png | 4 |
13 files changed, 480 insertions, 417 deletions
diff --git a/js/piwik.js b/js/piwik.js index 274d4ea4ac..deb7e71d59 100644 --- a/js/piwik.js +++ b/js/piwik.js @@ -2452,6 +2452,11 @@ if (typeof window.Matomo !== 'object') { configBrowserFeatureDetection = true; + // exclude paypal.com as referrer + if (/^https?:\/\/([a-z0-9\.\-]+\.)?paypal\.com(\/|$)/.test(configReferrerUrl)) { + configReferrerUrl = ''; + } + // Document title try { configTitle = documentAlias.title; diff --git a/js/piwik.min.js b/js/piwik.min.js index 940be1433a..24fce26258 100644 --- a/js/piwik.min.js +++ b/js/piwik.min.js @@ -30,11 +30,11 @@ at=ai.findFirstNodeHavingAttribute(au,this.CONTENT_PIECE_ATTR);if(!at){at=ai.fin }if(0===au.search("^[a-zA-Z]{2,11}:")){return au}if(au.search(/^\//)!==-1){return this.getLocation().origin+au}var at="(.*/)";var av=this.getLocation().origin+this.getLocation().pathname.match(new RegExp(at))[0];return av+au},isUrlToCurrentDomain:function(au){var av=this.toAbsoluteUrl(au);if(!av){return false}var at=this.getLocation().origin;if(at===av){return true}if(0===String(av).indexOf(at)){if(":"===String(av).substr(at.length,1)){return false}return true}return false},setHrefAttribute:function(au,at){if(!au||!at){return}ai.setAnyAttribute(au,"href",at)},shouldIgnoreInteraction:function(at){if(ai.hasNodeAttribute(at,this.CONTENT_IGNOREINTERACTION_ATTR)){return true}if(ai.hasNodeCssClass(at,this.CONTENT_IGNOREINTERACTION_CLASS)){return true}if(ai.hasNodeCssClass(at,this.LEGACY_CONTENT_IGNOREINTERACTION_CLASS)){return true}return false}};function aa(au,ax){if(ax){return ax}au=w.toAbsoluteUrl(au);if(A(au,"?")){var aw=au.indexOf("?");au=au.slice(0,aw)}if(U(au,"matomo.php")){au=f(au,"matomo.php".length) }else{if(U(au,"piwik.php")){au=f(au,"piwik.php".length)}else{if(U(au,".php")){var at=au.lastIndexOf("/");var av=1;au=au.slice(0,at+av)}}}if(U(au,"/js/")){au=f(au,"js/".length)}return au}function R(az){var aB="Matomo_Overlay";var au=new RegExp("index\\.php\\?module=Overlay&action=startOverlaySession&idSite=([0-9]+)&period=([^&]+)&date=([^&]+)(&segment=[^&]*)?");var av=au.exec(J.referrer);if(av){var ax=av[1];if(ax!==String(az)){return false}var ay=av[2],at=av[3],aw=av[4];if(!aw){aw=""}else{if(aw.indexOf("&segment=")===0){aw=aw.substr("&segment=".length)}}W.name=aB+"###"+ay+"###"+at+"###"+aw}var aA=W.name.split("###");return aA.length===4&&aA[0]===aB}function ad(au,az,av){var ay=W.name.split("###"),ax=ay[1],at=ay[2],aw=ay[3],aA=aa(au,az);o(aA+"plugins/Overlay/client/client.js?v=1",function(){Matomo_Overlay_Client.initialize(aA,av,ax,at,aw)})}function v(){var av;try{av=W.frameElement}catch(au){return true}if(M(av)){return(av&&String(av.nodeName).toLowerCase()==="iframe")?true:false}try{return W.self!==W.top }catch(at){return true}}function T(co,ci){var bR=this,bk="mtm_consent",cT="mtm_cookie_consent",c2="mtm_consent_removed",cd=ae(J.domain,W.location.href,N()),da=O(cd[0]),bW=p(cd[1]),bw=p(cd[2]),c8=false,cs="GET",dt=cs,aM="application/x-www-form-urlencoded; charset=UTF-8",cL=aM,aI=co||"",bQ="",dh="",cy="",cf=ci||"",bH="",bX="",bb,bq="",dp=["7z","aac","apk","arc","arj","asf","asx","avi","azw3","bin","csv","deb","dmg","doc","docx","epub","exe","flv","gif","gz","gzip","hqx","ibooks","jar","jpg","jpeg","js","mobi","mp2","mp3","mp4","mpg","mpeg","mov","movie","msi","msp","odb","odf","odg","ods","odt","ogg","ogv","pdf","phps","png","ppt","pptx","qt","qtm","ra","ram","rar","rpm","rtf","sea","sit","tar","tbz","tbz2","bz","bz2","tgz","torrent","txt","wav","wma","wmv","wpd","xls","xlsx","xml","z","zip"],aC=[da],bI=[],cM=[".paypal.com"],ct=[],bU=[],bf=[],bS=500,dd=true,cZ,bc,b0,bY,at,cC=["pk_campaign","mtm_campaign","piwik_campaign","matomo_campaign","utm_campaign","utm_source","utm_medium"],bP=["pk_kwd","mtm_kwd","piwik_kwd","matomo_kwd","utm_term"],br="_pk_",az="pk_vid",a6=180,df,by,b1=false,aN="Lax",bt=false,c6,bl,bE,c0=33955200000,cz=1800000,dn=15768000000,a9=true,bN=false,bo=false,bZ=false,aV=false,cl,b5={},cx={},bv={},bC=200,cH={},di={},dq={},aZ={},cj=[],bu=false,ck=[],cp=false,cR=false,au=false,dr=false,c3=false,aS=false,bj=v(),cN=null,dg=null,aW,bK,cg=aq,bx,aQ,bJ=false,cE=0,bD=["id","ses","cvar","ref"],cQ=false,bL=null,c1=[],cG=[],aB=X++,aA=false,de=true; -try{bq=J.title}catch(cO){bq=""}function aH(dE){if(bt&&dE!==c2){return 0}var dC=new RegExp("(^|;)[ ]*"+dE+"=([^;]*)"),dD=dC.exec(J.cookie);return dD?V(dD[2]):0}bL=!aH(c2);function dx(dG,dH,dK,dJ,dE,dF,dI){if(bt&&dG!==c2){return}var dD;if(dK){dD=new Date();dD.setTime(dD.getTime()+dK)}if(!dI){dI="Lax"}J.cookie=dG+"="+t(dH)+(dK?";expires="+dD.toGMTString():"")+";path="+(dJ||"/")+(dE?";domain="+dE:"")+(dF?";secure":"")+";SameSite="+dI;if((!dK||dK>=0)&&aH(dG)!==String(dH)){var dC="There was an error setting cookie `"+dG+"`. Please check domain and path.";ao(dC)}}function cb(dC){var dE,dD;dC=j(dC,az);dC=j(dC,"ignore_referrer");dC=j(dC,"ignore_referer");for(dD=0;dD<ct.length;dD++){dC=j(dC,ct[dD])}if(bY){dE=new RegExp("#.*");return dC.replace(dE,"")}return dC}function b4(dE,dC){var dF=s(dC),dD;if(dF){return dC}if(dC.slice(0,1)==="/"){return s(dE)+"://"+d(dE)+dC}dE=cb(dE);dD=dE.indexOf("?");if(dD>=0){dE=dE.slice(0,dD)}dD=dE.lastIndexOf("/");if(dD!==dE.length-1){dE=dE.slice(0,dD+1)}return dE+dC}function cX(dE,dC){var dD; -dE=String(dE).toLowerCase();dC=String(dC).toLowerCase();if(dE===dC){return true}if(dC.slice(0,1)==="."){if(dE===dC.slice(1)){return true}dD=dE.length-dC.length;if((dD>0)&&(dE.slice(dD)===dC)){return true}}return false}function cw(dC){var dD=document.createElement("a");if(dC.indexOf("//")!==0&&dC.indexOf("http")!==0){if(dC.indexOf("*")===0){dC=dC.substr(1)}if(dC.indexOf(".")===0){dC=dC.substr(1)}dC="http://"+dC}dD.href=w.toAbsoluteUrl(dC);if(dD.pathname){return dD.pathname}return""}function ba(dD,dC){if(!an(dC,"/")){dC="/"+dC}if(!an(dD,"/")){dD="/"+dD}var dE=(dC==="/"||dC==="/*");if(dE){return true}if(dD===dC){return true}dC=String(dC).toLowerCase();dD=String(dD).toLowerCase();if(U(dC,"*")){dC=dC.slice(0,-1);dE=(!dC||dC==="/");if(dE){return true}if(dD===dC){return true}return dD.indexOf(dC)===0}if(!U(dD,"/")){dD+="/"}if(!U(dC,"/")){dC+="/"}return dD.indexOf(dC)===0}function aw(dG,dI){var dD,dC,dE,dF,dH;for(dD=0;dD<aC.length;dD++){dF=O(aC[dD]);dH=cw(aC[dD]);if(cX(dG,dF)&&ba(dI,dH)){return true -}}return false}function a2(dF){var dD,dC,dE;for(dD=0;dD<aC.length;dD++){dC=O(aC[dD].toLowerCase());if(dF===dC){return true}if(dC.slice(0,1)==="."){if(dF===dC.slice(1)){return true}dE=dF.length-dC.length;if((dE>0)&&(dF.slice(dE)===dC)){return true}}}return false}function cD(dC){var dD,dF,dH,dE,dG;if(!dC.length||!cM.length){return false}dF=d(dC);dH=cw(dC);if(dF.indexOf("www.")===0){dF=dF.substr(4)}for(dD=0;dD<cM.length;dD++){dE=O(cM[dD]);dG=cw(cM[dD]);if(dE.indexOf("www.")===0){dE=dE.substr(4)}if(cX(dF,dE)&&ba(dH,dG)){return true}}return false}function cA(dC,dE){dC=dC.replace("send_image=0","send_image=1");var dD=new Image(1,1);dD.onload=function(){H=0;if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:true})}};dD.onerror=function(){if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:false})}};dD.src=aI+(aI.indexOf("?")<0?"?":"&")+dC}function cU(dC){if(dt==="POST"){return true}return dC&&(dC.length>2000||dC.indexOf('{"requests"')===0)}function aP(){return"object"===typeof g&&"function"===typeof g.sendBeacon&&"function"===typeof Blob -}function bd(dG,dJ,dI){var dE=aP();if(!dE){return false}var dF={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dK=false;var dD=aI;try{var dC=new Blob([dG],dF);if(dI&&!cU(dG)){dC=new Blob([],dF);dD=dD+(dD.indexOf("?")<0?"?":"&")+dG}dK=g.sendBeacon(dD,dC)}catch(dH){return false}if(dK&&typeof dJ==="function"){dJ({request:dG,trackerUrl:aI,success:true,isSendBeacon:true})}return dK}function dm(dD,dE,dC){if(!M(dC)||null===dC){dC=true}if(m&&bd(dD,dE,dC)){return}setTimeout(function(){if(m&&bd(dD,dE,dC)){return}var dH;try{var dG=W.XMLHttpRequest?new W.XMLHttpRequest():W.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;dG.open("POST",aI,true);dG.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dI=m&&bd(dD,dE,dC);if(!dI&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dE==="function")){dE({request:dD,trackerUrl:aI,success:true,xhr:this})}}}; -dG.setRequestHeader("Content-Type",cL);dG.withCredentials=true;dG.send(dD)}catch(dF){dH=m&&bd(dD,dE,dC);if(!dH&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false})}}}},50)}function cq(dD){var dC=new Date();var dE=dC.getTime()+dD;if(!r||dE>r){r=dE}}function bh(){bj=true;cN=new Date().getTime()}function dw(){var dC=new Date().getTime();return !cN||(dC-cN)>bc}function aD(){if(dw()){b0()}}function a1(){if(J.visibilityState==="hidden"&&dw()){b0()}else{if(J.visibilityState==="visible"){cN=new Date().getTime()}}}function dz(){if(aS||!bc){return}aS=true;ar(W,"focus",bh);ar(W,"blur",aD);ar(W,"visibilitychange",a1);af++;u.addPlugin("HeartBeat"+af,{unload:function(){if(aS&&dw()){b0()}}})}function cS(dG){var dD=new Date();var dC=dD.getTime();dg=dC;if(cR&&dC<cR){var dE=cR-dC;setTimeout(dG,dE);cq(dE+50);cR+=50;return}if(cR===false){var dF=800;cR=dC+dF}dG()}function aT(){if(aH(c2)){bL=false}else{if(aH(bk)){bL=true}}}function bT(dE){if(!aZ){return dE}var dD,dC="&uadata="+t(W.JSON.stringify(aZ)); +if(/^https?:\/\/([a-z0-9\.\-]+\.)?paypal\.com(\/|$)/.test(bw)){bw=""}try{bq=J.title}catch(cO){bq=""}function aH(dE){if(bt&&dE!==c2){return 0}var dC=new RegExp("(^|;)[ ]*"+dE+"=([^;]*)"),dD=dC.exec(J.cookie);return dD?V(dD[2]):0}bL=!aH(c2);function dx(dG,dH,dK,dJ,dE,dF,dI){if(bt&&dG!==c2){return}var dD;if(dK){dD=new Date();dD.setTime(dD.getTime()+dK)}if(!dI){dI="Lax"}J.cookie=dG+"="+t(dH)+(dK?";expires="+dD.toGMTString():"")+";path="+(dJ||"/")+(dE?";domain="+dE:"")+(dF?";secure":"")+";SameSite="+dI;if((!dK||dK>=0)&&aH(dG)!==String(dH)){var dC="There was an error setting cookie `"+dG+"`. Please check domain and path.";ao(dC)}}function cb(dC){var dE,dD;dC=j(dC,az);dC=j(dC,"ignore_referrer");dC=j(dC,"ignore_referer");for(dD=0;dD<ct.length;dD++){dC=j(dC,ct[dD])}if(bY){dE=new RegExp("#.*");return dC.replace(dE,"")}return dC}function b4(dE,dC){var dF=s(dC),dD;if(dF){return dC}if(dC.slice(0,1)==="/"){return s(dE)+"://"+d(dE)+dC}dE=cb(dE);dD=dE.indexOf("?");if(dD>=0){dE=dE.slice(0,dD)}dD=dE.lastIndexOf("/"); +if(dD!==dE.length-1){dE=dE.slice(0,dD+1)}return dE+dC}function cX(dE,dC){var dD;dE=String(dE).toLowerCase();dC=String(dC).toLowerCase();if(dE===dC){return true}if(dC.slice(0,1)==="."){if(dE===dC.slice(1)){return true}dD=dE.length-dC.length;if((dD>0)&&(dE.slice(dD)===dC)){return true}}return false}function cw(dC){var dD=document.createElement("a");if(dC.indexOf("//")!==0&&dC.indexOf("http")!==0){if(dC.indexOf("*")===0){dC=dC.substr(1)}if(dC.indexOf(".")===0){dC=dC.substr(1)}dC="http://"+dC}dD.href=w.toAbsoluteUrl(dC);if(dD.pathname){return dD.pathname}return""}function ba(dD,dC){if(!an(dC,"/")){dC="/"+dC}if(!an(dD,"/")){dD="/"+dD}var dE=(dC==="/"||dC==="/*");if(dE){return true}if(dD===dC){return true}dC=String(dC).toLowerCase();dD=String(dD).toLowerCase();if(U(dC,"*")){dC=dC.slice(0,-1);dE=(!dC||dC==="/");if(dE){return true}if(dD===dC){return true}return dD.indexOf(dC)===0}if(!U(dD,"/")){dD+="/"}if(!U(dC,"/")){dC+="/"}return dD.indexOf(dC)===0}function aw(dG,dI){var dD,dC,dE,dF,dH;for(dD=0; +dD<aC.length;dD++){dF=O(aC[dD]);dH=cw(aC[dD]);if(cX(dG,dF)&&ba(dI,dH)){return true}}return false}function a2(dF){var dD,dC,dE;for(dD=0;dD<aC.length;dD++){dC=O(aC[dD].toLowerCase());if(dF===dC){return true}if(dC.slice(0,1)==="."){if(dF===dC.slice(1)){return true}dE=dF.length-dC.length;if((dE>0)&&(dF.slice(dE)===dC)){return true}}}return false}function cD(dC){var dD,dF,dH,dE,dG;if(!dC.length||!cM.length){return false}dF=d(dC);dH=cw(dC);if(dF.indexOf("www.")===0){dF=dF.substr(4)}for(dD=0;dD<cM.length;dD++){dE=O(cM[dD]);dG=cw(cM[dD]);if(dE.indexOf("www.")===0){dE=dE.substr(4)}if(cX(dF,dE)&&ba(dH,dG)){return true}}return false}function cA(dC,dE){dC=dC.replace("send_image=0","send_image=1");var dD=new Image(1,1);dD.onload=function(){H=0;if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:true})}};dD.onerror=function(){if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:false})}};dD.src=aI+(aI.indexOf("?")<0?"?":"&")+dC}function cU(dC){if(dt==="POST"){return true}return dC&&(dC.length>2000||dC.indexOf('{"requests"')===0) +}function aP(){return"object"===typeof g&&"function"===typeof g.sendBeacon&&"function"===typeof Blob}function bd(dG,dJ,dI){var dE=aP();if(!dE){return false}var dF={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dK=false;var dD=aI;try{var dC=new Blob([dG],dF);if(dI&&!cU(dG)){dC=new Blob([],dF);dD=dD+(dD.indexOf("?")<0?"?":"&")+dG}dK=g.sendBeacon(dD,dC)}catch(dH){return false}if(dK&&typeof dJ==="function"){dJ({request:dG,trackerUrl:aI,success:true,isSendBeacon:true})}return dK}function dm(dD,dE,dC){if(!M(dC)||null===dC){dC=true}if(m&&bd(dD,dE,dC)){return}setTimeout(function(){if(m&&bd(dD,dE,dC)){return}var dH;try{var dG=W.XMLHttpRequest?new W.XMLHttpRequest():W.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;dG.open("POST",aI,true);dG.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dI=m&&bd(dD,dE,dC);if(!dI&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dE==="function")){dE({request:dD,trackerUrl:aI,success:true,xhr:this}) +}}};dG.setRequestHeader("Content-Type",cL);dG.withCredentials=true;dG.send(dD)}catch(dF){dH=m&&bd(dD,dE,dC);if(!dH&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false})}}}},50)}function cq(dD){var dC=new Date();var dE=dC.getTime()+dD;if(!r||dE>r){r=dE}}function bh(){bj=true;cN=new Date().getTime()}function dw(){var dC=new Date().getTime();return !cN||(dC-cN)>bc}function aD(){if(dw()){b0()}}function a1(){if(J.visibilityState==="hidden"&&dw()){b0()}else{if(J.visibilityState==="visible"){cN=new Date().getTime()}}}function dz(){if(aS||!bc){return}aS=true;ar(W,"focus",bh);ar(W,"blur",aD);ar(W,"visibilitychange",a1);af++;u.addPlugin("HeartBeat"+af,{unload:function(){if(aS&&dw()){b0()}}})}function cS(dG){var dD=new Date();var dC=dD.getTime();dg=dC;if(cR&&dC<cR){var dE=cR-dC;setTimeout(dG,dE);cq(dE+50);cR+=50;return}if(cR===false){var dF=800;cR=dC+dF}dG()}function aT(){if(aH(c2)){bL=false}else{if(aH(bk)){bL=true}}}function bT(dE){if(!aZ){return dE}var dD,dC="&uadata="+t(W.JSON.stringify(aZ)); if(dE instanceof Array){for(dD=0;dD<dE.length;dD++){dE[dD]+=dC}}else{dE+=dC}return dE}function cB(dC){if(!de||!M(g.userAgentData)||!C(g.userAgentData.getHighEntropyValues)){dC();return}aZ={brands:g.userAgentData.brands,platform:g.userAgentData.platform};g.userAgentData.getHighEntropyValues(["brands","model","platform","platformVersion","uaFullVersion","fullVersionList"]).then(function(dE){var dD;if(dE.fullVersionList){delete dE.brands;delete dE.uaFullVersion}aZ=dE;dC()},function(dD){dC()})}function bO(dD,dC,dE){if(!bu){cj.push(dD);return}aT();if(!bL){c1.push(dD);return}aA=true;if(!c6&&dD){if(cQ&&bL){dD+="&consent=1"}dD=bT(dD);cS(function(){if(dd&&bd(dD,dE,true)){cq(100);return}if(cU(dD)){dm(dD,dE)}else{cA(dD,dE)}cq(dC)})}if(!aS){dz()}}function cv(dC){if(c6){return false}return(dC&&dC.length)}function dl(dC,dG){if(!dG||dG>=dC.length){return[dC]}var dD=0;var dE=dC.length;var dF=[];for(dD;dD<dE;dD+=dG){dF.push(dC.slice(dD,dD+dG))}return dF}function dy(dD,dC){if(!cv(dD)){return}if(!bu){cj.push(dD); return}if(!bL){c1.push(dD);return}aA=true;cS(function(){var dG=dl(dD,50);var dE=0,dF;for(dE;dE<dG.length;dE++){dF='{"requests":["?'+bT(dG[dE]).join('","?')+'"],"send_image":0}';if(dd&&bd(dF,null,false)){cq(100)}else{dm(dF,null,false)}}cq(dC)})}function aY(dC){return br+dC+"."+cf+"."+bx}function b8(dE,dD,dC){dx(dE,"",-129600000,dD,dC)}function ce(){if(bt){return"0"}if(!M(W.showModalDialog)&&M(g.cookieEnabled)){return g.cookieEnabled?"1":"0"}var dC=br+"testcookie";dx(dC,"1",undefined,by,df,b1,aN);var dD=aH(dC)==="1"?"1":"0";b8(dC);return dD}function bp(){bx=cg((df||da)+(by||"/")).slice(0,4)}function cY(){cB(function(){var dI,dH;bu=true;for(dI=0;dI<cj.length;dI++){dH=typeof cj[dI];if(dH==="string"){bO(cj[dI],bS)}else{if(dH==="object"){dy(cj[dI],bS)}}}cj=[]});if(!de){return{}}if(M(dq.res)){return dq}var dD,dF,dG={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",fla:"application/x-shockwave-flash",java:"application/x-java-vm",ag:"application/x-silverlight"}; if(!((new RegExp("MSIE")).test(g.userAgent))){if(g.mimeTypes&&g.mimeTypes.length){for(dD in dG){if(Object.prototype.hasOwnProperty.call(dG,dD)){dF=g.mimeTypes[dG[dD]];dq[dD]=(dF&&dF.enabledPlugin)?"1":"0"}}}if(!((new RegExp("Edge[ /](\\d+[\\.\\d]+)")).test(g.userAgent))&&typeof navigator.javaEnabled!=="unknown"&&M(g.javaEnabled)&&g.javaEnabled()){dq.java="1"}if(!M(W.showModalDialog)&&M(g.cookieEnabled)){dq.cookie=g.cookieEnabled?"1":"0"}else{dq.cookie=ce()}}var dE=parseInt(ab.width,10);var dC=parseInt(ab.height,10);dq.res=parseInt(dE,10)+"x"+parseInt(dC,10);return dq}function b6(){var dD=aY("cvar"),dC=aH(dD);if(dC&&dC.length){dC=W.JSON.parse(dC);if(Z(dC)){return dC}}return{}}function cV(){if(aV===false){aV=b6()}}function c7(){var dC=cY();return cg((g.userAgent||"")+(g.platform||"")+W.JSON.stringify(dC)+(new Date()).getTime()+Math.random()).slice(0,16)}function aF(){var dC=cY();return cg((g.userAgent||"")+(g.platform||"")+W.JSON.stringify(dC)).slice(0,6)}function bm(){return Math.floor((new Date()).getTime()/1000) @@ -30,11 +30,11 @@ at=ai.findFirstNodeHavingAttribute(au,this.CONTENT_PIECE_ATTR);if(!at){at=ai.fin }if(0===au.search("^[a-zA-Z]{2,11}:")){return au}if(au.search(/^\//)!==-1){return this.getLocation().origin+au}var at="(.*/)";var av=this.getLocation().origin+this.getLocation().pathname.match(new RegExp(at))[0];return av+au},isUrlToCurrentDomain:function(au){var av=this.toAbsoluteUrl(au);if(!av){return false}var at=this.getLocation().origin;if(at===av){return true}if(0===String(av).indexOf(at)){if(":"===String(av).substr(at.length,1)){return false}return true}return false},setHrefAttribute:function(au,at){if(!au||!at){return}ai.setAnyAttribute(au,"href",at)},shouldIgnoreInteraction:function(at){if(ai.hasNodeAttribute(at,this.CONTENT_IGNOREINTERACTION_ATTR)){return true}if(ai.hasNodeCssClass(at,this.CONTENT_IGNOREINTERACTION_CLASS)){return true}if(ai.hasNodeCssClass(at,this.LEGACY_CONTENT_IGNOREINTERACTION_CLASS)){return true}return false}};function aa(au,ax){if(ax){return ax}au=w.toAbsoluteUrl(au);if(A(au,"?")){var aw=au.indexOf("?");au=au.slice(0,aw)}if(U(au,"matomo.php")){au=f(au,"matomo.php".length) }else{if(U(au,"piwik.php")){au=f(au,"piwik.php".length)}else{if(U(au,".php")){var at=au.lastIndexOf("/");var av=1;au=au.slice(0,at+av)}}}if(U(au,"/js/")){au=f(au,"js/".length)}return au}function R(az){var aB="Matomo_Overlay";var au=new RegExp("index\\.php\\?module=Overlay&action=startOverlaySession&idSite=([0-9]+)&period=([^&]+)&date=([^&]+)(&segment=[^&]*)?");var av=au.exec(J.referrer);if(av){var ax=av[1];if(ax!==String(az)){return false}var ay=av[2],at=av[3],aw=av[4];if(!aw){aw=""}else{if(aw.indexOf("&segment=")===0){aw=aw.substr("&segment=".length)}}W.name=aB+"###"+ay+"###"+at+"###"+aw}var aA=W.name.split("###");return aA.length===4&&aA[0]===aB}function ad(au,az,av){var ay=W.name.split("###"),ax=ay[1],at=ay[2],aw=ay[3],aA=aa(au,az);o(aA+"plugins/Overlay/client/client.js?v=1",function(){Matomo_Overlay_Client.initialize(aA,av,ax,at,aw)})}function v(){var av;try{av=W.frameElement}catch(au){return true}if(M(av)){return(av&&String(av.nodeName).toLowerCase()==="iframe")?true:false}try{return W.self!==W.top }catch(at){return true}}function T(co,ci){var bR=this,bk="mtm_consent",cT="mtm_cookie_consent",c2="mtm_consent_removed",cd=ae(J.domain,W.location.href,N()),da=O(cd[0]),bW=p(cd[1]),bw=p(cd[2]),c8=false,cs="GET",dt=cs,aM="application/x-www-form-urlencoded; charset=UTF-8",cL=aM,aI=co||"",bQ="",dh="",cy="",cf=ci||"",bH="",bX="",bb,bq="",dp=["7z","aac","apk","arc","arj","asf","asx","avi","azw3","bin","csv","deb","dmg","doc","docx","epub","exe","flv","gif","gz","gzip","hqx","ibooks","jar","jpg","jpeg","js","mobi","mp2","mp3","mp4","mpg","mpeg","mov","movie","msi","msp","odb","odf","odg","ods","odt","ogg","ogv","pdf","phps","png","ppt","pptx","qt","qtm","ra","ram","rar","rpm","rtf","sea","sit","tar","tbz","tbz2","bz","bz2","tgz","torrent","txt","wav","wma","wmv","wpd","xls","xlsx","xml","z","zip"],aC=[da],bI=[],cM=[".paypal.com"],ct=[],bU=[],bf=[],bS=500,dd=true,cZ,bc,b0,bY,at,cC=["pk_campaign","mtm_campaign","piwik_campaign","matomo_campaign","utm_campaign","utm_source","utm_medium"],bP=["pk_kwd","mtm_kwd","piwik_kwd","matomo_kwd","utm_term"],br="_pk_",az="pk_vid",a6=180,df,by,b1=false,aN="Lax",bt=false,c6,bl,bE,c0=33955200000,cz=1800000,dn=15768000000,a9=true,bN=false,bo=false,bZ=false,aV=false,cl,b5={},cx={},bv={},bC=200,cH={},di={},dq={},aZ={},cj=[],bu=false,ck=[],cp=false,cR=false,au=false,dr=false,c3=false,aS=false,bj=v(),cN=null,dg=null,aW,bK,cg=aq,bx,aQ,bJ=false,cE=0,bD=["id","ses","cvar","ref"],cQ=false,bL=null,c1=[],cG=[],aB=X++,aA=false,de=true; -try{bq=J.title}catch(cO){bq=""}function aH(dE){if(bt&&dE!==c2){return 0}var dC=new RegExp("(^|;)[ ]*"+dE+"=([^;]*)"),dD=dC.exec(J.cookie);return dD?V(dD[2]):0}bL=!aH(c2);function dx(dG,dH,dK,dJ,dE,dF,dI){if(bt&&dG!==c2){return}var dD;if(dK){dD=new Date();dD.setTime(dD.getTime()+dK)}if(!dI){dI="Lax"}J.cookie=dG+"="+t(dH)+(dK?";expires="+dD.toGMTString():"")+";path="+(dJ||"/")+(dE?";domain="+dE:"")+(dF?";secure":"")+";SameSite="+dI;if((!dK||dK>=0)&&aH(dG)!==String(dH)){var dC="There was an error setting cookie `"+dG+"`. Please check domain and path.";ao(dC)}}function cb(dC){var dE,dD;dC=j(dC,az);dC=j(dC,"ignore_referrer");dC=j(dC,"ignore_referer");for(dD=0;dD<ct.length;dD++){dC=j(dC,ct[dD])}if(bY){dE=new RegExp("#.*");return dC.replace(dE,"")}return dC}function b4(dE,dC){var dF=s(dC),dD;if(dF){return dC}if(dC.slice(0,1)==="/"){return s(dE)+"://"+d(dE)+dC}dE=cb(dE);dD=dE.indexOf("?");if(dD>=0){dE=dE.slice(0,dD)}dD=dE.lastIndexOf("/");if(dD!==dE.length-1){dE=dE.slice(0,dD+1)}return dE+dC}function cX(dE,dC){var dD; -dE=String(dE).toLowerCase();dC=String(dC).toLowerCase();if(dE===dC){return true}if(dC.slice(0,1)==="."){if(dE===dC.slice(1)){return true}dD=dE.length-dC.length;if((dD>0)&&(dE.slice(dD)===dC)){return true}}return false}function cw(dC){var dD=document.createElement("a");if(dC.indexOf("//")!==0&&dC.indexOf("http")!==0){if(dC.indexOf("*")===0){dC=dC.substr(1)}if(dC.indexOf(".")===0){dC=dC.substr(1)}dC="http://"+dC}dD.href=w.toAbsoluteUrl(dC);if(dD.pathname){return dD.pathname}return""}function ba(dD,dC){if(!an(dC,"/")){dC="/"+dC}if(!an(dD,"/")){dD="/"+dD}var dE=(dC==="/"||dC==="/*");if(dE){return true}if(dD===dC){return true}dC=String(dC).toLowerCase();dD=String(dD).toLowerCase();if(U(dC,"*")){dC=dC.slice(0,-1);dE=(!dC||dC==="/");if(dE){return true}if(dD===dC){return true}return dD.indexOf(dC)===0}if(!U(dD,"/")){dD+="/"}if(!U(dC,"/")){dC+="/"}return dD.indexOf(dC)===0}function aw(dG,dI){var dD,dC,dE,dF,dH;for(dD=0;dD<aC.length;dD++){dF=O(aC[dD]);dH=cw(aC[dD]);if(cX(dG,dF)&&ba(dI,dH)){return true -}}return false}function a2(dF){var dD,dC,dE;for(dD=0;dD<aC.length;dD++){dC=O(aC[dD].toLowerCase());if(dF===dC){return true}if(dC.slice(0,1)==="."){if(dF===dC.slice(1)){return true}dE=dF.length-dC.length;if((dE>0)&&(dF.slice(dE)===dC)){return true}}}return false}function cD(dC){var dD,dF,dH,dE,dG;if(!dC.length||!cM.length){return false}dF=d(dC);dH=cw(dC);if(dF.indexOf("www.")===0){dF=dF.substr(4)}for(dD=0;dD<cM.length;dD++){dE=O(cM[dD]);dG=cw(cM[dD]);if(dE.indexOf("www.")===0){dE=dE.substr(4)}if(cX(dF,dE)&&ba(dH,dG)){return true}}return false}function cA(dC,dE){dC=dC.replace("send_image=0","send_image=1");var dD=new Image(1,1);dD.onload=function(){H=0;if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:true})}};dD.onerror=function(){if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:false})}};dD.src=aI+(aI.indexOf("?")<0?"?":"&")+dC}function cU(dC){if(dt==="POST"){return true}return dC&&(dC.length>2000||dC.indexOf('{"requests"')===0)}function aP(){return"object"===typeof g&&"function"===typeof g.sendBeacon&&"function"===typeof Blob -}function bd(dG,dJ,dI){var dE=aP();if(!dE){return false}var dF={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dK=false;var dD=aI;try{var dC=new Blob([dG],dF);if(dI&&!cU(dG)){dC=new Blob([],dF);dD=dD+(dD.indexOf("?")<0?"?":"&")+dG}dK=g.sendBeacon(dD,dC)}catch(dH){return false}if(dK&&typeof dJ==="function"){dJ({request:dG,trackerUrl:aI,success:true,isSendBeacon:true})}return dK}function dm(dD,dE,dC){if(!M(dC)||null===dC){dC=true}if(m&&bd(dD,dE,dC)){return}setTimeout(function(){if(m&&bd(dD,dE,dC)){return}var dH;try{var dG=W.XMLHttpRequest?new W.XMLHttpRequest():W.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;dG.open("POST",aI,true);dG.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dI=m&&bd(dD,dE,dC);if(!dI&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dE==="function")){dE({request:dD,trackerUrl:aI,success:true,xhr:this})}}}; -dG.setRequestHeader("Content-Type",cL);dG.withCredentials=true;dG.send(dD)}catch(dF){dH=m&&bd(dD,dE,dC);if(!dH&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false})}}}},50)}function cq(dD){var dC=new Date();var dE=dC.getTime()+dD;if(!r||dE>r){r=dE}}function bh(){bj=true;cN=new Date().getTime()}function dw(){var dC=new Date().getTime();return !cN||(dC-cN)>bc}function aD(){if(dw()){b0()}}function a1(){if(J.visibilityState==="hidden"&&dw()){b0()}else{if(J.visibilityState==="visible"){cN=new Date().getTime()}}}function dz(){if(aS||!bc){return}aS=true;ar(W,"focus",bh);ar(W,"blur",aD);ar(W,"visibilitychange",a1);af++;u.addPlugin("HeartBeat"+af,{unload:function(){if(aS&&dw()){b0()}}})}function cS(dG){var dD=new Date();var dC=dD.getTime();dg=dC;if(cR&&dC<cR){var dE=cR-dC;setTimeout(dG,dE);cq(dE+50);cR+=50;return}if(cR===false){var dF=800;cR=dC+dF}dG()}function aT(){if(aH(c2)){bL=false}else{if(aH(bk)){bL=true}}}function bT(dE){if(!aZ){return dE}var dD,dC="&uadata="+t(W.JSON.stringify(aZ)); +if(/^https?:\/\/([a-z0-9\.\-]+\.)?paypal\.com(\/|$)/.test(bw)){bw=""}try{bq=J.title}catch(cO){bq=""}function aH(dE){if(bt&&dE!==c2){return 0}var dC=new RegExp("(^|;)[ ]*"+dE+"=([^;]*)"),dD=dC.exec(J.cookie);return dD?V(dD[2]):0}bL=!aH(c2);function dx(dG,dH,dK,dJ,dE,dF,dI){if(bt&&dG!==c2){return}var dD;if(dK){dD=new Date();dD.setTime(dD.getTime()+dK)}if(!dI){dI="Lax"}J.cookie=dG+"="+t(dH)+(dK?";expires="+dD.toGMTString():"")+";path="+(dJ||"/")+(dE?";domain="+dE:"")+(dF?";secure":"")+";SameSite="+dI;if((!dK||dK>=0)&&aH(dG)!==String(dH)){var dC="There was an error setting cookie `"+dG+"`. Please check domain and path.";ao(dC)}}function cb(dC){var dE,dD;dC=j(dC,az);dC=j(dC,"ignore_referrer");dC=j(dC,"ignore_referer");for(dD=0;dD<ct.length;dD++){dC=j(dC,ct[dD])}if(bY){dE=new RegExp("#.*");return dC.replace(dE,"")}return dC}function b4(dE,dC){var dF=s(dC),dD;if(dF){return dC}if(dC.slice(0,1)==="/"){return s(dE)+"://"+d(dE)+dC}dE=cb(dE);dD=dE.indexOf("?");if(dD>=0){dE=dE.slice(0,dD)}dD=dE.lastIndexOf("/"); +if(dD!==dE.length-1){dE=dE.slice(0,dD+1)}return dE+dC}function cX(dE,dC){var dD;dE=String(dE).toLowerCase();dC=String(dC).toLowerCase();if(dE===dC){return true}if(dC.slice(0,1)==="."){if(dE===dC.slice(1)){return true}dD=dE.length-dC.length;if((dD>0)&&(dE.slice(dD)===dC)){return true}}return false}function cw(dC){var dD=document.createElement("a");if(dC.indexOf("//")!==0&&dC.indexOf("http")!==0){if(dC.indexOf("*")===0){dC=dC.substr(1)}if(dC.indexOf(".")===0){dC=dC.substr(1)}dC="http://"+dC}dD.href=w.toAbsoluteUrl(dC);if(dD.pathname){return dD.pathname}return""}function ba(dD,dC){if(!an(dC,"/")){dC="/"+dC}if(!an(dD,"/")){dD="/"+dD}var dE=(dC==="/"||dC==="/*");if(dE){return true}if(dD===dC){return true}dC=String(dC).toLowerCase();dD=String(dD).toLowerCase();if(U(dC,"*")){dC=dC.slice(0,-1);dE=(!dC||dC==="/");if(dE){return true}if(dD===dC){return true}return dD.indexOf(dC)===0}if(!U(dD,"/")){dD+="/"}if(!U(dC,"/")){dC+="/"}return dD.indexOf(dC)===0}function aw(dG,dI){var dD,dC,dE,dF,dH;for(dD=0; +dD<aC.length;dD++){dF=O(aC[dD]);dH=cw(aC[dD]);if(cX(dG,dF)&&ba(dI,dH)){return true}}return false}function a2(dF){var dD,dC,dE;for(dD=0;dD<aC.length;dD++){dC=O(aC[dD].toLowerCase());if(dF===dC){return true}if(dC.slice(0,1)==="."){if(dF===dC.slice(1)){return true}dE=dF.length-dC.length;if((dE>0)&&(dF.slice(dE)===dC)){return true}}}return false}function cD(dC){var dD,dF,dH,dE,dG;if(!dC.length||!cM.length){return false}dF=d(dC);dH=cw(dC);if(dF.indexOf("www.")===0){dF=dF.substr(4)}for(dD=0;dD<cM.length;dD++){dE=O(cM[dD]);dG=cw(cM[dD]);if(dE.indexOf("www.")===0){dE=dE.substr(4)}if(cX(dF,dE)&&ba(dH,dG)){return true}}return false}function cA(dC,dE){dC=dC.replace("send_image=0","send_image=1");var dD=new Image(1,1);dD.onload=function(){H=0;if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:true})}};dD.onerror=function(){if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:false})}};dD.src=aI+(aI.indexOf("?")<0?"?":"&")+dC}function cU(dC){if(dt==="POST"){return true}return dC&&(dC.length>2000||dC.indexOf('{"requests"')===0) +}function aP(){return"object"===typeof g&&"function"===typeof g.sendBeacon&&"function"===typeof Blob}function bd(dG,dJ,dI){var dE=aP();if(!dE){return false}var dF={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dK=false;var dD=aI;try{var dC=new Blob([dG],dF);if(dI&&!cU(dG)){dC=new Blob([],dF);dD=dD+(dD.indexOf("?")<0?"?":"&")+dG}dK=g.sendBeacon(dD,dC)}catch(dH){return false}if(dK&&typeof dJ==="function"){dJ({request:dG,trackerUrl:aI,success:true,isSendBeacon:true})}return dK}function dm(dD,dE,dC){if(!M(dC)||null===dC){dC=true}if(m&&bd(dD,dE,dC)){return}setTimeout(function(){if(m&&bd(dD,dE,dC)){return}var dH;try{var dG=W.XMLHttpRequest?new W.XMLHttpRequest():W.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;dG.open("POST",aI,true);dG.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dI=m&&bd(dD,dE,dC);if(!dI&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dE==="function")){dE({request:dD,trackerUrl:aI,success:true,xhr:this}) +}}};dG.setRequestHeader("Content-Type",cL);dG.withCredentials=true;dG.send(dD)}catch(dF){dH=m&&bd(dD,dE,dC);if(!dH&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false})}}}},50)}function cq(dD){var dC=new Date();var dE=dC.getTime()+dD;if(!r||dE>r){r=dE}}function bh(){bj=true;cN=new Date().getTime()}function dw(){var dC=new Date().getTime();return !cN||(dC-cN)>bc}function aD(){if(dw()){b0()}}function a1(){if(J.visibilityState==="hidden"&&dw()){b0()}else{if(J.visibilityState==="visible"){cN=new Date().getTime()}}}function dz(){if(aS||!bc){return}aS=true;ar(W,"focus",bh);ar(W,"blur",aD);ar(W,"visibilitychange",a1);af++;u.addPlugin("HeartBeat"+af,{unload:function(){if(aS&&dw()){b0()}}})}function cS(dG){var dD=new Date();var dC=dD.getTime();dg=dC;if(cR&&dC<cR){var dE=cR-dC;setTimeout(dG,dE);cq(dE+50);cR+=50;return}if(cR===false){var dF=800;cR=dC+dF}dG()}function aT(){if(aH(c2)){bL=false}else{if(aH(bk)){bL=true}}}function bT(dE){if(!aZ){return dE}var dD,dC="&uadata="+t(W.JSON.stringify(aZ)); if(dE instanceof Array){for(dD=0;dD<dE.length;dD++){dE[dD]+=dC}}else{dE+=dC}return dE}function cB(dC){if(!de||!M(g.userAgentData)||!C(g.userAgentData.getHighEntropyValues)){dC();return}aZ={brands:g.userAgentData.brands,platform:g.userAgentData.platform};g.userAgentData.getHighEntropyValues(["brands","model","platform","platformVersion","uaFullVersion","fullVersionList"]).then(function(dE){var dD;if(dE.fullVersionList){delete dE.brands;delete dE.uaFullVersion}aZ=dE;dC()},function(dD){dC()})}function bO(dD,dC,dE){if(!bu){cj.push(dD);return}aT();if(!bL){c1.push(dD);return}aA=true;if(!c6&&dD){if(cQ&&bL){dD+="&consent=1"}dD=bT(dD);cS(function(){if(dd&&bd(dD,dE,true)){cq(100);return}if(cU(dD)){dm(dD,dE)}else{cA(dD,dE)}cq(dC)})}if(!aS){dz()}}function cv(dC){if(c6){return false}return(dC&&dC.length)}function dl(dC,dG){if(!dG||dG>=dC.length){return[dC]}var dD=0;var dE=dC.length;var dF=[];for(dD;dD<dE;dD+=dG){dF.push(dC.slice(dD,dD+dG))}return dF}function dy(dD,dC){if(!cv(dD)){return}if(!bu){cj.push(dD); return}if(!bL){c1.push(dD);return}aA=true;cS(function(){var dG=dl(dD,50);var dE=0,dF;for(dE;dE<dG.length;dE++){dF='{"requests":["?'+bT(dG[dE]).join('","?')+'"],"send_image":0}';if(dd&&bd(dF,null,false)){cq(100)}else{dm(dF,null,false)}}cq(dC)})}function aY(dC){return br+dC+"."+cf+"."+bx}function b8(dE,dD,dC){dx(dE,"",-129600000,dD,dC)}function ce(){if(bt){return"0"}if(!M(W.showModalDialog)&&M(g.cookieEnabled)){return g.cookieEnabled?"1":"0"}var dC=br+"testcookie";dx(dC,"1",undefined,by,df,b1,aN);var dD=aH(dC)==="1"?"1":"0";b8(dC);return dD}function bp(){bx=cg((df||da)+(by||"/")).slice(0,4)}function cY(){cB(function(){var dI,dH;bu=true;for(dI=0;dI<cj.length;dI++){dH=typeof cj[dI];if(dH==="string"){bO(cj[dI],bS)}else{if(dH==="object"){dy(cj[dI],bS)}}}cj=[]});if(!de){return{}}if(M(dq.res)){return dq}var dD,dF,dG={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",fla:"application/x-shockwave-flash",java:"application/x-java-vm",ag:"application/x-silverlight"}; if(!((new RegExp("MSIE")).test(g.userAgent))){if(g.mimeTypes&&g.mimeTypes.length){for(dD in dG){if(Object.prototype.hasOwnProperty.call(dG,dD)){dF=g.mimeTypes[dG[dD]];dq[dD]=(dF&&dF.enabledPlugin)?"1":"0"}}}if(!((new RegExp("Edge[ /](\\d+[\\.\\d]+)")).test(g.userAgent))&&typeof navigator.javaEnabled!=="unknown"&&M(g.javaEnabled)&&g.javaEnabled()){dq.java="1"}if(!M(W.showModalDialog)&&M(g.cookieEnabled)){dq.cookie=g.cookieEnabled?"1":"0"}else{dq.cookie=ce()}}var dE=parseInt(ab.width,10);var dC=parseInt(ab.height,10);dq.res=parseInt(dE,10)+"x"+parseInt(dC,10);return dq}function b6(){var dD=aY("cvar"),dC=aH(dD);if(dC&&dC.length){dC=W.JSON.parse(dC);if(Z(dC)){return dC}}return{}}function cV(){if(aV===false){aV=b6()}}function c7(){var dC=cY();return cg((g.userAgent||"")+(g.platform||"")+W.JSON.stringify(dC)+(new Date()).getTime()+Math.random()).slice(0,16)}function aF(){var dC=cY();return cg((g.userAgent||"")+(g.platform||"")+W.JSON.stringify(dC)).slice(0,6)}function bm(){return Math.floor((new Date()).getTime()/1000) @@ -30,11 +30,11 @@ at=ai.findFirstNodeHavingAttribute(au,this.CONTENT_PIECE_ATTR);if(!at){at=ai.fin }if(0===au.search("^[a-zA-Z]{2,11}:")){return au}if(au.search(/^\//)!==-1){return this.getLocation().origin+au}var at="(.*/)";var av=this.getLocation().origin+this.getLocation().pathname.match(new RegExp(at))[0];return av+au},isUrlToCurrentDomain:function(au){var av=this.toAbsoluteUrl(au);if(!av){return false}var at=this.getLocation().origin;if(at===av){return true}if(0===String(av).indexOf(at)){if(":"===String(av).substr(at.length,1)){return false}return true}return false},setHrefAttribute:function(au,at){if(!au||!at){return}ai.setAnyAttribute(au,"href",at)},shouldIgnoreInteraction:function(at){if(ai.hasNodeAttribute(at,this.CONTENT_IGNOREINTERACTION_ATTR)){return true}if(ai.hasNodeCssClass(at,this.CONTENT_IGNOREINTERACTION_CLASS)){return true}if(ai.hasNodeCssClass(at,this.LEGACY_CONTENT_IGNOREINTERACTION_CLASS)){return true}return false}};function aa(au,ax){if(ax){return ax}au=w.toAbsoluteUrl(au);if(A(au,"?")){var aw=au.indexOf("?");au=au.slice(0,aw)}if(U(au,"matomo.php")){au=f(au,"matomo.php".length) }else{if(U(au,"piwik.php")){au=f(au,"piwik.php".length)}else{if(U(au,".php")){var at=au.lastIndexOf("/");var av=1;au=au.slice(0,at+av)}}}if(U(au,"/js/")){au=f(au,"js/".length)}return au}function R(az){var aB="Matomo_Overlay";var au=new RegExp("index\\.php\\?module=Overlay&action=startOverlaySession&idSite=([0-9]+)&period=([^&]+)&date=([^&]+)(&segment=[^&]*)?");var av=au.exec(J.referrer);if(av){var ax=av[1];if(ax!==String(az)){return false}var ay=av[2],at=av[3],aw=av[4];if(!aw){aw=""}else{if(aw.indexOf("&segment=")===0){aw=aw.substr("&segment=".length)}}W.name=aB+"###"+ay+"###"+at+"###"+aw}var aA=W.name.split("###");return aA.length===4&&aA[0]===aB}function ad(au,az,av){var ay=W.name.split("###"),ax=ay[1],at=ay[2],aw=ay[3],aA=aa(au,az);o(aA+"plugins/Overlay/client/client.js?v=1",function(){Matomo_Overlay_Client.initialize(aA,av,ax,at,aw)})}function v(){var av;try{av=W.frameElement}catch(au){return true}if(M(av)){return(av&&String(av.nodeName).toLowerCase()==="iframe")?true:false}try{return W.self!==W.top }catch(at){return true}}function T(co,ci){var bR=this,bk="mtm_consent",cT="mtm_cookie_consent",c2="mtm_consent_removed",cd=ae(J.domain,W.location.href,N()),da=O(cd[0]),bW=p(cd[1]),bw=p(cd[2]),c8=false,cs="GET",dt=cs,aM="application/x-www-form-urlencoded; charset=UTF-8",cL=aM,aI=co||"",bQ="",dh="",cy="",cf=ci||"",bH="",bX="",bb,bq="",dp=["7z","aac","apk","arc","arj","asf","asx","avi","azw3","bin","csv","deb","dmg","doc","docx","epub","exe","flv","gif","gz","gzip","hqx","ibooks","jar","jpg","jpeg","js","mobi","mp2","mp3","mp4","mpg","mpeg","mov","movie","msi","msp","odb","odf","odg","ods","odt","ogg","ogv","pdf","phps","png","ppt","pptx","qt","qtm","ra","ram","rar","rpm","rtf","sea","sit","tar","tbz","tbz2","bz","bz2","tgz","torrent","txt","wav","wma","wmv","wpd","xls","xlsx","xml","z","zip"],aC=[da],bI=[],cM=[".paypal.com"],ct=[],bU=[],bf=[],bS=500,dd=true,cZ,bc,b0,bY,at,cC=["pk_campaign","mtm_campaign","piwik_campaign","matomo_campaign","utm_campaign","utm_source","utm_medium"],bP=["pk_kwd","mtm_kwd","piwik_kwd","matomo_kwd","utm_term"],br="_pk_",az="pk_vid",a6=180,df,by,b1=false,aN="Lax",bt=false,c6,bl,bE,c0=33955200000,cz=1800000,dn=15768000000,a9=true,bN=false,bo=false,bZ=false,aV=false,cl,b5={},cx={},bv={},bC=200,cH={},di={},dq={},aZ={},cj=[],bu=false,ck=[],cp=false,cR=false,au=false,dr=false,c3=false,aS=false,bj=v(),cN=null,dg=null,aW,bK,cg=aq,bx,aQ,bJ=false,cE=0,bD=["id","ses","cvar","ref"],cQ=false,bL=null,c1=[],cG=[],aB=X++,aA=false,de=true; -try{bq=J.title}catch(cO){bq=""}function aH(dE){if(bt&&dE!==c2){return 0}var dC=new RegExp("(^|;)[ ]*"+dE+"=([^;]*)"),dD=dC.exec(J.cookie);return dD?V(dD[2]):0}bL=!aH(c2);function dx(dG,dH,dK,dJ,dE,dF,dI){if(bt&&dG!==c2){return}var dD;if(dK){dD=new Date();dD.setTime(dD.getTime()+dK)}if(!dI){dI="Lax"}J.cookie=dG+"="+t(dH)+(dK?";expires="+dD.toGMTString():"")+";path="+(dJ||"/")+(dE?";domain="+dE:"")+(dF?";secure":"")+";SameSite="+dI;if((!dK||dK>=0)&&aH(dG)!==String(dH)){var dC="There was an error setting cookie `"+dG+"`. Please check domain and path.";ao(dC)}}function cb(dC){var dE,dD;dC=j(dC,az);dC=j(dC,"ignore_referrer");dC=j(dC,"ignore_referer");for(dD=0;dD<ct.length;dD++){dC=j(dC,ct[dD])}if(bY){dE=new RegExp("#.*");return dC.replace(dE,"")}return dC}function b4(dE,dC){var dF=s(dC),dD;if(dF){return dC}if(dC.slice(0,1)==="/"){return s(dE)+"://"+d(dE)+dC}dE=cb(dE);dD=dE.indexOf("?");if(dD>=0){dE=dE.slice(0,dD)}dD=dE.lastIndexOf("/");if(dD!==dE.length-1){dE=dE.slice(0,dD+1)}return dE+dC}function cX(dE,dC){var dD; -dE=String(dE).toLowerCase();dC=String(dC).toLowerCase();if(dE===dC){return true}if(dC.slice(0,1)==="."){if(dE===dC.slice(1)){return true}dD=dE.length-dC.length;if((dD>0)&&(dE.slice(dD)===dC)){return true}}return false}function cw(dC){var dD=document.createElement("a");if(dC.indexOf("//")!==0&&dC.indexOf("http")!==0){if(dC.indexOf("*")===0){dC=dC.substr(1)}if(dC.indexOf(".")===0){dC=dC.substr(1)}dC="http://"+dC}dD.href=w.toAbsoluteUrl(dC);if(dD.pathname){return dD.pathname}return""}function ba(dD,dC){if(!an(dC,"/")){dC="/"+dC}if(!an(dD,"/")){dD="/"+dD}var dE=(dC==="/"||dC==="/*");if(dE){return true}if(dD===dC){return true}dC=String(dC).toLowerCase();dD=String(dD).toLowerCase();if(U(dC,"*")){dC=dC.slice(0,-1);dE=(!dC||dC==="/");if(dE){return true}if(dD===dC){return true}return dD.indexOf(dC)===0}if(!U(dD,"/")){dD+="/"}if(!U(dC,"/")){dC+="/"}return dD.indexOf(dC)===0}function aw(dG,dI){var dD,dC,dE,dF,dH;for(dD=0;dD<aC.length;dD++){dF=O(aC[dD]);dH=cw(aC[dD]);if(cX(dG,dF)&&ba(dI,dH)){return true -}}return false}function a2(dF){var dD,dC,dE;for(dD=0;dD<aC.length;dD++){dC=O(aC[dD].toLowerCase());if(dF===dC){return true}if(dC.slice(0,1)==="."){if(dF===dC.slice(1)){return true}dE=dF.length-dC.length;if((dE>0)&&(dF.slice(dE)===dC)){return true}}}return false}function cD(dC){var dD,dF,dH,dE,dG;if(!dC.length||!cM.length){return false}dF=d(dC);dH=cw(dC);if(dF.indexOf("www.")===0){dF=dF.substr(4)}for(dD=0;dD<cM.length;dD++){dE=O(cM[dD]);dG=cw(cM[dD]);if(dE.indexOf("www.")===0){dE=dE.substr(4)}if(cX(dF,dE)&&ba(dH,dG)){return true}}return false}function cA(dC,dE){dC=dC.replace("send_image=0","send_image=1");var dD=new Image(1,1);dD.onload=function(){H=0;if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:true})}};dD.onerror=function(){if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:false})}};dD.src=aI+(aI.indexOf("?")<0?"?":"&")+dC}function cU(dC){if(dt==="POST"){return true}return dC&&(dC.length>2000||dC.indexOf('{"requests"')===0)}function aP(){return"object"===typeof g&&"function"===typeof g.sendBeacon&&"function"===typeof Blob -}function bd(dG,dJ,dI){var dE=aP();if(!dE){return false}var dF={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dK=false;var dD=aI;try{var dC=new Blob([dG],dF);if(dI&&!cU(dG)){dC=new Blob([],dF);dD=dD+(dD.indexOf("?")<0?"?":"&")+dG}dK=g.sendBeacon(dD,dC)}catch(dH){return false}if(dK&&typeof dJ==="function"){dJ({request:dG,trackerUrl:aI,success:true,isSendBeacon:true})}return dK}function dm(dD,dE,dC){if(!M(dC)||null===dC){dC=true}if(m&&bd(dD,dE,dC)){return}setTimeout(function(){if(m&&bd(dD,dE,dC)){return}var dH;try{var dG=W.XMLHttpRequest?new W.XMLHttpRequest():W.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;dG.open("POST",aI,true);dG.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dI=m&&bd(dD,dE,dC);if(!dI&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dE==="function")){dE({request:dD,trackerUrl:aI,success:true,xhr:this})}}}; -dG.setRequestHeader("Content-Type",cL);dG.withCredentials=true;dG.send(dD)}catch(dF){dH=m&&bd(dD,dE,dC);if(!dH&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false})}}}},50)}function cq(dD){var dC=new Date();var dE=dC.getTime()+dD;if(!r||dE>r){r=dE}}function bh(){bj=true;cN=new Date().getTime()}function dw(){var dC=new Date().getTime();return !cN||(dC-cN)>bc}function aD(){if(dw()){b0()}}function a1(){if(J.visibilityState==="hidden"&&dw()){b0()}else{if(J.visibilityState==="visible"){cN=new Date().getTime()}}}function dz(){if(aS||!bc){return}aS=true;ar(W,"focus",bh);ar(W,"blur",aD);ar(W,"visibilitychange",a1);af++;u.addPlugin("HeartBeat"+af,{unload:function(){if(aS&&dw()){b0()}}})}function cS(dG){var dD=new Date();var dC=dD.getTime();dg=dC;if(cR&&dC<cR){var dE=cR-dC;setTimeout(dG,dE);cq(dE+50);cR+=50;return}if(cR===false){var dF=800;cR=dC+dF}dG()}function aT(){if(aH(c2)){bL=false}else{if(aH(bk)){bL=true}}}function bT(dE){if(!aZ){return dE}var dD,dC="&uadata="+t(W.JSON.stringify(aZ)); +if(/^https?:\/\/([a-z0-9\.\-]+\.)?paypal\.com(\/|$)/.test(bw)){bw=""}try{bq=J.title}catch(cO){bq=""}function aH(dE){if(bt&&dE!==c2){return 0}var dC=new RegExp("(^|;)[ ]*"+dE+"=([^;]*)"),dD=dC.exec(J.cookie);return dD?V(dD[2]):0}bL=!aH(c2);function dx(dG,dH,dK,dJ,dE,dF,dI){if(bt&&dG!==c2){return}var dD;if(dK){dD=new Date();dD.setTime(dD.getTime()+dK)}if(!dI){dI="Lax"}J.cookie=dG+"="+t(dH)+(dK?";expires="+dD.toGMTString():"")+";path="+(dJ||"/")+(dE?";domain="+dE:"")+(dF?";secure":"")+";SameSite="+dI;if((!dK||dK>=0)&&aH(dG)!==String(dH)){var dC="There was an error setting cookie `"+dG+"`. Please check domain and path.";ao(dC)}}function cb(dC){var dE,dD;dC=j(dC,az);dC=j(dC,"ignore_referrer");dC=j(dC,"ignore_referer");for(dD=0;dD<ct.length;dD++){dC=j(dC,ct[dD])}if(bY){dE=new RegExp("#.*");return dC.replace(dE,"")}return dC}function b4(dE,dC){var dF=s(dC),dD;if(dF){return dC}if(dC.slice(0,1)==="/"){return s(dE)+"://"+d(dE)+dC}dE=cb(dE);dD=dE.indexOf("?");if(dD>=0){dE=dE.slice(0,dD)}dD=dE.lastIndexOf("/"); +if(dD!==dE.length-1){dE=dE.slice(0,dD+1)}return dE+dC}function cX(dE,dC){var dD;dE=String(dE).toLowerCase();dC=String(dC).toLowerCase();if(dE===dC){return true}if(dC.slice(0,1)==="."){if(dE===dC.slice(1)){return true}dD=dE.length-dC.length;if((dD>0)&&(dE.slice(dD)===dC)){return true}}return false}function cw(dC){var dD=document.createElement("a");if(dC.indexOf("//")!==0&&dC.indexOf("http")!==0){if(dC.indexOf("*")===0){dC=dC.substr(1)}if(dC.indexOf(".")===0){dC=dC.substr(1)}dC="http://"+dC}dD.href=w.toAbsoluteUrl(dC);if(dD.pathname){return dD.pathname}return""}function ba(dD,dC){if(!an(dC,"/")){dC="/"+dC}if(!an(dD,"/")){dD="/"+dD}var dE=(dC==="/"||dC==="/*");if(dE){return true}if(dD===dC){return true}dC=String(dC).toLowerCase();dD=String(dD).toLowerCase();if(U(dC,"*")){dC=dC.slice(0,-1);dE=(!dC||dC==="/");if(dE){return true}if(dD===dC){return true}return dD.indexOf(dC)===0}if(!U(dD,"/")){dD+="/"}if(!U(dC,"/")){dC+="/"}return dD.indexOf(dC)===0}function aw(dG,dI){var dD,dC,dE,dF,dH;for(dD=0; +dD<aC.length;dD++){dF=O(aC[dD]);dH=cw(aC[dD]);if(cX(dG,dF)&&ba(dI,dH)){return true}}return false}function a2(dF){var dD,dC,dE;for(dD=0;dD<aC.length;dD++){dC=O(aC[dD].toLowerCase());if(dF===dC){return true}if(dC.slice(0,1)==="."){if(dF===dC.slice(1)){return true}dE=dF.length-dC.length;if((dE>0)&&(dF.slice(dE)===dC)){return true}}}return false}function cD(dC){var dD,dF,dH,dE,dG;if(!dC.length||!cM.length){return false}dF=d(dC);dH=cw(dC);if(dF.indexOf("www.")===0){dF=dF.substr(4)}for(dD=0;dD<cM.length;dD++){dE=O(cM[dD]);dG=cw(cM[dD]);if(dE.indexOf("www.")===0){dE=dE.substr(4)}if(cX(dF,dE)&&ba(dH,dG)){return true}}return false}function cA(dC,dE){dC=dC.replace("send_image=0","send_image=1");var dD=new Image(1,1);dD.onload=function(){H=0;if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:true})}};dD.onerror=function(){if(typeof dE==="function"){dE({request:dC,trackerUrl:aI,success:false})}};dD.src=aI+(aI.indexOf("?")<0?"?":"&")+dC}function cU(dC){if(dt==="POST"){return true}return dC&&(dC.length>2000||dC.indexOf('{"requests"')===0) +}function aP(){return"object"===typeof g&&"function"===typeof g.sendBeacon&&"function"===typeof Blob}function bd(dG,dJ,dI){var dE=aP();if(!dE){return false}var dF={type:"application/x-www-form-urlencoded; charset=UTF-8"};var dK=false;var dD=aI;try{var dC=new Blob([dG],dF);if(dI&&!cU(dG)){dC=new Blob([],dF);dD=dD+(dD.indexOf("?")<0?"?":"&")+dG}dK=g.sendBeacon(dD,dC)}catch(dH){return false}if(dK&&typeof dJ==="function"){dJ({request:dG,trackerUrl:aI,success:true,isSendBeacon:true})}return dK}function dm(dD,dE,dC){if(!M(dC)||null===dC){dC=true}if(m&&bd(dD,dE,dC)){return}setTimeout(function(){if(m&&bd(dD,dE,dC)){return}var dH;try{var dG=W.XMLHttpRequest?new W.XMLHttpRequest():W.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;dG.open("POST",aI,true);dG.onreadystatechange=function(){if(this.readyState===4&&!(this.status>=200&&this.status<300)){var dI=m&&bd(dD,dE,dC);if(!dI&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false,xhr:this})}}}else{if(this.readyState===4&&(typeof dE==="function")){dE({request:dD,trackerUrl:aI,success:true,xhr:this}) +}}};dG.setRequestHeader("Content-Type",cL);dG.withCredentials=true;dG.send(dD)}catch(dF){dH=m&&bd(dD,dE,dC);if(!dH&&dC){cA(dD,dE)}else{if(typeof dE==="function"){dE({request:dD,trackerUrl:aI,success:false})}}}},50)}function cq(dD){var dC=new Date();var dE=dC.getTime()+dD;if(!r||dE>r){r=dE}}function bh(){bj=true;cN=new Date().getTime()}function dw(){var dC=new Date().getTime();return !cN||(dC-cN)>bc}function aD(){if(dw()){b0()}}function a1(){if(J.visibilityState==="hidden"&&dw()){b0()}else{if(J.visibilityState==="visible"){cN=new Date().getTime()}}}function dz(){if(aS||!bc){return}aS=true;ar(W,"focus",bh);ar(W,"blur",aD);ar(W,"visibilitychange",a1);af++;u.addPlugin("HeartBeat"+af,{unload:function(){if(aS&&dw()){b0()}}})}function cS(dG){var dD=new Date();var dC=dD.getTime();dg=dC;if(cR&&dC<cR){var dE=cR-dC;setTimeout(dG,dE);cq(dE+50);cR+=50;return}if(cR===false){var dF=800;cR=dC+dF}dG()}function aT(){if(aH(c2)){bL=false}else{if(aH(bk)){bL=true}}}function bT(dE){if(!aZ){return dE}var dD,dC="&uadata="+t(W.JSON.stringify(aZ)); if(dE instanceof Array){for(dD=0;dD<dE.length;dD++){dE[dD]+=dC}}else{dE+=dC}return dE}function cB(dC){if(!de||!M(g.userAgentData)||!C(g.userAgentData.getHighEntropyValues)){dC();return}aZ={brands:g.userAgentData.brands,platform:g.userAgentData.platform};g.userAgentData.getHighEntropyValues(["brands","model","platform","platformVersion","uaFullVersion","fullVersionList"]).then(function(dE){var dD;if(dE.fullVersionList){delete dE.brands;delete dE.uaFullVersion}aZ=dE;dC()},function(dD){dC()})}function bO(dD,dC,dE){if(!bu){cj.push(dD);return}aT();if(!bL){c1.push(dD);return}aA=true;if(!c6&&dD){if(cQ&&bL){dD+="&consent=1"}dD=bT(dD);cS(function(){if(dd&&bd(dD,dE,true)){cq(100);return}if(cU(dD)){dm(dD,dE)}else{cA(dD,dE)}cq(dC)})}if(!aS){dz()}}function cv(dC){if(c6){return false}return(dC&&dC.length)}function dl(dC,dG){if(!dG||dG>=dC.length){return[dC]}var dD=0;var dE=dC.length;var dF=[];for(dD;dD<dE;dD+=dG){dF.push(dC.slice(dD,dD+dG))}return dF}function dy(dD,dC){if(!cv(dD)){return}if(!bu){cj.push(dD); return}if(!bL){c1.push(dD);return}aA=true;cS(function(){var dG=dl(dD,50);var dE=0,dF;for(dE;dE<dG.length;dE++){dF='{"requests":["?'+bT(dG[dE]).join('","?')+'"],"send_image":0}';if(dd&&bd(dF,null,false)){cq(100)}else{dm(dF,null,false)}}cq(dC)})}function aY(dC){return br+dC+"."+cf+"."+bx}function b8(dE,dD,dC){dx(dE,"",-129600000,dD,dC)}function ce(){if(bt){return"0"}if(!M(W.showModalDialog)&&M(g.cookieEnabled)){return g.cookieEnabled?"1":"0"}var dC=br+"testcookie";dx(dC,"1",undefined,by,df,b1,aN);var dD=aH(dC)==="1"?"1":"0";b8(dC);return dD}function bp(){bx=cg((df||da)+(by||"/")).slice(0,4)}function cY(){cB(function(){var dI,dH;bu=true;for(dI=0;dI<cj.length;dI++){dH=typeof cj[dI];if(dH==="string"){bO(cj[dI],bS)}else{if(dH==="object"){dy(cj[dI],bS)}}}cj=[]});if(!de){return{}}if(M(dq.res)){return dq}var dD,dF,dG={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",fla:"application/x-shockwave-flash",java:"application/x-java-vm",ag:"application/x-silverlight"}; if(!((new RegExp("MSIE")).test(g.userAgent))){if(g.mimeTypes&&g.mimeTypes.length){for(dD in dG){if(Object.prototype.hasOwnProperty.call(dG,dD)){dF=g.mimeTypes[dG[dD]];dq[dD]=(dF&&dF.enabledPlugin)?"1":"0"}}}if(!((new RegExp("Edge[ /](\\d+[\\.\\d]+)")).test(g.userAgent))&&typeof navigator.javaEnabled!=="unknown"&&M(g.javaEnabled)&&g.javaEnabled()){dq.java="1"}if(!M(W.showModalDialog)&&M(g.cookieEnabled)){dq.cookie=g.cookieEnabled?"1":"0"}else{dq.cookie=ce()}}var dE=parseInt(ab.width,10);var dC=parseInt(ab.height,10);dq.res=parseInt(dE,10)+"x"+parseInt(dC,10);return dq}function b6(){var dD=aY("cvar"),dC=aH(dD);if(dC&&dC.length){dC=W.JSON.parse(dC);if(Z(dC)){return dC}}return{}}function cV(){if(aV===false){aV=b6()}}function c7(){var dC=cY();return cg((g.userAgent||"")+(g.platform||"")+W.JSON.stringify(dC)+(new Date()).getTime()+Math.random()).slice(0,16)}function aF(){var dC=cY();return cg((g.userAgent||"")+(g.platform||"")+W.JSON.stringify(dC)).slice(0,6)}function bm(){return Math.floor((new Date()).getTime()/1000) diff --git a/plugins/Login/tests/Integration/PasswordResetterTest.php b/plugins/Login/tests/Integration/PasswordResetterTest.php index 2dbb4f24c8..cbac1e1fd0 100644 --- a/plugins/Login/tests/Integration/PasswordResetterTest.php +++ b/plugins/Login/tests/Integration/PasswordResetterTest.php @@ -16,10 +16,10 @@ use Piwik\Auth; use Piwik\Container\StaticContainer; use Piwik\Option; use Piwik\Plugin\Manager; -use Piwik\Plugins\UsersManager\Model; -use Piwik\Tests\Framework\TestCase\IntegrationTestCase; use Piwik\Plugins\Login\PasswordResetter; +use Piwik\Plugins\UsersManager\Model; use Piwik\Tests\Framework\Fixture; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; /** * @group PasswordResetterTest @@ -41,6 +41,7 @@ class PasswordResetterTest extends IntegrationTestCase public function setUp(): void { parent::setUp(); + Fixture::createWebsite('2010-01-01 05:00:00'); $this->passwordResetter = new PasswordResetter(); $this->capturedToken = null; @@ -171,7 +172,7 @@ class PasswordResetterTest extends IntegrationTestCase [ 'userLogin' => 'pendingUser', 'email' => 'pending@user.io', - 'idSite' => 1, + 'initialIdSite' => 1, 'expiryInDays' => 7 ] ); diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php index 0d301929cb..ed3eaf8890 100644 --- a/plugins/UsersManager/API.php +++ b/plugins/UsersManager/API.php @@ -727,8 +727,16 @@ class API extends \Piwik\Plugin\API $password = Common::unsanitizeInputValue($password); UsersManager::checkPassword($password); + + $initialIdSite = $initialIdSite === null ? null : intval($initialIdSite); + if (!Piwik::hasUserSuperUserAccess()) { + if (empty($initialIdSite)) { + throw new \Exception(Piwik::translate("UsersManager_AddUserNoInitialAccessError")); + } + } + $this->userRepository->create( (string) $userLogin, (string) $email, @@ -750,7 +758,7 @@ class API extends \Piwik\Plugin\API /** * @throws Exception */ - public function inviteUser($userLogin, $email, $idSite = null, $expiryInDays = null) + public function inviteUser($userLogin, $email, $initialIdSite = null, $expiryInDays = null) { Piwik::checkUserHasSomeAdminAccess(); UsersManager::dieIfUsersAdminIsDisabled(); @@ -759,9 +767,14 @@ class API extends \Piwik\Plugin\API $expiryInDays = Config\GeneralConfig::getConfigValue('default_invite_user_token_expiry_days'); } - $idSite = $idSite === null ? null : intval($idSite); + if (empty($initialIdSite)) { + throw new \Exception(Piwik::translate("UsersManager_AddUserNoInitialAccessError")); + } else { + // check if the site exists + new Site($initialIdSite); + } - $this->userRepository->inviteUser((string) $userLogin, (string) $email, $idSite, (int) $expiryInDays); + $this->userRepository->inviteUser((string) $userLogin, (string) $email, intval($initialIdSite), (int) $expiryInDays); /** * Triggered after a new user was invited. diff --git a/plugins/UsersManager/Repository/UserRepository.php b/plugins/UsersManager/Repository/UserRepository.php index e806211abc..59f1946813 100644 --- a/plugins/UsersManager/Repository/UserRepository.php +++ b/plugins/UsersManager/Repository/UserRepository.php @@ -7,6 +7,7 @@ use Piwik\Container\StaticContainer; use Piwik\Date; use Piwik\Metrics\Formatter; use Piwik\Piwik; +use Piwik\Plugin; use Piwik\Plugins\CoreAdminHome\Emails\UserCreatedEmail; use Piwik\Plugins\UsersManager\API; use Piwik\Plugins\UsersManager\Emails\UserInviteEmail; @@ -18,8 +19,6 @@ use Piwik\Plugins\UsersManager\Validators\Email; use Piwik\Plugins\UsersManager\Validators\Login; use Piwik\Site; use Piwik\Validators\BaseValidator; -use Piwik\Validators\IdSite; -use Piwik\Plugin; class UserRepository { @@ -60,12 +59,10 @@ class UserRepository string $password = '', bool $isPasswordHashed = false ): void { + + if (!Piwik::hasUserSuperUserAccess()) { - if (empty($initialIdSite)) { - throw new \Exception(Piwik::translate("UsersManager_AddUserNoInitialAccessError")); - } - // check if the site exists - BaseValidator::check('siteId', $initialIdSite, [new IdSite()]); + // check if the user has admin access to the site Piwik::checkUserHasAdminAccess($initialIdSite); } diff --git a/plugins/UsersManager/tests/Integration/APITest.php b/plugins/UsersManager/tests/Integration/APITest.php index 181553fd23..e7bfb60edf 100644 --- a/plugins/UsersManager/tests/Integration/APITest.php +++ b/plugins/UsersManager/tests/Integration/APITest.php @@ -3,14 +3,17 @@ /** * Matomo - free/libre analytics platform * - * @link https://matomo.org + * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ namespace Piwik\Plugins\UsersManager\tests\Integration; +use Piwik\Access\Capability; +use Piwik\Access\Role\Admin; use Piwik\Access\Role\View; use Piwik\Access\Role\Write; +use Piwik\API\Request; use Piwik\Auth\Password; use Piwik\Config; use Piwik\Date; @@ -27,8 +30,6 @@ use Piwik\Plugins\UsersManager\UserUpdater; use Piwik\Tests\Framework\Fixture; use Piwik\Tests\Framework\Mock\FakeAccess; use Piwik\Tests\Framework\TestCase\IntegrationTestCase; -use Piwik\Access\Role\Admin; -use Piwik\Access\Capability; class TestCap1 extends Capability { @@ -57,7 +58,7 @@ class TestCap1 extends Capability public function getIncludedInRoles(): array { return [ - Admin::ID + Admin::ID, ]; } } @@ -89,8 +90,8 @@ class TestCap2 extends Capability public function getIncludedInRoles(): array { return [ - Write::ID, - Admin::ID + Write::ID, + Admin::ID, ]; } } @@ -153,7 +154,7 @@ class APITest extends IntegrationTestCase { parent::setUp(); - $this->api = API::getInstance(); + $this->api = API::getInstance(); $this->model = new Model(); FakeAccess::clearAccess(); @@ -172,10 +173,10 @@ class APITest extends IntegrationTestCase parent::tearDown(); } - public function test_setUserAccess_ShouldTriggerRemoveSiteAccessEvent_IfAccessToAWebsiteIsRemoved() + public function testSetUserAccessShouldTriggerRemoveSiteAccessEventIfAccessToAWebsiteIsRemoved() { $eventTriggered = false; - $self = $this; + $self = $this; Piwik::addAction('UsersManager.removeSiteAccess', function ($login, $idSites) use (&$eventTriggered, $self) { $eventTriggered = true; $self->assertEquals($self->login, $login); @@ -187,7 +188,7 @@ class APITest extends IntegrationTestCase $this->assertTrue($eventTriggered, 'UsersManager.removeSiteAccess event was not triggered'); } - public function test_setUserAccess_ShouldNotTriggerRemoveSiteAccessEvent_IfAccessIsAdded() + public function testSetUserAccessShouldNotTriggerRemoveSiteAccessEventIfAccessIsAdded() { $eventTriggered = false; Piwik::addAction('UsersManager.removeSiteAccess', function () use (&$eventTriggered) { @@ -199,25 +200,25 @@ class APITest extends IntegrationTestCase $this->assertFalse($eventTriggered, 'UsersManager.removeSiteAccess event was triggered but should not'); } - public function test_getAllUsersPreferences_isEmpty_whenNoPreference() + public function testGetAllUsersPreferencesIsEmptyWhenNoPreference() { $preferences = $this->api->getAllUsersPreferences(['preferenceName']); $this->assertEmpty($preferences); } - public function test_getAllUsersPreferences_isEmpty_whenNoPreferenceAndMultipleRequested() + public function testGetAllUsersPreferencesIsEmptyWhenNoPreferenceAndMultipleRequested() { $preferences = $this->api->getAllUsersPreferences(['preferenceName', 'randomDoesNotExist']); $this->assertEmpty($preferences); } - public function test_getUserPreference_ShouldReturnADefaultPreference_IfNoneIsSet() + public function testGetUserPreferenceShouldReturnADefaultPreferenceIfNoneIsSet() { $siteId = $this->api->getUserPreference(API::PREFERENCE_DEFAULT_REPORT, $this->login); $this->assertEquals('1', $siteId); } - public function test_getUserPreference_ShouldReturnASetreference_IfNoneIsSet() + public function testGetUserPreferenceShouldReturnASetreferenceIfNoneIsSet() { $this->api->setUserPreference($this->login, API::PREFERENCE_DEFAULT_REPORT, 5); @@ -225,7 +226,7 @@ class APITest extends IntegrationTestCase $this->assertEquals('5', $siteId); } - public function test_initUserPreferenceWithDefault_ShouldSaveTheDefaultPreference_IfPreferenceIsNotSet() + public function testInitUserPreferenceWithDefaultShouldSaveTheDefaultPreferenceIfPreferenceIsNotSet() { // make sure there is no value saved so it will use default preference $siteId = Option::get($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT)); @@ -238,7 +239,7 @@ class APITest extends IntegrationTestCase $this->assertEquals('1', $siteId); } - public function test_initUserPreferenceWithDefault_ShouldNotSaveTheDefaultPreference_IfPreferenceIsAlreadySet() + public function testInitUserPreferenceWithDefaultShouldNotSaveTheDefaultPreferenceIfPreferenceIsAlreadySet() { // set value so there will already be a default Option::set($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT), '999'); @@ -253,7 +254,7 @@ class APITest extends IntegrationTestCase $this->assertEquals('999', $siteId); } - public function test_getAllUsersPreferences_shouldGetMultiplePreferences() + public function testGetAllUsersPreferencesShouldGetMultiplePreferences() { $user2 = 'userLogin2'; $user3 = 'userLogin3'; @@ -267,24 +268,24 @@ class APITest extends IntegrationTestCase $this->api->setUserPreference($user3, 'RandomNOTREQUESTED', 'RandomNOTREQUESTED'); $expected = [ - $user2 => [ - API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2' - ], - $user3 => [ - API::PREFERENCE_DEFAULT_REPORT => 'valueForUser3', - API::PREFERENCE_DEFAULT_REPORT_DATE => 'otherPreferenceVALUE', - ], + $user2 => [ + API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2', + ], + $user3 => [ + API::PREFERENCE_DEFAULT_REPORT => 'valueForUser3', + API::PREFERENCE_DEFAULT_REPORT_DATE => 'otherPreferenceVALUE', + ], ]; - $result = $this->api->getAllUsersPreferences([ - API::PREFERENCE_DEFAULT_REPORT, - API::PREFERENCE_DEFAULT_REPORT_DATE, - 'randomDoesNotExist' - ]); + $result = $this->api->getAllUsersPreferences([ + API::PREFERENCE_DEFAULT_REPORT, + API::PREFERENCE_DEFAULT_REPORT_DATE, + 'randomDoesNotExist', + ]); $this->assertSame($expected, $result); } - public function test_getAllUsersPreferences_whenLoginContainsUnderscore() + public function testGetAllUsersPreferencesWhenLoginContainsUnderscore() { $user2 = 'user_Login2'; $this->api->addUser($user2, 'password', 'userlogin2@password.de'); @@ -292,16 +293,16 @@ class APITest extends IntegrationTestCase $this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT_DATE, 'RandomNOTREQUESTED'); $expected = [ - $user2 => [ - API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2' - ], + $user2 => [ + API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2', + ], ]; - $result = $this->api->getAllUsersPreferences([API::PREFERENCE_DEFAULT_REPORT, 'randomDoesNotExist']); + $result = $this->api->getAllUsersPreferences([API::PREFERENCE_DEFAULT_REPORT, 'randomDoesNotExist']); $this->assertSame($expected, $result); } - public function test_setUserPreference_throws_whenPreferenceNameContainsUnderscore() + public function testSetUserPreferenceThrowsWhenPreferenceNameContainsUnderscore() { $this->expectException(\Exception::class); @@ -310,20 +311,20 @@ class APITest extends IntegrationTestCase $this->api->setUserPreference($user2, 'ohOH_myPreferenceName', 'valueForUser2'); } - public function test_updateUser() + public function testUpdateUser() { $capturedMails = []; Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) { $capturedMails[] = $mail; }); - $identity = FakeAccess::$identity; + $identity = FakeAccess::$identity; FakeAccess::$identity = $this->login; // ensure password will be checked against this user $this->api->updateUser($this->login, 'newPassword', 'email@example.com', false, $this->password); FakeAccess::$identity = $identity; $model = new Model(); - $user = $model->getUser($this->login); + $user = $model->getUser($this->login); $this->assertSame('email@example.com', $user['email']); @@ -335,21 +336,21 @@ class APITest extends IntegrationTestCase return $mail->getSubject(); }, $capturedMails); $this->assertEquals([ - 'UsersManager_EmailChangeNotificationSubject', // sent twice to old email and new - 'UsersManager_EmailChangeNotificationSubject', - 'UsersManager_PasswordChangeNotificationSubject', - ], $subjects); + 'UsersManager_EmailChangeNotificationSubject', // sent twice to old email and new + 'UsersManager_EmailChangeNotificationSubject', + 'UsersManager_PasswordChangeNotificationSubject', + ], $subjects); } - public function test_updateUser_doesNotSendEmailsIfTurnedOffInConfig() + public function testUpdateUserDoesNotSendEmailsIfTurnedOffInConfig() { Config::getInstance()->General['enable_update_users_email'] = 0; - $capturedMails = []; + $capturedMails = []; Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) { $capturedMails[] = $mail; }); - $identity = FakeAccess::$identity; + $identity = FakeAccess::$identity; FakeAccess::$identity = $this->login; // en $this->api->updateUser($this->login, 'newPassword2', 'email2@example.com', false, $this->password); FakeAccess::$identity = $identity; @@ -361,14 +362,14 @@ class APITest extends IntegrationTestCase } - public function test_updateUser_doesNotSendEmailIfNoChangeAndDoesNotRequirePassword() + public function testUpdateUserDoesNotSendEmailIfNoChangeAndDoesNotRequirePassword() { $capturedMails = []; Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) { $capturedMails[] = $mail; }); - $identity = FakeAccess::$identity; + $identity = FakeAccess::$identity; FakeAccess::$identity = $this->login; // en $this->api->updateUser($this->login, false, strtoupper($this->email)); FakeAccess::$identity = $identity; @@ -376,12 +377,12 @@ class APITest extends IntegrationTestCase $this->assertEquals([], $capturedMails); } - public function test_updateUser_doesNotChangePasswordIfFalsey() + public function testUpdateUserDoesNotChangePasswordIfFalsey() { - $model = new Model(); + $model = new Model(); $userBefore = $model->getUser($this->login); - $identity = FakeAccess::$identity; + $identity = FakeAccess::$identity; FakeAccess::$identity = $this->login; // ensure password will be checked against this user $this->api->updateUser($this->login, false, 'email@example.com', false, $this->password); FakeAccess::$identity = $identity; @@ -392,7 +393,7 @@ class APITest extends IntegrationTestCase $this->assertSame($userBefore['ts_password_modified'], $user['ts_password_modified']); } - public function test_updateUser_failsIfPasswordTooLong() + public function testUpdateUserFailsIfPasswordTooLong() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionInvalidPasswordTooLong'); @@ -406,7 +407,7 @@ class APITest extends IntegrationTestCase ); } - public function test_update_user_fails_if_email_exists_as_other_user_username() + public function testUpdateUserFailsIfEmailExistsAsOtherUserUsername() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionEmailExistsAsLogin'); @@ -417,9 +418,9 @@ class APITest extends IntegrationTestCase $this->api->updateUser($this->login, $this->password, $user2, false, $this->password); } - public function test_update_can_update_user_email_to_own_username() + public function testUpdateCanUpdateUserEmailToOwnUsername() { - $user2 = 'ownemail@example.com'; + $user2 = 'ownemail@example.com'; $password = 'password'; $this->api->addUser($user2, $password, 'ownemail_wrong@example.com'); @@ -430,7 +431,7 @@ class APITest extends IntegrationTestCase $this->assertEquals($user2Array['email'], $user2); } - public function test_cannot_create_user_if_email_exists_as_username() + public function testCannotCreateUserIfEmailExistsAsUsername() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionEmailExistsAsLogin'); @@ -441,7 +442,7 @@ class APITest extends IntegrationTestCase $this->api->addUser('user3', 'password', $user2); } - public function test_cannot_create_user_if_username_exists_as_email() + public function testCannotCreateUserIfUsernameExistsAsEmail() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionLoginExistsAsEmail'); @@ -449,7 +450,7 @@ class APITest extends IntegrationTestCase $this->api->addUser($this->email, 'password', 'new_user@example.com'); } - public function test_getSitesAccessFromUser_forSuperUser() + public function testGetSitesAccessFromUserForSuperUser() { $user2 = 'userLogin2'; $this->api->addUser($user2, 'password', 'userlogin2@password.de'); @@ -462,25 +463,25 @@ class APITest extends IntegrationTestCase $userUpdater->setSuperUserAccessWithoutCurrentPassword($user2, true); // super user has admin access for every site - $access = $this->api->getSitesAccessFromUser($user2); + $access = $this->api->getSitesAccessFromUser($user2); $expected = [ - [ - 'site' => 1, - 'access' => 'admin' - ], - [ - 'site' => 2, - 'access' => 'admin' - ], - [ - 'site' => 3, - 'access' => 'admin' - ], + [ + 'site' => 1, + 'access' => 'admin', + ], + [ + 'site' => 2, + 'access' => 'admin', + ], + [ + 'site' => 3, + 'access' => 'admin', + ], ]; $this->assertEquals($expected, $access); } - public function test_getUsersPlusRole_shouldReturnSelfIfUserDoesNotHaveAdminAccessToSite() + public function testGetUsersPlusRoleShouldReturnSelfIfUserDoesNotHaveAdminAccessToSite() { $this->addUserWithAccess('userLogin2', 'view', 1); $this->setCurrentUser('userLogin2', 'view', 1); @@ -488,18 +489,18 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'role' => 'view', - 'capabilities' => [], - 'email' => 'userLogin2@password.de', - 'superuser_access' => '0', - ], + [ + 'login' => 'userLogin2', + 'role' => 'view', + 'capabilities' => [], + 'email' => 'userLogin2@password.de', + 'superuser_access' => '0', + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldIgnoreOffsetIfLimitIsNotSupplied() + public function testGetUsersPlusRoleShouldIgnoreOffsetIfLimitIsNotSupplied() { $this->addUserWithAccess('userLogin2', 'view', 1); $this->setCurrentUser('userLogin2', 'view', 1); @@ -507,18 +508,18 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, $limit = null, $offset = 1); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'role' => 'view', - 'capabilities' => [], - 'email' => 'userLogin2@password.de', - 'superuser_access' => '0', - ], + [ + 'login' => 'userLogin2', + 'role' => 'view', + 'capabilities' => [], + 'email' => 'userLogin2@password.de', + 'superuser_access' => '0', + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldNotAllowSuperuserFilter_ifUserIsNotSuperUser() + public function testGetUsersPlusRoleShouldNotAllowSuperuserFilterIfUserIsNotSuperUser() { $this->addUserWithAccess('userLogin2', 'view', 1); $this->addUserWithAccess('userLogin3', 'superuser', 1); @@ -527,18 +528,18 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, null, null, null, 'superuser'); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'role' => 'view', - 'capabilities' => [], - 'email' => 'userLogin2@password.de', - 'superuser_access' => '0', - ], + [ + 'login' => 'userLogin2', + 'role' => 'view', + 'capabilities' => [], + 'email' => 'userLogin2@password.de', + 'superuser_access' => '0', + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldReturnAllUsersAndAccess_ifUserHasAdminAccess() + public function testGetUsersPlusRoleShouldReturnAllUsersAndAccessIfUserHasAdminAccess() { $this->addUserWithAccess('userLogin2', 'admin', 1); $this->addUserWithAccess('userLogin3', 'view', 1); @@ -549,30 +550,30 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'role' => 'admin', - 'capabilities' => [], - 'email' => 'userLogin2@password.de', - 'superuser_access' => false, - ], - [ - 'login' => 'userLogin3', - 'role' => 'view', - 'capabilities' => [], - 'superuser_access' => false, - ], - [ - 'login' => 'userLogin4', - 'role' => 'admin', - 'capabilities' => [], - 'superuser_access' => false, - ], + [ + 'login' => 'userLogin2', + 'role' => 'admin', + 'capabilities' => [], + 'email' => 'userLogin2@password.de', + 'superuser_access' => false, + ], + [ + 'login' => 'userLogin3', + 'role' => 'view', + 'capabilities' => [], + 'superuser_access' => false, + ], + [ + 'login' => 'userLogin4', + 'role' => 'admin', + 'capabilities' => [], + 'superuser_access' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldLimitUsersReturnedToThoseWithAccessToSitesAsCurrentUsersAdminSites_IfCurrentUserIsAdmin() + public function testGetUsersPlusRoleForAdminShouldLimitUsersToThoseWithAccessToSitesAsCurrentUsersAdminSites() { $this->addUserWithAccess('userLogin2', 'admin', [1, 2]); $this->addUserWithAccess('userLogin3', 'view', 1); @@ -584,36 +585,36 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'role' => 'admin', - 'capabilities' => [], - 'email' => 'userLogin2@password.de', - 'superuser_access' => false, - ], - [ - 'login' => 'userLogin3', - 'role' => 'view', - 'capabilities' => [], - 'superuser_access' => false, - ], - [ - 'login' => 'userLogin4', - 'role' => 'admin', - 'capabilities' => [], - 'superuser_access' => false, - ], - [ - 'login' => 'userLogin5', - 'role' => 'noaccess', - 'capabilities' => [], - 'superuser_access' => false, - ], + [ + 'login' => 'userLogin2', + 'role' => 'admin', + 'capabilities' => [], + 'email' => 'userLogin2@password.de', + 'superuser_access' => false, + ], + [ + 'login' => 'userLogin3', + 'role' => 'view', + 'capabilities' => [], + 'superuser_access' => false, + ], + [ + 'login' => 'userLogin4', + 'role' => 'admin', + 'capabilities' => [], + 'superuser_access' => false, + ], + [ + 'login' => 'userLogin5', + 'role' => 'noaccess', + 'capabilities' => [], + 'superuser_access' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldReturnAllUsersAndAccess_ifUserHasSuperuserAccess() + public function testGetUsersPlusRoleShouldReturnAllUsersAndAccessIfUserHasSuperuserAccess() { $this->addUserWithAccess('userLogin2', 'superuser', 1); $this->addUserWithAccess('userLogin3', 'view', 1); @@ -624,51 +625,51 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin', - 'email' => 'userlogin@password.de', - 'superuser_access' => false, - 'role' => 'noaccess', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin2', - 'email' => 'userLogin2@password.de', - 'superuser_access' => true, - 'role' => 'superuser', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin3', - 'email' => 'userLogin3@password.de', - 'superuser_access' => false, - 'role' => 'view', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin4', - 'email' => 'userLogin4@password.de', - 'superuser_access' => true, - 'role' => 'superuser', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin5', - 'email' => 'userLogin5@password.de', - 'superuser_access' => false, - 'role' => 'noaccess', - 'capabilities' => [], - 'uses_2fa' => false, - ], + [ + 'login' => 'userLogin', + 'email' => 'userlogin@password.de', + 'superuser_access' => false, + 'role' => 'noaccess', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin2', + 'email' => 'userLogin2@password.de', + 'superuser_access' => true, + 'role' => 'superuser', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin3', + 'email' => 'userLogin3@password.de', + 'superuser_access' => false, + 'role' => 'view', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin4', + 'email' => 'userLogin4@password.de', + 'superuser_access' => true, + 'role' => 'superuser', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin5', + 'email' => 'userLogin5@password.de', + 'superuser_access' => false, + 'role' => 'noaccess', + 'capabilities' => [], + 'uses_2fa' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldFilterUsersByAccessCorrectly() + public function testGetUsersPlusRoleShouldFilterUsersByAccessCorrectly() { $this->addUserWithAccess('userLogin2', 'admin', 1); $this->addUserWithAccess('userLogin3', 'view', 1); @@ -680,18 +681,19 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, null, null, null, 'admin'); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'role' => 'admin', - 'capabilities' => [], - 'email' => 'userLogin2@password.de', - 'superuser_access' => false, - ], - ['login' => 'userLogin5', - 'role' => 'admin', - 'capabilities' => [], - 'superuser_access' => false, - ], + [ + 'login' => 'userLogin2', + 'role' => 'admin', + 'capabilities' => [], + 'email' => 'userLogin2@password.de', + 'superuser_access' => false, + ], + [ + 'login' => 'userLogin5', + 'role' => 'admin', + 'capabilities' => [], + 'superuser_access' => false, + ], ]; $this->assertEquals($expected, $users); @@ -699,12 +701,12 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, null, null, null, 'write'); $this->cleanUsers($users); $expected = [ - ['login' => 'userLogin6', 'role' => 'write', 'capabilities' => [], 'superuser_access' => false], + ['login' => 'userLogin6', 'role' => 'write', 'capabilities' => [], 'superuser_access' => false], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldReturnUsersWithNoAccessCorrectly() + public function testGetUsersPlusRoleShouldReturnUsersWithNoAccessCorrectly() { $this->addUserWithAccess('userLogin2', 'noaccess', 1); $this->addUserWithAccess('userLogin3', 'view', 1); @@ -714,35 +716,35 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, null, null, null, 'noaccess'); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin', - 'role' => 'noaccess', - 'superuser_access' => false, - 'email' => 'userlogin@password.de', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin2', - 'role' => 'noaccess', - 'superuser_access' => false, - 'email' => 'userLogin2@password.de', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin5', - 'role' => 'noaccess', - 'superuser_access' => false, - 'email' => 'userLogin5@password.de', - 'capabilities' => [], - 'uses_2fa' => false, - ], + [ + 'login' => 'userLogin', + 'role' => 'noaccess', + 'superuser_access' => false, + 'email' => 'userlogin@password.de', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin2', + 'role' => 'noaccess', + 'superuser_access' => false, + 'email' => 'userLogin2@password.de', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin5', + 'role' => 'noaccess', + 'superuser_access' => false, + 'email' => 'userLogin5@password.de', + 'capabilities' => [], + 'uses_2fa' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldSearchForSuperUsersCorrectly() + public function testGetUsersPlusRoleShouldSearchForSuperUsersCorrectly() { $this->addUserWithAccess('userLogin2', 'admin', 1); $userUpdater = new UserUpdater(); @@ -755,27 +757,27 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, null, null, null, 'superuser'); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin2', - 'email' => 'userLogin2@password.de', - 'superuser_access' => true, - 'role' => 'superuser', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin4', - 'email' => 'userLogin4@password.de', - 'superuser_access' => true, - 'role' => 'superuser', - 'capabilities' => [], - 'uses_2fa' => false, - ], + [ + 'login' => 'userLogin2', + 'email' => 'userLogin2@password.de', + 'superuser_access' => true, + 'role' => 'superuser', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin4', + 'email' => 'userLogin4@password.de', + 'superuser_access' => true, + 'role' => 'superuser', + 'capabilities' => [], + 'uses_2fa' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldSearchByTextCorrectly() + public function testGetUsersPlusRoleShouldSearchByTextCorrectly() { $this->addUserWithAccess('searchTextLogin', 'superuser', 1, 'someemail@email.com'); $this->addUserWithAccess('userLogin2', 'view', 1, 'searchTextdef@email.com'); @@ -786,27 +788,27 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, null, null, 'searchText'); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'searchTextLogin', - 'email' => 'someemail@email.com', - 'superuser_access' => true, - 'role' => 'superuser', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin2', - 'email' => 'searchTextdef@email.com', - 'superuser_access' => false, - 'role' => 'view', - 'capabilities' => [], - 'uses_2fa' => false, - ], + [ + 'login' => 'searchTextLogin', + 'email' => 'someemail@email.com', + 'superuser_access' => true, + 'role' => 'superuser', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin2', + 'email' => 'searchTextdef@email.com', + 'superuser_access' => false, + 'role' => 'view', + 'capabilities' => [], + 'uses_2fa' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getUsersPlusRole_shouldApplyLimitAndOffsetCorrectly() + public function testGetUsersPlusRoleShouldApplyLimitAndOffsetCorrectly() { $this->addUserWithAccess('searchTextLogin', 'superuser', 1, 'someemail@email.com'); $this->addUserWithAccess('userLogin2', 'view', 1, 'searchTextdef@email.com'); @@ -817,70 +819,71 @@ class APITest extends IntegrationTestCase $users = $this->api->getUsersPlusRole(1, $limit = 2, $offset = 1); $this->cleanUsers($users); $expected = [ - [ - 'login' => 'userLogin', - 'email' => 'userlogin@password.de', - 'superuser_access' => false, - 'role' => 'noaccess', - 'capabilities' => [], - 'uses_2fa' => false, - ], - [ - 'login' => 'userLogin2', - 'email' => 'searchTextdef@email.com', - 'superuser_access' => false, - 'role' => 'view', - 'capabilities' => [], - 'uses_2fa' => false, - ], + [ + 'login' => 'userLogin', + 'email' => 'userlogin@password.de', + 'superuser_access' => false, + 'role' => 'noaccess', + 'capabilities' => [], + 'uses_2fa' => false, + ], + [ + 'login' => 'userLogin2', + 'email' => 'searchTextdef@email.com', + 'superuser_access' => false, + 'role' => 'view', + 'capabilities' => [], + 'uses_2fa' => false, + ], ]; $this->assertEquals($expected, $users); } - public function test_getSitesAccessForUser_shouldReturnAccessForUser() + public function testGetSitesAccessForUserShouldReturnAccessForUser() { $this->api->setUserAccess('userLogin', 'admin', [1]); $this->api->setUserAccess('userLogin', 'view', [2]); $this->api->setUserAccess('userLogin', 'view', [3]); - $access = $this->api->getSitesAccessForUser('userLogin'); + $access = $this->api->getSitesAccessForUser('userLogin'); $expected = [ - ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []], - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function getSitesAccessForUser_shouldIgnoreOffsetIfLimitNotSupplied() + public function testGetSitesAccessForUserShouldIgnoreOffsetIfLimitNotSupplied() { $this->api->setUserAccess('userLogin', 'admin', [1]); $this->api->setUserAccess('userLogin', 'view', [2]); $this->api->setUserAccess('userLogin', 'view', [3]); - $access = $this->api->getSitesAccessForUser('userLogin', $limit = null, $offset = 1); + $access = $this->api->getSitesAccessForUser('userLogin', $limit = null, $offset = 1); $expected = [ - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldApplyLimitAndOffsetCorrectly() + public function testGetSitesAccessForUserShouldApplyLimitAndOffsetCorrectly() { $this->api->setUserAccess('userLogin', 'admin', [1]); $this->api->setUserAccess('userLogin', 'view', [2]); $this->api->setUserAccess('userLogin', 'view', [3]); - $access = $this->api->getSitesAccessForUser('userLogin', $limit = 2, $offset = 1); + $access = $this->api->getSitesAccessForUser('userLogin', $limit = 2, $offset = 1); $expected = [ - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldSearchSitesCorrectly() + public function testGetSitesAccessForUserShouldSearchSitesCorrectly() { Fixture::createWebsite('2010-01-02 00:00:00'); @@ -906,30 +909,30 @@ class APITest extends IntegrationTestCase 'the searchTerm group' ); - $access = $this->api->getSitesAccessForUser('userLogin', null, null, 'searchTerm'); + $access = $this->api->getSitesAccessForUser('userLogin', null, null, 'searchTerm'); $expected = [ - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '1', 'site_name' => 'searchTerm site', 'role' => 'admin', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '1', 'site_name' => 'searchTerm site', 'role' => 'admin', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldFilterByAccessCorrectly() + public function testGetSitesAccessForUserShouldFilterByAccessCorrectly() { $this->api->setUserAccess('userLogin', 'admin', [1]); $this->api->setUserAccess('userLogin', 'view', [2]); $this->api->setUserAccess('userLogin', 'view', [3]); - $access = $this->api->getSitesAccessForUser('userLogin', null, null, null, 'view'); + $access = $this->api->getSitesAccessForUser('userLogin', null, null, null, 'view'); $expected = [ - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldLimitSitesIfUserIsAdmin() + public function testGetSitesAccessForUserShouldLimitSitesIfUserIsAdmin() { $this->addUserWithAccess('userLogin2', 'view', [1, 2, 3], 'userlogin2@email.com'); @@ -938,15 +941,15 @@ class APITest extends IntegrationTestCase $this->setCurrentUser('userLogin', 'admin', [1, 2]); - $access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'view'); + $access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'view'); $expected = [ - ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldLimitSitesIfUserIsAdmin_AndStillSelectNoAccessSitesCorrectly() + public function testGetSitesAccessForUserShouldLimitSitesIfUserIsAdminAndStillSelectNoAccessSitesCorrectly() { $this->addUserWithAccess('userLogin2', 'view', [1], 'userlogin2@email.com'); @@ -954,46 +957,46 @@ class APITest extends IntegrationTestCase $this->setCurrentUser('userLogin', 'admin', [1, 2, 3]); - $access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'noaccess'); + $access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'noaccess'); $expected = [ - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldSelectSitesCorrectlyIfAtLeastViewRequested() + public function testGetSitesAccessForUserShouldSelectSitesCorrectlyIfAtLeastViewRequested() { $this->addUserWithAccess('userLogin2', 'view', [1], 'userlogin2@email.com'); $this->api->setUserAccess('userLogin2', 'admin', [2]); - $access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'some'); + $access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'some'); $expected = [ - ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []], + ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []], ]; $this->assertEquals($expected, $access); } - public function test_getSitesAccessForUser_shouldReportIfUserHasNoAccessToSites() + public function testGetSitesAccessForUserShouldReportIfUserHasNoAccessToSites() { - $access = $this->api->getSitesAccessForUser('userLogin'); + $access = $this->api->getSitesAccessForUser('userLogin'); $expected = [ - ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], - ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], - ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], + ['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], + ['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], + ['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []], ]; $this->assertEquals($expected, $access); // test when search returns empty result $this->api->setUserAccess('userLogin', 'view', 1); - $access = $this->api->getSitesAccessForUser('userLogin', null, null, 'asdklfjds'); + $access = $this->api->getSitesAccessForUser('userLogin', null, null, 'asdklfjds'); $expected = []; $this->assertEquals($expected, $access); } - public function test_setUserAccess_MultipleRolesCannotBeSet() + public function testSetUserAccessMultipleRolesCannotBeSet() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionMultipleRoleSet'); @@ -1001,7 +1004,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess($this->login, ['view', 'admin'], [1]); } - public function test_setUserAccess_NeedsAtLeastOneRole() + public function testSetUserAccessNeedsAtLeastOneRole() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionNoRoleSet'); @@ -1009,7 +1012,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess($this->login, [TestCap2::ID], [1]); } - public function test_setUserAccess_NeedsAtLeastOneRoleAsString() + public function testSetUserAccessNeedsAtLeastOneRoleAsString() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAccessValues'); @@ -1017,7 +1020,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess($this->login, TestCap2::ID, [1]); } - public function test_setUserAccess_InvalidCapability() + public function testSetUserAccessInvalidCapability() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAccessValues'); @@ -1025,7 +1028,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess($this->login, ['admin', 'foobar'], [1]); } - public function test_setUserAccess_NeedsAtLeastOneRoleNoneGiven() + public function testSetUserAccessNeedsAtLeastOneRoleNoneGiven() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionNoRoleSet'); @@ -1033,7 +1036,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess($this->login, [], [1]); } - public function test_setUserAccess_CannotSetAdminToAnonymous() + public function testSetUserAccessCannotSetAdminToAnonymous() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAnonymousAccessNotPossible'); @@ -1041,7 +1044,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess('anonymous', 'admin', [1]); } - public function test_setUserAccess_CannotSetWriteToAnonymous() + public function testSetUserAccessCannotSetWriteToAnonymous() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAnonymousAccessNotPossible'); @@ -1049,7 +1052,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess('anonymous', 'write', [1]); } - public function test_setUserAccess_UserDoesNotExist() + public function testSetUserAccessUserDoesNotExist() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist'); @@ -1057,7 +1060,7 @@ class APITest extends IntegrationTestCase $this->api->setUserAccess('foobar', Admin::ID, [1]); } - public function test_setUserAccess_SetRoleAndCapabilities() + public function testSetUserAccessSetRoleAndCapabilities() { $access = [TestCap2::ID, View::ID, TestCap3::ID]; $this->api->setUserAccess($this->login, $access, [1]); @@ -1065,14 +1068,14 @@ class APITest extends IntegrationTestCase $access = $this->model->getSitesAccessFromUser($this->login); $expected = [ - ['site' => '1', 'access' => 'view'], - ['site' => '1', 'access' => TestCap2::ID], - ['site' => '1', 'access' => TestCap3::ID], + ['site' => '1', 'access' => 'view'], + ['site' => '1', 'access' => TestCap2::ID], + ['site' => '1', 'access' => TestCap3::ID], ]; $this->assertEquals($expected, $access); } - public function test_setUserAccess_SetRoleAsString() + public function testSetUserAccessSetRoleAsString() { $this->api->setUserAccess($this->login, View::ID, [1]); @@ -1080,7 +1083,7 @@ class APITest extends IntegrationTestCase $this->assertEquals([['site' => '1', 'access' => 'view']], $access); } - public function test_setUserAccess_SetRoleAsArray() + public function testSetUserAccessSetRoleAsArray() { $this->api->setUserAccess($this->login, [View::ID], [1]); @@ -1088,7 +1091,7 @@ class APITest extends IntegrationTestCase $this->assertEquals([['site' => '1', 'access' => 'view']], $access); } - public function test_addCapabilities_failsWhenNotCapabilityIsGivenAsString() + public function testAddCapabilitiesFailsWhenNotCapabilityIsGivenAsString() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAccessValues'); @@ -1096,7 +1099,7 @@ class APITest extends IntegrationTestCase $this->api->addCapabilities($this->login, View::ID, [1]); } - public function test_addCapabilities_failsWhenNotCapabilityIsGivenAsArray() + public function testAddCapabilitiesFailsWhenNotCapabilityIsGivenAsArray() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAccessValues'); @@ -1104,7 +1107,7 @@ class APITest extends IntegrationTestCase $this->api->addCapabilities($this->login, [TestCap2::ID, View::ID], [1]); } - public function test_addCapabilities_failsWhenUserDoesNotExist() + public function testAddCapabilitiesFailsWhenUserDoesNotExist() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist'); @@ -1112,7 +1115,7 @@ class APITest extends IntegrationTestCase $this->api->addCapabilities('foobar', [TestCap2::ID], [1]); } - public function test_addCapabilities_DoesNotAddSameCapabilityTwice() + public function testAddCapabilitiesDoesNotAddSameCapabilityTwice() { $addAccess = [TestCap2::ID, View::ID, TestCap3::ID]; $this->api->setUserAccess($this->login, $addAccess, [1]); @@ -1120,9 +1123,9 @@ class APITest extends IntegrationTestCase $access = $this->model->getSitesAccessFromUser($this->login); $expected = [ - ['site' => '1', 'access' => 'view'], - ['site' => '1', 'access' => TestCap2::ID], - ['site' => '1', 'access' => TestCap3::ID], + ['site' => '1', 'access' => 'view'], + ['site' => '1', 'access' => TestCap2::ID], + ['site' => '1', 'access' => TestCap3::ID], ]; $this->assertEquals($expected, $access); @@ -1134,11 +1137,11 @@ class APITest extends IntegrationTestCase $this->api->addCapabilities($this->login, [TestCap2::ID, TestCap1::ID, TestCap3::ID], [1]); $expected[] = ['site' => '1', 'access' => TestCap1::ID]; - $access = $this->model->getSitesAccessFromUser($this->login); + $access = $this->model->getSitesAccessFromUser($this->login); $this->assertEquals($expected, $access); } - public function test_addCapabilities_DoesNotAddCapabilityToUserWithNoRole() + public function testAddCapabilitiesDoesNotAddCapabilityToUserWithNoRole() { self::expectException(\Exception::class); self::expectExceptionMessage('UsersManager_ExceptionNoCapabilitiesWithoutRole'); @@ -1150,34 +1153,34 @@ class APITest extends IntegrationTestCase $this->api->addCapabilities($this->login, array(TestCap2::ID, TestCap3::ID), array(1)); } - public function test_addCapabilities_DoesNotAddCapabilitiesWhichAreIncludedInRoleAlready() + public function testAddCapabilitiesDoesNotAddCapabilitiesWhichAreIncludedInRoleAlready() { $this->api->setUserAccess($this->login, Write::ID, [1]); $access = $this->model->getSitesAccessFromUser($this->login); $expected = [ - ['site' => '1', 'access' => 'write'], + ['site' => '1', 'access' => 'write'], ]; $this->assertEquals($expected, $access); $this->api->addCapabilities($this->login, [TestCap2::ID, TestCap3::ID], [1]); $expected[] = ['site' => '1', 'access' => TestCap3::ID]; - $access = $this->model->getSitesAccessFromUser($this->login); + $access = $this->model->getSitesAccessFromUser($this->login); // did not add TestCap2 $this->assertEquals($expected, $access); } - public function test_addCapabilities_DoesAddCapabilitiesWhichAreNotIncludedInRoleYetAlready() + public function testAddCapabilitiesDoesAddCapabilitiesWhichAreNotIncludedInRoleYetAlready() { $this->api->setUserAccess($this->login, Admin::ID, [1]); $access = $this->model->getSitesAccessFromUser($this->login); $expected = [ - ['site' => '1', 'access' => 'admin'], + ['site' => '1', 'access' => 'admin'], ]; $this->assertEquals($expected, $access); @@ -1187,7 +1190,7 @@ class APITest extends IntegrationTestCase $this->assertEquals($expected, $access); } - public function test_removeCapabilities_failsWhenNotCapabilityIsGivenAsString() + public function testRemoveCapabilitiesFailsWhenNotCapabilityIsGivenAsString() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAccessValues'); @@ -1195,7 +1198,7 @@ class APITest extends IntegrationTestCase $this->api->removeCapabilities($this->login, View::ID, [1]); } - public function test_removeCapabilities_failsWhenNotCapabilityIsGivenAsArray() + public function testRemoveCapabilitiesFailsWhenNotCapabilityIsGivenAsArray() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionAccessValues'); @@ -1203,7 +1206,7 @@ class APITest extends IntegrationTestCase $this->api->removeCapabilities($this->login, [TestCap2::ID, View::ID], [1]); } - public function test_removeCapabilities_failsWhenUserDoesNotExist() + public function testRemoveCapabilitiesFailsWhenUserDoesNotExist() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist'); @@ -1211,7 +1214,7 @@ class APITest extends IntegrationTestCase $this->api->removeCapabilities('foobar', [TestCap2::ID], [1]); } - public function test_removeCapabilities() + public function testRemoveCapabilities() { $addAccess = [View::ID, TestCap2::ID, TestCap3::ID, TestCap1::ID]; $this->api->setUserAccess($this->login, $addAccess, [1]); @@ -1225,7 +1228,7 @@ class APITest extends IntegrationTestCase $this->assertEquals([View::ID, TestCap1::ID], $access); } - public function test_setSuperUserAccess_failsIfCurrentPasswordIsIncorrect() + public function testSetSuperUserAccessFailsIfCurrentPasswordIsIncorrect() { $this->expectException(\Exception::class); $this->expectExceptionMessage('UsersManager_CurrentPasswordNotCorrect'); @@ -1233,15 +1236,49 @@ class APITest extends IntegrationTestCase $this->api->setSuperUserAccess($this->login, true, 'asldfkjds'); } + + public function testInviteUserInitialIdSiteMissing() + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('UsersManager_AddUserNoInitialAccessError'); + Request::processRequest( + 'UsersManager.inviteUser', + [ + 'userLogin' => "testInviteUser", + 'email' => "testInviteUser@example.com", + 'expiryInDays' => 7, + ] + ); + } + + public function testInviteUserInitialIdSiteError() + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage("An unexpected website was found in the request: website id was set to '10'"); + Request::processRequest( + 'UsersManager.inviteUser', + [ + 'userLogin' => "testInviteUser", + 'email' => "testInviteUser@example.com", + 'initialIdSite' => 10, + 'expiryInDays' => 7, + ] + ); + } + + public function testInviteUserAsSuperUser() { $eventWasFired = false; - EventDispatcher::getInstance()->addObserver('UsersManager.inviteUser.end', function ($userLogin, $email) use (&$eventWasFired) { - self::assertEquals('pendingLoginTest', $userLogin); - self::assertEquals('pendingLoginTest@matomo.org', $email); - $eventWasFired = true; - }); + EventDispatcher::getInstance()->addObserver( + 'UsersManager.inviteUser.end', + function ($userLogin, $email) use (&$eventWasFired) { + self::assertEquals('pendingLoginTest', $userLogin); + self::assertEquals('pendingLoginTest@matomo.org', $email); + $eventWasFired = true; + } + ); $this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1); $user = $this->model->isPendingUser('pendingLoginTest'); @@ -1291,13 +1328,13 @@ class APITest extends IntegrationTestCase public function testInviteUserExpiredInGivenDays() { - Date::$now = time(); // freeze time, so it doesn't change between inviting user and comparing the time + Date::$now = time(); // freeze time, so it doesn't change between inviting user and comparing the time $expiredDays = 10; - $this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', null, $expiredDays); - $user = $this->model->getUser('pendingLoginTest'); + $this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1, $expiredDays); + $user = $this->model->getUser('pendingLoginTest'); $expired = Date::factory($user['invite_expired_at'])->getTimestamp(); - $now = Date::now()->getTimestamp(); - $diff = $expired - $now; + $now = Date::now()->getTimestamp(); + $diff = $expired - $now; $this->assertEquals($expiredDays, $diff / 3600 / 24); } @@ -1309,10 +1346,13 @@ class APITest extends IntegrationTestCase $eventWasFired = false; - EventDispatcher::getInstance()->addObserver('UsersManager.inviteUser.resendInvite', function ($userLogin) use (&$eventWasFired) { - self::assertEquals('pendingLoginTest', $userLogin); - $eventWasFired = true; - }); + EventDispatcher::getInstance()->addObserver( + 'UsersManager.inviteUser.resendInvite', + function ($userLogin) use (&$eventWasFired) { + self::assertEquals('pendingLoginTest', $userLogin); + $eventWasFired = true; + } + ); $this->api->resendInvite('pendingLoginTest'); self::assertTrue($eventWasFired); @@ -1337,10 +1377,13 @@ class APITest extends IntegrationTestCase $eventWasFired = false; - EventDispatcher::getInstance()->addObserver('UsersManager.inviteUser.resendInvite', function ($userLogin) use (&$eventWasFired) { - self::assertEquals('pendingLoginTest', $userLogin); - $eventWasFired = true; - }); + EventDispatcher::getInstance()->addObserver( + 'UsersManager.inviteUser.resendInvite', + function ($userLogin) use (&$eventWasFired) { + self::assertEquals('pendingLoginTest', $userLogin); + $eventWasFired = true; + } + ); $this->api->resendInvite('pendingLoginTest'); self::assertTrue($eventWasFired); @@ -1437,7 +1480,7 @@ class APITest extends IntegrationTestCase private function getAccessInSite($login, $idSite) { $access = $this->model->getSitesAccessFromUser($login); - $ids = []; + $ids = []; foreach ($access as $entry) { if ($entry['site'] == $idSite) { $ids[] = $entry['access']; @@ -1454,22 +1497,26 @@ class APITest extends IntegrationTestCase public function provideContainerConfig() { return [ - 'Piwik\Access' => new FakeAccess(), - 'usersmanager.user_preference_names' => \DI\add([ - 'randomDoesNotExist', - 'RandomNOTREQUESTED', - 'preferenceName' - ]), - 'observers.global' => \DI\add([ - [ - 'Access.Capability.addCapabilities', - \DI\value(function (&$capabilities) { - $capabilities[] = new TestCap1(); - $capabilities[] = new TestCap2(); - $capabilities[] = new TestCap3(); - }) - ], - ]), + 'Piwik\Access' => new FakeAccess(), + 'usersmanager.user_preference_names' => \DI\add( + [ + 'randomDoesNotExist', + 'RandomNOTREQUESTED', + 'preferenceName', + ] + ), + 'observers.global' => \DI\add( + [ + [ + 'Access.Capability.addCapabilities', + \DI\value(function (&$capabilities) { + $capabilities[] = new TestCap1(); + $capabilities[] = new TestCap2(); + $capabilities[] = new TestCap3(); + }), + ], + ] + ), ]; } @@ -1486,7 +1533,7 @@ class APITest extends IntegrationTestCase public function setCurrentUser($username, $accessLevel, $idSite) { - FakeAccess::$identity = $username; + FakeAccess::$identity = $username; FakeAccess::$superUser = $accessLevel == 'superuser'; if ($accessLevel == 'view') { FakeAccess::$idSitesView = is_array($idSite) ? $idSite : [$idSite]; diff --git a/plugins/UsersManager/tests/Integration/UserInviteTest.php b/plugins/UsersManager/tests/Integration/UserInviteTest.php index 2c61bb90f4..792d4f8d0b 100644 --- a/plugins/UsersManager/tests/Integration/UserInviteTest.php +++ b/plugins/UsersManager/tests/Integration/UserInviteTest.php @@ -56,7 +56,7 @@ class UserInviteTest extends IntegrationTestCase [ 'userLogin' => $this->pendingUser['login'], 'email' => $this->pendingUser['email'], - 'idSite' => 1, + 'initialIdSite' => 1, 'expiryInDays' => 7 ] ); diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_rows_in_search.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_rows_in_search.png index fedb59b83e..78693a2697 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_rows_in_search.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_all_rows_in_search.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c231e9609f5928426cf71151d703557a0fafc08eb9ece4a1447149c966925c21 -size 100235 +oid sha256:e485f985a2096bfc259e9955a008ebd5879ee9725f691b1d4c5f10fd4d1dc73b +size 86742 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_edit.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_edit.png index faf8d32988..659afa6579 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_edit.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_permissions_edit.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:292e3f739530aad0ceba658f55e123556c845ec681ccc2f77244184028ef35cb -size 88585 +oid sha256:6a9b4f7b1ac46e2521631fa7055f94fe921c7088af7307191b0a1ef9bb0b6b46 +size 75169 diff --git a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_user_created.png b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_user_created.png index 9184f1a37d..0d4934988b 100644 --- a/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_user_created.png +++ b/plugins/UsersManager/tests/UI/expected-screenshots/UsersManager_user_created.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f97cfaa64c56e51a88d1f4727be80753f5e51956fd474d4d1ec89a5dfd0d5508 -size 22833 +oid sha256:406437e042339b681e39ce9e745e8ee5e391fd758a3bee0b8a1651a9c80f5c96 +size 22488 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png index 9bd04f9175..842a39ee1c 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d17357b1e8a3a7ea193d56a633eba6f563ff2d4f8ee008574d14abb8dbc8a38 -size 5077474 +oid sha256:5c3a0bbfd3f780aa41cb1914832e7c0389c81594752111c9698dd8d5759634fb +size 5077766 |