Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions admin/oauthlogintokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
use League\OAuth2\Client\Provider\GoogleUser;

// Load translation files required by the page
$langs->loadLangs(["errors","admin","googleapi@googleapi"]);
$langs->loadLangs(['errors', 'oauth', 'admin', 'googleapi@googleapi']);

if (!$user->admin) {
accessforbidden();
Expand Down Expand Up @@ -107,7 +107,7 @@
// This is to use external domain name found into config file
$urlwithroot = $urlwithouturlroot . DOL_URL_ROOT;
// This is to use same domain name than current
//$urlwithroot=DOL_MAIN_URL_ROOT;
// $urlwithroot=DOL_MAIN_URL_ROOT;

$form = new Form($db);

Expand All @@ -120,7 +120,6 @@

print dol_get_fiche_head($head, 'tokengeneration', '', -1, 'technic');


if ($user->admin) {
print $langs->trans("OAuthSetupForLogin") . "<br><br>\n";

Expand All @@ -142,26 +141,30 @@
$expiredat = '';


// Is token expired or will token expire in the next 30 seconds
// Is token expired or will token expire in the next 60 seconds
if (is_object($token)) {
$expire = $token->hasExpired();
$isgoingtoexpire = (time() > ($token->getExpires() - 30));
if ($isgoingtoexpire) {
$isgoingtoexpire = (time() > ($token->getExpires() - 60));
if ($isgoingtoexpire || $expire) {
$provider = new Google([
'clientId' => getDolGlobalString('OAUTH_GOOGLEAPI_ID'),
'clientSecret' => getDolGlobalString('OAUTH_GOOGLEAPI_SECRET'),
'redirectUri' => dol_buildpath('/googleapi/core/modules/oauth/googleapi_oauthcallback.php', 2),
]);
$grant = new RefreshToken();
$token = $provider->getAccessToken($grant, ['refresh_token' => $tokenrefreshbackup]);
$expire = $token->hasExpired();
storeAccessToken('GoogleApi', $token, $tokenrefreshbackup, $user->id);
setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
try {
$token = $provider->getAccessToken($grant, ['refresh_token' => $tokenrefreshbackup]);
$expire = $token->hasExpired();
storeAccessToken('GoogleApi', $token, $tokenrefreshbackup, $user->id);
setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
} catch (Exception $e) {
setEventMessages($e->getMessage(), null, 'errors');
}
}
$refreshtoken = $token->getRefreshToken();

$endoflife = $token->getExpires();
$expiredat = dol_print_date($endoflife, "dayhour");
$expiredat = dol_print_date($endoflife, "dayhour", "tzuser");
}

print '<form method="post" action="' . $_SERVER["PHP_SELF"] . '" autocomplete="off">';
Expand Down
50 changes: 48 additions & 2 deletions admin/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

// Load Dolibarr environment
include '../config.php';
/**
* @var DoliDB $db
* @var Translate $langs
*/

// Libraries
require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php";
Expand All @@ -38,7 +42,7 @@
use Cache\Adapter\Filesystem\FilesystemCachePool;

// Translations
$langs->loadLangs(["errors","admin","googleapi@googleapi"]);
$langs->loadLangs(['errors', 'admin', 'oauth', 'googleapi@googleapi']);

// Access control
if (! $user->admin) {
Expand Down Expand Up @@ -95,6 +99,13 @@
'CHECKLASTVERSION_EXTERNALMODULE' => 'CHECKLASTVERSION_EXTERNALMODULE',
];

$googleapicontexts = json_decode(getDolGlobalString('GOOGLEAPI_CONTEXTS_TO_SEND', '{}'), true);
if (empty($googleapicontexts)) {
// set default
dolibarr_set_const($db, 'GOOGLEAPI_CONTEXTS_TO_SEND', json_encode(['standard' => true]), 'chaine', 0, '', $conf->entity);
$googleapicontexts = json_decode(getDolGlobalString('GOOGLEAPI_CONTEXTS_TO_SEND', '{}'), true);
}

/*
* Actions
*/
Expand All @@ -108,6 +119,15 @@
//exit;
}
}
foreach ($googleapicontexts as $constant => $value) {
if ($action == 'contextenable_' . strtolower($constant)) {
$googleapicontexts[$constant] = true;
}
if ($action == 'contextdisable_' . strtolower($constant)) {
$googleapicontexts[$constant] = false;
}
dolibarr_set_const($db, 'GOOGLEAPI_CONTEXTS_TO_SEND', json_encode($googleapicontexts), 'chaine', 0, '', $conf->entity);
}
if ($action == 'update') {
$error = 0;
$db->begin();
Expand Down Expand Up @@ -145,7 +165,7 @@

if ($action == 'edit') {
print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
print '<input type="hidden" name="token" value="' . newToken() . '">';
print '<input type="hidden" name="action" value="update">';

//print $langs->trans("ListOfSupportedOauthProviders").'<br><br>';
Expand Down Expand Up @@ -234,6 +254,32 @@
}
print '</table>' . PHP_EOL;
print '<br>' . PHP_EOL;

// Contexts
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td>' . $langs->trans("GoogleApiSendContexts") . '</td>';
print '<td align="center" width="100">' . $langs->trans("Action") . '</td>';
print "</tr>\n";
foreach ($googleapicontexts as $constant => $value) {
print '<tr class="oddeven">';
print '<td>' . $langs->trans('GoogleApiEnabledContext', $constant) . '</td>';
print '<td align="center" width="100">';
// $value = (isset($conf->global->$constant) ? $conf->global->$constant : 0);
if (!$value) {
print '<a href="' . $_SERVER['PHP_SELF'] . '?action=contextenable_' . strtolower($constant) . '&amp;token=' . $_SESSION['newtoken'] . '">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print '</a>';
} elseif ($value) {
print '<a href="' . $_SERVER['PHP_SELF'] . '?action=contextdisable_' . strtolower($constant) . '&amp;token=' . $_SESSION['newtoken'] . '">';
print img_picto($langs->trans("Enabled"), 'switch_on');
print '</a>';
}
print "</td>";
print '</tr>';
}
print "</table>\n";
print "<br>\n";
}

print dol_get_fiche_end();
Expand Down
91 changes: 73 additions & 18 deletions class/actions_googleapi.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,14 @@
'googleapiremindemail' => [
'label' => $langs->trans('GoogleApiRemindByEmail'),
'disabled' => 0,
'mode' => 'email',
'data-html' => img_picto('', 'googleapi@googleapi', 'class="pictofixedwidth"') . $langs->trans('GoogleApiRemindByEmail'),
],
'googleapiremindnotif' => [
'label' => $langs->trans('GoogleApiRemindByNotification'),
'disabled' => 0,
'mode' => 'browser',
'data-html' => img_picto('', 'googleapi@googleapi', 'class="pictofixedwidth"') . $langs->trans('GoogleApiRemindByNotification'),
]
]
);
Expand Down Expand Up @@ -191,9 +195,6 @@
{
global $langs, $conf, $user;

// var_dump($parameters['object']);
// var_dump($parameters['mode']);
// var_dump($parameters);
if (!isset($parameters['object']->element)) {
return 0;
}
Expand Down Expand Up @@ -224,7 +225,7 @@
$sql .= ' AND fk_object=' . (int) $id;
$resql = $this->db->query($sql);
if ($resql && $obj = $this->db->fetch_object($resql)) {
$emailcount = $obj->nb;
$emailcount = (int) $obj->nb;
}
// If setting cache fails, this is not a problem, so we do not test result.
dol_setcache($cachekey, $emailcount, 120);
Expand Down Expand Up @@ -280,29 +281,40 @@
$error = 0; // Error counter
$contexts = explode(':', $parameters['context']);

// print '<pre>'.print_r($parameters, true).'</pre>';
// print '<pre>'.print_r($object, true).'</pre>';
// echo "action: " . $action;exit;
$context = $object->sendcontext ?? 'standard';
$googleapicontexts = json_decode(getDolGlobalString('GOOGLEAPI_CONTEXTS_TO_SEND', '{}'), true);
if (empty($googleapicontexts)) {
// set default
dolibarr_set_const($this->db, 'GOOGLEAPI_CONTEXTS_TO_SEND', json_encode(['standard' => true]), 'chaine', 0, '', $conf->entity);
$googleapicontexts = json_decode(getDolGlobalString('GOOGLEAPI_CONTEXTS_TO_SEND', '{}'), true);
}
if (!array_key_exists($context, $googleapicontexts)) {
// we found a new context
$googleapicontexts = array_merge($googleapicontexts, [$context => false]);
dolibarr_set_const($this->db, 'GOOGLEAPI_CONTEXTS_TO_SEND', json_encode($googleapicontexts), 'chaine', 0, '', $conf->entity);
}
$googleapicontextsok = [];
foreach ($googleapicontexts as $key => $item) {
if ($item) {
$googleapicontextsok[] = $key;
}
}
// what TODO with context 'emailing'
// context notification?
// https://developers.google.com/resources/api-libraries/documentation/gmail/v1/php/latest/class-Google_Service_Gmail_Message.html
if (in_array('mail', $contexts) && !in_array($object->sendcontext, ['emailing', 'notification'])) {
if (in_array($context, $googleapicontextsok)) {
dol_include_once('/googleapi/lib/googleapi.lib.php');
$fromsender = $this->getArrayAddress($object->addr_from);
if (!empty($user->array_options['options_googleapi_email']) && $fromsender[0]['address'] == $user->array_options['options_googleapi_email']) {
$client = getGoogleApiClient($user);
$service = new Google\Service\Gmail($client);

$replytosender = $this->getArrayAddress($object->reply_to);
$addrtorecipients = $this->getArrayAddress($object->addr_to);
$addrccrecipients = $this->getArrayAddress($object->addr_cc);
$addrbccrecipients = $this->getArrayAddress($object->addr_bcc);

$message = new Google\Service\Gmail\Message();
$mime = rtrim(strtr(base64_encode($object->message), '+/', '-_'), '=');
$mime = rtrim(strtr(base64_encode($this->buildRawMessage($object)), '+/', '-_'), '=');
$message->setRaw($mime);

$mailsent = false;
$response = null;
try {
$response = $service->users_messages->send('me', $message);
$mailsent = true;
Expand All @@ -314,24 +326,67 @@
if ($mailsent) {
$googleapiMessageId = $response->getId();
}
//var_dump($response);exit;
} else {
// nothing done
return 0;
}
}

if (!$error) {
//$this->results = array('msgid' => 'azerty');
//$this->resprints = 'A text to show';
// 1 si on a envoyé avec googleapi sinon 0
return 1; // or return 1 to replace standard code
} else {
$this->errors[] = 'Error message';
$this->errors[] = 'Error in googleapi module';
return -1;
}
}

/**
* Build a full RFC 822 raw message (headers + body + attachments) from a CMailFile object,
* suitable for the Gmail API 'raw' field.
*
* CMailFile only populates $object->headers/$object->message (the MIME parts used here) when
* $object->sendmode == 'mail'. On this instance MAIN_MAIL_SENDMODE is 'smtps', so those
* properties are never filled and used to be encoded empty, silently breaking every mail sent
* through this hook. Rebuilding the message here from data that CMailFile always populates
* (subject, addr_to/cc/bcc, html/msg, attachments, ...) makes this independent of sendmode.
*
* @param CMailFile $object The mail object to process
* @return string Full raw RFC 822 message
*/
private function buildRawMessage($object)
{
$subjecttouse = $object->subject;
if (!ascii_check($subjecttouse)) {
$subjecttouse = CMailFile::encodetorfc2822($subjecttouse);
}

$headers = "To: ".CMailFile::getValidAddress($object->addr_to, 0, 1).$object->eol2;

Check failure on line 364 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space after "."; 0 found

Check failure on line 364 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space before "."; 0 found

Check failure on line 364 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space after "."; 0 found

Check failure on line 364 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space before "."; 0 found
$headers .= "Subject: ".$subjecttouse.$object->eol2;

Check failure on line 365 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space after "."; 0 found

Check failure on line 365 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space before "."; 0 found

Check failure on line 365 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space after "."; 0 found

Check failure on line 365 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space before "."; 0 found
$headers .= $object->write_smtpheaders();
$headers .= $object->write_mimeheaders($object->filename_list, $object->mimefilename_list);
$headers = preg_replace("/([\r\n]+)$/i", "", $headers);

$msgforbody = $object->msgishtml ? $object->html : $object->msg;
$body = $object->write_body($msgforbody);

$filesencoded = '';
if (!empty($object->atleastonefile) && is_array($object->filename_list)) {
$refmethod = new ReflectionMethod($object, 'write_files');
$refmethod->setAccessible(true);
$result = $refmethod->invoke($object, $object->filename_list, $object->mimetype_list, $object->mimefilename_list, $object->cid_list);
if (is_string($result)) {
$filesencoded = $result;
}
}

$rawmessage = $headers.$object->eol.$object->eol; // Blank line to separate headers from body

Check failure on line 383 in class/actions_googleapi.class.php

View workflow job for this annotation

GitHub Actions / build

Expected at least 1 space before "."; 0 found
$rawmessage .= $body.$filesencoded;
$rawmessage .= "--".$object->mixed_boundary."--".$object->eol;

return $rawmessage;
}

/**
* Overloading the sendMailAfter function : replacing the parent's function with the one below
*
Expand Down
8 changes: 6 additions & 2 deletions class/googleapi.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ private function chekValidPushNotificationForEvents($user, $urlfornotification)
dol_include_once('/prune/vendor/autoload.php');
$client = getGoogleApiClient($user);
$service = new Google\Service\Calendar($client);
$calendarId = $user->array_options['options_googleapi_calendarId'] ?: 'primary';

$sql = "SELECT rowid, userid, uuid, id, resourcetype, resourceUri, ressourceId, expirationDateTime, lastmessagenumber FROM " . MAIN_DB_PREFIX . "googleapi_watchs";
$sql .= ' WHERE userid=' . (int) $user->id . ' AND resourcetype="events"';
Expand All @@ -143,7 +144,6 @@ private function chekValidPushNotificationForEvents($user, $urlfornotification)
if ($resql && $this->db->num_rows($resql) > 0) {
// on a déjà quelquechose
$row = $this->db->fetch_object($resql);
$calendarId = $user->array_options['options_googleapi_calendarId'] ?: 'primary';

// is it going to expire in 30min
// expiration is gmt
Expand Down Expand Up @@ -217,6 +217,7 @@ private function chekValidPushNotificationForEvents($user, $urlfornotification)
$resql = $this->db->query($sql);
} catch (Exception $e) {
dol_syslog($e->getmessage(), LOG_ERR);
return -1;
}
//exit;
}
Expand Down Expand Up @@ -313,17 +314,19 @@ private function chekValidPushNotificationForContacts($user, $urlfornotification
$sql .= ", 'contacts'";
$sql .= ", '" . $this->db->escape($watch->getResourceUri()) . "'";
$sql .= ", '" . $this->db->escape($watch->getResourceId()) . "'";
//$sql .= ", '" . ($watch->getExpiration())->format('Y-m-d H:i:s') . "'";
// $sql .= ", '" . ($watch->getExpiration())->format('Y-m-d H:i:s') . "'";
// timestamp in ms
$sql .= ", '" . ($this->db->idate(substr($watch->getExpiration(), 0, -3))) . "'";
$sql .= ", '1')";

$resql = $this->db->query($sql);
} catch (Exception $e) {
dol_syslog($e->getmessage(), LOG_ERR);
return -1;
}
//exit;
}

return 0;
}

Expand All @@ -333,6 +336,7 @@ private function chekValidPushNotificationForContacts($user, $urlfornotification
*/
private function getUuid()
{
$data = '0123456789012345';
try {
$data = random_bytes(16);
} catch (Exception $e) {
Expand Down
2 changes: 1 addition & 1 deletion config.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/*
* Copyright (C) 2019-2021 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2019-2026 Frédéric France <frederic.france@netlogic.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down
Loading
Loading