From a32220442c8c4d36f343e7b08ba9a30ff8cfe951 Mon Sep 17 00:00:00 2001 From: Sascha Nitsch Date: Wed, 17 Jul 2024 21:45:33 +0200 Subject: [PATCH] basic redis cache support --- README.md | 6 ++++ php/data/user.php | 35 ++++++++++++++++++++- php/dio/user.php | 20 +++++++----- plugins/rediscache.php | 70 ++++++++++++++++++++++++++++++++++++++++-- progress.md | 3 +- rediscache.ini | 5 +++ 6 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 rediscache.ini diff --git a/README.md b/README.md index 61c7ed5..5bf2d67 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ Needed SQL commands: This will be changed, but works for the current develop verison. +If the include redis cache is enabled, create a users.acl for redis with the content: + + user federator on ~u_* +get +set >redis*change*password + +change password in the rediscache.ini to match your given password. + To configure an apache server, add the following rewrite rules: diff --git a/php/data/user.php b/php/data/user.php index ac94a60..78f8be1 100644 --- a/php/data/user.php +++ b/php/data/user.php @@ -38,6 +38,25 @@ class User * */ public $session; + /** + * create new user object from json string + * + * @param string $input input string + * @return User|false + */ + public static function createFromJson($input) + { + $data = json_decode($input, true); + if ($data === null) { + return false; + } + $user = new User(); + $user->id = $data['id']; + /// TODO: replace with enums + $user->permissions = $data['permissions']; + return $user; + } + /** * check if use has asked permission * @param string $p @unused-param @@ -48,6 +67,20 @@ class User */ public function hasPermission(string $p) { - return in_array($p, $this->permissions); + return in_array($p, $this->permissions, false); + } + + /** + * convert internal data to json string + * + * @return string + */ + public function toJson() + { + $data = [ + 'id' => $this->id, + 'permissions' => $this->permissions + ]; + return json_encode($data) | ''; } } diff --git a/php/dio/user.php b/php/dio/user.php index c1e5d86..e75d2c9 100644 --- a/php/dio/user.php +++ b/php/dio/user.php @@ -33,28 +33,32 @@ class User * session * @param string $_user * user/profile name - * @param \Connector\Connector? $connector @unused-param + * @param \Federator\Connector\Connector $connector * connector to fetch use with - * @param \Cache\Cache? $cache + * @param \Federator\Cache\Cache|null $cache * optional caching service - * @return \Data\User|bool + * @return \Federator\Data\User|false */ public static function getUserBySession($dbh, $_session, $_user, $connector, $cache) { + $saveToCache = false; $user = false; - if ($cache) { + if ($cache !== null) { $user = $cache->getRemoteUserBySession($_session, $_user); } - // ask connector for user-id - $user = $connector->getRemoteUserBySession($_session, $_user); + if ($user === false) { + // ask connector for user-id + $user = $connector->getRemoteUserBySession($_session, $_user); + $saveToCache = true; + } if ($user === false) { return false; } - if ($cache) { + self::extendUser($dbh, $user); + if ($cache !== null && $saveToCache) { $cache->saveRemoteUserBySession($_session, $_user, $user); } - self::extendUser($dbh, $user); return $user; } } diff --git a/plugins/rediscache.php b/plugins/rediscache.php index 63cb805..8bbef5f 100644 --- a/plugins/rediscache.php +++ b/plugins/rediscache.php @@ -13,6 +13,20 @@ namespace Federator\Cache; */ class RedisCache implements Cache { + /** + * config data + * + * @var array $config + */ + private $config; + + /** + * connection to redis open flag + * + * @var bool $connected + */ + private $connected = false; + /** * connection handle * @@ -25,20 +39,72 @@ class RedisCache implements Cache */ public function __construct() { + $config = parse_ini_file('../rediscache.ini'); + if ($config !== false) { + $this->config = $config; + } } /** - * {@inheritDoc} + * connect to redis + * @return void + */ + private function connect() + { + $this->redis = new \Redis(); + $this->redis->pconnect($this->config['host'], intval($this->config['port'], 10)); + // @phan-suppress-next-line PhanTypeMismatchArgumentInternalProbablyReal + $this->redis->auth([$this->config['username'], $this->config['password']]); + } + + /** + * create key from session and user + * + * @param string $prefix prefix to create name spaces + * @param string $_session session id + * @param string $_user user/profile name + * @return string key + */ + private static function createKey($prefix, $_session, $_user) + { + $key = $prefix . '_'; + $key .= md5($_session . $_user); + return $key; + } + /** + * get remote user by given session + * + * @param string $_session session id + * @param string $_user user/profile name + * @return \Federator\Data\User | false */ public function getRemoteUserBySession($_session, $_user) { + if (!$this->connected) { + $this->connect(); + } + $key = self::createKey('u', $_session, $_user); + $data = $this->redis->get($key); + if ($data === false) { + return false; + } + $user = \Federator\Data\User::createFromJson($data); + return $user; } /** - * {@inheritDoc} + * save remote user by given session + * + * @param string $_session session id + * @param string $_user user/profile name + * @param \Federator\Data\User $user user data + * @return void */ public function saveRemoteUserBySession($_session, $_user, $user) { + $key = self::createKey('u', $_session, $_user); + $serialized = $user->toJson(); + $this->redis->set($key, $serialized); } } diff --git a/progress.md b/progress.md index 851b42c..1f0494d 100644 --- a/progress.md +++ b/progress.md @@ -14,8 +14,9 @@ primary goal is to connect ContentNation via ActivityPub again. ## roadmap to v1.0 - [X] API framework - [X] interfact to connect to existing service +- [X] cache layer for users minmal version - [ ] overlay to extend with needed info like private keys, urls, ... -- [ ] cache layer for users +- [ ] full cache for users - [ ] webfinger - [ ] discovery endpoints - [ ] ap outbox diff --git a/rediscache.ini b/rediscache.ini new file mode 100644 index 0000000..52244cd --- /dev/null +++ b/rediscache.ini @@ -0,0 +1,5 @@ +[redis] +host = localhost +port = 6379 +username = federator +password = redis*change*password