Test AcceptHandler

This commit is contained in:
Jeremy Dormitzer 2019-03-02 14:13:39 -05:00
parent 3b5c4f948c
commit 7eda747b4f
10 changed files with 382 additions and 40 deletions

View File

@ -60,7 +60,11 @@ class AcceptHandler implements EventSubscriberInterface
if ( ! $follow ) {
return;
}
if ( ! $follow->hasField( 'object') || ! $follow['object'] == $localActor ) {
if ( ! ( $follow->hasField( 'actor') && $localActor->equals( $follow['actor'] ) ) ) {
return;
}
$remoteActor = $event->getRequest()->attributes->get('actor');
if ( ! $remoteActor->equals( $follow['object'] ) ) {
return;
}
if ( $localActor->hasField( 'following' ) ) {
@ -76,7 +80,8 @@ class AcceptHandler implements EventSubscriberInterface
$localActor = $this->objectsService->update( $localActor['id'], $updatedLocalActor );
$following = $localActor['following'];
}
$this->collectionsService->addItem( $following, $activity['actor'] );
$newFollowing = $follow['object'];
$this->collectionsService->addItem( $following, $newFollowing->asArray() );
}
public function handleOutbox( OutboxActivityEvent $event )
@ -97,14 +102,14 @@ class AcceptHandler implements EventSubscriberInterface
if ( is_array( $followId ) && array_key_exists( 'id', $followId ) ) {
$followId = $followId['id'];
}
if ( !is_string( $followId ) ) {
if ( ! is_string( $followId ) ) {
return;
}
$follow = $this->objectsService->dereference( $followId );
if ( ! $follow ) {
return;
}
$follow = $follow->asArray( 0 );
$follow = $follow->asArray();
}
if ( !$follow || !array_key_exists( 'object', $follow ) ) {
return;
@ -113,11 +118,22 @@ class AcceptHandler implements EventSubscriberInterface
if ( is_array( $followObjectId ) && array_key_exists( 'id', $followObjectId ) ) {
$followObjectId = $followObjectId['id'];
}
$actor = $event->getActor();
if ( $followObjectId !== $actor['id'] ) {
$localActor = $event->getActor();
if ( $followObjectId !== $localActor['id'] ) {
return;
}
$this->collectionsService->addItem( $actor['followers'], $activity['actor'] );
$followers = $localActor['followers'];
if ( ! $followers ) {
$updatedLocalActor = $localActor->asArray();
$updatedLocalActor['followers'] = array(
'@context' => $this->contextProvider->getContext(),
'id' => rtrim( $updatedLocalActor['id'], '/' ) . '/followers',
'type' => 'OrderedCollection',
'orderedItems' => array(),
);
$localActor = $this->objectsService->update( $localActor['id'], $updatedLocalActor );
$followers = $localActor['followers'];
}
$this->collectionsService->addItem( $followers, $follow['actor'] );
}
}

View File

@ -4,6 +4,7 @@
namespace ActivityPub;
use ActivityPub\Activities\AcceptHandler;
use ActivityPub\Activities\CreateHandler;
use ActivityPub\Activities\DeleteHandler;
use ActivityPub\Activities\NonActivityHandler;
@ -86,6 +87,7 @@ class ActivityPub
$dispatcher->addSubscriber( $this->module->get( CreateHandler::class ) );
$dispatcher->addSubscriber( $this->module->get( UpdateHandler::class ) );
$dispatcher->addSubscriber( $this->module->get( DeleteHandler::class ) );
$dispatcher->addSubscriber( $this->module->get( AcceptHandler::class ) );
}
/**
@ -97,7 +99,7 @@ class ActivityPub
*/
public function updateSchema()
{
$entityManager = $this->module->get( EntityManager::class );
$entityManager = @$this->module->get( EntityManager::class );
$schemaTool = new SchemaTool( $entityManager );
$classes = $entityManager->getMetadataFactory()->getAllMetadata();
$schemaTool->updateSchema( $classes );

View File

@ -4,6 +4,7 @@
namespace ActivityPub\Config;
use ActivityPub\Activities\AcceptHandler;
use ActivityPub\Activities\CreateHandler;
use ActivityPub\Activities\DeleteHandler;
use ActivityPub\Activities\NonActivityHandler;
@ -133,6 +134,11 @@ class ActivityPubModule
$this->injector->register( DeleteHandler::class, DeleteHandler::class )
->addArgument( new Reference( SimpleDateTimeProvider::class ) )
->addArgument( new Reference( ObjectsService::class ) );
$this->injector->register( AcceptHandler::class, AcceptHandler::class )
->addArgument( new Reference( ObjectsService::class ) )
->addArgument( new Reference( CollectionsService::class ) )
->addArgument( new Reference( ContextProvider::class ) );
}
/**

View File

@ -2,20 +2,344 @@
namespace ActivityPub\Test\Activities;
use ActivityPub\Activities\AcceptHandler;
use ActivityPub\Activities\InboxActivityEvent;
use ActivityPub\Activities\OutboxActivityEvent;
use ActivityPub\Objects\CollectionsService;
use ActivityPub\Objects\ContextProvider;
use ActivityPub\Objects\ObjectsService;
use ActivityPub\Test\TestConfig\APTestCase;
use ActivityPub\Test\TestUtils\TestActivityPubObject;
use Symfony\Component\EventDispatcher\EventDispatcher;
class AcceptHandlerTest extends APTestCase
{
public static function getObjects()
{
return array(
'https://example.com/follows/1' => array(
'id' => 'https://example.com/follows/1',
'type' => 'Follow',
'actor' => array(
'id' => 'https://example.com/actors/1',
'following' => array(
'type' => 'OrderedCollection',
),
),
'object' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
'https://example.com/actors/1' => array(
'id' => 'https://example.com/actors/1',
'following' => array(
'type' => 'OrderedCollection',
)
),
'https://example.com/follows/2' => array(
'id' => 'https://example.com/follows/2',
'type' => 'Follow',
'actor' => array(
'id' => 'https://example.com/actors/2'
),
'object' => array(
'id' => 'https://elsewhere.com/actors/1',
),
),
'https://elsewhere.com/follows/1' => array(
'id' => 'https://elsewhere.com/follows/1',
'type' => 'Follow',
'actor' => array(
'id' => 'https://elsewhere.com/actors/1',
),
'object' => 'https://example.com/actors/1',
),
'https://example.com/actors/3' => array(
'id' => 'https://example.com/actors/3',
),
'https://example.com/follows/3' => array(
'id' => 'https://example.com/follows/3',
'actor' => array(
'id' => 'https://example.com/actors/3',
),
'object' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
);
}
public function testHandleInbox()
{
// TODO implement me
$this->assertTrue( false );
$testCases = array(
array(
'id' => 'basicInboxTest',
'eventName' => InboxActivityEvent::NAME,
'event' => new InboxActivityEvent(
array(
'id' => 'https://elsewhere.com/accepts/1',
'type' => 'Accept',
'actor' => array(
'id' => 'https://elsewhere.com/actors/1',
),
'object' => array(
'id' => 'https://example.com/follows/1',
),
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
'following' => array(
'type' => 'OrderedCollection',
),
) ),
self::requestWithAttributes(
'https://example.com/actors/1/inbox',
array( 'actor' => TestActivityPubObject::fromArray( array (
'id' => 'https://elsewhere.com/actors/1'
) ) )
)
),
'expectedNewFollowing' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
array(
'id' => 'acceptForSomeoneElsesFollow',
'eventName' => InboxActivityEvent::NAME,
'event' => new InboxActivityEvent(
array(
'id' => 'https://elsewhere.com/accepts/1',
'type' => 'Accept',
'actor' => array(
'id' => 'https://elsewhere.com/actors/1',
),
'object' => array(
'id' => 'https://example.com/follows/2',
),
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
'following' => array(
'type' => 'OrderedCollection',
),
) ),
self::requestWithAttributes(
'https://example.com/actors/1/inbox',
array( 'actor' => TestActivityPubObject::fromArray( array (
'id' => 'https://elsewhere.com/actors/1'
) ) )
)
),
),
array(
'id' => 'noFollowingTest',
'eventName' => InboxActivityEvent::NAME,
'event' => new InboxActivityEvent(
array(
'id' => 'https://elsewhere.com/accepts/2',
'type' => 'Accept',
'actor' => array(
'id' => 'https://elsewhere.com/actors/2',
),
'object' => array(
'id' => 'https://example.com/follows/3',
),
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/3',
) ),
self::requestWithAttributes(
'https://example.com/actors/3/inbox',
array( 'actor' => TestActivityPubObject::fromArray( array (
'id' => 'https://elsewhere.com/actors/1'
) ) )
)
),
'expectedNewFollowing' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
);
foreach( $testCases as $testCase ) {
$objectsService = $this->getMock( ObjectsService::class );
$objectsService->method( 'dereference')->willReturnCallback( function( $id ) {
$objects = self::getObjects();
if ( array_key_exists( $id, $objects ) ) {
return TestActivityPubObject::fromArray( $objects[$id] );
} else {
return null;
}
});
$objectsService->method( 'update')->willReturnCallback( function( $id, $arr ) {
return TestActivityPubObject::fromArray( $arr );
});
$collectionsService = $this->getMockBuilder( CollectionsService::class )
->disableOriginalConstructor()
->setMethods( array( 'addItem' ) )
->getMock();
if ( array_key_exists( 'expectedNewFollowing', $testCase ) ) {
$collectionsService->expects( $this->once() )
->method( 'addItem' )
->with(
$this->anything(),
$this->equalTo( $testCase['expectedNewFollowing'] )
);
} else {
$collectionsService->expects( $this->never() )
->method( 'addItem' );
}
$contextProvider = new ContextProvider();
$acceptHandler = new AcceptHandler( $objectsService, $collectionsService, $contextProvider );
$eventDispatcher = new EventDispatcher();
$eventDispatcher->addSubscriber( $acceptHandler );
$eventDispatcher->dispatch( $testCase['eventName'], $testCase['event'] );
}
}
public function testHandleOutbox()
{
// TODO implement me
$this->assertTrue( false );
$testCases = array(
array(
'id' => 'notAutoAccepted',
'eventName' => OutboxActivityEvent::NAME,
'event' => new OutboxActivityEvent(
array(
'id' => 'https://example.com/accepts/1',
'type' => 'Accept',
'object' => array(
'id' => 'https://elsewhere.com/follows/1',
),
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
'followers' => array(
'type' => 'OrderedCollection',
)
) ),
self::requestWithAttributes(
'https://example.com/actors/1/outbox',
array(
'actor' => TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
'followers' => array(
'type' => 'OrderedCollection',
)
) ),
)
)
),
'expectedNewFollower' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
array(
'id' => 'autoAccepted',
'eventName' => OutboxActivityEvent::NAME,
'event' => new OutboxActivityEvent(
array(
'id' => 'https://example.com/accepts/1',
'type' => 'Accept',
'actor' => array(
'id' => 'https://example.com/actor/1',
),
'object' => array(
'id' => 'https://elsewhere.com/follows/1',
),
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
'followers' => array(
'type' => 'OrderedCollection',
)
) ),
self::requestWithAttributes(
'https://example.com/actors/1/outbox',
array(
'actor' => TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
'followers' => array(
'type' => 'OrderedCollection',
)
) ),
'follow' => array(
'id' => 'https://elsewhere.com/follow/4',
'type' => 'Follow',
'actor' => array(
'id' => 'https://elsewhere.com/actors/1',
),
'object' => array(
'id' => 'https://example.com/actors/1',
),
),
)
)
),
'expectedNewFollower' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
array(
'id' => 'noFollowersCollection',
'eventName' => OutboxActivityEvent::NAME,
'event' => new OutboxActivityEvent(
array(
'id' => 'https://example.com/accepts/1',
'type' => 'Accept',
'object' => array(
'id' => 'https://elsewhere.com/follows/1',
),
),
TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
) ),
self::requestWithAttributes(
'https://example.com/actors/1/outbox',
array(
'actor' => TestActivityPubObject::fromArray( array(
'id' => 'https://example.com/actors/1',
) ),
)
)
),
'expectedNewFollower' => array(
'id' => 'https://elsewhere.com/actors/1',
)
),
);
foreach( $testCases as $testCase ) {
$objectsService = $this->getMock( ObjectsService::class );
$objectsService->method( 'dereference')->willReturnCallback( function( $id ) {
$objects = self::getObjects();
if ( array_key_exists( $id, $objects ) ) {
return TestActivityPubObject::fromArray( $objects[$id] );
} else {
return null;
}
});
$objectsService->method( 'update')->willReturnCallback( function( $id, $arr ) {
return TestActivityPubObject::fromArray( $arr );
});
$collectionsService = $this->getMockBuilder( CollectionsService::class )
->disableOriginalConstructor()
->setMethods( array( 'addItem' ) )
->getMock();
if ( array_key_exists( 'expectedNewFollower', $testCase ) ) {
$collectionsService->expects( $this->once() )
->method( 'addItem' )
->with(
$this->anything(),
$this->equalTo( $testCase['expectedNewFollower'] )
);
} else {
$collectionsService->expects( $this->never() )
->method( 'addItem' );
}
$contextProvider = new ContextProvider();
$acceptHandler = new AcceptHandler( $objectsService, $collectionsService, $contextProvider );
$eventDispatcher = new EventDispatcher();
$eventDispatcher->addSubscriber( $acceptHandler );
$eventDispatcher->dispatch( $testCase['eventName'], $testCase['event'] );
}
}
}

View File

@ -152,13 +152,6 @@ class DeleteHandlerTest extends APTestCase
}
}
public static function requestWithAttributes( $uri, $attributes )
{
$request = Request::create( $uri );
$request->attributes->add( $attributes );
return $request;
}
private static function getObjects()
{
return array(

View File

@ -225,12 +225,5 @@ class UpdateHandlerTest extends APTestCase
}
}
}
public static function requestWithAttributes( $uri, $attributes )
{
$request = Request::create( $uri );
$request->attributes->add( $attributes );
return $request;
}
}

View File

@ -46,7 +46,7 @@ class CollectionsServiceDbTest extends SQLiteTestCase
*/
private $collectionsService;
public function setUp()
protected function setUp()
{
parent::setUp();
$dbConfig = Setup::createAnnotationMetadataConfiguration(
@ -401,7 +401,7 @@ class CollectionsServiceDbTest extends SQLiteTestCase
);
foreach ( $testCases as $testCase )
{
self::setUp();
$this->setUp();
$collection = $this->objectsService->persist( $testCase['collection'] );
$this->collectionsService->addItem( $collection, $testCase['item'] );
$expectedDataSet = new ArrayDataSet( $testCase['expectedDataSet'] );
@ -415,7 +415,7 @@ class CollectionsServiceDbTest extends SQLiteTestCase
);
$this->assertTablesEqual( $expectedObjects, $actualObjects, "Error on test $testCase[id]");
$this->assertTablesEqual( $expectedFields, $actualFields, "Error on test $testCase[id]");
self::tearDown();
$this->tearDown();
}
}

View File

@ -6,7 +6,7 @@ use ActivityPub\Auth\AuthService;
use ActivityPub\Objects\CollectionsService;
use ActivityPub\Objects\ContextProvider;
use ActivityPub\Objects\ObjectsService;
use ActivityPub\Test\TestConfig\SQLiteTestCase;
use ActivityPub\Test\TestConfig\APTestCase;
use ActivityPub\Test\TestUtils\TestActivityPubObject;
use ActivityPub\Utils\SimpleDateTimeProvider;
use Doctrine\ORM\EntityManager;
@ -15,7 +15,7 @@ use GuzzleHttp\Psr7\Response as Psr7Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class CollectionsServiceTest extends SQLiteTestCase
class CollectionsServiceTest extends APTestCase
{
/**
* @var CollectionsService
@ -24,7 +24,6 @@ class CollectionsServiceTest extends SQLiteTestCase
public function setUp()
{
parent::setUp();
$authService = new AuthService();
$contextProvider = new ContextProvider();
$httpClient = $this->getMock( Client::class );
@ -50,11 +49,6 @@ class CollectionsServiceTest extends SQLiteTestCase
);
}
protected function getDataSet()
{
return new ArrayDataSet( array( 'objects' => array(), 'fields' => array() ) );
}
public function testCollectionPaging()
{
$testCases = array(

View File

@ -3,6 +3,7 @@
namespace ActivityPub\Test\TestConfig;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
abstract class APTestCase extends TestCase
{
@ -10,4 +11,17 @@ abstract class APTestCase extends TestCase
{
return parent::getMock( $originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget ); // TODO: Change the autogenerated stub
}
/**
* @param string $uri
* @param array $attributes
* @return Request
*/
public static function requestWithAttributes( $uri, $attributes )
{
$request = Request::create( $uri );
$request->attributes->add( $attributes );
return $request;
}
}

View File

@ -18,8 +18,8 @@ abstract class SQLiteTestCase extends APTestCase
final public function getConnection()
{
if ( $this->conn === null ) {
if ( $this->pdo === null ) {
if ( ! isset( $this->conn ) ) {
if ( ! isset( $this->pdo ) ) {
$this->dbPath = $this->getDbPath();
$this->pdo = new \PDO( "sqlite:{$this->dbPath}" );
}