diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 977857d34..07a217517 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -37,11 +37,13 @@ use OCA\Social\Search\UnifiedSearchProvider; use OCA\Social\Service\ConfigService; use OCA\Social\Service\UpdateService; +use OCA\Social\WellKnown\WebfingerHandler; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\QueryException; +use OCP\IDBConnection; use OCP\IServerContainer; use Throwable; @@ -53,16 +55,8 @@ * @package OCA\Social\AppInfo */ class Application extends App implements IBootstrap { - - const APP_NAME = 'social'; - - /** - * Application constructor. - * - * @param array $params - */ public function __construct(array $params = []) { parent::__construct(self::APP_NAME, $params); } @@ -73,9 +67,7 @@ public function __construct(array $params = []) { */ public function register(IRegistrationContext $context): void { $context->registerSearchProvider(UnifiedSearchProvider::class); - - // TODO: nc21, uncomment - // $context->registerEventListener(WellKnownEvent::class, WellKnownListener::class); + $context->registerWellKnownHandler(WebfingerHandler::class); } @@ -114,7 +106,7 @@ protected function checkUpgradeStatus(IServerContainer $container) { return; } - $schema = new SchemaWrapper($container->getDatabaseConnection()); + $schema = new SchemaWrapper($container->get(IDBConnection::class)); if ($schema->hasTable('social_a2_stream')) { $updateService->checkUpdateStatus(); } diff --git a/lib/Db/CoreRequestBuilder.php b/lib/Db/CoreRequestBuilder.php index 6b0b0964c..2c18d6ba4 100644 --- a/lib/Db/CoreRequestBuilder.php +++ b/lib/Db/CoreRequestBuilder.php @@ -112,7 +112,7 @@ public function __construct( ) { $this->dbConnection = $connection; $this->logger = $logger; - $this->loggerInterface = $loggerInterface; + $this->loggerInterface = $logger; $this->urlGenerator = $urlGenerator; $this->configService = $configService; $this->miscService = $miscService; diff --git a/lib/Listeners/WellKnownListener.php b/lib/Listeners/WellKnownListener.php deleted file mode 100644 index 8eb18c641..000000000 --- a/lib/Listeners/WellKnownListener.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @copyright 2020, Maxence Lange - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - - -namespace OCA\Social\Listeners; - - -use OC\WellKnown\Event\WellKnownEvent; -use OCA\Social\Exceptions\CacheActorDoesNotExistException; -use OCA\Social\Exceptions\SocialAppConfigException; -use OCA\Social\Exceptions\UnauthorizedFediverseException; -use OCA\Social\Service\WellKnownService; -use OCP\EventDispatcher\Event; -use OCP\EventDispatcher\IEventListener; -use OCP\WellKnown\IWellKnownManager; - - -/** - * Class WellKnownListener - * - * @package OCA\Social\Listeners - */ -class WellKnownListener implements IEventListener { - - - private $wellKnownService; - - - /** - * WellKnownListener constructor. - * - * @param WellKnownService $wellKnownService - */ - public function __construct(WellKnownService $wellKnownService) { - $this->wellKnownService = $wellKnownService; - } - - - /** - * @param Event $event - */ - public function handle(Event $event): void { - if (!$event instanceof WellKnownEvent) { - return; - } - - $wellKnown = $event->getWellKnown(); - if ($wellKnown->getService() === IWellKnownManager::WEBFINGER) { - try { - $this->wellKnownService->webfinger($wellKnown); - } catch (CacheActorDoesNotExistException | SocialAppConfigException | UnauthorizedFediverseException $e) { - } - } - } - -} - diff --git a/lib/Model/WebfingerLink.php b/lib/Model/WebfingerLink.php deleted file mode 100644 index 5e44f5935..000000000 --- a/lib/Model/WebfingerLink.php +++ /dev/null @@ -1,148 +0,0 @@ - - * @copyright 2018, Maxence Lange - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - - -namespace OCA\Social\Model; - -use JsonSerializable; - - -/** - * Class WebfingerLink - * - * @package OCA\Social\Model - */ -class WebfingerLink implements JsonSerializable { - - - /** @var string */ - private $href = ''; - - /** @var string */ - private $rel = ''; - - /** @var string */ - private $template = ''; - - /** @var string */ - private $type = ''; - - - /** - * @return string - */ - public function getHref(): string { - return $this->href; - } - - /** - * @param string $value - * - * @return WebfingerLink - */ - public function setHref(string $value): self { - $this->href = $value; - - return $this; - } - - - /** - * @return string - */ - public function getType(): string { - return $this->type; - } - - /** - * @param string $value - * - * @return WebfingerLink - */ - public function setType(string $value): self { - $this->type = $value; - - return $this; - } - - - /** - * @return string - */ - public function getRel(): string { - return $this->rel; - } - - /** - * @param string $value - * - * @return WebfingerLink - */ - public function setRel(string $value): self { - $this->rel = $value; - - return $this; - } - - - /** - * @return string - */ - public function getTemplate(): string { - return $this->template; - } - - /** - * @param string $value - * - * @return WebfingerLink - */ - public function setTemplate(string $value): self { - $this->template = $value; - - return $this; - } - - - /** - * @return array - */ - public function jsonSerialize(): array { - $data = [ - 'rel' => $this->getRel(), - 'type' => $this->getType(), - 'template' => $this->getTemplate(), - 'href' => $this->getHref() - ]; - - return array_filter($data); - } - -} - diff --git a/lib/Service/WellKnownService.php b/lib/Service/WellKnownService.php deleted file mode 100644 index 2ce5342f7..000000000 --- a/lib/Service/WellKnownService.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @copyright 2018, Maxence Lange - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -namespace OCA\Social\Service; - - -use OC\Webfinger\Event\WebfingerEvent; -use OCA\Social\Db\CacheActorsRequest; -use OCA\Social\Exceptions\CacheActorDoesNotExistException; -use OCA\Social\Exceptions\SocialAppConfigException; -use OCA\Social\Exceptions\UnauthorizedFediverseException; -use OCA\Social\Model\WebfingerLink; -use OCP\IURLGenerator; -use OCP\WellKnown\Model\IWellKnown; - -class WellKnownService { - - - /** @var IURLGenerator */ - private $urlGenerator; - - /** @var CacheActorsRequest */ - private $cacheActorsRequest; - - /** @var CacheActorService */ - private $cacheActorService; - - /** @var FediverseService */ - private $fediverseService; - - /** @var ConfigService */ - private $configService; - - /** @var MiscService */ - private $miscService; - - - /** - * WebfingerService constructor. - * - * @param IURLGenerator $urlGenerator - * @param CacheActorsRequest $cacheActorsRequest - * @param CacheActorService $cacheActorService - * @param FediverseService $fediverseService - * @param ConfigService $configService - * @param MiscService $miscService - */ - public function __construct( - IURLGenerator $urlGenerator, CacheActorsRequest $cacheActorsRequest, - CacheActorService $cacheActorService, FediverseService $fediverseService, - ConfigService $configService, MiscService $miscService - ) { - $this->urlGenerator = $urlGenerator; - $this->cacheActorsRequest = $cacheActorsRequest; - $this->cacheActorService = $cacheActorService; - $this->fediverseService = $fediverseService; - $this->configService = $configService; - $this->miscService = $miscService; - - } - - - /** - * @param IWellKnown $wellKnown - * - * @throws CacheActorDoesNotExistException - * @throws SocialAppConfigException - * @throws UnauthorizedFediverseException - */ - public function webfinger(IWellKnown $wellKnown) { - $this->fediverseService->jailed(); - - $subject = $wellKnown->getSubject(); - - if (strpos($subject, 'acct:') === 0) { - $subject = substr($subject, 5); - } - - try { - $actor = $this->cacheActorService->getFromLocalAccount($subject); - } catch (CacheActorDoesNotExistException $e) { - $actor = $this->cacheActorsRequest->getFromId($subject); - if (!$actor->isLocal()) { - throw new CacheActorDoesNotExistException(); - } - } - - $href = $this->configService->getSocialUrl() . '@' . $actor->getPreferredUsername(); - $href = rtrim($href, '/'); - - $linkPerson = new WebfingerLink(); - $linkPerson->setRel('self'); - $linkPerson->setType('application/activity+json'); - $linkPerson->setHref($href); - - $linkOstatus = new WebfingerLink(); - $linkOstatus->setRel('http://ostatus.org/schema/1.0/subscribe'); - $subscribe = $this->urlGenerator->linkToRouteAbsolute('social.OStatus.subscribe') . '?uri={uri}'; - $linkOstatus->setTemplate($subscribe); - - $wellKnown->addLinkSerialized($linkPerson) - ->addLinkSerialized($linkOstatus); - } - -} - diff --git a/lib/WellKnown/WebfingerHandler.php b/lib/WellKnown/WebfingerHandler.php new file mode 100644 index 000000000..7e7e7cb30 --- /dev/null +++ b/lib/WellKnown/WebfingerHandler.php @@ -0,0 +1,99 @@ + + * @copyright 2022 Carl Schwan + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Social\WellKnown; + +use OCA\Social\Db\CacheActorsRequest; +use OCA\Social\Exceptions\CacheActorDoesNotExistException; +use OCA\Social\Service\CacheActorService; +use OCA\Social\Service\ConfigService; +use OCA\Social\Service\FediverseService; +use OCP\Http\WellKnown\IHandler; +use OCP\Http\WellKnown\IRequestContext; +use OCP\Http\WellKnown\IResponse; +use OCP\Http\WellKnown\JrdResponse; +use OCP\IURLGenerator; + +class WebfingerHandler implements IHandler { + private IURLGenerator $urlGenerator; + private CacheActorsRequest $cacheActorsRequest; + private CacheActorService $cacheActorService; + private FediverseService $fediverseService; + private ConfigService $configService; + + public function __construct( + IURLGenerator $urlGenerator, CacheActorsRequest $cacheActorsRequest, + CacheActorService $cacheActorService, FediverseService $fediverseService, + ConfigService $configService + ) { + + $this->urlGenerator = $urlGenerator; + $this->cacheActorsRequest = $cacheActorsRequest; + $this->cacheActorService = $cacheActorService; + $this->fediverseService = $fediverseService; + $this->configService = $configService; + } + + public function handle(string $service, IRequestContext $context, ?IResponse $previousResponse): ?IResponse { + // See https://docs.joinmastodon.org/spec/webfinger/ + + $this->fediverseService->jailed(); + $subject = $context->getHttpRequest()->getParam('resource'); + + if (strpos($subject, 'acct:') === 0) { + $subject = substr($subject, 5); + } + + try { + $actor = $this->cacheActorService->getFromLocalAccount($subject); + } catch (CacheActorDoesNotExistException $e) { + $actor = $this->cacheActorsRequest->getFromId($subject); + if (!$actor->isLocal()) { + throw new CacheActorDoesNotExistException(); + } + } + + $response = new JrdResponse($subject); + + // ActivityPub profile + $href = $this->configService->getSocialUrl() . '@' . $actor->getPreferredUsername(); + $href = rtrim($href, '/'); + $response->addAlias($href); + $response->addLink('self', 'application/activity+json', $href); + + // Nextcloud profile page + $profilePageUrl = $this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', [ + 'targetUserId' => $actor->getPreferredUsername() + ]); + $response->addAlias($profilePageUrl); + $response->addLink('http://webfinger.net/rel/profile-page', 'text/html', $profilePageUrl); + + // Ostatus subscribe url + // JrdResponse doesn't support template + // $subscribe = $this->urlGenerator->linkToRouteAbsolute('social.OStatus.subscribe') . '?uri={uri}'; + // $response->addLink('http://ostatus.org/schema/1.0/subscribe', $subscribe); + + return $response; + } +} diff --git a/lib/webfinger.php b/lib/webfinger.php deleted file mode 100644 index 2c65be71a..000000000 --- a/lib/webfinger.php +++ /dev/null @@ -1,129 +0,0 @@ - - * @copyright 2018, Maxence Lange - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -namespace OCA\Social; - - -use Exception; -use OC; -use OCA\Social\Exceptions\SocialAppConfigException; -use OCA\Social\Service\CacheActorService; -use OCA\Social\Service\ConfigService; -use OCA\Social\Service\FediverseService; -use OCP\AppFramework\QueryException; - -require_once(__DIR__ . '/../vendor/autoload.php'); - -if (!array_key_exists('resource', $_GET)) { - echo 'missing resource'; - exit(); -} - -$subject = $_GET['resource']; - -$urlGenerator = OC::$server->getURLGenerator(); -$type = ''; - -if (strpos($subject, 'acct:') === 0) { - list($type, $account) = explode(':', $subject, 2); - $type .= ':'; -} else { - $account = $subject; -} - -list($username, $instance) = explode('@', $account); -try { - /** @var CacheActorService $cacheActorService */ - $cacheActorService = OC::$server->query(CacheActorService::class); - /** @var FediverseService $fediverseService */ - $fediverseService = OC::$server->query(FediverseService::class); - /** @var ConfigService $configService */ - $configService = OC::$server->query(ConfigService::class); -} catch (QueryException $e) { - OC::$server->getLogger() - ->log(1, 'QueryException - ' . $e->getMessage()); - http_response_code(404); - exit; -} - -try { - $fediverseService->jailed(); - - $cacheActorService->getFromLocalAccount($username); -} catch (Exception $e) { - if ($type !== '') { - OC::$server->getLogger() - ->log(1, 'Exception on webfinger/fromAccount - ' . $e->getMessage()); - http_response_code(404); - exit; - } - - try { - $fromId = $cacheActorService->getFromId($subject); - $instance = $configService->getSocialAddress(); - $username = $fromId->getPreferredUsername(); - } catch (Exception $e) { - OC::$server->getLogger() - ->log(1, 'Exception on webfinger/fromId - ' . $e->getMessage()); - http_response_code(404); - exit; - } -} - -try { - $href = $configService->getSocialUrl() . '@' . $username; -} catch (SocialAppConfigException $e) { - http_response_code(404); - exit; -} - -if (substr($href, -1) === '/') { - $href = substr($href, 0, -1); -} - -$finger = [ - 'subject' => $type . $username . '@' . $instance, - 'links' => [ - [ - 'rel' => 'self', - 'type' => 'application/activity+json', - 'href' => $href - ], - [ - 'rel' => 'http://ostatus.org/schema/1.0/subscribe', - 'template' => urldecode( - $href = $urlGenerator->linkToRouteAbsolute('social.OStatus.subscribe') . '?uri={uri}' - ) - ] - ] -]; - -header('Content-type: application/json'); - -echo json_encode($finger); -