renaming services

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/226/head
Maxence Lange 2018-12-17 08:12:27 -01:00
rodzic d028ab206c
commit a1f0ff0198
24 zmienionych plików z 2129 dodań i 900 usunięć

Wyświetl plik

@ -33,10 +33,10 @@ namespace OCA\Social\Command;
use Exception;
use OC\Core\Command\Base;
use OCA\Social\Service\ActivityPub\Object\DocumentService;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\DocumentService;
use OCA\Social\Service\MiscService;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -45,11 +45,11 @@ use Symfony\Component\Console\Output\OutputInterface;
class CacheRefresh extends Base {
/** @var ActorService */
/** @var AccountService */
private $actorService;
/** @var PersonService */
private $personService;
/** @var CacheActorService */
private $cacheActorService;
/** @var DocumentService */
private $documentService;
@ -64,20 +64,20 @@ class CacheRefresh extends Base {
/**
* CacheUpdate constructor.
*
* @param ActorService $actorService
* @param PersonService $personService
* @param AccountService $actorService
* @param CacheActorService $cacheActorService
* @param DocumentService $documentService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActorService $actorService, PersonService $personService, DocumentService $documentService,
ConfigService $configService, MiscService $miscService
AccountService $actorService, CacheActorService $cacheActorService,
DocumentService $documentService, ConfigService $configService, MiscService $miscService
) {
parent::__construct();
$this->actorService = $actorService;
$this->personService = $personService;
$this->cacheActorService = $cacheActorService;
$this->documentService = $documentService;
$this->configService = $configService;
$this->miscService = $miscService;
@ -105,10 +105,10 @@ class CacheRefresh extends Base {
$result = $this->actorService->manageCacheLocalActors();
$output->writeLn($result . ' local accounts regenerated');
$result = $this->personService->missingCacheRemoteActors();
$result = $this->cacheActorService->missingCacheRemoteActors();
$output->writeLn($result . ' remote accounts created');
$result = $this->personService->manageCacheRemoteActors();
$result = $this->cacheActorService->manageCacheRemoteActors();
$output->writeLn($result . ' remote accounts updated');
$result = $this->documentService->manageCacheDocuments();

Wyświetl plik

@ -33,9 +33,8 @@ namespace OCA\Social\Command;
use Exception;
use OC\Core\Command\Base;
use OCA\Social\Model\Post;
use OCA\Social\Service\ActivityPub\Object\NoteService;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\ActivityService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\CurlService;
use OCA\Social\Service\MiscService;
@ -54,10 +53,10 @@ class NoteCreate extends Base {
/** @var ActivityService */
private $activityService;
/** @var ActorService */
/** @var AccountService */
private $actorService;
/** @var NoteService */
/** @var PostService */
private $postService;
/** @var CurlService */
@ -71,14 +70,14 @@ class NoteCreate extends Base {
* NoteCreate constructor.
*
* @param ActivityService $activityService
* @param ActorService $actorService
* @param AccountService $actorService
* @param PostService $postService
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActivityService $activityService, ActorService $actorService,
ActivityService $activityService, AccountService $actorService,
PostService $postService, CurlService $curlService,
ConfigService $configService, MiscService $miscService
) {

Wyświetl plik

@ -34,7 +34,7 @@ namespace OCA\Social\Controller;
use daita\MySmallPhpTools\Traits\Nextcloud\TNCDataResponse;
use Exception;
use OCA\Social\AppInfo\Application;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\MiscService;
use OCP\Accounts\IAccountManager;
@ -61,7 +61,7 @@ class AccountController extends Controller {
/** @var ConfigService */
private $configService;
/** @var ActorService */
/** @var AccountService */
private $actorService;
/** @var MiscService */
@ -77,14 +77,14 @@ class AccountController extends Controller {
* @param IRequest $request
* @param IUserManager $userManager
* @param ConfigService $configService
* @param ActorService $actorService
* @param AccountService $actorService
* @param MiscService $miscService
* @param IAccountManager $accountManager
* @param string $userId
*/
public function __construct(
IRequest $request, $userId, IUserManager $userManager, ConfigService $configService,
ActorService $actorService, MiscService $miscService,
AccountService $actorService, MiscService $miscService,
IAccountManager $accountManager
) {
parent::__construct(Application::APP_NAME, $request);
@ -121,6 +121,9 @@ class AccountController extends Controller {
/**
*
* // TODO - is it still used ? maybe using info from LocalController !?
*
* @PublicPage
* @NoCSRFRequired
* @NoAdminRequired

Wyświetl plik

@ -34,15 +34,13 @@ use daita\MySmallPhpTools\Traits\Nextcloud\TNCDataResponse;
use Exception;
use OC\AppFramework\Http;
use OCA\Social\AppInfo\Application;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\SignatureIsGoneException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Service\ActivityPub\Activity\FollowService;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCA\Social\Service\ActivityService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\FollowService;
use OCA\Social\Service\ImportService;
use OCA\Social\Service\MiscService;
use OCA\Social\Service\SignatureService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\IRequest;
@ -57,8 +55,11 @@ class ActivityPubController extends Controller {
/** @var SocialPubController */
private $socialPubController;
/** @var ActivityService */
private $activityService;
/** @var CacheActorService */
private $cacheActorService;
/** @var SignatureService */
private $signatureService;
/** @var ImportService */
private $importService;
@ -66,15 +67,6 @@ class ActivityPubController extends Controller {
/** @var FollowService */
private $followService;
/** @var ActorService */
private $actorService;
/** @var PersonService */
private $personService;
/** @var NotesRequest */
private $notesRequest;
/** @var MiscService */
private $miscService;
@ -84,30 +76,24 @@ class ActivityPubController extends Controller {
*
* @param IRequest $request
* @param SocialPubController $socialPubController
* @param ActivityService $activityService
* @param CacheActorService $cacheActorService
* @param SignatureService $signatureService
* @param ImportService $importService
* @param FollowService $followService
* @param ActorService $actorService
* @param PersonService $personService
* @param NotesRequest $notesRequest
* @param MiscService $miscService
*/
public function __construct(
IRequest $request, SocialPubController $socialPubController,
ActivityService $activityService, ImportService $importService,
FollowService $followService, ActorService $actorService, PersonService $personService,
NotesRequest $notesRequest, MiscService $miscService
CacheActorService $cacheActorService, SignatureService $signatureService,
ImportService $importService, FollowService $followService, MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->socialPubController = $socialPubController;
$this->activityService = $activityService;
$this->cacheActorService = $cacheActorService;
$this->signatureService = $signatureService;
$this->importService = $importService;
$this->followService = $followService;
$this->actorService = $actorService;
$this->personService = $personService;
$this->notesRequest = $notesRequest;
$this->miscService = $miscService;
}
@ -133,7 +119,7 @@ class ActivityPubController extends Controller {
}
try {
$actor = $this->personService->getFromLocalAccount($username);
$actor = $this->cacheActorService->getFromLocalAccount($username);
// $actor->setTopLevel(true);
@ -177,10 +163,11 @@ class ActivityPubController extends Controller {
$body = file_get_contents('php://input');
$this->miscService->log('[<<] shared-inbox: ' . $body, 1);
$origin = $this->activityService->checkRequest($this->request);
$origin = $this->signatureService->checkRequest($this->request);
$activity = $this->importService->importFromJson($body);
$activity->setOrigin($origin);
try {
$this->importService->parseIncomingRequest($activity);
} catch (UnknownItemException $e) {
@ -212,7 +199,7 @@ class ActivityPubController extends Controller {
$body = file_get_contents('php://input');
$this->miscService->log('[<<] inbox: ' . $body, 1);
$origin = $this->activityService->checkRequest($this->request);
$origin = $this->signatureService->checkRequest($this->request);
// TODO - check the recipient <-> username
// $actor = $this->actorService->getActor($username);
@ -265,7 +252,7 @@ class ActivityPubController extends Controller {
}
try {
$actor = $this->actorService->getActor($username);
$actor = $this->cacheActorService->getFromLocalAccount($username);
$followers = $this->followService->getFollowersCollection($actor);
// $followers->setTopLevel(true);

Wyświetl plik

@ -38,13 +38,14 @@ use OCA\Social\Exceptions\AccountDoesNotExistException;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Note;
use OCA\Social\Model\Post;
use OCA\Social\Service\ActivityPub\Object\DocumentService;
use OCA\Social\Service\ActivityPub\Activity\FollowService;
use OCA\Social\Service\ActivityPub\Object\NoteService;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\DocumentService;
use OCA\Social\Service\FollowService;
use OCA\Social\Service\MiscService;
use OCA\Social\Service\NoteService;
use OCA\Social\Service\PostService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
@ -69,21 +70,21 @@ class LocalController extends Controller {
/** @var string */
private $userId;
/** @var PersonService */
private $personService;
/** @var CacheActorService */
private $cacheActorService;
/** @var FollowService */
private $followService;
/** @var ActorService */
private $actorService;
/** @var PostService */
private $postService;
/** @var NoteService */
private $noteService;
/** @var AccountService */
private $accountService;
/** @var DocumentService */
private $documentService;
@ -100,30 +101,28 @@ class LocalController extends Controller {
*
* @param IRequest $request
* @param string $userId
* @param PersonService $personService
* @param AccountService $accountService
* @param CacheActorService $cacheActorService
* @param FollowService $followService
* @param ActorService $actorService
* @param PostService $postService
* @param NoteService $noteService
* @param DocumentService $documentService
* @param MiscService $miscService
*/
public function __construct(
IRequest $request, $userId, PersonService $personService,
FollowService $followService, ActorService $actorService,
PostService $postService, NoteService $noteService,
DocumentService $documentService,
IRequest $request, $userId, AccountService $accountService,
CacheActorService $cacheActorService, FollowService $followService,
PostService $postService, NoteService $noteService, DocumentService $documentService,
MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->userId = $userId;
$this->actorService = $actorService;
$this->personService = $personService;
$this->followService = $followService;
$this->postService = $postService;
$this->cacheActorService = $cacheActorService;
$this->accountService = $accountService;
$this->noteService = $noteService;
$this->postService = $postService;
$this->followService = $followService;
$this->documentService = $documentService;
$this->miscService = $miscService;
}
@ -146,7 +145,7 @@ class LocalController extends Controller {
$post->setReplyTo($this->get('replyTo', $data, ''));
$post->setTo($this->getArray('to', $data, []));
$post->addTo($this->get('to', $data, ''));
$post->setType($this->get('type', $data, NoteService::TYPE_PUBLIC));
$post->setType($this->get('type', $data, Note::TYPE_PUBLIC));
/** @var ACore $activity */
$token = $this->postService->createPost($post, $activity);
@ -179,7 +178,7 @@ class LocalController extends Controller {
public function postDelete(string $id): DataResponse {
try {
$note = $this->noteService->getNoteById($id);
$actor = $this->actorService->getActorFromUserId($this->userId);
$actor = $this->accountService->getActorFromUserId($this->userId);
if ($note->getAttributedTo() !== $actor->getId()) {
throw new InvalidResourceException('user have no rights');
}
@ -234,7 +233,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$account = $this->actorService->getActor($username);
$account = $this->cacheActorService->getFromLocalAccount($username);
$posts = $this->noteService->getStreamAccount($account->getId(), $since, $limit);
return $this->success($posts);
@ -331,7 +330,7 @@ class LocalController extends Controller {
*/
public function actionFollow(string $account): DataResponse {
try {
$actor = $this->actorService->getActorFromUserId($this->userId);
$actor = $this->accountService->getActorFromUserId($this->userId);
$this->followService->followAccount($actor, $account);
return $this->success([]);
@ -355,7 +354,7 @@ class LocalController extends Controller {
*/
public function actionUnfollow(string $account): DataResponse {
try {
$actor = $this->actorService->getActorFromUserId($this->userId);
$actor = $this->accountService->getActorFromUserId($this->userId);
$this->followService->unfollowAccount($actor, $account);
return $this->success([]);
@ -377,8 +376,8 @@ class LocalController extends Controller {
*/
public function currentInfo(): DataResponse {
try {
$actor = $this->actorService->getActorFromUserId($this->userId);
$actor = $this->personService->getFromLocalAccount($actor->getPreferredUsername());
$local = $this->accountService->getActorFromUserId($this->userId);
$actor = $this->cacheActorService->getFromLocalAccount($local->getPreferredUsername());
return $this->success(['account' => $actor]);
} catch (Exception $e) {
@ -398,7 +397,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$actor = $this->actorService->getActorFromUserId($this->userId);
$actor = $this->accountService->getActorFromUserId($this->userId);
$followers = $this->followService->getFollowers($actor);
return $this->success($followers);
@ -419,7 +418,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$actor = $this->actorService->getActorFromUserId($this->userId);
$actor = $this->accountService->getActorFromUserId($this->userId);
$followers = $this->followService->getFollowing($actor);
return $this->success($followers);
@ -445,8 +444,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$actor = $this->actorService->getActor($username);
$actor = $this->personService->getFromLocalAccount($actor->getPreferredUsername());
$actor = $this->cacheActorService->getFromLocalAccount($username);
return $this->success(['account' => $actor]);
} catch (Exception $e) {
@ -468,7 +466,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$actor = $this->actorService->getActor($username);
$actor = $this->cacheActorService->getFromLocalAccount($username);
$followers = $this->followService->getFollowers($actor);
return $this->success($followers);
@ -492,7 +490,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$actor = $this->actorService->getActor($username);
$actor = $this->cacheActorService->getFromLocalAccount($username);
$following = $this->followService->getFollowing($actor);
return $this->success($following);
@ -518,7 +516,7 @@ class LocalController extends Controller {
try {
$this->initViewer();
$actor = $this->personService->getFromAccount($account);
$actor = $this->cacheActorService->getFromAccount($account);
return $this->success(['account' => $actor]);
} catch (Exception $e) {
@ -542,7 +540,7 @@ class LocalController extends Controller {
public function globalActorInfo(string $id): DataResponse {
try {
$this->initViewer();
$actor = $this->personService->getFromId($id);
$actor = $this->cacheActorService->getFromId($id);
return $this->success(['actor' => $actor]);
} catch (Exception $e) {
@ -561,7 +559,7 @@ class LocalController extends Controller {
*/
public function globalActorAvatar(string $id): Response {
try {
$actor = $this->personService->getFromId($id);
$actor = $this->cacheActorService->getFromId($id);
if ($actor->gotIcon()) {
$avatar = $actor->getIcon();
$document = $this->documentService->getFromCache($avatar->getId());
@ -606,13 +604,13 @@ class LocalController extends Controller {
/* Look for an exactly matching account */
$match = null;
try {
$match = $this->personService->getFromAccount($search, false);
$match = $this->cacheActorService->getFromAccount($search, false);
$match->setCompleteDetails(true);
} catch (Exception $e) {
}
try {
$accounts = $this->personService->searchCachedAccounts($search);
$accounts = $this->cacheActorService->searchCachedAccounts($search);
return $this->success(['accounts' => $accounts, 'exact' => $match]);
} catch (Exception $e) {
@ -658,11 +656,10 @@ class LocalController extends Controller {
*/
private function initViewer(bool $exception = false) {
try {
$this->viewer = $this->actorService->getActorFromUserId($this->userId, true);
$this->viewer = $this->accountService->getActorFromUserId($this->userId, true);
$this->followService->setViewerId($this->viewer->getId());
$this->personService->setViewerId($this->viewer->getId());
$this->noteService->setViewerId($this->viewer->getId());
$this->cacheActorService->setViewerId($this->viewer->getId());
} catch (Exception $e) {
if ($exception) {
throw new AccountDoesNotExistException();

Wyświetl plik

@ -37,11 +37,11 @@ use OC\User\NoUserException;
use OCA\Social\AppInfo\Application;
use OCA\Social\Exceptions\AccountAlreadyExistsException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Service\ActivityPub\Object\DocumentService;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCA\Social\Service\ActorService;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CheckService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\DocumentService;
use OCA\Social\Service\MiscService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
@ -69,8 +69,8 @@ class NavigationController extends Controller {
/** @var IURLGenerator */
private $urlGenerator;
/** @var ActorService */
private $actorService;
/** @var AccountService */
private $accountService;
private $documentService;
@ -83,46 +83,40 @@ class NavigationController extends Controller {
/** @var IL10N */
private $l10n;
/** @var PersonService */
private $personService;
/** @var CheckService */
private $checkService;
/**
* NavigationController constructor.
*
* @param IL10N $l10n
* @param IRequest $request
* @param string $userId
* @param IConfig $config
* @param IURLGenerator $urlGenerator
* @param ActorService $actorService
* @param AccountService $accountService
* @param DocumentService $documentService
* @param ConfigService $configService
* @param PersonService $personService
* @param CheckService $checkService
* @param MiscService $miscService
* @param IL10N $l10n
*/
public function __construct(
IRequest $request, $userId, IConfig $config, IURLGenerator $urlGenerator,
ActorService $actorService, DocumentService $documentService, ConfigService $configService,
PersonService $personService, CheckService $checkService,
MiscService $miscService, IL10N $l10n
IL10N $l10n, IRequest $request, $userId, IConfig $config, IURLGenerator $urlGenerator,
AccountService $accountService, DocumentService $documentService,
ConfigService $configService, CheckService $checkService, MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->userId = $userId;
$this->l10n = $l10n;
$this->config = $config;
$this->urlGenerator = $urlGenerator;
$this->checkService = $checkService;
$this->actorService = $actorService;
$this->accountService = $accountService;
$this->documentService = $documentService;
$this->configService = $configService;
$this->personService = $personService;
$this->miscService = $miscService;
$this->l10n = $l10n;
}
@ -136,6 +130,7 @@ class NavigationController extends Controller {
* @param string $path
*
* @return TemplateResponse
* @throws UrlCloudException
*/
public function navigate(string $path = ''): TemplateResponse {
$data = [
@ -143,7 +138,8 @@ class NavigationController extends Controller {
'public' => false,
'firstrun' => false,
'setup' => false,
'isAdmin' => \OC::$server->getGroupManager()->isAdmin($this->userId),
'isAdmin' => \OC::$server->getGroupManager()
->isAdmin($this->userId),
'cliUrl' => $this->getCliUrl()
]
];
@ -152,7 +148,7 @@ class NavigationController extends Controller {
$data['serverData']['cloudAddress'] = $this->configService->getCloudAddress();
} catch (SocialAppConfigException $e) {
$cloudAddress = $this->setupCloudAddress();
if ($cloudAddress !== ''){
if ($cloudAddress !== '') {
$data['serverData']['cloudAddress'] = $cloudAddress;
} else {
$data['serverData']['setup'] = true;
@ -177,7 +173,7 @@ class NavigationController extends Controller {
* Create social user account if it doesn't exist yet
*/
try {
$this->actorService->createActor($this->userId, $this->userId);
$this->accountService->createActor($this->userId, $this->userId);
$data['serverData']['firstrun'] = true;
} catch (AccountAlreadyExistsException $e) {
// we do nothing
@ -191,7 +187,9 @@ class NavigationController extends Controller {
}
private function setupCloudAddress(): string {
$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
$frontControllerActive =
($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true
|| getenv('front_controller_active') === 'true');
$cloudAddress = rtrim($this->config->getSystemValue('overwrite.cli.url', ''), '/');
if ($cloudAddress !== '') {
@ -199,17 +197,22 @@ class NavigationController extends Controller {
$cloudAddress .= '/index.php';
}
$this->configService->setCloudAddress($cloudAddress);
return $cloudAddress;
}
return '';
}
private function getCliUrl() {
$url = rtrim($this->urlGenerator->getBaseUrl(), '/');
$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
$frontControllerActive =
($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true
|| getenv('front_controller_active') === 'true');
if (!$frontControllerActive) {
$url .= '/index.php';
}
return $url;
}
@ -251,6 +254,7 @@ class NavigationController extends Controller {
* @param string $path
*
* @return TemplateResponse
* @throws UrlCloudException
*/
public function timeline(string $path = ''): TemplateResponse {
return $this->navigate();
@ -266,6 +270,7 @@ class NavigationController extends Controller {
* @param string $path
*
* @return TemplateResponse
* @throws UrlCloudException
*/
public function account(string $path = ''): TemplateResponse {
return $this->navigate();

Wyświetl plik

@ -30,10 +30,13 @@ declare(strict_types=1);
namespace OCA\Social\Controller;
use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Traits\TAsync;
use OCA\Social\AppInfo\Application;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\RequestQueue;
use OCA\Social\Service\ActivityService;
use OCA\Social\Service\MiscService;
@ -105,6 +108,9 @@ class QueueController extends Controller {
$this->activityService->manageRequest($request);
} catch (RequestException $e) {
} catch (SocialAppConfigException $e) {
} catch (RedundancyLimitException $e) {
} catch (UnknownItemException $e) {
} catch (MalformedArrayException $e) {
}
}
}

Wyświetl plik

@ -35,8 +35,9 @@ use Exception;
use OCA\Social\AppInfo\Application;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\FollowService;
use OCA\Social\Service\MiscService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\NotFoundResponse;
@ -57,11 +58,14 @@ class SocialPubController extends Controller {
/** @var IL10N */
private $l10n;
/** @var ActorService */
private $actorService;
/** @var AccountService */
private $accountService;
/** @var PersonService */
private $personService;
/** @var CacheActorService */
private $cacheActorService;
/** @var FollowService */
private $followService;
/** @var MiscService */
private $miscService;
@ -73,20 +77,22 @@ class SocialPubController extends Controller {
* @param $userId
* @param IRequest $request
* @param IL10N $l10n
* @param ActorService $actorService
* @param PersonService $personService
* @param AccountService $accountService
* @param CacheActorService $cacheActorService
* @param FollowService $followService
* @param MiscService $miscService
*/
public function __construct(
$userId, IRequest $request, IL10N $l10n, ActorService $actorService,
PersonService $personService, MiscService $miscService
$userId, IRequest $request, IL10N $l10n, AccountService $accountService,
CacheActorService $cacheActorService, FollowService $followService, MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
$this->userId = $userId;
$this->l10n = $l10n;
$this->actorService = $actorService;
$this->personService = $personService;
$this->accountService = $accountService;
$this->cacheActorService = $cacheActorService;
$this->followService = $followService;
$this->miscService = $miscService;
}
@ -105,14 +111,14 @@ class SocialPubController extends Controller {
public function actor(string $username): Response {
try {
$actor = $this->personService->getFromLocalAccount($username);
$actor = $this->cacheActorService->getFromLocalAccount($username);
$actor->setCompleteDetails(true);
$logged = false;
$ownAccount = false;
if ($this->userId !== null) {
$logged = true;
$local = $this->actorService->getActorFromUserId($this->userId, true);
$local = $this->accountService->getActorFromUserId($this->userId, true);
if ($local->getId() === $actor->getId()) {
$ownAccount = true;
} else {
@ -195,7 +201,7 @@ class SocialPubController extends Controller {
* @param Person $local
*/
private function fillActorWithLinks(Person $actor, Person $local) {
$links = $this->actorService->getLinksBetweenPersons($local, $actor);
$links = $this->followService->getLinksBetweenPersons($local, $actor);
$actor->addDetailArray('link', $links);
}

Wyświetl plik

@ -34,10 +34,10 @@ namespace OCA\Social\Cron;
use Exception;
use OC\BackgroundJob\TimedJob;
use OCA\Social\AppInfo\Application;
use OCA\Social\Service\ActivityPub\Object\DocumentService;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\DocumentService;
use OCA\Social\Service\MiscService;
use OCP\AppFramework\QueryException;
@ -50,11 +50,11 @@ use OCP\AppFramework\QueryException;
class Cache extends TimedJob {
/** @var ActorService */
private $actorService;
/** @var AccountService */
private $accountService;
/** @var PersonService */
private $personService;
/** @var CacheActorService */
private $cacheActorService;
/** @var DocumentService */
private $documentService;
@ -83,8 +83,8 @@ class Cache extends TimedJob {
$app = new Application();
$c = $app->getContainer();
$this->actorService = $c->query(ActorService::class);
$this->personService = $c->query(PersonService::class);
$this->accountService = $c->query(AccountService::class);
$this->cacheActorService = $c->query(CacheActorService::class);
$this->documentService = $c->query(DocumentService::class);
$this->configService = $c->query(ConfigService::class);
$this->miscService = $c->query(MiscService::class);
@ -95,12 +95,12 @@ class Cache extends TimedJob {
private function manageCache() {
try {
$this->actorService->manageCacheLocalActors();
$this->accountService->manageCacheLocalActors();
} catch (Exception $e) {
}
try {
$this->personService->manageCacheRemoteActors();
$this->cacheActorService->manageCacheRemoteActors();
} catch (Exception $e) {
}

Wyświetl plik

@ -31,10 +31,13 @@ declare(strict_types=1);
namespace OCA\Social\Cron;
use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
use OC\BackgroundJob\TimedJob;
use OCA\Social\AppInfo\Application;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Service\ActivityService;
use OCA\Social\Service\MiscService;
use OCA\Social\Service\QueueService;
@ -70,7 +73,10 @@ class Queue extends TimedJob {
/**
* @param mixed $argument
*
* @throws MalformedArrayException
* @throws QueryException
* @throws RedundancyLimitException
* @throws UnknownItemException
*/
protected function run($argument) {
$app = new Application();
@ -84,6 +90,11 @@ class Queue extends TimedJob {
}
/**
* @throws RedundancyLimitException
* @throws UnknownItemException
* @throws MalformedArrayException
*/
private function manageQueue() {
$requests = $this->queueService->getRequestStandby();
$this->activityService->manageInit();

Wyświetl plik

@ -38,10 +38,9 @@ use OCA\Social\Exceptions\InvalidOriginException;
use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Interfaces\IActivityPubInterface;
abstract class ACore extends Item implements JsonSerializable {
class ACore extends Item implements JsonSerializable {
use TArrayTools;
@ -72,8 +71,6 @@ abstract class ACore extends Item implements JsonSerializable {
/** @var Document */
private $icon = null;
/** @var IActivityPubInterface */
private $saveAs;
/**
* Core constructor.
@ -168,21 +165,6 @@ abstract class ACore extends Item implements JsonSerializable {
}
// /**
// * @param ICoreService $class
// */
// public function saveAs(ICoreService $class) {
// $this->saveAs = $class;
// }
//
// /**
// * @return ICoreService
// */
// public function savingAs() {
// return $this->saveAs;
// }
//
/**
* @param string $base
*

Wyświetl plik

@ -38,12 +38,9 @@ use OCA\Social\Db\FollowsRequest;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\AccountAlreadyExistsException;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\FollowDoesNotExistException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Interfaces\Object\DocumentInterface;
use OCA\Social\Interfaces\Actor\PersonInterface;
use OCP\Accounts\IAccountManager;
use OCP\IUserManager;
@ -53,7 +50,7 @@ use OCP\IUserManager;
*
* @package OCA\Social\Service
*/
class ActorService {
class AccountService {
use TArrayTools;
@ -74,13 +71,13 @@ class ActorService {
/** @var NotesRequest */
private $notesRequest;
/** @var PersonInterface */
private $personService;
/** @var ActorService */
private $actorService;
/** @var SignatureService */
private $signatureService;
/** @var DocumentInterface */
/** @var DocumentService */
private $documentService;
/** @var ConfigService */
@ -98,15 +95,16 @@ class ActorService {
* @param ActorsRequest $actorsRequest
* @param FollowsRequest $followsRequest
* @param NotesRequest $notesRequest
* @param PersonInterface $personService
* @param DocumentInterface $documentService
* @param ActorService $actorService
* @param DocumentService $documentService
* @param SignatureService $signatureService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
IUserManager $userManager, IAccountManager $accountManager, ActorsRequest $actorsRequest,
FollowsRequest $followsRequest, NotesRequest $notesRequest, PersonInterface $personService,
DocumentInterface $documentService, SignatureService $signatureService,
FollowsRequest $followsRequest, NotesRequest $notesRequest, ActorService $actorService,
DocumentService $documentService, SignatureService $signatureService,
ConfigService $configService, MiscService $miscService
) {
$this->userManager = $userManager;
@ -114,7 +112,7 @@ class ActorService {
$this->actorsRequest = $actorsRequest;
$this->followsRequest = $followsRequest;
$this->notesRequest = $notesRequest;
$this->personService = $personService;
$this->actorService = $actorService;
$this->documentService = $documentService;
$this->signatureService = $signatureService;
$this->configService = $configService;
@ -129,7 +127,6 @@ class ActorService {
* @throws ActorDoesNotExistException
* @throws SocialAppConfigException
*/
public function getActor(string $username): Person {
$actor = $this->actorsRequest->getFromUsername($username);
@ -143,7 +140,7 @@ class ActorService {
* @throws ActorDoesNotExistException
* @throws SocialAppConfigException
*/
public function getActorById(string $id): Person {
public function getFromId(string $id): Person {
$actor = $this->actorsRequest->getFromId($id);
return $actor;
@ -228,35 +225,6 @@ class ActorService {
}
/**
* @param Person $local
* @param Person $actor
*
* @return array
*/
public function getLinksBetweenPersons(Person $local, Person $actor): array {
$links = [
'follower' => false,
'following' => false
];
try {
$this->followsRequest->getByPersons($local->getId(), $actor->getId());
$links['following'] = true;
} catch (FollowDoesNotExistException $e) {
}
try {
$this->followsRequest->getByPersons($actor->getId(), $local->getId());
$links['follower'] = true;
} catch (FollowDoesNotExistException $e) {
}
return $links;
}
/**
* @param string $username
* @param bool $refresh
@ -284,8 +252,7 @@ class ActorService {
];
$actor->addDetailArray('count', $count);
$this->personService->cacheLocalActor($actor, $refresh);
$this->actorService->cacheLocalActor($actor, $refresh);
} catch (ActorDoesNotExistException $e) {
}
}

Wyświetl plik

@ -33,23 +33,20 @@ namespace OCA\Social\Service;
use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime;
use Exception;
use OCA\Social\Db\ActorsRequest;
use OCA\Social\AP;
use OCA\Social\Db\FollowsRequest;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\EmptyQueueException;
use OCA\Social\Exceptions\InvalidOriginException;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\NoHighPriorityRequestException;
use OCA\Social\Exceptions\QueueStatusException;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SignatureException;
use OCA\Social\Exceptions\SignatureIsGoneException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Activity\Create;
use OCA\Social\Model\ActivityPub\Activity\Delete;
@ -57,8 +54,6 @@ use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Tombstone;
use OCA\Social\Model\InstancePath;
use OCA\Social\Model\RequestQueue;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
use OCP\IRequest;
class ActivityService {
@ -81,9 +76,6 @@ class ActivityService {
const DATE_DELAY = 30;
/** @var ActorsRequest */
private $actorsRequest;
/** @var NotesRequest */
private $notesRequest;
@ -93,14 +85,8 @@ class ActivityService {
/** @var QueueService */
private $queueService;
/** @var ActorService */
private $actorService;
/** @var PersonService */
private $personService;
/** @var InstanceService */
private $instanceService;
/** @var AccountService */
private $accountService;
/** @var ConfigService */
private $configService;
@ -119,31 +105,24 @@ class ActivityService {
/**
* ActivityService constructor.
*
* @param QueueService $queueService
* @param ActorsRequest $actorsRequest
* @param NotesRequest $notesRequest
* @param FollowsRequest $followsRequest
* @param QueueService $queueService
* @param AccountService $accountService
* @param CurlService $curlService
* @param ActorService $actorService
* @param PersonService $personService
* @param InstanceService $instanceService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActorsRequest $actorsRequest, NotesRequest $notesRequest, FollowsRequest $followsRequest,
QueueService $queueService, CurlService $curlService, ActorService $actorService,
PersonService $personService, InstanceService $instanceService,
ConfigService $configService, MiscService $miscService
NotesRequest $notesRequest, FollowsRequest $followsRequest, QueueService $queueService,
AccountService $accountService,
CurlService $curlService, ConfigService $configService, MiscService $miscService
) {
$this->actorsRequest = $actorsRequest;
$this->notesRequest = $notesRequest;
$this->followsRequest = $followsRequest;
$this->queueService = $queueService;
$this->accountService = $accountService;
$this->curlService = $curlService;
$this->actorService = $actorService;
$this->personService = $personService;
$this->instanceService = $instanceService;
$this->configService = $configService;
$this->miscService = $miscService;
}
@ -212,14 +191,14 @@ class ActivityService {
}
$requests = [
$this->notesRequest
'Note'
];
foreach ($requests as $request) {
try {
$toDelete = $request->getNoteById($id);
$interface = AP::$activityPub->getInterfaceFromType($request);
return $toDelete;
return $interface->getItemById($id);
} catch (Exception $e) {
}
}
@ -307,7 +286,8 @@ class ActivityService {
}
/**
/** // ====> instanceService
*
* @param ACore $activity
*
* @return InstancePath[]
@ -382,11 +362,11 @@ class ActivityService {
$date = gmdate(self::DATE_FORMAT);
$localActor = $this->getActorFromAuthor($queue->getAuthor());
// TODO: move this to SignatureService ?
$localActorLink =
$this->configService->getUrlSocial() . '@' . $localActor->getPreferredUsername();
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $path->getAddress()
. "\ndate: " . $date;
openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256);
$signed = base64_encode($signed);
@ -414,44 +394,6 @@ class ActivityService {
}
/**
* @param IRequest $request
*
* @return string
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws RequestException
* @throws SignatureException
* @throws SocialAppConfigException
* @throws UrlCloudException
* @throws SignatureIsGoneException
* @throws InvalidOriginException
*/
public function checkRequest(IRequest $request): string {
// TODO : check host is our current host.
// $host = $request->getHeader('host');
// if ($host === '') {
// throw new SignatureException('host is not set');
// }
$dTime = new DateTime($request->getHeader('date'));
$dTime->format(self::DATE_FORMAT);
if ($dTime->getTimestamp() < (time() - self::DATE_DELAY)) {
throw new SignatureException('object is too old');
}
try {
$origin = $this->checkSignature($request);
} catch (Request410Exception $e) {
throw new SignatureIsGoneException();
}
return $origin;
}
/**
* @param ACore $activity
*
@ -471,144 +413,157 @@ class ActivityService {
* @param string $author
*
* @return Person
* @throws ActorDoesNotExistException
* @throws SocialAppConfigException
* @throws ActorDoesNotExistException
*/
private function getActorFromAuthor(string $author): Person {
return $this->actorService->getActorById($author);
return $this->accountService->getFromId($author);
}
/**
* @param IRequest $request
*
* @return string
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws Request410Exception
* @throws RequestException
* @throws SignatureException
* @throws SocialAppConfigException
* @throws UrlCloudException
* @throws InvalidOriginException
*/
private function checkSignature(IRequest $request): string {
$signatureHeader = $request->getHeader('Signature');
// /**
// * @param IRequest $request
// *
// * @return string
// * @throws InvalidResourceException
// * @throws MalformedArrayException
// * @throws Request410Exception
// * @throws RequestException
// * @throws SignatureException
// * @throws SocialAppConfigException
// * @throws UrlCloudException
// * @throws InvalidOriginException
// */
// private function checkSignature(IRequest $request): string {
// $signatureHeader = $request->getHeader('Signature');
//
// $sign = $this->parseSignatureHeader($signatureHeader);
// $this->mustContains(['keyId', 'headers', 'signature'], $sign);
//
// $keyId = $sign['keyId'];
// $origin = $this->getKeyOrigin($keyId);
//
// $headers = $sign['headers'];
// $signed = base64_decode($sign['signature']);
// $estimated = $this->generateEstimatedSignature($headers, $request);
//
// $publicKey = $this->retrieveKey($keyId);
//
// if ($publicKey === '' || openssl_verify($estimated, $signed, $publicKey, 'sha256') !== 1) {
// throw new SignatureException('signature cannot be checked');
// }
//
// return $origin;
// }
//
$sign = $this->parseSignatureHeader($signatureHeader);
$this->mustContains(['keyId', 'headers', 'signature'], $sign);
$keyId = $sign['keyId'];
$origin = $this->getKeyOrigin($keyId);
$headers = $sign['headers'];
$signed = base64_decode($sign['signature']);
$estimated = $this->generateEstimatedSignature($headers, $request);
$publicKey = $this->retrieveKey($keyId);
if ($publicKey === '' || openssl_verify($estimated, $signed, $publicKey, 'sha256') !== 1) {
throw new SignatureException('signature cannot be checked');
}
return $origin;
}
// /**
// * @param $id
// *
// * @return string
// * @throws InvalidOriginException
// */
// private function getKeyOrigin($id) {
// $host = parse_url($id, PHP_URL_HOST);
// if (is_string($host) && ($host !== '')) {
// return $host;
// }
//
// throw new InvalidOriginException();
// }
//
//
// /**
// * @param string $headers
// * @param IRequest $request
// *
// * @return string
// */
// private function generateEstimatedSignature(string $headers, IRequest $request): string {
// $keys = explode(' ', $headers);
//
// $target = '';
// try {
// $target = strtolower($request->getMethod()) . " " . $request->getRequestUri();
// } catch (Exception $e) {
// }
//
// $estimated = "(request-target): " . $target;
//
// 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 $id
*
* @return string
* @throws InvalidOriginException
*/
private function getKeyOrigin($id) {
$host = parse_url($id, PHP_URL_HOST);
if (is_string($host) && ($host !== '')) {
return $host;
}
throw new InvalidOriginException();
}
/**
* @param string $headers
* @param IRequest $request
*
* @return string
*/
private function generateEstimatedSignature(string $headers, IRequest $request): string {
$keys = explode(' ', $headers);
$target = '';
try {
$target = strtolower($request->getMethod()) . " " . $request->getRequestUri();
} catch (Exception $e) {
}
$estimated = "(request-target): " . $target;
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 string
* @throws InvalidResourceException
* @throws RequestException
* @throws SocialAppConfigException
* @throws UrlCloudException
* @throws Request410Exception
*/
private function retrieveKey($keyId): string {
$actor = $this->personService->getFromId($keyId);
return $actor->getPublicKey();
}
// /**
// * @param $keyId
// *
// * @return string
// * @throws InvalidResourceException
// * @throws RequestException
// * @throws SocialAppConfigException
// * @throws UrlCloudException
// * @throws Request410Exception
// */
// private function retrieveKey($keyId): string {
// $actor = $this->cacheActorService->getFromId($keyId);
//
// return $actor->getPublicKey();
// }
/**
* @param ACore $activity
*/
private function saveActivity(ACore $activity) {
$coreService = $activity->savingAs();
if ($coreService !== null) {
$coreService->save($activity);
}
// TODO: save activity in DB ?
if ($activity->gotObject()) {
$this->saveActivity($activity->getObject());
$this->saveObject($activity->getObject());
}
}
/**
* @param ACore $activity
*/
private function saveObject(ACore $activity) {
try {
if ($activity->gotObject()) {
$this->saveObject($activity->getObject());
}
$service = AP::$activityPub->getInterfaceForItem($activity);
$service->save($activity);
} catch (UnknownItemException $e) {
}
}

Wyświetl plik

@ -0,0 +1,317 @@
<?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\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Traits\TArrayTools;
use Exception;
use OCA\Social\AP;
use OCA\Social\Db\CacheActorsRequest;
use OCA\Social\Db\CacheDocumentsRequest;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Exceptions\CacheDocumentDoesNotExistException;
use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Actor\Person;
/**
* Class ActorService
*
* @package OCA\Social\Service
*/
class ActorService {
use TArrayTools;
/** @var CacheActorsRequest */
private $cacheActorsRequest;
/** @var CacheDocumentsRequest */
private $cacheDocumentsRequest;
/** @var CurlService */
private $curlService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/** @var string */
private $viewerId = '';
/**
* ActorService constructor.
*
* @param CacheActorsRequest $cacheActorsRequest
* @param CacheDocumentsRequest $cacheDocumentsRequest
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
CacheActorsRequest $cacheActorsRequest, CacheDocumentsRequest $cacheDocumentsRequest,
CurlService $curlService,
ConfigService $configService,
MiscService $miscService
) {
$this->cacheActorsRequest = $cacheActorsRequest;
$this->cacheDocumentsRequest = $cacheDocumentsRequest;
$this->curlService = $curlService;
$this->configService = $configService;
$this->miscService = $miscService;
}
/**
* @param string $viewerId
*/
public function setViewerId(string $viewerId) {
$this->viewerId = $viewerId;
$this->cacheActorsRequest->setViewerId($viewerId);
}
public function getViewerId(): string {
return $this->viewerId;
}
/**
* @param Person $actor
* @param bool $refresh
*/
public function cacheLocalActor(Person $actor, bool $refresh = false) {
if ($refresh) {
$this->cacheActorsRequest->deleteFromId($actor->getId());
}
$actor->setLocal(true);
$actor->setSource(json_encode($actor, JSON_UNESCAPED_SLASHES));
$this->save($actor);
}
/**
* @param string $id
*
* @param bool $refresh
*
* @return Person
* @throws InvalidResourceException
* @throws RequestException
* @throws SocialAppConfigException
* @throws UrlCloudException
* @throws Request410Exception
* @throws MalformedArrayException
* @throws InvalidResourceEntryException
*/
public function getFromId(string $id, bool $refresh = false): Person {
$posAnchor = strpos($id, '#');
if ($posAnchor !== false) {
$id = substr($id, 0, $posAnchor);
}
try {
if ($refresh) {
$this->cacheActorsRequest->deleteFromId($id);
throw new CacheActorDoesNotExistException();
}
$actor = $this->cacheActorsRequest->getFromId($id);
} catch (CacheActorDoesNotExistException $e) {
$object = $this->curlService->retrieveObject($id);
$actor = $this->generateActorFromObject($object);
$actor->setAccount($actor->getPreferredUsername() . '@' . $this->get('_host', $object));
try {
$this->save($actor);
} catch (Exception $e) {
throw new InvalidResourceException($e->getMessage());
}
}
return $actor;
}
// /**
// * @param string $account
// *
// * @param bool $retrieve
// *
// * @return Person
// * @throws InvalidResourceException
// * @throws RequestException
// * @throws CacheActorDoesNotExistException
// * @throws SocialAppConfigException
// * @throws UrlCloudException
// * @throws Request410Exception
// * @throws MalformedArrayException
// * @throws InvalidResourceEntryException
// */
// public function getFromAccount(string $account, bool $retrieve = true): Person {
//
// try {
// $actor = $this->cacheActorsRequest->getFromAccount($account);
// } catch (CacheActorDoesNotExistException $e) {
// if (!$retrieve) {
// throw new CacheActorDoesNotExistException();
// }
//
// $object = $this->curlService->retrieveAccount($account);
// $actor = $this->generateActorFromObject($object);
// $actor->setAccount($account);
// try {
// $this->save($actor);
// } catch (Exception $e) {
// throw new InvalidResourceException($e->getMessage());
// }
// }
//
// return $actor;
// }
//
// /**
// * @param string $account
// *
// * @return Person
// * @throws CacheActorDoesNotExistException
// */
// public function getFromLocalAccount(string $account): Person {
// return $this->cacheActorsRequest->getFromLocalAccount($account);
// }
/**
* @param array $object
*
* @return Person
* @throws InvalidResourceException
* @throws SocialAppConfigException
* @throws UrlCloudException
* @throws InvalidResourceEntryException
*/
private function generateActorFromObject(array $object) {
$actor = new Person();
$actor->setUrlCloud($this->configService->getCloudAddress());
$actor->import($object);
if ($actor->getType() !== Person::TYPE) {
throw new InvalidResourceException();
}
$actor->setSource(json_encode($object, JSON_UNESCAPED_SLASHES));
return $actor;
}
//
// /**
// * @param string $search
// *
// * @return Person[]
// */
// public function searchCachedAccounts(string $search): array {
// return $this->cacheActorsRequest->searchAccounts($search);
// }
//
// /**
// * @throws Exception
// * @return int
// */
// public function missingCacheRemoteActors(): int {
// // TODO - looking for missing cache remote actors...
// $missing = [];
//
// foreach ($missing as $item) {
// try {
// $this->getFromId($item->getId());
// } catch (Exception $e) {
// }
// }
//
// return sizeof($missing);
// }
//
// /**
// * @throws Exception
// * @return int
// */
// public function manageCacheRemoteActors(): int {
// $update = $this->cacheActorsRequest->getRemoteActorsToUpdate();
//
// foreach ($update as $item) {
// try {
// $this->getFromId($item->getId(), true);
// } catch (Exception $e) {
// }
// }
//
// return sizeof($update);
// }
/**
* @param Person $actor
*/
public function save(Person $actor) {
if ($actor->gotIcon()) {
try {
$icon = $this->cacheDocumentsRequest->getBySource(
$actor->getIcon()
->getUrl()
);
$actor->setIcon($icon);
} catch (CacheDocumentDoesNotExistException $e) {
$this->cacheDocumentsRequest->save($actor->getIcon());
}
}
$this->cacheActorsRequest->save($actor);
}
}

Wyświetl plik

@ -0,0 +1,255 @@
<?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\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Traits\TArrayTools;
use Exception;
use OCA\Social\AP;
use OCA\Social\Db\CacheActorsRequest;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\ActivityPub\Actor\Person;
class CacheActorService {
use TArrayTools;
/** @var CacheActorsRequest */
private $cacheActorsRequest;
/** @var CurlService */
private $curlService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/** @var string */
private $viewerId;
/**
* CacheService constructor.
*
* @param CacheActorsRequest $cacheActorsRequest
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
CacheActorsRequest $cacheActorsRequest, CurlService $curlService,
ConfigService $configService, MiscService $miscService
) {
$this->cacheActorsRequest = $cacheActorsRequest;
$this->curlService = $curlService;
$this->configService = $configService;
$this->miscService = $miscService;
}
/**
* @param string $viewerId
*/
public function setViewerId(string $viewerId) {
$this->viewerId = $viewerId;
$this->cacheActorsRequest->setViewerId($viewerId);
}
public function getViewerId(): string {
return $this->viewerId;
}
/**
* @param string $id
*
* @param bool $refresh
*
* @return Person
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws Request410Exception
* @throws RequestException
* @throws SocialAppConfigException
* @throws RedundancyLimitException
* @throws UnknownItemException
*/
public function getFromId(string $id, bool $refresh = false): Person {
$posAnchor = strpos($id, '#');
if ($posAnchor !== false) {
$id = substr($id, 0, $posAnchor);
}
try {
if ($refresh) {
$this->cacheActorsRequest->deleteFromId($id);
throw new CacheActorDoesNotExistException();
}
$actor = $this->cacheActorsRequest->getFromId($id);
} catch (CacheActorDoesNotExistException $e) {
$object = $this->curlService->retrieveObject($id);
/** @var Person $actor */
$actor = AP::$activityPub->getItemFromData($object);
$actor->setAccount($actor->getPreferredUsername() . '@' . $this->get('_host', $object));
try {
$this->save($actor);
} catch (Exception $e) {
throw new InvalidResourceException($e->getMessage());
}
}
return $actor;
}
/**
* @param string $account
*
* @return Person
* @throws CacheActorDoesNotExistException
*/
public function getFromLocalAccount(string $account): Person {
return $this->cacheActorsRequest->getFromLocalAccount($account);
}
/**
* @param string $account
*
* @param bool $retrieve
*
* @return Person
* @throws CacheActorDoesNotExistException
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws RedundancyLimitException
* @throws Request410Exception
* @throws RequestException
* @throws SocialAppConfigException
* @throws UnknownItemException
*/
public function getFromAccount(string $account, bool $retrieve = true): Person {
try {
$actor = $this->cacheActorsRequest->getFromAccount($account);
} catch (CacheActorDoesNotExistException $e) {
if (!$retrieve) {
throw new CacheActorDoesNotExistException();
}
$object = $this->curlService->retrieveAccount($account);
/** @var Person $actor */
$actor = AP::$activityPub->getItemFromData($object);
$actor->setAccount($account);
try {
$this->save($actor);
} catch (Exception $e) {
throw new InvalidResourceException($e->getMessage());
}
}
return $actor;
}
/**
* @param string $search
*
* @return Person[]
*/
public function searchCachedAccounts(string $search): array {
return $this->cacheActorsRequest->searchAccounts($search);
}
/**
* @throws Exception
* @return int
*/
public function missingCacheRemoteActors(): int {
// TODO - looking for missing cache remote actors...
$missing = [];
foreach ($missing as $item) {
try {
$this->getFromId($item->getId());
} catch (Exception $e) {
}
}
return sizeof($missing);
}
/**
* @throws Exception
* @return int
*/
public function manageCacheRemoteActors(): int {
$update = $this->cacheActorsRequest->getRemoteActorsToUpdate();
foreach ($update as $item) {
try {
$this->getFromId($item->getId(), true);
} catch (Exception $e) {
}
}
return sizeof($update);
}
/**
* @param Person $actor
*/
private function save(Person $actor) {
try {
$interface = AP::$activityPub->getInterfaceFromType(Person::TYPE);
$interface->save($actor);
} catch (UnknownItemException $e) {
}
}
}

Wyświetl plik

@ -41,7 +41,7 @@ use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
class CacheService {
class CacheDocumentService {
const ERROR_MAX_SIZE = 1;

Wyświetl plik

@ -30,10 +30,13 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use daita\MySmallPhpTools\Exceptions\ArrayNotFoundException;
use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\TArrayTools;
use daita\MySmallPhpTools\Traits\TPathTools;
use Exception;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException;
@ -68,6 +71,65 @@ class CurlService {
}
/**
* @param string $account
*
* @return mixed
* @throws RequestException
* @throws InvalidResourceException
* @throws Request410Exception
* @throws MalformedArrayException
*/
public function retrieveAccount(string $account) {
$account = $this->withoutBeginAt($account);
if (strstr(substr($account, 0, -3), '@') === false) {
throw new InvalidResourceException();
}
list($username, $host) = explode('@', $account);
// if ($username === null || $host === null) {
// throw new InvalidResourceException();
// }
$request = new Request('/.well-known/webfinger');
$request->addData('resource', 'acct:' . $account);
$request->setAddress($host);
$result = $this->request($request);
try {
$link = $this->extractArray('rel', 'self', $this->getArray('links', $result));
} catch (ArrayNotFoundException $e) {
throw new RequestException();
}
return $this->retrieveObject($this->get('href', $link, ''));
}
/**
* @param $id
*
* @return mixed
* @throws RequestException
* @throws Request410Exception
* @throws MalformedArrayException
*/
public function retrieveObject($id) {
$url = parse_url($id);
$this->mustContains(['path', 'host'], $url);
$request = new Request($url['path'], Request::TYPE_GET);
$request->setAddress($url['host']);
$result = $this->request($request);
if (is_array($result)) {
$result['_host'] = $url['host'];
}
return $result;
}
/**
* @param Request $request
*

Wyświetl plik

@ -0,0 +1,231 @@
<?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 Exception;
use OCA\Social\Db\ActorsRequest;
use OCA\Social\Db\CacheDocumentsRequest;
use OCA\Social\Exceptions\CacheContentException;
use OCA\Social\Exceptions\CacheContentMimeTypeException;
use OCA\Social\Exceptions\CacheContentSizeException;
use OCA\Social\Exceptions\CacheDocumentDoesNotExistException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\ActivityPub\Object\Image;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\IURLGenerator;
class DocumentService {
const ERROR_SIZE = 1;
const ERROR_MIMETYPE = 2;
/** @var IURLGenerator */
private $urlGenerator;
/** @var CacheDocumentsRequest */
private $cacheDocumentsRequest;
/** @var ActorsRequest */
private $actorRequest;
/** @var CacheDocumentService */
private $cacheService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/**
* DocumentInterface constructor.
*
* @param IUrlGenerator $urlGenerator
* @param CacheDocumentsRequest $cacheDocumentsRequest
* @param ActorsRequest $actorRequest
* @param CacheDocumentService $cacheService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
IUrlGenerator $urlGenerator, CacheDocumentsRequest $cacheDocumentsRequest,
ActorsRequest $actorRequest,
CacheDocumentService $cacheService,
ConfigService $configService, MiscService $miscService
) {
$this->urlGenerator = $urlGenerator;
$this->cacheDocumentsRequest = $cacheDocumentsRequest;
$this->actorRequest = $actorRequest;
$this->configService = $configService;
$this->cacheService = $cacheService;
$this->miscService = $miscService;
}
/**
* @param string $id
* @param bool $public
*
* @return Document
* @throws CacheDocumentDoesNotExistException
* @throws NotPermittedException
*/
public function cacheRemoteDocument(string $id, bool $public = false) {
$document = $this->cacheDocumentsRequest->getById($id, $public);
if ($document->getError() > 0) {
throw new CacheDocumentDoesNotExistException();
}
if ($document->getLocalCopy() !== '') {
return $document;
}
if ($document->getCaching() > (time() - (CacheDocumentsRequest::CACHING_TIMEOUT * 60))) {
return $document;
}
$mime = '';
$this->cacheDocumentsRequest->initCaching($document);
try {
$localCopy = $this->cacheService->saveRemoteFileToCache($document->getUrl(), $mime);
$document->setMimeType($mime);
$document->setLocalCopy($localCopy);
$this->cacheDocumentsRequest->endCaching($document);
return $document;
} catch (CacheContentMimeTypeException $e) {
$document->setMimeType($mime);
$document->setError(self::ERROR_MIMETYPE);
$this->cacheDocumentsRequest->endCaching($document);
} catch (CacheContentSizeException $e) {
$document->setError(self::ERROR_SIZE);
$this->cacheDocumentsRequest->endCaching($document);
} catch (CacheContentException $e) {
}
throw new CacheDocumentDoesNotExistException();
}
/**
* @param string $id
*
* @param bool $public
*
* @return ISimpleFile
* @throws CacheContentException
* @throws CacheDocumentDoesNotExistException
* @throws NotPermittedException
*/
public function getFromCache(string $id, bool $public = false) {
$document = $this->cacheRemoteDocument($id, $public);
return $this->cacheService->getContentFromCache($document->getLocalCopy());
}
/**
* @return int
* @throws Exception
*/
public function manageCacheDocuments(): int {
$update = $this->cacheDocumentsRequest->getNotCachedDocuments();
$count = 0;
foreach ($update as $item) {
if ($item->getLocalCopy() === 'avatar') {
continue;
}
try {
$this->cacheRemoteDocument($item->getId());
} catch (Exception $e) {
continue;
}
$count++;
}
return $count;
}
/**
* @param Person $actor
*
* @return string
* @throws SocialAppConfigException
* @throws UrlCloudException
*/
public function cacheLocalAvatarByUsername(Person $actor): string {
$url = $this->urlGenerator->linkToRouteAbsolute(
'core.avatar.getAvatar', ['userId' => $actor->getUserId(), 'size' => 128]
);
$versionCurrent =
(int)$this->configService->getUserValue('version', $actor->getUserId(), 'avatar');
$versionCached = $actor->getAvatarVersion();
if ($versionCurrent > $versionCached) {
$icon = new Image();
$icon->setUrl($url);
$icon->setUrlcloud($this->configService->getCloudAddress());
$icon->generateUniqueId('/documents/avatar');
$icon->setMediaType('');
$icon->setLocalCopy('avatar');
$this->cacheDocumentsRequest->deleteByUrl($icon->getUrl());
$this->cacheDocumentsRequest->save($icon);
$actor->setAvatarVersion($versionCurrent);
$this->actorRequest->update($actor);
} else {
try {
$icon = $this->cacheDocumentsRequest->getBySource($url);
} catch (CacheDocumentDoesNotExistException $e) {
return '';
}
}
return $icon->getId();
}
}

Wyświetl plik

@ -0,0 +1,271 @@
<?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\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Traits\TArrayTools;
use OCA\Social\Db\FollowsRequest;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Exceptions\FollowDoesNotExistException;
use OCA\Social\Exceptions\FollowSameAccountException;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Activity\Follow;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\OrderedCollection;
use OCA\Social\Model\InstancePath;
class FollowService {
use TArrayTools;
const REQUEST_INBOX = 1;
const TIMEOUT_LIVE = 2;
const TIMEOUT_ASYNC = 5;
const TIMEOUT_SERVICE = 10;
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 FollowsRequest */
private $followsRequest;
/** @var CacheActorService */
private $cacheActorService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/** @var string */
private $viewerId = '';
/**
* FollowService constructor.
*
* @param FollowsRequest $followsRequest
* @param CacheActorService $cacheActorService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
FollowsRequest $followsRequest, CacheActorService $cacheActorService,
ConfigService $configService, MiscService $miscService
) {
$this->followsRequest = $followsRequest;
$this->cacheActorService = $cacheActorService;
$this->configService = $configService;
$this->miscService = $miscService;
}
//
/**
* @param string $viewerId
*/
public function setViewerId(string $viewerId) {
$this->viewerId = $viewerId;
$this->followsRequest->setViewerId($viewerId);
}
public function getViewerId(): string {
return $this->viewerId;
}
/**
* @param Person $actor
* @param string $account
*
* @throws CacheActorDoesNotExistException
* @throws FollowSameAccountException
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws RedundancyLimitException
* @throws Request410Exception
* @throws RequestException
* @throws SocialAppConfigException
* @throws UrlCloudException
* @throws UnknownItemException
*/
public function followAccount(Person $actor, string $account) {
$remoteActor = $this->cacheActorService->getFromAccount($account);
if ($remoteActor->getId() === $actor->getId()) {
throw new FollowSameAccountException("Don't follow yourself, be your own lead");
}
$follow = new Follow();
$follow->setUrlCloud($this->configService->getCloudAddress());
$follow->generateUniqueId();
$follow->setActorId($actor->getId());
$follow->setObjectId($remoteActor->getId());
$follow->setFollowId($remoteActor->getFollowers());
try {
$this->followsRequest->getByPersons($actor->getId(), $remoteActor->getId());
} catch (FollowDoesNotExistException $e) {
$this->followsRequest->save($follow);
// TODO - Remove this auto-accepted.
$this->followsRequest->accepted($follow);
$follow->addInstancePath(
new InstancePath(
$remoteActor->getInbox(), InstancePath::TYPE_INBOX, InstancePath::PRIORITY_TOP
)
);
// $this->activityService->request($follow);
}
}
/**
* @param Person $actor
* @param string $account
*
* @throws CacheActorDoesNotExistException
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws RedundancyLimitException
* @throws Request410Exception
* @throws RequestException
* @throws SocialAppConfigException
* @throws UnknownItemException
*/
public function unfollowAccount(Person $actor, string $account) {
$remoteActor = $this->cacheActorService->getFromAccount($account);
try {
$follow = $this->followsRequest->getByPersons($actor->getId(), $remoteActor->getId());
$this->followsRequest->delete($follow);
} catch (FollowDoesNotExistException $e) {
}
}
/**
* @param Person $local
* @param Person $actor
*
* @return array
*/
public function getLinksBetweenPersons(Person $local, Person $actor): array {
$links = [
'follower' => false,
'following' => false
];
try {
$this->followsRequest->getByPersons($local->getId(), $actor->getId());
$links['following'] = true;
} catch (FollowDoesNotExistException $e) {
}
try {
$this->followsRequest->getByPersons($actor->getId(), $local->getId());
$links['follower'] = true;
} catch (FollowDoesNotExistException $e) {
}
return $links;
}
/**
* @param Person $actor
*
* @return Person[]
*/
public function getFollowers(Person $actor): array {
return $this->followsRequest->getFollowersByActorId($actor->getId());
}
/**
* @param Person $actor
*
* @return OrderedCollection
*/
public function getFollowersCollection(Person $actor): OrderedCollection {
$collection = new OrderedCollection();
$collection->setId($actor->getFollowers());
$collection->setTotalItems(20);
$collection->setFirst('...');
return $collection;
}
/**
* @param Person $actor
*
* @return Person[]
*/
public function getFollowing(Person $actor): array {
return $this->followsRequest->getFollowingByActorId($actor->getId());
}
/**
* @param Person $actor
*
* @return OrderedCollection
*/
public function getFollowingCollection(Person $actor): OrderedCollection {
$collection = new OrderedCollection();
// $collection->setId($actor->getFollowers());
// $collection->setTotalItems(20);
// $collection->setFirst('...');
return $collection;
}
}

Wyświetl plik

@ -33,42 +33,12 @@ namespace OCA\Social\Service;
use daita\MySmallPhpTools\Traits\TArrayTools;
use Exception;
use OCA\Social\AP;
use OCA\Social\Exceptions\ActivityPubFormatException;
use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Activity\Accept;
use OCA\Social\Model\ActivityPub\Activity\Add;
use OCA\Social\Model\ActivityPub\Activity\Block;
use OCA\Social\Model\ActivityPub\Activity\Create;
use OCA\Social\Model\ActivityPub\Activity\Delete;
use OCA\Social\Model\ActivityPub\Activity\Follow;
use OCA\Social\Model\ActivityPub\Activity\Like;
use OCA\Social\Model\ActivityPub\Activity\Reject;
use OCA\Social\Model\ActivityPub\Activity\Remove;
use OCA\Social\Model\ActivityPub\Activity\Undo;
use OCA\Social\Model\ActivityPub\Activity\Update;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\ActivityPub\Object\Image;
use OCA\Social\Model\ActivityPub\Object\Note;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Tombstone;
use OCA\Social\Service\ActivityPub\Activity\AcceptService;
use OCA\Social\Service\ActivityPub\Activity\AddService;
use OCA\Social\Service\ActivityPub\Activity\BlockService;
use OCA\Social\Service\ActivityPub\Activity\CreateService;
use OCA\Social\Service\ActivityPub\Activity\DeleteService;
use OCA\Social\Service\ActivityPub\Activity\FollowService;
use OCA\Social\Service\ActivityPub\Activity\LikeService;
use OCA\Social\Service\ActivityPub\Activity\RejectService;
use OCA\Social\Service\ActivityPub\Activity\RemoveService;
use OCA\Social\Service\ActivityPub\Activity\UndoService;
use OCA\Social\Service\ActivityPub\Activity\UpdateService;
use OCA\Social\Service\ActivityPub\ICoreService;
use OCA\Social\Service\ActivityPub\Object\NoteService;
use OCA\Social\Service\ActivityPub\Actor\PersonService;
class ImportService {
@ -76,44 +46,6 @@ class ImportService {
use TArrayTools;
/** @var AcceptService */
private $acceptService;
/** @var AddService */
private $addService;
/** @var BlockService */
private $blockService;
/** @var CreateService */
private $createService;
/** @var DeleteService */
private $deleteService;
/** @var FollowService */
private $followService;
/** @var LikeService */
private $likeService;
/** @var PersonService */
private $personService;
/** @var NoteService */
private $noteService;
/** @var RejectService */
private $rejectService;
/** @var RemoveService */
private $removeService;
/** @var UndoService */
private $undoService;
/** @var UpdateService */
private $updateService;
/** @var ConfigService */
private $configService;
@ -125,43 +57,10 @@ class ImportService {
/**
* ImportService constructor.
*
* @param AcceptService $acceptService
* @param AddService $addService
* @param BlockService $blockService
* @param CreateService $createService
* @param DeleteService $deleteService
* @param FollowService $followService
* @param NoteService $noteService
* @param LikeService $likeService
* @param PersonService $personService
* @param RejectService $rejectService
* @param RemoveService $removeService
* @param UndoService $undoService
* @param UpdateService $updateService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
AcceptService $acceptService, AddService $addService, BlockService $blockService,
CreateService $createService, DeleteService $deleteService, FollowService $followService,
NoteService $noteService, LikeService $likeService, PersonService $personService,
RejectService $rejectService, RemoveService $removeService,
UndoService $undoService, UpdateService $updateService,
ConfigService $configService, MiscService $miscService
) {
$this->acceptService = $acceptService;
$this->addService = $addService;
$this->blockService = $blockService;
$this->createService = $createService;
$this->deleteService = $deleteService;
$this->followService = $followService;
$this->likeService = $likeService;
$this->rejectService = $rejectService;
$this->removeService = $removeService;
$this->personService = $personService;
$this->noteService = $noteService;
$this->undoService = $undoService;
$this->updateService = $updateService;
public function __construct(ConfigService $configService, MiscService $miscService) {
$this->configService = $configService;
$this->miscService = $miscService;
}
@ -172,118 +71,54 @@ class ImportService {
*
* @return ACore
* @throws UnknownItemException
* @throws UrlCloudException
* @throws SocialAppConfigException
* @throws ActivityPubFormatException
* @throws RedundancyLimitException
*/
public function importFromJson(string $json) {
public function importFromJson(string $json): ACore {
$data = json_decode($json, true);
if (!is_array($data)) {
throw new ActivityPubFormatException();
}
$activity = $this->importFromData($data, null);
return $activity;
return AP::$activityPub->getItemFromData($data);
}
/**
* @param array $data
* @param ACore $root
*
* @return ACore
* @throws UnknownItemException
* @throws UrlCloudException
* @throws SocialAppConfigException
* @throws InvalidResourceEntryException
*/
private function importFromData(array $data, $root = null): ACore {
// TODO - missing : Person (why not ?), OrderCollection (not yet), Document (should ?)
switch ($this->get('type', $data, '')) {
case Accept::TYPE:
$item = new Accept($root);
break;
case Add::TYPE:
$item = new Add($root);
break;
case Block::TYPE:
$item = new Block($root);
break;
case Create::TYPE:
$item = new Create($root);
break;
case Delete::TYPE:
$item = new Delete($root);
break;
case Follow::TYPE:
$item = new Follow($root);
break;
case Image::TYPE:
$item = new Image($root);
break;
case Like::TYPE:
$item = new Like($root);
break;
case Note::TYPE:
$item = new Note($root);
break;
case Person::TYPE:
$item = new Note($root);
break;
case Reject::TYPE:
$item = new Reject($root);
break;
case Remove::TYPE:
$item = new Remove($root);
break;
case Tombstone::TYPE:
$item = new Tombstone($root);
break;
case Undo::TYPE:
$item = new Undo($root);
break;
case Update::TYPE:
$item = new Update($root);
break;
default:
throw new UnknownItemException();
}
$item->setUrlCloud($this->configService->getCloudAddress());
$item->import($data);
$item->setSource(json_encode($data, JSON_UNESCAPED_SLASHES));
try {
$object = $this->importFromData($this->getArray('object', $data, []), $item);
$item->setObject($object);
} catch (UnknownItemException $e) {
}
try {
/** @var Document $icon */
$icon = $this->importFromData($this->getArray('icon', $data, []), $item);
$item->setIcon($icon);
} catch (UnknownItemException $e) {
}
return $item;
}
//
// /**
// * @param array $data
// * @param ACore $root
// *
// * @return ACore
// * @throws UnknownItemException
// * @throws UrlCloudException
// * @throws SocialAppConfigException
// * @throws InvalidResourceEntryException
// */
// private function importFromData(array $data, $root = null): ACore {
//
// $item = AP::$activityPub->getItemFromData($data);
// $item->setParent($root);
//
// $item->setUrlCloud($this->configService->getCloudAddress());
// $item->setSource(json_encode($data, JSON_UNESCAPED_SLASHES));
//
// try {
// $object = $this->importFromData($this->getArray('object', $data, []), $item);
// $item->setObject($object);
// } catch (UnknownItemException $e) {
// }
//
// try {
// /** @var Document $icon */
// $icon = $this->importFromData($this->getArray('icon', $data, []), $item);
// $item->setIcon($icon);
// } catch (UnknownItemException $e) {
// }
//
// return $item;
// }
/**
@ -292,19 +127,10 @@ class ImportService {
* @throws UnknownItemException
*/
public function parseIncomingRequest(ACore $activity) {
// not sure we need to recursive on activity/parsing.
// if ($activity->gotObject()) {
// try {
// $this->parseIncomingRequest($activity->getObject());
// } catch (UnknownItemException $e) {
// }
// }
$service = $this->getServiceForItem($activity);
$interface = AP::$activityPub->getInterfaceForItem($activity);
try {
$service->processIncomingRequest($activity, $this);
$interface->processIncomingRequest($activity);
} catch (Exception $e) {
$this->miscService->log(
'Cannot parse ' . $activity->getType() . ': ' . $e->getMessage()
@ -313,74 +139,5 @@ class ImportService {
}
/**
* @param ACore $activity
*
* @return ICoreService
* @throws UnknownItemException
*/
public function getServiceForItem(Acore $activity): ICoreService {
switch ($activity->getType()) {
case Accept::TYPE:
$service = $this->acceptService;
break;
case Add::TYPE:
$service = $this->addService;
break;
case Block::TYPE:
$service = $this->blockService;
break;
case Create::TYPE:
$service = $this->createService;
break;
case Delete::TYPE:
$service = $this->deleteService;
break;
case Follow::TYPE:
$service = $this->followService;
break;
case Like::TYPE:
$service = $this->likeService;
break;
case Note::TYPE:
$service = $this->noteService;
break;
case Person::TYPE:
$service = $this->personService;
break;
case Reject::TYPE:
$service = $this->rejectService;
break;
case Remove::TYPE:
$service = $this->removeService;
break;
case Undo::TYPE:
$service = $this->undoService;
break;
case Update::TYPE:
$service = $this->updateService;
break;
default:
throw new UnknownItemException();
}
return $service;
}
}

Wyświetl plik

@ -1,203 +0,0 @@
<?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\MySmallPhpTools\Exceptions\ArrayNotFoundException;
use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\TArrayTools;
use daita\MySmallPhpTools\Traits\TPathTools;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\Instance;
use OCA\Social\Model\InstancePath;
class InstanceService {
use TPathTools;
use TArrayTools;
/** @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 string $account
*
* @return mixed
* @throws RequestException
* @throws InvalidResourceException
* @throws Request410Exception
* @throws MalformedArrayException
*/
public function retrieveAccount(string $account) {
$account = $this->withoutBeginAt($account);
if (strstr(substr($account, 0, -3), '@') === false) {
throw new InvalidResourceException();
}
list($username, $host) = explode('@', $account);
// if ($username === null || $host === null) {
// throw new InvalidResourceException();
// }
$request = new Request('/.well-known/webfinger');
$request->addData('resource', 'acct:' . $account);
$request->setAddress($host);
$result = $this->curlService->request($request);
try {
$link = $this->extractArray('rel', 'self', $this->getArray('links', $result));
} catch (ArrayNotFoundException $e) {
throw new RequestException();
}
return $this->retrieveObject($this->get('href', $link, ''));
}
/**
* @param $id
*
* @return mixed
* @throws RequestException
* @throws Request410Exception
* @throws MalformedArrayException
*/
public function retrieveObject($id) {
$url = parse_url($id);
$this->mustContains(['path', 'host'], $url);
$request = new Request($url['path'], Request::TYPE_GET);
$request->setAddress($url['host']);
$result = $this->curlService->request($request);
if (is_array($result)) {
$result['_host'] = $url['host'];
}
return $result;
}
/**
* @param ACore $activity
*
* @return Instance[]
*/
public function getInstancesFromActivity(ACore $activity): array {
$instances = [];
foreach ($activity->getInstancePaths() as $instancePath) {
$this->addInstances($instancePath, $instances);
}
return $instances;
}
/**
* @param InstancePath $instancePath
* @param Instance[] $instances
*/
private function addInstances(InstancePath $instancePath, array &$instances) {
$address = $this->getHostFromUriId($instancePath->getUri());
if ($address === '') {
return;
}
foreach ($instances as $instance) {
if ($instance->getAddress() === $address) {
$instance->addPath($instancePath);
return;
}
}
$instance = new Instance($address);
$instance->addPath($instancePath);
$instances[] = $instance;
}
/**
* @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'];
}
}

Wyświetl plik

@ -0,0 +1,356 @@
<?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 Exception;
use OC\User\NoUserException;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\AccountAlreadyExistsException;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\NoteNotFoundException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Note;
use OCA\Social\Model\InstancePath;
class NoteService {
/** @var NotesRequest */
private $notesRequest;
/** @var ActivityService */
private $activityService;
/** @var AccountService */
private $accountService;
/** @var CacheActorService */
private $cacheActorService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/** @var string */
private $viewerId = '';
/**
* NoteService constructor.
*
* @param NotesRequest $notesRequest
* @param ActivityService $activityService
* @param AccountService $accountService
* @param CacheActorService $cacheActorService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
NotesRequest $notesRequest,
ActivityService $activityService,
AccountService $accountService,
CacheActorService $cacheActorService,
ConfigService $configService,
MiscService $miscService
) {
$this->notesRequest = $notesRequest;
$this->activityService = $activityService;
$this->accountService = $accountService;
$this->cacheActorService = $cacheActorService;
$this->configService = $configService;
$this->miscService = $miscService;
}
/**
* @param string $viewerId
*/
public function setViewerId(string $viewerId) {
$this->viewerId = $viewerId;
$this->notesRequest->setViewerId($viewerId);
}
public function getViewerId(): string {
return $this->viewerId;
}
/**
* @param string $userId
* @param string $content
*
* @param string $type
*
* @return Note
* @throws ActorDoesNotExistException
* @throws NoUserException
* @throws SocialAppConfigException
* @throws AccountAlreadyExistsException
* @throws UrlCloudException
*/
public function generateNote(string $userId, string $content, string $type) {
$note = new Note();
$actor = $this->accountService->getActorFromUserId($userId);
$note->setId($this->configService->generateId('@' . $actor->getPreferredUsername()));
$note->setPublished(date("c"));
$note->setAttributedTo(
$this->configService->getUrlSocial() . '@' . $actor->getPreferredUsername()
);
$this->setRecipient($note, $actor, $type);
$note->setContent($content);
$note->convertPublished();
$note->setLocal(true);
return $note;
}
/**
* @param Note $note
* @param Person $actor
* @param string $type
*/
private function setRecipient(Note $note, Person $actor, string $type) {
switch ($type) {
case Note::TYPE_UNLISTED:
$note->setTo($actor->getFollowers());
$note->addInstancePath(
new InstancePath(
$actor->getFollowers(), InstancePath::TYPE_FOLLOWERS,
InstancePath::PRIORITY_LOW
)
);
$note->addCc(ActivityService::TO_PUBLIC);
break;
case Note::TYPE_FOLLOWERS:
$note->setTo($actor->getFollowers());
$note->addInstancePath(
new InstancePath(
$actor->getFollowers(), InstancePath::TYPE_FOLLOWERS,
InstancePath::PRIORITY_LOW
)
);
break;
case Note::TYPE_DIRECT:
break;
default:
$note->setTo(ActivityService::TO_PUBLIC);
$note->addCc($actor->getFollowers());
$note->addInstancePath(
new InstancePath(
$actor->getFollowers(), InstancePath::TYPE_FOLLOWERS,
InstancePath::PRIORITY_LOW
)
);
break;
}
}
/**
* @param Note $note
* @param string $type
* @param string $account
*/
public function addRecipient(Note $note, string $type, string $account) {
if ($account === '') {
return;
}
try {
$actor = $this->cacheActorService->getFromAccount($account);
} catch (Exception $e) {
return;
}
$instancePath = new InstancePath(
$actor->getInbox(), InstancePath::TYPE_INBOX, InstancePath::PRIORITY_MEDIUM
);
if ($type === Note::TYPE_DIRECT) {
$instancePath->setPriority(InstancePath::PRIORITY_HIGH);
$note->addToArray($actor->getId());
} else {
$note->addCc($actor->getId());
}
$note->addTag(
[
'type' => 'Mention',
'href' => $actor->getId()
]
);
$note->addInstancePath($instancePath);
}
/**
* @param Note $note
* @param string $type
* @param array $accounts
*/
public function addRecipients(Note $note, string $type, array $accounts) {
if ($accounts === []) {
return;
}
foreach ($accounts as $account) {
$this->addRecipient($note, $type, $account);
}
}
/**
* @param Note $note
* @param string $replyTo
*/
public function replyTo(Note $note, string $replyTo) {
if ($replyTo === '') {
return;
}
$note->setInReplyTo($replyTo);
// TODO - type can be NOT public !
$note->addInstancePath(
new InstancePath($replyTo, InstancePath::TYPE_PUBLIC, InstancePath::PRIORITY_HIGH)
);
}
/**
* @param Note $note
*
* @throws Exception
*/
public function deleteLocalNote(Note $note) {
if (!$note->isLocal()) {
return;
}
$note->setActorId($note->getAttributedTo());
$this->activityService->deleteActivity($note);
$this->notesRequest->deleteNoteById($note->getId());
}
/**
* @param string $id
*
* @return Note
* @throws NoteNotFoundException
*/
public function getNoteById(string $id): Note {
return $this->notesRequest->getNoteById($id);
}
/**
* @param Person $actor
* @param int $since
* @param int $limit
*
* @return Note[]
*/
public function getStreamHome(Person $actor, int $since = 0, int $limit = 5): array {
return $this->notesRequest->getStreamHome($actor, $since, $limit);
}
/**
* @param string $actorId
* @param int $since
* @param int $limit
*
* @return Note[]
*/
public function getStreamAccount(string $actorId, int $since = 0, int $limit = 5): array {
return $this->notesRequest->getStreamAccount($actorId, $since, $limit);
}
/**
* @param Person $actor
* @param int $since
* @param int $limit
*
* @return Note[]
*/
public function getStreamDirect(Person $actor, int $since = 0, int $limit = 5): array {
return $this->notesRequest->getStreamDirect($actor, $since, $limit);
}
/**
* @param int $since
* @param int $limit
*
* @return Note[]
*/
public function getStreamLocalTimeline(int $since = 0, int $limit = 5): array {
return $this->notesRequest->getStreamTimeline($since, $limit, true);
}
/**
* @param int $since
* @param int $limit
*
* @return Note[]
*/
public function getStreamInternalTimeline(int $since = 0, int $limit = 5): array {
// TODO - admin should be able to provide a list of 'friendly/internal' instance of ActivityPub
return [];
}
/**
* @param int $since
* @param int $limit
*
* @return Note[]
*/
public function getStreamGlobalTimeline(int $since = 0, int $limit = 5): array {
return $this->notesRequest->getStreamTimeline($since, $limit, false);
}
}

Wyświetl plik

@ -36,7 +36,6 @@ use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\Post;
use OCA\Social\Service\ActivityPub\Object\NoteService;
class PostService {
@ -44,7 +43,7 @@ class PostService {
/** @var NoteService */
private $noteService;
/** @var ActorService */
/** @var AccountService */
private $actorService;
/** @var ActivityService */
@ -58,12 +57,12 @@ class PostService {
* PostService constructor.
*
* @param NoteService $noteService
* @param ActorService $actorService
* @param AccountService $actorService
* @param ActivityService $activityService
* @param MiscService $miscService
*/
public function __construct(
NoteService $noteService, ActorService $actorService, ActivityService $activityService,
NoteService $noteService, AccountService $actorService, ActivityService $activityService,
MiscService $miscService
) {
$this->noteService = $noteService;

Wyświetl plik

@ -0,0 +1,266 @@
<?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\MySmallPhpTools\Exceptions\MalformedArrayException;
use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime;
use Exception;
use OCA\Social\Exceptions\InvalidOriginException;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\Request410Exception;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SignatureException;
use OCA\Social\Exceptions\SignatureIsGoneException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCP\IRequest;
class SignatureService {
use TArrayTools;
const DATE_FORMAT = 'D, d M Y H:i:s T';
const DATE_DELAY = 30;
/** @var CacheActorService */
private $cacheActorService;
/** @var CurlService */
private $curlService;
/** @var ConfigService */
private $configService;
/** @var MiscService */
private $miscService;
/**
* ActivityService constructor.
*
* @param AccountService $accountService
* @param CacheActorService $cacheActorService
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
CacheActorService $cacheActorService, CurlService $curlService,
ConfigService $configService, MiscService $miscService
) {
$this->cacheActorService = $cacheActorService;
$this->curlService = $curlService;
$this->configService = $configService;
$this->miscService = $miscService;
}
/**
* @param Person $actor
*/
public function generateKeys(Person &$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);
}
/**
* @param IRequest $request
*
* @return string
* @throws InvalidOriginException
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws RedundancyLimitException
* @throws RequestException
* @throws SignatureException
* @throws SignatureIsGoneException
* @throws SocialAppConfigException
* @throws UnknownItemException
*/
public function checkRequest(IRequest $request): string {
$dTime = new DateTime($request->getHeader('date'));
$dTime->format(self::DATE_FORMAT);
if ($dTime->getTimestamp() < (time() - self::DATE_DELAY)) {
throw new SignatureException('object is too old');
}
try {
$origin = $this->checkRequestSignature($request);
} catch (Request410Exception $e) {
throw new SignatureIsGoneException();
}
return $origin;
}
/**
* @param IRequest $request
*
* @return string
* @throws InvalidOriginException
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws RedundancyLimitException
* @throws Request410Exception
* @throws RequestException
* @throws SignatureException
* @throws SocialAppConfigException
* @throws UnknownItemException
*/
private function checkRequestSignature(IRequest $request): string {
$signatureHeader = $request->getHeader('Signature');
$sign = $this->parseSignatureHeader($signatureHeader);
$this->mustContains(['keyId', 'headers', 'signature'], $sign);
$keyId = $sign['keyId'];
$origin = $this->getKeyOrigin($keyId);
$headers = $sign['headers'];
$signed = base64_decode($sign['signature']);
$estimated = $this->generateEstimatedSignature($headers, $request);
$publicKey = $this->retrieveKey($keyId);
if ($publicKey === '' || openssl_verify($estimated, $signed, $publicKey, 'sha256') !== 1) {
throw new SignatureException('signature cannot be checked');
}
return $origin;
}
/**
* @param string $headers
* @param IRequest $request
*
* @return string
*/
private function generateEstimatedSignature(string $headers, IRequest $request): string {
$keys = explode(' ', $headers);
$target = '';
try {
$target = strtolower($request->getMethod()) . " " . $request->getRequestUri();
} catch (Exception $e) {
}
$estimated = "(request-target): " . $target;
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 string
* @throws InvalidResourceException
* @throws MalformedArrayException
* @throws Request410Exception
* @throws RequestException
* @throws SocialAppConfigException
* @throws UnknownItemException
* @throws RedundancyLimitException
*/
private function retrieveKey($keyId): string {
$actor = $this->cacheActorService->getFromId($keyId);
return $actor->getPublicKey();
}
/**
* @param $id
*
* @return string
* @throws InvalidOriginException
*/
private function getKeyOrigin($id) {
$host = parse_url($id, PHP_URL_HOST);
if (is_string($host) && ($host !== '')) {
return $host;
}
throw new InvalidOriginException();
}
}