Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117885392
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Apr 6, 2:00 AM (1 w, 12 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18831909
Default Alt Text
(10 KB)
Attached To
Mode
rRPK roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline