forked from grumpydevelop/federator
		
	initial webfinger support
This commit is contained in:
		
							parent
							
								
									eed9678dbf
								
							
						
					
					
						commit
						47efd74b6c
					
				
					 12 changed files with 364 additions and 59 deletions
				
			
		| 
						 | 
				
			
			@ -39,6 +39,7 @@ To configure an apache server, add the following rewrite rules:
 | 
			
		|||
      RewriteEngine on
 | 
			
		||||
      RewriteBase /
 | 
			
		||||
      RewriteRule ^api/(.+)$ api.php?_call=$1 [L]
 | 
			
		||||
      RewriteRule ^(\.well-known/.*)$ /api.php?_call=$1 [L,END]
 | 
			
		||||
    </Directory>
 | 
			
		||||
 | 
			
		||||
With the dummy plugin and everything installed correctly a
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
[generic]
 | 
			
		||||
externaldomain = 'your.fqdn'
 | 
			
		||||
 | 
			
		||||
[database]
 | 
			
		||||
host = '127.0.0.1'
 | 
			
		||||
username = 'federator'
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +8,7 @@ password = '*change*me*'
 | 
			
		|||
database = 'federator'
 | 
			
		||||
 | 
			
		||||
[templates]
 | 
			
		||||
path = '../templates/'
 | 
			
		||||
path = '../templates/federator/'
 | 
			
		||||
compiledir = '../cache'
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,6 @@ class Api extends Main
 | 
			
		|||
     */
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        $this->smarty = null;
 | 
			
		||||
        $this->contentType = "application/json";
 | 
			
		||||
        Main::__construct();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -77,40 +76,39 @@ class Api extends Main
 | 
			
		|||
        $this->loadPlugins();
 | 
			
		||||
        $retval = "";
 | 
			
		||||
        $handler = null;
 | 
			
		||||
        if (!array_key_exists('HTTP_X_SESSION', $_SERVER) || !array_key_exists('HTTP_X_PROFILE', $_SERVER)) {
 | 
			
		||||
            http_response_code(403);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if ($this->connector === null) {
 | 
			
		||||
            http_response_code(500);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        $this->user = DIO\User::getUserBySession(
 | 
			
		||||
            $this->dbh,
 | 
			
		||||
            $_SERVER['HTTP_X_SESSION'],
 | 
			
		||||
            $_SERVER['HTTP_X_PROFILE'],
 | 
			
		||||
            $this->connector,
 | 
			
		||||
            $this->cache
 | 
			
		||||
        );
 | 
			
		||||
        if ($this->user === false) {
 | 
			
		||||
            http_response_code(403);
 | 
			
		||||
            return;
 | 
			
		||||
        if (array_key_exists('HTTP_X_SESSION', $_SERVER) && array_key_exists('HTTP_X_PROFILE', $_SERVER)) {
 | 
			
		||||
            $this->user = DIO\User::getUserBySession(
 | 
			
		||||
                $this->dbh,
 | 
			
		||||
                $_SERVER['HTTP_X_SESSION'],
 | 
			
		||||
                $_SERVER['HTTP_X_PROFILE'],
 | 
			
		||||
                $this->connector,
 | 
			
		||||
                $this->cache
 | 
			
		||||
            );
 | 
			
		||||
            if ($this->user === false) {
 | 
			
		||||
                http_response_code(403);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        switch ($this->path[0]) {
 | 
			
		||||
            case 'v':
 | 
			
		||||
                if ($this->paths[0] === "v1") {
 | 
			
		||||
                    switch ($this->paths[1]) {
 | 
			
		||||
                        case 'dummy':
 | 
			
		||||
                            $handler = new Api\V1\Dummy($this);
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
        switch ($this->paths[0]) {
 | 
			
		||||
            case 'v1':
 | 
			
		||||
                switch ($this->paths[1]) {
 | 
			
		||||
                    case 'dummy':
 | 
			
		||||
                        $handler = new Api\V1\Dummy($this);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case '.well-known':
 | 
			
		||||
                $handler = new Api\WellKnown($this);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        $printresponse = true;
 | 
			
		||||
        if ($handler !== null) {
 | 
			
		||||
            try {
 | 
			
		||||
                $printresponse = $handler->exec($this->paths);
 | 
			
		||||
                $printresponse = $handler->exec($this->paths, $this->user);
 | 
			
		||||
                if ($printresponse) {
 | 
			
		||||
                    $retval = $handler->toJson();
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,15 +11,17 @@ namespace Federator\Api;
 | 
			
		|||
/**
 | 
			
		||||
 * API interface
 | 
			
		||||
 */
 | 
			
		||||
interface V1
 | 
			
		||||
interface APIInterface
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * run given url path
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string> $paths path array split by /
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Federator\Data\User|false $user user who is calling us
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function exec($paths);
 | 
			
		||||
    public function exec($paths, $user);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get internal represenation as json string
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ namespace Federator\Api\V1;
 | 
			
		|||
/**
 | 
			
		||||
 * dummy api class for functional poc
 | 
			
		||||
 */
 | 
			
		||||
class Dummy implements \Federator\Api\V1
 | 
			
		||||
class Dummy implements \Federator\Api\APIInterface
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * \Federator\Main instance
 | 
			
		||||
| 
						 | 
				
			
			@ -41,10 +41,15 @@ class Dummy implements \Federator\Api\V1
 | 
			
		|||
     * run given url path
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string> $paths path array split by /
 | 
			
		||||
     * @param \Federator\Data\User|false $user user who is calling us
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function exec($paths) : bool
 | 
			
		||||
    public function exec($paths, $user) : bool
 | 
			
		||||
    {
 | 
			
		||||
        // only for user with the 'publish' permission
 | 
			
		||||
        if ($user === false || $user->hasPermission('publish') === false) {
 | 
			
		||||
            throw new \Federator\Exceptions\PermissionDenied();
 | 
			
		||||
        }
 | 
			
		||||
        $method = $_SERVER["REQUEST_METHOD"];
 | 
			
		||||
        switch ($method) {
 | 
			
		||||
            case 'GET':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										84
									
								
								php/federator/api/wellknown.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								php/federator/api/wellknown.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,84 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
 namespace Federator\Api;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * .well-known handlers
 | 
			
		||||
 */
 | 
			
		||||
class WellKnown implements APIInterface
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * main instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var \Federator\Main $main
 | 
			
		||||
     */
 | 
			
		||||
    private $main;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * response from sub-calls
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $response
 | 
			
		||||
     */
 | 
			
		||||
    private $response;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Federator\Main $main main instance
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($main)
 | 
			
		||||
    {
 | 
			
		||||
        $this->main = $main;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * run given url path
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string> $paths path array split by /
 | 
			
		||||
     * @param \Federator\Data\User|false $user user who is calling us @unused-param
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function exec($paths, $user)
 | 
			
		||||
    {
 | 
			
		||||
        $method = $_SERVER["REQUEST_METHOD"];
 | 
			
		||||
        switch ($method) {
 | 
			
		||||
            case 'GET':
 | 
			
		||||
                switch (sizeof($paths)) {
 | 
			
		||||
                    case 2:
 | 
			
		||||
                        if ($paths[1] === 'webfinger') {
 | 
			
		||||
                            $wf = new WellKnown\WebFinger($this, $this->main);
 | 
			
		||||
                            return $wf->exec();
 | 
			
		||||
                        }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        $this->main->setResponseCode(404);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set response
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $response response to set
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setResponse($response)
 | 
			
		||||
    {
 | 
			
		||||
        $this->response = $response;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get internal represenation as json string
 | 
			
		||||
     * @return string json string or html
 | 
			
		||||
     */
 | 
			
		||||
    public function toJson()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->response;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								php/federator/api/wellknown/webfinger.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								php/federator/api/wellknown/webfinger.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Api\WellKnown;
 | 
			
		||||
 | 
			
		||||
class WebFinger
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * parent instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var \Federator\Api\WellKnown $wellKnown
 | 
			
		||||
     */
 | 
			
		||||
    private $wellKnown;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * main instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var \Federator\Main $main
 | 
			
		||||
     */
 | 
			
		||||
    private $main;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Federator\Api\WellKnown $wellKnown parent instance
 | 
			
		||||
     * @param \Federator\Main $main main instance
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($wellKnown, $main)
 | 
			
		||||
    {
 | 
			
		||||
        $this->wellKnown = $wellKnown;
 | 
			
		||||
        $this->main = $main;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * handle webfinger request
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function exec()
 | 
			
		||||
    {
 | 
			
		||||
        $_resource = $this->main->extractFromURI('resource');
 | 
			
		||||
        $matches = [];
 | 
			
		||||
        $config = $this->main->getConfig();
 | 
			
		||||
        $domain = $config['generic']['externaldomain'];
 | 
			
		||||
        if (preg_match("/^acct:([^@]+)@(.*)$/", $_resource, $matches) != 1 || $matches[2] !== $domain) {
 | 
			
		||||
            throw new \Federator\Exceptions\InvalidArgument();
 | 
			
		||||
        }
 | 
			
		||||
        $user = \Federator\DIO\User::getUserByName($this->main->getDatabase(), $matches[1]);
 | 
			
		||||
        if ($user->id == 0) {
 | 
			
		||||
            throw new \Federator\Exceptions\FileNotFound();
 | 
			
		||||
        }
 | 
			
		||||
        $data = [
 | 
			
		||||
            'username' => $user->id,
 | 
			
		||||
            'domain' => $domain,
 | 
			
		||||
        ];
 | 
			
		||||
        $response = $this->main->renderTemplate('webfinger_acct.json', $data);
 | 
			
		||||
        $this->wellKnown->setResponse($response);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +70,33 @@ class User
 | 
			
		|||
        // no further processing for now
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get user by name
 | 
			
		||||
     *
 | 
			
		||||
     * @param \mysqli $dbh
 | 
			
		||||
     *          database handle
 | 
			
		||||
     * @param string $_name
 | 
			
		||||
     *          user name
 | 
			
		||||
     * @return \Federator\Data\User
 | 
			
		||||
     */
 | 
			
		||||
    public static function getUserByName($dbh, $_name)
 | 
			
		||||
    {
 | 
			
		||||
        $sql = 'select id from users where id=?';
 | 
			
		||||
        $stmt = $dbh->prepare($sql);
 | 
			
		||||
        if ($stmt === false) {
 | 
			
		||||
            throw new \Federator\Exceptions\ServerError();
 | 
			
		||||
        }
 | 
			
		||||
        $stmt->bind_param("s", $_name);
 | 
			
		||||
        $user = new \Federator\Data\User();
 | 
			
		||||
        $ret = $stmt->bind_result($user->id);
 | 
			
		||||
        $stmt->execute();
 | 
			
		||||
        if ($ret) {
 | 
			
		||||
            $stmt->fetch();
 | 
			
		||||
        }
 | 
			
		||||
        $stmt->close();
 | 
			
		||||
        return $user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get User by session id
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,9 @@
 | 
			
		|||
 * @author Author: Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
 namespace Federator;
 | 
			
		||||
namespace Federator;
 | 
			
		||||
 | 
			
		||||
require_once($_SERVER['DOCUMENT_ROOT'] . '../vendor/autoload.php');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for Api and related classes
 | 
			
		||||
| 
						 | 
				
			
			@ -51,30 +53,20 @@ class Main
 | 
			
		|||
     * @var array<string,string>  $headers
 | 
			
		||||
     */
 | 
			
		||||
    protected $headers = [];
 | 
			
		||||
    /**
 | 
			
		||||
     * languange instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var Language $lang
 | 
			
		||||
     */
 | 
			
		||||
    protected $lang = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * redirect URL
 | 
			
		||||
     *
 | 
			
		||||
     * @var ?string $redirect
 | 
			
		||||
     */
 | 
			
		||||
    protected $redirect = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * response code
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $responseCode
 | 
			
		||||
     */
 | 
			
		||||
    protected $responseCode = 200;
 | 
			
		||||
    /**
 | 
			
		||||
     * smarty instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var \Smarty\Smarty|null $smarty
 | 
			
		||||
     */
 | 
			
		||||
    protected $smarty;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +82,29 @@ class Main
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * extract parameter from URI
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $param
 | 
			
		||||
     *          parameter to extract
 | 
			
		||||
     * @param string $fallback
 | 
			
		||||
     *          optional fallback
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public static function extractFromURI($param, $fallback = '')
 | 
			
		||||
    {
 | 
			
		||||
        $uri = $_SERVER['REQUEST_URI'];
 | 
			
		||||
        $params = substr($uri, (int)(strpos($uri, '?') + 1));
 | 
			
		||||
        $params = explode('&', $params);
 | 
			
		||||
        foreach ($params as $p) {
 | 
			
		||||
            $tokens = explode('=', $p);
 | 
			
		||||
            if ($tokens[0] === $param) {
 | 
			
		||||
                return urldecode($tokens[1]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return $fallback;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * do a remote call and return results
 | 
			
		||||
     * @param string $remoteURL remote URL
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +143,7 @@ class Main
 | 
			
		|||
    /**
 | 
			
		||||
     * get database handle
 | 
			
		||||
     *
 | 
			
		||||
     * @return \mysqli|false database handle
 | 
			
		||||
     * @return \mysqli database handle
 | 
			
		||||
     */
 | 
			
		||||
    public function getDatabase()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +190,27 @@ class Main
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * render template
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $template template file to render
 | 
			
		||||
     * @param array<string, mixed> $data template variables
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public function renderTemplate($template, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $smarty = new \Smarty\Smarty();
 | 
			
		||||
        $root = $_SERVER['DOCUMENT_ROOT'];
 | 
			
		||||
        $smarty->setCompileDir($root . $this->config['templates']['compiledir']);
 | 
			
		||||
        $smarty->setTemplateDir((string)realpath($root . $this->config['templates']['path']));
 | 
			
		||||
        $smarty->assign('database', $this->dbh);
 | 
			
		||||
        $smarty->assign('maininstance', $this);
 | 
			
		||||
        foreach ($data as $key => $value) {
 | 
			
		||||
            $smarty->assign($key, $value);
 | 
			
		||||
        }
 | 
			
		||||
        return $smarty->fetch($template);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set cache
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -215,20 +251,10 @@ class Main
 | 
			
		|||
     *          optional parameters
 | 
			
		||||
     * @return string translation
 | 
			
		||||
     */
 | 
			
		||||
    public function translate(?string $lang, string $group, string $key, array $parameters = array()) : string
 | 
			
		||||
    public static function translate(?string $lang, string $group, string $key, array $parameters = array()) : string
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->lang === null) {
 | 
			
		||||
            $this->validLanguage($lang);
 | 
			
		||||
        }
 | 
			
		||||
        if ($this->lang !== null) {
 | 
			
		||||
            if ($this->lang->getLang() !== $lang) {
 | 
			
		||||
                $l = new Language($lang);
 | 
			
		||||
                return $l->printlang($group, $key, $parameters);
 | 
			
		||||
            }
 | 
			
		||||
            return $this->lang->printlang($group, $key, $parameters);
 | 
			
		||||
        } else {
 | 
			
		||||
            return $key;
 | 
			
		||||
        }
 | 
			
		||||
        $l = new Language($lang);
 | 
			
		||||
        return $l->printlang($group, $key, $parameters);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -236,11 +262,10 @@ class Main
 | 
			
		|||
     *
 | 
			
		||||
     * @param ?string $lang
 | 
			
		||||
     */
 | 
			
		||||
    public function validLanguage(?string $lang) : bool
 | 
			
		||||
    public static function validLanguage(?string $lang) : bool
 | 
			
		||||
    {
 | 
			
		||||
        $language = new Language($lang);
 | 
			
		||||
        if ($language->getLang() === $lang) {
 | 
			
		||||
            $this->lang = $language;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										83
									
								
								plugins/federator/contentnation.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								plugins/federator/contentnation.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
 namespace Federator\Connector;
 | 
			
		||||
 | 
			
		||||
 /**
 | 
			
		||||
  * Connector to ContentNation.net
 | 
			
		||||
  */
 | 
			
		||||
class ContentNation implements Connector
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * service-URL
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $service
 | 
			
		||||
     */
 | 
			
		||||
    private $service;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string, mixed> $config
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($config)
 | 
			
		||||
    {
 | 
			
		||||
        $this->service = $config['service-uri'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get remote user by given session
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $_session session id
 | 
			
		||||
     * @param string $_user user or profile name
 | 
			
		||||
     * @return \Federator\Data\User | false
 | 
			
		||||
     */
 | 
			
		||||
    public function getRemoteUserBySession(string $_session, string $_user)
 | 
			
		||||
    {
 | 
			
		||||
        // validate $_session and $user
 | 
			
		||||
        if (preg_match("/^[a-z0-9]{16}$/", $_session) != 1) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (preg_match("/^[a-zA-Z0-9_\-]+$/", $_user) != 1) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $remoteURL = $this->service . '/api/users/permissions?profile=' . urlencode($_user);
 | 
			
		||||
        $headers = ['Cookie: session=' . $_session, 'Accept: application/json'];
 | 
			
		||||
        [$response, $info] = \Federator\Main::getFromRemote($remoteURL, $headers);
 | 
			
		||||
 | 
			
		||||
        if ($info['http_code'] != 200) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $r = json_decode($response, true);
 | 
			
		||||
        if ($r === false || !is_array($r) ||  !array_key_exists($_user, $r)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $user = new \Federator\Data\User();
 | 
			
		||||
        $user->externalid = $_user;
 | 
			
		||||
        $user->permissions = [];
 | 
			
		||||
        $user->session = $_session;
 | 
			
		||||
        foreach ($r[$_user] as $p) {
 | 
			
		||||
            $user->permissions[] = $p;
 | 
			
		||||
        }
 | 
			
		||||
        return $user;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Federator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function to initialize plugin
 | 
			
		||||
 *
 | 
			
		||||
 * @param  \Federator\Main $main main instance
 | 
			
		||||
 * @return void
 | 
			
		||||
 */
 | 
			
		||||
function contentnation_load($main)
 | 
			
		||||
{
 | 
			
		||||
    $cn = new Connector\ContentNation($main->getConfig()['contentnation']);
 | 
			
		||||
    $main->setConnector($cn);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ primary goal is to connect ContentNation via ActivityPub again.
 | 
			
		|||
- [X] cache layer for users minmal version
 | 
			
		||||
- [X] overlay to extend with needed info like private keys, urls, ...
 | 
			
		||||
- [X] full cache for users
 | 
			
		||||
- [ ] webfinger
 | 
			
		||||
- [X] webfinger
 | 
			
		||||
- [ ] discovery endpoints
 | 
			
		||||
- [ ] ap outbox
 | 
			
		||||
- [ ] ap inbox
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								templates/federator/webfinger_acct.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								templates/federator/webfinger_acct.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
{ldelim}
 | 
			
		||||
  "subject": "acct:{$username}@{$domain}",
 | 
			
		||||
  "aliases": ["https://{$domain}/@{$username}"],
 | 
			
		||||
  "links": [
 | 
			
		||||
    {ldelim}"rel": "self", "type": "application/activity+json", "href": "https://{$domain}/{$username}"{rdelim},
 | 
			
		||||
{if $type=='Group'}
 | 
			
		||||
    {ldelim}"rel": "http://webfinger.net/rel/profile-page", "type": "text/html", "href": "https://{$domain}/@{$username}/"{rdelim},
 | 
			
		||||
{/if}
 | 
			
		||||
    {ldelim}"rel": "http://ostatus.org/schema/1.0/subscribe", "template": "https://{$domain}/authorize_interaction?uri={ldelim}uri{rdelim}"{rdelim}
 | 
			
		||||
  ]
 | 
			
		||||
{rdelim}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue