Compare commits
	
		
			2 commits
		
	
	
		
			6ea9c2728f
			...
			a32220442c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | a32220442c | ||
|   | d96b05a658 | 
					 15 changed files with 159 additions and 29 deletions
				
			
		|  | @ -359,6 +359,9 @@ return [ | ||||||
|     'directory_list' => [ |     'directory_list' => [ | ||||||
|         'vendor/phan/phan/src/Phan', |         'vendor/phan/phan/src/Phan', | ||||||
|         'vendor/smarty/smarty/src', |         'vendor/smarty/smarty/src', | ||||||
|  |         'php/', | ||||||
|  |         'plugins', | ||||||
|  |         'htdocs', | ||||||
|     ], |     ], | ||||||
| 
 | 
 | ||||||
|     // A list of individual files to include in analysis
 |     // A list of individual files to include in analysis
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,12 @@ Needed SQL commands: | ||||||
| 
 | 
 | ||||||
| This will be changed, but works for the current develop verison. | 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: | To configure an apache server, add the following rewrite rules: | ||||||
| 
 | 
 | ||||||
|     <Directory /where/ever/you/put/it> |     <Directory /where/ever/you/put/it> | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ if (! array_key_exists('_call', $_REQUEST)) { | ||||||
|     exit(); |     exit(); | ||||||
| } | } | ||||||
| date_default_timezone_set("Europe/Berlin"); | date_default_timezone_set("Europe/Berlin"); | ||||||
| spl_autoload_register(function ($className) { | spl_autoload_register(static function (string $className) { | ||||||
|     // strip Federator from class path
 |     // strip Federator from class path
 | ||||||
|     $className = str_replace('Federator\\', '', $className); |     $className = str_replace('Federator\\', '', $className); | ||||||
|     include '../php/' . str_replace("\\", "/", strtolower($className)) . '.php'; |     include '../php/' . str_replace("\\", "/", strtolower($className)) . '.php'; | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								php/api.php
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								php/api.php
									
										
									
									
									
								
							|  | @ -30,7 +30,7 @@ class Api extends Main | ||||||
|     /** |     /** | ||||||
|      * current user |      * current user | ||||||
|      * |      * | ||||||
|      * @var Data\User $user |      * @var Data\User|false $user | ||||||
|      * */ |      * */ | ||||||
|     private $user; |     private $user; | ||||||
| 
 | 
 | ||||||
|  | @ -56,8 +56,9 @@ class Api extends Main | ||||||
|      * |      * | ||||||
|      * @param string $call |      * @param string $call | ||||||
|      *          path of called function
 |      *          path of called function
 | ||||||
|  |      * @return void | ||||||
|      */ |      */ | ||||||
|     public function setPath(string $call) : void |     public function setPath($call) | ||||||
|     { |     { | ||||||
|         $this->path = $call; |         $this->path = $call; | ||||||
|         while ($this->path[0] === '/') { |         while ($this->path[0] === '/') { | ||||||
|  | @ -71,7 +72,7 @@ class Api extends Main | ||||||
|      */ |      */ | ||||||
|     public function run() : void |     public function run() : void | ||||||
|     { |     { | ||||||
|         $this->setPath($_REQUEST["_call"]); |         $this->setPath((string)$_REQUEST['_call']); | ||||||
|         $this->openDatabase(); |         $this->openDatabase(); | ||||||
|         $this->loadPlugins(); |         $this->loadPlugins(); | ||||||
|         $retval = ""; |         $retval = ""; | ||||||
|  | @ -131,6 +132,7 @@ class Api extends Main | ||||||
|             if ($this->redirect !== null) { |             if ($this->redirect !== null) { | ||||||
|                 header("Location: $this->redirect"); |                 header("Location: $this->redirect"); | ||||||
|             } |             } | ||||||
|  |             // @phan-suppress-next-line PhanSuspiciousValueComparison
 | ||||||
|             if ($this->responseCode != 200) { |             if ($this->responseCode != 200) { | ||||||
|                 http_response_code($this->responseCode); |                 http_response_code($this->responseCode); | ||||||
|             } |             } | ||||||
|  | @ -168,6 +170,9 @@ class Api extends Main | ||||||
|     public function checkPermission($permission, $exception = "\Exceptions\PermissionDenied", $message = null) : void |     public function checkPermission($permission, $exception = "\Exceptions\PermissionDenied", $message = null) : void | ||||||
|     { |     { | ||||||
|         // generic check first
 |         // generic check first
 | ||||||
|  |         if ($this->user === false) { | ||||||
|  |             throw new Exceptions\PermissionDenied(); | ||||||
|  |         } | ||||||
|         if ($this->user->id == 0) { |         if ($this->user->id == 0) { | ||||||
|             throw new Exceptions\PermissionDenied(); |             throw new Exceptions\PermissionDenied(); | ||||||
|         } |         } | ||||||
|  | @ -228,10 +233,7 @@ class Api extends Main | ||||||
|         if ($int === true) { |         if ($int === true) { | ||||||
|             return intval($_POST[$key]); |             return intval($_POST[$key]); | ||||||
|         } |         } | ||||||
|         $ret = $this->dbh->escape_string($this->stripHTML($_POST[$key])); |         $ret = $this->dbh->escape_string($this->stripHTML((string)$_POST[$key])); | ||||||
|         if ($ret === false) { |  | ||||||
|             return $int ? 0 : ""; |  | ||||||
|         } |  | ||||||
|         return $ret; |         return $ret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ class Dummy implements \Federator\Api\V1 | ||||||
|     /** |     /** | ||||||
|      * constructor |      * constructor | ||||||
|      * |      * | ||||||
|      * @param \Main $main main instance |      * @param \Federator\Main $main main instance | ||||||
|      */ |      */ | ||||||
|     public function __construct(\Federator\Main $main) |     public function __construct(\Federator\Main $main) | ||||||
|     { |     { | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								php/cache/cache.php
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								php/cache/cache.php
									
										
									
									
										vendored
									
									
								
							|  | @ -15,9 +15,10 @@ interface Cache extends \Federator\Connector\Connector | ||||||
| { | { | ||||||
|     /** |     /** | ||||||
|      * save remote user by given session |      * save remote user by given session | ||||||
|  |      * | ||||||
|      * @param string $_session session id |      * @param string $_session session id | ||||||
|      * @param string $_user user/profile name |      * @param string $_user user/profile name | ||||||
|      * @aramm \Federator\Data\User $user user data |      * @param \Federator\Data\User $user user data | ||||||
|      * @return void |      * @return void | ||||||
|      */ |      */ | ||||||
|     public function saveRemoteUserBySession($_session, $_user, $user); |     public function saveRemoteUserBySession($_session, $_user, $user); | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ interface Connector | ||||||
| { | { | ||||||
|     /** |     /** | ||||||
|      * get remote user by given session |      * get remote user by given session | ||||||
|  |      * | ||||||
|      * @param string $_session session id |      * @param string $_session session id | ||||||
|      * @param string $_user user/profile name |      * @param string $_user user/profile name | ||||||
|      * @return \Federator\Data\User | false |      * @return \Federator\Data\User | false | ||||||
|  |  | ||||||
|  | @ -38,6 +38,25 @@ class User | ||||||
|      * */ |      * */ | ||||||
|     public $session; |     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 |      * check if use has asked permission | ||||||
|      * @param string $p @unused-param |      * @param string $p @unused-param | ||||||
|  | @ -48,6 +67,20 @@ class User | ||||||
|      */ |      */ | ||||||
|     public function hasPermission(string $p) |     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) | ''; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,28 +33,32 @@ class User | ||||||
|      *          session |      *          session | ||||||
|      * @param string $_user |      * @param string $_user | ||||||
|      *          user/profile name |      *          user/profile name | ||||||
|      * @param \Connector\Connector? $connector @unused-param |      * @param \Federator\Connector\Connector $connector | ||||||
|      *          connector to fetch use with |      *          connector to fetch use with | ||||||
|      * @param \Cache\Cache? $cache |      * @param \Federator\Cache\Cache|null $cache | ||||||
|      *          optional caching service |      *          optional caching service | ||||||
|      * @return \Data\User|bool |      * @return \Federator\Data\User|false | ||||||
|      */ |      */ | ||||||
|     public static function getUserBySession($dbh, $_session, $_user, $connector, $cache) |     public static function getUserBySession($dbh, $_session, $_user, $connector, $cache) | ||||||
|     { |     { | ||||||
|  |         $saveToCache = false; | ||||||
|         $user = false; |         $user = false; | ||||||
|         if ($cache) { |         if ($cache !== null) { | ||||||
|             $user = $cache->getRemoteUserBySession($_session, $_user); |             $user = $cache->getRemoteUserBySession($_session, $_user); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // ask connector for user-id
 |         if ($user === false) { | ||||||
|         $user = $connector->getRemoteUserBySession($_session, $_user); |             // ask connector for user-id
 | ||||||
|  |             $user = $connector->getRemoteUserBySession($_session, $_user); | ||||||
|  |             $saveToCache = true; | ||||||
|  |         } | ||||||
|         if ($user === false) { |         if ($user === false) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         if ($cache) { |         self::extendUser($dbh, $user); | ||||||
|  |         if ($cache !== null && $saveToCache) { | ||||||
|             $cache->saveRemoteUserBySession($_session, $_user, $user); |             $cache->saveRemoteUserBySession($_session, $_user, $user); | ||||||
|         } |         } | ||||||
|         self::extendUser($dbh, $user); |  | ||||||
|         return $user; |         return $user; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ class Language | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if ($uselang === null && array_key_exists('_lang', $_REQUEST)) { |         if ($uselang === null && array_key_exists('_lang', $_REQUEST)) { | ||||||
|             $language = $_REQUEST['_lang']; |             $language = (string)$_REQUEST['_lang']; | ||||||
|             if (array_key_exists($language, $this->validLanguages)) { |             if (array_key_exists($language, $this->validLanguages)) { | ||||||
|                 $uselang = $language; |                 $uselang = $language; | ||||||
|             } |             } | ||||||
|  | @ -126,7 +126,7 @@ class Language | ||||||
|      * |      * | ||||||
|      * @param string $group |      * @param string $group | ||||||
|      *          group name to fetch keys |      *          group name to fetch keys | ||||||
|      * @return array<string> list of keys |      * @return list<string> list of keys | ||||||
|      */ |      */ | ||||||
|     public function getKeys(string $group) |     public function getKeys(string $group) | ||||||
|     { |     { | ||||||
|  | @ -135,6 +135,7 @@ class Language | ||||||
|             require_once($_SERVER['DOCUMENT_ROOT'] . '/../lang/' . $this->uselang . "/$group.inc"); |             require_once($_SERVER['DOCUMENT_ROOT'] . '/../lang/' . $this->uselang . "/$group.inc"); | ||||||
|             $this->lang[$group] = $l; |             $this->lang[$group] = $l; | ||||||
|         } |         } | ||||||
|  |         // @phan-suppress-next-line PhanPartialTypeMismatchReturn
 | ||||||
|         return array_keys($this->lang[$group]); |         return array_keys($this->lang[$group]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -263,11 +264,11 @@ function smarty_function_printlang($params, $template) : string | ||||||
| { | { | ||||||
|     $lang = $template->getTemplateVars("language"); |     $lang = $template->getTemplateVars("language"); | ||||||
|     <<<'PHAN' |     <<<'PHAN' | ||||||
|       @phan-var \Language $lang |       @phan-var \Federator\Language $lang | ||||||
|       PHAN; |       PHAN; | ||||||
|     $forcelang = array_key_exists('lang', $params) ? $params['lang'] : null; |     $forcelang = array_key_exists('lang', $params) ? $params['lang'] : null; | ||||||
|     if ($forcelang !== null) { |     if ($forcelang !== null) { | ||||||
|         $lang = new Language($forcelang); |         $lang = new \Federator\Language($forcelang); | ||||||
|     } |     } | ||||||
|     if (isset($params['var'])) { |     if (isset($params['var'])) { | ||||||
|         return $lang->printlang($params['group'], $params['key'], $params['var']); |         return $lang->printlang($params['group'], $params['key'], $params['var']); | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								php/main.php
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								php/main.php
									
										
									
									
									
								
							|  | @ -53,7 +53,7 @@ class Main | ||||||
|     /** |     /** | ||||||
|      * languange instance |      * languange instance | ||||||
|      * |      * | ||||||
|      * @var \Language $lang |      * @var Language $lang | ||||||
|      */ |      */ | ||||||
|     protected $lang = null; |     protected $lang = null; | ||||||
|     /** |     /** | ||||||
|  | @ -80,7 +80,11 @@ class Main | ||||||
|      */ |      */ | ||||||
|     public function __construct() |     public function __construct() | ||||||
|     { |     { | ||||||
|         $this->config = parse_ini_file('../config.ini', true); |         $this->responseCode = 200; | ||||||
|  |         $config = parse_ini_file('../config.ini', true); | ||||||
|  |         if ($config !== false) { | ||||||
|  |             $this->config = $config; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -92,6 +96,9 @@ class Main | ||||||
|     public static function getFromRemote(string $remoteURL, $headers) |     public static function getFromRemote(string $remoteURL, $headers) | ||||||
|     { |     { | ||||||
|         $ch = curl_init(); |         $ch = curl_init(); | ||||||
|  |         if ($ch === false) { | ||||||
|  |             return ['', null]; | ||||||
|  |         } | ||||||
|         curl_setopt($ch, CURLOPT_URL, $remoteURL); |         curl_setopt($ch, CURLOPT_URL, $remoteURL); | ||||||
|         curl_setopt($ch, CURLOPT_HEADER, 0); |         curl_setopt($ch, CURLOPT_HEADER, 0); | ||||||
|         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ class DummyConnector implements Connector | ||||||
|      * get remote user by given session |      * get remote user by given session | ||||||
|      * @param string $_session session id |      * @param string $_session session id | ||||||
|      * @param string $_user user or profile name |      * @param string $_user user or profile name | ||||||
|      * @return Data\User | false |      * @return \Federator\Data\User | false | ||||||
|      */ |      */ | ||||||
|     public function getRemoteUserBySession(string $_session, string $_user) |     public function getRemoteUserBySession(string $_session, string $_user) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -13,6 +13,20 @@ namespace Federator\Cache; | ||||||
|  */ |  */ | ||||||
| class RedisCache implements Cache | class RedisCache implements Cache | ||||||
| { | { | ||||||
|  |     /** | ||||||
|  |      * config data | ||||||
|  |      * | ||||||
|  |      * @var array<string, mixed> $config | ||||||
|  |      */ | ||||||
|  |     private $config; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * connection to redis open flag | ||||||
|  |      * | ||||||
|  |      * @var bool $connected | ||||||
|  |      */ | ||||||
|  |     private $connected = false; | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * connection handle |      * connection handle | ||||||
|      * |      * | ||||||
|  | @ -25,20 +39,72 @@ class RedisCache implements Cache | ||||||
|      */ |      */ | ||||||
|     public function __construct() |     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) |     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) |     public function saveRemoteUserBySession($_session, $_user, $user) | ||||||
|     { |     { | ||||||
|  |         $key = self::createKey('u', $_session, $_user); | ||||||
|  |         $serialized = $user->toJson(); | ||||||
|  |         $this->redis->set($key, $serialized); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,8 +14,9 @@ primary goal is to connect ContentNation via ActivityPub again. | ||||||
| ## roadmap to v1.0 | ## roadmap to v1.0 | ||||||
| - [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 | ||||||
| - [ ] overlay to extend with needed info like private keys, urls, ... | - [ ] overlay to extend with needed info like private keys, urls, ... | ||||||
| - [ ] cache layer for users | - [ ] full cache for users | ||||||
| - [ ] webfinger | - [ ] webfinger | ||||||
| - [ ] discovery endpoints | - [ ] discovery endpoints | ||||||
| - [ ] ap outbox | - [ ] ap outbox | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								rediscache.ini
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								rediscache.ini
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | [redis] | ||||||
|  | host = localhost | ||||||
|  | port = 6379 | ||||||
|  | username = federator | ||||||
|  | password = redis*change*password | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue