From 9c7eb01edc3c26883d69e4aad413c811677be81c Mon Sep 17 00:00:00 2001 From: Jeremy Dormitzer Date: Thu, 21 Mar 2019 23:20:47 -0400 Subject: [PATCH] [WIP] Begin implementing block filtering --- src/Config/ActivityPubModule.php | 7 ++++- src/Controllers/GetController.php | 43 ++++++++++++++++++++++++++++-- src/Objects/BlockService.php | 21 +++++++++++++++ src/Objects/CollectionsService.php | 16 +++++++---- test/Objects/BlockServiceTest.php | 14 ++++++++++ 5 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 src/Objects/BlockService.php create mode 100644 test/Objects/BlockServiceTest.php diff --git a/src/Config/ActivityPubModule.php b/src/Config/ActivityPubModule.php index 331307f..99914a8 100644 --- a/src/Config/ActivityPubModule.php +++ b/src/Config/ActivityPubModule.php @@ -20,6 +20,7 @@ use ActivityPub\Controllers\PostController; use ActivityPub\Crypto\HttpSignatureService; use ActivityPub\Database\PrefixNamingStrategy; use ActivityPub\Http\Router; +use ActivityPub\Objects\BlockService; use ActivityPub\Objects\CollectionsService; use ActivityPub\Objects\ContextProvider; use ActivityPub\Objects\IdProvider; @@ -108,10 +109,14 @@ class ActivityPubModule ->addArgument( new Reference( RandomProvider::class ) ) ->addArgument( $config->getIdPathPrefix() ); + $this->injector->register( BlockService::class, BlockService::class ) + ->addArgument( new Reference( ObjectsService::class ) ); + $this->injector->register( GetController::class, GetController::class ) ->addArgument( new Reference( ObjectsService::class ) ) ->addArgument( new Reference( CollectionsService::class ) ) - ->addArgument( new Reference( AuthService::class ) ); + ->addArgument( new Reference( AuthService::class ) ) + ->addArgument( new Reference( BlockService::class ) ); $this->injector->register( PostController::class, PostController::class ) ->addArgument( new Reference( EventDispatcher::class ) ) diff --git a/src/Controllers/GetController.php b/src/Controllers/GetController.php index 5a9b656..bc32220 100644 --- a/src/Controllers/GetController.php +++ b/src/Controllers/GetController.php @@ -3,6 +3,8 @@ namespace ActivityPub\Controllers; use ActivityPub\Auth\AuthService; +use ActivityPub\Entities\ActivityPubObject; +use ActivityPub\Objects\BlockService; use ActivityPub\Objects\CollectionsService; use ActivityPub\Objects\ObjectsService; use Symfony\Component\HttpFoundation\JsonResponse; @@ -32,13 +34,20 @@ class GetController */ private $authService; + /** + * @var BlockService + */ + private $blockService; + public function __construct( ObjectsService $objectsService, CollectionsService $collectionsService, - AuthService $authService ) + AuthService $authService, + BlockService $blockService ) { $this->objectsService = $objectsService; $this->collectionsService = $collectionsService; $this->authService = $authService; + $this->blockService = $blockService; } /** @@ -66,7 +75,37 @@ class GetController if ( $object->hasField( 'type' ) && ( $object['type'] === 'Collection' || $object['type'] === 'OrderedCollection' ) ) { - $pagedCollection = $this->collectionsService->pageAndFilterCollection( $request, $object ); + if ( $object->hasReferencingField( 'inbox' ) ) { + // TODO figure out what to pass in here + $blockedActorIds = $this->blockService->getBlockedActorIds(); + $filterFunc = function ( ActivityPubObject $item ) use ( $request, $blockedActorIds ) { + $authorized = $this->authService->isAuthorized( $request, $item ); + foreach ( array( 'actor', 'attributedTo' ) as $actorField ) { + if ( $item->hasField( $actorField ) ) { + $actorFieldValue = $item->getFieldValue( $actorField ); + if ( ! $actorFieldValue ) { + continue; + } + if ( is_string( $actorFieldValue && + in_array( $actorFieldValue, $blockedActorIds ) ) ) { + $authorized = false; + break; + } else if ( $actorFieldValue instanceof ActivityPubObject && + in_array( $actorFieldValue['id'], $blockedActorIds ) ) { + $authorized = false; + break; + } + } + } + return $authorized; + } + } else { + $filterFunc = function ( ActivityPubObject $item ) use ( $request ) { + return $this->authService->isAuthorized( $request, $item ); + }; + } + $pagedCollection = $this->collectionsService->pageAndFilterCollection( $request, $object, $filterFunc ); + return new JsonResponse( $pagedCollection ); } $response = new JsonResponse( $object->asArray() ); diff --git a/src/Objects/BlockService.php b/src/Objects/BlockService.php new file mode 100644 index 0000000..dcd791d --- /dev/null +++ b/src/Objects/BlockService.php @@ -0,0 +1,21 @@ +objectsService = $objectsService; + } + + public function getBlockedActorIds() + { + // TODO implement me + } +} \ No newline at end of file diff --git a/src/Objects/CollectionsService.php b/src/Objects/CollectionsService.php index 285ff3d..db7bd2b 100644 --- a/src/Objects/CollectionsService.php +++ b/src/Objects/CollectionsService.php @@ -8,6 +8,7 @@ use ActivityPub\Auth\AuthService; use ActivityPub\Entities\ActivityPubObject; use ActivityPub\Entities\Field; use ActivityPub\Utils\DateTimeProvider; +use Closure; use Doctrine\ORM\EntityManager; use Exception; use GuzzleHttp\Client; @@ -77,14 +78,18 @@ class CollectionsService * Returns the collection paged and filtered by the request's authorization status * @param Request $request * @param ActivityPubObject $collection + * @param Closure $filterFunc The function to filter by. Should be a closure that + * takes an ActivityPubObject and returns a boolean, where + * true means keep the item and false means filter it out * @return array */ public function pageAndFilterCollection( Request $request, - ActivityPubObject $collection ) + ActivityPubObject $collection, + Closure $filterFunc ) { if ( $request->query->has( 'offset' ) ) { return $this->getCollectionPage( - $collection, $request, intval( $request->query->get( 'offset' ) ), $this->pageSize + $collection, $request, intval( $request->query->get( 'offset' ) ), $this->pageSize, $filterFunc ); } $colArr = array(); @@ -98,7 +103,7 @@ class CollectionsService } } $firstPage = $this->getCollectionPage( - $collection, $request, 0, $this->pageSize + $collection, $request, 0, $this->pageSize, $filterFunc ); $colArr['first'] = $firstPage; return $colArr; @@ -107,7 +112,8 @@ class CollectionsService private function getCollectionPage( ActivityPubObject $collection, Request $request, $offset, - $pageSize ) + $pageSize, + Closure $filterFunc ) { $itemsKey = 'items'; $pageType = 'CollectionPage'; @@ -133,7 +139,7 @@ class CollectionsService if ( is_string( $item ) ) { $pageItems[] = $item; $count++; - } else if ( $this->authService->isAuthorized( $request, $item ) ) { + } else if ( call_user_func( $filterFunc, $item ) ) { $pageItems[] = $item->asArray( 1 ); $count++; } diff --git a/test/Objects/BlockServiceTest.php b/test/Objects/BlockServiceTest.php new file mode 100644 index 0000000..2e3dd74 --- /dev/null +++ b/test/Objects/BlockServiceTest.php @@ -0,0 +1,14 @@ +assertTrue( false ); + } +} \ No newline at end of file