Merge pull request #48 from nextcloud-gmbh/broadcast-and-remote-delete

followers and remote delete
pull/50/head
Maxence Lange 2018-11-21 21:00:17 -01:00 zatwierdzone przez GitHub
commit 21d7cbf613
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
18 zmienionych plików z 311 dodań i 60 usunięć

Wyświetl plik

@ -91,6 +91,13 @@
<notnull>true</notnull> <notnull>true</notnull>
</field> </field>
<field>
<name>follow_id</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field> <field>
<name>accepted</name> <name>accepted</name>
<type>boolean</type> <type>boolean</type>
@ -227,6 +234,13 @@
<notnull>true</notnull> <notnull>true</notnull>
</field> </field>
<field>
<name>instances</name>
<type>text</type>
<length>3000</length>
<notnull>true</notnull>
</field>
<field> <field>
<name>creation</name> <name>creation</name>
<type>timestamp</type> <type>timestamp</type>

Wyświetl plik

@ -5,7 +5,7 @@
<name>Social</name> <name>Social</name>
<summary>🎉 Nextcloud becomes part of the federated social networks!</summary> <summary>🎉 Nextcloud becomes part of the federated social networks!</summary>
<description><![CDATA[test]]></description> <description><![CDATA[test]]></description>
<version>0.0.35</version> <version>0.0.37</version>
<licence>agpl</licence> <licence>agpl</licence>
<author mail="maxence@artificial-owl.com">Maxence Lange</author> <author mail="maxence@artificial-owl.com">Maxence Lange</author>
<author mail="jus@bitgrid.net">Julius Härtl</author> <author mail="jus@bitgrid.net">Julius Härtl</author>

8
composer.lock wygenerowano
Wyświetl plik

@ -12,12 +12,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/daita/my-small-php-tools.git", "url": "https://github.com/daita/my-small-php-tools.git",
"reference": "1e70e4c2a6fee89577df1dd37052065e02c4b2e7" "reference": "fc822e4c08072844ad9d58846d407e83a62b3d38"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/1e70e4c2a6fee89577df1dd37052065e02c4b2e7", "url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/fc822e4c08072844ad9d58846d407e83a62b3d38",
"reference": "1e70e4c2a6fee89577df1dd37052065e02c4b2e7", "reference": "fc822e4c08072844ad9d58846d407e83a62b3d38",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -40,7 +40,7 @@
} }
], ],
"description": "My small PHP Tools", "description": "My small PHP Tools",
"time": "2018-11-20T22:24:36+00:00" "time": "2018-11-20T22:42:57+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [],

Wyświetl plik

@ -44,6 +44,7 @@ use OCA\Social\Service\ActorService;
use OCA\Social\Service\MiscService; use OCA\Social\Service\MiscService;
use OCA\Social\Service\PostService; use OCA\Social\Service\PostService;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest; use OCP\IRequest;
@ -158,12 +159,11 @@ class LocalController extends Controller {
try { try {
$note = $this->noteService->getNoteById($id); $note = $this->noteService->getNoteById($id);
$actor = $this->actorService->getActorFromUserId($this->userId); $actor = $this->actorService->getActorFromUserId($this->userId);
if ($note->getAttributedTo() !== $actor->getId()) { if ($note->getAttributedTo() !== $actor->getId()) {
throw new InvalidResourceException('user have no rights'); throw new InvalidResourceException('user have no rights');
} }
$this->noteService->delete($note); $this->noteService->deleteLocalNote($note);
return $this->success(); return $this->success();
} catch (Exception $e) { } catch (Exception $e) {
@ -184,9 +184,6 @@ class LocalController extends Controller {
* @return DataResponse * @return DataResponse
*/ */
public function timeline($since = 0, $limit = 5): DataResponse { public function timeline($since = 0, $limit = 5): DataResponse {
// $this->miscService->log('timeline: ' . json_encode($data));
try { try {
$posts = $this->noteService->getTimeline((int)$since, (int)$limit); $posts = $this->noteService->getTimeline((int)$since, (int)$limit);

Wyświetl plik

@ -154,7 +154,7 @@ class CoreRequestBuilder {
/** /**
* Limit the request to the ServiceId * Limit the request to the ActorId
* *
* @param IQueryBuilder $qb * @param IQueryBuilder $qb
* @param string $actorId * @param string $actorId
@ -164,6 +164,17 @@ class CoreRequestBuilder {
} }
/**
* Limit the request to the FollowId
*
* @param IQueryBuilder $qb
* @param string $followId
*/
protected function limitToFollowId(IQueryBuilder &$qb, string $followId) {
$this->limitToDBField($qb, 'follow_id', $followId);
}
/** /**
* Limit the request to the ServiceId * Limit the request to the ServiceId
* *

Wyświetl plik

@ -52,7 +52,8 @@ class FollowsRequest extends FollowsRequestBuilder {
$qb = $this->getFollowsInsertSql(); $qb = $this->getFollowsInsertSql();
$qb->setValue('id', $qb->createNamedParameter($follow->getId())) $qb->setValue('id', $qb->createNamedParameter($follow->getId()))
->setValue('actor_id', $qb->createNamedParameter($follow->getActorId())) ->setValue('actor_id', $qb->createNamedParameter($follow->getActorId()))
->setValue('object_id', $qb->createNamedParameter($follow->getObjectId())); ->setValue('object_id', $qb->createNamedParameter($follow->getObjectId()))
->setValue('follow_id', $qb->createNamedParameter($follow->getFollowId()));
$qb->execute(); $qb->execute();
} }
@ -95,6 +96,27 @@ class FollowsRequest extends FollowsRequestBuilder {
} }
/**
* @param string $followId
*
* @return Follow[]
*/
public function getByFollowId(string $followId): array {
$qb = $this->getFollowsSelectSql();
$this->limitToFollowId($qb, $followId);
$this->leftJoinCacheActors($qb, 'actor_id');
$follows = [];
$cursor = $qb->execute();
while ($data = $cursor->fetch()) {
$follows[] = $this->parseFollowsSelectSql($data);
}
$cursor->closeCursor();
return $follows;
}
/** /**
* @param Follow $follow * @param Follow $follow
*/ */

Wyświetl plik

@ -32,6 +32,7 @@ namespace OCA\Social\Db;
use daita\MySmallPhpTools\Traits\TArrayTools; use daita\MySmallPhpTools\Traits\TArrayTools;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Model\ActivityPub\Follow; use OCA\Social\Model\ActivityPub\Follow;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
@ -82,7 +83,7 @@ class FollowsRequestBuilder extends CoreRequestBuilder {
$qb = $this->dbConnection->getQueryBuilder(); $qb = $this->dbConnection->getQueryBuilder();
/** @noinspection PhpMethodParametersCountMismatchInspection */ /** @noinspection PhpMethodParametersCountMismatchInspection */
$qb->select('f.id', 'f.actor_id', 'f.object_id', 'f.creation') $qb->select('f.id', 'f.actor_id', 'f.object_id', 'f.follow_id', 'f.creation')
->from(self::TABLE_SERVER_FOLLOWS, 'f'); ->from(self::TABLE_SERVER_FOLLOWS, 'f');
$this->defaultSelectAlias = 'f'; $this->defaultSelectAlias = 'f';
@ -114,6 +115,14 @@ class FollowsRequestBuilder extends CoreRequestBuilder {
$follow->setId($data['id']) $follow->setId($data['id'])
->setActorId($data['actor_id']) ->setActorId($data['actor_id'])
->setObjectId($data['object_id']); ->setObjectId($data['object_id']);
$follow->setFollowId($data['follow_id']);
try {
$actor = $this->parseCacheActorsLeftJoin($data);
$follow->setCompleteDetails(true);
$follow->setActor($actor);
} catch (InvalidResourceException $e) {
}
return $follow; return $follow;
} }

Wyświetl plik

@ -94,6 +94,11 @@ class NotesRequest extends NotesRequestBuilder {
->setValue('attributed_to', $qb->createNamedParameter($note->getAttributedTo())) ->setValue('attributed_to', $qb->createNamedParameter($note->getAttributedTo()))
->setValue('in_reply_to', $qb->createNamedParameter($note->getInReplyTo())) ->setValue('in_reply_to', $qb->createNamedParameter($note->getInReplyTo()))
->setValue('source', $qb->createNamedParameter($note->getSource())) ->setValue('source', $qb->createNamedParameter($note->getSource()))
->setValue(
'instances', $qb->createNamedParameter(
json_encode($note->getInstancePaths(), JSON_UNESCAPED_SLASHES)
)
)
->setValue('local', $qb->createNamedParameter(($note->isLocal()) ? '1' : '0')) ->setValue('local', $qb->createNamedParameter(($note->isLocal()) ? '1' : '0'))
->setValue( ->setValue(
'creation', 'creation',

Wyświetl plik

@ -34,6 +34,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime; use DateTime;
use OCA\Social\Exceptions\InvalidResourceException; use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Model\ActivityPub\Note; use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Model\InstancePath;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
class NotesRequestBuilder extends CoreRequestBuilder { class NotesRequestBuilder extends CoreRequestBuilder {
@ -80,7 +81,7 @@ class NotesRequestBuilder extends CoreRequestBuilder {
$qb->select( $qb->select(
'sn.id', 'sn.to', 'sn.to_array', 'sn.cc', 'sn.bcc', 'sn.content', 'sn.summary', 'sn.id', 'sn.to', 'sn.to_array', 'sn.cc', 'sn.bcc', 'sn.content', 'sn.summary',
'sn.published', 'sn.published_time', 'sn.attributed_to', 'sn.in_reply_to', 'sn.source', 'sn.published', 'sn.published_time', 'sn.attributed_to', 'sn.in_reply_to', 'sn.source',
'sn.creation' 'sn.local', 'sn.instances', 'sn.creation'
) )
->from(self::TABLE_SERVER_NOTES, 'sn'); ->from(self::TABLE_SERVER_NOTES, 'sn');
@ -117,12 +118,18 @@ class NotesRequestBuilder extends CoreRequestBuilder {
->setToArray(json_decode($data['to_array'], true)) ->setToArray(json_decode($data['to_array'], true))
->setCcArray(json_decode($data['cc'], true)) ->setCcArray(json_decode($data['cc'], true))
->setBccArray(json_decode($data['bcc'])) ->setBccArray(json_decode($data['bcc']))
->setLocal(($data['local'] === '1') ? true : false)
->setPublished($data['published']); ->setPublished($data['published']);
$note->setContent($data['content']) $note->setContent($data['content'])
->setPublishedTime($dTime->getTimestamp()) ->setPublishedTime($dTime->getTimestamp())
->setAttributedTo($data['attributed_to']) ->setAttributedTo($data['attributed_to'])
->setInReplyTo($data['in_reply_to']); ->setInReplyTo($data['in_reply_to']);
$instances = json_decode($data['instances'], true);
foreach ($instances as $instance) {
$note->addInstancePath(new InstancePath($instance['uri'], $instance['type']));
}
try { try {
$actor = $this->parseCacheActorsLeftJoin($data); $actor = $this->parseCacheActorsLeftJoin($data);
$note->setCompleteDetails(true); $note->setCompleteDetails(true);

Wyświetl plik

@ -234,7 +234,9 @@ abstract class ACore implements JsonSerializable {
* @return ACore * @return ACore
*/ */
public function addInstancePath(InstancePath $instancePath): ACore { public function addInstancePath(InstancePath $instancePath): ACore {
$this->instancePaths[] = $instancePath; if ($instancePath->getUri() !== '') {
$this->instancePaths[] = $instancePath;
}
return $this; return $this;
} }

Wyświetl plik

@ -45,6 +45,10 @@ class Follow extends ACore implements JsonSerializable {
const TYPE = 'Follow'; const TYPE = 'Follow';
/** @var string */
private $followId = '';
/** /**
* Follow constructor. * Follow constructor.
* *
@ -57,6 +61,25 @@ class Follow extends ACore implements JsonSerializable {
} }
/**
* @return string
*/
public function getFollowId(): string {
return $this->followId;
}
/**
* @param string $followId
*
* @return Follow
*/
public function setFollowId(string $followId): Follow {
$this->followId = $followId;
return $this;
}
/** /**
* @param array $data * @param array $data
*/ */

Wyświetl plik

@ -44,13 +44,28 @@ class InstancePath implements JsonSerializable {
use TArrayTools; use TArrayTools;
const TYPE_PUBLIC = 0;
const TYPE_INBOX = 1;
const TYPE_GLOBAL = 2;
const TYPE_FOLLOWERS = 3;
/** @var string */ /** @var string */
private $uri = ''; private $uri = '';
/** @var int */
private $type = 0;
public function __construct(string $uri) {
/**
* InstancePath constructor.
*
* @param string $uri
* @param int $type
*/
public function __construct(string $uri = '', int $type = 0) {
$this->uri = $uri; $this->uri = $uri;
$this->type = $type;
} }
@ -62,6 +77,24 @@ class InstancePath implements JsonSerializable {
} }
/**
* @return int
*/
public function getType(): int {
return $this->type;
}
/**
* @return string
*/
public function getAddress(): string {
$info = parse_url($this->uri);
return $this->get('host', $info, '');
}
/** /**
* @return string * @return string
*/ */
@ -71,12 +104,20 @@ class InstancePath implements JsonSerializable {
return $this->get('path', $info, ''); return $this->get('path', $info, '');
} }
public function import(array $data) {
}
/** /**
* @return array * @return array
*/ */
public function jsonSerialize(): array { public function jsonSerialize(): array {
return [ return [
'uri' => $this->getUri() 'uri' => $this->getUri(),
'type' => $this->getType()
]; ];
} }

Wyświetl plik

@ -33,6 +33,7 @@ namespace OCA\Social\Service\ActivityPub;
use Exception; use Exception;
use OCA\Social\Db\FollowsRequest; use OCA\Social\Db\FollowsRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\FollowDoesNotExistException; use OCA\Social\Exceptions\FollowDoesNotExistException;
use OCA\Social\Exceptions\RequestException; use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException; use OCA\Social\Exceptions\SocialAppConfigException;
@ -97,6 +98,7 @@ class FollowService implements ICoreService {
* *
* @throws RequestException * @throws RequestException
* @throws SocialAppConfigException * @throws SocialAppConfigException
* @throws ActorDoesNotExistException
*/ */
public function followAccount(Person $actor, string $account) { public function followAccount(Person $actor, string $account) {
$remoteActor = $this->personService->getFromAccount($account); $remoteActor = $this->personService->getFromAccount($account);
@ -108,11 +110,12 @@ class FollowService implements ICoreService {
try { try {
$this->followsRequest->getByPersons($actor->getId(), $remoteActor->getId()); $this->followsRequest->getByPersons($actor->getId(), $remoteActor->getId());
} catch (FollowDoesNotExistException $e) { } catch (FollowDoesNotExistException $e) {
$this->miscService->log('CREATE NEW ONE !');
$this->followsRequest->save($follow); $this->followsRequest->save($follow);
$follow->addInstancePath(new InstancePath($remoteActor->getInbox())); $follow->addInstancePath(
$this->activityService->manageRequest($follow, ActivityService::REQUEST_INBOX); new InstancePath($remoteActor->getInbox(), InstancePath::TYPE_INBOX)
);
$this->activityService->manageRequest($follow);
} }
} }
@ -157,15 +160,18 @@ class FollowService implements ICoreService {
$remoteActor = $this->personService->getFromId($follow->getActorId()); $remoteActor = $this->personService->getFromId($follow->getActorId());
$accept = new Accept(); $accept = new Accept();
$accept->setId($follow->getObjectId() . '#accepts/follows/1234'); // TODO: improve the generation of the Id
$accept->setId($follow->getObjectId() . '#accepts/follows/' . rand(1000, 100000000));
$accept->setActorId($follow->getObjectId()); $accept->setActorId($follow->getObjectId());
$accept->setObject($follow); $accept->setObject($follow);
$accept->addInstancePath(new InstancePath($remoteActor->getInbox())); $accept->addInstancePath(
new InstancePath($remoteActor->getInbox(), InstancePath::TYPE_INBOX)
);
$follow->setParent($accept); $follow->setParent($accept);
$this->activityService->manageRequest($accept, ActivityService::REQUEST_INBOX); $this->activityService->manageRequest($accept);
$this->followsRequest->accepted($follow); $this->followsRequest->accepted($follow);
} catch (Exception $e) { } catch (Exception $e) {
} }
@ -186,8 +192,12 @@ class FollowService implements ICoreService {
try { try {
$this->followsRequest->getByPersons($follow->getActorId(), $follow->getObjectId()); $this->followsRequest->getByPersons($follow->getActorId(), $follow->getObjectId());
} catch (FollowDoesNotExistException $e) { } catch (FollowDoesNotExistException $e) {
$this->followsRequest->save($follow); $actor = $this->personService->getFromId($follow->getObjectId());
$this->confirmFollowRequest($follow); if ($actor->isLocal()) {
$follow->setFollowId($actor->getFollowers());
$this->followsRequest->save($follow);
$this->confirmFollowRequest($follow);
}
} }
} else { } else {
$parent = $follow->getParent(); $parent = $follow->getParent();

Wyświetl plik

@ -61,6 +61,9 @@ class NoteService implements ICoreService {
/** @var NotesRequest */ /** @var NotesRequest */
private $notesRequest; private $notesRequest;
/** @var ActivityService */
private $activityService;
/** @var ActorService */ /** @var ActorService */
private $actorService; private $actorService;
@ -81,6 +84,7 @@ class NoteService implements ICoreService {
* NoteService constructor. * NoteService constructor.
* *
* @param NotesRequest $notesRequest * @param NotesRequest $notesRequest
* @param ActivityService $activityService
* @param ActorService $actorService * @param ActorService $actorService
* @param PersonService $personService * @param PersonService $personService
* @param CurlService $curlService * @param CurlService $curlService
@ -88,10 +92,13 @@ class NoteService implements ICoreService {
* @param MiscService $miscService * @param MiscService $miscService
*/ */
public function __construct( public function __construct(
NotesRequest $notesRequest, ActorService $actorService, PersonService $personService, NotesRequest $notesRequest, ActivityService $activityService, ActorService $actorService,
CurlService $curlService, ConfigService $configService, MiscService $miscService PersonService $personService,
CurlService $curlService, ConfigService $configService,
MiscService $miscService
) { ) {
$this->notesRequest = $notesRequest; $this->notesRequest = $notesRequest;
$this->activityService = $activityService;
$this->actorService = $actorService; $this->actorService = $actorService;
$this->personService = $personService; $this->personService = $personService;
$this->curlService = $curlService; $this->curlService = $curlService;
@ -141,11 +148,17 @@ class NoteService implements ICoreService {
switch ($type) { switch ($type) {
case self::TYPE_UNLISTED: case self::TYPE_UNLISTED:
$note->setTo($actor->getFollowers()); $note->setTo($actor->getFollowers());
$note->addInstancePath(
new InstancePath($actor->getFollowers(), InstancePath::TYPE_FOLLOWERS)
);
$note->addCc(ActivityService::TO_PUBLIC); $note->addCc(ActivityService::TO_PUBLIC);
break; break;
case self::TYPE_FOLLOWERS: case self::TYPE_FOLLOWERS:
$note->setTo($actor->getFollowers()); $note->setTo($actor->getFollowers());
$note->addInstancePath(
new InstancePath($actor->getFollowers(), InstancePath::TYPE_FOLLOWERS)
);
break; break;
case self::TYPE_DIRECT: case self::TYPE_DIRECT:
@ -154,9 +167,10 @@ class NoteService implements ICoreService {
default: default:
$note->setTo(ActivityService::TO_PUBLIC); $note->setTo(ActivityService::TO_PUBLIC);
$note->addCc($actor->getFollowers()); $note->addCc($actor->getFollowers());
$note->addInstancePath(
new InstancePath($actor->getFollowers(), InstancePath::TYPE_FOLLOWERS)
);
break; break;
} }
} }
@ -188,7 +202,7 @@ class NoteService implements ICoreService {
] ]
); );
$note->addInstancePath(new InstancePath($actor->getInbox())); $note->addInstancePath(new InstancePath($actor->getInbox(), InstancePath::TYPE_INBOX));
} }
@ -253,6 +267,36 @@ class NoteService implements ICoreService {
} }
/**
* @param Note $note
*
* @throws ActorDoesNotExistException
* @throws RequestException
* @throws SocialAppConfigException
*/
public function deleteLocalNote(Note $note) {
if (!$note->isLocal()) {
return;
}
$note->setActorId($note->getAttributedTo());
$this->activityService->deleteActivity($note);
}
// /**
// * @param Note $note
// */
// private function assignInstances(Note $note) {
// $note->addInstancePath(new InstancePath($note->getTo()));
// $all = array_merge($note->getToArray(), $note->getCcArray(), $note->getBccArray());
// foreach ($all as $uri) {
// $note->addInstancePath(new InstancePath($uri));
// }
// $note->addInstancePath(new InstancePath($note->getInReplyTo()));
// }
/** /**
* @param ACore $item * @param ACore $item
*/ */

Wyświetl plik

@ -36,6 +36,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime; use DateTime;
use Exception; use Exception;
use OCA\Social\Db\ActorsRequest; use OCA\Social\Db\ActorsRequest;
use OCA\Social\Db\FollowsRequest;
use OCA\Social\Db\NotesRequest; use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException; use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\InvalidResourceException; use OCA\Social\Exceptions\InvalidResourceException;
@ -44,6 +45,8 @@ use OCA\Social\Exceptions\SignatureException;
use OCA\Social\Exceptions\SocialAppConfigException; use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Model\ActivityPub\ACore; use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Activity\Create; use OCA\Social\Model\ActivityPub\Activity\Create;
use OCA\Social\Model\ActivityPub\Activity\Delete;
use OCA\Social\Model\ActivityPub\Activity\Tombstone;
use OCA\Social\Model\ActivityPub\Person; use OCA\Social\Model\ActivityPub\Person;
use OCA\Social\Model\InstancePath; use OCA\Social\Model\InstancePath;
use OCA\Social\Service\ActivityPub\PersonService; use OCA\Social\Service\ActivityPub\PersonService;
@ -71,6 +74,9 @@ class ActivityService {
/** @var NotesRequest */ /** @var NotesRequest */
private $notesRequest; private $notesRequest;
/** @var FollowsRequest */
private $followsRequest;
/** @var ActorService */ /** @var ActorService */
private $actorService; private $actorService;
@ -95,6 +101,7 @@ class ActivityService {
* *
* @param ActorsRequest $actorsRequest * @param ActorsRequest $actorsRequest
* @param NotesRequest $notesRequest * @param NotesRequest $notesRequest
* @param FollowsRequest $followsRequest
* @param CurlService $curlService * @param CurlService $curlService
* @param ActorService $actorService * @param ActorService $actorService
* @param PersonService $personService * @param PersonService $personService
@ -103,8 +110,8 @@ class ActivityService {
* @param MiscService $miscService * @param MiscService $miscService
*/ */
public function __construct( public function __construct(
ActorsRequest $actorsRequest, NotesRequest $notesRequest, CurlService $curlService, ActorsRequest $actorsRequest, NotesRequest $notesRequest, FollowsRequest $followsRequest,
ActorService $actorService, CurlService $curlService, ActorService $actorService,
PersonService $personService, InstanceService $instanceService, PersonService $personService, InstanceService $instanceService,
ConfigService $configService, ConfigService $configService,
MiscService $miscService MiscService $miscService
@ -112,6 +119,7 @@ class ActivityService {
$this->curlService = $curlService; $this->curlService = $curlService;
$this->actorsRequest = $actorsRequest; $this->actorsRequest = $actorsRequest;
$this->notesRequest = $notesRequest; $this->notesRequest = $notesRequest;
$this->followsRequest = $followsRequest;
$this->actorService = $actorService; $this->actorService = $actorService;
$this->personService = $personService; $this->personService = $personService;
$this->instanceService = $instanceService; $this->instanceService = $instanceService;
@ -123,7 +131,6 @@ class ActivityService {
/** /**
* @param Person $actor * @param Person $actor
* @param ACore $item * @param ACore $item
* @param int $type
* @param ACore $activity * @param ACore $activity
* *
* @return array * @return array
@ -131,7 +138,7 @@ class ActivityService {
* @throws SocialAppConfigException * @throws SocialAppConfigException
* @throws ActorDoesNotExistException * @throws ActorDoesNotExistException
*/ */
public function createActivity(Person $actor, ACore $item, int $type, ACore &$activity = null public function createActivity(Person $actor, ACore $item, ACore &$activity = null
): array { ): array {
$activity = new Create(); $activity = new Create();
@ -141,7 +148,7 @@ class ActivityService {
$activity->setObject($item); $activity->setObject($item);
$activity->setId($item->getId() . '/activity'); $activity->setId($item->getId() . '/activity');
$activity->addInstancePaths($item->getInstancePaths()); $activity->setInstancePaths($item->getInstancePaths());
// if ($item->getToArray() !== []) { // if ($item->getToArray() !== []) {
// $activity->setToArray($item->getToArray()); // $activity->setToArray($item->getToArray());
@ -151,12 +158,34 @@ class ActivityService {
$activity->setActor($actor); $activity->setActor($actor);
$result = $this->request($activity, $type); $result = $this->request($activity);
return $result; return $result;
} }
/**
* @param ACore $item
*
* @throws ActorDoesNotExistException
* @throws RequestException
* @throws SocialAppConfigException
*/
public function deleteActivity(ACore $item) {
$delete = new Delete();
$delete->setId($item->getId() . '#delete');
$delete->setActorId($item->getActorId());
$tombstone = new Tombstone($delete);
$tombstone->setId($item->getId());
$delete->setObject($tombstone);
$delete->addInstancePaths($item->getInstancePaths());
$this->request($delete);
}
/** /**
* @param string $id * @param string $id
* *
@ -174,7 +203,7 @@ class ActivityService {
foreach ($requests as $request) { foreach ($requests as $request) {
try { try {
$toDelete = $request->getFromId($id); $toDelete = $request->getNoteById($id);
return $toDelete; return $toDelete;
} catch (Exception $e) { } catch (Exception $e) {
@ -187,14 +216,13 @@ class ActivityService {
/** /**
* @param ACore $activity * @param ACore $activity
* @param int $type
* *
* @throws RequestException * @throws RequestException
* @throws SocialAppConfigException * @throws SocialAppConfigException
* @throws ActorDoesNotExistException * @throws ActorDoesNotExistException
*/ */
public function manageRequest(ACore $activity, int $type) { public function manageRequest(ACore $activity) {
$result = $this->request($activity, $type); $result = $this->request($activity);
$this->miscService->log('Activity: ' . json_encode($activity)); $this->miscService->log('Activity: ' . json_encode($activity));
$this->miscService->log('Result: ' . json_encode($result)); $this->miscService->log('Result: ' . json_encode($result));
} }
@ -203,48 +231,86 @@ class ActivityService {
/** /**
* @param ACore $activity * @param ACore $activity
* *
* @param int $type
* *
* @return array * @return array
* @throws RequestException * @throws RequestException
* @throws SocialAppConfigException * @throws SocialAppConfigException
* @throws ActorDoesNotExistException * @throws ActorDoesNotExistException
*/ */
public function request(ACore &$activity, int $type) { public function request(ACore &$activity) {
$this->setupCore($activity); $this->setupCore($activity);
$hosts = $this->instanceService->getInstancesFromActivity($activity); // $hosts = $this->instanceService->getInstancesFromActivity($activity);
$result = []; $result = [];
foreach ($hosts as $host) { // foreach ($hosts as $host) {
foreach ($host->getInstancePaths() as $path) { // foreach ($host->getInstancePaths() as $path) {
$result[] = $this->generateRequest($host->getAddress(), $path, $type, $activity); foreach ($activity->getInstancePaths() as $instancePath) {
if ($instancePath->getType() === InstancePath::TYPE_FOLLOWERS) {
$result = array_merge($result, $this->requestToFollowers($activity, $instancePath));
} else {
$result[] = $this->generateRequest($instancePath, $activity);
} }
} }
// }
return $result;
}
/**
* @param ACore $activity
* @param InstancePath $instancePath
*
* @return array
* @throws ActorDoesNotExistException
* @throws RequestException
* @throws SocialAppConfigException
*/
private function requestToFollowers(ACore &$activity, InstancePath $instancePath): array {
$result = [];
$sharedInboxes = [];
$follows = $this->followsRequest->getByFollowId($instancePath->getUri());
foreach ($follows as $follow) {
if (!$follow->gotActor()) {
// TODO - check if cache can be empty at this point ?
continue;
}
$sharedInbox = $follow->getActor()
->getSharedInbox();
if (in_array($sharedInbox, $sharedInboxes)) {
continue;
}
$sharedInboxes[] = $sharedInbox;
$result[] = $this->generateRequest(
new InstancePath($sharedInbox, InstancePath::TYPE_GLOBAL), $activity
);
}
return $result; return $result;
} }
/** /**
* @param string $address
* @param InstancePath $path * @param InstancePath $path
* @param int $type
* @param ACore $activity * @param ACore $activity
* *
* @return Request[] * @return Request[]
* @throws ActorDoesNotExistException
* @throws RequestException * @throws RequestException
* @throws SocialAppConfigException * @throws SocialAppConfigException
* @throws ActorDoesNotExistException
*/ */
public function generateRequest(string $address, InstancePath $path, int $type, ACore $activity public function generateRequest(InstancePath $path, ACore $activity): array {
): array {
$document = json_encode($activity); $document = json_encode($activity);
$date = gmdate(self::DATE_FORMAT); $date = gmdate(self::DATE_FORMAT);
$localActor = $this->getActorFromItem($activity); $localActor = $this->getActorFromItem($activity);
$localActorLink = $localActorLink =
$this->configService->getUrlRoot() . '@' . $localActor->getPreferredUsername(); $this->configService->getUrlRoot() . '@' . $localActor->getPreferredUsername();
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $address $signature = "(request-target): post " . $path->getPath() . "\nhost: " . $path->getAddress()
. "\ndate: " . $date; . "\ndate: " . $date;
openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256); openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256);
@ -255,18 +321,19 @@ class ActivityService {
. $signed . '"'; . $signed . '"';
$requestType = Request::TYPE_GET; $requestType = Request::TYPE_GET;
if ($type === self::REQUEST_INBOX) { if ($path->getType() === InstancePath::TYPE_INBOX
|| $path->getType() === InstancePath::TYPE_GLOBAL
|| $path->getType() === InstancePath::TYPE_FOLLOWERS) {
$requestType = Request::TYPE_POST; $requestType = Request::TYPE_POST;
} }
$request = new Request($path->getPath(), $requestType); $request = new Request($path->getPath(), $requestType);
$request->addHeader('Host: ' . $address); $request->addHeader('Host: ' . $path->getAddress());
$request->addHeader('Date: ' . $date); $request->addHeader('Date: ' . $date);
$request->addHeader('Signature: ' . $header); $request->addHeader('Signature: ' . $header);
$request->setDataJson($document); $request->setDataJson($document);
$request->setAddress($address); $request->setAddress($path->getAddress());
return $this->curlService->request($request); return $this->curlService->request($request);
} }
@ -317,6 +384,7 @@ class ActivityService {
* @throws RequestException * @throws RequestException
* @throws SignatureException * @throws SignatureException
* @throws MalformedArrayException * @throws MalformedArrayException
* @throws Exception
*/ */
private function checkSignature(IRequest $request) { private function checkSignature(IRequest $request) {
$signatureHeader = $request->getHeader('Signature'); $signatureHeader = $request->getHeader('Signature');

Wyświetl plik

@ -82,6 +82,7 @@ class CurlService {
} }
$ret['_address'] = $request->getAddress(); $ret['_address'] = $request->getAddress();
$ret['_path'] = $request->getUrl();
$ret['_code'] = $code; $ret['_code'] = $code;
return $ret; return $ret;

Wyświetl plik

@ -116,7 +116,6 @@ class ImportService {
*/ */
private function createItem(array $data, $root = null): ACore { private function createItem(array $data, $root = null): ACore {
// $isTopLevel = ($root === null);
switch ($this->get('type', $data)) { switch ($this->get('type', $data)) {
case Create::TYPE: case Create::TYPE:
$item = new Create($root); $item = new Create($root);

Wyświetl plik

@ -94,9 +94,7 @@ class PostService {
$actor = $this->actorService->getActorFromUserId($post->getUserId()); $actor = $this->actorService->getActorFromUserId($post->getUserId());
return $this->activityService->createActivity( return $this->activityService->createActivity($actor, $note, $activity);
$actor, $note, ActivityService::REQUEST_INBOX, $activity
);
} }