Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/plugins/kolab/Kolab/Client.php b/plugins/kolab/Kolab/Client.php
index dcca2b2d..27133e22 100644
--- a/plugins/kolab/Kolab/Client.php
+++ b/plugins/kolab/Kolab/Client.php
@@ -1,344 +1,350 @@
<?php
namespace Kolab;
/**
* Kolab Cockpit API (HTTP) client
*/
class Client
{
protected static $cached_requests = [
'get:api/v4/config/webmail',
'get:api/v4/users/%d/delegators',
];
/**
* Makes a HTTP request to the Cockpit API
*/
private static function request($method, $path, $query = [], $post = [])
{
// Get the response from cache
if ($cache_key = self::cacheKey($method, $path)) {
if ($response = self::cacheGet($cache_key)) {
return $response;
}
}
$rcube = \rcube::get_instance();
$base_uri = $rcube->config->get('kolab_api_url', 'https://' . $_SERVER['HTTP_HOST']);
$debug = $rcube->config->get('kolab_api_debug');
$path = ltrim($path, '/');
$stack = new \GuzzleHttp\HandlerStack();
$stack->setHandler(\GuzzleHttp\choose_handler());
if (!str_starts_with($path, 'api/auth/login')) {
$stack->push(\GuzzleHttp\Middleware::retry(
function (
int $retries,
\GuzzleHttp\Psr7\Request $request,
\GuzzleHttp\Psr7\Response $response = null,
$exception = null
) {
$maxRetries = 2;
if ($retries >= $maxRetries) {
return false;
}
if ($response && $response->getStatusCode() === 401) {
self::refreshAccessToken();
return true;
}
return false;
},
function (int $retries) {
return 0; // no delay on retry
}
));
}
$stack->push(\GuzzleHttp\Middleware::mapRequest(
function (\GuzzleHttp\Psr7\Request $request) use ($rcube, $debug) {
if ($debug) {
self::requestDebug($request);
}
if (!str_starts_with($request->getUri()->getPath(), '/api/auth/login')) {
if (isset($_SESSION['kolab_access_token'])) {
$token = $rcube->decrypt($_SESSION['kolab_access_token']);
return $request->withHeader('Authorization', 'Bearer ' . $token);
}
}
return $request;
}
));
// Add response debug middleware
if ($debug) {
$stack->push(\GuzzleHttp\Middleware::mapResponse(
function (\Psr\Http\Message\ResponseInterface $response) use ($rcube) {
$code = $response->getStatusCode();
if ($code > 200) {
$rcube->write_log('kolab', '[' . $code . '] ' . $response->getReasonPhrase());
} else {
$rcube->write_log('kolab', '[' . $code . '] ' . (string) $response->getBody());
}
return $response;
}
));
}
$client = $rcube->get_http_client([
'http_errors' => false, // No exceptions from Guzzle on error responses
'base_uri' => rtrim($base_uri, '/') . '/',
'handler' => $stack,
'verify' => false,
'connect_timeout' => 5,
'timeout' => 10,
]);
try {
$request = [
'json' => $post,
'query' => $query,
];
$response = $client->request($method, $path, $request);
$code = $response->getStatusCode();
if ($code == 200) {
$json = json_decode((string) $response->getBody());
if ($cache_key) {
self::cacheSet($cache_key, $json);
}
return $json;
} else {
$rcube->raise_error("Request to $base_uri/$path failed [$code]: " . (string) $response->getBody(), true);
}
} catch (\Exception $e) {
$rcube->raise_error($e, true, false);
}
}
/**
* Get a new access token
*/
private static function refreshAccessToken()
{
$rcube = \rcube::get_instance();
$username = $rcube->get_user_name();
$password = $rcube->get_user_password();
- $response = self::request('POST', 'api/auth/login', [], ['email' => $username, 'password' => $password]);
+ $post = [
+ 'email' => $username,
+ 'password' => $password,
+ 'mode' => 'fast',
+ ];
+
+ $response = self::request('POST', 'api/auth/login', [], $post);
if ($response && isset($response->access_token)) {
$_SESSION['kolab_access_token'] = $rcube->encrypt($response->access_token);
$_SESSION['kolab_user_id'] = $response->id ?? null;
}
}
/**
* Request debug logger
*/
private static function requestDebug($request): void
{
$log_request = $request->getMethod() . ': ' . $request->getUri()->getPath();
$query = $request->getUri()->getQuery();
if (!empty($query)) {
$log_request .= '?' . $query;
}
\rcube::get_instance()->write_log('kolab', $log_request);
}
/**
* Returns current user contacts (global addressbook)
*/
public static function getContacts(string $search, int $limit): array
{
$response = self::request('GET', 'api/v4/search/contacts', ['search' => $search, 'limit' => $limit]);
if ($response && isset($response->list)) {
return $response->list;
}
return [];
}
/**
* Get current user delegators
*/
public static function getDelegators(): array
{
$result = [];
if ($id = self::getUserId()) {
$response = self::request('GET', "api/v4/users/{$id}/delegators");
if ($response && isset($response->list)) {
return $response->list;
}
}
return $result;
}
/**
* Returns current user email addresses
*/
public static function getMyAddresses(): array
{
$response = self::request('GET', 'api/v4/search/self', ['alias' => 1, 'limit' => 999]);
if ($response && isset($response->list)) {
return array_column($response->list, 'email');
}
return [];
}
/**
* Returns current user configuration
*/
public static function getMyConfig(): array
{
$rcube = \rcube::get_instance();
if ($rcube->get_user_name() && $rcube->get_user_password()) {
$response = self::request('GET', 'api/v4/config/webmail');
if ($response) {
return (array) $response;
}
}
return [];
}
/**
* Get current user identifier in Cockpit
*/
private static function getUserId()
{
if (empty($_SESSION['kolab_user_id'])) {
self::refreshAccessToken();
/*
$response = self::request('GET', 'api/auth/info');
if ($response && isset($response->id)) {
$_SESSION['kolab_user_id'] = $response->id;
}
*/
}
return $_SESSION['kolab_user_id'] ?? 0;
}
/**
* User search
*/
public static function getUsers(string $search, int $limit = 15): array
{
$response = self::request('GET', 'api/v4/search/user', ['alias' => 0, 'search' => $search, 'limit' => $limit]);
if ($response && isset($response->list)) {
return $response->list;
}
return [];
}
/**
* Resolve user email into user name
*/
/*
public static function getUserName(string $email): ?string
{
$response = self::request('GET', 'api/v4/search/user', ['alias' => 0, 'search' => $email, 'limit' => 10]);
if ($response && isset($response->list)) {
foreach ($response->list as $user) {
if ($user->email === $email) {
return $user->name;
}
}
}
return null;
}
*/
/**
* Clear all cache entries
*/
public static function cacheClear()
{
if ($cache = self::cacheInstance()) {
$cache->remove(null, true);
}
}
/**
* Get a value from the cache
*/
protected static function cacheGet($key)
{
$cache = self::cacheInstance();
return $cache ? $cache->get($key) : null;
}
/**
* Store a value in the cache
*/
protected static function cacheSet($key, $value)
{
if ($cache = self::cacheInstance()) {
$cache->set($key, $value);
}
}
/**
* Build a cache key for a request, if it's eligible for caching
*/
protected static function cacheKey($method, $path): ?string
{
// TODO: Support caching for requests with POST/GET arguments
$key = strtolower($method) . ':' . $path;
foreach (self::$cached_requests as $req) {
if ($key == $req) {
return $key;
}
$scan = sscanf($key, $req);
if (count($scan) >= 1 && !empty($scan[0])) {
return $key;
}
}
return null;
}
/**
* Get a cache object, if client cache is enabled
*/
protected static function cacheInstance(): ?\rcube_cache
{
$rcube = \rcube::get_instance();
if ($type = $rcube->config->get('kolab_client_cache')) {
$ttl = $rcube->config->get('kolab_client_cache_ttl', '10m');
return $rcube->get_cache('kolab_client', $type, $ttl);
}
return null;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 6, 2:00 AM (1 w, 7 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18831909
Default Alt Text
(10 KB)

Event Timeline