mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Merge remote-tracking branch 'origin/support/3.2' into develop
This commit is contained in:
@@ -575,6 +575,12 @@ class LogChannels
|
||||
*/
|
||||
public const DATATABLE = 'Datatable';
|
||||
|
||||
/**
|
||||
* @var string Everything related to the data integrity
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public const DATA_INTEGRITY = 'DataIntegrity';
|
||||
|
||||
public const DEADLOCK = 'DeadLock';
|
||||
/**
|
||||
* @var string Everything related to PHP sessions tracking
|
||||
|
||||
@@ -58,6 +58,9 @@ $progress-bar-error-bg-color: #F56565 !default;
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes progress_bar_color_ongoing {
|
||||
|
||||
@@ -129,6 +129,8 @@
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/ckeditor/adapters/jquery.js'|add_itop_version }}"></script>
|
||||
{# - Hilighter for code snippets created with CKEditor #}
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/ckeditor/plugins/codesnippet/lib/highlight/highlight.pack.js'|add_itop_version }}"></script>
|
||||
{# - Custom settings #}
|
||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/ckeditor.on-init.js'|add_itop_version }}"></script>
|
||||
{# Date-time picker for Bootstrap #}
|
||||
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'|add_itop_version }}"></script>
|
||||
{# Typeahead files for autocomplete #}
|
||||
|
||||
@@ -564,6 +564,9 @@
|
||||
<item id="org_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
</items>
|
||||
</default_search>
|
||||
<list>
|
||||
|
||||
@@ -575,6 +575,19 @@
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<default_search>
|
||||
<items>
|
||||
<item id="ticket_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="contact_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="role_code">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</default_search>
|
||||
<search>
|
||||
<items>
|
||||
<item id="ticket_id">
|
||||
@@ -820,6 +833,25 @@
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<default_search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="team_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="agent_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="start_date">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</default_search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="status">
|
||||
|
||||
121
setup/csp-detection.js
Normal file
121
setup/csp-detection.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Detects the current server's Content-Security-Policy to stop the setup if any directive doesn't meet the application's requirements
|
||||
*
|
||||
* @type {{_FindItopVersionInURI: (function(): string|string), aFlags: {bUnsafeInlineScriptOk: boolean, bUnsafeEvalScriptOk: boolean, bUnsafeInlineStyleOk: boolean}, _TestUnsafeEvalScript: SetupCSPDetection._TestUnsafeEvalScript, _HideContinueButtonIfPolicyNotOk: SetupCSPDetection._HideContinueButtonIfPolicyNotOk, _TestUnsafeInlineStyle: SetupCSPDetection._TestUnsafeInlineStyle, Run: SetupCSPDetection.Run, _TestUnSafeInlineScript: SetupCSPDetection._TestUnSafeInlineScript, _AddErrorAlert: SetupCSPDetection._AddErrorAlert}}
|
||||
* @since 2.7.11 3.0.5 3.1.2 3.2.0 N°7075
|
||||
*/
|
||||
SetupCSPDetection = {
|
||||
aFlags: {
|
||||
bUnsafeInlineScriptOk: false,
|
||||
bUnsafeEvalScriptOk: false,
|
||||
bUnsafeInlineStyleOk: false,
|
||||
},
|
||||
Run: function () {
|
||||
this._TestUnSafeInlineScript();
|
||||
this._TestUnsafeEvalScript();
|
||||
this._TestUnsafeInlineStyle();
|
||||
this._HideContinueButtonIfPolicyNotOk();
|
||||
},
|
||||
/**
|
||||
* Test if the CSP "unsafe-inline" directive for script-src if enabled, otherwise it forbids the setup to go further
|
||||
* @private
|
||||
*/
|
||||
_TestUnSafeInlineScript: function() {
|
||||
var sBaitElemID = "csp-detection--unsafe-inline-script-bait";
|
||||
|
||||
// Add inline script that should add an element in the DOM
|
||||
var sAddedScript = '<script>$("body").append(\'<div id="' + sBaitElemID + '" class="ibo-is-hidden">If this is present in the DOM, then unsafe-inline for scripts policy is allowed</div>\')</script>';
|
||||
$("body").append(sAddedScript);
|
||||
|
||||
// Check if element has been added to the DOM
|
||||
if ($("#" + sBaitElemID).length === 1) {
|
||||
this.aFlags.bUnsafeInlineScriptOk = true;
|
||||
} else {
|
||||
this._AddErrorAlert("unsafe-inline", "script");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Test if the CSP "unsafe-eval" directive for script-src if enabled, otherwise it forbids the setup to go further
|
||||
* @private
|
||||
*/
|
||||
_TestUnsafeEvalScript: function() {
|
||||
var sBaitElemID = "csp-detection--unsafe-eval-script-bait";
|
||||
|
||||
// Add inline eval script that should add an element in the DOM
|
||||
var sAddedScript = '<script>eval(\'$("body").append(\\\'<div id="' + sBaitElemID + '" class="ibo-is-hidden">If this is present in the DOM, then unsafe-eval for scripts policy is allowed</div>\\\')\')</script>';
|
||||
$("body").append(sAddedScript);
|
||||
|
||||
// Check if element has been added to the DOM
|
||||
if ($("#" + sBaitElemID).length === 1) {
|
||||
this.aFlags.bUnsafeEvalScriptOk = true;
|
||||
} else {
|
||||
this._AddErrorAlert("unsafe-eval", "script");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Test if the CSP "unsafe-inline" directive for style-src if enabled, otherwise it forbids the setup to go further
|
||||
* @private
|
||||
*/
|
||||
_TestUnsafeInlineStyle: function() {
|
||||
var sBaitElemID = "csp-detection--unsafe-inline-style-bait";
|
||||
|
||||
// Add inline eval script that should add an element in the DOM
|
||||
$("body").append("<div id=\"" + sBaitElemID + "\">If this is present in the DOM and visible, then unsafe-inline for styles policy must be allowed</div>");
|
||||
$("body").append("<style>#" + sBaitElemID + " { display: none; }</style>");
|
||||
|
||||
// Check if style has been applied
|
||||
if ($("#" + sBaitElemID).is(":visible") === false) {
|
||||
this.aFlags.bUnsafeInlineStyleOk = true;
|
||||
} else {
|
||||
// Remove bait div to avoid polluting the screen
|
||||
$("#" + sBaitElemID).remove();
|
||||
this._AddErrorAlert("unsafe-inline", "style");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Hide continue button to prevent setup from going further if any policy is not OK
|
||||
* @private
|
||||
*/
|
||||
_HideContinueButtonIfPolicyNotOk: function() {
|
||||
if (false === this.aFlags.bUnsafeInlineScriptOk || false === this.aFlags.bUnsafeEvalScriptOk || false === this.aFlags.bUnsafeInlineStyleOk) {
|
||||
// Hide next button to prevent user from going forward.
|
||||
// Note that we don't remove it completely to be able to by-pass it.
|
||||
$("#btn_next").addClass("ibo-is-hidden");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Internal helper to add an error alert in case of failure
|
||||
* @param {String} sPolicyOption e.g. "unsafe-inline", "unsafe-eval", ...
|
||||
* @param {String} sResourceType script|style
|
||||
* @private
|
||||
*/
|
||||
_AddErrorAlert: function(sPolicyOption, sResourceType) {
|
||||
var sFilesType = sResourceType === "script" ? "scripts" : "styles";
|
||||
|
||||
// Add alert in the DOM
|
||||
$("<div class=\"message message-error\"><span class=\"message-title\">Error:</span>Your server Content-Security-Policy header doesn't allow <b>" + sPolicyOption + " " + sFilesType + "</b>. Therefore, the application cannot be installed (<a" +
|
||||
" href=\"https://www.itophub.io/wiki/page?id=" + this._FindItopVersionInURI() + ":install:security#content-security-policy\" target=\"_blank\">see documentation</a>).</div>")
|
||||
.insertAfter(
|
||||
$("#wiz_form h1:first")
|
||||
);
|
||||
|
||||
},
|
||||
/**
|
||||
* Internal helper to find the iTop version as wiki syntax from the script URI
|
||||
* @returns {string|string}
|
||||
* @private
|
||||
*/
|
||||
_FindItopVersionInURI: function() {
|
||||
// First find script tag for the current file
|
||||
var sScriptURI = $('script[src*="setup/csp-detection.js"]').attr("src");
|
||||
|
||||
// Extract parameter value from URI
|
||||
var regex = new RegExp('[\\?&]' + 'itop_version_wiki_syntax' + '=([^&#]*)');
|
||||
var results = regex.exec(sScriptURI);
|
||||
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
SetupCSPDetection.Run();
|
||||
});
|
||||
@@ -43,6 +43,7 @@ class SetupPage extends NiceWebPage
|
||||
$this->LinkScriptFromAppRoot('node_modules/@popperjs/core/dist/umd/popper.js');
|
||||
$this->LinkScriptFromAppRoot('node_modules/tippy.js/dist/tippy-bundle.umd.js');
|
||||
$this->LinkScriptFromAppRoot("setup/setup.js");
|
||||
$this->LinkScriptFromAppRoot("setup/csp-detection.js?itop_version_wiki_syntax=" . utils::GetItopVersionWikiSyntax());
|
||||
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
|
||||
$this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
|
||||
$this->LinkStylesheetFromAppRoot('node_modules/tippy.js/dist/tippy.css');
|
||||
|
||||
@@ -544,7 +544,9 @@ class WebPage implements Page
|
||||
return;
|
||||
}
|
||||
|
||||
if (false === utils::RealPath(APPROOT . $sFileRelPath, APPROOT)) {
|
||||
// Ensure file is within the app folder
|
||||
$sFileRelPathWithoutQueryParams = explode("?", $sFileRelPath)[0];
|
||||
if (false === utils::RealPath(APPROOT . $sFileRelPathWithoutQueryParams, APPROOT)) {
|
||||
IssueLog::Warning("Linked resource added to page with a path from outside app directory, it will be ignored.", LogChannels::CONSOLE, [
|
||||
"linked_resource_uri" => $sFileRelPath,
|
||||
"request_uri" => $_SERVER['REQUEST_URI'] ?? '' /* CLI */,
|
||||
@@ -580,7 +582,9 @@ class WebPage implements Page
|
||||
return;
|
||||
}
|
||||
|
||||
$sFileAbsPath = MODULESROOT . $sFileRelPath;
|
||||
// Ensure file is within the app folder
|
||||
$sFileRelPathWithoutQueryParams = explode("?", $sFileRelPath)[0];
|
||||
$sFileAbsPath = MODULESROOT . $sFileRelPathWithoutQueryParams;
|
||||
// For modules only, we don't check real path if symlink as the file would not be in under MODULESROOT
|
||||
if (false === is_link($sFileAbsPath) && false === utils::RealPath($sFileAbsPath, MODULESROOT)) {
|
||||
IssueLog::Warning("Linked resource added to page with a path from outside current env. directory, it will be ignored.", LogChannels::CONSOLE, [
|
||||
|
||||
@@ -58,6 +58,11 @@ class WebPageTest extends ItopDataTestCase
|
||||
"js/utils.js",
|
||||
1,
|
||||
],
|
||||
"LinkScriptFromAppRoot: Relative URI of existing file with query params should be completed / added" => [
|
||||
"LinkScriptFromAppRoot",
|
||||
"js/utils.js?foo=bar",
|
||||
1,
|
||||
],
|
||||
"LinkScriptFromAppRoot: Relative URI of NON existing file should be ignored" => [
|
||||
"LinkScriptFromAppRoot",
|
||||
"js/some-file.js",
|
||||
@@ -80,6 +85,11 @@ class WebPageTest extends ItopDataTestCase
|
||||
"itop-portal-base/portal/public/js/toolbox.js",
|
||||
1,
|
||||
],
|
||||
"LinkScriptFromModule: Relative URI of existing file with query params should be completed / added" => [
|
||||
"LinkScriptFromModule",
|
||||
"itop-portal-base/portal/public/js/toolbox.js?foo=bar",
|
||||
1,
|
||||
],
|
||||
"LinkScriptFromModule: Relative URI of NON existing file should be completed / added" => [
|
||||
"LinkScriptFromModule",
|
||||
"some-module/asset/js/some-file.js",
|
||||
@@ -107,6 +117,11 @@ class WebPageTest extends ItopDataTestCase
|
||||
"https://external.server/file.js",
|
||||
1,
|
||||
],
|
||||
"LinkScriptFromURI: Absolute URI with query params should be added" => [
|
||||
"LinkScriptFromURI",
|
||||
"https://external.server/file.js?foo=bar",
|
||||
1,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -148,6 +163,11 @@ class WebPageTest extends ItopDataTestCase
|
||||
"css/login.css",
|
||||
1,
|
||||
],
|
||||
"LinkStylesheetFromAppRoot: Relative URI of existing file with query params should be completed / added" => [
|
||||
"LinkStylesheetFromAppRoot",
|
||||
"css/login.css?foo=bar",
|
||||
1,
|
||||
],
|
||||
"LinkStylesheetFromAppRoot: Relative URI of NON existing file should be ignored" => [
|
||||
"LinkStylesheetFromAppRoot",
|
||||
"css/some-file.css",
|
||||
@@ -170,6 +190,11 @@ class WebPageTest extends ItopDataTestCase
|
||||
"itop-portal-base/portal/public/css/portal.css",
|
||||
1,
|
||||
],
|
||||
"LinkStylesheetFromModule: Relative URI of existing file with query params should be completed / added" => [
|
||||
"LinkStylesheetFromModule",
|
||||
"itop-portal-base/portal/public/css/portal.css?foo=bar",
|
||||
1,
|
||||
],
|
||||
"LinkStylesheetFromModule: Relative URI of NON existing file should be completed / added" => [
|
||||
"LinkStylesheetFromModule",
|
||||
"some-module/asset/js/some-file.js",
|
||||
@@ -197,6 +222,11 @@ class WebPageTest extends ItopDataTestCase
|
||||
"https://external.server/file.css",
|
||||
1,
|
||||
],
|
||||
"LinkStylesheetFromURI: Absolute URI with query params should be added" => [
|
||||
"LinkStylesheetFromURI",
|
||||
"https://external.server/file.css?foo=bar",
|
||||
1,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user