mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 00:02:17 +02:00
N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\OAuthClient\Controller;
|
||||
|
||||
use cmdbAbstractObject;
|
||||
use Combodo\iTop\Application\TwigBase\Controller\Controller;
|
||||
use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory;
|
||||
use Dict;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use utils;
|
||||
|
||||
class AjaxOauthClientController extends Controller
|
||||
{
|
||||
const LOG_CHANNEL = 'OAuth';
|
||||
|
||||
public function OperationGetOAuthAuthorizationUrl()
|
||||
{
|
||||
$sClass = utils::ReadParam('class');
|
||||
$sId = utils::ReadParam('id');
|
||||
|
||||
IssueLog::Debug("GetAuthorizationUrl for $sClass::$sId", self::LOG_CHANNEL);
|
||||
|
||||
$oObject = MetaModel::GetObject($sClass, $sId);
|
||||
|
||||
$aResult = ['status' => 'success', 'data' => []];
|
||||
$sProvider = $oObject->Get('provider');
|
||||
$sClientId = $oObject->Get('client_id');
|
||||
$sClientSecret = $oObject->Get('client_secret');
|
||||
$sScope = $oObject->GetScope();
|
||||
$aAdditional = [];
|
||||
$sAuthorizationUrl = OAuthClientProviderFactory::getVendorProviderForAccessUrl($sProvider, $sClientId, $sClientSecret, $sScope, $aAdditional);
|
||||
$aResult['data']['authorization_url'] = $sAuthorizationUrl;
|
||||
|
||||
$this->DisplayJSONPage($aResult);
|
||||
|
||||
}
|
||||
|
||||
public function OperationGetDisplayAuthenticationResults()
|
||||
{
|
||||
$sClass = utils::ReadParam('class');
|
||||
$sId = utils::ReadParam('id');
|
||||
|
||||
IssueLog::Debug("GetDisplayAuthenticationResults for $sClass::$sId", self::LOG_CHANNEL);
|
||||
|
||||
$oObject = MetaModel::GetObject($sClass, $sId);
|
||||
$bIsCreation = empty($oObject->Get('token'));
|
||||
|
||||
$sProvider = $oObject->Get('provider');
|
||||
$sClientId = $oObject->Get('client_id');
|
||||
$sClientSecret = $oObject->Get('client_secret');
|
||||
$sScope = $oObject->GetScope();
|
||||
$aAdditional = [];
|
||||
|
||||
$sRedirectUrl = utils::ReadParam('redirect_url', '', false, 'raw');
|
||||
|
||||
$sRedirectUrlQuery = parse_url($sRedirectUrl)['query'];
|
||||
|
||||
$aQuery = [];
|
||||
parse_str($sRedirectUrlQuery, $aQuery);
|
||||
$sCode = $aQuery['code'];
|
||||
$oProvider = OAuthClientProviderFactory::getVendorProvider($sProvider, $sClientId, $sClientSecret, $sScope, $aAdditional);
|
||||
$oAccessToken = OAuthClientProviderFactory::getAccessTokenFromCode($oProvider, $sCode);
|
||||
|
||||
$oObject->Set('token', $oAccessToken->getToken());
|
||||
$oObject->Set('refresh_token', $oAccessToken->getRefreshToken());
|
||||
$oObject->DBUpdate();
|
||||
|
||||
cmdbAbstractObject::SetSessionMessage(
|
||||
$sClass,
|
||||
$sId,
|
||||
"$sClass:$sId:TokenCreated",
|
||||
$bIsCreation ? Dict::S('itop-oauth-client:Message:TokenCreated') : Dict::S('itop-oauth-client:Message:TokenRecreated'),
|
||||
'ok',
|
||||
1,
|
||||
true
|
||||
);
|
||||
|
||||
$aResult = ['status' => 'success'];
|
||||
$aResult['data'] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=details&class=$sClass&id=$sId";
|
||||
|
||||
$this->DisplayJSONPage($aResult);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\OAuthClient\Controller;
|
||||
|
||||
use Combodo\iTop\Application\TwigBase\Controller\Controller;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use utils;
|
||||
|
||||
class OAuthClientController extends Controller
|
||||
{
|
||||
const LOG_CHANNEL = 'OAuth';
|
||||
|
||||
public function OperationCreateMailbox()
|
||||
{
|
||||
$aParams = [];
|
||||
|
||||
$sClass = utils::ReadParam('class');
|
||||
$sId = utils::ReadParam('id');
|
||||
|
||||
IssueLog::Debug("CreateMailbox for $sClass::$sId", self::LOG_CHANNEL);
|
||||
|
||||
$oOAuthClient = MetaModel::GetObject($sClass, $sId);
|
||||
$sLogin = $oOAuthClient->Get('name');
|
||||
$sDefaultServer = $oOAuthClient->GetDefaultMailServer();
|
||||
$sDefaultPort = $oOAuthClient->GetDefaultMailServerPort();
|
||||
|
||||
$aParams['sURL'] = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=new&class=MailInboxOAuth'.
|
||||
'&default[mailbox]=INBOX'.
|
||||
'&default[server]='.$sDefaultServer.
|
||||
'&default[port]='.$sDefaultPort.
|
||||
'&default[oauth_client_id]='.$sId.
|
||||
'&default[login]='.$sLogin;
|
||||
|
||||
$this->DisplayPage($aParams);
|
||||
}
|
||||
}
|
||||
147
datamodels/2.x/itop-oauth-client/src/Model/OAuthClientAzure.php
Normal file
147
datamodels/2.x/itop-oauth-client/src/Model/OAuthClientAzure.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderAbstract;
|
||||
|
||||
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('SMTP,IMAP'),
|
||||
'display_style' => 'list',
|
||||
'sql' => 'scope',
|
||||
'default_value' => 'SMTP',
|
||||
'is_null_allowed' => false,
|
||||
'depends_on' => [],
|
||||
'always_load_in_tables' => true,
|
||||
]));
|
||||
|
||||
MetaModel::Init_SetZListItems('details', [
|
||||
0 => 'name',
|
||||
1 => 'description',
|
||||
2 => 'provider',
|
||||
3 => 'scope',
|
||||
4 => 'redirect_url',
|
||||
5 => 'client_id',
|
||||
6 => 'client_secret',
|
||||
7 => 'mailbox_list',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('standard_search', [
|
||||
0 => 'name',
|
||||
2 => 'provider',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('list', [
|
||||
]);
|
||||
}
|
||||
|
||||
public function PrefillCreationForm(&$aContextParam)
|
||||
{
|
||||
$this->Set('provider', 'Azure');
|
||||
$this->Set('redirect_url', OAuthClientProviderAbstract::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', OAuthClientProviderAbstract::GetRedirectUri());
|
||||
}
|
||||
}
|
||||
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'outlook.office365.com';
|
||||
}
|
||||
|
||||
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 GetScope()
|
||||
{
|
||||
$sScope = $this->Get('scope');
|
||||
if ($sScope == 'IMAP') {
|
||||
return 'https://outlook.office.com/IMAP.AccessAsUser.All offline_access';
|
||||
}
|
||||
|
||||
// default is smtp
|
||||
return 'https://outlook.office.com/SMTP.Send offline_access';
|
||||
}
|
||||
|
||||
public function AfterInsert()
|
||||
{
|
||||
parent::AfterInsert();
|
||||
$sClass = get_class($this);
|
||||
$sId = $this->GetKey();
|
||||
cmdbAbstractObject::SetSessionMessage(
|
||||
$sClass,
|
||||
$sId,
|
||||
"$sClass:$sId:OAuthClientCreated",
|
||||
Dict::S('itop-oauth-client:Message:OAuthClientCreated'),
|
||||
'info',
|
||||
100,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
145
datamodels/2.x/itop-oauth-client/src/Model/OAuthClientGoogle.php
Normal file
145
datamodels/2.x/itop-oauth-client/src/Model/OAuthClientGoogle.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderAbstract;
|
||||
|
||||
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', [
|
||||
0 => 'name',
|
||||
1 => 'description',
|
||||
2 => 'provider',
|
||||
3 => 'scope',
|
||||
4 => 'redirect_url',
|
||||
5 => 'client_id',
|
||||
6 => 'client_secret',
|
||||
7 => 'mailbox_list',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('standard_search', [
|
||||
0 => 'name',
|
||||
2 => 'provider',
|
||||
]);
|
||||
MetaModel::Init_SetZListItems('list', [
|
||||
]);
|
||||
}
|
||||
|
||||
public function PrefillCreationForm(&$aContextParam)
|
||||
{
|
||||
$this->Set('provider', 'Google');
|
||||
$this->Set('scope', 'EMail');
|
||||
$this->Set('redirect_url', OAuthClientProviderAbstract::GetRedirectUri());
|
||||
|
||||
parent::PrefillCreationForm($aContextParam);
|
||||
}
|
||||
|
||||
public function GetDefaultMailServer()
|
||||
{
|
||||
return 'imap.gmail.com';
|
||||
}
|
||||
|
||||
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', OAuthClientProviderAbstract::GetRedirectUri());
|
||||
}
|
||||
if (empty($this->Get('scope'))) {
|
||||
$this->Set('scope', 'EMail');
|
||||
}
|
||||
}
|
||||
|
||||
public function GetScope()
|
||||
{
|
||||
return 'https://mail.google.com/';
|
||||
}
|
||||
|
||||
public function AfterInsert()
|
||||
{
|
||||
parent::AfterInsert();
|
||||
$sClass = get_class($this);
|
||||
$sId = $this->GetKey();
|
||||
cmdbAbstractObject::SetSessionMessage(
|
||||
$sClass,
|
||||
$sId,
|
||||
"$sClass:$sId:OAuthClientCreated",
|
||||
Dict::S('itop-oauth-client:Message:OAuthClientCreated'),
|
||||
'info',
|
||||
100,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\OAuthClient\Service;
|
||||
|
||||
use AbstractApplicationObjectExtension;
|
||||
use Exception;
|
||||
use OAuthClient;
|
||||
|
||||
class ApplicationObjectExtension extends AbstractApplicationObjectExtension
|
||||
{
|
||||
|
||||
public function OnDBInsert($oObject, $oChange = null)
|
||||
{
|
||||
if ($oObject instanceof OAuthClient) {
|
||||
try {
|
||||
// Ask for tokens the first time
|
||||
|
||||
//$response = utils::DoPostRequest($sRestUrl, $aPostedData);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
}
|
||||
parent::OnDBInsert($oObject, $oChange); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\OAuthClient\Service;
|
||||
|
||||
use ApplicationContext;
|
||||
use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderAbstract;
|
||||
use Dict;
|
||||
use iPopupMenuExtension;
|
||||
use JSPopupMenuItem;
|
||||
use OAuthClient;
|
||||
use SeparatorPopupMenuItem;
|
||||
use URLPopupMenuItem;
|
||||
use utils;
|
||||
|
||||
class PopupMenuExtension implements \iPopupMenuExtension
|
||||
{
|
||||
const MODULE_CODE = 'itop-oauth-client';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function EnumItems($iMenuId, $param)
|
||||
{
|
||||
$aResult = [];
|
||||
|
||||
switch ($iMenuId) {
|
||||
case iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS:
|
||||
$oObj = $param;
|
||||
if ($oObj instanceof OAuthClient) {
|
||||
$bHasToken = !empty($oObj->Get('token'));
|
||||
$aResult[] = new SeparatorPopupMenuItem();
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sMenu = $bHasToken ? 'Menu:RegenerateTokens' : 'Menu:GenerateTokens';
|
||||
$sObjClass = get_class($oObj);
|
||||
$sClass = $sObjClass;
|
||||
$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';
|
||||
$sRedirectUri = OAuthClientProviderAbstract::GetRedirectUri();
|
||||
$aResult[] = new JSPopupMenuItem(
|
||||
$sMenu.' from '.$sObjClass,
|
||||
Dict::S($sMenu),
|
||||
"OAuthConnect('$sClass', $sId, '$sAjaxUri', '$sRedirectUri')",
|
||||
[$sJSFileUrl]
|
||||
);
|
||||
|
||||
if ($bHasToken) {
|
||||
$sScope = $oObj->Get('scope');
|
||||
if ($sScope == 'IMAP' || $sScope == 'EMail') {
|
||||
$aParams = $oAppContext->GetAsHash();
|
||||
$sMenu = 'Menu:CreateMailbox';
|
||||
$sObjClass = get_class($oObj);
|
||||
$aParams['class'] = $sObjClass;
|
||||
$aParams['id'] = $oObj->GetKey();
|
||||
$aParams['operation'] = 'CreateMailBox';
|
||||
$aResult[] = new URLPopupMenuItem(
|
||||
$sMenu.' from '.$sObjClass,
|
||||
Dict::S($sMenu),
|
||||
utils::GetAbsoluteUrlModulePage(static::MODULE_CODE, 'index.php', $aParams)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown type of menu, do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user