diff options
author | Stefan Giehl <stefan@matomo.org> | 2022-02-14 19:43:46 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-14 19:43:46 +0300 |
commit | 34e226540e69ab4b6dd82a9024d72782e1ac058a (patch) | |
tree | f7297830e03cbf304efe9029390a07787a4094e3 | |
parent | 4350dfb18698f54f164a868c0cb6c41ed3a6e67f (diff) |
Fix session timeouts in overlay session (#18648)
* Ensure samesite cookie attribute is set correctly for requests coming from overlay session
* Don't fetch API.getPagesComparisonsDisabledFor on Overlay page
* Check for explicit overlay requests
* Adds valid host check
* parse referer query
* use UrlHelper::getArrayFromQueryString
* Adds some tests for Overlay::isOverlayRequest
* apply review feedback
* built vue files
Co-authored-by: sgiehl <sgiehl@users.noreply.github.com>
-rw-r--r-- | core/Session.php | 6 | ||||
-rw-r--r-- | core/UrlHelper.php | 2 | ||||
-rw-r--r-- | plugins/CoreHome/vue/dist/CoreHome.umd.js | 2 | ||||
-rw-r--r-- | plugins/CoreHome/vue/dist/CoreHome.umd.min.js | 2 | ||||
-rw-r--r-- | plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts | 1 | ||||
-rw-r--r-- | plugins/Overlay/Overlay.php | 38 | ||||
-rw-r--r-- | plugins/Overlay/tests/Unit/OverlayTest.php | 127 |
7 files changed, 173 insertions, 5 deletions
diff --git a/core/Session.php b/core/Session.php index 641334676c..096914e6e0 100644 --- a/core/Session.php +++ b/core/Session.php @@ -11,6 +11,7 @@ namespace Piwik; use Exception; use Piwik\Container\StaticContainer; use Piwik\Exception\MissingFilePermissionException; +use Piwik\Plugins\Overlay\Overlay; use Piwik\Session\SaveHandler\DbTable; use Psr\Log\LoggerInterface; use Zend_Session; @@ -170,10 +171,11 @@ class Session extends Zend_Session $module = Piwik::getModule(); $action = Piwik::getAction(); + $method = Common::getRequestVar('method', '', 'string'); + $referer = Url::getReferrer(); $isOptOutRequest = $module == 'CoreAdminHome' && $action == 'optOut'; - $isOverlay = $module == 'Overlay'; - $shouldUseNone = !empty($general['enable_framed_pages']) || $isOptOutRequest || $isOverlay; + $shouldUseNone = !empty($general['enable_framed_pages']) || $isOptOutRequest || Overlay::isOverlayRequest($module, $action, $method, $referer); if ($shouldUseNone && ProxyHttp::isHttps()) { return 'None'; diff --git a/core/UrlHelper.php b/core/UrlHelper.php index 2a0fc4cb1d..94c8ff9d55 100644 --- a/core/UrlHelper.php +++ b/core/UrlHelper.php @@ -202,7 +202,7 @@ class UrlHelper */ public static function getArrayFromQueryString($urlQuery) { - if (strlen($urlQuery) == 0) { + if (empty($urlQuery)) { return array(); } diff --git a/plugins/CoreHome/vue/dist/CoreHome.umd.js b/plugins/CoreHome/vue/dist/CoreHome.umd.js index 2ae2a7a672..924398606c 100644 --- a/plugins/CoreHome/vue/dist/CoreHome.umd.js +++ b/plugins/CoreHome/vue/dist/CoreHome.umd.js @@ -4314,7 +4314,7 @@ var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () { return; } - if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation') { + if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation' || matomoModule === 'Overlay') { this.privateState.comparisonsDisabledFor = []; return; } diff --git a/plugins/CoreHome/vue/dist/CoreHome.umd.min.js b/plugins/CoreHome/vue/dist/CoreHome.umd.min.js index 78e25cc4df..53247e6ee4 100644 --- a/plugins/CoreHome/vue/dist/CoreHome.umd.min.js +++ b/plugins/CoreHome/vue/dist/CoreHome.umd.min.js @@ -288,7 +288,7 @@ function bn(e){return{restrict:"A",priority:10,link:function(t,n,r){var i={insta * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var hr=8,gr=3;function vr(e){return e?Array.isArray(e)?e:[e]:[]}var br=function(){function e(){var t=this;dr(this,e),fr(this,"privateState",Object(a["reactive"])({comparisonsDisabledFor:[]})),fr(this,"state",Object(a["readonly"])(this.privateState)),fr(this,"colors",{}),fr(this,"segmentComparisons",Object(a["computed"])((function(){return t.parseSegmentComparisons()}))),fr(this,"periodComparisons",Object(a["computed"])((function(){return t.parsePeriodComparisons()}))),fr(this,"isEnabled",Object(a["computed"])((function(){return t.checkEnabledForCurrentPage()}))),this.loadComparisonsDisabledFor(),$((function(){t.colors=t.getAllSeriesColors()})),Object(a["watch"])((function(){return t.getComparisons()}),(function(){return S.postEvent("piwikComparisonsChanged")}),{deep:!0})}return mr(e,[{key:"getComparisons",value:function(){return this.getSegmentComparisons().concat(this.getPeriodComparisons())}},{key:"isComparing",value:function(){return this.isComparisonEnabled()&&(this.segmentComparisons.value.length>1||this.periodComparisons.value.length>1)}},{key:"isComparingPeriods",value:function(){return this.getPeriodComparisons().length>1}},{key:"getSegmentComparisons",value:function(){return this.isComparisonEnabled()?this.segmentComparisons.value:[]}},{key:"getPeriodComparisons",value:function(){return this.isComparisonEnabled()?this.periodComparisons.value:[]}},{key:"getSeriesColor",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=this.getComparisonSeriesIndex(t.index,e.index)%hr;if(0===n)return this.colors["series".concat(r)];var i=n%gr;return this.colors["series".concat(r,"-shade").concat(i)]}},{key:"getSeriesColorName",value:function(e,t){var n="series".concat(e%hr);return t>0&&(n+="-shade".concat(t%gr)),n}},{key:"isComparisonEnabled",value:function(){return this.isEnabled.value}},{key:"getIndividualComparisonRowIndices",value:function(e){var t=this.getSegmentComparisons().length,n=e%t,r=Math.floor(e/t);return{segmentIndex:n,periodIndex:r}}},{key:"getComparisonSeriesIndex",value:function(e,t){var n=this.getSegmentComparisons().length;return e*n+t}},{key:"getAllComparisonSeries",value:function(){var e=this,t=[],n=0;return this.getPeriodComparisons().forEach((function(r){e.getSegmentComparisons().forEach((function(i){t.push({index:n,params:Object.assign(Object.assign({},i.params),r.params),color:e.colors["series".concat(n)]}),n+=1}))})),t}},{key:"removeSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=ar(this.segmentComparisons.value);t.splice(e,1);var n={};0===e&&(n.segment=t[0].params.segment),this.updateQueryParamsFromComparisons(t,this.periodComparisons.value,n)}},{key:"addSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=this.segmentComparisons.value.concat([{params:e,index:-1,title:""}]);this.updateQueryParamsFromComparisons(t,this.periodComparisons.value)}},{key:"updateQueryParamsFromComparisons",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r={},i={},a=!1,o=!1;e.forEach((function(e){a?r[e.params.segment]=!0:a=!0})),t.forEach((function(e){o?i["".concat(e.params.period,"|").concat(e.params.date)]=!0:o=!0}));var l=[],c=[];Object.keys(i).forEach((function(e){var t=e.split("|");l.push(t[0]),c.push(t[1])}));var s={compareSegments:Object.keys(r),comparePeriods:l,compareDates:c},u=S.helper.isAngularRenderingThePage()?Ce.hashParsed.value:Ce.urlParsed.value;Ce.updateLocation(Object.assign(Object.assign(Object.assign({},u),s),n))}},{key:"getAllSeriesColors",value:function(){var e=S.ColorManager;if(!e)return[];for(var t=[],n=0;n<hr;n+=1){t.push("series".concat(n));for(var r=0;r<gr;r+=1)t.push("series".concat(n,"-shade").concat(r))}return e.getColors("comparison-series-color",t)}},{key:"loadComparisonsDisabledFor",value:function(){var e=this,t=Ce.parsed.value.module;window.piwik.installation?this.privateState.comparisonsDisabledFor=[]:"CoreUpdater"!==t&&"Installation"!==t?Xe.fetch({module:"API",method:"API.getPagesComparisonsDisabledFor"}).then((function(t){e.privateState.comparisonsDisabledFor=t})):this.privateState.comparisonsDisabledFor=[]}},{key:"parseSegmentComparisons",value:function(){var e=ir.state.availableSegments,t=ar(vr(Ce.parsed.value.compareSegments));t.unshift(Ce.parsed.value.segment||"");var n=[];return t.forEach((function(t,r){var i;e.forEach((function(e){e.definition!==t&&e.definition!==decodeURIComponent(t)&&decodeURIComponent(e.definition)!==t||(i=e)}));var a=i?i.name:C("General_Unknown");""===t.trim()&&(a=C("SegmentEditor_DefaultAllVisits")),n.push({params:{segment:t},title:S.helper.htmlDecode(a),index:r})})),n}},{key:"parsePeriodComparisons",value:function(){var e=ar(vr(Ce.parsed.value.comparePeriods)),t=ar(vr(Ce.parsed.value.compareDates));e.unshift(Ce.parsed.value.period),t.unshift(Ce.parsed.value.date);for(var n=[],r=0;r<Math.min(t.length,e.length);r+=1){var i=void 0;try{i=p.parse(e[r],t[r]).getPrettyString()}catch(a){i=C("General_Error")}n.push({params:{date:t[r],period:e[r]},title:i,index:r})}return n}},{key:"checkEnabledForCurrentPage",value:function(){var e=Ce.parsed.value.category||Ce.parsed.value.module,t=Ce.parsed.value.subcategory||Ce.parsed.value.action,n="".concat(e,".").concat(t),r=-1===this.privateState.comparisonsDisabledFor.indexOf(n)&&-1===this.privateState.comparisonsDisabledFor.indexOf("".concat(e,".*"));return document.documentElement.classList.toggle("comparisonsDisabled",!r),r}}]),e}(),yr=new br,wr={key:0,ref:"root",class:"matomo-comparisons"},Or={class:"comparison-type"},jr=["title"],kr=["href"],Sr=["title"],Cr={class:"comparison-period-label"},Er=["onClick"],Dr=["title"],Pr={class:"loadingPiwik",style:{display:"none"}},Vr=["alt"];function Nr(e,t,n,r,i,o){var l=Object(a["resolveDirective"])("tooltips");return e.isComparing?Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",wr,[Object(a["createElementVNode"])("h3",null,Object(a["toDisplayString"])(e.translate("General_Comparisons")),1),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.segmentComparisons,(function(t,n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"comparison card",key:t.index},[Object(a["createElementVNode"])("div",Or,Object(a["toDisplayString"])(e.translate("General_Segment")),1),Object(a["createElementVNode"])("div",{class:"title",title:t.title+"<br/>"+decodeURIComponent(t.params.segment)},[Object(a["createElementVNode"])("a",{target:"_blank",href:e.getUrlToSegment(t.params.segment)},Object(a["toDisplayString"])(t.title),9,kr)],8,jr),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.periodComparisons,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"comparison-period",key:n.index,title:e.getComparisonTooltip(t,n)},[Object(a["createElementVNode"])("span",{class:"comparison-dot",style:Object(a["normalizeStyle"])({"background-color":e.getSeriesColor(t,n)})},null,4),Object(a["createElementVNode"])("span",Cr,Object(a["toDisplayString"])(n.title)+" ("+Object(a["toDisplayString"])(e.getComparisonPeriodType(n))+") ",1)],8,Sr)})),128)),e.segmentComparisons.length>1?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:0,class:"remove-button",onClick:function(t){return e.removeSegmentComparison(n)}},[Object(a["createElementVNode"])("span",{class:"icon icon-close",title:e.translate("General_ClickToRemoveComp")},null,8,Dr)],8,Er)):Object(a["createCommentVNode"])("",!0)])})),128)),Object(a["createElementVNode"])("div",Pr,[Object(a["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",alt:e.translate("General_LoadingData")},null,8,Vr),Object(a["createTextVNode"])(" "+Object(a["toDisplayString"])(e.translate("General_LoadingData")),1)])],512)),[[l,{duration:200,delay:200,content:e.transformTooltipContent}]]):Object(a["createCommentVNode"])("",!0)} + */var hr=8,gr=3;function vr(e){return e?Array.isArray(e)?e:[e]:[]}var br=function(){function e(){var t=this;dr(this,e),fr(this,"privateState",Object(a["reactive"])({comparisonsDisabledFor:[]})),fr(this,"state",Object(a["readonly"])(this.privateState)),fr(this,"colors",{}),fr(this,"segmentComparisons",Object(a["computed"])((function(){return t.parseSegmentComparisons()}))),fr(this,"periodComparisons",Object(a["computed"])((function(){return t.parsePeriodComparisons()}))),fr(this,"isEnabled",Object(a["computed"])((function(){return t.checkEnabledForCurrentPage()}))),this.loadComparisonsDisabledFor(),$((function(){t.colors=t.getAllSeriesColors()})),Object(a["watch"])((function(){return t.getComparisons()}),(function(){return S.postEvent("piwikComparisonsChanged")}),{deep:!0})}return mr(e,[{key:"getComparisons",value:function(){return this.getSegmentComparisons().concat(this.getPeriodComparisons())}},{key:"isComparing",value:function(){return this.isComparisonEnabled()&&(this.segmentComparisons.value.length>1||this.periodComparisons.value.length>1)}},{key:"isComparingPeriods",value:function(){return this.getPeriodComparisons().length>1}},{key:"getSegmentComparisons",value:function(){return this.isComparisonEnabled()?this.segmentComparisons.value:[]}},{key:"getPeriodComparisons",value:function(){return this.isComparisonEnabled()?this.periodComparisons.value:[]}},{key:"getSeriesColor",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=this.getComparisonSeriesIndex(t.index,e.index)%hr;if(0===n)return this.colors["series".concat(r)];var i=n%gr;return this.colors["series".concat(r,"-shade").concat(i)]}},{key:"getSeriesColorName",value:function(e,t){var n="series".concat(e%hr);return t>0&&(n+="-shade".concat(t%gr)),n}},{key:"isComparisonEnabled",value:function(){return this.isEnabled.value}},{key:"getIndividualComparisonRowIndices",value:function(e){var t=this.getSegmentComparisons().length,n=e%t,r=Math.floor(e/t);return{segmentIndex:n,periodIndex:r}}},{key:"getComparisonSeriesIndex",value:function(e,t){var n=this.getSegmentComparisons().length;return e*n+t}},{key:"getAllComparisonSeries",value:function(){var e=this,t=[],n=0;return this.getPeriodComparisons().forEach((function(r){e.getSegmentComparisons().forEach((function(i){t.push({index:n,params:Object.assign(Object.assign({},i.params),r.params),color:e.colors["series".concat(n)]}),n+=1}))})),t}},{key:"removeSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=ar(this.segmentComparisons.value);t.splice(e,1);var n={};0===e&&(n.segment=t[0].params.segment),this.updateQueryParamsFromComparisons(t,this.periodComparisons.value,n)}},{key:"addSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=this.segmentComparisons.value.concat([{params:e,index:-1,title:""}]);this.updateQueryParamsFromComparisons(t,this.periodComparisons.value)}},{key:"updateQueryParamsFromComparisons",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r={},i={},a=!1,o=!1;e.forEach((function(e){a?r[e.params.segment]=!0:a=!0})),t.forEach((function(e){o?i["".concat(e.params.period,"|").concat(e.params.date)]=!0:o=!0}));var l=[],c=[];Object.keys(i).forEach((function(e){var t=e.split("|");l.push(t[0]),c.push(t[1])}));var s={compareSegments:Object.keys(r),comparePeriods:l,compareDates:c},u=S.helper.isAngularRenderingThePage()?Ce.hashParsed.value:Ce.urlParsed.value;Ce.updateLocation(Object.assign(Object.assign(Object.assign({},u),s),n))}},{key:"getAllSeriesColors",value:function(){var e=S.ColorManager;if(!e)return[];for(var t=[],n=0;n<hr;n+=1){t.push("series".concat(n));for(var r=0;r<gr;r+=1)t.push("series".concat(n,"-shade").concat(r))}return e.getColors("comparison-series-color",t)}},{key:"loadComparisonsDisabledFor",value:function(){var e=this,t=Ce.parsed.value.module;window.piwik.installation?this.privateState.comparisonsDisabledFor=[]:"CoreUpdater"!==t&&"Installation"!==t&&"Overlay"!==t?Xe.fetch({module:"API",method:"API.getPagesComparisonsDisabledFor"}).then((function(t){e.privateState.comparisonsDisabledFor=t})):this.privateState.comparisonsDisabledFor=[]}},{key:"parseSegmentComparisons",value:function(){var e=ir.state.availableSegments,t=ar(vr(Ce.parsed.value.compareSegments));t.unshift(Ce.parsed.value.segment||"");var n=[];return t.forEach((function(t,r){var i;e.forEach((function(e){e.definition!==t&&e.definition!==decodeURIComponent(t)&&decodeURIComponent(e.definition)!==t||(i=e)}));var a=i?i.name:C("General_Unknown");""===t.trim()&&(a=C("SegmentEditor_DefaultAllVisits")),n.push({params:{segment:t},title:S.helper.htmlDecode(a),index:r})})),n}},{key:"parsePeriodComparisons",value:function(){var e=ar(vr(Ce.parsed.value.comparePeriods)),t=ar(vr(Ce.parsed.value.compareDates));e.unshift(Ce.parsed.value.period),t.unshift(Ce.parsed.value.date);for(var n=[],r=0;r<Math.min(t.length,e.length);r+=1){var i=void 0;try{i=p.parse(e[r],t[r]).getPrettyString()}catch(a){i=C("General_Error")}n.push({params:{date:t[r],period:e[r]},title:i,index:r})}return n}},{key:"checkEnabledForCurrentPage",value:function(){var e=Ce.parsed.value.category||Ce.parsed.value.module,t=Ce.parsed.value.subcategory||Ce.parsed.value.action,n="".concat(e,".").concat(t),r=-1===this.privateState.comparisonsDisabledFor.indexOf(n)&&-1===this.privateState.comparisonsDisabledFor.indexOf("".concat(e,".*"));return document.documentElement.classList.toggle("comparisonsDisabled",!r),r}}]),e}(),yr=new br,wr={key:0,ref:"root",class:"matomo-comparisons"},Or={class:"comparison-type"},jr=["title"],kr=["href"],Sr=["title"],Cr={class:"comparison-period-label"},Er=["onClick"],Dr=["title"],Pr={class:"loadingPiwik",style:{display:"none"}},Vr=["alt"];function Nr(e,t,n,r,i,o){var l=Object(a["resolveDirective"])("tooltips");return e.isComparing?Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",wr,[Object(a["createElementVNode"])("h3",null,Object(a["toDisplayString"])(e.translate("General_Comparisons")),1),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.segmentComparisons,(function(t,n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"comparison card",key:t.index},[Object(a["createElementVNode"])("div",Or,Object(a["toDisplayString"])(e.translate("General_Segment")),1),Object(a["createElementVNode"])("div",{class:"title",title:t.title+"<br/>"+decodeURIComponent(t.params.segment)},[Object(a["createElementVNode"])("a",{target:"_blank",href:e.getUrlToSegment(t.params.segment)},Object(a["toDisplayString"])(t.title),9,kr)],8,jr),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.periodComparisons,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"comparison-period",key:n.index,title:e.getComparisonTooltip(t,n)},[Object(a["createElementVNode"])("span",{class:"comparison-dot",style:Object(a["normalizeStyle"])({"background-color":e.getSeriesColor(t,n)})},null,4),Object(a["createElementVNode"])("span",Cr,Object(a["toDisplayString"])(n.title)+" ("+Object(a["toDisplayString"])(e.getComparisonPeriodType(n))+") ",1)],8,Sr)})),128)),e.segmentComparisons.length>1?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:0,class:"remove-button",onClick:function(t){return e.removeSegmentComparison(n)}},[Object(a["createElementVNode"])("span",{class:"icon icon-close",title:e.translate("General_ClickToRemoveComp")},null,8,Dr)],8,Er)):Object(a["createCommentVNode"])("",!0)])})),128)),Object(a["createElementVNode"])("div",Pr,[Object(a["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",alt:e.translate("General_LoadingData")},null,8,Vr),Object(a["createTextVNode"])(" "+Object(a["toDisplayString"])(e.translate("General_LoadingData")),1)])],512)),[[l,{duration:200,delay:200,content:e.transformTooltipContent}]]):Object(a["createCommentVNode"])("",!0)} /*! * Matomo - free/libre analytics platform * diff --git a/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts b/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts index d6ba47e865..f6734c3e56 100644 --- a/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts +++ b/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts @@ -301,6 +301,7 @@ export default class ComparisonsStore { if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation' + || matomoModule === 'Overlay' ) { this.privateState.comparisonsDisabledFor = []; return; diff --git a/plugins/Overlay/Overlay.php b/plugins/Overlay/Overlay.php index 1828dfaed5..49a389f359 100644 --- a/plugins/Overlay/Overlay.php +++ b/plugins/Overlay/Overlay.php @@ -9,6 +9,11 @@ namespace Piwik\Plugins\Overlay; +use Piwik\Common; +use Piwik\Piwik; +use Piwik\Url; +use Piwik\UrlHelper; + class Overlay extends \Piwik\Plugin { /** @@ -37,4 +42,37 @@ class Overlay extends \Piwik\Plugin $translationKeys[] = 'General_OverlayRowActionTooltipTitle'; $translationKeys[] = 'General_OverlayRowActionTooltip'; } + + /** + * Returns if a request belongs to the Overlay page + * + * Whenever we change the Overlay, or any feature that is available on that page, this list needs to be adjusted + * Otherwise it can happen, that the session cookie is sent with samesite=lax, which might break the session in Overlay + * See https://github.com/matomo-org/matomo/pull/18648 + */ + public static function isOverlayRequest($module, $action, $method, $referer) + { + $isOverlay = $module == 'Overlay'; + $referrerUrlQuery = parse_url($referer ?? '', PHP_URL_QUERY); + $referrerUrlQueryParams = UrlHelper::getArrayFromQueryString($referrerUrlQuery); + $referrerUrlHost = parse_url($referer ?? '', PHP_URL_HOST); + $comingFromOverlay = Url::isValidHost($referrerUrlHost) && !empty($referrerUrlQueryParams['module']) && $referrerUrlQueryParams['module'] === 'Overlay'; + $isPossibleOverlayRequest = ( + $module === 'Proxy' // JS & CSS requests + || ($module === 'API' && 0 === strpos($method, 'Overlay.')) // Overlay API data + || ($module === 'CoreHome' && $action === 'getRowEvolutionPopover') // Row evolution + || ($module === 'CoreHome' && $action === 'getRowEvolutionGraph') // Row evolution (graph) + || ($module === 'CoreHome' && $action === 'saveViewDataTableParameters') // store chart changes (within row evolution & transitions) + || $module === 'Annotations' // required to interact with annotations in evolution charts (within row evolution) + || ($module === 'Transitions' && $action === 'renderPopover') // Transitions + || ($module === 'API' && 0 === strpos($method, 'Transitions.')) // Transitions API data + || ($module === 'Live' && $action === 'indexVisitorLog') // Visits Log + || ($module === 'Live' && $action === 'getLastVisitsDetails') // Visits Log (pagination) + || ($module === 'Live' && $action === 'getVisitorProfilePopup') // Visitor Profile + || ($module === 'Live' && $action === 'getVisitList') // Visitor Profile (load more visits) + || ($module === 'UserCountryMap' && $action === 'realtimeMap') // Visitor Profile (map) + ); + + return $isOverlay || ($comingFromOverlay && $isPossibleOverlayRequest); + } } diff --git a/plugins/Overlay/tests/Unit/OverlayTest.php b/plugins/Overlay/tests/Unit/OverlayTest.php new file mode 100644 index 0000000000..0111f98252 --- /dev/null +++ b/plugins/Overlay/tests/Unit/OverlayTest.php @@ -0,0 +1,127 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Plugins\Overlay\tests\Unit; + +use Piwik\Plugins\Overlay\Overlay; + +class OverlayTest extends \PHPUnit\Framework\TestCase +{ + /** + * @dataProvider getOverlayRequestTestData + */ + public function testIsOverlayRequestWithValidReferredRequests($module, $action, $method) + { + $this->assertSame(true, Overlay::isOverlayRequest($module, $action, $method, 'https://demo.matomo.cloud/index.php?module=Overlay&period=month&date=today&idSite=1')); + $this->assertSame(false, Overlay::isOverlayRequest($module, $action, $method, 'https://demo.matomo.org')); + } + + public function getOverlayRequestTestData() + { + return [ + [ // CSS + 'Proxy', + 'getCss', + '', + ], + [ // JS + 'Proxy', + 'getCoreJs', + '', + ], + [ // API request + 'API', + 'index', + 'Overlay.getTranslations', + ], + [ // API request + 'API', + 'index', + 'Transitions.get', + ], + [ // Row evolution + 'CoreHome', + 'getRowEvolutionPopover', + '', + ], + [ // Row evolution + 'CoreHome', + 'getRowEvolutionGraph', + '', + ], + [ + 'CoreHome', + 'saveViewDataTableParameters', + '', + ], + [ + 'Transitions', + 'renderPopover', + '', + ], + [ + 'Live', + 'indexVisitorLog', + '', + ], + [ + 'Live', + 'getLastVisitsDetails', + '', + ], + [ + 'Live', + 'getVisitorProfilePopup', + '', + ], + [ + 'Live', + 'getVisitList', + '', + ], + [ + 'UserCountryMap', + 'realtimeMap', + '', + ], + ]; + } + + /** + * @dataProvider getInvalidOverlayRequestTestData + */ + public function testIsOverlayRequestWithiNValidReferredRequests($module, $action, $method, $referer) + { + $this->assertSame(false, Overlay::isOverlayRequest($module, $action, $method, $referer)); + } + + public function getInvalidOverlayRequestTestData() + { + return [ + [ // invalid module / action + 'Referer', + 'get', + '', + 'https://demo.matomo.cloud/index.php?module=Overlay&period=month&date=today&idSite=1' + ], + [ // invalid api method + 'API', + 'index', + 'VisitsSummary.get', + 'https://demo.matomo.cloud/index.php?module=Overlay&period=month&date=today&idSite=1' + ], + [ // invalid referer + 'API', + 'index', + 'Transitions.get', + 'https://demo.matomo.cloud/index.php?module=Overlay&module=CoreHome&action=index&period=month&date=today&idSite=1' + ], + ]; + } +}
\ No newline at end of file |