support for local users with extra-data needed for activity-pub

develop
Sascha Nitsch 2024-07-19 20:37:09 +02:00
parent 199922299d
commit 0d3a7c871b
7 changed files with 76 additions and 11 deletions

View File

@ -13,6 +13,13 @@ namespace Federator\Data;
*/ */
class User class User
{ {
/**
* user id on the external system
*
* @var string $externalid
*/
public $externalid;
/** /**
* user id * user id
* *
@ -52,6 +59,7 @@ class User
} }
$user = new User(); $user = new User();
$user->id = $data['id']; $user->id = $data['id'];
$user->externalid = $data['externalid'];
/// TODO: replace with enums /// TODO: replace with enums
$user->permissions = $data['permissions']; $user->permissions = $data['permissions'];
return $user; return $user;
@ -79,6 +87,7 @@ class User
{ {
$data = [ $data = [
'id' => $this->id, 'id' => $this->id,
'externalid' => $this->externalid,
'permissions' => $this->permissions 'permissions' => $this->permissions
]; ];
return json_encode($data) | ''; return json_encode($data) | '';

View File

@ -14,14 +14,60 @@ namespace Federator\DIO;
class User class User
{ {
/** /**
* extend the given user with internal data * add local user based on given user object received from remote service
* @param \mysqli $dbh database handle @unused-param * @param \mysqli $dbh database handle
* @param \Federator\Data\User $user user to extend @unused-param * @param \Federator\Data\User $user user object to use
* @param string $_user user/profile name
* @return void
*/ */
protected static function extendUser(\mysqli $dbh, \Federator\Data\User $user) : void protected static function addLocalUser($dbh, $user, $_user)
{ {
// do nothing for now echo "a new user\n";
// TODO: if a new user, create own database entry with additionally needed info // needed fields: RSA key pair, user name (handle)
$private_key = openssl_pkey_new();
if ($private_key === false) {
throw new \Federator\Exceptions\ServerError();
}
$public = openssl_pkey_get_details($private_key)['key'];
$private = '';
openssl_pkey_export($private_key, $private);
$sql = 'insert into users (id, externalid, rsapublic, rsaprivate) values (?, ?, ?, ?)';
$stmt = $dbh->prepare($sql);
if ($stmt === false) {
throw new \Federator\Exceptions\ServerError();
}
$stmt->bind_param("ssss", $_user, $user->externalid, $public, $private);
$stmt->execute();
$stmt->close();
}
/**
* extend the given user with internal data
* @param \mysqli $dbh database handle
* @param \Federator\Data\User $user user to extend
* @param string $_user user/profile name
*/
protected static function extendUser(\mysqli $dbh, $user, $_user) : void
{
$sql = 'select id from users where id=?';
$stmt = $dbh->prepare($sql);
if ($stmt === false) {
throw new \Federator\Exceptions\ServerError();
}
$stmt->bind_param("s", $_user);
$ret = $stmt->bind_result($user->id);
$stmt->execute();
if ($ret) {
$stmt->fetch();
}
$stmt->close();
// if a new user, create own database entry with additionally needed info
if ($user->id === null) {
self::addLocalUser($dbh, $user, $_user);
}
// no further processing for now
} }
/** /**
@ -55,7 +101,7 @@ class User
if ($user === false) { if ($user === false) {
return false; return false;
} }
self::extendUser($dbh, $user); self::extendUser($dbh, $user, $_user);
if ($cache !== null && $saveToCache) { if ($cache !== null && $saveToCache) {
$cache->saveRemoteUserBySession($_session, $_user, $user); $cache->saveRemoteUserBySession($_session, $_user, $user);
} }

View File

@ -29,7 +29,7 @@ class DummyConnector implements Connector
{ {
// validate $_session and $user // validate $_session and $user
$user = new \Federator\Data\User(); $user = new \Federator\Data\User();
$user->id = $_user; $user->externalid = $_user;
$user->permissions = ['PUBLISH']; $user->permissions = ['PUBLISH'];
$user->session = $_session; $user->session = $_session;
return $user; return $user;

View File

@ -34,6 +34,13 @@ class RedisCache implements Cache
*/ */
private $redis; private $redis;
/**
* user cache time to life
*
* @var int time to life in secons
*/
private $userTTL;
/** /**
* constructor * constructor
*/ */
@ -42,6 +49,7 @@ class RedisCache implements Cache
$config = parse_ini_file('../rediscache.ini'); $config = parse_ini_file('../rediscache.ini');
if ($config !== false) { if ($config !== false) {
$this->config = $config; $this->config = $config;
$this->userTTL = array_key_exists('userttl', $config) ? intval($config['userttl'], 10) : 60;
} }
} }
@ -104,7 +112,7 @@ class RedisCache implements Cache
{ {
$key = self::createKey('u', $_session, $_user); $key = self::createKey('u', $_session, $_user);
$serialized = $user->toJson(); $serialized = $user->toJson();
$this->redis->set($key, $serialized); $this->redis->setEx($key, $this->userTTL, $serialized,);
} }
} }

View File

@ -15,8 +15,8 @@ primary goal is to connect ContentNation via ActivityPub again.
- [X] API framework - [X] API framework
- [X] interfact to connect to existing service - [X] interfact to connect to existing service
- [X] cache layer for users minmal version - [X] cache layer for users minmal version
- [ ] overlay to extend with needed info like private keys, urls, ... - [X] overlay to extend with needed info like private keys, urls, ...
- [ ] full cache for users - [X] full cache for users
- [ ] webfinger - [ ] webfinger
- [ ] discovery endpoints - [ ] discovery endpoints
- [ ] ap outbox - [ ] ap outbox

View File

@ -3,3 +3,4 @@ host = localhost
port = 6379 port = 6379
username = federator username = federator
password = redis*change*password password = redis*change*password
userttl = 10

View File

@ -1,2 +1,3 @@
create table settings(`key` varchar(255) unique primary key, `value` text); create table settings(`key` varchar(255) unique primary key, `value` text);
create table users(`id` varchar(255) unique primary key, `externalid` varchar(255), index(`externalid`), `rsapublic` text, `rsaprivate` text);
insert into settings (`key`, `value`) value ("database_version", "2024-08-19"); insert into settings (`key`, `value`) value ("database_version", "2024-08-19");