mark before cleaning

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/6/head
Maxence Lange 2018-09-28 13:41:24 +02:00
rodzic edee5f2746
commit 3e399899ed
41 zmienionych plików z 4544 dodań i 58 usunięć

Wyświetl plik

@ -64,6 +64,7 @@
<primary>true</primary>
</field>
// @deprecated
<field>
<name>service_id</name>
<type>integer</type>
@ -77,30 +78,41 @@
<length>63</length>
</field>
<field>
<name>username</name>
<type>text</type>
<length>63</length>
</field>
// @deprecated
<field>
<name>account</name>
<type>text</type>
<length>127</length>
</field>
// @deprecated
<field>
<name>account_id</name>
<type>integer</type>
<length>7</length>
</field>
// @deprecated
<field>
<name>status</name>
<type>integer</type>
<length>1</length>
</field>
// @deprecated
<field>
<name>auth</name>
<type>text</type>
<length>2000</length>
</field>
// @deprecated
<field>
<name>config</name>
<type>text</type>
@ -115,5 +127,261 @@
</declaration>
</table>
<table>
<name>*dbprefix*social_server_actors</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<length>7</length>
<unsigned>true</unsigned>
<notnull>true</notnull>
<autoincrement>true</autoincrement>
<primary>true</primary>
</field>
<field>
<name>type</name>
<type>text</type>
<length>15</length>
<notnull>true</notnull>
</field>
<field>
<name>user_id</name>
<type>text</type>
<length>63</length>
<notnull>true</notnull>
</field>
<field>
<name>preferred_username</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>public_key</name>
<type>text</type>
<length>1000</length>
</field>
<field>
<name>private_key</name>
<type>text</type>
<length>2000</length>
</field>
<field>
<name>creation</name>
<type>timestamp</type>
</field>
</declaration>
</table>
<table>
<name>*dbprefix*social_server_activities</name>
<declaration>
<field>
<name>id</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>activity</name>
<type>text</type>
<length>6000</length>
<notnull>true</notnull>
</field>
<field>
<name>object</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
</declaration>
</table>
<table>
<name>*dbprefix*social_server_notes</name>
<declaration>
<field>
<name>id</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<!--<field>-->
<!--<name>type</name>-->
<!--<type>text</type>-->
<!--<length>15</length>-->
<!--<notnull>true</notnull>-->
<!--</field>-->
<field>
<name>to</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>to_array</name>
<type>text</type>
<length>2000</length>
<notnull>true</notnull>
</field>
<field>
<name>cc</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>bcc</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>content</name>
<type>text</type>
<length>3000</length>
<notnull>true</notnull>
</field>
<field>
<name>summary</name>
<type>text</type>
<length>255</length>
<notnull>true</notnull>
</field>
<field>
<name>published</name>
<type>text</type>
<length>31</length>
<notnull>true</notnull>
</field>
<field>
<name>attributed_to</name>
<type>text</type>
<length>127</length>
</field>
<field>
<name>in_reply_to</name>
<type>text</type>
<length>127</length>
</field>
<field>
<name>creation</name>
<type>timestamp</type>
</field>
</declaration>
</table>
<table>
<name>*dbprefix*social_cache_actors</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<length>8</length>
<unsigned>true</unsigned>
<notnull>true</notnull>
<autoincrement>true</autoincrement>
<primary>true</primary>
</field>
<field>
<name>account</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>url</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>actor</name>
<type>text</type>
<length>8000</length>
<notnull>true</notnull>
</field>
<field>
<name>creation</name>
<type>timestamp</type>
</field>
</declaration>
</table>
<table>
<name>*dbprefix*social_cache_actors</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<length>8</length>
<unsigned>true</unsigned>
<notnull>true</notnull>
<autoincrement>true</autoincrement>
<primary>true</primary>
</field>
<field>
<name>account</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>url</name>
<type>text</type>
<length>127</length>
<notnull>true</notnull>
</field>
<field>
<name>actor</name>
<type>text</type>
<length>8000</length>
<notnull>true</notnull>
</field>
<field>
<name>creation</name>
<type>timestamp</type>
</field>
</declaration>
</table>
</database>

Wyświetl plik

@ -5,7 +5,7 @@
<name>Social</name>
<summary>🎉 Nextcloud becomes part of the federated social networks!</summary>
<description><![CDATA[test]]></description>
<version>0.0.10</version>
<version>0.0.17</version>
<licence>agpl</licence>
<author mail="maxence@artificial-owl.com">Maxence Lange</author>
<author mail="jus@bitgrid.net">Julius Härtl</author>
@ -26,4 +26,8 @@
</navigation>
</navigations>
<commands>
<command>OCA\Social\Command\NoteCreate</command>
</commands>
</info>

Wyświetl plik

@ -39,6 +39,22 @@ return [
[
'name' => 'OAuth2#setCode', 'url' => '/client/oauth2/redirect/{serviceId}/',
'verb' => 'GET'
]
]
],
['name' => 'Account#create', 'url' => '/local/account/{username}', 'verb' => 'POST'],
['name' => 'ActivityPub#sharedInbox', 'url' => '/inbox', 'verb' => 'POST'],
['name' => 'ActivityPub#actor', 'url' => '/users/{username}', 'verb' => 'GET'],
['name' => 'ActivityPub#aliasactor', 'url' => '/@{username}', 'verb' => 'GET'],
['name' => 'ActivityPub#inbox', 'url' => '/@{username}/inbox', 'verb' => 'POST'],
['name' => 'ActivityPub#outbox', 'url' => '/@{username}/outbox', 'verb' => 'POST'],
['name' => 'ActivityPub#followers', 'url' => '/@{username}/followers', 'verb' => 'GET'],
['name' => 'ActivityPub#following', 'url' => '/@{username}/following', 'verb' => 'GET'],
['name' => 'SocialPub#displayPost', 'url' => '/@{username}/{postId}', 'verb' => 'GET']
,
['name' => 'ActivityPub#test', 'url' => '/inbox/{username}', 'verb' => 'POST'],
]
];

Wyświetl plik

@ -0,0 +1,150 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Command;
use Exception;
use OC\Core\Command\Base;
use OCA\Social\Service\ActivityPub\NoteService;
use OCA\Social\Service\ActivityPubService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\CurlService;
use OCA\Social\Service\MiscService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class NoteCreate extends Base {
/** @var ConfigService */
private $configService;
/** @var ActivityPubService */
private $activityPubService;
/** @var ActorService */
private $actorService;
/** @var NoteService */
private $noteService;
/** @var CurlService */
private $curlService;
/** @var MiscService */
private $miscService;
/**
* Index constructor.
*
* @param ActivityPubService $activityPubService
* @param ActorService $actorService
* @param NoteService $noteService
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActivityPubService $activityPubService, ActorService $actorService,
NoteService $noteService, CurlService $curlService,
ConfigService $configService, MiscService $miscService
) {
parent::__construct();
$this->activityPubService = $activityPubService;
$this->actorService = $actorService;
$this->noteService = $noteService;
$this->curlService = $curlService;
$this->configService = $configService;
$this->miscService = $miscService;
}
/**
*
*/
protected function configure() {
parent::configure();
$this->setName('social:note:create')
->addOption(
'replyTo', 'r', InputOption::VALUE_OPTIONAL, 'in reply to an existing thread'
)
->addOption(
'to', 't', InputOption::VALUE_OPTIONAL, 'to (default Public)'
)
->addArgument('userid', InputArgument::REQUIRED, 'userId of the author')
->addArgument('content', InputArgument::REQUIRED, 'content of the post')
->setDescription('Create a new note');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @throws Exception
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$userId = $input->getArgument('userid');
$content = $input->getArgument('content');
$to = $input->getOption('to');
$replyTo = $input->getOption('replyTo');
$note = $this->noteService->generateNote($userId, $content, ActivityPubService::TO_PUBLIC);
if ($to !== null) {
$note->setTo($to);
$note->addTag(
[
'type' => 'Mention',
'href' => $to
]
);
}
if ($replyTo !== null) {
$note->setInReplyTo($replyTo);
}
$result = $this->activityPubService->createActivity($userId, $note, $activity);
echo 'object: ' . json_encode($activity, JSON_PRETTY_PRINT) . "\n";
echo 'result: ' . json_encode($result, JSON_PRETTY_PRINT) . "\n";
}
}

Wyświetl plik

@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Controller;
use daita\Traits\TArrayTools;
use daita\Traits\TNCDataResponse;
use Exception;
use OCA\Social\AppInfo\Application;
use OCA\Social\Service\ActivityPubService;
use OCA\Social\Service\ActivityStreamsService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\MiscService;
use OCA\Social\Service\ServiceAccountsService;
use OCA\Social\Service\ServicesService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
class AccountController extends Controller {
use TNCDataResponse;
/** @var string */
private $userId;
/** @var ConfigService */
private $configService;
/** @var ActorService */
private $actorService;
/** @var MiscService */
private $miscService;
/**
* AccountController constructor.
*
* @param IRequest $request
* @param string $userId
* @param ConfigService $configService
* @param ActorService $actorService
* @param MiscService $miscService
*/
public function __construct(
IRequest $request, string $userId, ConfigService $configService,
ActorService $actorService, MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->userId = $userId;
$this->configService = $configService;
$this->actorService = $actorService;
$this->miscService = $miscService;
}
/**
* @NoAdminRequired
*
* @param array $data
*
* @return DataResponse
*/
public function create(string $username): DataResponse {
try {
$this->actorService->createActor($this->userId, $username);
return $this->success([]);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
}

Wyświetl plik

@ -0,0 +1,250 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Controller;
use daita\Traits\TNCDataResponse;
use Exception;
use OCA\Social\AppInfo\Application;
use OCA\Social\Service\ActivityPubService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\MiscService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\IRequest;
class ActivityPubController extends Controller {
use TNCDataResponse;
/** @var SocialPubController */
private $socialPubController;
/** @var ActivityPubService */
private $activityPubService;
/** @var ActorService */
private $actorService;
/** @var MiscService */
private $miscService;
/**
* ActivityPubController constructor.
*
* @param SocialPubController $socialPubController
* @param ActivityPubService $activityPubService
* @param ActorService $actorService
* @param IRequest $request
* @param MiscService $miscService
*/
public function __construct(
SocialPubController $socialPubController, ActivityPubService $activityPubService,
ActorService $actorService, IRequest $request,
MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->socialPubController = $socialPubController;
$this->activityPubService = $activityPubService;
$this->actorService = $actorService;
$this->miscService = $miscService;
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function actor(string $username) {
if (!$this->checkSourceActivityStreams()) {
return $this->socialPubController->actor($username);
}
try {
// $this->activityPubService->generateActor($userId);
$actor = $this->actorService->getActor($username);
return $this->directSuccess($actor);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function aliasactor(string $username) {
return $this->actor($username);
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @return Response
*/
public function sharedInbox() {
return $this->success([]);
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @return Response
*/
public function inbox($username) {
try {
$this->activityPubService->checkRequest($this->request);
// $this->noteService->receiving(file_get_contents('php://input'));
$body = file_get_contents('php://input');
$this->miscService->log('### ' . $body);
return $this->success([]);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function test($username, $body) {
return $this->success([$username]);
// $this->miscService->log('#### ' . $toto . ' ' . json_encode($_SERVER) . ' ' . json_encode($_POST));
// try {
// return $this->success(['author' => $author]);
// } catch (Exception $e) {
// return $this->fail('ddsaads');
// }
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function outbox($username) {
return $this->success([$username]);
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function followers($username) {
if (!$this->checkSourceActivityStreams()) {
return $this->socialPubController->followers($username);
}
return $this->success([$username]);
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function following($username) {
if (!$this->checkSourceActivityStreams()) {
return $this->socialPubController->following($username);
}
return $this->success([$username]);
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
* @param $postId
*
* @return Response
*/
public function displayPost($username, $postId) {
return $this->success([$username, $postId]);
}
/**
*
*/
private function checkSourceActivityStreams() {
return true;
if ($this->request->getHeader('Accept')
=== 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"') {
return true;
}
return false;
}
}

Wyświetl plik

@ -0,0 +1,132 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Controller;
use daita\Traits\TNCDataResponse;
use OCA\Social\AppInfo\Application;
use OCA\Social\Service\ActivityPubService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\MiscService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IRequest;
class SocialPubController extends Controller {
use TNCDataResponse;
/** @var ActivityPubService */
private $activityPubService;
/** @var ActorService */
private $actorService;
/** @var MiscService */
private $miscService;
/**
* ActivityPubController constructor.
*
* @param ActivityPubService $activityPubService
* @param ActorService $actorService
* @param IRequest $request
* @param MiscService $miscService
*/
public function __construct(
ActivityPubService $activityPubService, ActorService $actorService, IRequest $request,
MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->activityPubService = $activityPubService;
$this->actorService = $actorService;
$this->miscService = $miscService;
}
/**
* @NoCSRFRequired
* @PublicPage
e*
* @param string $username
*
* @return Response
*/
public function actor(string $username) {
return new TemplateResponse(Application::APP_NAME, 'actor', [], 'blank');
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function followers($username) {
return new TemplateResponse(Application::APP_NAME, 'followers', [], 'blank');
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
*
* @return Response
*/
public function following($username) {
return new TemplateResponse(Application::APP_NAME, 'following', [], 'blank');
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param string $username
* @param $postId
*
* @return Response
*/
public function displayPost($username, $postId) {
return $this->success([$username, $postId]);
}
}

Wyświetl plik

@ -0,0 +1,173 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Db;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Actor;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\MiscService;
use OCP\IDBConnection;
class ActorsRequest extends ActorsRequestBuilder {
/**
* ServicesRequest constructor.
*
* @param IDBConnection $connection
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
IDBConnection $connection, ConfigService $configService, MiscService $miscService
) {
parent::__construct($connection, $configService, $miscService);
}
/**
* @param Actor $actor
*
* @return int
* @throws \Exception
*/
public function create(Actor $actor): int {
try {
$qb = $this->getActorsInsertSql();
$qb->setValue('type', $qb->createNamedParameter($actor->getType()))
->setValue('user_id', $qb->createNamedParameter($actor->getUserId()))
->setValue(
'preferred_username', $qb->createNamedParameter($actor->getPreferredUsername())
)
->setValue('public_key', $qb->createNamedParameter($actor->getPublicKey()))
->setValue('private_key', $qb->createNamedParameter($actor->getPrivateKey()));
$qb->execute();
return $qb->getLastInsertId();
} catch (\Exception $e) {
throw $e;
}
}
/**
* return service.
*
* @param string $username
*
* @return Actor
* @throws ActorDoesNotExistException
*/
public function getFromUsername(string $username): Actor {
$qb = $this->getActorsSelectSql();
$this->limitToPreferredUsername($qb, $username);
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new ActorDoesNotExistException('Actor not found');
}
return $this->parseActorsSelectSql($data);
}
/**
* return service.
*
* @param string $userId
*
* @return Actor
* @throws ActorDoesNotExistException
*/
public function getFromUserId(string $userId): Actor {
$qb = $this->getActorsSelectSql();
$this->limitToUserId($qb, $userId);
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new ActorDoesNotExistException('Actor not found');
}
return $this->parseActorsSelectSql($data);
}
//
// /**
// * @param Service $service
// *
// * @return bool
// */
// public function update(Service $service): bool {
//
// try {
// $this->getService($service->getId());
// } catch (ServiceDoesNotExistException $e) {
// return false;
// }
//
// $qb = $this->getServicesUpdateSql();
// $qb->set('address', $qb->createNamedParameter($service->getAddress()));
// $qb->set('config', $qb->createNamedParameter(json_encode($service->getConfigAll())));
// $qb->set('status', $qb->createNamedParameter($service->getStatus()));
// $qb->set('config', $qb->createNamedParameter(json_encode($service->getConfigAll())));
//
// $this->limitToId($qb, $service->getId());
//
// $qb->execute();
//
// return true;
// }
//
// /**
// * @param int $serviceId
// */
// public function delete(int $serviceId) {
// $qb = $this->getServicesDeleteSql();
// $this->limitToId($qb, $serviceId);
//
// $qb->execute();
// }
}

Wyświetl plik

@ -0,0 +1,129 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Db;
use daita\Traits\TArrayTools;
use OCA\Social\Model\ActivityPub\Actor;
use OCP\DB\QueryBuilder\IQueryBuilder;
class ActorsRequestBuilder extends CoreRequestBuilder {
use TArrayTools;
/**
* Base of the Sql Insert request
*
* @return IQueryBuilder
*/
protected function getActorsInsertSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert(self::TABLE_SERVER_ACTORS);
return $qb;
}
/**
* Base of the Sql Update request
*
* @return IQueryBuilder
*/
protected function getActorsUpdateSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->update(self::TABLE_SERVER_ACTORS);
return $qb;
}
/**
* Base of the Sql Select request for Shares
*
* @return IQueryBuilder
*/
protected function getActorsSelectSql() {
$qb = $this->dbConnection->getQueryBuilder();
/** @noinspection PhpMethodParametersCountMismatchInspection */
$qb->select(
'sa.id', 'sa.type', 'sa.user_id', 'sa.preferred_username', 'sa.public_key',
'sa.private_key', 'sa.creation'
)
->from(self::TABLE_SERVER_ACTORS, 'sa');
$this->defaultSelectAlias = 'sa';
return $qb;
}
/**
* Base of the Sql Delete request
*
* @return IQueryBuilder
*/
protected function getActorsDeleteSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete(self::TABLE_SERVER_ACTORS);
return $qb;
}
/**
* @param array $data
*
* @return Actor
*/
protected function parseActorsSelectSql($data): Actor {
$id = $this->configService->getRoot() . '@' . $data['preferred_username'];
$actor = new Actor();
$actor->setId($id)
->setType($this->get('type', $data, ''))
->setRoot($this->configService->getRoot());
$actor->setUserId($data['user_id'])
->setPreferredUsername($data['preferred_username'])
->setPublicKey($data['public_key'])
->setPrivateKey($data['private_key'])
->setInbox($id . '/inbox')
->setOutbox($id . '/outbox')
->setFollowers($id . '/followers')
->setFollowing($id . '/following')
->setSharedInbox($this->configService->getRoot() . 'inbox')
->setCreation($this->getInt('creation', $data, 0));
return $actor;
}
}

Wyświetl plik

@ -0,0 +1,130 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Db;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Actor;
use OCA\Social\Model\ActivityPub\Cache\CacheActor;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\MiscService;
use OCP\IDBConnection;
class CacheActorsRequest extends CacheActorsRequestBuilder {
/**
* ServicesRequest constructor.
*
* @param IDBConnection $connection
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
IDBConnection $connection, ConfigService $configService, MiscService $miscService
) {
parent::__construct($connection, $configService, $miscService);
}
/**
* @param Actor $actor
*
* @return int
* @throws \Exception
*/
public function create(Actor $actor, array $object): int {
try {
$qb = $this->getCacheActorsInsertSql();
$qb->setValue('account', $qb->createNamedParameter($actor->getAccount()))
->setValue('url', $qb->createNamedParameter($actor->getId()))
->setValue('actor', $qb->createNamedParameter(json_encode($object)));
$qb->execute();
return $qb->getLastInsertId();
} catch (\Exception $e) {
throw $e;
}
}
/**
* return service.
*
* @param string $account
*
* @return CacheActor
* @throws CacheActorDoesNotExistException
*/
public function getFromAccount(string $account): Actor {
$qb = $this->getCacheActorsSelectSql();
$this->limitToAccount($qb, $account);
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new CacheActorDoesNotExistException();
}
return $this->parseCacheActorsSelectSql($data);
}
/**
* return service.
*
* @param string $url
*
* @return CacheActor
* @throws CacheActorDoesNotExistException
*/
public function getFromUrl(string $url): CacheActor {
$qb = $this->getCacheActorsSelectSql();
$this->limitToUrl($qb, $url);
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new CacheActorDoesNotExistException();
}
return $this->parseCacheActorsSelectSql($data);
}
}

Wyświetl plik

@ -0,0 +1,122 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Db;
use daita\Traits\TArrayTools;
use OCA\Social\Model\ActivityPub\Actor;
use OCA\Social\Model\ActivityPub\Cache\CacheActor;
use OCA\Social\Model\Service;
use OCA\Social\Model\ServiceAccount;
use OCP\DB\QueryBuilder\IQueryBuilder;
class CacheActorsRequestBuilder extends CoreRequestBuilder {
use TArrayTools;
/**
* Base of the Sql Insert request
*
* @return IQueryBuilder
*/
protected function getCacheActorsInsertSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert(self::TABLE_CACHE_ACTORS);
return $qb;
}
/**
* Base of the Sql Update request
*
* @return IQueryBuilder
*/
protected function getCacheActorsUpdateSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->update(self::TABLE_CACHE_ACTORS);
return $qb;
}
/**
* Base of the Sql Select request for Shares
*
* @return IQueryBuilder
*/
protected function getCacheActorsSelectSql() {
$qb = $this->dbConnection->getQueryBuilder();
/** @noinspection PhpMethodParametersCountMismatchInspection */
$qb->select(
'ca.id', 'ca.account', 'ca.url', 'ca.actor', 'ca.creation'
)
->from(self::TABLE_CACHE_ACTORS, 'ca');
$this->defaultSelectAlias = 'ca';
return $qb;
}
/**
* Base of the Sql Delete request
*
* @return IQueryBuilder
*/
protected function getCacheActorsDeleteSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete(self::TABLE_CACHE_ACTORS);
return $qb;
}
/**
* @param array $data
*
* @return CacheActor
*/
protected function parseCacheActorsSelectSql($data): CacheActor {
$actor = new CacheActor();
$actor->setId($this->getInt('id', $data))
->setAccount($data['account'])
->setUrl($data['url'])
->setActor(json_decode($data['actor'], true))
->setCreation($this->getInt('creation', $data, 0));
return $actor;
}
}

Wyświetl plik

@ -40,7 +40,11 @@ class CoreRequestBuilder {
const TABLE_SERVICES = 'social_services';
const TABLE_ACCOUNTS = 'social_accounts';
const TABLE_OAUTH2_TOKENS = 'social_oauth2_tokens';
const TABLE_SERVER_ACTORS = 'social_server_actors';
const TABLE_SERVER_NOTES = 'social_server_notes';
const TABLE_CACHE_ACTORS = 'social_cache_actors';
/** @var IDBConnection */
@ -95,6 +99,17 @@ class CoreRequestBuilder {
}
/**
* Limit the request to the OwnerId
*
* @param IQueryBuilder $qb
* @param string $userId
*/
protected function limitToPreferredUsername(IQueryBuilder &$qb, $userId) {
$this->limitToDBField($qb, 'preferred_username', $userId);
}
/**
* Limit the request to the OwnerId
*
@ -128,6 +143,17 @@ class CoreRequestBuilder {
}
/**
* Limit the request to the url
*
* @param IQueryBuilder $qb
* @param string $url
*/
protected function limitToUrl(IQueryBuilder &$qb, string $url) {
$this->limitToDBField($qb, 'url', $url);
}
/**
* Limit the request to the status
*

Wyświetl plik

@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Db;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Model\ActivityPub\Actor;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\MiscService;
use OCP\IDBConnection;
class NotesRequest extends NotesRequestBuilder {
/**
* ServicesRequest constructor.
*
* @param IDBConnection $connection
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
IDBConnection $connection, ConfigService $configService, MiscService $miscService
) {
parent::__construct($connection, $configService, $miscService);
}
/**
* @param Note $note
*
* @return int
* @throws \Exception
*/
public function create(Note $note): int {
try {
$qb = $this->getNotesInsertSql();
$qb->setValue('id', $qb->createNamedParameter($note->getId()))
->setValue('to', $qb->createNamedParameter($note->getTo()))
->setValue('to_array', $qb->createNamedParameter(json_encode($note->getToArray())))
->setValue('cc', $qb->createNamedParameter(json_encode($note->getCc())))
->setValue('bcc', $qb->createNamedParameter(json_encode($note->getBcc())))
->setValue('content', $qb->createNamedParameter($note->getContent()))
->setValue('summary', $qb->createNamedParameter($note->getSummary()))
->setValue('published', $qb->createNamedParameter($note->getPublished()))
->setValue('attributed_to', $qb->createNamedParameter($note->getAttributedTo()))
->setValue('in_reply_to', $qb->createNamedParameter($note->getInReplyTo()));
$qb->execute();
return $qb->getLastInsertId();
} catch (\Exception $e) {
throw $e;
}
}
}

Wyświetl plik

@ -0,0 +1,124 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Db;
use daita\Traits\TArrayTools;
use OCA\Social\Model\ActivityPub\Note;
use OCP\DB\QueryBuilder\IQueryBuilder;
class NotesRequestBuilder extends CoreRequestBuilder {
use TArrayTools;
/**
* Base of the Sql Insert request
*
* @return IQueryBuilder
*/
protected function getNotesInsertSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert(self::TABLE_SERVER_NOTES);
return $qb;
}
/**
* Base of the Sql Update request
*
* @return IQueryBuilder
*/
protected function getNotesUpdateSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->update(self::TABLE_SERVER_NOTES);
return $qb;
}
/**
* Base of the Sql Select request for Shares
*
* @return IQueryBuilder
*/
protected function getNotesSelectSql() {
$qb = $this->dbConnection->getQueryBuilder();
/** @noinspection PhpMethodParametersCountMismatchInspection */
$qb->select(
'sn.id', 'sn.to', 'sn.to_array', 'sn.cc', 'sn.bcc', 'sn.content', 'sn_summary',
'sn.published', 'sn.attributed_to', 'sn.in_reply_to', 'sn.creation'
)
->from(self::TABLE_SERVER_NOTES, 'sn');
$this->defaultSelectAlias = 'sn';
return $qb;
}
/**
* Base of the Sql Delete request
*
* @return IQueryBuilder
*/
protected function getNotesDeleteSql() {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete(self::TABLE_SERVER_NOTES);
return $qb;
}
/**
* @param array $data
*
* @return Note
*/
protected function parseNotesSelectSql($data): Note {
$note = new Note();
$note->setId($data['id'])
->setTo($data['to'])
->setToArray(json_decode($data['to_array'], true))
->setCc(json_decode($data['cc'], true))
->setBcc(json_decode($data['bcc']));
$note->setContent($data['content'])
->setPublished($data['published'])
->setAttributedTo($data['attributed_to'])
->setInReplyTo($data['in_reply_to']);
return $note;
}
}

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class ActorAlreadyExistsException extends \Exception {
}

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class ActorDoesNotExistException extends \Exception {
}

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class CacheActorDoesNotExistException extends \Exception {
}

Wyświetl plik

@ -0,0 +1,87 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model;
use daita\Traits\TArrayTools;
use JsonSerializable;
class APHosts implements JsonSerializable {
use TArrayTools;
/** @var string */
private $address;
/** @var array */
private $uriIds = [];
public function __construct(string $address = '') {
$this->address = $address;
}
/**
* @return string
*/
public function getAddress(): string {
return $this->address;
}
/**
* @param string $uriId
*
* @return APHosts
*/
public function addUriId(string $uriId): APHosts {
$this->uriIds[] = $uriId;
return $this;
}
/**
* @return array
*/
public function getUriIds(): array {
return $this->uriIds;
}
public function jsonSerialize() {
return [
'address' => $this->address,
'urlIds' => $this->getUriIds()
];
}
}

Wyświetl plik

@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\ActivityPub;
use JsonSerializable;
class ActivityCreate extends Core implements JsonSerializable {
/**
* ActivityCreate constructor.
*
* @param bool $isTopLevel
*/
public function __construct(bool $isTopLevel = false) {
parent::__construct($isTopLevel);
$this->setType('Create');
}
/**
* @return array
*/
public function jsonSerialize(): array {
return array_merge(
parent::jsonSerialize(),
[
]
);
}
}

Wyświetl plik

@ -0,0 +1,330 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\ActivityPub;
use JsonSerializable;
use OCA\Social\Service\ActivityPubService;
class Actor extends Core implements JsonSerializable {
/** @var string */
private $userId = '';
/** @var string */
private $preferredUsername = '';
/** @var string */
private $publicKey = '';
/** @var string */
private $privateKey = '';
/** @var int */
private $creation = 0;
/** @var string */
private $account = '';
/** @var string */
private $following = '';
/** @var string */
private $followers = '';
/** @var string */
private $inbox = '';
/** @var string */
private $outbox = '';
/** @var string */
private $sharedInbox = '';
/**
* Actor constructor.
*
* @param bool $isTopLevel
*/
public function __construct(bool $isTopLevel = false) {
parent::__construct($isTopLevel);
$this->setType('Person');
}
/**
* @return string
*/
public function getUserId(): string {
return $this->userId;
}
/**
* @param string $userId
*
* @return Actor
*/
public function setUserId(string $userId): Actor {
$this->userId = $userId;
if ($this->getPreferredUsername() === '') {
$this->setPreferredUsername($userId);
}
return $this;
}
/**
* @return string
*/
public function getPreferredUsername(): string {
return $this->preferredUsername;
}
/**
* @param string $preferredUsername
*
* @return Actor
*/
public function setPreferredUsername(string $preferredUsername): Actor {
if ($preferredUsername !== '') {
$this->preferredUsername = $preferredUsername;
}
return $this;
}
/**
* @return string
*/
public function getPublicKey(): string {
return $this->publicKey;
}
/**
* @param string $publicKey
*
* @return Actor
*/
public function setPublicKey(string $publicKey): Actor {
$this->publicKey = $publicKey;
return $this;
}
/**
* @return string
*/
public function getPrivateKey(): string {
return $this->privateKey;
}
/**
* @param string $privateKey
*
* @return Actor
*/
public function setPrivateKey(string $privateKey): Actor {
$this->privateKey = $privateKey;
return $this;
}
/**
* @return int
*/
public function getCreation(): int {
return $this->creation;
}
/**
* @param int $creation
*
* @return Actor
*/
public function setCreation(int $creation): Actor {
$this->creation = $creation;
return $this;
}
/**
* @return string
*/
public function getFollowing(): string {
return $this->following;
}
/**
* @param string $following
*
* @return Actor
*/
public function setFollowing(string $following): Actor {
$this->following = $following;
return $this;
}
/**
* @return string
*/
public function getFollowers(): string {
return $this->followers;
}
/**
* @param string $followers
*
* @return Actor
*/
public function setFollowers(string $followers): Actor {
$this->followers = $followers;
return $this;
}
/**
* @return string
*/
public function getAccount(): string {
return $this->account;
}
/**
* @param string $account
*
* @return Actor
*/
public function setAccount(string $account): Actor {
$this->account = $account;
return $this;
}
/**
* @return string
*/
public function getInbox(): string {
return $this->inbox;
}
/**
* @param string $inbox
*
* @return Actor
*/
public function setInbox(string $inbox): Actor {
$this->inbox = $inbox;
return $this;
}
/**
* @return string
*/
public function getOutbox(): string {
return $this->outbox;
}
/**
* @param string $outbox
*
* @return Actor
*/
public function setOutbox(string $outbox): Actor {
$this->outbox = $outbox;
return $this;
}
/**
* @return string
*/
public function getSharedInbox(): string {
return $this->sharedInbox;
}
/**
* @param string $sharedInbox
*
* @return Actor
*/
public function setSharedInbox(string $sharedInbox): Actor {
$this->sharedInbox = $sharedInbox;
return $this;
}
/**
* @return array
*/
public function jsonSerialize(): array {
return [
'@context' => [
ActivityPubService::CONTEXT_ACTIVITYSTREAMS,
ActivityPubService::CONTEXT_SECURITY
],
'aliases' => [
$this->getRoot() . '@' . $this->getPreferredUsername(),
$this->getRoot() . 'users/' . $this->getPreferredUsername()
],
'id' => $this->getId(),
'type' => $this->getType(),
'preferredUsername' => $this->getPreferredUsername(),
'inbox' => $this->getInbox(),
'outbox' => $this->getOutbox(),
'following' => $this->getFollowing(),
'followers' => $this->getFollowers(),
'url' => $this->getId(),
'endpoints' =>
['sharedInbox' => $this->getSharedInbox()],
'publicKey' => [
'id' => $this->getId() . '#main-key',
'owner' => $this->getId(),
'publicKeyPem' => $this->getPublicKey()
]
];
}
}

Wyświetl plik

@ -0,0 +1,157 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\ActivityPub\Cache;
class CacheActor {
/** @var int */
private $id;
/** @var string */
private $account = '';
/** @var string */
private $url;
/** @var array */
private $actor = [];
/** @var int */
private $creation = 0;
/**
* CacheActor constructor.
*
* @param int $id
*/
public function __construct($id = 0) {
$this->id = $id;
}
/**
* @return int
*/
public function getId(): int {
return $this->id;
}
/**
* @param int $id
*
* @return CacheActor
*/
public function setId(int $id): CacheActor {
$this->account = $id;
return $this;
}
/**
* @return string
*/
public function getAccount(): string {
return $this->account;
}
/**
* @param string $account
*
* @return CacheActor
*/
public function setAccount(string $account): CacheActor {
$this->account = $account;
return $this;
}
/**
* @return string
*/
public function getUrl(): string {
return $this->url;
}
/**
* @param string $url
*
* @return CacheActor
*/
public function setUrl(string $url): CacheActor {
$this->url = $url;
return $this;
}
/**
* @return array
*/
public function getActor(): array {
return $this->actor;
}
/**
* @param array $actor
*
* @return CacheActor
*/
public function setActor(array $actor): CacheActor {
$this->actor = $actor;
return $this;
}
/**
* @return int
*/
public function getCreation(): int {
return $this->creation;
}
/**
* @param int $creation
*
* @return CacheActor
*/
public function setCreation(int $creation): CacheActor {
$this->creation = $creation;
return $this;
}
}

Wyświetl plik

@ -0,0 +1,443 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\ActivityPub;
use JsonSerializable;
use OCA\Social\Service\ICoreService;
class Core implements JsonSerializable {
/** @var string */
private $root = '';
/** @var bool */
private $isTopLevel = false;
/** @var string */
private $address = '';
/** @var string */
private $id = '';
/** @var string */
private $type;
/** @var string */
private $to = '';
/** @var array */
private $toArray = [];
/** @var array */
private $cc = [];
/** @var array */
private $bcc = [];
/** @var Actor */
private $actor;
/** @var array */
private $tags = [];
/** @var array */
private $entries = [];
/** @var Core */
private $object = null;
/** @var ICoreService */
private $saveAs;
/**
* Core constructor.
*
* @param bool $isTopLevel
*/
public function __construct(bool $isTopLevel = false) {
$this->isTopLevel = $isTopLevel;
}
/**
* @return string
*/
public function getId(): string {
return $this->id;
}
/**
* @param string $id
*
* @return Core
*/
public function setId(string $id): Core {
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getType(): string {
return $this->type;
}
/**
* @param string $type
*
* @return Core
*/
public function setType(string $type): Core {
$this->type = $type;
return $this;
}
/**
* @return Actor
*/
public function getActor(): Actor {
return $this->actor;
}
/**
* @param Actor $actor
*
* @return Core
*/
public function setActor(Actor $actor): Core {
$this->actor = $actor;
return $this;
}
/**
* @return bool
*/
public function gotActor(): bool {
if ($this->actor === null) {
return false;
}
return true;
}
/**
* @return string
*/
public function getRoot(): string {
return $this->root;
}
/**
* @param string $path
*
* @return Core
*/
public function setRoot(string $path): Core {
$this->root = $path;
return $this;
}
/**
* @return string
*/
public function getAddress(): string {
return $this->address;
}
/**
* @param string $address
*
* @return Core
*/
public function setAddress(string $address) {
$this->address = $address;
return $this;
}
/**
* @return string
*/
public function getTo(): string {
return $this->to;
}
/**
* @param string $to
*
* @return Core
*/
public function setTo(string $to): Core {
$this->to = $to;
return $this;
}
/**
* @return array
*/
public function getToArray(): array {
return $this->toArray;
}
/**
* @param array $toArray
*
* @return Core
*/
public function setToArray(array $toArray): Core {
$this->toArray = $toArray;
return $this;
}
/**
* @return array
*/
public function getCc(): array {
return $this->cc;
}
/**
* @param array $cc
*
* @return Core
*/
public function setCc(array $cc): Core {
$this->cc = $cc;
return $this;
}
/**
* @return array
*/
public function getBcc(): array {
return $this->bcc;
}
/**
* @param array $bcc
*
* @return Core
*/
public function setBcc(array $bcc): Core {
$this->bcc = $bcc;
return $this;
}
/**
* @param array $tag
*
* @return Core
*/
public function addTag(array $tag): Core {
$this->tags[] = $tag;
return $this;
}
/**
* @return array
*/
public function getTags(): array {
return $this->tags;
}
/**
* @param array $tag
*
* @return Core
*/
public function setTags(array $tag): Core {
$this->tags = $tag;
return $this;
}
/**
* @return bool
*/
public function gotObject(): bool {
if ($this->object === null) {
return false;
}
return true;
}
/**
* @return Core
*/
public function getObject(): Core {
return $this->object;
}
/**
* @param Core $object
*
* @return Core
*/
public function setObject(Core $object): Core {
$this->object = $object;
return $this;
}
/**
* @return bool
*/
public function isTopLevel(): bool {
return $this->isTopLevel;
}
/**
* @param array $arr
*
* @return Core
*/
public function setEntries(array $arr): Core {
$this->entries = $arr;
return $this;
}
/**
* @return array
*/
public function getEntries(): array {
return $this->entries;
}
/**
* @param string $k
* @param string $v
*
* @return Core
*/
public function addEntry(string $k, string $v): Core {
if ($v === '') {
unset($this->entries[$k]);
return $this;
}
$this->entries[$k] = $v;
return $this;
}
/**
* @param string $k
* @param array $v
*
* @return Core
*/
public function addEntryArray(string $k, array $v): Core {
$this->entries[$k] = $v;
return $this;
}
/**
* @param ICoreService $class
*/
public function saveAs(ICoreService $class) {
$this->saveAs = $class;
}
/**
* @return ICoreService
*/
public function savingAs() {
return $this->saveAs;
}
/**
* @return array
*/
public function jsonSerialize(): array {
$this->addEntry('id', $this->getId());
$this->addEntry('type', $this->getType());
$this->addEntry('url', $this->getId());
if ($this->getToArray() === []) {
$this->addEntry('to', $this->getTo());
} else {
$this->addEntryArray('to', $this->getToArray());
}
$this->addEntryArray('cc', $this->getCc());
if ($this->gotActor()) {
$this->addEntry(
'actor', $this->getActor()
->getId()
);
}
if ($this->getTags() !== []) {
$this->addEntryArray('tag', $this->getTags());
}
$arr = $this->getEntries();
if ($this->gotObject()) {
$arr['object'] = $this->getObject();
}
return $arr;
}
}

Wyświetl plik

@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\ActivityPub;
use JsonSerializable;
class Note extends Core implements JsonSerializable {
/** @var string */
private $content;
/** @var string */
private $summary = '';
/** @var string */
private $published;
/** @var string */
private $attributedTo;
/** @var string */
private $inReplyTo = '';
/**
* Note constructor.
*
* @param bool $isTopLevel
*/
public function __construct(bool $isTopLevel = false) {
parent::__construct($isTopLevel);
$this->setType('Note');
}
/**
* @return string
*/
public function getContent(): string {
return $this->content;
}
/**
* @param string $content
*
* @return Note
*/
public function setContent(string $content): Note {
$this->content = $content;
return $this;
}
/**
* @return string
*/
public function getSummary(): string {
return $this->summary;
}
/**
* @param string $summary
*
* @return Note
*/
public function setSummary(string $summary): Note {
$this->summary = $summary;
return $this;
}
/**
* @return string
*/
public function getPublished(): string {
return $this->published;
}
/**
* @param string $published
*
* @return Note
*/
public function setPublished(string $published): Note {
$this->published = $published;
return $this;
}
/**
* @return string
*/
public function getAttributedTo(): string {
return $this->attributedTo;
}
/**
* @param string $attributedTo
*
* @return Note
*/
public function setAttributedTo(string $attributedTo): Note {
$this->attributedTo = $attributedTo;
return $this;
}
/**
* @return string
*/
public function getInReplyTo(): string {
return $this->inReplyTo;
}
/**
* @param string $inReplyTo
*
* @return Note
*/
public function setInReplyTo(string $inReplyTo): Note {
$this->inReplyTo = $inReplyTo;
return $this;
}
// public function
//"published": "2018-06-23T17:17:11Z",
//"attributedTo": "https://my-example.com/actor",
//"inReplyTo": "https://mastodon.social/@Gargron/100254678717223630",
/**
* @return array
*/
public function jsonSerialize(): array {
return array_merge(
parent::jsonSerialize(),
[
'content' => $this->getContent(),
'published' => $this->getPublished(),
'attributedTo' => $this->getRoot() . $this->getAttributedTo(),
'inReplyTo' => $this->getInReplyTo()
]
);
}
}

Wyświetl plik

@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service\ActivityPub;
use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Service\ActivityStreamsService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\CurlService;
use OCA\Social\Service\ICoreService;
use OCA\Social\Service\MiscService;
class InboxService implements ICoreService {
/** @var InboxRequest */
private $inboxRequest;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/**
* InboxService constructor.
*
* @param InboxRequest $inboxRequest
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
InboxRequest $inboxRequest,
ConfigService $configService,
MiscService $miscService
) {
$this->inboxRequest = $inboxRequest;
$this->configService = $configService;
$this->miscService = $miscService;
}
}

Wyświetl plik

@ -0,0 +1,130 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service\ActivityPub;
use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Service\ActivityStreamsService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\CurlService;
use OCA\Social\Service\ICoreService;
use OCA\Social\Service\MiscService;
class NoteService implements ICoreService {
/** @var NotesRequest */
private $notesRequest;
/** @var ActivityStreamsService */
private $activityStreamsService;
/** @var ActorService */
private $actorService;
/** @var CurlService */
private $curlService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/**
* NoteService constructor.
*
* @param NotesRequest $notesRequest
* @param ActivityStreamsService $activityStreamsService
* @param ActorService $actorService
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
NotesRequest $notesRequest, ActivityStreamsService $activityStreamsService,
ActorService $actorService,
CurlService $curlService,
ConfigService $configService,
MiscService $miscService
) {
$this->notesRequest = $notesRequest;
$this->activityStreamsService = $activityStreamsService;
$this->actorService = $actorService;
$this->curlService = $curlService;
$this->configService = $configService;
$this->miscService = $miscService;
}
/**
* @param string $userId
* @param string $content
* @param string $to
*
* @return Note
* @throws ActorDoesNotExistException
* @throws NoUserException
*/
public function generateNote(string $userId, string $content, string $to) {
$note = new Note();
$actor = $this->actorService->getActorFromUserId($userId);
$note->setId($this->configService->generateId('@' . $actor->getPreferredUsername()));
$note->setPublished(date("c"));
$note->setAttributedTo(
$this->configService->getRoot() . '@' . $actor->getPreferredUsername()
);
$note->setTo($to);
$note->setContent($content);
$note->saveAs($this);
return $note;
}
/**
* @param Core $note
*
* @throws Exception
*/
public function save(Core $note) {
/** @var Note $note */
$this->notesRequest->create($note);
}
}

Wyświetl plik

@ -0,0 +1,491 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use daita\Model\Request;
use DateTime;
use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\ActorsRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\APIRequestException;
use OCA\Social\Exceptions\InvalidAccessTokenException;
use OCA\Social\Exceptions\MovedPermanentlyException;
use OCA\Social\Model\ActivityPub\ActivityCreate;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Model\APHosts;
use OCP\IRequest;
class ActivityPubService {
const CONTEXT_ACTIVITYSTREAMS = 'https://www.w3.org/ns/activitystreams';
const CONTEXT_SECURITY = 'https://w3id.org/security/v1';
const TO_PUBLIC = 'https://www.w3.org/ns/activitystreams#Public';
const DATE_FORMAT = 'D, d M Y H:i:s T';
const DATE_DELAY = 30;
/** @var ActivityStreamsService */
private $activityStreamsService;
/** @var ActorsRequest */
private $actorsRequest;
/** @var ActorService */
private $actorService;
/** @var ConfigService */
private $configService;
/** @var CurlService */
private $curlService;
/** @var MiscService */
private $miscService;
/**
* ActivityStreamsService constructor.
*
* @param ActivityStreamsService $activityStreamsService
* @param CurlService $curlService
* @param ActorsRequest $actorsRequest
* @param ActorService $actorService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActivityStreamsService $activityStreamsService,
CurlService $curlService,
ActorsRequest $actorsRequest,
ActorService $actorService,
ConfigService $configService, MiscService $miscService
) {
$this->activityStreamsService = $activityStreamsService;
$this->curlService = $curlService;
$this->actorsRequest = $actorsRequest;
$this->actorService = $actorService;
$this->configService = $configService;
$this->miscService = $miscService;
}
public function test() {
}
/**
* @param string $userId
*
* @param Core $item
* @param Core $activity
*
* @return array
* @throws ActorDoesNotExistException
* @throws NoUserException
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
*/
public function createActivity($userId, Core $item, Core &$activity = null): array {
$activity = new ActivityCreate(true);
// $this->activityStreamsService->initCore($activity);
$actor = $this->actorService->getActorFromUserId($userId);
$activity->setId($item->getId() . '/activity');
if ($item->getToArray() !== []) {
$activity->setToArray($item->getToArray());
} else {
$activity->setTo($item->getTo());
}
$activity->setActor($actor);
$activity->setObject($item);
$this->setupCore($activity);
$result = $this->request($activity);
return $result;
}
/**
* @param Core $activity
*
* @return array
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
*/
public function request(Core $activity) {
$hosts = $this->getAPHostsFromActivity($activity);
$result = [];
foreach ($hosts as $host) {
$request = $this->generateRequest($host, $activity);
$result[] = $this->curlService->request($request);
}
return $result;
}
/**
* @param APHosts $host
* @param Core $activity
*
* @return Request
*/
public function generateRequest(APHosts $host, Core $activity): Request {
$document = json_encode($activity);
$date = date(self::DATE_FORMAT);
$localActor = $activity->getActor();
$uriIds = $host->getUriIds();
$remoteActor = $this->getRemoteActor($uriIds[0]);
$localActorLink =
$this->configService->getRoot() . '@' . $localActor->getPreferredUsername();
$signature = "(request-target): post /users/testSocial/inbox\nhost: " . $host->getAddress()
. "\ndate: " . $date;
openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256);
$signed = base64_encode($signed);
$header =
'keyId="' . $localActorLink . '",headers="(request-target) host date",signature="'
. $signed . '"';
$request = new Request('/users/testSocial/inbox', Request::TYPE_POST);
$request->addHeader('Host: ' . $host->getAddress());
$request->addHeader('Date: ' . $date);
$request->addHeader('Signature: ' . $header);
$request->setDataJson($document);
$request->setAddress($host->getAddress());
return $request;
}
/**
* @param IRequest $request
*
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
* @throws Exception
*/
public function checkRequest(IRequest $request) {
$dTime = new DateTime($request->getHeader('date'));
$dTime->format(self::DATE_FORMAT);
if ($dTime->getTimestamp() < (time() - self::DATE_DELAY)) {
throw new Exception('object is too old');
}
$this->checkSignature($request);
}
// /**
// * @param Core $activity
// *
// * @return array
// */
// private function getHostsFromActivity(Core $activity) {
//
// $hosts = [];
// $hosts[] = $this->getHostFromUriId($activity->getTo());
// foreach ($activity->getToArray() as $to) {
// $hosts[] = $this->getHostFromUriId($to);
// }
//
// if ($activity instanceof Note) {
// /** @var Note $activity */
// $hosts[] = $this->getHostFromUriId($activity->getInReplyTo());
// }
//
// $hosts = $this->cleaningHosts($hosts);
//
// return $hosts;
// }
/**
* @param Core $activity
*
* @return APHosts[]
*/
private function getAPHostsFromActivity(Core $activity) {
$hosts = [];
// $uriIds = [];
$this->addAPHosts($activity->getTo(), $hosts);
foreach ($activity->getToArray() as $to) {
$this->addAPHosts($to, $hosts);
// $uriIds[] = $to;
}
if ($activity instanceof Note) {
/** @var Note $activity */
$this->addAPHosts($activity->getInReplyTo(), $hosts);
// $uriIds[] = $activity->getInReplyTo();
}
// $uriId = $this->cleaningHosts($uriId);
return $hosts;
}
/**
* @param string $uriId
* @param APHosts[] $hosts
*/
private function addAPHosts(string $uriId, array &$hosts) {
$address = $this->getHostFromUriId($uriId);
if ($address === '') {
return;
}
foreach ($hosts as $host) {
if ($host->getAddress() === $address) {
$host->addUriId($uriId);
return;
}
}
$apHost = new APHosts($address);
$apHost->addUriId($uriId);
$hosts[] = $apHost;
}
/**
* @param string $uriId
*
* @return mixed
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
*/
private function getRemoteActor(string $uriId) {
$actor = $this->actorService->getFromUri($uriId);
return $actor;
}
/**
* @param string $uriId
*
* @return string
*/
private function getHostFromUriId(string $uriId) {
$ignoreThose = [
'',
'https://www.w3.org/ns/activitystreams#Public'
];
if (in_array($uriId, $ignoreThose)) {
return '';
}
$url = parse_url($uriId);
if (!is_array($url) || !array_key_exists('host', $url)) {
return '';
}
return $url['host'];
}
// /**
// * @param array $hosts
// *
// * @return array
// */
// private function cleaningHosts(array $hosts) {
// $ret = [];
// foreach ($hosts as $host) {
// if ($host === '') {
// continue;
// }
//
// $ret[] = $host;
// }
//
// return $ret;
// }
/**
* @param IRequest $request
*
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
* @throws Exception
*/
private function checkSignature(IRequest $request) {
$signatureHeader = $request->getHeader('Signature');
$sign = $this->parseSignatureHeader($signatureHeader);
$this->miscService->mustContains(['keyId', 'headers', 'signature'], $sign);
$keyId = $sign['keyId'];
$headers = $sign['headers'];
$signed = base64_decode($sign['signature']);
$estimated = $this->generateEstimatedSignature($headers, $request);
$publicKey = $this->retrieveKey($keyId);
if (openssl_verify($estimated, $signed, $publicKey, 'sha256') !== 1) {
throw new Exception('signature cannot be checked');
}
}
/**
* @param string $headers
* @param IRequest $request
*
* @return string
*/
private function generateEstimatedSignature(string $headers, IRequest $request): string {
$keys = explode(' ', $headers);
$estimated = "(request-target): post /apps/social/@maxence/inbox";
foreach ($keys as $key) {
if ($key === '(request-target)') {
continue;
}
$estimated .= "\n" . $key . ': ' . $request->getHeader($key);
}
return $estimated;
}
/**
* @param $signatureHeader
*
* @return array
*/
private function parseSignatureHeader($signatureHeader) {
$sign = [];
$entries = explode(',', $signatureHeader);
foreach ($entries as $entry) {
list($k, $v) = explode('=', $entry, 2);
preg_match('/"([^"]+)"/', $v, $varr);
$v = trim($varr[0], '"');
$sign[$k] = $v;
}
return $sign;
}
/**
* @param $keyId
*
* @return array
* @throws MovedPermanentlyException
* @throws APIRequestException
* @throws InvalidAccessTokenException
*/
private function retrieveKey($keyId) {
$actor = $this->retrieveObject($keyId);
return $actor['publicKey']['publicKeyPem'];
}
//
// /**
// * @param $id
// *
// * @return mixed
// * @throws MovedPermanentlyException
// * @throws APIRequestException
// * @throws InvalidAccessTokenException
// */
// private function retrieveObject($id) {
// $url = parse_url($id);
//
// $request = new Request($url['path'], Request::TYPE_GET);
// $request->setAddress($url['host']);
//
//// $key = $url['fragment'];
//
// return $this->curlService->request($request);
// }
/**
* @param Core $activity
*/
private function setupCore(Core $activity) {
// $this->initCore($activity);
if ($activity->isTopLevel()) {
$activity->addEntry('@context', self::CONTEXT_ACTIVITYSTREAMS);
}
$coreService = $activity->savingAs();
if ($coreService !== null) {
$coreService->save($activity);
}
if ($activity->gotObject()) {
$this->setupCore($activity->getObject());
}
}
// public function setRoot(IActivityPub $actor) {
// $actor->setRoot('https://test.artificial-owl.com/apps/social');
// }
}

Wyświetl plik

@ -35,6 +35,7 @@ use Exception;
use OCA\Social\Db\ServiceAccountsRequest;
use OCA\Social\Exceptions\ActivityStreamsRequestException;
use OCA\Social\Exceptions\InvalidAccessTokenException;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Model\ServiceAccount;
use OCA\Social\Traits\TOAuth2;
@ -57,8 +58,8 @@ class ActivityStreamsService {
/** @var ConfigService */
private $configService;
/** @var CurlService */
private $curlService;
/** @var ClientCurlService */
private $clientCurlService;
/** @var MiscService */
private $miscService;
@ -69,20 +70,32 @@ class ActivityStreamsService {
*
* @param ServiceAccountsRequest $serviceAccountsRequest
* @param ConfigService $configService
* @param CurlService $curlService
* @param ClientCurlService $clientCurlService
* @param MiscService $miscService
*/
public function __construct(
ServiceAccountsRequest $serviceAccountsRequest, ConfigService $configService,
CurlService $curlService, MiscService $miscService
ClientCurlService $clientCurlService, MiscService $miscService
) {
$this->serviceAccountsRequest = $serviceAccountsRequest;
$this->configService = $configService;
$this->curlService = $curlService;
$this->clientCurlService = $clientCurlService;
$this->miscService = $miscService;
}
/**
* @param Core $core
*/
public function initCore(Core &$core) {
$core->setRoot('https://test.artificial-owl.com/apps/social');
}
// TODO : clean below !
/**
* @param ServiceAccount $account
*
@ -146,7 +159,7 @@ class ActivityStreamsService {
*/
private function request(ServiceAccount $account, Request $request) {
try {
return $this->curlService->request($account, $request, true);
return $this->clientCurlService->request($account, $request, true);
} catch (InvalidAccessTokenException $e) {
// $this->oAuth2TokensRequest->resetToken($auth);
throw new ActivityStreamsRequestException($e->getMessage());

Wyświetl plik

@ -0,0 +1,232 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use daita\Traits\TArrayTools;
use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\ActorsRequest;
use OCA\Social\Db\CacheActorsRequest;
use OCA\Social\Exceptions\ActorAlreadyExistsException;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\APIRequestException;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Exceptions\InvalidAccessTokenException;
use OCA\Social\Exceptions\MovedPermanentlyException;
use OCA\Social\Model\ActivityPub\Actor;
class ActorService {
use TArrayTools;
/** @var UriIdService */
private $uriIdService;
/** @var ConfigService */
private $configService;
/** @var ActorsRequest */
private $actorsRequest;
/** @var CacheActorsRequest */
private $cacheActorsRequest;
/** @var MiscService */
private $miscService;
/**
* ActivityStreamsService constructor.
*
* @param ActorsRequest $actorsRequest
* @param CacheActorsRequest $cacheActorsRequest
* @param UriIdService $uriIdService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActorsRequest $actorsRequest,
CacheActorsRequest $cacheActorsRequest, UriIdService $uriIdService,
ConfigService $configService, MiscService $miscService
) {
$this->configService = $configService;
$this->uriIdService = $uriIdService;
$this->actorsRequest = $actorsRequest;
$this->cacheActorsRequest = $cacheActorsRequest;
$this->miscService = $miscService;
}
/**
* @param string $username
*
* @return Actor
* @throws ActorDoesNotExistException
* @throws NoUserException
*/
public function getActor(string $username): Actor {
$actor = $this->actorsRequest->getFromUsername($username);
return $actor;
}
/**
* @param string $userId
*
* @return Actor
* @throws ActorDoesNotExistException
* @throws NoUserException
*/
public function getActorFromUserId(string $userId): Actor {
$this->miscService->confirmUserId($userId);
$actor = $this->actorsRequest->getFromUserId($userId);
return $actor;
}
/**
* @param string $uriId
*
* @return Actor
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
* @throws Exception
*/
public function getFromUri(string $uriId) {
try {
$cache = $this->cacheActorsRequest->getFromUrl($uriId);
return $this->generateActor($cache->getActor());
} catch (CacheActorDoesNotExistException $e) {
$object = $this->uriIdService->retrieveObject($uriId);
$actor = $this->generateActor($object);
$this->cacheActorsRequest->create($actor, $object);
return $actor;
}
}
/**
* @param array $object
*
* @return Actor
*/
public function generateActor(array $object) {
$actor = new Actor();
$actor->setId($this->get('id', $object));
$actor->setFollowers($this->get('followers', $object));
$actor->setFollowing($this->get('following', $object));
$actor->setInbox($this->get('inbox', $object));
$actor->setOutbox($this->get('outbox', $object));
$actor->setPublicKey($object['publicKey']['publicKeyPem']);
$actor->setPreferredUsername($this->get('preferredUsername', $object));
$actor->setAccount('@' . $actor->getPreferredUsername() . '@' . $object['_address']);
// $actor->setSharedInbox($this->get(''))
return $actor;
}
/**
* @param string $userId
*
* @throws ActorAlreadyExistsException
* @throws NoUserException
* @throws Exception
*/
public function createActor(string $userId, string $username) {
$this->miscService->confirmUserId($userId);
$this->checkActorUsername($username);
$this->configService->setCoreValue('public_webfinger', 'social/lib/webfinger.php');
try {
$this->actorsRequest->getFromUsername($username);
throw new ActorAlreadyExistsException('actor with that name already exist');
} catch (ActorDoesNotExistException $e) {
/* we do nohtin */
}
try {
$this->actorsRequest->getFromUserId($userId);
throw new ActorAlreadyExistsException('account for this user already exist');
} catch (ActorDoesNotExistException $e) {
/* we do nohtin */
}
$actor = new Actor();
$actor->setUserId($userId);
$actor->setPreferredUsername($username);
$this->generateKeys($actor);
$this->actorsRequest->create($actor);
}
/**
* @param $username
*
* @return bool
*/
private function checkActorUsername($username) {
return;
}
/**
* @param Actor $actor
*/
private function generateKeys(Actor &$actor) {
$res = openssl_pkey_new(
[
"digest_alg" => "rsa",
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
]
);
openssl_pkey_export($res, $privateKey);
$publicKey = openssl_pkey_get_details($res)['key'];
$actor->setPublicKey($publicKey);
$actor->setPrivateKey($privateKey);
}
}

Wyświetl plik

@ -0,0 +1,214 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use daita\Model\Request;
use OCA\Social\Exceptions\APIRequestException;
use OCA\Social\Exceptions\InvalidAccessTokenException;
use OCA\Social\Exceptions\MovedPermanentlyException;
use OCA\Social\Model\Service;
use OCA\Social\Model\ServiceAccount;
class ClientCurlService {
/** @var MiscService */
private $miscService;
/**
* ClientCurlService constructor.
*
* @param MiscService $miscService
*/
public function __construct(MiscService $miscService) {
$this->miscService = $miscService;
}
/**
* @param ServiceAccount $account
* @param Request $request
* @param bool $authed
*
* @return array
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
* @throws APIRequestException
*/
public function request(ServiceAccount $account, Request $request, bool $authed = true) {
$curl = $this->initRequest($account, $request, $authed);
$this->initRequestPost($curl, $request);
$this->initRequestPut($curl, $request);
$this->initRequestDelete($curl, $request);
$result = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
echo 'code: ' . $code . "\n";
echo 'result: ' . json_encode($result) . "\n";
$this->parseRequestResultCode301($code);
$this->parseRequestResultCode401($code);
$this->parseRequestResultCode404($code);
// $this->parseRequestResultCode503($code);
// $this->parseRequestResultCode500($code);
// $this->parseRequestResult($result);
return json_decode($result, true);
}
/**
* @param ServiceAccount $account
* @param Request $request
* @param bool $authed
*
* @return resource
*/
private function initRequest(ServiceAccount $account, Request $request, bool $authed) {
$curl = $this->generateCurlRequest($account, $request);
$headers = $request->getHeaders();
if ($authed) {
$headers[] = 'Authorization: Bearer ' . $account->getAuth('token');
}
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($curl, CURLOPT_TIMEOUT, 20);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
return $curl;
}
/**
* @param ServiceAccount $account
* @param Request $request
*
* @return resource
*/
private function generateCurlRequest(ServiceAccount $account, Request $request) {
$service = $account->getService();
$url = 'https://' . $service->getAddress() . $request->getParsedUrl();
if ($request->getType() !== Request::TYPE_GET) {
$curl = curl_init($url);
} else {
$curl = curl_init($url . '?' . $request->getDataBody());
}
return $curl;
}
/**
* @param resource $curl
* @param Request $request
*/
private function initRequestPost($curl, Request $request) {
if ($request->getType() !== Request::TYPE_POST) {
return;
}
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
}
/**
* @param resource $curl
* @param Request $request
*/
private function initRequestPut($curl, Request $request) {
if ($request->getType() !== Request::TYPE_PUT) {
return;
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
}
/**
* @param resource $curl
* @param Request $request
*/
private function initRequestDelete($curl, Request $request) {
if ($request->getType() !== Request::TYPE_DELETE) {
return;
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
}
/**
* @param int $code
*
* @throws MovedPermanentlyException
*/
private function parseRequestResultCode301($code) {
if ($code === 301) {
throw new MovedPermanentlyException('301 Moved Permanently');
}
}
/**
* @param int $code
*
* @throws InvalidAccessTokenException
*/
private function parseRequestResultCode401($code) {
if ($code === 401) {
throw new InvalidAccessTokenException('401 Access Token Invalid');
}
}
/**
* @param int $code
*
* @throws APIRequestException
*/
private function parseRequestResultCode404($code) {
if ($code === 404) {
throw new APIRequestException('404 Not Found');
}
}
}

Wyświetl plik

@ -70,7 +70,8 @@ class ConfigService {
* @param MiscService $miscService
*/
public function __construct(
string $userId, IConfig $config, IRequest $request, MiscService $miscService
$userId, IConfig $config, IRequest $request,
MiscService $miscService
) {
$this->userId = $userId;
$this->config = $config;
@ -176,6 +177,15 @@ class ConfigService {
}
/**
* @param string $key
* @param string $value
*/
public function setCoreValue(string $key, string $value) {
$this->config->setAppValue('core', $key, $value);
}
/**
* @param $key
*
@ -189,6 +199,32 @@ class ConfigService {
return $this->request->getServerHost();
}
/**
* @return string
*/
public function getRoot(): string {
return 'https://test.artificial-owl.com/apps/social/';
}
/**
* @param string $path
* @param bool $generateId
*
* @return string
*/
public function generateId(string $path = '', $generateId = true): string {
$this->miscService->formatPath($path);
$id = $this->getRoot() . $path;
if ($generateId === true) {
$id .= time() . crc32(uniqid());
}
return $id;
}
// /**
// * @return array
// */

Wyświetl plik

@ -34,6 +34,7 @@ use daita\Model\Request;
use OCA\Social\Exceptions\APIRequestException;
use OCA\Social\Exceptions\InvalidAccessTokenException;
use OCA\Social\Exceptions\MovedPermanentlyException;
use OCA\Social\Model\Service;
use OCA\Social\Model\ServiceAccount;
class CurlService {
@ -44,7 +45,7 @@ class CurlService {
/**
* CurlService constructor.
* ClientCurlService constructor.
*
* @param MiscService $miscService
*/
@ -54,51 +55,53 @@ class CurlService {
/**
* @param ServiceAccount $account
* @param Request $request
* @param bool $authed
*
* @return array
* @throws APIRequestException
* @throws InvalidAccessTokenException
* @throws MovedPermanentlyException
* @throws APIRequestException
*/
public function request(ServiceAccount $account, Request $request, bool $authed = true) {
public function request(Request $request): array {
$curl = $this->initRequest($request);
$curl = $this->initRequest($account, $request, $authed);
$this->initRequestPost($curl, $request);
$this->initRequestPut($curl, $request);
$this->initRequestDelete($curl, $request);
$result = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$this->parseRequestResultCode301($code);
$this->parseRequestResultCode401($code);
// $this->parseRequestResultCode401($code);
$this->parseRequestResultCode404($code);
// $this->parseRequestResultCode503($code);
// $this->parseRequestResultCode500($code);
// $this->parseRequestResult($result);
$ret = json_decode($result, true);
if (!is_array($ret)) {
$ret = ['_result' => $result];
}
return json_decode($result, true);
$ret['_address'] = $request->getAddress();
$ret['_code'] = $code;
return $ret;
}
/**
* @param ServiceAccount $account
* @param Request $request
* @param bool $authed
*
* @return resource
*/
private function initRequest(ServiceAccount $account, Request $request, bool $authed) {
private function initRequest(Request $request) {
$curl = $this->generateCurlRequest($account, $request);
$headers = [];
if ($authed) {
$headers[] = 'Authorization: Bearer ' . $account->getAuth('token');
}
$curl = $this->generateCurlRequest($request);
$headers = $request->getHeaders();
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($curl, CURLOPT_TIMEOUT, 20);
@ -111,14 +114,12 @@ class CurlService {
/**
* @param ServiceAccount $account
* @param Request $request
*
* @return resource
*/
private function generateCurlRequest(ServiceAccount $account, Request $request) {
$service = $account->getService();
$url = 'https://' . $service->getAddress() . $request->getParsedUrl();
private function generateCurlRequest(Request $request) {
$url = 'https://' . $request->getAddress() . $request->getParsedUrl();
if ($request->getType() !== Request::TYPE_GET) {
$curl = curl_init($url);
@ -183,16 +184,6 @@ class CurlService {
}
}
/**
* @param int $code
*
* @throws InvalidAccessTokenException
*/
private function parseRequestResultCode401($code) {
if ($code === 401) {
throw new InvalidAccessTokenException('401 Access Token Invalid');
}
}
/**
* @param int $code

Wyświetl plik

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use OCA\Social\Model\ActivityPub\Core;
interface ICoreService {
public function save(Core $core);
}

Wyświetl plik

@ -29,8 +29,11 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use Exception;
use OC\User\NoUserException;
use OCA\Social\AppInfo\Application;
use OCP\ILogger;
use OCP\IUserManager;
class MiscService {
@ -38,14 +41,19 @@ class MiscService {
/** @var ILogger */
private $logger;
/** @var IUserManager */
private $userManager;
/**
* MiscService constructor.
*
* @param ILogger $logger
* @param IUserManager $userManager
*/
public function __construct(ILogger $logger) {
public function __construct(ILogger $logger, IUserManager $userManager) {
$this->logger = $logger;
$this->userManager = $userManager;
}
@ -63,6 +71,20 @@ class MiscService {
}
/**
* @param array $keys
* @param array $arr
*
* @throws Exception
*/
public function mustContains(array $keys, array $arr) {
foreach ($keys as $key) {
if (!array_key_exists($key, $arr)) {
throw new Exception('missing elements');
}
}
}
public static function noEndSlash($path) {
if (substr($path, -1) === '/') {
$path = substr($path, 0, -1);
@ -72,5 +94,39 @@ class MiscService {
}
/**
* @param string $path
*/
public function formatPath(string &$path) {
if ($path === '') {
return;
}
if (substr($path, 0, 1) === '/') {
$path = substr($path, 1);
}
if (substr($path, -1) !== '/') {
$path .= '/';
}
}
/**
* @param string $userId
*
* @throws NoUserException
*/
public function confirmUserId(string &$userId) {
$user = $this->userManager->get($userId);
return;
if ($user === null) {
throw new NoUserException('user does not exist');
}
$userId = $user->getUID();
}
}

Wyświetl plik

@ -53,8 +53,8 @@ class ServicesService {
/** @var ConfigService */
private $configService;
/** @var CurlService */
private $curlService;
/** @var ClientCurlService */
private $clientCurlService;
/** @var MiscService */
private $miscService;
@ -65,16 +65,16 @@ class ServicesService {
*
* @param ServicesRequest $servicesRequest
* @param ConfigService $configService
* @param CurlService $curlService
* @param ClientCurlService $clientCurlService
* @param MiscService $miscService
*/
public function __construct(
ServicesRequest $servicesRequest, ConfigService $configService, CurlService $curlService,
ServicesRequest $servicesRequest, ConfigService $configService, ClientCurlService $clientCurlService,
MiscService $miscService
) {
$this->servicesRequest = $servicesRequest;
$this->configService = $configService;
$this->curlService = $curlService;
$this->clientCurlService = $clientCurlService;
$this->miscService = $miscService;
}
@ -151,7 +151,7 @@ class ServicesService {
$request = new Request(ActivityStreamsService::URL_CREATE_APP, Request::TYPE_POST);
$request->setData($data);
return $this->curlService->request($account, $request, false);
return $this->clientCurlService->request($account, $request, false);
}

Wyświetl plik

@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use daita\Model\Request;
use OCA\Social\Exceptions\APIRequestException;
use OCA\Social\Exceptions\InvalidAccessTokenException;
use OCA\Social\Exceptions\MovedPermanentlyException;
class UriIdService {
/** @var ConfigService */
private $configService;
private $curlService;
/** @var MiscService */
private $miscService;
/**
* UriIdService constructor.
*
* @param ConfigService $configService
* @param CurlService $curlService
* @param MiscService $miscService
*/
public function __construct(
ConfigService $configService, CurlService $curlService, MiscService $miscService
) {
$this->configService = $configService;
$this->curlService = $curlService;
$this->miscService = $miscService;
}
/**
* @param $id
*
* @return mixed
* @throws MovedPermanentlyException
* @throws APIRequestException
* @throws InvalidAccessTokenException
*/
public function retrieveObject($id) {
$url = parse_url($id);
$request = new Request($url['path'], Request::TYPE_GET);
$request->setAddress($url['host']);
// $key = $url['fragment'];
return $this->curlService->request($request);
}
}

Wyświetl plik

@ -47,6 +47,9 @@ class Request implements \JsonSerializable {
/** @var int */
private $type;
/** @var array */
private $headers = [];
/** @var array */
private $data = [];
@ -88,6 +91,10 @@ class Request implements \JsonSerializable {
$url = $this->getUrl();
$ak = array_keys($this->getData());
foreach ($ak as $k) {
if (!is_string($this->data[$k])) {
continue;
}
$url = str_replace(':' . $k, $this->data[$k], $url);
}
@ -111,6 +118,32 @@ class Request implements \JsonSerializable {
}
public function addHeader($header): Request {
$this->headers[] = $header;
return $this;
}
/**
* @return array
*/
public function getHeaders(): array {
return $this->headers;
}
/**
* @param array $headers
*
* @return Request
*/
public function setHeaders(array $headers): Request {
$this->headers = $headers;
return $this;
}
/**
* @return array
*/
@ -185,14 +218,14 @@ class Request implements \JsonSerializable {
* @return string
*/
public function getDataBody() {
if ($this->getData() === []) {
return '';
}
return preg_replace(
'/([(%5B)]{1})[0-9]+([(%5D)]{1})/', '$1$2', http_build_query($this->getData())
);
return json_encode($this->getData());
// if ($this->getData() === []) {
// return '';
// }
//
// return preg_replace(
// '/([(%5B)]{1})[0-9]+([(%5D)]{1})/', '$1$2', http_build_query($this->getData())
// );
}

Wyświetl plik

@ -30,6 +30,7 @@ declare(strict_types=1);
namespace daita\Traits;
use JsonSerializable;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
@ -60,7 +61,17 @@ trait TNCDataResponse {
'status' => 1
];
return new DataResponse($data, Http::STATUS_CREATED);
return new DataResponse($data, Http::STATUS_OK);
}
/**
* @param JsonSerializable $result
*
* @return DataResponse
*/
private function directSuccess(JsonSerializable $result): DataResponse {
return new DataResponse($result, Http::STATUS_OK);
}
}

66
lib/webfinger.php 100644
Wyświetl plik

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social;
require_once __DIR__ . '/../appinfo/autoload.php';
require_once(__DIR__ . '/../lib/autoload.php');
if (!array_key_exists('resource', $_GET)) {
echo 'missing resource';
exit();
}
$subject = $_GET['resource'];
$urlGenerator = \OC::$server->getURLGenerator();
list($type, $account) = explode(':', $subject, 2);
if ($type !== 'acct') {
echo 'no acct';
exit();
}
$username = substr($account, 0, strrpos($account, '@'));
$finger = [
'subject' => $subject,
'links' => [
[
'rel' => 'self',
'type' => 'application/activity+json',
// 'href' => 'https://test.artificial-owl.com/apps/social/@' . $username
'href' => $urlGenerator->linkToRouteAbsolute(
'social.ActivityPub.aliasactor', ['username' => $username]
)
]
]
];
header('Content-type: application/json');
echo json_encode($finger);

Wyświetl plik

@ -0,0 +1 @@
ACTOR !

Wyświetl plik

@ -0,0 +1 @@
FOLLOWERS !!!1

Wyświetl plik

@ -0,0 +1 @@
FOLLOWING