mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts: # composer.lock # datamodels/2.x/itop-oauth-client/datamodel.itop-oauth-client.xml # lib/composer/autoload_files.php # lib/composer/autoload_real.php # lib/composer/autoload_static.php # lib/composer/installed.json # lib/composer/installed.php
This commit is contained in:
@@ -114,9 +114,9 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)).
|
||||
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
||||
Emoji examples :
|
||||
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.dev/)).
|
||||
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
|
||||
Emoji examples :
|
||||
* 🌐 `:globe_with_meridians:` for translations
|
||||
* 🎨 `:art:` when improving the format/structure of the code
|
||||
* ⚡️ `:zap:` when improving performance
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\Title;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/application/template.class.inc.php');
|
||||
@@ -655,8 +653,7 @@ abstract class MenuNode
|
||||
$this->sMenuId = $sMenuId;
|
||||
$this->iParentIndex = $iParentIndex;
|
||||
$this->aReflectionProperties = array();
|
||||
if (utils::StrLen($sEnableClass) > 0)
|
||||
{
|
||||
if (utils::IsNotNullOrEmptyString($sEnableClass)) {
|
||||
$this->aReflectionProperties['enable_class'] = $sEnableClass;
|
||||
$this->aReflectionProperties['enable_action'] = $iActionCode;
|
||||
$this->aReflectionProperties['enable_permission'] = $iAllowedResults;
|
||||
|
||||
@@ -973,7 +973,7 @@ HTML
|
||||
);
|
||||
|
||||
$oPage->add_ready_script(<<<JS
|
||||
$('#ac_create_{$this->iId}').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
|
||||
$('#ac_create_{$this->iId}').dialog({ width: $(window).width() * 0.6, height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
|
||||
$('#dcr_{$this->iId} form').removeAttr('onsubmit');
|
||||
$('#dcr_{$this->iId} form').find('button[type="submit"]').on('click', oACWidget_{$this->iId}.DoCreateObject);
|
||||
JS
|
||||
|
||||
@@ -1942,7 +1942,7 @@ class utils
|
||||
*/
|
||||
public static function CompileCSSFromSASS($sSassContent, $aImportPaths = array(), $aVariables = array())
|
||||
{
|
||||
$oSass = new Compiler();//['checkImportResolutions'=>true]);
|
||||
$oSass = new Compiler();
|
||||
$oSass->setOutputStyle(OutputStyle::COMPRESSED);
|
||||
// Setting our variables
|
||||
$aCssVariable = [];
|
||||
@@ -2845,6 +2845,36 @@ HTML;
|
||||
return strlen($sString ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper around the native strlen() PHP method to test a string for null or empty value
|
||||
*
|
||||
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
|
||||
*
|
||||
* @param string|null $sString
|
||||
*
|
||||
* @return bool if string null or empty
|
||||
* @since 3.0.2 N°5302
|
||||
*/
|
||||
public static function IsNullOrEmptyString(?string $sString): bool
|
||||
{
|
||||
return $sString == null || strlen($sString) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper around the native strlen() PHP method to test a string not null or empty value
|
||||
*
|
||||
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
|
||||
*
|
||||
* @param string|null $sString
|
||||
*
|
||||
* @return bool if string is not null and not empty
|
||||
* @since 3.0.2 N°5302
|
||||
*/
|
||||
public static function IsNotNullOrEmptyString(?string $sString): bool
|
||||
{
|
||||
return !static::IsNullOrEmptyString($sString);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Environment helpers
|
||||
//----------------------------------------------
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"name": "combodo/itop",
|
||||
"description": "IT Operations Portal",
|
||||
"type": "project",
|
||||
"license": "AGPLv3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.2.5 <8.0.0",
|
||||
"ext-ctype": "*",
|
||||
|
||||
@@ -293,7 +293,7 @@ abstract class AsyncTask extends DBObject
|
||||
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
|
||||
}
|
||||
|
||||
$this->Set('last_error', $sErrorMessage);
|
||||
$this->SetTrim('last_error', $sErrorMessage);
|
||||
$this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!!
|
||||
$this->Set('last_attempt', time());
|
||||
|
||||
|
||||
@@ -530,7 +530,7 @@ class Config
|
||||
],
|
||||
'email_transport' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)',
|
||||
'description' => 'Mean to send emails: PHPMail (uses the function mail()), SMTP (implements the client protocol) or SMTP_OAuth (connect to the server using OAuth 2.0)',
|
||||
'default' => "PHPMail",
|
||||
'value' => "PHPMail",
|
||||
'source_of_value' => '',
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
|
||||
namespace Combodo\iTop;
|
||||
|
||||
use \DOMDocument;
|
||||
use \DOMFormatException;
|
||||
use DOMDocument;
|
||||
use DOMFormatException;
|
||||
use IssueLog;
|
||||
use LogAPI;
|
||||
|
||||
/**
|
||||
* Class \Combodo\iTop\DesignDocument
|
||||
@@ -64,9 +66,13 @@ class DesignDocument extends DOMDocument
|
||||
* @param $filename
|
||||
* @param int $options
|
||||
*/
|
||||
public function load($filename, $options = 0)
|
||||
public function load($filename, $options = null)
|
||||
{
|
||||
parent::load($filename, LIBXML_NOBLANKS);
|
||||
libxml_clear_errors();
|
||||
if (parent::load($filename, LIBXML_NOBLANKS) === false) {
|
||||
$aErrors = libxml_get_errors();
|
||||
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,10 +83,10 @@ class DesignDocument extends DOMDocument
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function save($filename, $options = 0)
|
||||
public function save($filename, $options = null)
|
||||
{
|
||||
$this->documentElement->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
|
||||
return parent::save($filename, LIBXML_NOBLANKS);
|
||||
return parent::save($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -461,7 +461,7 @@ abstract class MetaModel
|
||||
$oStyle = self::$m_aClassParams[$sClass]['style'];
|
||||
$sIcon = $oStyle->GetIconAsAbsUrl();
|
||||
}
|
||||
if (utils::StrLen($sIcon) == 0) {
|
||||
if (utils::IsNullOrEmptyString($sIcon)) {
|
||||
$sParentClass = self::GetParentPersistentClass($sClass);
|
||||
if (strlen($sParentClass) > 0) {
|
||||
return self::GetClassIcon($sParentClass, $bImgTag, $sMoreStyles);
|
||||
@@ -494,7 +494,7 @@ abstract class MetaModel
|
||||
$oStyle = new ormStyle("ibo-class-style--$sClass", "ibo-class-style-alt--$sClass");
|
||||
}
|
||||
|
||||
if ((utils::StrLen($oStyle->GetMainColor()) > 0) && (utils::StrLen($oStyle->GetComplementaryColor()) > 0) && (utils::StrLen($oStyle->GetIconAsRelPath()) > 0)) {
|
||||
if (utils::IsNotNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNotNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNotNullOrEmptyString($oStyle->GetIconAsRelPath())) {
|
||||
// all the parameters are set, no need to search in the parent classes
|
||||
return $oStyle;
|
||||
}
|
||||
@@ -504,18 +504,18 @@ abstract class MetaModel
|
||||
while (strlen($sParentClass) > 0) {
|
||||
$oParentStyle = self::GetClassStyle($sParentClass);
|
||||
if (!is_null($oParentStyle)) {
|
||||
if (utils::StrLen($oStyle->GetMainColor()) == 0) {
|
||||
if (utils::IsNullOrEmptyString($oStyle->GetMainColor())) {
|
||||
$oStyle->SetMainColor($oParentStyle->GetMainColor());
|
||||
$oStyle->SetStyleClass($oParentStyle->GetStyleClass());
|
||||
}
|
||||
if (utils::StrLen($oStyle->GetComplementaryColor()) == 0) {
|
||||
if (utils::IsNullOrEmptyString($oStyle->GetComplementaryColor())) {
|
||||
$oStyle->SetComplementaryColor($oParentStyle->GetComplementaryColor());
|
||||
$oStyle->SetAltStyleClass($oParentStyle->GetAltStyleClass());
|
||||
}
|
||||
if (utils::StrLen($oStyle->GetIconAsRelPath()) == 0) {
|
||||
if (utils::IsNullOrEmptyString($oStyle->GetIconAsRelPath())) {
|
||||
$oStyle->SetIcon($oParentStyle->GetIconAsRelPath());
|
||||
}
|
||||
if ((utils::StrLen($oStyle->GetMainColor()) > 0) && (utils::StrLen($oStyle->GetComplementaryColor()) > 0) && (utils::StrLen($oStyle->GetIconAsRelPath()) > 0)) {
|
||||
if (utils::IsNotNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNotNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNotNullOrEmptyString($oStyle->GetIconAsRelPath())) {
|
||||
// all the parameters are set, no need to search in the parent classes
|
||||
return $oStyle;
|
||||
}
|
||||
@@ -523,7 +523,7 @@ abstract class MetaModel
|
||||
$sParentClass = self::GetParentPersistentClass($sParentClass);
|
||||
}
|
||||
|
||||
if ((utils::StrLen($oStyle->GetMainColor()) == 0) && (utils::StrLen($oStyle->GetComplementaryColor()) == 0) && (utils::StrLen($oStyle->GetIconAsRelPath()) == 0)) {
|
||||
if (utils::IsNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNullOrEmptyString($oStyle->GetIconAsRelPath())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class ormStyle
|
||||
*/
|
||||
public function HasMainColor(): bool
|
||||
{
|
||||
return utils::StrLen($this->sMainColor) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sMainColor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ class ormStyle
|
||||
*/
|
||||
public function SetMainColor(?string $sMainColor)
|
||||
{
|
||||
$this->sMainColor = (utils::StrLen($sMainColor) === 0) ? null : $sMainColor;
|
||||
$this->sMainColor = utils::IsNullOrEmptyString($sMainColor) ? null : $sMainColor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class ormStyle
|
||||
*/
|
||||
public function HasComplementaryColor(): bool
|
||||
{
|
||||
return utils::StrLen($this->sComplementaryColor) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sComplementaryColor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +96,7 @@ class ormStyle
|
||||
*/
|
||||
public function SetComplementaryColor(?string $sComplementaryColor)
|
||||
{
|
||||
$this->sComplementaryColor = (utils::StrLen($sComplementaryColor) === 0) ? null : $sComplementaryColor;
|
||||
$this->sComplementaryColor = utils::IsNullOrEmptyString($sComplementaryColor) ? null : $sComplementaryColor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class ormStyle
|
||||
*/
|
||||
public function HasStyleClass(): bool
|
||||
{
|
||||
return utils::StrLen($this->sStyleClass) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sStyleClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,7 +134,7 @@ class ormStyle
|
||||
*/
|
||||
public function SetStyleClass(?string $sStyleClass)
|
||||
{
|
||||
$this->sStyleClass = (utils::StrLen($sStyleClass) === 0) ? null : $sStyleClass;
|
||||
$this->sStyleClass = utils::IsNullOrEmptyString($sStyleClass) ? null : $sStyleClass;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ class ormStyle
|
||||
*/
|
||||
public function HasAltStyleClass(): bool
|
||||
{
|
||||
return utils::StrLen($this->sAltStyleClass) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sAltStyleClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ class ormStyle
|
||||
*/
|
||||
public function SetAltStyleClass(?string $sAltStyleClass)
|
||||
{
|
||||
$this->sAltStyleClass = (utils::StrLen($sAltStyleClass) === 0) ? null : $sAltStyleClass;
|
||||
$this->sAltStyleClass = utils::IsNullOrEmptyString($sAltStyleClass) ? null : $sAltStyleClass;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ class ormStyle
|
||||
*/
|
||||
public function HasDecorationClasses(): bool
|
||||
{
|
||||
return utils::StrLen($this->sDecorationClasses) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sDecorationClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,7 +190,7 @@ class ormStyle
|
||||
*/
|
||||
public function SetDecorationClasses(?string $sDecorationClasses)
|
||||
{
|
||||
$this->sDecorationClasses = (utils::StrLen($sDecorationClasses) === 0) ? null : $sDecorationClasses;
|
||||
$this->sDecorationClasses = utils::IsNullOrEmptyString($sDecorationClasses) ? null : $sDecorationClasses;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ class ormStyle
|
||||
*/
|
||||
public function HasIcon(): bool
|
||||
{
|
||||
return utils::StrLen($this->sIcon) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,7 +210,7 @@ class ormStyle
|
||||
*/
|
||||
public function SetIcon(?string $sIcon)
|
||||
{
|
||||
$this->sIcon = (utils::StrLen($sIcon) === 0) ? null : $sIcon;
|
||||
$this->sIcon = utils::IsNullOrEmptyString($sIcon) ? null : $sIcon;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
2
css/backoffice/vendors/_selectize.scss
vendored
2
css/backoffice/vendors/_selectize.scss
vendored
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
# Extension OAuth 2.0 client
|
||||
|
||||
## GMail
|
||||
|
||||
If the account is in test, after 7 days the tokens are no longer valid, you have to renew the tokens manually.
|
||||
|
||||
@@ -17,8 +17,7 @@ if (version_compare(ITOP_DESIGN_LATEST_VERSION , '3.0') >= 0) {
|
||||
}
|
||||
|
||||
$oUpdateController = new AjaxOauthClientController($sTemplates, 'itop-oauth-client');
|
||||
$oUpdateController->AllowOnlyAdmin();
|
||||
$oUpdateController->SetDefaultOperation('CreateMailbox');
|
||||
$oUpdateController->SetMenuId('OAuthClient');
|
||||
$oUpdateController->HandleOperation();
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<class id="OAuthClient" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<category>cloud,searchable</category>
|
||||
<category>grant_by_profile,application</category>
|
||||
<abstract>true</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_oauth_client</db_table>
|
||||
@@ -17,14 +17,15 @@
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<display_template/>
|
||||
<icon/>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="provider" xsi:type="AttributeString">
|
||||
@@ -119,22 +120,35 @@
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareHeader($oPage, $bEditMode);
|
||||
if (!$bEditMode) {
|
||||
$oConfig = utils::GetConfig();
|
||||
$sScope = $this->Get('scope');
|
||||
if ($this->Get('status') == 'inactive') {
|
||||
$oPage->p('<b>'.Dict::S('itop-oauth-client:Message:MissingToken').'</b>');
|
||||
} elseif (($sScope == 'SMTP' || $sScope == 'EMail') && $oConfig->Get('email_transport_smtp.username') == $this->Get('name')) {
|
||||
$sLabel = Dict::S('itop-oauth-client:UsedForSMTP');
|
||||
$sTestLabel = Dict::S('itop-oauth-client:TestSMTP');
|
||||
$sTestURL = utils::GetAbsoluteUrlAppRoot().'setup/email.test.php';
|
||||
$oPage->p("<b>$sLabel</b> <a href='$sTestURL' target='_blank'>$sTestLabel</a>");
|
||||
}
|
||||
}
|
||||
}
|
||||
public function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
$aHeaderBlocks = parent::DisplayBareHeader($oPage, $bEditMode);
|
||||
$aTags = [];
|
||||
if (!$bEditMode) {
|
||||
$oConfig = utils::GetConfig();
|
||||
if ($this->Get('status') == 'inactive') {
|
||||
$sLabel = Dict::S('itop-oauth-client:Message:MissingToken');
|
||||
$sTitle = '';
|
||||
$aTags['oauth-message'] = ['title' => $sTitle, 'css_classes' => 'ibo-object-details--tag--oauth-message', 'decoration_classes' => 'fas fa-exclamation-triangle', 'label' => $sLabel];
|
||||
} elseif ($this->Get('used_for_smtp') == 'yes' && $oConfig->Get('email_transport_smtp.username') == $this->Get('name')) {
|
||||
$sLabel = Dict::S('itop-oauth-client:UsedForSMTP');
|
||||
$sTestLabel = Dict::S('itop-oauth-client:TestSMTP');
|
||||
$sTestURL = utils::GetAbsoluteUrlAppRoot().'setup/email.test.php';
|
||||
$sLabel = Dict::S('itop-oauth-client:UsedForSMTP')." <a href='$sTestURL' target='_blank'>$sTestLabel</a>";
|
||||
$sTitle = '';
|
||||
$aTags['oauth-message'] = ['title' => $sTitle, 'css_classes' => 'ibo-object-details--tag--oauth-message', 'decoration_classes' => 'far fa-envelope', 'label' => $sLabel];
|
||||
}
|
||||
}
|
||||
foreach ($aTags as $sIconId => $aIconData) {
|
||||
$sTagTooltipContent = utils::EscapeHtml($aIconData['title']);
|
||||
$aHeaderBlocks['subtitle'][static::HEADER_BLOCKS_SUBTITLE_TAG_PREFIX.$sIconId] = new Combodo\iTop\Application\UI\Base\Component\Html\Html(<<<HTML
|
||||
<span id="{$sIconId}" class="ibo-object-details--tag {$aIconData['css_classes']}" data-tooltip-content="{$sTagTooltipContent}" data-tooltip-html-enabled="true"><span class="ibo-object-details--tag-icon"><span class="{$aIconData['decoration_classes']}"></span></span>{$aIconData['label']}</span>
|
||||
HTML
|
||||
);
|
||||
}
|
||||
|
||||
return $aHeaderBlocks;
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetAttributeFlags">
|
||||
@@ -142,14 +156,14 @@
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
if ($sAttCode == 'status') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
if ($sAttCode == 'status') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetInitialStateAttributeFlags">
|
||||
@@ -157,68 +171,68 @@
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||
{
|
||||
if ($sAttCode == 'status') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||
{
|
||||
if ($sAttCode == 'status') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetDefaultMailServer">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'imap.'.$this->Get('provider').'.com';
|
||||
}
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'imap.'.$this->Get('provider').'.com';
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetDefaultMailServerPort">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetDefaultMailServerPort()
|
||||
{
|
||||
return 993;
|
||||
}
|
||||
public function GetDefaultMailServerPort()
|
||||
{
|
||||
return 993;
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetAccessToken">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetAccessToken()
|
||||
{
|
||||
if ($this->Get('status') == 'active') {
|
||||
return new \League\OAuth2\Client\Token\AccessToken([
|
||||
'access_token' => $this->Get('token'),
|
||||
'expires_in' => date_format(new DateTime($this->Get('token_expiration')), 'U') - time(),
|
||||
'refresh_token' => $this->Get('refresh_token'),
|
||||
'token_type' => 'Bearer',
|
||||
]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function GetAccessToken()
|
||||
{
|
||||
if ($this->Get('status') == 'active') {
|
||||
return new \League\OAuth2\Client\Token\AccessToken([
|
||||
'access_token' => $this->Get('token'),
|
||||
'expires_in' => date_format(new DateTime($this->Get('token_expiration')), 'U') - time(),
|
||||
'refresh_token' => $this->Get('refresh_token'),
|
||||
'token_type' => 'Bearer',
|
||||
]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="SetAccessToken">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function SetAccessToken(\League\OAuth2\Client\Token\AccessTokenInterface $oAccessToken)
|
||||
{
|
||||
$this->Set('token', $oAccessToken->getToken());
|
||||
$this->Set('token_expiration', date(AttributeDateTime::GetSQLFormat(), $oAccessToken->getExpires()));
|
||||
if (!empty($oAccessToken->getRefreshToken())) {
|
||||
$this->Set('refresh_token', $oAccessToken->getRefreshToken());
|
||||
}
|
||||
$this->Set('status', 'active');
|
||||
$this->DBUpdate();
|
||||
}
|
||||
public function SetAccessToken(\League\OAuth2\Client\Token\AccessTokenInterface $oAccessToken)
|
||||
{
|
||||
$this->Set('token', $oAccessToken->getToken());
|
||||
$this->Set('token_expiration', date(AttributeDateTime::GetSQLFormat(), $oAccessToken->getExpires()));
|
||||
if (!empty($oAccessToken->getRefreshToken())) {
|
||||
$this->Set('refresh_token', $oAccessToken->getRefreshToken());
|
||||
}
|
||||
$this->Set('status', 'active');
|
||||
$this->DBUpdate();
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
@@ -280,6 +294,632 @@
|
||||
</default_search>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="OAuthClientAzure" _delta="define">
|
||||
<parent>OAuthClient</parent>
|
||||
<properties>
|
||||
<category>grant_by_profile,application</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_oauth_client_azure</db_table>
|
||||
<db_key_field>id</db_key_field>
|
||||
<db_final_class_field/>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<uniqueness_rules>
|
||||
<rule id="server">
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="client_id"/>
|
||||
<attribute id="client_secret"/>
|
||||
</attributes>
|
||||
<is_blocking>true</is_blocking>
|
||||
</rule>
|
||||
</uniqueness_rules>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="scope" xsi:type="AttributeEnumSet">
|
||||
<always_load_in_tables>true</always_load_in_tables>
|
||||
<values>
|
||||
<value id="SMTP">
|
||||
<code>SMTP</code>
|
||||
</value>
|
||||
<value id="IMAP">
|
||||
<code>IMAP</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>scope</sql>
|
||||
<default_value>SMTP,IMAP</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="advanced_scope" xsi:type="AttributeString">
|
||||
<sql>advanced_scope</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="used_scope" xsi:type="AttributeEnum">
|
||||
<always_load_in_tables>true</always_load_in_tables>
|
||||
<values>
|
||||
<value id="simple">
|
||||
<code>simple</code>
|
||||
</value>
|
||||
<value id="advanced">
|
||||
<code>advanced</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>used_scope</sql>
|
||||
<default_value>simple</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<dependencies>
|
||||
<attribute id="scope"/>
|
||||
<attribute id="advanced_scope"/>
|
||||
</dependencies>
|
||||
</field>
|
||||
<field id="used_for_smtp" xsi:type="AttributeEnum">
|
||||
<always_load_in_tables>true</always_load_in_tables>
|
||||
<values>
|
||||
<value id="yes">
|
||||
<code>yes</code>
|
||||
</value>
|
||||
<value id="no">
|
||||
<code>no</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>used_for_smtp</sql>
|
||||
<default_value>no</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="col:col1">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="fieldset:OAuthClient:baseinfo">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="provider">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="redirect_url">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="client_id">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
<item id="client_secret">
|
||||
<rank>70</rank>
|
||||
</item>
|
||||
<item id="mailbox_list">
|
||||
<rank>80</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="col:col2">
|
||||
<rank>20</rank>
|
||||
<items>
|
||||
<item id="fieldset:OAuthClient:scope">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="used_scope">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="scope">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="advanced_scope">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="used_for_smtp">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<list>
|
||||
<items>
|
||||
<item id="provider">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<standard_search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="provider">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</standard_search>
|
||||
</presentation>
|
||||
<methods>
|
||||
<method id="PrefillCreationForm">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function PrefillCreationForm(&$aContextParam)
|
||||
{
|
||||
$this->Set('provider', 'Azure');
|
||||
$this->Set('redirect_url', Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory::GetRedirectUri());
|
||||
$this->Set('scope', 'SMTP, IMAP');
|
||||
|
||||
parent::PrefillCreationForm($aContextParam);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="DoCheckToWrite">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[ public function DoCheckToWrite()
|
||||
{
|
||||
parent::DoCheckToWrite();
|
||||
|
||||
$aChanges = $this->ListChanges();
|
||||
if (array_key_exists('name', $aChanges) || array_key_exists('used_for_smtp', $aChanges))
|
||||
{
|
||||
$sNewName = $this->Get('name');
|
||||
$sNewUseForSMTP = $this->Get('used_for_smtp');
|
||||
if ($sNewUseForSMTP == 'yes') {
|
||||
$oSearch = DBObjectSearch::FromOQL_AllData("SELECT OAuthClientGoogle WHERE name = :newname AND used_for_smtp = :newuseforsmtp AND id != :id UNION SELECT OAuthClientAzure WHERE name = :newname AND used_for_smtp = :newuseforsmtp AND id != :id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), ['id' => $this->GetKey(), 'newname' => $sNewName, 'newuseforsmtp' => $sNewUseForSMTP]);
|
||||
if ($oSet->Count() > 0)
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('OAuthClient:Name/UseForSMTPMustBeUnique', $sNewName, $sNewUseForSMTP);
|
||||
}
|
||||
}
|
||||
}
|
||||
} ]]></code>
|
||||
</method>
|
||||
<method id="ComputeValues">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function ComputeValues()
|
||||
{
|
||||
parent::ComputeValues();
|
||||
if (empty($this->Get('provider'))) {
|
||||
$this->Set('provider', 'Azure');
|
||||
}
|
||||
if (empty($this->Get('redirect_url'))) {
|
||||
$this->Set('redirect_url', Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory::GetRedirectUri());
|
||||
}
|
||||
if (empty($this->Get('advanced_scope'))) {
|
||||
$this->Set('used_scope', 'simple');
|
||||
if (count($this->Get('scope')->GetValues()) == 0) {
|
||||
$this->Set('scope', 'SMTP, IMAP');
|
||||
}
|
||||
} else {
|
||||
$this->Set('used_scope', 'advanced');
|
||||
$this->Set('scope', '');
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetAttributeFlags">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
switch ($sAttCode) {
|
||||
case 'provider':
|
||||
case 'redirect_url':
|
||||
case 'used_scope':
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetInitialStateAttributeFlags">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||
{
|
||||
switch ($sAttCode) {
|
||||
case 'provider':
|
||||
case 'redirect_url':
|
||||
case 'used_scope':
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetDefaultMailServer">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'outlook.office365.com';
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetScope">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetScope()
|
||||
{
|
||||
if (!empty($this->Get('advanced_scope'))) {
|
||||
return $this->Get('advanced_scope');
|
||||
}
|
||||
$aScopes = $this->Get('scope')->GetValues();
|
||||
$aRawScopes = ['offline_access'];
|
||||
foreach ($aScopes as $sScope) {
|
||||
switch ($sScope) {
|
||||
case 'SMTP':
|
||||
$aRawScopes[] = 'https://outlook.office.com/SMTP.Send';
|
||||
break;
|
||||
|
||||
case 'IMAP':
|
||||
$aRawScopes[] = 'https://outlook.office.com/IMAP.AccessAsUser.All';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return implode(' ', $aRawScopes);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
<class id="OAuthClientGoogle" _delta="define">
|
||||
<parent>OAuthClient</parent>
|
||||
<properties>
|
||||
<category>grant_by_profile,application</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_oauth_client_google</db_table>
|
||||
<db_key_field>id</db_key_field>
|
||||
<db_final_class_field/>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<uniqueness_rules>
|
||||
<rule id="server">
|
||||
<attributes>
|
||||
<attribute id="provider"/>
|
||||
<attribute id="client_id"/>
|
||||
<attribute id="client_secret"/>
|
||||
</attributes>
|
||||
<is_blocking>true</is_blocking>
|
||||
</rule>
|
||||
</uniqueness_rules>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="scope" xsi:type="AttributeEnumSet">
|
||||
<always_load_in_tables>true</always_load_in_tables>
|
||||
<values>
|
||||
<value id="SMTP">
|
||||
<code>SMTP</code>
|
||||
</value>
|
||||
<value id="IMAP">
|
||||
<code>IMAP</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>scope</sql>
|
||||
<default_value>SMTP,IMAP</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="advanced_scope" xsi:type="AttributeString">
|
||||
<sql>advanced_scope</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="used_scope" xsi:type="AttributeEnum">
|
||||
<always_load_in_tables>true</always_load_in_tables>
|
||||
<values>
|
||||
<value id="simple">
|
||||
<code>simple</code>
|
||||
</value>
|
||||
<value id="advanced">
|
||||
<code>advanced</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>used_scope</sql>
|
||||
<default_value>simple</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<dependencies>
|
||||
<attribute id="scope"/>
|
||||
<attribute id="advanced_scope"/>
|
||||
</dependencies>
|
||||
</field>
|
||||
<field id="used_for_smtp" xsi:type="AttributeEnum">
|
||||
<always_load_in_tables>true</always_load_in_tables>
|
||||
<values>
|
||||
<value id="yes">
|
||||
<code>yes</code>
|
||||
</value>
|
||||
<value id="no">
|
||||
<code>no</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>used_for_smtp</sql>
|
||||
<default_value>no</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="col:col1">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="fieldset:OAuthClient:baseinfo">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="provider">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="redirect_url">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="client_id">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
<item id="client_secret">
|
||||
<rank>70</rank>
|
||||
</item>
|
||||
<item id="mailbox_list">
|
||||
<rank>80</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="col:col2">
|
||||
<rank>20</rank>
|
||||
<items>
|
||||
<item id="fieldset:OAuthClient:scope">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="used_scope">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="scope">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="advanced_scope">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="used_for_smtp">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<list>
|
||||
<items>
|
||||
<item id="provider">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<standard_search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="provider">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</standard_search>
|
||||
</presentation>
|
||||
<methods>
|
||||
<method id="PrefillCreationForm">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function PrefillCreationForm(&$aContextParam)
|
||||
{
|
||||
$this->Set('provider', 'Google');
|
||||
$this->Set('redirect_url', Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory::GetRedirectUri());
|
||||
$this->Set('scope', 'SMTP, IMAP');
|
||||
|
||||
parent::PrefillCreationForm($aContextParam);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="DoCheckToWrite">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[ public function DoCheckToWrite()
|
||||
{
|
||||
parent::DoCheckToWrite();
|
||||
|
||||
$aChanges = $this->ListChanges();
|
||||
if (array_key_exists('name', $aChanges) || array_key_exists('used_for_smtp', $aChanges))
|
||||
{
|
||||
$sNewName = $this->Get('name');
|
||||
$sNewUseForSMTP = $this->Get('used_for_smtp');
|
||||
if ($sNewUseForSMTP == 'yes') {
|
||||
$oSearch = DBObjectSearch::FromOQL_AllData("SELECT OAuthClientGoogle WHERE name = :newname AND used_for_smtp = :newuseforsmtp AND id != :id UNION SELECT OAuthClientAzure WHERE name = :newname AND used_for_smtp = :newuseforsmtp AND id != :id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), ['id' => $this->GetKey(), 'newname' => $sNewName, 'newuseforsmtp' => $sNewUseForSMTP]);
|
||||
if ($oSet->Count() > 0)
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('OAuthClient:Name/UseForSMTPMustBeUnique', $sNewName, $sNewUseForSMTP);
|
||||
}
|
||||
}
|
||||
}
|
||||
} ]]></code>
|
||||
</method>
|
||||
<method id="ComputeValues">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function ComputeValues()
|
||||
{
|
||||
parent::ComputeValues();
|
||||
if (empty($this->Get('provider'))) {
|
||||
$this->Set('provider', 'Google');
|
||||
}
|
||||
if (empty($this->Get('redirect_url'))) {
|
||||
$this->Set('redirect_url', Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory::GetRedirectUri());
|
||||
}
|
||||
if (empty($this->Get('advanced_scope'))) {
|
||||
$this->Set('used_scope', 'simple');
|
||||
if (count($this->Get('scope')->GetValues()) == 0) {
|
||||
$this->Set('scope', 'SMTP, IMAP');
|
||||
}
|
||||
} else {
|
||||
$this->Set('used_scope', 'advanced');
|
||||
$this->Set('scope', '');
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetAttributeFlags">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
switch ($sAttCode) {
|
||||
case 'provider':
|
||||
case 'redirect_url':
|
||||
case 'used_scope':
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetInitialStateAttributeFlags">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||
{
|
||||
switch ($sAttCode) {
|
||||
case 'provider':
|
||||
case 'redirect_url':
|
||||
case 'used_scope':
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetDefaultMailServer">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'imap.gmail.com';
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetScope">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function GetScope()
|
||||
{
|
||||
if (!empty($this->Get('advanced_scope'))) {
|
||||
return $this->Get('advanced_scope');
|
||||
}
|
||||
$aScopes = $this->Get('scope')->GetValues();
|
||||
$aRawScopes = [];
|
||||
foreach ($aScopes as $sScope) {
|
||||
switch ($sScope) {
|
||||
case 'SMTP':
|
||||
$aRawScopes['https://mail.google.com/'] = 'https://mail.google.com/';
|
||||
break;
|
||||
|
||||
case 'IMAP':
|
||||
$aRawScopes['https://mail.google.com/'] = 'https://mail.google.com/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return implode(' ', $aRawScopes);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="OAuthClient" xsi:type="OQLMenuNode" _delta="define">
|
||||
@@ -289,13 +929,16 @@
|
||||
<do_search>1</do_search>
|
||||
<enable_admin_only>0</enable_admin_only>
|
||||
<enable_class>OAuthClient</enable_class>
|
||||
<enable_action>UR_ACTION_READ</enable_action>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
</menus>
|
||||
<user_rights>
|
||||
<groups>
|
||||
<group id="OauthConnection" _delta="define">
|
||||
<classes>
|
||||
<class id="OAuthClient"/>
|
||||
</classes>
|
||||
</group>
|
||||
</groups>
|
||||
<profiles>
|
||||
</profiles>
|
||||
</user_rights>
|
||||
</itop_design>
|
||||
|
||||
@@ -21,6 +21,11 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'itop-oauth-client:Message:MissingToken' => 'Generate access token before using this OAuth client',
|
||||
'itop-oauth-client:Message:TokenCreated' => 'Access token created',
|
||||
'itop-oauth-client:Message:TokenRecreated' => 'Access token regenerated',
|
||||
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already be used for OAuth Client',
|
||||
|
||||
'OAuthClient:baseinfo' => 'Base Information',
|
||||
'OAuthClient:scope' => 'Scope',
|
||||
]);
|
||||
|
||||
//
|
||||
@@ -32,19 +37,17 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:OAuthClient/Attribute:provider' => 'Provider',
|
||||
'Class:OAuthClient/Attribute:provider+' => '',
|
||||
'Class:OAuthClient/Attribute:name' => 'Login',
|
||||
'Class:OAuthClient/Attribute:name+' => '',
|
||||
'Class:OAuthClient/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClient/Attribute:scope+' => '',
|
||||
'Class:OAuthClient/Attribute:name+' => 'In general, this is your email address',
|
||||
'Class:OAuthClient/Attribute:status' => 'Status',
|
||||
'Class:OAuthClient/Attribute:status+' => '',
|
||||
'Class:OAuthClient/Attribute:status+' => 'After creation, use the action “Generate access token” to be able to use this OAuth client',
|
||||
'Class:OAuthClient/Attribute:status/Value:active' => 'Access token generated',
|
||||
'Class:OAuthClient/Attribute:status/Value:inactive' => 'No Access token',
|
||||
'Class:OAuthClient/Attribute:description' => 'Description',
|
||||
'Class:OAuthClient/Attribute:description+' => '',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id',
|
||||
'Class:OAuthClient/Attribute:client_id+' => '',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret',
|
||||
'Class:OAuthClient/Attribute:client_secret+' => '',
|
||||
'Class:OAuthClient/Attribute:client_secret+' => 'Another long string of characters provided by your OAuth2 provider',
|
||||
'Class:OAuthClient/Attribute:refresh_token' => 'Refresh token',
|
||||
'Class:OAuthClient/Attribute:refresh_token+' => '',
|
||||
'Class:OAuthClient/Attribute:refresh_token_expiration' => 'Refresh token expiration',
|
||||
@@ -54,7 +57,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '',
|
||||
'Class:OAuthClient/Attribute:redirect_url' => 'Redirect url',
|
||||
'Class:OAuthClient/Attribute:redirect_url+' => '',
|
||||
'Class:OAuthClient/Attribute:redirect_url+' => 'This url must be copied in the OAuth2 configuration of the provider',
|
||||
'Class:OAuthClient/Attribute:mailbox_list' => 'Mailbox list',
|
||||
'Class:OAuthClient/Attribute:mailbox_list+' => '',
|
||||
]);
|
||||
@@ -62,17 +65,53 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
//
|
||||
// Class: OAuthClientAzure
|
||||
//
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
|
||||
]);
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClientAzure/Attribute:scope+' => 'Usually default selection is appropriate',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:SMTP' => 'SMTP',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:SMTP+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:IMAP' => 'IMAP',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:IMAP+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence on the “Scope” selection which is then ignored',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope' => 'Used scope',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:advanced' => 'Advanced',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:advanced+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp' => 'Used for SMTP',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp+' => 'At least one OAuth client must have this flag to “Yes”, if you want iTop to use it for sending mails',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp/Value:yes' => 'Yes',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp/Value:no' => 'No',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: OAuthClientGoogle
|
||||
//
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
]);
|
||||
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClientGoogle/Attribute:scope+' => 'Usually default selection is appropriate',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:SMTP' => 'SMTP',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:SMTP+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:IMAP' => 'IMAP',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:IMAP+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence on the “Scope” selection which is then ignored',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope' => 'Used scope',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:simple' => 'Simple',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:simple+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:advanced' => 'Advanced',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:advanced+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp' => 'Used for SMTP',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp+' => 'At least one OAuth client must have this flag to “Yes”, if you want iTop to use it for sending mails',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp/Value:yes' => 'Yes',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp/Value:no' => 'No',
|
||||
));
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* @copyright Copyright (C) 2013 XXXXX
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Menu:CreateMailbox' => 'Créer une boite mail...',
|
||||
'Menu:OAuthClient' => 'Client OAuth',
|
||||
@@ -20,6 +21,11 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'itop-oauth-client:Message:MissingToken' => 'Générez le jeton d\'accès avant d\'utiliser ce client OAuth',
|
||||
'itop-oauth-client:Message:TokenCreated' => 'Le jeton d\'accès à été créé',
|
||||
'itop-oauth-client:Message:TokenRecreated' => 'Le jeton d\'accès à été renouvelé',
|
||||
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'La combinaison Login (%1$s) and Utilisé pour SMTP (%2$s) a déjà été utilisée pour OAuth Client',
|
||||
|
||||
'OAuthClient:baseinfo' => 'Information',
|
||||
'OAuthClient:scope' => 'Scope',
|
||||
]);
|
||||
|
||||
//
|
||||
@@ -31,15 +37,17 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:OAuthClient/Attribute:provider' => 'Fournisseur',
|
||||
'Class:OAuthClient/Attribute:provider+' => '',
|
||||
'Class:OAuthClient/Attribute:name' => 'Login',
|
||||
'Class:OAuthClient/Attribute:name+' => '',
|
||||
'Class:OAuthClient/Attribute:scope' => 'Niveaux d\'accès',
|
||||
'Class:OAuthClient/Attribute:scope+' => '',
|
||||
'Class:OAuthClient/Attribute:name+' => 'L\'adresse email à utiliser chez ce fournisseur',
|
||||
'Class:OAuthClient/Attribute:status' => 'Statut',
|
||||
'Class:OAuthClient/Attribute:status+' => 'Après la création, effectuer l\'action \'Créer un jeton d\'accès...\' pour activer ce client OAuth',
|
||||
'Class:OAuthClient/Attribute:status/Value:active' => 'Jeton d\'accès créé',
|
||||
'Class:OAuthClient/Attribute:status/Value:inactive' => 'Pas de jeton d\'accès',
|
||||
'Class:OAuthClient/Attribute:description' => 'Description',
|
||||
'Class:OAuthClient/Attribute:description+' => '',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'ID Client',
|
||||
'Class:OAuthClient/Attribute:client_id+' => '',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'Recopier la chaine fournie par votre fournisseur OAuth2',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Code secret du client',
|
||||
'Class:OAuthClient/Attribute:client_secret+' => '',
|
||||
'Class:OAuthClient/Attribute:client_secret+' => 'Recopier l\'information fournie par votre fournisseur OAuth2',
|
||||
'Class:OAuthClient/Attribute:refresh_token' => 'Jeton de renouvellement',
|
||||
'Class:OAuthClient/Attribute:refresh_token+' => '',
|
||||
'Class:OAuthClient/Attribute:refresh_token_expiration' => 'Date d\'expiration du jeton de renouvellement',
|
||||
@@ -49,7 +57,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Date d\'expiration du jeton d\'accès',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '',
|
||||
'Class:OAuthClient/Attribute:redirect_url' => 'URL de redirection',
|
||||
'Class:OAuthClient/Attribute:redirect_url+' => '',
|
||||
'Class:OAuthClient/Attribute:redirect_url+' => 'Cet URL doit être recopié dans la configuration OAuth2 de votre fournisseur',
|
||||
'Class:OAuthClient/Attribute:mailbox_list' => 'Mailbox list',
|
||||
'Class:OAuthClient/Attribute:mailbox_list+' => '',
|
||||
]);
|
||||
@@ -57,22 +65,52 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
//
|
||||
// Class: OAuthClientAzure
|
||||
//
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:OAuthClientAzure' => 'Client OAuth pour Microsoft Azure',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
|
||||
]);
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Niveaux d\'accès',
|
||||
'Class:OAuthClientAzure/Attribute:scope+' => 'Les niveaux par défaut sont les plus souvent suffisants',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:SMTP' => 'SMTP',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:SMTP+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:IMAP' => 'IMAP',
|
||||
'Class:OAuthClientAzure/Attribute:scope/Value:IMAP+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Niveaux d\'accès avancé',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'A saisir, lorsque les niveaux prédéfinis ne suffisent pas',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope' => 'Niveaux d\'accès utilisés',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:advanced' => 'Avancé',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:advanced+' => '',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp' => 'Utilisé pour SMTP',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp+' => 'Le Client OAuth utilisé pour l\'envoi d\'emails doit être à \'Oui\'',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp/Value:yes' => 'Oui',
|
||||
'Class:OAuthClientAzure/Attribute:used_for_smtp/Value:no' => 'Non',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: OAuthClientGoogle
|
||||
//
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:OAuthClientGoogle' => 'Client OAuth pour Google',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
]);
|
||||
|
||||
|
||||
// Additional language entries not present in English dict
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:OAuthClient/Name' => '%1$s-%%2$~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Niveaux d\'accès',
|
||||
'Class:OAuthClientGoogle/Attribute:scope+' => 'Les niveaux par défaut sont les plus souvent suffisants',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:SMTP' => 'SMTP',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:SMTP+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:IMAP' => 'IMAP',
|
||||
'Class:OAuthClientGoogle/Attribute:scope/Value:IMAP+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Niveaux d\'accès avancé',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'A saisir, lorsque les niveaux prédéfinis ne suffisent pas',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope' => 'Niveaux d\'accès utilisés',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:simple' => 'Simple',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:advanced' => 'Avancé',
|
||||
'Class:OAuthClientGoogle/Attribute:used_scope/Value:advanced+' => '',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp' => 'Utilisé pour SMTP',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp+' => 'Le Client OAuth utilisé pour l\'envoi d\'emails doit être à \'Oui\'',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp/Value:yes' => 'Oui',
|
||||
'Class:OAuthClientGoogle/Attribute:used_for_smtp/Value:no' => 'Non',
|
||||
));
|
||||
|
||||
@@ -25,9 +25,8 @@ SetupWebPage::AddModule(
|
||||
'datamodel' => array(
|
||||
'vendor/autoload.php',
|
||||
'model.itop-oauth-client.php', // Contains the PHP code generated by the "compilation" of datamodel.remote-authent-oauth.xml
|
||||
'src/Model/OAuthClientGoogle.php',
|
||||
'src/Model/OAuthClientAzure.php',
|
||||
'src/Service/PopupMenuExtension.php',
|
||||
'src/Service/ApplicationUIExtension.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory;
|
||||
|
||||
class OAuthClientAzure extends OAuthClient
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = [
|
||||
'category' => 'cloud',
|
||||
'key_type' => 'autoincrement',
|
||||
'name_attcode' => ['name', 'scope'],
|
||||
'state_attcode' => '',
|
||||
'reconc_keys' => ['provider', 'name'],
|
||||
'db_table' => 'priv_oauth_client_azure',
|
||||
'db_key_field' => 'id',
|
||||
'icon' => utils::GetAbsoluteUrlModulesRoot().'itop-oauth-client/assets/img/icons8-azure.svg',
|
||||
'db_finalclass_field' => '',
|
||||
'uniqueness_rules' => [
|
||||
'Username for scope' =>
|
||||
[
|
||||
'attributes' => ['name', 'scope'],
|
||||
'filter' => null,
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
],
|
||||
'OAuth Server' =>
|
||||
[
|
||||
'attributes' => ['provider', 'scope', 'client_id', 'client_secret'],
|
||||
'filter' => null,
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum('scope', [
|
||||
'allowed_values' => new ValueSetEnum('EMail'),
|
||||
'display_style' => 'list',
|
||||
'sql' => 'scope',
|
||||
'default_value' => 'EMail',
|
||||
'is_null_allowed' => false,
|
||||
'depends_on' => [],
|
||||
'always_load_in_tables' => true,
|
||||
]));
|
||||
|
||||
MetaModel::Init_SetZListItems('details', [
|
||||
'name',
|
||||
'status',
|
||||
'description',
|
||||
'provider',
|
||||
'scope',
|
||||
'redirect_url',
|
||||
'client_id',
|
||||
'client_secret',
|
||||
'mailbox_list',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('standard_search', [
|
||||
'name',
|
||||
'provider',
|
||||
'status',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('list', [
|
||||
'status',
|
||||
'provider',
|
||||
]);
|
||||
}
|
||||
|
||||
public function PrefillCreationForm(&$aContextParam)
|
||||
{
|
||||
$this->Set('provider', 'Azure');
|
||||
$this->Set('redirect_url', OAuthClientProviderFactory::GetRedirectUri());
|
||||
|
||||
parent::PrefillCreationForm($aContextParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute read-only values
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
*/
|
||||
public function ComputeValues()
|
||||
{
|
||||
parent::ComputeValues();
|
||||
if (empty($this->Get('provider'))) {
|
||||
$this->Set('provider', 'Azure');
|
||||
}
|
||||
if (empty($this->Get('redirect_url'))) {
|
||||
$this->Set('redirect_url', OAuthClientProviderFactory::GetRedirectUri());
|
||||
}
|
||||
}
|
||||
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
if ($sAttCode == 'provider' || $sAttCode == 'redirect_url') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||
{
|
||||
if ($sAttCode == 'provider' || $sAttCode == 'redirect_url') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'outlook.office365.com';
|
||||
}
|
||||
|
||||
public function GetScope()
|
||||
{
|
||||
return 'https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send offline_access';
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory;
|
||||
|
||||
class OAuthClientGoogle extends OAuthClient
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
'category' => 'cloud',
|
||||
'key_type' => 'autoincrement',
|
||||
'name_attcode' => ['name', 'scope'],
|
||||
'state_attcode' => '',
|
||||
'reconc_keys' => ['provider', 'name'],
|
||||
'db_table' => 'priv_oauth_client_google',
|
||||
'db_key_field' => 'id',
|
||||
'icon' => utils::GetAbsoluteUrlModulesRoot().'itop-oauth-client/assets/img/icons8-google.svg',
|
||||
'db_finalclass_field' => '',
|
||||
'uniqueness_rules' => [
|
||||
'Username for scope' =>
|
||||
[
|
||||
'attributes' => ['name', 'scope'],
|
||||
'filter' => null,
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
],
|
||||
'OAuth Server' =>
|
||||
[
|
||||
'attributes' => ['provider', 'scope', 'client_id', 'client_secret'],
|
||||
'filter' => null,
|
||||
'disabled' => false,
|
||||
'is_blocking' => true,
|
||||
],
|
||||
],
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum('scope', [
|
||||
'allowed_values' => new ValueSetEnum('EMail'),
|
||||
'display_style' => 'list',
|
||||
'sql' => 'scope',
|
||||
'default_value' => 'EMail',
|
||||
'is_null_allowed' => false,
|
||||
'depends_on' => [],
|
||||
'always_load_in_tables' => true,
|
||||
]));
|
||||
|
||||
MetaModel::Init_SetZListItems('details', [
|
||||
'name',
|
||||
'status',
|
||||
'description',
|
||||
'provider',
|
||||
'scope',
|
||||
'redirect_url',
|
||||
'client_id',
|
||||
'client_secret',
|
||||
'mailbox_list',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('standard_search', [
|
||||
'name',
|
||||
'provider',
|
||||
'status',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('list', [
|
||||
'status',
|
||||
'provider',
|
||||
]);
|
||||
}
|
||||
|
||||
public function PrefillCreationForm(&$aContextParam)
|
||||
{
|
||||
$this->Set('provider', 'Google');
|
||||
$this->Set('scope', 'EMail');
|
||||
$this->Set('redirect_url', OAuthClientProviderFactory::GetRedirectUri());
|
||||
|
||||
parent::PrefillCreationForm($aContextParam);
|
||||
}
|
||||
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
if ($sAttCode == 'provider' || $sAttCode == 'scope' || $sAttCode == 'redirect_url') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
|
||||
{
|
||||
if ($sAttCode == 'provider' || $sAttCode == 'scope' || $sAttCode == 'redirect_url') {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute read-only values
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
*/
|
||||
public function ComputeValues()
|
||||
{
|
||||
parent::ComputeValues();
|
||||
if (empty($this->Get('provider'))) {
|
||||
$this->Set('provider', 'Google');
|
||||
}
|
||||
if (empty($this->Get('redirect_url'))) {
|
||||
$this->Set('redirect_url', OAuthClientProviderFactory::GetRedirectUri());
|
||||
}
|
||||
if (empty($this->Get('scope'))) {
|
||||
$this->Set('scope', 'EMail');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'imap.gmail.com';
|
||||
}
|
||||
|
||||
public function GetScope()
|
||||
{
|
||||
return 'https://mail.google.com/';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\OAuthClient\Service;
|
||||
|
||||
use AbstractApplicationUIExtension;
|
||||
use OAuthClient;
|
||||
use utils;
|
||||
|
||||
class ApplicationUIExtension extends AbstractApplicationUIExtension
|
||||
{
|
||||
|
||||
public function GetHilightClass($oObject)
|
||||
{
|
||||
if ($oObject instanceof OAuthClient) {
|
||||
// Possible return values are:
|
||||
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
|
||||
$oConfig = utils::GetConfig();
|
||||
if ($oObject->Get('status') == 'inactive') {
|
||||
return HILIGHT_CLASS_WARNING;
|
||||
} elseif ($oObject->Get('used_for_smtp') == 'yes' && $oConfig->Get('email_transport_smtp.username') == $oObject->Get('name')) {
|
||||
return HILIGHT_CLASS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return HILIGHT_CLASS_NONE;
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class PopupMenuExtension implements \iPopupMenuExtension
|
||||
$sId = $oObj->GetKey();
|
||||
$sAjaxUri = utils::GetAbsoluteUrlModulePage(static::MODULE_CODE, 'ajax.php');
|
||||
// Add a new menu item that triggers a custom JS function defined in our own javascript file: js/sample.js
|
||||
$sJSFileUrl = utils::GetAbsoluteUrlModulesRoot().static::MODULE_CODE.'/assets/js/oauth_connect.js';
|
||||
$sJSFileUrl = 'env-'.utils::GetCurrentEnvironment().'/'.static::MODULE_CODE.'/assets/js/oauth_connect.js';
|
||||
$sRedirectUri = OAuthClientProviderFactory::GetRedirectUri();
|
||||
$aResult[] = new JSPopupMenuItem(
|
||||
$sMenu.' from '.$sObjClass,
|
||||
@@ -51,8 +51,8 @@ class PopupMenuExtension implements \iPopupMenuExtension
|
||||
);
|
||||
|
||||
if ($bHasToken) {
|
||||
$sScope = $oObj->Get('scope');
|
||||
if ($sScope == 'EMail') {
|
||||
$aScopes = $oObj->Get('scope')->GetValues();
|
||||
if (in_array('IMAP', $aScopes)) {
|
||||
$aParams = $oAppContext->GetAsHash();
|
||||
$sMenu = 'Menu:CreateMailbox';
|
||||
$sObjClass = get_class($oObj);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{# @copyright Copyright (C) 2010-2022 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{# @copyright Copyright (C) 2010-2022 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
window.location.href = '{{ sURL|raw }}'
|
||||
@@ -93,7 +93,7 @@ class ObjectFormManager extends FormManager
|
||||
* @since 2.7.6 3.0.0 N°4384 method creation : factorize as this is used twice now
|
||||
* @since 2.7.7 3.0.1 N°4867 now only used once, but we decided to keep this method anyway
|
||||
*/
|
||||
protected static function DecodeFormManagerData($formManagerData)
|
||||
public static function DecodeFormManagerData($formManagerData)
|
||||
{
|
||||
if (is_array($formManagerData)) {
|
||||
return $formManagerData;
|
||||
|
||||
@@ -453,7 +453,7 @@ class ObjectFormHandlerHelper
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function CheckReadFormDataAllowed($sFormManagerData){
|
||||
$aJsonFromData = json_decode($sFormManagerData, true);
|
||||
$aJsonFromData = ObjectFormManager::DecodeFormManagerData($sFormManagerData);
|
||||
if(isset($aJsonFromData['formobject_class'])
|
||||
&& isset($aJsonFromData['formobject_id'])
|
||||
&& !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $aJsonFromData['formobject_class'], $aJsonFromData['formobject_id'])){
|
||||
|
||||
@@ -156,7 +156,7 @@ $(function()
|
||||
});
|
||||
me._updateExtraTabsList();
|
||||
}, {
|
||||
root: $('.ibo-tab-container--tabs-list')[0],
|
||||
root: this.element.find(this.js_selectors.tabs_list)[0],
|
||||
threshold: [0.9] // N°4783 Should be completely visible, but lowering the threshold prevents a bug in the JS Observer API when the window is zoomed in/out, in which case all items respond as being hidden even when they are not.
|
||||
});
|
||||
this.element.find(this.js_selectors.tab_header).each(function(){
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f::getLoader();
|
||||
|
||||
@@ -149,7 +149,7 @@ class ClassLoader
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
|
||||
@@ -21,26 +21,11 @@ use Composer\Semver\VersionParser;
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
@@ -243,7 +228,7 @@ class InstalledVersions
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
@@ -257,7 +242,7 @@ class InstalledVersions
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@@ -280,7 +265,7 @@ class InstalledVersions
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
@@ -303,7 +288,7 @@ class InstalledVersions
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
@@ -313,7 +298,7 @@ class InstalledVersions
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// include_paths.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
||||
@@ -11,10 +11,10 @@ if (!(PHP_VERSION_ID >= 70205)) {
|
||||
$missingExtensions = array();
|
||||
extension_loaded('dom') || $missingExtensions[] = 'dom';
|
||||
extension_loaded('gd') || $missingExtensions[] = 'gd';
|
||||
extension_loaded('iconv') || $missingExtensions[] = 'iconv';
|
||||
extension_loaded('json') || $missingExtensions[] = 'json';
|
||||
extension_loaded('libxml') || $missingExtensions[] = 'libxml';
|
||||
extension_loaded('mysqli') || $missingExtensions[] = 'mysqli';
|
||||
extension_loaded('openssl') || $missingExtensions[] = 'openssl';
|
||||
extension_loaded('soap') || $missingExtensions[] = 'soap';
|
||||
extension_loaded('tokenizer') || $missingExtensions[] = 'tokenizer';
|
||||
extension_loaded('xml') || $missingExtensions[] = 'xml';
|
||||
|
||||
4
lib/thenetworg/oauth2-azure/.gitignore
vendored
4
lib/thenetworg/oauth2-azure/.gitignore
vendored
@@ -3,3 +3,7 @@
|
||||
composer.phar
|
||||
composer.lock
|
||||
.DS_Store
|
||||
|
||||
# IDE
|
||||
/.idea
|
||||
/.vscode
|
||||
|
||||
@@ -46,7 +46,7 @@ $provider = new TheNetworg\OAuth2\Client\Provider\Azure([
|
||||
'clientSecret' => '{azure-client-secret}',
|
||||
'redirectUri' => 'https://example.com/callback-url',
|
||||
//Optional
|
||||
'scopes' => 'openid',
|
||||
'scopes' => ['openid'],
|
||||
//Optional
|
||||
'defaultEndPointVersion' => '2.0'
|
||||
]);
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
"sso"
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.6|^7.0|^8.0",
|
||||
"ext-json": "*",
|
||||
"ext-openssl": "*",
|
||||
"php": "^7.1|^8.0",
|
||||
"league/oauth2-client": "~2.0",
|
||||
"firebase/php-jwt": "~3.0||~4.0||~5.0"
|
||||
"firebase/php-jwt": "~3.0||~4.0||~5.0||~6.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
namespace TheNetworg\OAuth2\Client\Provider;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\JWK;
|
||||
use Firebase\JWT\Key;
|
||||
use League\OAuth2\Client\Grant\AbstractGrant;
|
||||
use League\OAuth2\Client\Provider\AbstractProvider;
|
||||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
|
||||
use League\OAuth2\Client\Token\AccessTokenInterface;
|
||||
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TheNetworg\OAuth2\Client\Grant\JwtBearer;
|
||||
@@ -66,7 +70,8 @@ class Azure extends AbstractProvider
|
||||
}
|
||||
if (!array_key_exists($version, $this->openIdConfiguration[$tenant])) {
|
||||
$versionInfix = $this->getVersionUriInfix($version);
|
||||
$openIdConfigurationUri = 'https://login.microsoftonline.com/' . $tenant . $versionInfix . '/.well-known/openid-configuration';
|
||||
$openIdConfigurationUri = $this->urlLogin . $tenant . $versionInfix . '/.well-known/openid-configuration?appid=' . $this->clientId;
|
||||
|
||||
$factory = $this->getRequestFactory();
|
||||
$request = $factory->getRequestWithOptions(
|
||||
'get',
|
||||
@@ -80,19 +85,28 @@ class Azure extends AbstractProvider
|
||||
return $this->openIdConfiguration[$tenant][$version];
|
||||
}
|
||||
|
||||
public function getBaseAuthorizationUrl()
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseAuthorizationUrl(): string
|
||||
{
|
||||
$openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion);
|
||||
return $openIdConfiguration['authorization_endpoint'];
|
||||
}
|
||||
|
||||
public function getBaseAccessTokenUrl(array $params)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseAccessTokenUrl(array $params): string
|
||||
{
|
||||
$openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion);
|
||||
return $openIdConfiguration['token_endpoint'];
|
||||
}
|
||||
|
||||
public function getAccessToken($grant, array $options = [])
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAccessToken($grant, array $options = []): AccessTokenInterface
|
||||
{
|
||||
if ($this->defaultEndPointVersion != self::ENDPOINT_VERSION_2_0) {
|
||||
// Version 2.0 does not support the resources parameter
|
||||
@@ -106,14 +120,21 @@ class Azure extends AbstractProvider
|
||||
return parent::getAccessToken($grant, $options);
|
||||
}
|
||||
|
||||
public function getResourceOwner(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getResourceOwner(\League\OAuth2\Client\Token\AccessToken $token): ResourceOwnerInterface
|
||||
{
|
||||
$data = $token->getIdTokenClaims();
|
||||
return $this->createResourceOwner($data, $token);
|
||||
}
|
||||
|
||||
public function getResourceOwnerDetailsUrl(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getResourceOwnerDetailsUrl(\League\OAuth2\Client\Token\AccessToken $token): string
|
||||
{
|
||||
return ''; // shouldn't that return such a URL?
|
||||
}
|
||||
|
||||
public function getObjects($tenant, $ref, &$accessToken, $headers = [])
|
||||
@@ -164,11 +185,11 @@ class Azure extends AbstractProvider
|
||||
return 'https://' . $openIdConfiguration['msgraph_host'];
|
||||
}
|
||||
|
||||
public function get($ref, &$accessToken, $headers = [])
|
||||
public function get($ref, &$accessToken, $headers = [], $doNotWrap = false)
|
||||
{
|
||||
$response = $this->request('get', $ref, $accessToken, ['headers' => $headers]);
|
||||
|
||||
return $this->wrapResponse($response);
|
||||
return $doNotWrap ? $response : $this->wrapResponse($response);
|
||||
}
|
||||
|
||||
public function post($ref, $body, &$accessToken, $headers = [])
|
||||
@@ -352,8 +373,24 @@ class Azure extends AbstractProvider
|
||||
|
||||
$publicKey = $pkey_array ['key'];
|
||||
|
||||
$keys[$keyinfo['kid']] = $publicKey;
|
||||
$keys[$keyinfo['kid']] = new Key($publicKey, 'RS256');
|
||||
}
|
||||
} else if (isset($keyinfo['n']) && isset($keyinfo['e'])) {
|
||||
$pkey_object = JWK::parseKey($keyinfo);
|
||||
|
||||
if ($pkey_object === false) {
|
||||
throw new \RuntimeException('An attempt to read a public key from a ' . $keyinfo['n'] . ' certificate failed.');
|
||||
}
|
||||
|
||||
$pkey_array = openssl_pkey_get_details($pkey_object);
|
||||
|
||||
if ($pkey_array === false) {
|
||||
throw new \RuntimeException('An attempt to get a public key as an array from a ' . $keyinfo['n'] . ' certificate failed.');
|
||||
}
|
||||
|
||||
$publicKey = $pkey_array ['key'];
|
||||
|
||||
$keys[$keyinfo['kid']] = new Key($publicKey, 'RS256');;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +419,10 @@ class Azure extends AbstractProvider
|
||||
return $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion);
|
||||
}
|
||||
|
||||
protected function checkResponse(ResponseInterface $response, $data)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkResponse(ResponseInterface $response, $data): void
|
||||
{
|
||||
if (isset($data['odata.error']) || isset($data['error'])) {
|
||||
if (isset($data['odata.error']['message']['value'])) {
|
||||
@@ -402,27 +442,39 @@ class Azure extends AbstractProvider
|
||||
throw new IdentityProviderException(
|
||||
$message,
|
||||
$response->getStatusCode(),
|
||||
$response
|
||||
$response->getBody()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getDefaultScopes()
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getDefaultScopes(): array
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
protected function getScopeSeparator()
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getScopeSeparator(): string
|
||||
{
|
||||
return $this->scopeSeparator;
|
||||
}
|
||||
|
||||
protected function createAccessToken(array $response, AbstractGrant $grant)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function createAccessToken(array $response, AbstractGrant $grant): AccessToken
|
||||
{
|
||||
return new AccessToken($response, $this);
|
||||
}
|
||||
|
||||
protected function createResourceOwner(array $response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function createResourceOwner(array $response, \League\OAuth2\Client\Token\AccessToken $token): AzureResourceOwner
|
||||
{
|
||||
return new AzureResourceOwner($response);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ class AccessToken extends \League\OAuth2\Client\Token\AccessToken
|
||||
if (!empty($options['id_token'])) {
|
||||
$this->idToken = $options['id_token'];
|
||||
|
||||
unset($this->values['id_token']);
|
||||
|
||||
$keys = $provider->getJwtVerificationKeys();
|
||||
$idTokenClaims = null;
|
||||
try {
|
||||
@@ -45,8 +47,27 @@ class AccessToken extends \League\OAuth2\Client\Token\AccessToken
|
||||
}
|
||||
}
|
||||
|
||||
public function getIdToken()
|
||||
{
|
||||
return $this->idToken;
|
||||
}
|
||||
|
||||
public function getIdTokenClaims()
|
||||
{
|
||||
return $this->idTokenClaims;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
$parameters = parent::jsonSerialize();
|
||||
|
||||
if ($this->idToken) {
|
||||
$parameters['id_token'] = $this->idToken;
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1672,214 +1672,6 @@ Awesome, nor vice versa. **Please do not use brand logos for any purpose except
|
||||
to represent the company, product, or service to which they refer.**
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="datamodels">apereo/phpcas</product>
|
||||
<author>Joachim Fritschi - Adam Franco</author>
|
||||
<license_type>Apache-2.0</license_type>
|
||||
<text><![CDATA[
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="js">C3 js</product>
|
||||
<author>Masayuki Tanaka</author>
|
||||
|
||||
@@ -684,6 +684,7 @@ class SetupUtils
|
||||
* Emulates sys_get_temp_dir if needed (PHP < 5.2.1)
|
||||
*
|
||||
* @return string Path to the system's temp directory
|
||||
* @uses \sys_get_temp_dir()
|
||||
*/
|
||||
public static function GetTmpDir() {
|
||||
return realpath(sys_get_temp_dir());
|
||||
|
||||
@@ -424,11 +424,11 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory
|
||||
$oButton->SetActionType($sActionType)
|
||||
->SetColor($sColor);
|
||||
|
||||
if (utils::StrLen($sValue) > 0) {
|
||||
if (utils::IsNotNullOrEmptyString($sValue)) {
|
||||
$oButton->SetValue($sValue);
|
||||
}
|
||||
|
||||
if (utils::StrLen($sName) > 0) {
|
||||
if (utils::IsNotNullOrEmptyString($sName)) {
|
||||
$oButton->SetName($sName);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class InputWithLabel extends UIBlock
|
||||
*/
|
||||
public function HasDescription(): bool
|
||||
{
|
||||
return utils::StrLen($this->sDescription) > 0;
|
||||
return utils::IsNotNullOrEmptyString($this->sDescription);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,15 +8,8 @@ use OAuthClient;
|
||||
|
||||
abstract class OAuthClientProviderAbstract implements IOAuthClientProvider
|
||||
{
|
||||
// /** @var string */
|
||||
// static protected $sVendorName = '';
|
||||
// /** @var array */
|
||||
// static protected $sVendorColors = ['', '', '', ''];
|
||||
// /** @var string */
|
||||
// static protected $sVendorIcon = '';
|
||||
// static protected $sRequiredSMTPScope = '';
|
||||
// static protected $sRequiredIMAPScope = '';
|
||||
// static protected $sRequiredPOPScope = '';
|
||||
/** @var string */
|
||||
static protected $sVendorName = '';
|
||||
|
||||
/** @var \League\OAuth2\Client\Provider\GenericProvider */
|
||||
protected $oVendorProvider;
|
||||
@@ -69,4 +62,12 @@ abstract class OAuthClientProviderAbstract implements IOAuthClientProvider
|
||||
return $this->oOauthClient->GetScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function GetVendorName()
|
||||
{
|
||||
return self::$sVendorName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,16 +6,8 @@ use TheNetworg\OAuth2\Client\Provider\Azure;
|
||||
|
||||
class OAuthClientProviderAzure extends OAuthClientProviderAbstract
|
||||
{
|
||||
// /** @var string */
|
||||
// static protected $sVendorName = 'Azure';
|
||||
// /** @var array */
|
||||
// static protected $sVendorColors = ['#0766b7', '#0d396b', '#2893df', '#3ccbf4'];
|
||||
// /** @var string */
|
||||
// static protected $sVendorIcon = '../images/icons/icons8-azure.svg';
|
||||
// static protected $sRequiredSMTPScope = 'https://outlook.office.com/SMTP.Send offline_access';
|
||||
// static protected $sRequiredIMAPScope = 'https://outlook.office.com/IMAP.AccessAsUser.All offline_access';
|
||||
// static protected $sRequiredPOPScope = 'https://outlook.office.com/POP.AccessAsUser.All offline access';
|
||||
|
||||
/** @var string */
|
||||
static protected $sVendorName = 'Azure';
|
||||
|
||||
public function __construct($oOAuthClient, array $collaborators = [])
|
||||
{
|
||||
|
||||
@@ -43,8 +43,7 @@ class OAuthClientProviderFactory
|
||||
throw new CoreException(Dict::Format('itop-oauth-client:MissingOAuthClient', $sUsername));
|
||||
}
|
||||
while ($oOAuthClient = $oSet->Fetch()) {
|
||||
$sScope = $oOAuthClient->Get('scope');
|
||||
if ($sScope == 'EMail') {
|
||||
if ($oOAuthClient->Get('used_for_smtp') == 'yes') {
|
||||
return $oOAuthClient;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,8 @@ use League\OAuth2\Client\Provider\Google;
|
||||
|
||||
class OAuthClientProviderGoogle extends OAuthClientProviderAbstract
|
||||
{
|
||||
// /** @var string */
|
||||
// static protected $sVendorName = 'Google';
|
||||
// /** @var array */
|
||||
// static protected $sVendorColors = ['#DB4437', '#F4B400', '#0F9D58', '#4285F4'];
|
||||
// /** @var string */
|
||||
// static protected $sVendorIcon = '../images/icons/icons8-google.svg';
|
||||
//
|
||||
// static protected $sRequiredSMTPScope = 'https://mail.google.com/';
|
||||
// static protected $sRequiredIMAPScope = 'https://mail.google.com/';
|
||||
// static protected $sRequiredPOPScope = 'https://mail.google.com/';
|
||||
/** @var string */
|
||||
static protected $sVendorName = 'Google';
|
||||
|
||||
public function __construct($oOAuthClient, array $collaborators = [])
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user