mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-04 00:24:14 +01:00
Compare commits
11 Commits
feature/86
...
issue/8543
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2067940a37 | ||
|
|
685373c60a | ||
|
|
f82389d156 | ||
|
|
f558093f5d | ||
|
|
5201a1ed3b | ||
|
|
29920bfeb7 | ||
|
|
aede5ea7b8 | ||
|
|
da6c443a35 | ||
|
|
9c39efd9af | ||
|
|
d5f2303ed2 | ||
|
|
48e584503e |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -58,6 +58,9 @@ tests/*/vendor/*
|
||||
/tests/php-unit-tests/phpunit.xml
|
||||
/tests/php-unit-tests/postbuild_integration.xml
|
||||
|
||||
# PHP CS Fixer: Cache file
|
||||
/.php-cs-fixer.cache
|
||||
|
||||
|
||||
# Jetbrains
|
||||
/.idea/**
|
||||
|
||||
@@ -181,6 +181,9 @@ class utils
|
||||
|
||||
protected static function LoadParamFile($sParamFile)
|
||||
{
|
||||
if (utils::RealPath($sParamFile, APPROOT) !== false) {
|
||||
throw new Exception("File '".utils::HtmlEntities($sParamFile)."' should be outside iTop");
|
||||
}
|
||||
if (!file_exists($sParamFile)) {
|
||||
throw new Exception("Could not find the parameter file: '".utils::HtmlEntities($sParamFile)."'");
|
||||
}
|
||||
|
||||
@@ -1738,6 +1738,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'security.force_login_when_no_execution_policy' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true, when no execution policy is defined, the user will be forced to log in (instead of being automatically logged in with the default profile)',
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'behind_reverse_proxy' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true, then proxies custom header (X-Forwarded-*) are taken into account. Use only if the webserver is not publicly accessible (reachable only by the reverse proxy)',
|
||||
|
||||
@@ -59,7 +59,7 @@ class DBUnionSearch extends DBSearch
|
||||
public function AllowAllData($bAllowAllData = true)
|
||||
{
|
||||
foreach ($this->aSearches as $oSearch) {
|
||||
$oSearch->AllowAllData();
|
||||
$oSearch->AllowAllData($bAllowAllData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -362,8 +362,7 @@ class ormDocument
|
||||
throw new Exception("Invalid id ($id) for class '$sClass' - the object does not exist or you are not allowed to view it");
|
||||
}
|
||||
}
|
||||
if (($sSecretField != null) && ($oObj->Get($sSecretField) != $sSecretValue)) {
|
||||
usleep(200);
|
||||
if (($sSecretField != null) && !hash_equals($oObj->Get($sSecretField), $sSecretValue)) {
|
||||
throw new Exception("Invalid secret for class '$sClass' - the object does not exist or you are not allowed to view it");
|
||||
}
|
||||
/** @var \ormDocument $oDocument */
|
||||
|
||||
@@ -72,9 +72,12 @@ $ibo-panel--icon--spacing--as-medallion--is-sticking: $ibo-panel--icon--spacing-
|
||||
$ibo-panel--icon--bottom--as-medallion--is-sticking: -12px !default;
|
||||
$ibo-panel--icon--border--as-medallion--is-sticking: 1px $ibo-panel--base-border-style $ibo-panel--base-border-color !default;
|
||||
|
||||
$ibo-panel--icon-background--size--must-contain: contain !default;
|
||||
$ibo-panel--icon-background--size--must-cover: cover !default;
|
||||
$ibo-panel--icon-background--size--must-zoomout: 66.67% !default;
|
||||
$ibo-panel--icon-background--size--must-contain: contain !default; // deprecated, to be removed in favor of $ibo-panel--icon-img--size--must-contain
|
||||
$ibo-panel--icon-background--size--must-cover: cover !default; // deprecated, to be removed in favor of $ibo-panel--icon-img--size--must-cover
|
||||
$ibo-panel--icon-background--size--must-zoomout: 66.67% !default; // deprecated, to be removed in favor of $ibo-panel--icon-img--size--must-zoomout
|
||||
$ibo-panel--icon-img--size--must-contain: $ibo-panel--icon-background--size--must-contain !default; // TODO remove when dealing with N°9317
|
||||
$ibo-panel--icon-img--size--must-cover: $ibo-panel--icon-background--size--must-cover !default; // TODO remove when dealing with N°9317
|
||||
$ibo-panel--icon-img--size--must-zoomout: $ibo-panel--icon-background--size--must-zoomout !default; // TODO remove when dealing with N°9317
|
||||
|
||||
$ibo-panel--title--font-size--is-sticking: $ibo-font-size-150 !default;
|
||||
$ibo-panel--title--color: $ibo-color-grey-900 !default;
|
||||
@@ -179,24 +182,25 @@ $ibo-panel--is-selectable--body--after--font-size: $ibo-font-size-700 !default;
|
||||
min-height: $ibo-panel--icon--size;
|
||||
}
|
||||
|
||||
.ibo-panel--icon-background {
|
||||
.ibo-panel--icon-img, .ibo-panel--icon-background { // second class is deprecated, remove it when dealing with N°9317
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: $ibo-panel--icon-background--size--must-contain;
|
||||
background-size: $ibo-panel--icon-img--size--must-contain;
|
||||
}
|
||||
|
||||
.ibo-panel--icon-background--must-contain {
|
||||
background-size: $ibo-panel--icon-background--size--must-contain;
|
||||
.ibo-panel--icon-img--must-contain, .ibo-panel--icon-background--must-contain { // second class is deprecated, remove it when dealing with N°9317
|
||||
background-size: $ibo-panel--icon-img--size--must-contain;
|
||||
}
|
||||
|
||||
.ibo-panel--icon-background--must-cover {
|
||||
background-size: $ibo-panel--icon-background--size--must-cover;
|
||||
.ibo-panel--icon-img--must-cover, .ibo-panel--icon-background--must-cover { // second class is deprecated, remove it when dealing with N°9317
|
||||
background-size: $ibo-panel--icon-img--size--must-cover;
|
||||
}
|
||||
|
||||
.ibo-panel--icon-background--must-zoomout {
|
||||
background-size: $ibo-panel--icon-background--size--must-zoomout;
|
||||
.ibo-panel--icon-img--must-zoomout, .ibo-panel--icon-background--must-zoomout { // second class is deprecated, remove it when dealing with N°9317
|
||||
width: $ibo-panel--icon-img--size--must-zoomout;
|
||||
height: $ibo-panel--icon-img--size--must-zoomout;
|
||||
}
|
||||
|
||||
.ibo-panel--title {
|
||||
|
||||
@@ -11,9 +11,12 @@ $ibo-title--icon--size: 90px !default;
|
||||
$ibo-title--icon--size-2: 80px !default;
|
||||
$ibo-title--icon--size-3: 70px !default;
|
||||
|
||||
$ibo-title--icon-background--size--must-contain: contain !default;
|
||||
$ibo-title--icon-background--size--must-cover: cover !default;
|
||||
$ibo-title--icon-background--size--must-zoomout: 66.67% !default;
|
||||
$ibo-title--icon-background--size--must-contain: contain !default; // deprecated, to be removed in favor of $ibo-title--icon-img--size--must-contain
|
||||
$ibo-title--icon-background--size--must-cover: cover !default; // deprecated, to be removed in favor of $ibo-title--icon-img--size--must-cover
|
||||
$ibo-title--icon-background--size--must-zoomout: 66.67% !default; // deprecated, to be removed in favor of $ibo-title--icon-img--size--must-zoomout
|
||||
$ibo-title--icon-img--size--must-contain: $ibo-title--icon-background--size--must-contain !default; // TODO remove when dealing with N°9317
|
||||
$ibo-title--icon-img--size--must-cover: $ibo-title--icon-background--size--must-cover !default; // TODO remove when dealing with N°9317
|
||||
$ibo-title--icon-img--size--must-zoomout: $ibo-title--icon-background--size--must-zoomout !default; // TODO remove when dealing with N°9317
|
||||
|
||||
|
||||
.ibo-title {
|
||||
@@ -44,24 +47,23 @@ $ibo-title--icon-background--size--must-zoomout: 66.67% !default;
|
||||
min-height: $ibo-title--icon--size-3;
|
||||
}
|
||||
|
||||
.ibo-title--icon-background {
|
||||
.ibo-title--icon-img, .ibo-title--icon-background { // second class is deprecated, remove it when dealing with N°9317
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: $ibo-title--icon-background--size--must-contain;
|
||||
object-position: center;
|
||||
background-size: $ibo-title--icon-img--size--must-contain;
|
||||
}
|
||||
|
||||
.ibo-title--icon-background--must-contain {
|
||||
background-size: $ibo-title--icon-background--size--must-contain;
|
||||
.ibo-title--icon-img--must-contain, .ibo-title--icon-background--must-contain { // second class is deprecated, remove it when dealing with N°9317
|
||||
background-size: $ibo-title--icon-img--size--must-contain;
|
||||
}
|
||||
|
||||
.ibo-title--icon-background--must-cover {
|
||||
background-size: $ibo-title--icon-background--size--must-cover;
|
||||
.ibo-title--icon-img--must-cover, .ibo-title--icon-background--must-cover { // second class is deprecated, remove it when dealing with N°9317
|
||||
background-size: $ibo-title--icon-img--size--must-cover;
|
||||
}
|
||||
|
||||
.ibo-title--icon-background--must-zoomout {
|
||||
background-size: $ibo-title--icon-background--size--must-zoomout;
|
||||
.ibo-title--icon-img--must-zoomout, .ibo-title--icon-background--must-zoomout { // second class is deprecated, remove it when dealing with N°9317
|
||||
background-size: $ibo-title--icon-img--size--must-zoomout;
|
||||
}
|
||||
|
||||
.ibo-title--for-object-details {
|
||||
|
||||
@@ -199,15 +199,15 @@ function RaiseAlarm($sMessage)
|
||||
//////////
|
||||
// Main
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
echo "Error: ".$e->GetMessage()."\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
if (utils::IsModeCLI()) {
|
||||
SetupUtils::CheckPhpAndExtensionsForCli(new CLIPage('Check backup utility'));
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
echo 'Error: '.$e->GetMessage()."\n";
|
||||
exit;
|
||||
}
|
||||
$oP = new CLIPage('Check backup utility');
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP);
|
||||
|
||||
echo date('Y-m-d H:i:s')." - running check-backup utility\n";
|
||||
try {
|
||||
|
||||
@@ -88,16 +88,15 @@ if (utils::IsModeCLI()) {
|
||||
$oP = new CLIPage(GetOperationName());
|
||||
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP);
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
ExitError($oP, $e->GetMessage());
|
||||
}
|
||||
} else {
|
||||
$oP = new WebPage(GetOperationName());
|
||||
}
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
ExitError($oP, $e->GetMessage());
|
||||
}
|
||||
|
||||
ExecuteMainOperation($oP);
|
||||
|
||||
$oP->output();
|
||||
|
||||
@@ -2140,7 +2140,7 @@ EOF
|
||||
$oAttachment->Set('item_class', $sObjClass);
|
||||
$oAttachment->SetDefaultOrgId();
|
||||
$oAttachment->Set('contents', $oDoc);
|
||||
$oAttachment->Set('secret', sprintf('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess
|
||||
$oAttachment->Set('secret', bin2hex(random_bytes(16))); // 128 bits of entropy, cryptographically secure
|
||||
$iAttId = $oAttachment->DBInsert();
|
||||
|
||||
$aResult['uploaded'] = 1;
|
||||
@@ -2198,7 +2198,7 @@ EOF
|
||||
$oAttachment->Set('item_class', $sObjClass);
|
||||
$oAttachment->SetDefaultOrgId();
|
||||
$oAttachment->Set('contents', $oDoc);
|
||||
$oAttachment->Set('secret', sprintf('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess
|
||||
$oAttachment->Set('secret', bin2hex(random_bytes(16))); // 128 bits of entropy, cryptographically secure
|
||||
$iAttId = $oAttachment->DBInsert();
|
||||
|
||||
IssueLog::Trace('InlineImage created', LogChannels::INLINE_IMAGE, [
|
||||
|
||||
@@ -97,4 +97,29 @@ if ($sTargetPage === false) {
|
||||
//
|
||||
// GO!
|
||||
//
|
||||
// check module white list
|
||||
// check conf param
|
||||
// force login if needed
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
$aModuleDelegatedExecutionPolicy = GetModuleDelegatedExecutionPolicy($sModule);
|
||||
if (is_null($aModuleDelegatedExecutionPolicy) || !in_array($sPage, $aModuleDelegatedExecutionPolicy)) {
|
||||
$bForceLoginWhenNoExecutionPolicy = MetaModel::GetConfig()->Get('security.force_login_when_no_execution_policy');
|
||||
// TODO in N°9343 : remove the conf and this 'if' condition to perform login by default when no execution policy is defined
|
||||
LoginWebPage::DoLoginEx();
|
||||
}
|
||||
if (is_array($aModuleDelegatedExecutionPolicy) && !in_array($sPage, $aModuleDelegatedExecutionPolicy)) {
|
||||
// if module defined a delegated execution policy but not for the current page, we consider that the page is not allowed to be executed without login
|
||||
LoginWebPage::DoLoginEx();
|
||||
}
|
||||
|
||||
require_once($sTargetPage);
|
||||
|
||||
function GetModuleDelegatedExecutionPolicy(string $sModuleName): ?array
|
||||
{
|
||||
$sModuleFile = APPROOT.'/env-'.utils::GetCurrentEnvironment().'/'.$sModuleName.'/module.'.$sModuleName.'.php';
|
||||
|
||||
$oExtensionMap = new iTopExtensionsMap();
|
||||
$aModuleParam = $oExtensionMap->GetModuleInfo($sModuleFile)[2];
|
||||
return $aModuleParam['execution_policy'] ?? null;
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ class iTopExtensionsMap
|
||||
* @param string $sModuleFile
|
||||
* @return array
|
||||
*/
|
||||
protected function GetModuleInfo($sModuleFile)
|
||||
public function GetModuleInfo($sModuleFile)
|
||||
{
|
||||
static $iDummyClassIndex = 0;
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
|
||||
protected $aDeferredBlocks;
|
||||
/** @var bool If set to true, the content block will have a surrounding <div> no matter its options / CSS classes / ... */
|
||||
protected $bHasForcedDiv;
|
||||
/** @var bool if set to true, the icon will be lazy loaded
|
||||
* @since 3.2.3
|
||||
*/
|
||||
protected bool $bHasLazyLoadIcon;
|
||||
|
||||
/**
|
||||
* UIContentBlock constructor.
|
||||
@@ -48,6 +52,7 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
|
||||
$this->aSubBlocks = [];
|
||||
$this->aDeferredBlocks = [];
|
||||
$this->bHasForcedDiv = false;
|
||||
$this->bHasLazyLoadIcon = false;
|
||||
$this->SetCSSClasses($aContainerClasses);
|
||||
}
|
||||
|
||||
@@ -220,4 +225,24 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
|
||||
$this->bHasForcedDiv = $bHasForcedDiv;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$bHasLazyLoadIcon
|
||||
* @return bool
|
||||
*/
|
||||
public function HasLazyLoadIcon(): bool
|
||||
{
|
||||
return $this->bHasLazyLoadIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$bHasLazyLoadIcon
|
||||
* @param bool $bLazyLoadIcon
|
||||
* @return $this
|
||||
*/
|
||||
public function SetHasLazyLoadIcon(bool $bLazyLoadIcon)
|
||||
{
|
||||
$this->bHasLazyLoadIcon = $bLazyLoadIcon;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,11 @@ use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\Application\TwigBase\Controller\Controller;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\Button;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\Toggler;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\Panel;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
|
||||
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuItem\PopoverMenuItemFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary;
|
||||
@@ -29,13 +26,10 @@ use CoreException;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use Dict;
|
||||
use JSPopupMenuItem;
|
||||
use MetaModel;
|
||||
use SecurityException;
|
||||
use URLPopupMenuItem;
|
||||
use UserRights;
|
||||
use utils;
|
||||
use appUserPreferences;
|
||||
|
||||
/**
|
||||
* Class iTopNewsroomController
|
||||
@@ -376,6 +370,7 @@ JS
|
||||
$sReadColor = $oEvent->Get('read') === 'no' ? 'ibo-notifications--view-all--item--unread' : 'ibo-notifications--view-all--item--read';
|
||||
$sReadLabel = $oEvent->Get('read') === 'no' ? Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Unread:Label') : Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Read:Label');
|
||||
$oEventBlock = new ObjectSummary($oEvent);
|
||||
$oEventBlock->SetHasLazyLoadIcon(true);
|
||||
$oEventBlock->SetCSSColorClass($sReadColor);
|
||||
$oEventBlock->SetSubTitle($sReadLabel);
|
||||
$oEventBlock->SetClassLabel('');
|
||||
|
||||
@@ -67,18 +67,18 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
|
||||
if (utils::IsModeCLI()) {
|
||||
$oP = new CLIPage(Dict::S("TitleSynchroExecution"));
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP, -2);
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
$oP->p('Error: '.$e->GetMessage());
|
||||
$oP->output();
|
||||
exit - 2;
|
||||
}
|
||||
} else {
|
||||
$oP = new WebPage(Dict::S("TitleSynchroExecution"));
|
||||
}
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
$oP->p("Error: ".$e->GetMessage());
|
||||
$oP->output();
|
||||
exit -2;
|
||||
}
|
||||
|
||||
if (utils::IsModeCLI()) {
|
||||
$sAuthUser = ReadMandatoryParam($oP, 'auth_user', 'raw_data');
|
||||
$sAuthPwd = ReadMandatoryParam($oP, 'auth_pwd', 'raw_data');
|
||||
|
||||
@@ -224,18 +224,18 @@ function ChangeDateFormat($sProposedDate, $sFormat, $bDateOnly)
|
||||
if (utils::IsModeCLI()) {
|
||||
$oP = new CLIPage(Dict::S('TitleSynchroExecution'));
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP, -2);
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
$oP->p('Error: '.$e->GetMessage());
|
||||
$oP->output();
|
||||
exit - 2;
|
||||
}
|
||||
} else {
|
||||
$oP = new CLILikeWebPage(Dict::S('TitleSynchroExecution'));
|
||||
}
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
$oP->p("Error: ".$e->GetMessage());
|
||||
$oP->output();
|
||||
exit -2;
|
||||
}
|
||||
|
||||
if (utils::IsModeCLI()) {
|
||||
// Next steps:
|
||||
// specific arguments: 'csvfile'
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
{% if oUIBlock.HasIcon() %}
|
||||
<div class="ibo-panel--icon" data-role="ibo-panel--icon">
|
||||
{% block iboPanelIcon %}
|
||||
<div class="ibo-panel--icon-background ibo-panel--icon-background--must-{{ oUIBlock.GetIconCoverMethod() }}" data-role="ibo-panel--icon-background" style="background-image: url('{{ oUIBlock.GetIconUrl()|raw }}');"></div>
|
||||
<img class="ibo-panel--icon-background ibo-panel--icon-img--must-{{ oUIBlock.GetIconCoverMethod() }}
|
||||
ibo-panel--icon-background--must-{{ oUIBlock.GetIconCoverMethod() }}"
|
||||
{% if oUIBlock.HasLazyLoadIcon %} loading="lazy" {% endif %}
|
||||
data-role="ibo-panel--icon-img" src="{{ oUIBlock.GetIconUrl()|raw }}" alt="" aria-hidden="true">
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
|
||||
class LoginWebPageTest extends ItopDataTestCase
|
||||
{
|
||||
public const USE_TRANSACTION = false;
|
||||
|
||||
public const PASSWORD = 'a209320P!ù;ralùqpi,pàcqi"nr';
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->BackupConfiguration();
|
||||
$sFolderPath = APPROOT.'env-production/extension-with-execution-policy';
|
||||
if (file_exists($sFolderPath)) {
|
||||
throw new Exception("Folder $sFolderPath already exists, please remove it before running the test");
|
||||
}
|
||||
mkdir($sFolderPath);
|
||||
$this->RecurseCopy(__DIR__.'/extension-with-execution-policy', $sFolderPath);
|
||||
|
||||
$sFolderPath = APPROOT.'env-production/extension-without-execution-policy';
|
||||
if (file_exists($sFolderPath)) {
|
||||
throw new Exception("Folder $sFolderPath already exists, please remove it before running the test");
|
||||
}
|
||||
mkdir($sFolderPath);
|
||||
$this->RecurseCopy(__DIR__.'/extension-without-execution-policy', $sFolderPath);
|
||||
}
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
$sFolderPath = APPROOT.'env-production/extension-with-execution-policy';
|
||||
if (file_exists($sFolderPath)) {
|
||||
$this->RecurseRmdir($sFolderPath);
|
||||
} else {
|
||||
throw new Exception("Folder $sFolderPath does not exist, it should have been created in setUp");
|
||||
}
|
||||
$sFolderPath = APPROOT.'env-production/extension-without-execution-policy';
|
||||
if (file_exists($sFolderPath)) {
|
||||
$this->RecurseRmdir($sFolderPath);
|
||||
} else {
|
||||
throw new Exception("Folder $sFolderPath does not exist, it should have been created in setUp");
|
||||
}
|
||||
}
|
||||
|
||||
protected function GivenConfigFileAllowedLoginTypes($aAllowedLoginTypes): void
|
||||
{
|
||||
@chmod(MetaModel::GetConfig()->GetLoadedFile(), 0770);
|
||||
MetaModel::GetConfig()->SetAllowedLoginTypes($aAllowedLoginTypes);
|
||||
MetaModel::GetConfig()->WriteToFile();
|
||||
@chmod(MetaModel::GetConfig()->GetLoadedFile(), 0444);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testInExecutionPolicyFile()
|
||||
{
|
||||
// generate random login
|
||||
$sUserLogin = 'user-'.date('YmdHis');
|
||||
$this->CreateUser($sUserLogin, self::$aURP_Profiles['Administrator'], self::PASSWORD);
|
||||
$this->GivenConfigFileAllowedLoginTypes(explode('|', 'form'));
|
||||
|
||||
$sPageContent = $this->CallItopUri(
|
||||
"pages/exec.php?exec_module=extension-with-execution-policy&exec_page=src/Controller/CheckAnything.php",
|
||||
[
|
||||
'auth_user' => $sUserLogin,
|
||||
'auth_pwd' => self::PASSWORD,
|
||||
],
|
||||
[],
|
||||
true
|
||||
);
|
||||
|
||||
$this->assertStringNotContainsString('<title>iTop login</title>', $sPageContent); // in execution policy file (in the module), login should not be proposed, file handle its own policy
|
||||
}
|
||||
|
||||
public function testNotInExecutionPolicyFileWithForceLoginConf()
|
||||
{
|
||||
MetaModel::GetConfig()->Set('security.force_login_when_no_execution_policy', true);
|
||||
|
||||
$sPageContent = $this->CallItopUri(
|
||||
"pages/exec.php?exec_module=extension-with-execution-policy&exec_page=src/Controller/AnotherFile.php",
|
||||
);
|
||||
|
||||
$this->assertStringContainsString('<title>iTop login</title>', $sPageContent); // if itop is configured to force login when no execution policy, then login should be proposed since file is not in execution policy file
|
||||
}
|
||||
|
||||
public function testNotInExecutionPolicyFileWithoutForceLoginConf()
|
||||
{
|
||||
$sPageContent = $this->CallItopUri(
|
||||
"pages/exec.php?exec_module=extension-with-execution-policy&exec_page=src/Controller/AnotherFile.php",
|
||||
);
|
||||
|
||||
$this->assertStringNotContainsString('<title>iTop login</title>', $sPageContent); // by default (until N°9343) if no execution policy is defined, login is not forced
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'extension-with-execution-policy/0.0.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Templates foundation',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => [],
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
'installer' => 'TemplatesBaseInstaller',
|
||||
|
||||
// Security
|
||||
'execution_policy' => [
|
||||
'src/Controller/CheckAnything.php',
|
||||
],
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => [
|
||||
'model.templates-base.php',
|
||||
],
|
||||
'webservice' => [],
|
||||
'data.struct' => [// add your 'structure' definition XML files here,
|
||||
],
|
||||
'data.sample' => [// add your sample data XML files here,
|
||||
],
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => [
|
||||
// Select where, in the main UI, the extra data should be displayed:
|
||||
// tab (dedicated tab)
|
||||
// properties (right after the properties, but before the log if any)
|
||||
// none (extra data accessed only by programs)
|
||||
'view_extra_data' => 'relations',
|
||||
],
|
||||
]
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'Yo !';
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'Yo !';
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'extension-without-execution-policy/0.0.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Templates foundation',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => [],
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
'installer' => 'TemplatesBaseInstaller',
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => [
|
||||
'model.templates-base.php',
|
||||
],
|
||||
'webservice' => [],
|
||||
'data.struct' => [// add your 'structure' definition XML files here,
|
||||
],
|
||||
'data.sample' => [// add your sample data XML files here,
|
||||
],
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => [
|
||||
// Select where, in the main UI, the extra data should be displayed:
|
||||
// tab (dedicated tab)
|
||||
// properties (right after the properties, but before the log if any)
|
||||
// none (extra data accessed only by programs)
|
||||
'view_extra_data' => 'relations',
|
||||
],
|
||||
]
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'Yo !';
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'Yo !';
|
||||
@@ -123,7 +123,7 @@ abstract class ItopDataTestCase extends ItopTestCase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
\IssueLog::Error($this->getName());
|
||||
\IssueLog::Info("Running phpunit test: ".$this->getName());
|
||||
|
||||
$this->PrepareEnvironment();
|
||||
|
||||
@@ -1446,9 +1446,6 @@ abstract class ItopDataTestCase extends ItopTestCase
|
||||
{
|
||||
$sConfigPath = MetaModel::GetConfig()->GetLoadedFile();
|
||||
clearstatcache();
|
||||
echo sprintf("rights via ls on %s:\n %s \n", $sConfigPath, exec("ls -al $sConfigPath"));
|
||||
$sFilePermOutput = substr(sprintf('%o', fileperms('/etc/passwd')), -4);
|
||||
echo sprintf("rights via fileperms on %s:\n %s \n", $sConfigPath, $sFilePermOutput);
|
||||
|
||||
$this->sConfigTmpBackupFile = tempnam(sys_get_temp_dir(), "config_");
|
||||
MetaModel::GetConfig()->WriteToFile($this->sConfigTmpBackupFile);
|
||||
|
||||
@@ -996,4 +996,46 @@ HTML,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testLoadParamFile()
|
||||
{
|
||||
$sTmpFileInsideItop = APPROOT.'data/test/testLoadParamFile.params';
|
||||
$sDir = dirname($sTmpFileInsideItop);
|
||||
if (!is_dir($sDir)) {
|
||||
mkdir($sDir, 0777, true);
|
||||
}
|
||||
$sParamName = 'IP1';
|
||||
$sParamValue = 'IV1';
|
||||
$sParams = <<<INI
|
||||
# comment
|
||||
$sParamName = $sParamValue
|
||||
INI;
|
||||
file_put_contents($sTmpFileInsideItop, $sParams);
|
||||
|
||||
try {
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage("File '$sTmpFileInsideItop' should be outside iTop");
|
||||
self::InvokeNonPublicStaticMethod(utils::class, 'LoadParamFile', [$sTmpFileInsideItop]);
|
||||
self::assertNotEquals($sParamValue, utils::ReadParam($sParamName, null), "utils::LoadParamFile() should NOT have loaded the file: $sTmpFileInsideItop");
|
||||
} finally {
|
||||
if (file_exists($sTmpFileInsideItop)) {
|
||||
unlink($sTmpFileInsideItop);
|
||||
}
|
||||
}
|
||||
|
||||
$sParamName = 'OP2';
|
||||
$sParamValue = 'OV2';
|
||||
|
||||
$sTmpFileOutsideItop = tempnam(sys_get_temp_dir(), 'utils-test');
|
||||
$sParams = <<<INI
|
||||
# comment
|
||||
$sParamName = $sParamValue
|
||||
INI;
|
||||
|
||||
file_put_contents($sTmpFileOutsideItop, $sParams);
|
||||
self::InvokeNonPublicStaticMethod(utils::class, 'LoadParamFile', [$sTmpFileOutsideItop]);
|
||||
self::assertEquals($sParamValue, utils::ReadParam($sParamName, null), "utils::LoadParamFile() should have loaded the file: $sTmpFileOutsideItop");
|
||||
|
||||
unlink($sTmpFileOutsideItop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,4 +183,14 @@ class DBUnionSearchTest extends ItopDataTestCase
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testAllowAllDataOnUnions()
|
||||
{
|
||||
$oSearch = \DBObjectSearch::FromOQL('SELECT Server UNION SELECT VirtualMachine');
|
||||
$oSearch->AllowAllData(false);
|
||||
self::assertFalse($oSearch->IsAllDataAllowed(), 'DBUnionSearch AllowData value');
|
||||
$oSearch->AllowAllData(true);
|
||||
self::assertTrue($oSearch->IsAllDataAllowed(), 'DBUnionSearch AllowData value');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -446,18 +446,16 @@ function ReSyncProcesses($oP, $bVerbose, $bDebug)
|
||||
//
|
||||
|
||||
set_time_limit(0); // Some background actions may really take long to finish (like backup)
|
||||
|
||||
$bIsModeCLI = utils::IsModeCLI();
|
||||
if ($bIsModeCLI) {
|
||||
$oP = new CLIPage("iTop - cron");
|
||||
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL);
|
||||
} else {
|
||||
$oP = new WebPage("iTop - cron");
|
||||
}
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
$bIsModeCLI = utils::IsModeCLI();
|
||||
if ($bIsModeCLI) {
|
||||
$oP = new CLIPage("iTop - cron");
|
||||
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL);
|
||||
utils::UseParamFile();
|
||||
} else {
|
||||
$oP = new WebPage("iTop - cron");
|
||||
}
|
||||
|
||||
$bVerbose = utils::ReadParam('verbose', false, true /* Allow CLI */);
|
||||
$bDebug = utils::ReadParam('debug', false, true /* Allow CLI */);
|
||||
|
||||
@@ -43,10 +43,12 @@ const EXIT_CODE_ERROR = -1;
|
||||
const EXIT_CODE_FATAL = -2;
|
||||
|
||||
try {
|
||||
// Do this before loging, in order to allow setting user credentials from within the file
|
||||
utils::UseParamFile();
|
||||
if (utils::IsModeCLI()) {
|
||||
// Do this before logging, in order to allow setting user credentials from within the file
|
||||
utils::UseParamFile();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo "Error: ".$e->GetMessage()."<br/>\n";
|
||||
echo "Error: ".$e->GetMessage()."\n";
|
||||
exit(EXIT_CODE_FATAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,18 +208,18 @@ $oCtx = new ContextTag(ContextTag::TAG_IMPORT);
|
||||
if (utils::IsModeCLI()) {
|
||||
$oP = new CLIPage("iTop - Bulk import");
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP, -2);
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
$oP->p('Error: '.$e->GetMessage());
|
||||
$oP->output();
|
||||
exit(-2);
|
||||
}
|
||||
} else {
|
||||
$oP = new CSVPage("iTop - Bulk import");
|
||||
}
|
||||
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
} catch (Exception $e) {
|
||||
$oP->p("Error: ".$e->GetMessage());
|
||||
$oP->output();
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
if (utils::IsModeCLI()) {
|
||||
// Next steps:
|
||||
// specific arguments: 'csvfile'
|
||||
|
||||
@@ -91,10 +91,8 @@ if (empty($sJsonString)) {
|
||||
|
||||
$sProvider = '';
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oKPI->ComputeAndReport('Data model loaded');
|
||||
|
||||
// N°6358 - force credentials for REST calls
|
||||
|
||||
Reference in New Issue
Block a user