diff options
| author | winter | 2024-12-09 21:13:16 +0000 |
|---|---|---|
| committer | winter | 2024-12-09 21:13:16 +0000 |
| commit | 1ab1c4d9c6a28e9929052bd00f15866eb1a5a200 (patch) | |
| tree | 1396a368e7e05eb3c701d69deb9311d7361dd2ba | |
| parent | bda28640d6e066ae338c6f31407df274ed09f026 (diff) | |
implement webfinger lookups
| -rw-r--r-- | WpfTest/Model/Actor.php | 33 | ||||
| -rw-r--r-- | WpfTest/Model/FetchableModel.php | 2 | ||||
| -rwxr-xr-x | bin/shell | 12 | ||||
| -rw-r--r-- | routes/webfinger.php | 12 |
4 files changed, 53 insertions, 6 deletions
diff --git a/WpfTest/Model/Actor.php b/WpfTest/Model/Actor.php index 0b0e729..a745a96 100644 --- a/WpfTest/Model/Actor.php +++ b/WpfTest/Model/Actor.php @@ -4,6 +4,8 @@ namespace WpfTest\Model; use WpfTest\RemoteFetchable; class Actor extends FetchableModel implements \JsonSerializable { + public const REL_URI = "https://pawpub.entities.org.uk/rel/actor.html"; + public ?int $id; public string $uri; public bool $isLocal = false; @@ -32,6 +34,37 @@ class Actor extends FetchableModel implements \JsonSerializable { return self::findWhere('is_local = true AND handle = ?', [$handle]); } + public static function findByWebfinger(string $acct, bool $autoSave = true, bool $forceRefetch = false): ?self { + // normalise uri + if (!str_starts_with($acct, 'acct:')) { + if (str_starts_with($acct, '@')) { + $acct = substr($acct, 1); + } + $acct = "acct:$acct"; + } + // fetch it + $domain = explode('@', $acct, 2)[1]; + $data = @file_get_contents("https://$domain/.well-known/webfinger?resource=$acct", + context: stream_context_create([ + 'http' => ['header' => 'Accept: application/jrd+json, application/json'] + ]) + ); + if ($data === false) + return null; + $data = json_decode($data); + if ($data === null) + return null; + // find the right link + if (!isset($data->links)) + return null; + $matching = array_filter($data->links, function (\stdClass $linkObj) { + return $linkObj->rel == self::REL_URI; + }); + if (count($matching) == 0) + return null; + return self::findByUri($matching[0]->href, $autoSave, $forceRefetch); + } + public function jsonSerialize(): array { return [ 'type' => 'actor', diff --git a/WpfTest/Model/FetchableModel.php b/WpfTest/Model/FetchableModel.php index 44106d4..5dce010 100644 --- a/WpfTest/Model/FetchableModel.php +++ b/WpfTest/Model/FetchableModel.php @@ -21,7 +21,7 @@ abstract class FetchableModel extends Model implements RemoteFetchable { if ($data === false) return null; $data = json_decode($data); - if ($data === false) + if ($data === null) return null; // default everything nullable to null $obj = new static(); diff --git a/bin/shell b/bin/shell new file mode 100755 index 0000000..d699a14 --- /dev/null +++ b/bin/shell @@ -0,0 +1,12 @@ +#!/bin/sh +# set up autoloads<?php echo "\n"; goto skipShell; ?> +cd "$(dirname "$0")/../" || exit 1 +php -a -d auto_prepend_file=bin/shell +exit + +<?php skipShell: +require __DIR__ . '/../vendor/autoload.php'; +foreach (glob(__DIR__ . '/../misc/*.php') as $filename) { + require $filename; +} + diff --git a/routes/webfinger.php b/routes/webfinger.php index 4445cad..db29e73 100644 --- a/routes/webfinger.php +++ b/routes/webfinger.php @@ -3,6 +3,7 @@ use WpfTest\GlobalConfig; use WpfTest\HttpResponseStatus\BadRequest; use WpfTest\HttpResponseStatus\NotFound; +use WpfTest\Model\Actor; use WpfTest\Router; Router::getInstance()->mount('/.well-known/webfinger', function (array $args) { @@ -18,15 +19,16 @@ Router::getInstance()->mount('/.well-known/webfinger', function (array $args) { if ($remotePart != GlobalConfig::getInstance()->getCanonicalHost()) { throw new NotFound('i only know about local accounts'); } - if ($localPart != 'winter') { - throw new NotFound('i only know about winter!!!'); + $actor = Actor::findLocalByHandle($localPart); + if ($actor == null) { + throw new NotFound('no local actor found with that name!'); } json_response([ - 'subject' => "acct:$localPart@$remotePart", + 'subject' => "acct:$actor->handle@$remotePart", 'links' => [ [ - 'rel' => 'urn:example:wpf:actor', - 'href' => path_to_uri('/user/winter'), + 'rel' => Actor::REL_URI, + 'href' => path_to_uri("/user/$actor->handle"), 'type' => 'application/json' ] ] |
