support for user discovery endpoint
parent
4c8e765a9e
commit
61203001a3
15
README.md
15
README.md
|
@ -25,7 +25,10 @@ Needed SQL commands:
|
||||||
create user if not exists 'federatoradmin'@'localhost' identified by '*change*me*as*well';
|
create user if not exists 'federatoradmin'@'localhost' identified by '*change*me*as*well';
|
||||||
grant all privileges on federator.* to 'federatoradmin'@'localhost';
|
grant all privileges on federator.* to 'federatoradmin'@'localhost';
|
||||||
|
|
||||||
This will be changed, but works for the current develop verison.
|
After this, change the settings in the ini file to match above changed passwords.
|
||||||
|
change to php/federator and run
|
||||||
|
php maintenance dbupgrade
|
||||||
|
to install all the needed table. Also run this after an update.
|
||||||
|
|
||||||
If the include redis cache is enabled, create a users.acl for redis with the content:
|
If the include redis cache is enabled, create a users.acl for redis with the content:
|
||||||
|
|
||||||
|
@ -38,8 +41,15 @@ To configure an apache server, add the following rewrite rules:
|
||||||
<Directory /where/ever/you/put/it>
|
<Directory /where/ever/you/put/it>
|
||||||
RewriteEngine on
|
RewriteEngine on
|
||||||
RewriteBase /
|
RewriteBase /
|
||||||
RewriteRule ^api/federator/(.+)$ federator.php?_call=$1 [L]
|
RewriteCond expr "%{HTTP:accept} -strcmatch '*application/ld+json*'" [OR]
|
||||||
|
RewriteCond expr "%{HTTP:accept} -strcmatch '*application/jrd+json*'" [OR]
|
||||||
|
RewriteCond expr "%{HTTP:accept} -strcmatch '*application/activity+json*'" [OR]
|
||||||
|
RewriteCond expr "%{HTTP:content-type} -strcmatch '*application/activity+json*'"
|
||||||
|
RewriteRule ^@(.*)$ /federator.php?_call=fedusers/$1 [L,END]
|
||||||
|
RewriteRule ^users/(.*)$ /federator.php?_call=fedusers/$1 [L,END]
|
||||||
|
RewriteRule ^api/federator/(.+)$ federator.php?_call=$1 [L,END]
|
||||||
RewriteRule ^(\.well-known/.*)$ /federator.php?_call=$1 [L,END]
|
RewriteRule ^(\.well-known/.*)$ /federator.php?_call=$1 [L,END]
|
||||||
|
RewriteRule ^(nodeinfo/2\.[01])$ /federator.php?_call=$1 [L,END]
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
With the dummy plugin and everything installed correctly a
|
With the dummy plugin and everything installed correctly a
|
||||||
|
@ -47,4 +57,3 @@ With the dummy plugin and everything installed correctly a
|
||||||
> curl -v http://localhost/api/federator/v1/dummy/moo -H "X-Session: somethingvalid" -H "X-Profile: ihaveone"
|
> curl -v http://localhost/api/federator/v1/dummy/moo -H "X-Session: somethingvalid" -H "X-Profile: ihaveone"
|
||||||
|
|
||||||
should return a piece of ascii art.
|
should return a piece of ascii art.
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,9 @@ class Api extends Main
|
||||||
case 'nodeinfo':
|
case 'nodeinfo':
|
||||||
$handler = new Api\WellKnown($this);
|
$handler = new Api\WellKnown($this);
|
||||||
break;
|
break;
|
||||||
|
case 'fedusers':
|
||||||
|
$handler = new Api\FedUsers($this);
|
||||||
|
break;
|
||||||
case 'v1':
|
case 'v1':
|
||||||
switch ($this->paths[1]) {
|
switch ($this->paths[1]) {
|
||||||
case 'dummy':
|
case 'dummy':
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /@username or /users/ handlers
|
||||||
|
*/
|
||||||
|
class FedUsers 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
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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:
|
||||||
|
// /users/username or /@username
|
||||||
|
return $this->returnUserProfile($paths[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$this->main->setResponseCode(404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return user profile
|
||||||
|
*
|
||||||
|
* @param string $_name
|
||||||
|
* @return boolean true on success
|
||||||
|
*/
|
||||||
|
private function returnUserProfile($_name)
|
||||||
|
{
|
||||||
|
$user = \Federator\DIO\User::getUserByName(
|
||||||
|
$this->main->getDatabase(),
|
||||||
|
$_name,
|
||||||
|
$this->main->getConnector(),
|
||||||
|
$this->main->getCache()
|
||||||
|
);
|
||||||
|
if ($user === false || $user->id === null) {
|
||||||
|
throw new \Federator\Exceptions\FileNotFound();
|
||||||
|
}
|
||||||
|
$data = [
|
||||||
|
'iconMediaType' => $user->iconMediaType,
|
||||||
|
'iconURL' => $user->iconURL,
|
||||||
|
'imageMediaType' => $user->imageMediaType,
|
||||||
|
'imageURL' => $user->imageURL,
|
||||||
|
'fqdn' => $_SERVER['SERVER_NAME'],
|
||||||
|
'name' => $user->name,
|
||||||
|
'username' => $user->id,
|
||||||
|
'publickey' => str_replace("\n", "\\n", $user->publicKey),
|
||||||
|
'registered' => gmdate('Y-m-d\TH:i:s\Z', $user->registered), // 2021-03-25T00:00:00Z
|
||||||
|
'summary' => $user->summary,
|
||||||
|
'type' => $user->type
|
||||||
|
];
|
||||||
|
$this->response = $this->main->renderTemplate('user.json', $data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,20 @@ class User
|
||||||
*/
|
*/
|
||||||
public $externalid;
|
public $externalid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* icon media type
|
||||||
|
*
|
||||||
|
* @var string $iconMediaType
|
||||||
|
*/
|
||||||
|
public $iconMediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* icon url
|
||||||
|
*
|
||||||
|
* @var string $iconURL
|
||||||
|
*/
|
||||||
|
public $iconURL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user id
|
* user id
|
||||||
*
|
*
|
||||||
|
@ -27,9 +41,29 @@ class User
|
||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* image media type
|
||||||
|
*
|
||||||
|
* @var string $imageMediaType
|
||||||
|
*/
|
||||||
|
public $imageMediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* image url
|
||||||
|
*
|
||||||
|
* @var string $imageURL
|
||||||
|
*/
|
||||||
|
public $imageURL;
|
||||||
|
|
||||||
/* @var string user language */
|
/* @var string user language */
|
||||||
//public $lang;
|
//public $lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user name
|
||||||
|
*
|
||||||
|
* @var string $name
|
||||||
|
*/
|
||||||
|
public $name = '';
|
||||||
/**
|
/**
|
||||||
* user permissions
|
* user permissions
|
||||||
*
|
*
|
||||||
|
@ -38,12 +72,40 @@ class User
|
||||||
*/
|
*/
|
||||||
public $permissions = [];
|
public $permissions = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user public key
|
||||||
|
*
|
||||||
|
* @var string $publicKey
|
||||||
|
*/
|
||||||
|
public $publicKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* registered unix timestamp
|
||||||
|
*
|
||||||
|
* @var int $registered
|
||||||
|
*/
|
||||||
|
public $registered = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* session id
|
* session id
|
||||||
*
|
*
|
||||||
* @var string $session
|
* @var string $session
|
||||||
* */
|
* */
|
||||||
public $session;
|
public $session = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* summary for user/profile
|
||||||
|
*
|
||||||
|
* @var string $summary
|
||||||
|
*/
|
||||||
|
public $summary = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* type of user (user/group)
|
||||||
|
*
|
||||||
|
* @var string $type
|
||||||
|
*/
|
||||||
|
public $type = 'group';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create new user object from json string
|
* create new user object from json string
|
||||||
|
@ -58,10 +120,18 @@ class User
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$user = new User();
|
$user = new User();
|
||||||
|
$user->iconMediaType = $data['iconMediaType'];
|
||||||
|
$user->iconURL = $data['iconURL'];
|
||||||
$user->id = $data['id'];
|
$user->id = $data['id'];
|
||||||
|
$user->imageMediaType = $data['imageMediaType'];
|
||||||
|
$user->imageURL = $data['imageURL'];
|
||||||
$user->externalid = $data['externalid'];
|
$user->externalid = $data['externalid'];
|
||||||
|
$user->name = $data['name'];
|
||||||
/// TODO: replace with enums
|
/// TODO: replace with enums
|
||||||
$user->permissions = $data['permissions'];
|
$user->permissions = $data['permissions'];
|
||||||
|
$user->publicKey = $data['publicKey'];
|
||||||
|
$user->summary = $data['summary'];
|
||||||
|
$user->type = $data['type'];
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +156,17 @@ class User
|
||||||
public function toJson()
|
public function toJson()
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
|
'iconMediaType' => $this->iconMediaType,
|
||||||
|
'iconURL' => $this->iconURL,
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
|
'imageMediaType' => $this->iconMediaType,
|
||||||
|
'imageURL' => $this->iconURL,
|
||||||
'externalid' => $this->externalid,
|
'externalid' => $this->externalid,
|
||||||
'permissions' => $this->permissions
|
'name' => $this->name,
|
||||||
|
'permissions' => $this->permissions,
|
||||||
|
'publicKey' => $this->publicKey,
|
||||||
|
'summary' => $this->summary,
|
||||||
|
'type' => $this->type
|
||||||
];
|
];
|
||||||
return json_encode($data) | '';
|
return json_encode($data) | '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,21 @@ class User
|
||||||
*/
|
*/
|
||||||
protected static function addLocalUser($dbh, $user, $_user)
|
protected static function addLocalUser($dbh, $user, $_user)
|
||||||
{
|
{
|
||||||
// needed fields: RSA key pair, user name (handle)
|
// check if it is timed out user
|
||||||
|
$sql = 'select unix_timestamp(`validuntil`) from users where id=?';
|
||||||
|
$stmt = $dbh->prepare($sql);
|
||||||
|
if ($stmt === false) {
|
||||||
|
throw new \Federator\Exceptions\ServerError();
|
||||||
|
}
|
||||||
|
$stmt->bind_param("s", $_user);
|
||||||
|
$validuntil = 0;
|
||||||
|
$ret = $stmt->bind_result($validuntil);
|
||||||
|
$stmt->execute();
|
||||||
|
if ($ret) {
|
||||||
|
$stmt->fetch();
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
if ($validuntil == 0) {
|
||||||
$private_key = openssl_pkey_new();
|
$private_key = openssl_pkey_new();
|
||||||
if ($private_key === false) {
|
if ($private_key === false) {
|
||||||
throw new \Federator\Exceptions\ServerError();
|
throw new \Federator\Exceptions\ServerError();
|
||||||
|
@ -30,19 +44,56 @@ class User
|
||||||
$public = openssl_pkey_get_details($private_key)['key'];
|
$public = openssl_pkey_get_details($private_key)['key'];
|
||||||
$private = '';
|
$private = '';
|
||||||
openssl_pkey_export($private_key, $private);
|
openssl_pkey_export($private_key, $private);
|
||||||
try {
|
$sql = 'insert into users (id, externalid, rsapublic, rsaprivate, validuntil, type, name, summary, registered, iconmediatype, iconurl, imagemediatype, imageurl)';
|
||||||
$sql = 'insert into users (id, externalid, rsapublic, rsaprivate, validuntil)';
|
$sql .= ' values (?, ?, ?, ?, now() + interval 1 day, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||||
$sql .= ' values (?, ?, ?, ?, now() + interval 1 day)';
|
|
||||||
$sql .= ' on duplicate key update validuntil=now() + interval 1 day';
|
|
||||||
$stmt = $dbh->prepare($sql);
|
$stmt = $dbh->prepare($sql);
|
||||||
if ($stmt === false) {
|
if ($stmt === false) {
|
||||||
throw new \Federator\Exceptions\ServerError();
|
throw new \Federator\Exceptions\ServerError();
|
||||||
}
|
}
|
||||||
$stmt->bind_param("ssss", $_user, $user->externalid, $public, $private);
|
$registered = gmdate('Y-m-d H:i:s', $user->registered);
|
||||||
|
$stmt->bind_param(
|
||||||
|
"ssssssssssss",
|
||||||
|
$_user,
|
||||||
|
$user->externalid,
|
||||||
|
$public,
|
||||||
|
$private,
|
||||||
|
$user->type,
|
||||||
|
$user->name,
|
||||||
|
$user->summary,
|
||||||
|
$registered,
|
||||||
|
$user->iconMediaType,
|
||||||
|
$user->iconURL,
|
||||||
|
$user->imageMediaType,
|
||||||
|
$user->imageURL
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// update to existing user
|
||||||
|
$sql = 'update users set validuntil=now() + interval 1 day, type=?, name=?, summary=?, registered=?, iconmediatype=?, iconurl=?, imagemediatype=?, imageurl=? where id=?';
|
||||||
|
$stmt = $dbh->prepare($sql);
|
||||||
|
if ($stmt === false) {
|
||||||
|
throw new \Federator\Exceptions\ServerError();
|
||||||
|
}
|
||||||
|
$registered = gmdate('Y-m-d H:i:s', $user->registered);
|
||||||
|
$stmt->bind_param(
|
||||||
|
"sssssssss",
|
||||||
|
$user->type,
|
||||||
|
$user->name,
|
||||||
|
$user->summary,
|
||||||
|
$registered,
|
||||||
|
$user->iconMediaType,
|
||||||
|
$user->iconURL,
|
||||||
|
$user->imageMediaType,
|
||||||
|
$user->imageURL,
|
||||||
|
$_user
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
$user->id = $_user;
|
$user->id = $_user;
|
||||||
} catch (\mysqli_sql_exception $e) {
|
} catch (\mysqli_sql_exception $e) {
|
||||||
|
error_log($sql);
|
||||||
|
error_log(print_r($user, true));
|
||||||
error_log($e->getMessage());
|
error_log($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,20 +106,21 @@ class User
|
||||||
*/
|
*/
|
||||||
protected static function extendUser(\mysqli $dbh, $user, $_user) : void
|
protected static function extendUser(\mysqli $dbh, $user, $_user) : void
|
||||||
{
|
{
|
||||||
$sql = 'select id from users where id=?';
|
$sql = 'select id,unix_timestamp(`validuntil`) from users where id=?';
|
||||||
$stmt = $dbh->prepare($sql);
|
$stmt = $dbh->prepare($sql);
|
||||||
if ($stmt === false) {
|
if ($stmt === false) {
|
||||||
throw new \Federator\Exceptions\ServerError();
|
throw new \Federator\Exceptions\ServerError();
|
||||||
}
|
}
|
||||||
$stmt->bind_param("s", $_user);
|
$stmt->bind_param("s", $_user);
|
||||||
$ret = $stmt->bind_result($user->id);
|
$validuntil = 0;
|
||||||
|
$ret = $stmt->bind_result($user->id, $validuntil);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
$stmt->fetch();
|
$stmt->fetch();
|
||||||
}
|
}
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
// if a new user, create own database entry with additionally needed info
|
// if a new user, create own database entry with additionally needed info
|
||||||
if ($user->id === null) {
|
if ($user->id === null || $validuntil < time()) {
|
||||||
self::addLocalUser($dbh, $user, $_user);
|
self::addLocalUser($dbh, $user, $_user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +151,26 @@ class User
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
// check our db
|
// check our db
|
||||||
$sql = 'select id,externalid from users where id=? and validuntil>=now()';
|
$sql = 'select id,externalid,type,name,summary,unix_timestamp(registered),rsapublic,iconmediatype,iconurl,imagemediatype,imageurl from users where id=? and validuntil>=now()';
|
||||||
$stmt = $dbh->prepare($sql);
|
$stmt = $dbh->prepare($sql);
|
||||||
if ($stmt === false) {
|
if ($stmt === false) {
|
||||||
throw new \Federator\Exceptions\ServerError();
|
throw new \Federator\Exceptions\ServerError();
|
||||||
}
|
}
|
||||||
$stmt->bind_param("s", $_name);
|
$stmt->bind_param("s", $_name);
|
||||||
$user = new \Federator\Data\User();
|
$user = new \Federator\Data\User();
|
||||||
$ret = $stmt->bind_result($user->id, $user->externalid);
|
$ret = $stmt->bind_result(
|
||||||
|
$user->id,
|
||||||
|
$user->externalid,
|
||||||
|
$user->type,
|
||||||
|
$user->name,
|
||||||
|
$user->summary,
|
||||||
|
$user->registered,
|
||||||
|
$user->publicKey,
|
||||||
|
$user->iconMediaType,
|
||||||
|
$user->iconURL,
|
||||||
|
$user->imageMediaType,
|
||||||
|
$user->imageURL,
|
||||||
|
);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
$stmt->fetch();
|
$stmt->fetch();
|
||||||
|
|
|
@ -83,11 +83,16 @@ class ContentNation implements Connector
|
||||||
if ($r === false || $r === null || !is_array($r)) {
|
if ($r === false || $r === null || !is_array($r)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!array_key_exists('name', $r) || $r['name'] !== $_name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$user = new \Federator\Data\User();
|
$user = new \Federator\Data\User();
|
||||||
$user->externalid = $_name;
|
$user->externalid = $_name;
|
||||||
|
$user->iconMediaType = $r['iconMediaType'];
|
||||||
|
$user->iconURL = $r['iconURL'];
|
||||||
|
$user->imageMediaType = $r['imageMediaType'];
|
||||||
|
$user->imageURL = $r['imageURL'];
|
||||||
|
$user->name = $r['name'];
|
||||||
|
$user->summary = $r['summary'];
|
||||||
|
$user->type = $r['type'];
|
||||||
|
$user->registered = intval($r['registered'], 10);
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +123,11 @@ class ContentNation implements Connector
|
||||||
if ($r === false || !is_array($r) || !array_key_exists($_user, $r)) {
|
if ($r === false || !is_array($r) || !array_key_exists($_user, $r)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$user = new \Federator\Data\User();
|
$user = $this->getRemoteUserByName($_user);
|
||||||
$user->externalid = $_user;
|
if ($user === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// extend with permissions
|
||||||
$user->permissions = [];
|
$user->permissions = [];
|
||||||
$user->session = $_session;
|
$user->session = $_session;
|
||||||
foreach ($r[$_user] as $p) {
|
foreach ($r[$_user] as $p) {
|
||||||
|
|
|
@ -43,8 +43,6 @@ class DummyConnector implements Connector
|
||||||
// validate $_session and $user
|
// validate $_session and $user
|
||||||
$user = new \Federator\Data\User();
|
$user = new \Federator\Data\User();
|
||||||
$user->externalid = $_name;
|
$user->externalid = $_name;
|
||||||
$user->permissions = [];
|
|
||||||
$user->session = '';
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
alter table users add `type` enum('person', 'group') default 'person';
|
||||||
|
alter table users add `name` varchar(255) default '';
|
||||||
|
alter table users add `summary` text default '';
|
||||||
|
alter table users add `registered` timestamp default 0;
|
||||||
|
alter table users add `iconmediatype` varchar(255) default '';
|
||||||
|
alter table users add `iconurl` varchar(255) default '';
|
||||||
|
alter table users add `imagemediatype` varchar(255) default '';
|
||||||
|
alter table users add `imageurl` varchar(255) default '';
|
||||||
|
update settings set `value`="2024-07-23" where `key`="database_version";
|
|
@ -0,0 +1,104 @@
|
||||||
|
{ldelim}
|
||||||
|
"@context":[
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{ldelim}
|
||||||
|
"manuallyApprovesFollowers":"as:manuallyApprovesFollowers",
|
||||||
|
"toot":"http://joinmastodon.org/ns#",
|
||||||
|
"featured":{ldelim}
|
||||||
|
"@id":"toot:featured",
|
||||||
|
"@type":"@id"
|
||||||
|
{rdelim},
|
||||||
|
"featuredTags":{ldelim}
|
||||||
|
"@id":"toot:featuredTags",
|
||||||
|
"@type":"@id"
|
||||||
|
{rdelim},
|
||||||
|
"alsoKnownAs":{ldelim}
|
||||||
|
"@id":"as:alsoKnownAs",
|
||||||
|
"@type":"@id"
|
||||||
|
{rdelim},
|
||||||
|
"movedTo":{ldelim}
|
||||||
|
"@id":"as:movedTo",
|
||||||
|
"@type":"@id"
|
||||||
|
{rdelim},
|
||||||
|
"schema":"http://schema.org#",
|
||||||
|
"PropertyValue":"schema:PropertyValue",
|
||||||
|
"value":"schema:value",
|
||||||
|
"discoverable":"toot:discoverable",
|
||||||
|
"Device":"toot:Device",
|
||||||
|
"Ed25519Signature":"toot:Ed25519Signature",
|
||||||
|
"Ed25519Key":"toot:Ed25519Key",
|
||||||
|
"Curve25519Key":"toot:Curve25519Key",
|
||||||
|
"EncryptedMessage":"toot:EncryptedMessage",
|
||||||
|
"publicKeyBase64":"toot:publicKeyBase64",
|
||||||
|
"deviceId":"toot:deviceId",
|
||||||
|
"claim":{ldelim}
|
||||||
|
"@type":"@id",
|
||||||
|
"@id":"toot:claim"
|
||||||
|
{rdelim},
|
||||||
|
"fingerprintKey":{ldelim}
|
||||||
|
"@type":"@id",
|
||||||
|
"@id":"toot:fingerprintKey"
|
||||||
|
{rdelim},
|
||||||
|
"identityKey":{ldelim}
|
||||||
|
"@type":"@id",
|
||||||
|
"@id":"toot:identityKey"
|
||||||
|
{rdelim},
|
||||||
|
"devices":{ldelim}
|
||||||
|
"@type":"@id",
|
||||||
|
"@id":"toot:devices"
|
||||||
|
{rdelim},
|
||||||
|
"messageFranking":"toot:messageFranking",
|
||||||
|
"messageType":"toot:messageType",
|
||||||
|
"cipherText":"toot:cipherText",
|
||||||
|
"suspended":"toot:suspended",
|
||||||
|
"focalPoint":{ldelim}
|
||||||
|
"@container":"@list",
|
||||||
|
"@id":"toot:focalPoint"
|
||||||
|
{rdelim}
|
||||||
|
{rdelim}
|
||||||
|
],
|
||||||
|
"id":"https://{$fqdn}/users/{$username}",
|
||||||
|
"type":"{$type}",
|
||||||
|
"following":"https://{$fqdn}/users/{$username}/following",
|
||||||
|
"followers":"https://{$fqdn}/users/{$username}/followers",
|
||||||
|
"inbox":"https://{$fqdn}/users/{$username}/inbox",
|
||||||
|
"outbox":"https://{$fqdn}/users/{$username}/outbox",
|
||||||
|
"featured":"https://{$fqdn}/users/{$username}/collections/featured",
|
||||||
|
"featuredTags":"https://{$fqdn}/users/{$username}/collections/tags",
|
||||||
|
"preferredUsername":"{$username}",
|
||||||
|
"name":"{$name}",
|
||||||
|
"summary":"{$summary}",
|
||||||
|
"url":"https://{$fqdn}/@{$username}",
|
||||||
|
"manuallyApprovesFollowers":false,
|
||||||
|
"discoverable":true,
|
||||||
|
"published":"{$registered}",
|
||||||
|
"publicKey":{ldelim}
|
||||||
|
"id":"https://{$fqdn}/users/{$username}#main-key",
|
||||||
|
"owner":"https://{$fqdn}/users/{$username}",
|
||||||
|
"publicKeyPem":"{$publickey}"
|
||||||
|
{rdelim},
|
||||||
|
"tag":[],
|
||||||
|
"attachment":[
|
||||||
|
{if $type==='group'}{ldelim}
|
||||||
|
"type":"PropertyValue",
|
||||||
|
"name":"website",
|
||||||
|
"value":"\u003ca href=\"https://{$fqdn}/@{$username}\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003e{$fqdn}/@{$username}\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"
|
||||||
|
{rdelim}{/if}
|
||||||
|
],
|
||||||
|
"endpoints":{ldelim}
|
||||||
|
"sharedInbox":"https://{$fqdn}/inbox"
|
||||||
|
{rdelim},
|
||||||
|
{if $iconURL !== ''} "icon":{ldelim}
|
||||||
|
"type":"Image",
|
||||||
|
"mediaType":"{$iconMediaType}",
|
||||||
|
"url":"{$iconURL}"
|
||||||
|
{rdelim},
|
||||||
|
{/if}
|
||||||
|
{if $imageURL !== ''} "image":{ldelim}
|
||||||
|
"type":"Image",
|
||||||
|
"mediaType":"{$imageMediaType}",
|
||||||
|
"url":"{$imageURL}"
|
||||||
|
{rdelim}
|
||||||
|
{/if}
|
||||||
|
{rdelim}
|
|
@ -1,6 +1,9 @@
|
||||||
{ldelim}
|
{ldelim}
|
||||||
"subject": "acct:{$username}@{$domain}",
|
"subject": "acct:{$username}@{$domain}",
|
||||||
"aliases": ["https://{$domain}/@{$username}"],
|
"aliases": [
|
||||||
|
"https://{$domain}/@{$username}"
|
||||||
|
"https://{$domain}/users/{$username}"
|
||||||
|
],
|
||||||
"links": [
|
"links": [
|
||||||
{ldelim}"rel": "self", "type": "application/activity+json", "href": "https://{$domain}/{$username}"{rdelim},
|
{ldelim}"rel": "self", "type": "application/activity+json", "href": "https://{$domain}/{$username}"{rdelim},
|
||||||
{if $type=='Group'}
|
{if $type=='Group'}
|
||||||
|
|
Loading…
Reference in New Issue