kopia lustrzana https://github.com/nextcloud/social
InstancePath and Delete
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/48/head
rodzic
b48d962164
commit
16d42a9e53
|
@ -43,6 +43,7 @@ use OCA\Social\Service\ActorService;
|
|||
use OCA\Social\Service\MiscService;
|
||||
use OCA\Social\Service\PostService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
|
@ -162,7 +163,7 @@ class LocalController extends Controller {
|
|||
throw new InvalidResourceException('user have no rights');
|
||||
}
|
||||
|
||||
$this->noteService->delete($note);
|
||||
$this->noteService->deleteLocalNote($note);
|
||||
|
||||
return $this->success();
|
||||
} catch (Exception $e) {
|
||||
|
@ -183,9 +184,6 @@ class LocalController extends Controller {
|
|||
* @return DataResponse
|
||||
*/
|
||||
public function timeline($since = 0, $limit = 5): DataResponse {
|
||||
|
||||
// $this->miscService->log('timeline: ' . json_encode($data));
|
||||
|
||||
try {
|
||||
$posts = $this->noteService->getTimeline((int)$since, (int)$limit);
|
||||
|
||||
|
|
|
@ -94,6 +94,11 @@ class NotesRequest extends NotesRequestBuilder {
|
|||
->setValue('attributed_to', $qb->createNamedParameter($note->getAttributedTo()))
|
||||
->setValue('in_reply_to', $qb->createNamedParameter($note->getInReplyTo()))
|
||||
->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(
|
||||
'creation',
|
||||
|
|
|
@ -34,6 +34,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
|
|||
use DateTime;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Model\ActivityPub\Note;
|
||||
use OCA\Social\Model\InstancePath;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
class NotesRequestBuilder extends CoreRequestBuilder {
|
||||
|
@ -80,7 +81,7 @@ class NotesRequestBuilder extends CoreRequestBuilder {
|
|||
$qb->select(
|
||||
'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.creation'
|
||||
'sn.local', 'sn.instances', 'sn.creation'
|
||||
)
|
||||
->from(self::TABLE_SERVER_NOTES, 'sn');
|
||||
|
||||
|
@ -117,12 +118,18 @@ class NotesRequestBuilder extends CoreRequestBuilder {
|
|||
->setToArray(json_decode($data['to_array'], true))
|
||||
->setCcArray(json_decode($data['cc'], true))
|
||||
->setBccArray(json_decode($data['bcc']))
|
||||
->setLocal(($data['local'] === '1') ? true : false)
|
||||
->setPublished($data['published']);
|
||||
$note->setContent($data['content'])
|
||||
->setPublishedTime($dTime->getTimestamp())
|
||||
->setAttributedTo($data['attributed_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 {
|
||||
$actor = $this->parseCacheActorsLeftJoin($data);
|
||||
$note->setCompleteDetails(true);
|
||||
|
|
|
@ -234,7 +234,9 @@ abstract class ACore implements JsonSerializable {
|
|||
* @return ACore
|
||||
*/
|
||||
public function addInstancePath(InstancePath $instancePath): ACore {
|
||||
$this->instancePaths[] = $instancePath;
|
||||
if ($instancePath->getUri() !== '') {
|
||||
$this->instancePaths[] = $instancePath;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -44,13 +44,28 @@ class InstancePath implements JsonSerializable {
|
|||
|
||||
use TArrayTools;
|
||||
|
||||
const TYPE_PUBLIC = 0;
|
||||
const TYPE_INBOX = 1;
|
||||
const TYPE_GLOBAL = 2;
|
||||
const TYPE_FOLLOWERS = 3;
|
||||
|
||||
|
||||
/** @var string */
|
||||
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->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
|
||||
*/
|
||||
|
@ -71,12 +104,20 @@ class InstancePath implements JsonSerializable {
|
|||
return $this->get('path', $info, '');
|
||||
}
|
||||
|
||||
|
||||
public function import(array $data) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
return [
|
||||
'uri' => $this->getUri()
|
||||
'uri' => $this->getUri(),
|
||||
'type' => $this->getType()
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,9 @@ class NoteService implements ICoreService {
|
|||
/** @var NotesRequest */
|
||||
private $notesRequest;
|
||||
|
||||
/** @var ActivityService */
|
||||
private $activityService;
|
||||
|
||||
/** @var ActorService */
|
||||
private $actorService;
|
||||
|
||||
|
@ -81,6 +84,7 @@ class NoteService implements ICoreService {
|
|||
* NoteService constructor.
|
||||
*
|
||||
* @param NotesRequest $notesRequest
|
||||
* @param ActivityService $activityService
|
||||
* @param ActorService $actorService
|
||||
* @param PersonService $personService
|
||||
* @param CurlService $curlService
|
||||
|
@ -88,10 +92,13 @@ class NoteService implements ICoreService {
|
|||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
NotesRequest $notesRequest, ActorService $actorService, PersonService $personService,
|
||||
CurlService $curlService, ConfigService $configService, MiscService $miscService
|
||||
NotesRequest $notesRequest, ActivityService $activityService, ActorService $actorService,
|
||||
PersonService $personService,
|
||||
CurlService $curlService, ConfigService $configService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
$this->notesRequest = $notesRequest;
|
||||
$this->activityService = $activityService;
|
||||
$this->actorService = $actorService;
|
||||
$this->personService = $personService;
|
||||
$this->curlService = $curlService;
|
||||
|
@ -141,11 +148,17 @@ class NoteService implements ICoreService {
|
|||
switch ($type) {
|
||||
case self::TYPE_UNLISTED:
|
||||
$note->setTo($actor->getFollowers());
|
||||
$note->addInstancePath(
|
||||
new InstancePath($actor->getFollowers(), InstancePath::TYPE_FOLLOWERS)
|
||||
);
|
||||
$note->addCc(ActivityService::TO_PUBLIC);
|
||||
break;
|
||||
|
||||
case self::TYPE_FOLLOWERS:
|
||||
$note->setTo($actor->getFollowers());
|
||||
$note->addInstancePath(
|
||||
new InstancePath($actor->getFollowers(), InstancePath::TYPE_FOLLOWERS)
|
||||
);
|
||||
break;
|
||||
|
||||
case self::TYPE_DIRECT:
|
||||
|
@ -154,9 +167,10 @@ class NoteService implements ICoreService {
|
|||
default:
|
||||
$note->setTo(ActivityService::TO_PUBLIC);
|
||||
$note->addCc($actor->getFollowers());
|
||||
$note->addInstancePath(
|
||||
new InstancePath($actor->getFollowers(), InstancePath::TYPE_FOLLOWERS)
|
||||
);
|
||||
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,35 @@ class NoteService implements ICoreService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Note $note
|
||||
*/
|
||||
public function deleteLocalNote(Note $note) {
|
||||
if (!$note->isLocal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// $this->notesRequest->deleteNoteById($note->getId());
|
||||
|
||||
// $this->miscService->log('___' . json_encode($note->getInstancePaths()));
|
||||
$this->activityService->deleteActivity($note);
|
||||
// $this->deleteService->deleteItem($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
|
||||
*/
|
||||
|
|
|
@ -36,6 +36,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
|
|||
use DateTime;
|
||||
use Exception;
|
||||
use OCA\Social\Db\ActorsRequest;
|
||||
use OCA\Social\Db\FollowsRequest;
|
||||
use OCA\Social\Db\NotesRequest;
|
||||
use OCA\Social\Exceptions\ActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
|
@ -44,6 +45,8 @@ use OCA\Social\Exceptions\SignatureException;
|
|||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
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\InstancePath;
|
||||
use OCA\Social\Service\ActivityPub\PersonService;
|
||||
|
@ -71,6 +74,9 @@ class ActivityService {
|
|||
/** @var NotesRequest */
|
||||
private $notesRequest;
|
||||
|
||||
/** @var FollowsRequest */
|
||||
private $followsRequest;
|
||||
|
||||
/** @var ActorService */
|
||||
private $actorService;
|
||||
|
||||
|
@ -95,6 +101,7 @@ class ActivityService {
|
|||
*
|
||||
* @param ActorsRequest $actorsRequest
|
||||
* @param NotesRequest $notesRequest
|
||||
* @param FollowsRequest $followsRequest
|
||||
* @param CurlService $curlService
|
||||
* @param ActorService $actorService
|
||||
* @param PersonService $personService
|
||||
|
@ -103,8 +110,8 @@ class ActivityService {
|
|||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
ActorsRequest $actorsRequest, NotesRequest $notesRequest, CurlService $curlService,
|
||||
ActorService $actorService,
|
||||
ActorsRequest $actorsRequest, NotesRequest $notesRequest, FollowsRequest $followsRequest,
|
||||
CurlService $curlService, ActorService $actorService,
|
||||
PersonService $personService, InstanceService $instanceService,
|
||||
ConfigService $configService,
|
||||
MiscService $miscService
|
||||
|
@ -112,6 +119,7 @@ class ActivityService {
|
|||
$this->curlService = $curlService;
|
||||
$this->actorsRequest = $actorsRequest;
|
||||
$this->notesRequest = $notesRequest;
|
||||
$this->followsRequest = $followsRequest;
|
||||
$this->actorService = $actorService;
|
||||
$this->personService = $personService;
|
||||
$this->instanceService = $instanceService;
|
||||
|
@ -131,7 +139,7 @@ class ActivityService {
|
|||
* @throws SocialAppConfigException
|
||||
* @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 {
|
||||
|
||||
$activity = new Create();
|
||||
|
@ -151,12 +159,34 @@ class ActivityService {
|
|||
|
||||
$activity->setActor($actor);
|
||||
|
||||
$result = $this->request($activity, $type);
|
||||
$result = $this->request($activity);
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -174,7 +204,7 @@ class ActivityService {
|
|||
|
||||
foreach ($requests as $request) {
|
||||
try {
|
||||
$toDelete = $request->getFromId($id);
|
||||
$toDelete = $request->getNoteById($id);
|
||||
|
||||
return $toDelete;
|
||||
} catch (Exception $e) {
|
||||
|
@ -187,14 +217,13 @@ class ActivityService {
|
|||
|
||||
/**
|
||||
* @param ACore $activity
|
||||
* @param int $type
|
||||
*
|
||||
* @throws RequestException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws ActorDoesNotExistException
|
||||
*/
|
||||
public function manageRequest(ACore $activity, int $type) {
|
||||
$result = $this->request($activity, $type);
|
||||
public function manageRequest(ACore $activity) {
|
||||
$result = $this->request($activity);
|
||||
$this->miscService->log('Activity: ' . json_encode($activity));
|
||||
$this->miscService->log('Result: ' . json_encode($result));
|
||||
}
|
||||
|
@ -203,48 +232,86 @@ class ActivityService {
|
|||
/**
|
||||
* @param ACore $activity
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @return array
|
||||
* @throws RequestException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws ActorDoesNotExistException
|
||||
*/
|
||||
public function request(ACore &$activity, int $type) {
|
||||
public function request(ACore &$activity) {
|
||||
$this->setupCore($activity);
|
||||
$hosts = $this->instanceService->getInstancesFromActivity($activity);
|
||||
// $hosts = $this->instanceService->getInstancesFromActivity($activity);
|
||||
|
||||
$result = [];
|
||||
foreach ($hosts as $host) {
|
||||
foreach ($host->getInstancePaths() as $path) {
|
||||
$result[] = $this->generateRequest($host->getAddress(), $path, $type, $activity);
|
||||
// foreach ($hosts as $host) {
|
||||
// foreach ($host->getInstancePaths() as $path) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $address
|
||||
* @param InstancePath $path
|
||||
* @param int $type
|
||||
* @param ACore $activity
|
||||
*
|
||||
* @return Request[]
|
||||
* @throws ActorDoesNotExistException
|
||||
* @throws RequestException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws ActorDoesNotExistException
|
||||
*/
|
||||
public function generateRequest(string $address, InstancePath $path, int $type, ACore $activity
|
||||
): array {
|
||||
public function generateRequest(InstancePath $path, ACore $activity): array {
|
||||
$document = json_encode($activity);
|
||||
$date = gmdate(self::DATE_FORMAT);
|
||||
$localActor = $this->getActorFromItem($activity);
|
||||
|
||||
$localActorLink =
|
||||
$this->configService->getUrlRoot() . '@' . $localActor->getPreferredUsername();
|
||||
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $address
|
||||
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $path->getAddress()
|
||||
. "\ndate: " . $date;
|
||||
|
||||
openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256);
|
||||
|
@ -255,18 +322,19 @@ class ActivityService {
|
|||
. $signed . '"';
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
$request = new Request($path->getPath(), $requestType);
|
||||
$request->addHeader('Host: ' . $address);
|
||||
$request->addHeader('Host: ' . $path->getAddress());
|
||||
$request->addHeader('Date: ' . $date);
|
||||
$request->addHeader('Signature: ' . $header);
|
||||
|
||||
$request->setDataJson($document);
|
||||
$request->setAddress($address);
|
||||
$request->setAddress($path->getAddress());
|
||||
|
||||
return $this->curlService->request($request);
|
||||
}
|
||||
|
@ -317,6 +385,7 @@ class ActivityService {
|
|||
* @throws RequestException
|
||||
* @throws SignatureException
|
||||
* @throws MalformedArrayException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function checkSignature(IRequest $request) {
|
||||
$signatureHeader = $request->getHeader('Signature');
|
||||
|
|
|
@ -79,6 +79,7 @@ class CurlService {
|
|||
}
|
||||
|
||||
$ret['_address'] = $request->getAddress();
|
||||
$ret['_path'] = $request->getUrl();
|
||||
$ret['_code'] = $code;
|
||||
|
||||
return $ret;
|
||||
|
|
|
@ -116,7 +116,6 @@ class ImportService {
|
|||
*/
|
||||
private function createItem(array $data, $root = null): ACore {
|
||||
|
||||
// $isTopLevel = ($root === null);
|
||||
switch ($this->get('type', $data)) {
|
||||
case Create::TYPE:
|
||||
$item = new Create($root);
|
||||
|
|
|
@ -94,9 +94,7 @@ class PostService {
|
|||
|
||||
$actor = $this->actorService->getActorFromUserId($post->getUserId());
|
||||
|
||||
return $this->activityService->createActivity(
|
||||
$actor, $note, ActivityService::REQUEST_INBOX, $activity
|
||||
);
|
||||
return $this->activityService->createActivity($actor, $note, $activity);
|
||||
}
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue