diff --git a/.drone.yml b/.drone.yml
index 334b38f2..6f6ec4a8 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -4,6 +4,71 @@ clone:
depth: 1
pipeline:
+ check-app-compatbility:
+ image: nextcloudci/php7.0:php7.0-17
+ environment:
+ - APP_NAME=social
+ - CORE_BRANCH=stable15
+ - DB=sqlite
+ commands:
+ # Pre-setup steps
+ - wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
+ - bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
+ - cd ../server
+ # Code checker
+ - ./occ app:check-code $APP_NAME -c strong-comparison
+ - ./occ app:check-code $APP_NAME -c deprecation
+ when:
+ matrix:
+ TESTS: check-app-compatbility
+ syntax-php7.0:
+ image: nextcloudci/php7.0:php7.0-17
+ environment:
+ - APP_NAME=social
+ - CORE_BRANCH=stable15
+ - DB=sqlite
+ commands:
+ - composer install
+ - ./vendor/bin/parallel-lint --exclude ./vendor/ .
+ when:
+ matrix:
+ TESTS: syntax-php7.0
+ syntax-php7.1:
+ image: nextcloudci/php7.1:php7.1-15
+ environment:
+ - APP_NAME=social
+ - CORE_BRANCH=stable15
+ - DB=sqlite
+ commands:
+ - composer install
+ - ./vendor/bin/parallel-lint --exclude ./vendor/ .
+ when:
+ matrix:
+ TESTS: syntax-php7.1
+ syntax-php7.2:
+ image: nextcloudci/php7.2:php7.2-9
+ environment:
+ - APP_NAME=social
+ - CORE_BRANCH=stable15
+ - DB=sqlite
+ commands:
+ - composer install
+ - ./vendor/bin/parallel-lint --exclude ./vendor/ .
+ when:
+ matrix:
+ TESTS: syntax-php7.2
+ syntax-php7.3:
+ image: nextcloudci/php7.3:php7.3-2
+ environment:
+ - APP_NAME=social
+ - CORE_BRANCH=stable15
+ - DB=sqlite
+ commands:
+ - composer install
+ - ./vendor/bin/parallel-lint --exclude ./vendor/ .
+ when:
+ matrix:
+ TESTS: syntax-php7.3
eslint:
image: nextcloudci/jsunit:jsunit-5
commands:
@@ -12,7 +77,6 @@ pipeline:
when:
matrix:
TESTS: eslint
-
vue-build:
image: nextcloudci/jsunit:jsunit-5
commands:
@@ -20,10 +84,15 @@ pipeline:
- npm run build
when:
matrix:
- TESTS:vue-build
+ TESTS: vue-build
matrix:
include:
+ - TESTS: check-app-compatbility
+ - TESTS: syntax-php7.0
+ - TESTS: syntax-php7.1
+ - TESTS: syntax-php7.2
+ - TESTS: syntax-php7.3
- TESTS: eslint
- TESTS: vue-build
diff --git a/appinfo/info.xml b/appinfo/info.xml
index f8d819ed..6520f085 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -26,25 +26,24 @@
Social
social
https://github.com/nextcloud/social
- https://github.com/nextcloud/social.git
https://github.com/nextcloud/social/issues
+ https://github.com/nextcloud/social.git
https://raw.githubusercontent.com/nextcloud/social/master/img/screenshot.png
-
-
- Social
- social.Navigation.navigate
- 6
-
-
OCA\Social\Cron\Cache
OCA\Social\Cron\Queue
+
+
+ OCA\Social\Migration\CheckInstallation
+
+
+
OCA\Social\Command\CacheRefresh
OCA\Social\Command\NoteCreate
@@ -52,4 +51,11 @@
OCA\Social\Command\QueueProcess
+
+
+ Social
+ social.Navigation.navigate
+ 6
+
+
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 6a595a4e..506a89aa 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -65,6 +65,7 @@ return [
['name' => 'SocialPub#displayPost', 'url' => '/@{username}/{postId}', 'verb' => 'GET'],
['name' => 'Local#streamHome', 'url' => '/api/v1/stream/home', 'verb' => 'GET'],
+ ['name' => 'Local#streamNotifications', 'url' => '/api/v1/stream/notifications', 'verb' => 'GET'],
['name' => 'Local#streamTimeline', 'url' => '/api/v1/stream/timeline', 'verb' => 'GET'],
['name' => 'Local#streamFederated', 'url' => '/api/v1/stream/federated', 'verb' => 'GET'],
['name' => 'Local#streamDirect', 'url' => '/api/v1/stream/direct', 'verb' => 'GET'],
diff --git a/composer.json b/composer.json
index 3bf0a3c8..e0b5708d 100644
--- a/composer.json
+++ b/composer.json
@@ -10,6 +10,10 @@
}
],
"require": {
- "daita/my-small-php-tools": "dev-master"
+ "daita/my-small-php-tools": "dev-master",
+ "digitalbazaar/json-ld": "0.4.7"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "^1.0"
}
}
diff --git a/composer.lock b/composer.lock
index 9b755307..81e358ae 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,10 +1,10 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "02220c2a6087d409a5e53060ee20c47e",
+ "content-hash": "2c21b8c338f3d2f929f349df19edbc0e",
"packages": [
{
"name": "daita/my-small-php-tools",
@@ -12,12 +12,12 @@
"source": {
"type": "git",
"url": "https://github.com/daita/my-small-php-tools.git",
- "reference": "7a61e966ac2a01db6fd0096f77620a7db978af18"
+ "reference": "29754f18951856a22c0fd5fc388b6162ea98fe8a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/7a61e966ac2a01db6fd0096f77620a7db978af18",
- "reference": "7a61e966ac2a01db6fd0096f77620a7db978af18",
+ "url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/29754f18951856a22c0fd5fc388b6162ea98fe8a",
+ "reference": "29754f18951856a22c0fd5fc388b6162ea98fe8a",
"shasum": ""
},
"require": {
@@ -40,10 +40,105 @@
}
],
"description": "My small PHP Tools",
- "time": "2018-12-04T10:09:31+00:00"
+ "time": "2018-12-18T00:38:01+00:00"
+ },
+ {
+ "name": "digitalbazaar/json-ld",
+ "version": "0.4.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/digitalbazaar/php-json-ld.git",
+ "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/digitalbazaar/php-json-ld/zipball/dc1bd23f0ee2efd27ccf636d32d2738dabcee182",
+ "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "jsonld.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Digital Bazaar, Inc.",
+ "email": "support@digitalbazaar.com"
+ }
+ ],
+ "description": "A JSON-LD Processor and API implementation in PHP.",
+ "homepage": "https://github.com/digitalbazaar/php-json-ld",
+ "keywords": [
+ "JSON-LD",
+ "Linked Data",
+ "RDF",
+ "Semantic Web",
+ "json",
+ "jsonld"
+ ],
+ "time": "2016-04-25T04:17:52+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "jakub-onderka/php-parallel-lint",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
+ "reference": "04fbd3f5fb1c83f08724aa58a23db90bd9086ee8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/04fbd3f5fb1c83f08724aa58a23db90bd9086ee8",
+ "reference": "04fbd3f5fb1c83f08724aa58a23db90bd9086ee8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "jakub-onderka/php-console-highlighter": "~0.3",
+ "nette/tester": "~1.3",
+ "squizlabs/php_codesniffer": "~2.7"
+ },
+ "suggest": {
+ "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
+ },
+ "bin": [
+ "parallel-lint"
+ ],
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "./"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jakub Onderka",
+ "email": "ahoj@jakubonderka.cz"
+ }
+ ],
+ "description": "This tool check syntax of PHP files about 20x faster than serial check.",
+ "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
+ "time": "2018-02-24T15:31:20+00:00"
}
],
- "packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php
index e4d51fa9..4d4c119b 100644
--- a/lib/Controller/AccountController.php
+++ b/lib/Controller/AccountController.php
@@ -126,8 +126,6 @@ class AccountController extends Controller {
*
* @PublicPage
* @NoCSRFRequired
- * @NoAdminRequired
- * @NoSubAdminRequired
*
* @param string $username
*
diff --git a/lib/Controller/ActivityPubController.php b/lib/Controller/ActivityPubController.php
index 1a87c56e..a01cf951 100644
--- a/lib/Controller/ActivityPubController.php
+++ b/lib/Controller/ActivityPubController.php
@@ -34,8 +34,21 @@ 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\ActivityPubFormatException;
+use OCA\Social\Exceptions\InvalidResourceEntryException;
+use OCA\Social\Exceptions\InvalidResourceException;
+use OCA\Social\Exceptions\Request410Exception;
+use OCA\Social\Exceptions\RequestException;
use OCA\Social\Exceptions\SignatureIsGoneException;
+use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
+use OCA\Social\Exceptions\UrlCloudException;
+use OCA\Social\Model\ActivityPub\ACore;
+use OCA\Social\Service\ActivityPub\FollowService;
+use OCA\Social\Service\ActivityPub\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;
@@ -166,7 +179,9 @@ class ActivityPubController extends Controller {
$origin = $this->signatureService->checkRequest($this->request);
$activity = $this->importService->importFromJson($body);
- $activity->setOrigin($origin);
+ if (!$this->activityService->checkObject($activity)) {
+ $activity->setOrigin($origin);
+ }
try {
$this->importService->parseIncomingRequest($activity);
@@ -205,7 +220,10 @@ class ActivityPubController extends Controller {
// $actor = $this->actorService->getActor($username);
$activity = $this->importService->importFromJson($body);
- $activity->setOrigin($origin);
+ if (!$this->activityService->checkObject($activity)) {
+ $activity->setOrigin($origin);
+ }
+
try {
$this->importService->parseIncomingRequest($activity);
} catch (UnknownItemException $e) {
diff --git a/lib/Controller/LocalController.php b/lib/Controller/LocalController.php
index 89d0fed3..6ab4994f 100644
--- a/lib/Controller/LocalController.php
+++ b/lib/Controller/LocalController.php
@@ -163,11 +163,8 @@ class LocalController extends Controller {
/**
- * Create a new post.
+ * Delete your own post.
*
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -193,9 +190,6 @@ class LocalController extends Controller {
/**
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -216,10 +210,32 @@ class LocalController extends Controller {
}
+
+
/**
- * // TODO: Delete the NoCSRF check
- *
* @NoCSRFRequired
+ * @NoAdminRequired
+ * @NoSubAdminRequired
+ *
+ * @param int $since
+ * @param int $limit
+ *
+ * @return DataResponse
+ */
+ public function streamNotifications($since = 0, int $limit = 5): DataResponse {
+ try {
+ $this->initViewer(true);
+ $posts = $this->noteService->getStreamNotifications($this->viewer, $since, $limit);
+
+ return $this->success($posts);
+ } catch (Exception $e) {
+ return $this->fail($e);
+ }
+ }
+
+
+
+ /**
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -244,9 +260,6 @@ class LocalController extends Controller {
/**
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -270,9 +283,6 @@ class LocalController extends Controller {
/**
* Get timeline
*
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -294,9 +304,6 @@ class LocalController extends Controller {
/**
* Get timeline
*
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -317,10 +324,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -341,10 +344,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -365,10 +364,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -387,7 +382,6 @@ class LocalController extends Controller {
/**
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -408,7 +402,6 @@ class LocalController extends Controller {
/**
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -429,10 +422,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -454,7 +443,6 @@ class LocalController extends Controller {
/**
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -477,7 +465,6 @@ class LocalController extends Controller {
/**
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -501,10 +488,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -526,10 +509,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -549,7 +528,6 @@ class LocalController extends Controller {
}
/**
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -578,10 +556,6 @@ class LocalController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -620,9 +594,6 @@ class LocalController extends Controller {
/**
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
diff --git a/lib/Controller/NavigationController.php b/lib/Controller/NavigationController.php
index fa19d0f9..a6d55ed9 100644
--- a/lib/Controller/NavigationController.php
+++ b/lib/Controller/NavigationController.php
@@ -147,6 +147,7 @@ class NavigationController extends Controller {
try {
$data['serverData']['cloudAddress'] = $this->configService->getCloudAddress();
} catch (SocialAppConfigException $e) {
+ $this->checkService->checkInstallationStatus();
$cloudAddress = $this->setupCloudAddress();
if ($cloudAddress !== '') {
$data['serverData']['cloudAddress'] = $cloudAddress;
@@ -221,8 +222,6 @@ class NavigationController extends Controller {
*
* @NoCSRFRequired
* @PublicPage
- * @NoAdminRequired
- * @NoSubAdminRequired
*
* @return DataResponse
*/
@@ -278,10 +277,6 @@ class NavigationController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
- * @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*
@@ -302,13 +297,8 @@ class NavigationController extends Controller {
/**
- *
- * // TODO: Delete the NoCSRF check
- *
* @PublicPage
* @NoCSRFRequired
- * @NoAdminRequired
- * @NoSubAdminRequired
*
* @param string $id
*
diff --git a/lib/Controller/QueueController.php b/lib/Controller/QueueController.php
index c9de7c32..dfdde52b 100644
--- a/lib/Controller/QueueController.php
+++ b/lib/Controller/QueueController.php
@@ -86,12 +86,8 @@ class QueueController extends Controller {
/**
- * // TODO: Delete the NoCSRF check
- *
* @PublicPage
* @NoCSRFRequired
- * @NoAdminRequired
- * @NoSubAdminRequired
*
* @param string $token
*/
diff --git a/lib/Db/FollowsRequest.php b/lib/Db/FollowsRequest.php
index eb8789ed..7cec6859 100644
--- a/lib/Db/FollowsRequest.php
+++ b/lib/Db/FollowsRequest.php
@@ -143,6 +143,20 @@ class FollowsRequest extends FollowsRequestBuilder {
}
+ /**
+ * @return int
+ */
+ public function countFollows() {
+ $qb = $this->countFollowsSelectSql();
+
+ $cursor = $qb->execute();
+ $data = $cursor->fetch();
+ $cursor->closeCursor();
+
+ return $this->getInt('count', $data, 0);
+ }
+
+
/**
* @param string $followId
*
diff --git a/lib/Db/NotesRequest.php b/lib/Db/NotesRequest.php
index fa2f77b2..cbc825fa 100644
--- a/lib/Db/NotesRequest.php
+++ b/lib/Db/NotesRequest.php
@@ -133,7 +133,7 @@ class NotesRequest extends NotesRequestBuilder {
$cursor->closeCursor();
if ($data === false) {
- throw new NoteNotFoundException();
+ throw new NoteNotFoundException('Post not found');
}
return $this->parseNotesSelectSql($data);
@@ -186,10 +186,42 @@ class NotesRequest extends NotesRequestBuilder {
}
+ /**
+ * Should returns:
+ * * Public/Unlisted/Followers-only post where current $actor is tagged,
+ * - Events: (not yet)
+ * - people liking or re-posting your posts (not yet)
+ * - someone wants to follow you (not yet)
+ * - someone is following you (not yet)
+ *
+ * @param Person $actor
+ * @param int $since
+ * @param int $limit
+ *
+ * @return array
+ */
+ public function getStreamNotifications(Person $actor, int $since = 0, int $limit = 5): array {
+ $qb = $this->getNotesSelectSql();
+
+ $this->limitPaginate($qb, $since, $limit);
+ $this->limitToRecipient($qb, $actor->getId(), false);
+ $this->leftJoinCacheActors($qb, 'attributed_to');
+
+ $notes = [];
+ $cursor = $qb->execute();
+ while ($data = $cursor->fetch()) {
+ $notes[] = $this->parseNotesSelectSql($data);
+ }
+ $cursor->closeCursor();
+
+ return $notes;
+ }
+
+
/**
* Should returns:
* * public message from actorId.
- * - to followers-only if follower is logged.
+ * - to followers-only if follower is logged. (not yet (check ?))
*
* @param string $actorId
* @param int $since
@@ -218,7 +250,7 @@ class NotesRequest extends NotesRequestBuilder {
/**
* Should returns:
* * Private message.
- * - group messages.
+ * - group messages. (not yet)
*
* @param Person $actor
* @param int $since
@@ -249,7 +281,7 @@ class NotesRequest extends NotesRequestBuilder {
/**
* Should returns:
- * - All local public/federated posts
+ * * All local public/federated posts
*
* @param int $since
* @param int $limit
@@ -266,7 +298,7 @@ class NotesRequest extends NotesRequestBuilder {
}
$this->leftJoinCacheActors($qb, 'attributed_to');
// TODO: to: = real public, cc: = unlisted !?
- $this->limitToRecipient($qb, ActivityService::TO_PUBLIC);
+ $this->limitToRecipient($qb, ActivityService::TO_PUBLIC, true, ['to']);
$notes = [];
$cursor = $qb->execute();
diff --git a/lib/Db/NotesRequestBuilder.php b/lib/Db/NotesRequestBuilder.php
index 4adaf37a..443deb8e 100644
--- a/lib/Db/NotesRequestBuilder.php
+++ b/lib/Db/NotesRequestBuilder.php
@@ -138,7 +138,7 @@ class NotesRequestBuilder extends CoreRequestBuilder {
$pf = $this->defaultSelectAlias . '.';
$on = $expr->orX();
- $on->add($this->exprLimitToRecipient($qb, $actor->getFollowers(), true));
+ $on->add($this->exprLimitToRecipient($qb, $actor->getFollowers(), false));
// list of possible recipient as a follower (to, to_array, cc, ...)
$recipientFields = $expr->orX();
@@ -230,11 +230,12 @@ class NotesRequestBuilder extends CoreRequestBuilder {
* @param IQueryBuilder $qb
* @param string $recipient
* @param bool $asAuthor
+ * @param array $type
*/
protected function limitToRecipient(
- IQueryBuilder &$qb, string $recipient, bool $asAuthor = false
+ IQueryBuilder &$qb, string $recipient, bool $asAuthor = false, array $type = []
) {
- $qb->andWhere($this->exprLimitToRecipient($qb, $recipient, $asAuthor));
+ $qb->andWhere($this->exprLimitToRecipient($qb, $recipient, $asAuthor, $type));
}
@@ -242,11 +243,12 @@ class NotesRequestBuilder extends CoreRequestBuilder {
* @param IQueryBuilder $qb
* @param string $recipient
* @param bool $asAuthor
+ * @param array $type
*
* @return ICompositeExpression
*/
protected function exprLimitToRecipient(
- IQueryBuilder &$qb, string $recipient, bool $asAuthor = false
+ IQueryBuilder &$qb, string $recipient, bool $asAuthor = false, array $type = []
): ICompositeExpression {
$expr = $qb->expr();
@@ -262,15 +264,42 @@ class NotesRequestBuilder extends CoreRequestBuilder {
);
}
- $limit->add($expr->eq('to', $qb->createNamedParameter($recipient)));
- $limit->add($this->exprValueWithinJsonFormat($qb, 'to_array', $recipient));
- $limit->add($this->exprValueWithinJsonFormat($qb, 'cc', $recipient));
- $limit->add($this->exprValueWithinJsonFormat($qb, 'bcc', $recipient));
+ if ($type === []) {
+ $type = ['to', 'cc', 'bcc'];
+ }
+
+ $this->addLimitToRecipient($qb, $limit, $type, $recipient);
return $limit;
}
+ /**
+ * @param IQueryBuilder $qb
+ * @param ICompositeExpression $limit
+ * @param array $type
+ * @param string $to
+ */
+ private function addLimitToRecipient(
+ IQueryBuilder $qb, ICompositeExpression &$limit, array $type, string $to
+ ) {
+
+ $expr = $qb->expr();
+ if (in_array('to', $type)) {
+ $limit->add($expr->eq('to', $qb->createNamedParameter($to)));
+ $limit->add($this->exprValueWithinJsonFormat($qb, 'to_array', $to));
+ }
+
+ if (in_array('cc', $type)) {
+ $limit->add($this->exprValueWithinJsonFormat($qb, 'cc', $to));
+ }
+
+ if (in_array('bcc', $type)) {
+ $limit->add($this->exprValueWithinJsonFormat($qb, 'bcc', $to));
+ }
+ }
+
+
/**
* @param IQueryBuilder $qb
* @param string $recipient
diff --git a/lib/Exceptions/LinkedDataSignatureMissingException.php b/lib/Exceptions/LinkedDataSignatureMissingException.php
new file mode 100644
index 00000000..f49db7b6
--- /dev/null
+++ b/lib/Exceptions/LinkedDataSignatureMissingException.php
@@ -0,0 +1,8 @@
+
+ * @copyright 2018, Maxence Lange
+ * @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 .
+ *
+ */
+
+
+namespace OCA\Social\Migration;
+
+
+use OCA\Social\Service\CheckService;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+
+/**
+ * Class CheckInstallation
+ *
+ * @package OCA\Social\Migration
+ */
+class CheckInstallation implements IRepairStep {
+
+
+ /** @var CheckService */
+ protected $checkService;
+
+
+ /**
+ * CheckInstallation constructor.
+ *
+ * @param CheckService $checkService
+ */
+ public function __construct(CheckService $checkService) {
+ $this->checkService = $checkService;
+ }
+
+
+ /**
+ * Returns the step's name
+ *
+ * @return string
+ * @since 9.1.0
+ */
+ public function getName() {
+ return 'Check the installation of the Social app.';
+ }
+
+
+ /**
+ * @param IOutput $output
+ */
+ public function run(IOutput $output) {
+ $this->checkService->checkInstallationStatus();
+ }
+
+
+}
diff --git a/lib/Model/ActivityPub/ACore.php b/lib/Model/ActivityPub/ACore.php
index aded0ddb..a9d69ec1 100644
--- a/lib/Model/ActivityPub/ACore.php
+++ b/lib/Model/ActivityPub/ACore.php
@@ -37,6 +37,8 @@ use OCA\Social\Exceptions\ActivityCantBeVerifiedException;
use OCA\Social\Exceptions\InvalidOriginException;
use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\UrlCloudException;
+use OCA\Social\Model\LinkedDataSignature;
+use OCA\Social\Service\ActivityPub\ICoreService;
use OCA\Social\Model\ActivityPub\Object\Document;
@@ -72,6 +74,10 @@ class ACore extends Item implements JsonSerializable {
private $icon = null;
+ /** @var LinkedDataSignature */
+ private $signature = null;
+
+
/**
* Core constructor.
*
@@ -165,14 +171,45 @@ class ACore extends Item implements JsonSerializable {
}
+ /**
+ * @return bool
+ */
+ public function gotSignature(): bool {
+ return ($this->signature !== null);
+ }
+
+ /**
+ * @return LinkedDataSignature
+ */
+ public function getSignature(): LinkedDataSignature {
+ return $this->signature;
+ }
+
+ /**
+ * @param LinkedDataSignature $signature
+ *
+ * @return ACore
+ */
+ public function setSignature(LinkedDataSignature $signature): Acore {
+ $this->signature = $signature;
+
+ return $this;
+ }
+
+
/**
* @param string $base
+ * @param bool $root
*
* @throws UrlCloudException
*/
- public function generateUniqueId(string $base = '') {
- if ($this->getUrlCloud() === '') {
- throw new UrlCloudException();
+ public function generateUniqueId(string $base = '', bool $root = true) {
+ $url = '';
+ if ($root) {
+ $url = $this->getUrlCloud();
+ if ($url === '') {
+ throw new UrlCloudException();
+ }
}
if ($base !== '') {
@@ -185,7 +222,7 @@ class ACore extends Item implements JsonSerializable {
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
- $this->setId($this->getUrlCloud() . $base . '/' . $uuid);
+ $this->setId($url . $base . '/' . $uuid);
}
@@ -490,13 +527,21 @@ class ACore extends Item implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
+
+ if ($this->gotSignature()) {
+ $this->entries['signature'] = $this->getSignature();
+ }
+
if ($this->isRoot()) {
- $this->addEntryArray(
- '@context', [
- self::CONTEXT_ACTIVITYSTREAMS,
- self::CONTEXT_SECURITY
- ]
- );
+ $context = [self::CONTEXT_ACTIVITYSTREAMS];
+
+ if ($this->gotObject()
+ && $this->getObject()
+ ->gotSignature()) {
+ array_push($context, self::CONTEXT_SECURITY);
+ }
+
+ $this->addEntryArray('@context', $context);
}
$this->addEntry('id', $this->getId());
@@ -523,7 +568,6 @@ class ACore extends Item implements JsonSerializable {
$this->addEntry('published', $this->getPublished());
$this->addEntryArray('tag', $this->getTags());
-// $arr = $this->getEntries();
if ($this->gotObject()) {
$this->addEntryItem('object', $this->getObject());
} else {
diff --git a/lib/Model/ActivityPub/Activity/Accept.php b/lib/Model/ActivityPub/Activity/Accept.php
index 9d310c2d..af82c9ec 100644
--- a/lib/Model/ActivityPub/Activity/Accept.php
+++ b/lib/Model/ActivityPub/Activity/Accept.php
@@ -71,11 +71,7 @@ class Accept extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/ActivityPub/Activity/Create.php b/lib/Model/ActivityPub/Activity/Create.php
index a2b8690f..42a77f87 100644
--- a/lib/Model/ActivityPub/Activity/Create.php
+++ b/lib/Model/ActivityPub/Activity/Create.php
@@ -70,11 +70,7 @@ class Create extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/ActivityPub/Activity/Delete.php b/lib/Model/ActivityPub/Activity/Delete.php
index 9e23d76e..69c20037 100644
--- a/lib/Model/ActivityPub/Activity/Delete.php
+++ b/lib/Model/ActivityPub/Activity/Delete.php
@@ -71,11 +71,7 @@ class Delete extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/ActivityPub/Activity/Follow.php b/lib/Model/ActivityPub/Activity/Follow.php
index 1d35680a..ebb526b3 100644
--- a/lib/Model/ActivityPub/Activity/Follow.php
+++ b/lib/Model/ActivityPub/Activity/Follow.php
@@ -126,13 +126,19 @@ class Follow extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- 'follow_id' => $this->getFollowId(),
- 'accepted' => $this->isAccepted()
- ]
- );
+ $result = parent::jsonSerialize();
+
+ if ($this->isCompleteDetails()) {
+ array_merge(
+ $result,
+ [
+ 'follow_id' => $this->getFollowId(),
+ 'accepted' => $this->isAccepted()
+ ]
+ );
+ }
+
+ return $result;
}
}
diff --git a/lib/Model/ActivityPub/Activity/Reject.php b/lib/Model/ActivityPub/Activity/Reject.php
index 5ceb2808..77accf20 100644
--- a/lib/Model/ActivityPub/Activity/Reject.php
+++ b/lib/Model/ActivityPub/Activity/Reject.php
@@ -71,11 +71,7 @@ class Reject extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/ActivityPub/Activity/Undo.php b/lib/Model/ActivityPub/Activity/Undo.php
index ec1cfee4..806969de 100644
--- a/lib/Model/ActivityPub/Activity/Undo.php
+++ b/lib/Model/ActivityPub/Activity/Undo.php
@@ -70,11 +70,7 @@ class Undo extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/ActivityPub/Object/Image.php b/lib/Model/ActivityPub/Object/Image.php
index be7fd266..6d9399e2 100644
--- a/lib/Model/ActivityPub/Object/Image.php
+++ b/lib/Model/ActivityPub/Object/Image.php
@@ -75,11 +75,7 @@ class Image extends Document implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/ActivityPub/Object/Note.php b/lib/Model/ActivityPub/Object/Note.php
index 8b5c7e87..185f4ec9 100644
--- a/lib/Model/ActivityPub/Object/Note.php
+++ b/lib/Model/ActivityPub/Object/Note.php
@@ -35,6 +35,7 @@ use JsonSerializable;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Service\ActivityService;
+
class Note extends ACore implements JsonSerializable {
diff --git a/lib/Model/ActivityPub/Object/Tombstone.php b/lib/Model/ActivityPub/Object/Tombstone.php
index 6247f37d..2e48b22b 100644
--- a/lib/Model/ActivityPub/Object/Tombstone.php
+++ b/lib/Model/ActivityPub/Object/Tombstone.php
@@ -71,11 +71,7 @@ class Tombstone extends ACore implements JsonSerializable {
* @return array
*/
public function jsonSerialize(): array {
- return array_merge(
- parent::jsonSerialize(),
- [
- ]
- );
+ return parent::jsonSerialize();
}
}
diff --git a/lib/Model/LinkedDataSignature.php b/lib/Model/LinkedDataSignature.php
new file mode 100644
index 00000000..689a5091
--- /dev/null
+++ b/lib/Model/LinkedDataSignature.php
@@ -0,0 +1,318 @@
+
+ * @copyright 2018, Maxence Lange
+ * @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 .
+ *
+ */
+
+
+namespace OCA\Social\Model;
+
+
+use daita\MySmallPhpTools\Traits\TArrayTools;
+use JsonSerializable;
+use OCA\Social\Exceptions\LinkedDataSignatureMissingException;
+use OCA\Social\Model\ActivityPub\ACore;
+
+
+/**
+ * Class InstancePath
+ *
+ * @package OCA\Social\Model
+ */
+class LinkedDataSignature implements JsonSerializable {
+
+
+ use TArrayTools;
+
+ /** @var string */
+ private $type = '';
+
+ /** @var string */
+ private $creator = '';
+
+ /** @var string */
+ private $created = '';
+
+ /** @var string */
+ private $signatureValue = '';
+
+ /** @var string */
+ private $privateKey = '';
+
+ /** @var string */
+ private $publicKey = '';
+
+ /** @var array */
+ private $object = [];
+
+
+ /**
+ * LinkedDataSignature constructor.
+ */
+ public function __construct() {
+ }
+
+ /**
+ * @return string
+ */
+ public function getType(): string {
+ return $this->type;
+ }
+
+ /**
+ * @param string $type
+ *
+ * @return LinkedDataSignature
+ */
+ public function setType(string $type): LinkedDataSignature {
+ $this->type = $type;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCreator(): string {
+ return $this->creator;
+ }
+
+ /**
+ * @param string $creator
+ *
+ * @return LinkedDataSignature
+ */
+ public function setCreator(string $creator): LinkedDataSignature {
+ $this->creator = $creator;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCreated(): string {
+ return $this->created;
+ }
+
+ /**
+ * @param string $created
+ *
+ * @return LinkedDataSignature
+ */
+ public function setCreated(string $created): LinkedDataSignature {
+ $this->created = $created;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSignatureValue(): string {
+ return $this->signatureValue;
+ }
+
+ /**
+ * @param string $signatureValue
+ *
+ * @return LinkedDataSignature
+ */
+ public function setSignatureValue(string $signatureValue): LinkedDataSignature {
+ $this->signatureValue = $signatureValue;
+
+ return $this;
+ }
+
+
+ /**
+ * @return array
+ */
+ public function getObject(): array {
+ return $this->object;
+ }
+
+ /**
+ * @param array $object
+ *
+ * @return LinkedDataSignature
+ */
+ public function setObject(array $object): LinkedDataSignature {
+ $this->object = $object;
+
+ return $this;
+ }
+
+
+ /**
+ * @return string
+ */
+ public function getPrivateKey(): string {
+ return $this->privateKey;
+ }
+
+ /**
+ * @param string $privateKey
+ *
+ * @return LinkedDataSignature
+ */
+ public function setPrivateKey(string $privateKey): LinkedDataSignature {
+ $this->privateKey = $privateKey;
+
+ return $this;
+ }
+
+
+ /**
+ * @return string
+ */
+ public function getPublicKey(): string {
+ return $this->publicKey;
+ }
+
+ /**
+ * @param string $publicKey
+ *
+ * @return LinkedDataSignature
+ */
+ public function setPublicKey(string $publicKey): LinkedDataSignature {
+ $this->publicKey = $publicKey;
+
+ return $this;
+ }
+
+
+ /**
+ * @throws LinkedDataSignatureMissingException
+ */
+ public function sign() {
+ $header = [
+ '@context' => 'https://w3id.org/identity/v1',
+ 'creator' => $this->getCreator(),
+ 'created' => $this->getCreated()
+ ];
+
+ $hash = $this->hashedCanonicalize($header) . $this->hashedCanonicalize($this->getObject());
+
+ $algo = OPENSSL_ALGO_SHA256;
+ if ($this->getType() === 'RsaSignature2017') {
+ $algo = OPENSSL_ALGO_SHA256;
+ }
+
+ if (!openssl_sign($hash, $signed, $this->getPrivateKey(), $algo)) {
+ throw new LinkedDataSignatureMissingException();
+ }
+
+ $this->setSignatureValue(base64_encode($signed));
+ }
+
+
+ /**
+ * @return bool
+ */
+ public function verify(): bool {
+
+ $header = [
+ '@context' => 'https://w3id.org/identity/v1',
+ 'creator' => $this->getCreator(),
+ 'created' => $this->getCreated()
+ ];
+
+ $hash = $this->hashedCanonicalize($header) . $this->hashedCanonicalize($this->getObject());
+ $signed = base64_decode($this->getSignatureValue());
+
+ $algo = OPENSSL_ALGO_SHA256;
+ if ($this->getType() === 'RsaSignature2017') {
+ $algo = OPENSSL_ALGO_SHA256;
+ }
+
+ if (openssl_verify($hash, $signed, $this->getPublicKey(), $algo) === 1) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return string
+ */
+ private function hashedCanonicalize(array $data): string {
+ $object = json_decode(json_encode($data), false);
+ $res = jsonld_normalize(
+ $object,
+ [
+ 'algorithm' => 'URDNA2015',
+ 'format' => 'application/nquads'
+ ]
+ );
+
+ return hash('sha256', $res);
+ }
+
+
+ /**
+ * @param array $data
+ *
+ * @throws LinkedDataSignatureMissingException
+ */
+ public function import(array $data) {
+
+ if (!in_array(ACore::CONTEXT_SECURITY, $this->getArray('@context', $data, []))) {
+ throw new LinkedDataSignatureMissingException();
+ }
+
+ $signature = $this->getArray('signature', $data, []);
+ if ($signature === []) {
+ throw new LinkedDataSignatureMissingException();
+ }
+
+ $this->setType($this->get('type', $signature, ''));
+ $this->setCreator($this->get('creator', $signature, ''));
+ $this->setCreated($this->get('created', $signature, ''));
+ $this->setSignatureValue($this->get('signatureValue', $signature, ''));
+
+ unset($data['signature']);
+
+ $this->setObject($data);
+ }
+
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array {
+ return [
+ 'type' => $this->getType(),
+ 'creator' => $this->getCreator(),
+ 'created' => $this->getCreated(),
+ 'signatureValue' => $this->getSignatureValue()
+ ];
+ }
+
+}
+
diff --git a/lib/Service/ActivityService.php b/lib/Service/ActivityService.php
index 585d62dd..8aa943c7 100644
--- a/lib/Service/ActivityService.php
+++ b/lib/Service/ActivityService.php
@@ -39,6 +39,7 @@ use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\EmptyQueueException;
use OCA\Social\Exceptions\InvalidResourceException;
+use OCA\Social\Exceptions\LinkedDataSignatureMissingException;
use OCA\Social\Exceptions\NoHighPriorityRequestException;
use OCA\Social\Exceptions\QueueStatusException;
use OCA\Social\Exceptions\Request410Exception;
@@ -51,6 +52,7 @@ use OCA\Social\Model\ActivityPub\Activity\Delete;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Tombstone;
use OCA\Social\Model\InstancePath;
+use OCA\Social\Model\LinkedDataSignature;
use OCA\Social\Model\RequestQueue;
class ActivityService {
@@ -65,9 +67,6 @@ class ActivityService {
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';
@@ -137,6 +136,7 @@ class ActivityService {
public function createActivity(Person $actor, ACore $item, ACore &$activity = null): string {
$activity = new Create();
+ $item->setParent($activity);
// $this->activityStreamsService->initCore($activity);
@@ -151,6 +151,7 @@ class ActivityService {
// }
$activity->setActor($actor);
+ $this->signObject($actor, $activity);
return $this->request($activity);
}
@@ -393,6 +394,96 @@ 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 Person $actor
+ * @param ACore $object
+ */
+ public function signObject(Person $actor, ACore &$object) {
+ $signature = new LinkedDataSignature();
+ $signature->setPrivateKey($actor->getPrivateKey());
+ $signature->setType('RsaSignature2017');
+ $signature->setCreator($actor->getId() . '#main-key');
+ $signature->setCreated($object->getPublished());
+ $signature->setObject(json_decode(json_encode($object), true));
+
+ try {
+ $signature->sign();
+ $object->setSignature($signature);
+ } catch (LinkedDataSignatureMissingException $e) {
+ }
+ }
+
+
+ /**
+ * @param ACore $object
+ *
+ * @return bool
+ * @throws InvalidResourceException
+ * @throws Request410Exception
+ * @throws RequestException
+ * @throws SocialAppConfigException
+ * @throws UrlCloudException
+ * @throws InvalidOriginException
+ */
+ public function checkObject(ACore $object): bool {
+ try {
+ $actorId = $object->getActorId();
+
+ $signature = new LinkedDataSignature();
+ $signature->import(json_decode($object->getSource(), true));
+ $signature->setPublicKey($this->retrieveKey($actorId));
+
+ if ($signature->verify()) {
+ $object->setOrigin($this->getKeyOrigin($actorId));
+
+ return true;
+ }
+ } catch (LinkedDataSignatureMissingException $e) {
+ }
+
+ return false;
+ }
+
+
+ /**
+ * $signature = new LinkedDataSignature();
* @param ACore $activity
*
* @return string
diff --git a/lib/Service/CacheDocumentService.php b/lib/Service/CacheDocumentService.php
index d3d8702b..5bf92f0a 100644
--- a/lib/Service/CacheDocumentService.php
+++ b/lib/Service/CacheDocumentService.php
@@ -103,7 +103,6 @@ class CacheDocumentService {
$content = $this->retrieveContent($url);
- // TODO - get mime type in a better way.
// To get the mime type, we create a temp file
$tmpFile = tmpfile();
$tmpPath = stream_get_meta_data($tmpFile)['uri'];
diff --git a/lib/Service/CheckService.php b/lib/Service/CheckService.php
index dea98418..306f13e0 100644
--- a/lib/Service/CheckService.php
+++ b/lib/Service/CheckService.php
@@ -24,6 +24,9 @@
namespace OCA\Social\Service;
+use daita\MySmallPhpTools\Traits\TStringTools;
+use OCA\Social\Db\FollowsRequest;
+use OCA\Social\Model\ActivityPub\Follow;
use OCP\AppFramework\Http;
use OCP\Http\Client\IClientService;
use OCP\ICache;
@@ -31,25 +34,56 @@ use OCP\IConfig;
use OCP\IRequest;
use OCP\IURLGenerator;
+
+/**
+ * Class CheckService
+ *
+ * @package OCA\Social\Service
+ */
class CheckService {
+
+ use TStringTools;
+
+
private $cache;
private $config;
private $clientService;
private $request;
private $urlGenerator;
+ /** @var FollowsRequest */
+ private $followRequest;
+
const CACHE_PREFIX = 'social_check_';
- public function __construct(ICache $cache, IConfig $config, IClientService $clientService, IRequest $request, IURLGenerator $urlGenerator) {
+ /**
+ * CheckService constructor.
+ *
+ * @param ICache $cache
+ * @param IConfig $config
+ * @param IClientService $clientService
+ * @param IRequest $request
+ * @param IURLGenerator $urlGenerator
+ * @param FollowsRequest $followRequest
+ */
+ public function __construct(
+ ICache $cache, IConfig $config, IClientService $clientService, IRequest $request,
+ IURLGenerator $urlGenerator, FollowsRequest $followRequest
+ ) {
$this->cache = $cache;
$this->config = $config;
$this->clientService = $clientService;
$this->request = $request;
$this->urlGenerator = $urlGenerator;
+ $this->followRequest = $followRequest;
}
+
+ /**
+ * @return array
+ */
public function checkDefault(): array {
$checks = [];
$checks['wellknown'] = $this->checkWellKnown();
@@ -60,13 +94,19 @@ class CheckService {
$success = false;
}
}
+
return [
'success' => $success,
- 'checks' => $checks
+ 'checks' => $checks
];
}
+
+
+ /**
+ * @return bool
+ */
public function checkWellKnown(): bool {
- $state = (bool) ($this->cache->get(self::CACHE_PREFIX . 'wellknown') === 'true');
+ $state = (bool)($this->cache->get(self::CACHE_PREFIX . 'wellknown') === 'true');
if ($state === true) {
return true;
}
@@ -77,7 +117,9 @@ class CheckService {
return true;
}
- if ($this->requestWellKnown($this->request->getServerProtocol() . '://' . $this->request->getServerHost())) {
+ if ($this->requestWellKnown(
+ $this->request->getServerProtocol() . '://' . $this->request->getServerHost()
+ )) {
return true;
}
@@ -88,17 +130,50 @@ class CheckService {
return false;
}
- private function requestWellKnown($base) {
+
+ /**
+ *
+ */
+ public function checkInstallationStatus() {
+ $this->checkStatusTableFollows();
+ }
+
+
+ public function checkStatusTableFollows() {
+ if ($this->followRequest->countFollows() > 0) {
+ return;
+ }
+
+ $follow = new Follow();
+ $follow->setId($this->uuid());
+ $follow->setType('Unknown');
+ $follow->setActorId($this->uuid());
+ $follow->setObjectId($this->uuid());
+ $follow->setFollowId($this->uuid());
+
+ $this->followRequest->save($follow);
+ }
+
+
+ /**
+ * @param string $base
+ *
+ * @return bool
+ */
+ private function requestWellKnown(string $base) {
try {
$url = $base . '/.well-known/webfinger';
- $response = $this->clientService->newClient()->get($url);
+ $response = $this->clientService->newClient()
+ ->get($url);
if ($response->getStatusCode() === Http::STATUS_OK) {
$this->cache->set(self::CACHE_PREFIX . 'wellknown', 'true', 3600);
+
return true;
}
} catch (\GuzzleHttp\Exception\ClientException $e) {
} catch (\Exception $e) {
}
+
return false;
}
diff --git a/lib/Service/ImportService.php b/lib/Service/ImportService.php
index 9ba9085f..935a2cb9 100644
--- a/lib/Service/ImportService.php
+++ b/lib/Service/ImportService.php
@@ -39,6 +39,20 @@ use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\ActivityPub\ACore;
+use OCA\Social\Model\ActivityPub\Activity\Accept;
+use OCA\Social\Model\ActivityPub\Activity\Create;
+use OCA\Social\Model\ActivityPub\Activity\Delete;
+use OCA\Social\Model\ActivityPub\Activity\Reject;
+use OCA\Social\Model\ActivityPub\Tombstone;
+use OCA\Social\Model\ActivityPub\Document;
+use OCA\Social\Model\ActivityPub\Follow;
+use OCA\Social\Model\ActivityPub\Image;
+use OCA\Social\Model\ActivityPub\Note;
+use OCA\Social\Model\ActivityPub\Activity\Undo;
+use OCA\Social\Service\ActivityPub\DeleteService;
+use OCA\Social\Service\ActivityPub\FollowService;
+use OCA\Social\Service\ActivityPub\NoteService;
+use OCA\Social\Service\ActivityPub\UndoService;
class ImportService {
@@ -70,10 +84,14 @@ class ImportService {
* @param string $json
*
* @return ACore
+ * @throws ActivityPubFormatException
+ * @throws InvalidResourceEntryException
+ * @throws SocialAppConfigException
* @throws UnknownItemException
* @throws SocialAppConfigException
* @throws ActivityPubFormatException
* @throws RedundancyLimitException
+ * @throws UrlCloudException
*/
public function importFromJson(string $json): ACore {
$data = json_decode($json, true);
diff --git a/lib/Service/NoteService.php b/lib/Service/NoteService.php
index 7cf1486b..2b2d8384 100644
--- a/lib/Service/NoteService.php
+++ b/lib/Service/NoteService.php
@@ -30,14 +30,21 @@ declare(strict_types=1);
namespace OCA\Social\Service;
+use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
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\InvalidOriginException;
use OCA\Social\Exceptions\NoteNotFoundException;
+use OCA\Social\Exceptions\RedundancyLimitException;
use OCA\Social\Exceptions\SocialAppConfigException;
+use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Exceptions\UrlCloudException;
+use OCA\Social\Exceptions\InvalidResourceException;
+use OCA\Social\Exceptions\Request410Exception;
+use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Note;
use OCA\Social\Model\InstancePath;
@@ -79,12 +86,9 @@ class NoteService {
* @param MiscService $miscService
*/
public function __construct(
- NotesRequest $notesRequest,
- ActivityService $activityService,
- AccountService $accountService,
- CacheActorService $cacheActorService,
- ConfigService $configService,
- MiscService $miscService
+ NotesRequest $notesRequest, ActivityService $activityService,
+ AccountService $accountService, CacheActorService $cacheActorService,
+ ConfigService $configService, MiscService $miscService
) {
$this->notesRequest = $notesRequest;
$this->activityService = $activityService;
@@ -241,16 +245,29 @@ class NoteService {
/**
* @param Note $note
* @param string $replyTo
+ *
+ * @throws InvalidOriginException
+ * @throws InvalidResourceException
+ * @throws MalformedArrayException
+ * @throws NoteNotFoundException
+ * @throws RedundancyLimitException
+ * @throws Request410Exception
+ * @throws RequestException
+ * @throws SocialAppConfigException
+ * @throws UnknownItemException
*/
public function replyTo(Note $note, string $replyTo) {
if ($replyTo === '') {
return;
}
+ $author = $this->getAuthorFromPostId($replyTo);
$note->setInReplyTo($replyTo);
// TODO - type can be NOT public !
$note->addInstancePath(
- new InstancePath($replyTo, InstancePath::TYPE_PUBLIC, InstancePath::PRIORITY_HIGH)
+ new InstancePath(
+ $author->getSharedInbox(), InstancePath::TYPE_INBOX, InstancePath::PRIORITY_HIGH
+ )
);
}
@@ -294,6 +311,18 @@ class NoteService {
}
+ /**
+ * @param Person $actor
+ * @param int $since
+ * @param int $limit
+ *
+ * @return Note[]
+ */
+ public function getStreamNotifications(Person $actor, int $since = 0, int $limit = 5): array {
+ return $this->notesRequest->getStreamNotifications($actor, $since, $limit);
+ }
+
+
/**
* @param string $actorId
* @param int $since
@@ -352,5 +381,25 @@ class NoteService {
}
+ /**
+ * @param $noteId
+ *
+ * @return Person
+ * @throws InvalidResourceException
+ * @throws MalformedArrayException
+ * @throws NoteNotFoundException
+ * @throws Request410Exception
+ * @throws RequestException
+ * @throws SocialAppConfigException
+ * @throws InvalidOriginException
+ * @throws RedundancyLimitException
+ * @throws UnknownItemException
+ */
+ public function getAuthorFromPostId($noteId) {
+ $note = $this->notesRequest->getNoteById($noteId);
+
+ return $this->cacheActorService->getFromId($note->getAttributedTo());
+ }
+
}
diff --git a/package-lock.json b/package-lock.json
index 801247eb..16a2cdbc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,25 +14,115 @@
}
},
"@babel/core": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.2.tgz",
- "integrity": "sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==",
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.2.2.tgz",
+ "integrity": "sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
- "@babel/generator": "^7.1.2",
- "@babel/helpers": "^7.1.2",
- "@babel/parser": "^7.1.2",
- "@babel/template": "^7.1.2",
- "@babel/traverse": "^7.1.0",
- "@babel/types": "^7.1.2",
+ "@babel/generator": "^7.2.2",
+ "@babel/helpers": "^7.2.0",
+ "@babel/parser": "^7.2.2",
+ "@babel/template": "^7.2.2",
+ "@babel/traverse": "^7.2.2",
+ "@babel/types": "^7.2.2",
"convert-source-map": "^1.1.0",
- "debug": "^3.1.0",
- "json5": "^0.5.0",
+ "debug": "^4.1.0",
+ "json5": "^2.1.0",
"lodash": "^4.17.10",
"resolve": "^1.3.2",
"semver": "^5.4.1",
"source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "@babel/generator": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz",
+ "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.2.2",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.10",
+ "source-map": "^0.5.0",
+ "trim-right": "^1.0.1"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.2.tgz",
+ "integrity": "sha512-UNTmQ5cSLDeBGBl+s7JeowkqIHgmFAGBnLDdIzFmUNSuS5JF0XBcN59jsh/vJO/YjfsBqMxhMjoFGmNExmf0FA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz",
+ "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.2.2",
+ "@babel/types": "^7.2.2"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.2.tgz",
+ "integrity": "sha512-E5Bn9FSwHpSkUhthw/XEuvFZxIgrqb9M8cX8j5EUQtrUG5DQUy6bFyl7G7iQ1D1Czudor+xkmp81JbLVVM0Sjg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/generator": "^7.2.2",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.0.0",
+ "@babel/parser": "^7.2.2",
+ "@babel/types": "^7.2.2",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.10"
+ }
+ },
+ "@babel/types": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz",
+ "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.10",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+ "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "json5": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
+ "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
}
},
"@babel/generator": {
@@ -254,14 +344,78 @@
}
},
"@babel/helpers": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.2.tgz",
- "integrity": "sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.2.0.tgz",
+ "integrity": "sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==",
"dev": true,
"requires": {
"@babel/template": "^7.1.2",
- "@babel/traverse": "^7.1.0",
- "@babel/types": "^7.1.2"
+ "@babel/traverse": "^7.1.5",
+ "@babel/types": "^7.2.0"
+ },
+ "dependencies": {
+ "@babel/generator": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz",
+ "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.2.2",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.10",
+ "source-map": "^0.5.0",
+ "trim-right": "^1.0.1"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.2.tgz",
+ "integrity": "sha512-UNTmQ5cSLDeBGBl+s7JeowkqIHgmFAGBnLDdIzFmUNSuS5JF0XBcN59jsh/vJO/YjfsBqMxhMjoFGmNExmf0FA==",
+ "dev": true
+ },
+ "@babel/traverse": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.2.tgz",
+ "integrity": "sha512-E5Bn9FSwHpSkUhthw/XEuvFZxIgrqb9M8cX8j5EUQtrUG5DQUy6bFyl7G7iQ1D1Czudor+xkmp81JbLVVM0Sjg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/generator": "^7.2.2",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.0.0",
+ "@babel/parser": "^7.2.2",
+ "@babel/types": "^7.2.2",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.10"
+ }
+ },
+ "@babel/types": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz",
+ "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.10",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+ "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
}
},
"@babel/highlight": {
@@ -2643,6 +2797,12 @@
}
}
},
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
"clone-regexp": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz",
@@ -2987,9 +3147,9 @@
}
},
"css-loader": {
- "version": "2.0.0",
- "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-2.0.0.tgz",
- "integrity": "sha512-3Fq8HJYs7ruBiDpJA/w2ZROtivA769ePuH3/vgPdOB+FQiotErJ7VJYRZq86SPRVFaccn1wEktUnaaUyf+Uslw==",
+ "version": "2.0.1",
+ "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-2.0.1.tgz",
+ "integrity": "sha512-XIVwoIOzSFRVsafOKa060GJ/A70c0IP/C1oVPHEX4eHIFF39z0Jl7j8Kua1SUTiqWDupUnbY3/yQx9r7EUB35w==",
"dev": true,
"requires": {
"icss-utils": "^4.0.0",
@@ -3005,9 +3165,9 @@
},
"dependencies": {
"ajv": {
- "version": "6.6.1",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz",
- "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==",
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
+ "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
@@ -3035,9 +3195,9 @@
"dev": true
},
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -4294,19 +4454,19 @@
}
},
"file-loader": {
- "version": "1.1.11",
- "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
- "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
+ "version": "2.0.0",
+ "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz",
+ "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==",
"dev": true,
"requires": {
"loader-utils": "^1.0.2",
- "schema-utils": "^0.4.5"
+ "schema-utils": "^1.0.0"
},
"dependencies": {
"ajv": {
- "version": "6.5.4",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
- "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
+ "version": "6.6.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz",
+ "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
@@ -4334,12 +4494,13 @@
"dev": true
},
"schema-utils": {
- "version": "0.4.7",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
- "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
"dev": true,
"requires": {
"ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
"ajv-keywords": "^3.1.0"
}
}
@@ -5453,9 +5614,9 @@
},
"dependencies": {
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -7388,14 +7549,6 @@
"requires": {
"clone": "2.x",
"lodash": "4.x"
- },
- "dependencies": {
- "clone": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
- "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
- "dev": true
- }
}
},
"node-int64": {
@@ -8058,9 +8211,9 @@
},
"dependencies": {
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -8088,9 +8241,9 @@
},
"dependencies": {
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -8117,9 +8270,9 @@
},
"dependencies": {
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -8146,9 +8299,9 @@
},
"dependencies": {
"postcss": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
- "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+ "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -11771,9 +11924,9 @@
"integrity": "sha512-CKITl7I1cb3X4zIHbVSyrupPTs9XxZGVV/N+P5lSxSrGW+D92gq6zuTy/XnvJOwMRkjJuiotJAQrgv+gOwSx3g=="
},
"vue-jest": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/vue-jest/-/vue-jest-3.0.1.tgz",
- "integrity": "sha512-otS+n341cTsp0pF7tuTu2x43b23x/+K0LZdAXV+ewKYIMZRqhuQaJTECWEt/cN/YZw2JC6hUM6xybdnOB4ZQ+g==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/vue-jest/-/vue-jest-3.0.2.tgz",
+ "integrity": "sha512-5XIQ1xQFW0ZnWxHWM7adVA2IqbDsdw1vhgZfGFX4oWd75J38KIS3YT41PtiE7lpMLmNM6+VJ0uprT2mhHjUgkA==",
"dev": true,
"requires": {
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
@@ -12476,9 +12629,9 @@
}
},
"webpack-merge": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz",
- "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.5.tgz",
+ "integrity": "sha512-sVcM+MMJv6DO0C0GLLltx8mUlGMKXE0zBsuMqZ9jz2X9gsekALw6Rs0cAfTWc97VuWS6NpVUa78959zANnMMLQ==",
"dev": true,
"requires": {
"lodash": "^4.17.5"
diff --git a/package.json b/package.json
index 593d0acc..47bb68d4 100644
--- a/package.json
+++ b/package.json
@@ -54,14 +54,14 @@
"node": ">=10.0.0"
},
"devDependencies": {
- "@babel/core": "^7.1.2",
+ "@babel/core": "^7.2.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.2.0",
"@vue/test-utils": "^1.0.0-beta.27",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.4",
- "css-loader": "^2.0.0",
+ "css-loader": "^2.0.1",
"eslint": "^4.19.1",
"eslint-config-standard": "^11.0.0",
"eslint-friendly-formatter": "^4.0.1",
@@ -72,7 +72,7 @@
"eslint-plugin-standard": "^3.1.0",
"eslint-plugin-vue": "^4.5.0",
"extract-text-webpack-plugin": "^3.0.2",
- "file-loader": "^1.1.11",
+ "file-loader": "^2.0.0",
"jest": "^23.6.0",
"jest-serializer-vue": "^2.0.2",
"mini-css-extract-plugin": "^0.5.0",
@@ -81,13 +81,13 @@
"stylelint": "^8.4.0",
"stylelint-config-recommended-scss": "^3.2.0",
"stylelint-webpack-plugin": "^0.10.5",
- "vue-jest": "^3.0.1",
+ "vue-jest": "^3.0.2",
"vue-loader": "^15.4.2",
"vue-style-loader": "^4.1.1",
"vue-template-compiler": "^2.5.21",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2",
- "webpack-merge": "^4.1.2"
+ "webpack-merge": "^4.1.5"
},
"jest": {
"moduleFileExtensions": [