diff --git a/appinfo/application.php b/appinfo/application.php index 9ffb63e5..61ccb9a5 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -22,11 +22,14 @@ use OCA\OJSXC\StanzaLogger; use OCA\OJSXC\RawRequest; use OCA\OJSXC\DataRetriever; -use OCP\AppFramework\App; +use OCA\OJSXC\UserProvider; use OCA\OJSXC\ILock; use OCA\OJSXC\DbLock; use OCA\OJSXC\MemLock; use OCA\OJSXC\Hooks; +use OCA\OJSXC\UserManagerUserProvider; +use OCA\OJSXC\ContactsStoreUserProvider; +use OCP\AppFramework\App; use OCP\IContainer; use OCP\IRequest; @@ -50,6 +53,9 @@ public function __construct(array $urlParams=array()){ ['locking' => false]); + /** + * Controllers + */ $container->registerService('HttpBindController', function(IContainer $c) { return new HttpBindController( $c->query('AppName'), @@ -153,7 +159,8 @@ public function __construct(array $urlParams=array()){ $c->query('OJSXC_UserId'), $c->query('MessageMapper'), $c->query('NewContentContainer'), - self::$config['polling']['timeout'] + self::$config['polling']['timeout'], + $c->query('UserProvider') ); }); @@ -166,7 +173,8 @@ public function __construct(array $urlParams=array()){ $c->query('OJSXC_UserId'), $c->query('Host'), $c->query('OCP\IUserManager'), - $c->query('OCP\IConfig') + $c->query('OCP\IConfig'), + $c->query('UserProvider') ); }); @@ -183,7 +191,9 @@ public function __construct(array $urlParams=array()){ return new Message( $c->query('OJSXC_UserId'), $c->query('Host'), - $c->query('MessageMapper') + $c->query('MessageMapper'), + $c->query('UserProvider'), + $c->query('OCP\ILogger') ); }); @@ -196,6 +206,9 @@ public function __construct(array $urlParams=array()){ return $request->getServerHost(); }); + /** + * Helpers + */ $container->registerService('NewContentContainer', function() { return new NewContentContainer(); }); @@ -214,7 +227,8 @@ public function __construct(array $urlParams=array()){ $c->query('ServerContainer')->getUserSession(), $c->query('Host'), $c->query('IQRosterPushMapper'), - $c->query('ServerContainer')->getDatabaseConnection() + $c->query('ServerContainer')->getDatabaseConnection(), + $c->query('UserProvider') ); }); @@ -224,14 +238,36 @@ public function __construct(array $urlParams=array()){ $c->query('ServerContainer')->getUserSession(), $c->query('RosterPush'), $c->query('PresenceMapper'), - $c->query('StanzaMapper') + $c->query('StanzaMapper'), + $c->query('ServerContainer')->query('GroupManager') ); }); + $container->registerService('UserProvider', function(IContainer $c) { + if (self::contactsStoreApiSupported()) { + return new ContactsStoreUserProvider( + $c->query('OCP\Contacts\ContactsMenu\IContactsStore'), + $c->query('ServerContainer')->getUserSession(), + $c->query('ServerContainer')->getUserManager(), + $c->query('OCP\IGroupManager'), + $c->query('OCP\IConfig') + ); + } else { + return new UserManagerUserProvider( + $c->query('ServerContainer')->getUserManager() + ); + } + }); + + + /** + * Commands + */ $container->registerService('RefreshRosterCommand', function($c) { return new RefreshRoster( $c->query('ServerContainer')->getUserManager(), - $c->query('RosterPush') + $c->query('RosterPush'), + $c->query('PresenceMapper') ); }); @@ -257,6 +293,10 @@ public function __construct(array $urlParams=array()){ return new DataRetriever(); }); + + /** + * Migrations + */ $container->registerService('OCA\OJSXC\Migration\RefreshRoster', function(IContainer $c) { return new RefreshRosterMigration( $c->query('RosterPush'), @@ -304,4 +344,13 @@ static public function santizeUserId($userId) { ) ); } + + /** + * @return bool whether the ContactsStore API is enabled + */ + public static function contactsStoreApiSupported() { + $version = \OCP\Util::getVersion(); + return $version[0] >= 13; + } + } diff --git a/composer.json b/composer.json index 05258f5a..8a205c61 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "sabre/uri": "~1.0" }, "require-dev": { - "phpunit/phpunit": "*.*", + "phpunit/phpunit": "^6.5|^5.7", "friendsofphp/php-cs-fixer": "^2.4|^2.10" } } diff --git a/composer.lock b/composer.lock index c08a9a98..b1410a27 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "be95748aeff5cdb6b71c6c21cfb69247", + "content-hash": "68dd955ad2897b8a072841c7be414b04", "packages": [ { "name": "sabre/uri", @@ -186,30 +186,30 @@ }, { "name": "doctrine/annotations", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", "shasum": "" }, "require": { "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -250,36 +250,36 @@ "docblock", "parser" ], - "time": "2017-02-24T16:22:25+00:00" + "time": "2017-12-06T07:11:42+00:00" }, { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -304,7 +304,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "doctrine/lexer", @@ -449,28 +449,31 @@ }, { "name": "gecko-packages/gecko-php-unit", - "version": "v3.0", + "version": "v3.1", "source": { "type": "git", "url": "https://github.com/GeckoPackages/GeckoPHPUnit.git", - "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3" + "reference": "dbb18b292cfa14444d2e6d15202b9dcf5ab8365e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/6a866551dffc2154c1b091bae3a7877d39c25ca3", - "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3", + "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/dbb18b292cfa14444d2e6d15202b9dcf5ab8365e", + "reference": "dbb18b292cfa14444d2e6d15202b9dcf5ab8365e", "shasum": "" }, "require": { "php": "^7.0" }, + "conflict": { + "phpunit/phpunit": "<6.0" + }, "require-dev": { "phpunit/phpunit": "^6.0" }, "suggest": { "ext-dom": "When testing with xml.", "ext-libxml": "When testing with xml.", - "phpunit/phpunit": "This is an extension for it so make sure you have it some way." + "phpunit/phpunit": "This is an extension for PHPUnit so make sure you have that in some way." }, "type": "library", "extra": { @@ -494,7 +497,7 @@ "filesystem", "phpunit" ], - "time": "2017-08-23T07:46:41+00:00" + "time": "2018-01-24T18:03:59+00:00" }, { "name": "myclabs/deep-copy", @@ -589,6 +592,108 @@ ], "time": "2017-09-27T21:40:39+00:00" }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2017-03-05T17:38:23+00:00" + }, { "name": "php-cs-fixer/diff", "version": "v1.2.1", @@ -857,40 +962,40 @@ }, { "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/661f34d0bd3f1a7225ef491a70a020ad23a057a1", + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^6.0" }, "suggest": { - "ext-xdebug": "^2.5.1" + "ext-xdebug": "^2.5.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -905,7 +1010,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -916,7 +1021,7 @@ "testing", "xunit" ], - "time": "2017-04-02T07:44:40+00:00" + "time": "2017-12-06T09:29:45+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1106,47 +1211,53 @@ }, { "name": "phpunit/phpunit", - "version": "5.5.4", + "version": "6.5.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5" + "reference": "3330ef26ade05359d006041316ed0fa9e8e3cefe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6e88e56c912133de6e99b87728cca7ed70c5f5", - "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3330ef26ade05359d006041316ed0fa9e8e3cefe", + "reference": "3330ef26ade05359d006041316ed0fa9e8e3cefe", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "^4.0.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3 || ^2.0", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0|~2.0", - "symfony/yaml": "~2.1|~3.0" + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.5", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" }, "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" }, "suggest": { - "phpunit/php-invoker": "~1.1" + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" }, "bin": [ "phpunit" @@ -1154,7 +1265,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.5.x-dev" + "dev-master": "6.5.x-dev" } }, "autoload": { @@ -1180,33 +1291,33 @@ "testing", "xunit" ], - "time": "2016-08-26T07:11:44+00:00" + "time": "2018-02-01T05:57:37+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" }, "conflict": { - "phpunit/phpunit": "<5.4.0" + "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "^6.5" }, "suggest": { "ext-soap": "*" @@ -1214,7 +1325,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -1229,7 +1340,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -1239,54 +1350,7 @@ "mock", "xunit" ], - "time": "2017-06-30T09:13:00+00:00" - }, - { - "name": "psr/log", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2018-01-06T05:45:45+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1335,30 +1399,30 @@ }, { "name": "sebastian/comparator", - "version": "1.2.4", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -1389,38 +1453,38 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", - "version": "1.4.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1447,32 +1511,32 @@ "keywords": [ "diff" ], - "time": "2017-05-22T07:24:03+00:00" + "time": "2017-08-03T08:09:46+00:00" }, { "name": "sebastian/environment", - "version": "2.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -1497,34 +1561,34 @@ "environment", "hhvm" ], - "time": "2016-11-26T07:53:53+00:00" + "time": "2017-07-01T08:51:00+00:00" }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "php": "^7.0", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -1564,27 +1628,27 @@ "export", "exporter" ], - "time": "2016-06-17T09:04:28+00:00" + "time": "2017-04-03T13:19:02+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -1592,7 +1656,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1615,33 +1679,34 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2017-04-27T15:39:26+00:00" }, { "name": "sebastian/object-enumerator", - "version": "1.0.0", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~1.0" + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1661,32 +1726,77 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28T13:25:10+00:00" + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.5", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1714,7 +1824,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" + "time": "2017-03-03T06:23:57+00:00" }, { "name": "sebastian/resource-operations", @@ -1803,45 +1913,44 @@ }, { "name": "symfony/console", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b0878233cb5c4391347e5495089c7af11b8e6201" + "reference": "36d5b41e7d4e1ccf0370f6babe966c08ef0a1488" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b0878233cb5c4391347e5495089c7af11b8e6201", - "reference": "b0878233cb5c4391347e5495089c7af11b8e6201", + "url": "https://api.github.com/repos/symfony/console/zipball/36d5b41e7d4e1ccf0370f6babe966c08ef0a1488", + "reference": "36d5b41e7d4e1ccf0370f6babe966c08ef0a1488", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/debug": "~2.8|~3.0", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~3.3", - "symfony/dependency-injection": "~3.3", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", - "symfony/filesystem": "", + "symfony/lock": "", "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1868,90 +1977,34 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-07-29T21:27:59+00:00" - }, - { - "name": "symfony/debug", - "version": "v3.3.6", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13", - "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2017-07-28T15:27:31+00:00" + "time": "2018-01-29T09:06:29+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e" + "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67535f1e3fd662bdc68d7ba317c93eecd973617e", - "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74d33aac36208c4d6757807d9f598f0133a3a4eb", + "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" }, "suggest": { "symfony/dependency-injection": "", @@ -1960,7 +2013,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1987,29 +2040,29 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-06-09T14:53:08+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/filesystem", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "427987eb4eed764c3b6e38d52a0f87989e010676" + "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/427987eb4eed764c3b6e38d52a0f87989e010676", - "reference": "427987eb4eed764c3b6e38d52a0f87989e010676", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/760e47a4ee64b4c48f4b30017011e09d4c0f05ed", + "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2036,29 +2089,29 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-07-11T07:17:58+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/finder", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4" + "reference": "8b08180f2b7ccb41062366b9ad91fbc4f1af8601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4", + "url": "https://api.github.com/repos/symfony/finder/zipball/8b08180f2b7ccb41062366b9ad91fbc4f1af8601", + "reference": "8b08180f2b7ccb41062366b9ad91fbc4f1af8601", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2085,29 +2138,29 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-06-01T21:01:25+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/options-resolver", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "ff48982d295bcac1fd861f934f041ebc73ae40f0" + "reference": "371532a2cfe932f7a3766dd4c45364566def1dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ff48982d295bcac1fd861f934f041ebc73ae40f0", - "reference": "ff48982d295bcac1fd861f934f041ebc73ae40f0", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/371532a2cfe932f7a3766dd4c45364566def1dd0", + "reference": "371532a2cfe932f7a3766dd4c45364566def1dd0", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2139,7 +2192,7 @@ "configuration", "options" ], - "time": "2017-04-12T14:14:56+00:00" + "time": "2018-01-18T22:19:33+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2316,25 +2369,25 @@ }, { "name": "symfony/process", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a" + "reference": "e1712002d81de6f39f854bc5bbd9e9f4bb6345b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a", - "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a", + "url": "https://api.github.com/repos/symfony/process/zipball/e1712002d81de6f39f854bc5bbd9e9f4bb6345b4", + "reference": "e1712002d81de6f39f854bc5bbd9e9f4bb6345b4", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2361,29 +2414,29 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-07-13T13:05:09+00:00" + "time": "2018-01-29T09:06:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v3.3.6", + "version": "v4.0.4", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "602a15299dc01556013b07167d4f5d3a60e90d15" + "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/602a15299dc01556013b07167d4f5d3a60e90d15", - "reference": "602a15299dc01556013b07167d4f5d3a60e90d15", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d52321f0e2b596bd03b5d1dd6eebe71caa925704", + "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2410,62 +2463,47 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-04-12T14:14:56+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { - "name": "symfony/yaml", - "version": "v3.3.6", + "name": "theseer/tokenizer", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed", - "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", "shasum": "" }, "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/console": "~2.8|~3.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2017-07-23T12:43:26+00:00" + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" }, { "name": "webmozart/assert", diff --git a/js/ojsxc.js b/js/ojsxc.js index 063624a8..cd823836 100644 --- a/js/ojsxc.js +++ b/js/ojsxc.js @@ -330,6 +330,16 @@ jsxc.storage.setItem('login_without_chat', false); }); + $(document).on('connfail.jsxc', function(ev, condition) { + if (condition === 'x-nc-not_allowed_to_chat') { + jsxc.gui.roster.toggle(jsxc.CONST.HIDDEN); + $('.jsxc_chatIcon').remove(); + jsxc.storage.removeItem('jid'); + jsxc.storage.removeItem('sid'); + jsxc.storage.removeItem('rid'); + } + }); + $(document).on('status.contacts.count status.contact.updated', function() { if (jsxc.restoreCompleted) { setTimeout(function() { @@ -394,6 +404,7 @@ if ($('#contactsmenu').length > 0) { observeContactsMenu(); } + }); $(document).on('click', '#jsxc_roster p', function() { diff --git a/lib/ContactsStoreUserProvider.php b/lib/ContactsStoreUserProvider.php new file mode 100644 index 00000000..cf48d037 --- /dev/null +++ b/lib/ContactsStoreUserProvider.php @@ -0,0 +1,126 @@ +contactsStore = $contactsStore; + $this->userSession = $userSession; + $this->userManager = $userManager; + $this->groupManager = $groupManager; + $this->config = $config; + } + + public function getAllUsers() + { + if (is_null(self::$cache)) { + $result = []; + $contacts = $this->contactsStore->getContacts($this->userSession->getUser(), ''); + // TODO check if contact is disabled + foreach ($contacts as $contact) { + $uid = $contact->getProperty('UID'); + if ($contact->getProperty('isLocalSystemBook') + && !$this->isUserExcluded($uid) + && $this->userManager->get($uid)->isEnabled()) { + $result[] = new User($uid, $contact->getFullName(), $contact); + } + } + self::$cache = $result; + } + + return self::$cache; + } + + public function hasUser(User $user) + { + return !is_null($this->contactsStore->findOne($this->userSession->getUser(), 0, $user->getUid())); + } + + public function hasUserByUID($uid) + { + return !is_null($this->contactsStore->findOne($this->userSession->getUser(), 0, $uid)); + } + + public function getAllUsersForUser(User $user) + { + return $this->getAllUsersForUserByUID($user->getUid()); + } + + public function getAllUsersForUserByUID($uid) + { + $result = []; + $contacts = $this->contactsStore->getContacts($this->userManager->get($uid), ''); + foreach ($contacts as $contact) { + if ($contact->getProperty('isLocalSystemBook')) { + $result[] = new User($contact->getProperty('UID'), $contact->getFullName(), $contact); + } + } + return $result; + } + + public function hasUserForUser(User $user1, User $user2) + { + return !is_null($this->contactsStore->findOne($this->userManager->get($user1->getUid()), 0, $user2->getUid())); + } + + public function hasUserForUserByUID($uid1, $uid2) + { + return !is_null($this->contactsStore->findOne($this->userManager->get($uid1), 0, $uid2)); + } + + public function isUserExcluded($userId) + { + if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') { + $user = $this->userManager->get($userId); + $user_groups = $this->groupManager->getUserGroupIds($user); + $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', ''); + $decodedExcludeGroups = json_decode($excludedGroups, true); + $excludeGroupsList = ($decodedExcludeGroups !== null) ? $decodedExcludeGroups : []; + + if (count(array_intersect($excludeGroupsList, $user_groups)) !== 0) { + // a group of the current user is excluded -> filter all local users + return true; + } + } + return false; + } +} diff --git a/lib/Controller/HttpBindController.php b/lib/Controller/HttpBindController.php index f57c03e3..923b51e9 100644 --- a/lib/Controller/HttpBindController.php +++ b/lib/Controller/HttpBindController.php @@ -5,6 +5,7 @@ use OCA\OJSXC\Db\Presence; use OCA\OJSXC\Db\PresenceMapper; use OCA\OJSXC\Db\StanzaMapper; +use OCA\OJSXC\Exceptions\TerminateException; use OCA\OJSXC\Http\XMPPResponse; use OCA\OJSXC\ILock; use OCA\OJSXC\NewContentContainer; @@ -162,50 +163,55 @@ public function index() $input = $this->body; $longpoll = true; // set to false when the response should directly be returned and no polling should be done $longpollStart = true; // start the first long poll cycle - if (!empty($input)) { - // replace invalid XML by valid XML one - $input = str_replace("", "", $input); - $reader = new Reader(); - $reader->xml($input); - $reader->elementMap = [ - '{jabber:client}message' => 'Sabre\Xml\Element\KeyValue', - '{jabber:client}presence' => function (Reader $reader) { - return Presence::createFromXml($reader, $this->userId); + try { + if (!empty($input)) { + // replace invalid XML by valid XML one + $input = str_replace("", "", $input); + $reader = new Reader(); + $reader->xml($input); + $reader->elementMap = [ + '{jabber:client}message' => 'Sabre\Xml\Element\KeyValue', + '{jabber:client}presence' => function (Reader $reader) { + return Presence::createFromXml($reader, $this->userId); + } + ]; + $parsedInput = null; + try { + $parsedInput = $reader->parse(); + } catch (LibXMLException $e) { } - ]; - $parsedInput = null; - try { - $parsedInput = $reader->parse(); - } catch (LibXMLException $e) { - } - if (!is_null($parsedInput) - && is_array($parsedInput['value']) - && count($parsedInput['value']) > 0) { - $this->stanzaLogger->logRaw($input, StanzaLogger::RECEIVING); + if (!is_null($parsedInput) + && is_array($parsedInput['value']) + && count($parsedInput['value']) > 0) { + $this->stanzaLogger->logRaw($input, StanzaLogger::RECEIVING); - $stanzas = $parsedInput['value']; - foreach ($stanzas as $stanza) { - $stanzaType = $this->getStanzaType($stanza); - if ($stanzaType === self::MESSAGE) { - $this->messageHandler->handle($stanza); - } elseif ($stanzaType === self::IQ) { - $result = $this->iqHandler->handle($stanza); - if (!is_null($result)) { - $longpoll = false; - $this->response->write($result); - } - } elseif ($stanza['value'] instanceof Presence) { - $results = $this->presenceHandler->handle($stanza['value']); - if (!is_null($results) && is_array($results)) { - $longpoll = false; - $longpollStart = false; - foreach ($results as $r) { - $this->response->write($r); + $stanzas = $parsedInput['value']; + foreach ($stanzas as $stanza) { + $stanzaType = $this->getStanzaType($stanza); + if ($stanzaType === self::MESSAGE) { + $this->messageHandler->handle($stanza); + } elseif ($stanzaType === self::IQ) { + $result = $this->iqHandler->handle($stanza); + if (!is_null($result)) { + $longpoll = false; + $this->response->write($result); + } + } elseif ($stanza['value'] instanceof Presence) { + $results = $this->presenceHandler->handle($stanza['value']); + if (!is_null($results) && is_array($results)) { + $longpoll = false; + $longpollStart = false; + foreach ($results as $r) { + $this->response->write($r); + } } } } } } + } catch (TerminateException $e) { + $this->response->terminate(); + return $this->response; } // Start long polling diff --git a/lib/Exceptions/TerminateException.php b/lib/Exceptions/TerminateException.php new file mode 100644 index 00000000..1b7fdb4c --- /dev/null +++ b/lib/Exceptions/TerminateException.php @@ -0,0 +1,8 @@ +uid = Application::santizeUserId($uid); + $this->fullName = $fullName; + $this->origin = $origin; + } + + /** + * @return string + */ + public function getUid() + { + return $this->uid; + } + + /** + * @param string $uid + */ + public function setUid($uid) + { + $this->uid = Application::santizeUserId($uid); + } + + /** + * @return string + */ + public function getFullName() + { + return $this->fullName; + } + + /** + * @param string $fullName + */ + public function setFullName($fullName) + { + $this->fullName = $fullName; + } +} diff --git a/lib/UserManagerUserProvider.php b/lib/UserManagerUserProvider.php new file mode 100644 index 00000000..7685d647 --- /dev/null +++ b/lib/UserManagerUserProvider.php @@ -0,0 +1,85 @@ +userManager = $userManager; + } + + public function getAllUsers() + { + if (is_null(self::$cache)) { + $result = []; + foreach ($this->userManager->search('') as $user) { + if ($user->isEnabled()) { + $result[] = new User($user->getUID(), $user->getDisplayName(), $user); + } + } + + self::$cache = $result; + } + return self::$cache; + } + + public function hasUser(User $user) + { + return !is_null($this->userManager->get($user->getUid())); + } + + public function hasUserByUID($uid) + { + return !is_null($this->userManager->get($uid)); + } + + public function getAllUsersForUser(User $user) + { + // since we don't have access to the ContactsStore, we don't apply the enhancement privacy rules. + return $this->getAllUsers(); + } + + public function getAllUsersForUserByUID($uid) + { + // since we don't have access to the ContactsStore, we don't apply the enhancement privacy rules. + return $this->getAllUsers(); + } + + public function hasUserForUser(User $user1, User $user2) + { + // since we don't have access to the ContactsStore, we don't apply the enhancement privacy rules. + $this->hasUser($user2); + } + + public function hasUserForUserByUID($uid1, $uid2) + { + // since we don't have access to the ContactsStore, we don't apply the enhancement privacy rules. + $this->hasUserByUID($uid2); + } + + public function isUserExcluded($userId) + { + // to limit inconsistency we only support the settings in NC > 13.0.0 + return false; + } +} diff --git a/lib/command/refreshroster.php b/lib/command/refreshroster.php index e11c7836..77266705 100644 --- a/lib/command/refreshroster.php +++ b/lib/command/refreshroster.php @@ -2,6 +2,7 @@ namespace OCA\OJSXC\Command; +use OCA\OJSXC\Db\PresenceMapper; use OCA\OJSXC\RosterPush; use OCP\IUserManager; use Symfony\Component\Console\Command\Command; @@ -22,13 +23,20 @@ class RefreshRoster extends Command */ private $rosterPush; + /** + * @var PresenceMapper + */ + private $presenceMapper; + public function __construct( IUserManager $userManager, - RosterPush $rosterPush + RosterPush $rosterPush, + PresenceMapper $presenceMapper ) { parent::__construct(); $this->userManager = $userManager; $this->rosterPush = $rosterPush; + $this->presenceMapper = $presenceMapper; } protected function configure() diff --git a/lib/db/presencemapper.php b/lib/db/presencemapper.php index adc4831c..a55bc1fe 100644 --- a/lib/db/presencemapper.php +++ b/lib/db/presencemapper.php @@ -3,6 +3,7 @@ namespace OCA\OJSXC\Db; use OCA\OJSXC\Db\Presence as PresenceEntity; +use OCA\OJSXC\IUserProvider; use OCA\OJSXC\NewContentContainer; use OCP\AppFramework\Db\Mapper; use OCP\IDBConnection; @@ -58,7 +59,13 @@ class PresenceMapper extends Mapper /** * @var null|string the userId of the current user */ - private $userId; + private $userIdPresenceMapperPresenceMapperPresenceMapper; + + + /** + * @var IUserProvider + */ + private $userProvider; /** * PresenceMapper constructor. @@ -69,8 +76,9 @@ class PresenceMapper extends Mapper * @param MessageMapper $messageMapper * @param NewContentContainer $newContentContainer * @param int $timeout + * @param IUserProvider $userProvider */ - public function __construct(IDBConnection $db, $host, $userId, MessageMapper $messageMapper, NewContentContainer $newContentContainer, $timeout) + public function __construct(IDBConnection $db, $host, $userId, MessageMapper $messageMapper, NewContentContainer $newContentContainer, $timeout, IUserProvider $userProvider) { parent::__construct($db, 'ojsxc_presence'); $this->host = $host; @@ -78,6 +86,7 @@ public function __construct(IDBConnection $db, $host, $userId, MessageMapper $me $this->messageMapper = $messageMapper; $this->newContentContainer = $newContentContainer; $this->timeout = $timeout; + $this->userProvider = $userProvider; } /** @@ -136,6 +145,9 @@ public function getConnectedUsers() $stmt = $this->execute("SELECT `userid` FROM `*PREFIX*ojsxc_presence` WHERE `presence` != 'unavailable' AND `userid` != ?", [$this->userId]); $results = []; while ($row = $stmt->fetch()) { + if (!$this->userProvider->hasUserByUID($row['userid'])) { + continue; + } $results[] = $row['userid']; } $stmt->closeCursor(); diff --git a/lib/hooks.php b/lib/hooks.php index c9ecba55..164207d1 100644 --- a/lib/hooks.php +++ b/lib/hooks.php @@ -2,8 +2,11 @@ namespace OCA\OJSXC; +use OCA\OJSXC\AppInfo\Application; use OCA\OJSXC\Db\PresenceMapper; use OCA\OJSXC\Db\StanzaMapper; +use OCP\IGroup; +use OCP\IGroupManager; use OCP\IUserManager; use OCP\IUser; @@ -32,18 +35,30 @@ class Hooks */ private $stanzaMapper; + /** + * @var RosterPush + */ + private $rosterPush; + + /** + * @var IGroupManager + */ + private $groupManager; + public function __construct( IUserManager $userManager, IUserSession $userSession, RosterPush $rosterPush, PresenceMapper $presenceMapper, - StanzaMapper $stanzaMapper + StanzaMapper $stanzaMapper, + IGroupManager $groupManager ) { $this->userManager = $userManager; $this->userSession = $userSession; $this->rosterPush = $rosterPush; $this->presenceMapper = $presenceMapper; $this->stanzaMapper = $stanzaMapper; + $this->groupManager = $groupManager; } public function register() @@ -51,6 +66,8 @@ public function register() $this->userManager->listen('\OC\User', 'postCreateUser', [$this, 'onCreateUser']); $this->userManager->listen('\OC\User', 'postDelete', [$this, 'onDeleteUser']); $this->userSession->listen('\OC\User', 'changeUser', [$this, 'onChangeUser']); + $this->groupManager->listen('\OC\Group', 'postAddUser', [$this, 'onAddUserToGroup']); + $this->groupManager->listen('\OC\Group', 'postRemoveUser', [$this, 'onRemoveUserFromGroup']); } /** @@ -112,4 +129,18 @@ public function onChangeUser(IUser $user, $feature, $value) $this->onCreateUser($user, ''); } } + + public function onAddUserToGroup(IGroup $group, IUser $user) + { + $this->rosterPush->createOrUpdateRosterItem($user); + $this->rosterPush->addUserToGroup($user, $group); + } + + public function onRemoveUserFromGroup(IGroup $group, IUser $user) + { + if (Application::contactsStoreApiSupported()) { + $this->rosterPush->removeRosterItemForUsersInGroup($group, $user->getUID()); + } + $this->rosterPush->removeUserFromGroup($user, $group); + } } diff --git a/lib/http/xmppresponse.php b/lib/http/xmppresponse.php index 349016f0..8680bd7b 100644 --- a/lib/http/xmppresponse.php +++ b/lib/http/xmppresponse.php @@ -60,4 +60,17 @@ public function render() $this->writer->endElement(); return $this->writer->outputMemory(); } + + /** + * Terminates the Chat connection with the `x-nc-not_allowed_to_chat` condition. + */ + public function terminate() + { + $this->writer = new Writer(); + $this->writer->openMemory(); + $this->writer->startElement('body'); + $this->writer->writeAttribute('xmlns', 'http://jabber.org/protocol/httpbind'); + $this->writer->writeAttribute('type', 'terminate'); + $this->writer->writeAttribute('condition', 'x-nc-not_allowed_to_chat'); + } } diff --git a/lib/rosterpush.php b/lib/rosterpush.php index d9c47764..e019f61a 100644 --- a/lib/rosterpush.php +++ b/lib/rosterpush.php @@ -5,6 +5,7 @@ use OCA\OJSXC\Db\IQRosterPush; use OCA\OJSXC\Db\IQRosterPushMapper; use OCP\IDBConnection; +use OCP\IGroup; use OCP\IUserManager; use OCP\IUser; @@ -35,18 +36,35 @@ class RosterPush */ private $db; + /** + * @var IUserProvider + */ + private $userProvider; + + /** + * RosterPush constructor. + * + * @param IUserManager $userManager + * @param IUserSession $userSession + * @param string $host + * @param IQRosterPushMapper $iqRosterPushMapper + * @param IDBConnection $db + * @param IUserProvider $userProvider + */ public function __construct( IUserManager $userManager, IUserSession $userSession, $host, IQRosterPushMapper $iqRosterPushMapper, - IDbConnection $db + IDbConnection $db, + IUserProvider $userProvider ) { $this->userManager = $userManager; $this->userSession = $userSession; $this->host = $host; $this->iqRosterPushMapper = $iqRosterPushMapper; $this->db = $db; + $this->userProvider = $userProvider; } /** @@ -62,7 +80,7 @@ public function createOrUpdateRosterItem(IUser $user) $iq->setFrom(''); - foreach ($this->userManager->search('') as $recipient) { + foreach ($this->userProvider->getAllUsersForUserByUID($user->getUID()) as $recipient) { if ($recipient->getUID() !== $user->getUID()) { $iq->setTo($recipient->getUID()); $this->iqRosterPushMapper->insert($iq); @@ -139,4 +157,67 @@ public function refreshRoster() return $stats; } + + /** + * When a user is removed from a group, the roster items for the $userId must be removed for all users in the $group + * but only if $userId isn't accessible anymore for a user in $group. + * + * @param IGroup $group + * @param string $userId the user which is removed + */ + public function removeRosterItemForUsersInGroup(IGroup $group, $userId) + { + $iq = new IQRosterPush(); + $iq->setJid($userId); + $iq->setSubscription('remove'); + $iq->setFrom(''); + + + foreach ($group->getUsers() as $recipient) { + // check if $recipient can still chat with $userId + // if not -> remove $userId from $recipient's roster. + if ($recipient->getUID() !== $userId && !$this->userProvider->hasUserForUserByUID($recipient->getUID(), $userId)) { + $iq->setTo($recipient->getUID()); + $this->iqRosterPushMapper->insert($iq); + } + } + } + + /** + * When a user is added to a group, this user should get a rosterPush for all users in this group + * + * @param IUser $receiver + * @param IGroup $group + */ + public function addUserToGroup(IUser $receiver, IGroup $group) + { + $iq = new IQRosterPush(); + $iq->setSubscription('both'); + $iq->setFrom(''); + $iq->setTo($receiver->getUID()); + foreach ($group->getUsers() as $user) { + $iq->setJid($user->getUID()); + $iq->setName($user->getDisplayName()); + $this->iqRosterPushMapper->insert($iq); + } + } + + /** + * When a user is removed from a group, this user should get a rosterPush for all users in this group + * + * @param IUser $receiver + * @param IGroup $group + */ + public function removeUserFromGroup(IUser $receiver, IGroup $group) + { + $iq = new IQRosterPush(); + $iq->setSubscription('remove'); + $iq->setFrom(''); + $iq->setTo($receiver->getUID()); + foreach ($group->getUsers() as $user) { + $iq->setJid($user->getUID()); + $iq->setName($user->getDisplayName()); + $this->iqRosterPushMapper->insert($iq); + } + } } diff --git a/lib/stanzahandlers/iq.php b/lib/stanzahandlers/iq.php index 9d36cc66..fd5d3577 100644 --- a/lib/stanzahandlers/iq.php +++ b/lib/stanzahandlers/iq.php @@ -3,6 +3,9 @@ namespace OCA\OJSXC\StanzaHandlers; use OCA\OJSXC\Db\IQRoster; +use OCA\OJSXC\Exceptions\TerminateException; +use OCA\OJSXC\IUserProvider; +use OCA\OJSXC\NewContentContainer; use OCP\IConfig; use OCP\IUserManager; use Sabre\Xml\Reader; @@ -27,6 +30,11 @@ class IQ extends StanzaHandler */ private $config; + /** + * @var IUserProvider + */ + private $userProvider; + /** * IQ constructor. * @@ -34,18 +42,21 @@ class IQ extends StanzaHandler * @param string $host * @param IUserManager $userManager * @param IConfig $config + * @param IUserProvider $userProvider */ - public function __construct($userId, $host, IUserManager $userManager, IConfig $config) + public function __construct($userId, $host, IUserManager $userManager, IConfig $config, IUserProvider $userProvider) { parent::__construct($userId, $host); $this->userManager = $userManager; $this->config = $config; + $this->userProvider = $userProvider; } /** * @param array $stanza * @return IQRoster + * @throws TerminateException */ public function handle(array $stanza) { @@ -54,16 +65,21 @@ public function handle(array $stanza) // if in debug mode we show the own username in the roster for testing $debugMode = $this->config->getSystemValue("debug"); - if ($stanza['value'][0]['name'] === '{jabber:iq:roster}query') { + if ($stanza['value'][0]['name'] === '{http://jabber.org/protocol/disco#items}query' || $stanza['value'][0]['name'] === '{http://jabber.org/protocol/disco#info}query') { + // the disco queries are currently not implemented but these are the first stanzas send to the server so + // they are ideal to terminate the connection if a user is excluded from chatting. + if ($this->userProvider->isUserExcluded($this->userId)) { + throw new TerminateException(); + } + } elseif ($stanza['value'][0]['name'] === '{jabber:iq:roster}query') { $id = $stanza['attributes']['id']; $iqRoster = new IQRoster(); $iqRoster->setType('result'); $iqRoster->setTo($this->userId); $iqRoster->setQid($id); - foreach ($this->userManager->search('') as $user) { - $userId = Application::santizeUserId($user->getUID()); - if ($debugMode || ($userId !== $this->userId && $user->isEnabled())) { - $iqRoster->addItem($userId . '@' . $this->host, $user->getDisplayName()); + foreach ($this->userProvider->getAllUsers() as $user) { + if ($debugMode || $user->getUID() !== $this->userId) { + $iqRoster->addItem($user->getUID() . '@' . $this->host, $user->getFullName()); } } return $iqRoster; diff --git a/lib/stanzahandlers/message.php b/lib/stanzahandlers/message.php index d3c5727f..6ce6bb04 100644 --- a/lib/stanzahandlers/message.php +++ b/lib/stanzahandlers/message.php @@ -3,8 +3,8 @@ namespace OCA\OJSXC\StanzaHandlers; use OCA\OJSXC\Db\MessageMapper; -use Sabre\Xml\Reader; -use Sabre\Xml\Writer; +use OCA\OJSXC\IUserProvider; +use OCP\ILogger; use OCA\OJSXC\Db\Message as MessageEntity; /** @@ -20,6 +20,11 @@ class Message extends StanzaHandler */ private $messageMapper; + /** + * @var IUserProvider $userProvider + */ + private $userProvider; + /** * @var string $type */ @@ -35,17 +40,25 @@ class Message extends StanzaHandler */ private $msgId; + /** + * @var ILogger $logger + */ + private $logger; + /** * Message constructor. * * @param string $userId * @param string $host * @param MessageMapper $messageMapper + * @param IUserProvider $userProvider */ - public function __construct($userId, $host, MessageMapper $messageMapper) + public function __construct($userId, $host, MessageMapper $messageMapper, IUserProvider $userProvider, ILogger $logger) { parent::__construct($userId, $host); $this->messageMapper = $messageMapper; + $this->userProvider = $userProvider; + $this->logger = $logger; } /** @@ -56,10 +69,16 @@ public function handle(array $stanza) $to = $this->getAttribute($stanza, 'to'); $pos = strrpos($to, '@'); $this->to = substr($to, 0, $pos); + + if (!$this->userProvider->hasUserByUID($this->to)) { + $this->logger->warning('User ' . $this->userId . ' is trying to send a message to ' . $this->to . ' but this isn\'t allowed'); + return; + } + foreach ($stanza['value'] as $keyRaw => $value) { // remove namespace from key as it is unneeded and cause problems $key = substr($keyRaw, strpos($keyRaw, '}') + 1, strlen($keyRaw)); - // fetch namespace from key to readd it + // fetch namespace from key to read it $ns = substr($keyRaw, 1, strpos($keyRaw, '}') - 1); $this->values[] = [ diff --git a/lib/stanzahandlers/presence.php b/lib/stanzahandlers/presence.php index 97a49c27..efbfd945 100644 --- a/lib/stanzahandlers/presence.php +++ b/lib/stanzahandlers/presence.php @@ -4,6 +4,7 @@ use OCA\OJSXC\Db\MessageMapper; use OCA\OJSXC\Db\PresenceMapper; +use OCA\OJSXC\Exceptions\TerminateException; use Sabre\Xml\Reader; use Sabre\Xml\Writer; use OCA\OJSXC\Db\Presence as PresenceEntity; @@ -47,11 +48,14 @@ public function __construct($userId, $host, PresenceMapper $presenceMapper, Mess * - update the presence in the database * - broadcast the presence * - return the active presence if the type isn't equal to unavailable + * * @param PresenceEntity $presence * @return PresenceEntity[] + * @throws TerminateException */ public function handle(PresenceEntity $presence) { + // update the presence $this->presenceMapper->setPresence($presence); diff --git a/phpunit.integration.xml b/phpunit.integration.xml index 6d99d054..07fb64ef 100644 --- a/phpunit.integration.xml +++ b/phpunit.integration.xml @@ -13,6 +13,10 @@ lib/db lib/dblock.php lib/memlock.php + lib/User.php + lib/ContactsStoreUserProvider.php + lib/UserManagerUserProvider.php + lib/rosterpush.php - \ No newline at end of file + diff --git a/tests/integration/ContactsStoreUserProviderTest.php b/tests/integration/ContactsStoreUserProviderTest.php new file mode 100644 index 00000000..30c2dfe2 --- /dev/null +++ b/tests/integration/ContactsStoreUserProviderTest.php @@ -0,0 +1,281 @@ +markTestSkipped(); + return; + } + $this->config = \OC::$server->getConfig(); + $this->config->setAppValue('core', 'shareapi_only_share_with_group_members', 'no'); + foreach (\OC::$server->getUserManager()->search('') as $user) { + $user->delete(); + } + + $users[] = \OC::$server->getUserManager()->createUser('admin', 'admin'); + $users[] = \OC::$server->getUserManager()->createUser('derp', 'derp'); + $users[] = \OC::$server->getUserManager()->createUser('derpina', 'derpina'); + $users[] = \OC::$server->getUserManager()->createUser('herp', 'herp'); + $users[] = \OC::$server->getUserManager()->createUser('foo', 'foo'); + + $currentUser = \OC::$server->getUserManager()->createUser('autotest', 'autotest'); + $this->userSession = \OC::$server->getUserSession(); + $this->userSession->setUser($currentUser); + $this->userManager = \OC::$server->getUserManager(); + $this->groupManager = \OC::$server->getGroupManager(); + $this->contactsStore = \OC::$server->query(ContactsStore::class); + $this->contactsManager = \OC::$server->getContactsManager(); + + /** @var \OCA\DAV\CardDAV\SyncService $syncService */ + $syncService = \OC::$server->query('CardDAVSyncService'); + $syncService->getLocalSystemAddressBook(); + $syncService->updateUser($currentUser); + + + $davApp = new DavApp(); + + $this->cardDavBackend = $davApp->getContainer()->query(CardDavBackend::class); + + // create some contacts + $vCard = new VCard(); + $vCard->VERSION = '3.0'; + $vCard->UID = 'Test1'; + $vCard->FN = 'Test1'; + + $id = $this->setupAddressBook('autotest'); + $this->cardDavBackend->createCard($id, 'Alice.Test1.vcf', $vCard->serialize()); + + foreach ($users as $user) { + $syncService->updateUser($user); + } + + $davApp->setupSystemContactsProvider($this->contactsManager); + \OC_User::setIncognitoMode(false); + \OC::$server->getDatabaseConnection()->executeQuery("DELETE FROM *PREFIX*ojsxc_stanzas"); + + + $this->contactsStoreUserProvider = new ContactsStoreUserProvider( + $this->contactsStore, + $this->userSession, + $this->userManager, + $this->groupManager, + $this->config + ); + } + + private function setupAddressBook($userId) + { + $addressBooks = $this->cardDavBackend->getAddressBooksForUser("principals/users/$userId"); + foreach ($addressBooks as $addressBookInfo) { + $this->cardDavBackend->deleteAddressBook($addressBookInfo['id']); + } + $addressBookId = $this->cardDavBackend->createAddressBook('principals/users/' . $userId, 'principals/users/' . $userId, []); + + $addressBooks = $this->cardDavBackend->getAddressBooksForUser("principals/users/$userId"); + + foreach ($addressBooks as $addressBookInfo) { + $addressBook = new \OCA\DAV\CardDAV\AddressBook($this->cardDavBackend, $addressBookInfo, \OC::$server->getL10N('dav')); + $this->contactsManager->registerAddressBook( + new AddressBookImpl( + $addressBook, + $addressBookInfo, + $this->cardDavBackend, + \OC::$server->getURLGenerator() + ) + ); + } + + return $addressBookId; + } + + protected function tearDown() + { + $config = \OC::$server->getConfig(); + $config->setAppValue('core', 'shareapi_only_share_with_group_members', 'no'); + $config->setAppValue('core', 'shareapi_exclude_groups', 'no'); + $config->setAppValue('core', 'shareapi_exclude_groups_list', json_encode([])); + foreach (\OC::$server->getUserManager()->search('') as $user) { + $user->delete(); + } + } + + public function testNormalSituation() + { + + // no special settings set + $derp = new User('derp', 'derp', $this->contactsStore->findOne($this->userManager->get('autotest'), 6, 'derp')); + $derpina = new User('derpina', 'derpina', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'derpina')[0]); + $herp = new User('herp', 'herp', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'herp')[0]); + $foo = new User('foo', 'foo', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'foo')[0]); + $admin = new User('admin', 'admin', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'admin')[0]); + $autotest = new User('autotest', 'autotest', $this->contactsStore->getContacts($this->userManager->get('derpina'), 'autotest')[0]); + + $expected = [ + $foo, + $admin, + $derp, + $derpina, + $herp + ]; + + $this->assertCanonicalizeEquals($expected, $this->contactsStoreUserProvider->getAllUsers()); + $this->assertCanonicalizeEquals([$autotest, $derp, $herp, $foo, $admin], $this->contactsStoreUserProvider->getAllUsersForUserByUID('derpina')); + $this->assertCanonicalizeEquals([$autotest, $derp, $herp, $foo, $admin], $this->contactsStoreUserProvider->getAllUsersForUser($derpina)); + + $this->assertTrue($this->contactsStoreUserProvider->hasUserForUserByUID('derp', 'derpina')); + $this->assertTrue($this->contactsStoreUserProvider->hasUserForUser($derp, $derpina)); + $this->assertTrue($this->contactsStoreUserProvider->hasUserByUID('derpina')); + $this->assertTrue($this->contactsStoreUserProvider->hasUser($derpina)); + $this->assertFalse($this->contactsStoreUserProvider->isUserExcluded('derpina')); + } + + public function testGroupsOnly() + { + $this->setValueOfPrivateProperty($this->contactsStoreUserProvider, 'cache', null); + $group1 = $this->groupManager->createGroup('group1'); + $group2 = $this->groupManager->createGroup('group2'); + $group1->addUser($this->userManager->get('derp')); + $group1->addUser($this->userManager->get('foo')); + $group2->addUser($this->userManager->get('derpina')); + $group2->addUser($this->userManager->get('herp')); + + $this->config->setAppValue('core', 'shareapi_only_share_with_group_members', 'yes'); + + // no special settings set + $derp = new User('derp', 'derp', $this->contactsStore->getContacts($this->userManager->get('foo'), 'derp')[0]); + $derpina = new User('derpina', 'derpina', $this->contactsStore->getContacts($this->userManager->get('herp'), 'derpina')[0]); + $herp = new User('herp', 'herp', $this->contactsStore->getContacts($this->userManager->get('derpina'), 'herp')[0]); + $foo = new User('foo', 'foo', $this->contactsStore->getContacts($this->userManager->get('derp'), 'foo')[0]); + + $this->assertCanonicalizeEquals([], $this->contactsStoreUserProvider->getAllUsers()); // running as autotest -> not in any group + $this->assertCanonicalizeEquals([$herp], $this->contactsStoreUserProvider->getAllUsersForUserByUID('derpina')); + $this->assertCanonicalizeEquals([$herp], $this->contactsStoreUserProvider->getAllUsersForUser($derpina)); + $this->assertCanonicalizeEquals([$foo], $this->contactsStoreUserProvider->getAllUsersForUserByUID('derp')); + $this->assertCanonicalizeEquals([$foo], $this->contactsStoreUserProvider->getAllUsersForUser($derp)); + + $this->assertFalse($this->contactsStoreUserProvider->hasUserForUserByUID('derp', 'derpina')); + $this->assertFalse($this->contactsStoreUserProvider->hasUserForUser($derp, $derpina)); + $this->assertFalse($this->contactsStoreUserProvider->hasUserForUserByUID('derpina', 'derp')); + $this->assertFalse($this->contactsStoreUserProvider->hasUserForUser($derpina, $derp)); + + $this->assertTrue($this->contactsStoreUserProvider->hasUserForUserByUID('derp', 'foo')); + $this->assertTrue($this->contactsStoreUserProvider->hasUserForUser($derp, $foo)); + $this->assertTrue($this->contactsStoreUserProvider->hasUserForUserByUID('foo', 'derp')); + $this->assertTrue($this->contactsStoreUserProvider->hasUserForUser($foo, $derp)); + + $this->assertFalse($this->contactsStoreUserProvider->hasUserByUID('derpina')); + $this->assertFalse($this->contactsStoreUserProvider->hasUser($derpina)); + $this->assertFalse($this->contactsStoreUserProvider->isUserExcluded('derpina')); + } + + public function testExcluded() + { + $this->setValueOfPrivateProperty($this->contactsStoreUserProvider, 'cache', null); + $groupExcluded = $this->groupManager->createGroup('excluded'); + $this->config->setAppValue('core', 'shareapi_exclude_groups', 'yes'); + $this->config->setAppValue('core', 'shareapi_exclude_groups_list', json_encode(['excluded'])); + $groupExcluded->addUser($this->userManager->get('derp')); + $groupExcluded->addUser($this->userManager->get('derpina')); + + $herp = new User('herp', 'herp', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'herp')[0]); + $foo = new User('foo', 'foo', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'foo')[0]); + $admin = new User('admin', 'admin', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'admin')[0]); + $autotest = new User('autotest', 'autotest', $this->contactsStore->getContacts($this->userManager->get('admin'), 'autotest')[0]); + + $this->assertCanonicalizeEquals([$admin, $herp, $foo], $this->contactsStoreUserProvider->getAllUsers()); + $this->assertTrue($this->contactsStoreUserProvider->isUserExcluded('derp')); + $this->assertTrue($this->contactsStoreUserProvider->isUserExcluded('derpina')); + $this->assertFalse($this->contactsStoreUserProvider->isUserExcluded('autotest')); + $this->assertFalse($this->contactsStoreUserProvider->isUserExcluded('admin')); + $this->assertFalse($this->contactsStoreUserProvider->isUserExcluded('foo')); + $this->assertFalse($this->contactsStoreUserProvider->isUserExcluded('herp')); + + $this->config->setAppValue('core', 'shareapi_exclude_groups', 'no'); + $this->config->setAppValue('core', 'shareapi_exclude_groups_list', json_encode([])); + } + + public function testDisabled() + { + $this->setValueOfPrivateProperty($this->contactsStoreUserProvider, 'cache', null); + $derpina = new User('derpina', 'derpina', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'derpina')[0]); + $herp = new User('herp', 'herp', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'herp')[0]); + $foo = new User('foo', 'foo', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'foo')[0]); + $admin = new User('admin', 'admin', $this->contactsStore->getContacts($this->userManager->get('autotest'), 'admin')[0]); + + $this->userManager->get('derp')->setEnabled(false); + + $expected = [ + $admin, + $derpina, + $herp, + $foo + ]; + + $this->assertCanonicalizeEquals($expected, $this->contactsStoreUserProvider->getAllUsers()); + } + + private function assertCanonicalizeEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $ignoreCase = false) + { + $this->assertEquals($expected, $actual, $message, $delta, $maxDepth, true, $ignoreCase); + } +} diff --git a/tests/integration/RosterPushTest.php b/tests/integration/RosterPushTest.php new file mode 100644 index 00000000..7b46b112 --- /dev/null +++ b/tests/integration/RosterPushTest.php @@ -0,0 +1,174 @@ +markTestSkipped(); + return; + } + + $this->userManager = \OC::$server->getUserManager(); + $this->groupManager = \OC::$server->getGroupManager(); + $this->userSession = \OC::$server->getUserSession(); + $this->iqRosterPushMapper = $this->getMockBuilder(IQRosterPushMapper::class)->disableOriginalConstructor()->getMock(); + $this->dbConnection = \OC::$server->getDatabaseConnection(); + $this->config = \OC::$server->getConfig(); + $this->contactsStore = $this->getMockBuilder(IContactsStore::class)->disableOriginalConstructor()->getMock(); + + $this->userProvider = new ContactsStoreUserProvider( + $this->contactsStore, + $this->userSession, + $this->userManager, + $this->groupManager, + $this->config + ); + + $this->rosterPush = new RosterPush( + $this->userManager, + $this->userSession, + 'localhost', + $this->iqRosterPushMapper, + $this->dbConnection, + $this->userProvider + ); + + foreach (\OC::$server->getUserManager()->search('') as $user) { + $user->delete(); + } + foreach (\OC::$server->getGroupManager()->search('') as $group) { + $group->delete(); + } + } + + public function testRemoveRosterItemForUsersInGroup() + { + $group1 = $this->groupManager->createGroup('group1'); + $group2 = $this->groupManager->createGroup('group2'); + $group3 = $this->groupManager->createGroup('group3'); + $user1 = $this->userManager->createUser('user1', 'user1'); + $user2 = $this->userManager->createUser('user2', 'user2'); + $user3 = $this->userManager->createUser('user3', 'user3'); + $user4 = $this->userManager->createUser('user4', 'user4'); + + $group1->addUser($user1); + $group1->addUser($user2); + $group1->addUser($user3); + $group2->addUser($user1); + $group2->addUser($user2); + $group3->addUser($user4); + + // remove $user1 from $group1 + // when no special settings are set this should result in no rosterMessages + $this->iqRosterPushMapper->expects($this->never())->method('insert'); + $this->contactsStore->expects($this->at(0)) + ->method('findOne') + ->with($user2, 0, 'user1') + ->willReturn([$user2]); + $this->contactsStore->expects($this->at(1)) + ->method('findOne') + ->with($user3, 0, 'user1') + ->willReturn([$user3]); + $this->rosterPush->removeRosterItemForUsersInGroup($group1, 'user1'); + } + public function testRemoveRosterItemForUsersInGroupOwnGroups() + { + $group1 = $this->groupManager->createGroup('group1'); + $group2 = $this->groupManager->createGroup('group2'); + $group3 = $this->groupManager->createGroup('group3'); + $user1 = $this->userManager->createUser('user1', 'user1'); + $user2 = $this->userManager->createUser('user2', 'user2'); + $user3 = $this->userManager->createUser('user3', 'user3'); + $user4 = $this->userManager->createUser('user4', 'user4'); + + $group1->addUser($user1); + $group1->addUser($user2); + $group1->addUser($user3); + $group2->addUser($user1); + $group2->addUser($user2); + $group3->addUser($user4); + + $this->config->setAppValue('core', 'shareapi_only_share_with_group_members', 'yes'); + + // remove $user1 from $group1 + // users can only chat with users in their groups + // $user2 should still be reachable by $group2 + // $user3 should be become unreachable + // for $user4 nothing changes + $this->iqRosterPushMapper->expects($this->once())->method('insert'); + + $this->contactsStore->expects($this->at(0)) + ->method('findOne') + ->with($user2, 0, 'user1') + ->willReturn([$user2]); + + $this->contactsStore->expects($this->at(1)) + ->method('findOne') + ->with($user3, 0, 'user1') + ->willReturn(null); + + $this->rosterPush->removeRosterItemForUsersInGroup($group1, 'user1'); + + $this->config->setAppValue('core', 'shareapi_only_share_with_group_members', 'no'); + } +} diff --git a/tests/integration/db/PresenceMapperTest.php b/tests/integration/db/PresenceMapperTest.php index a81cdd3f..79b8748d 100644 --- a/tests/integration/db/PresenceMapperTest.php +++ b/tests/integration/db/PresenceMapperTest.php @@ -2,9 +2,11 @@ namespace OCA\OJSXC\Db; +use OCA\OJSXC\AppInfo\Application; use OCA\OJSXC\Db\Presence as PresenceEntity; use OCA\OJSXC\NewContentContainer; use OCA\OJSXC\Utility\MapperTestUtility; +use OCA\DAV\AppInfo\Application as DavApp; $time = 0; @@ -41,6 +43,49 @@ protected function setUp() $this->setValueOfPrivateProperty($this->mapper, 'connectedUsers', []); $this->newContentContainer = $this->container->query('NewContentContainer'); $this->setValueOfPrivateProperty($this->newContentContainer, 'stanzas', []); + foreach (\OC::$server->getUserManager()->search('') as $user) { + $user->delete(); + } + } + + protected function tearDown() + { + foreach (\OC::$server->getUserManager()->search('') as $user) { + $user->delete(); + } + } + + public function setupContactsStoreAPI() + { + foreach (\OC::$server->getUserManager()->search('') as $user) { + $user->delete(); + } + + $users[] = \OC::$server->getUserManager()->createUser('admin', 'admin'); + $users[] = \OC::$server->getUserManager()->createUser('derp', 'derp'); + $users[] = \OC::$server->getUserManager()->createUser('derpina', 'derpina'); + $users[] = \OC::$server->getUserManager()->createUser('herp', 'herp'); + $users[] = \OC::$server->getUserManager()->createUser('foo', 'foo'); + + $currentUser = \OC::$server->getUserManager()->createUser('autotest', 'autotest'); + \OC::$server->getUserSession()->setUser($currentUser); + + if (Application::contactsStoreApiSupported()) { + /** @var \OCA\DAV\CardDAV\SyncService $syncService */ + $syncService = \OC::$server->query('CardDAVSyncService'); + $syncService->getLocalSystemAddressBook(); + $syncService->updateUser($currentUser); + + foreach ($users as $user) { + $syncService->updateUser($user); + } + + $cm = \OC::$server->getContactsManager(); + $davApp = new DavApp(); + $davApp->setupSystemContactsProvider($cm); + } + \OC_User::setIncognitoMode(false); + \OC::$server->getDatabaseConnection()->executeQuery("DELETE FROM *PREFIX*ojsxc_stanzas"); } /** @@ -223,7 +268,7 @@ public function getPresenceProvider() ] ]; } - + /** * @dataProvider getPresenceProvider * @param $inputs @@ -285,6 +330,7 @@ public function getConnectedUsersProvider() */ public function testGetConnectedUsers($inputs, $expected) { + $this->setupContactsStoreAPI(); foreach ($inputs as $input) { $this->mapper->setPresence($input); } @@ -297,6 +343,55 @@ public function testGetConnectedUsers($inputs, $expected) $this->assertEquals($expected, $result); } + public function testGetConnectedUsersIfUserHasNot() + { + $this->setValueOfPrivateProperty($this->mapper, 'connectedUsers', []); + $this->setupContactsStoreAPI(); + if (!Application::contactsStoreApiSupported()) { + $this->markTestSkipped(); + } + + $group = \OC::$server->getGroupManager()->createGroup('group1'); + $group->addUser(\OC::$server->getUserManager()->get('derp')); + + $group2 = \OC::$server->getGroupManager()->createGroup('group2'); + $group2->addUser(\OC::$server->getUserManager()->get('autotest')); + $group2->addUser(\OC::$server->getUserManager()->get('foo')); + $group2->addUser(\OC::$server->getUserManager()->get('admin')); + + \OC::$server->getConfig()->setAppValue('core', 'shareapi_only_share_with_group_members', 'yes'); + + $input1 = new PresenceEntity(); + $input1->setPresence('online'); + $input1->setUserid('foo'); + $input1->setLastActive(23434475); + + $input2 = new PresenceEntity(); + $input2->setPresence('online'); + $input2->setUserid('derp'); + $input2->setLastActive(23434475); + + $this->mapper->setPresence($input1); + $this->mapper->setPresence($input2); + + $expected = ['foo']; + + $result = $this->mapper->getConnectedUsers(); + + $this->assertCount(count($expected), $result); + sort($expected); + sort($result); + $this->assertEquals($expected, $result); + + \OC::$server->getConfig()->setAppValue('core', 'shareapi_only_share_with_group_members', 'no'); + + $group->removeUser(\OC::$server->getUserManager()->get('derp')); + $group->delete(); + $group2->removeUser(\OC::$server->getUserManager()->get('autotest')); + $group2->removeUser(\OC::$server->getUserManager()->get('admin')); + $group2->delete(); + } + public function updatePresenceProvider() { $input1 = new PresenceEntity(); @@ -384,6 +479,7 @@ public function updatePresenceProvider() */ public function testUpdatePresence($inputs, $expInput, $expConnectedUsers, $expNewContent, $expNewContentCount, $expStanzasToSend) { + $this->setupContactsStoreAPI(); global $time; $time = 1000; foreach ($inputs as $input) { diff --git a/tests/unit/HooksTest.php b/tests/unit/HooksTest.php index d8616a8a..2c67ed88 100644 --- a/tests/unit/HooksTest.php +++ b/tests/unit/HooksTest.php @@ -3,9 +3,12 @@ namespace OCA\OJSXC; +use OCA\OJSXC\AppInfo\Application; use OCA\OJSXC\Db\Presence; use OCA\OJSXC\Db\PresenceMapper; use OCA\OJSXC\Db\StanzaMapper; +use OCP\IGroup; +use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use PHPUnit_Framework_MockObject_MockObject; @@ -44,6 +47,11 @@ class HooksTest extends TestCase */ private $stanzaMapper; + /** + * @var PHPUnit_Framework_MockObject_MockObject | \OCP\IGroupManager + */ + private $groupManager; + public function setUp() { $this->userManager = $this->getMockBuilder('OCP\IUserManager')->setMethods(['listen', 'registerBackend', 'getBackends', 'removeBackend', 'clearBackends', 'get', 'userExists', 'checkPassword', 'search', 'searchDisplayName', 'createUser', 'createUserFromBackend', 'countUsers', 'callForAllUsers', 'countDisabledUsers', 'countSeenUsers', 'callForSeenUsers', 'getByEmail'])->getMock(); @@ -57,12 +65,15 @@ public function setUp() $this->stanzaMapper = $this->getMockBuilder('OCA\OJSXC\Db\StanzaMapper')->disableOriginalConstructor()->getMock(); + $this->groupManager = $this->getMockBuilder('OCP\IGroupManager')->disableOriginalConstructor()->setMethods(['listen', 'isBackendUsed', 'addBackend', 'clearBackends', 'get', 'groupExists', 'createGroup', 'search', 'getUserGroups', 'getUserGroupIds', 'displayNamesInGroup', 'isAdmin', 'isInGroup', 'getBackends'])->getMock(); + $this->hooks = new Hooks( $this->userManager, $this->userSession, $this->rosterPush, $this->presenceMapper, - $this->stanzaMapper + $this->stanzaMapper, + $this->groupManager ); } @@ -157,4 +168,30 @@ public function testOnChangeUserDisplayName() $hooks->onChangeUser($user, 'displayName', 'abc'); } + + public function testOnAddUserToGroup() + { + $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); + $group = $this->getMockBuilder(IGroup::class)->disableOriginalConstructor()->getMock(); + + $this->rosterPush->expects($this->once())->method('createOrUpdateRosterItem')->with($user); + $this->rosterPush->expects($this->once())->method('addUserToGroup')->with($user, $group); + + $this->hooks->onAddUserToGroup($group, $user); + } + + public function testOnRemoveUserFromGroup() + { + $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); + $group = $this->getMockBuilder(IGroup::class)->disableOriginalConstructor()->getMock(); + + if (Application::contactsStoreApiSupported()) { + $user->expects($this->once())->method('getUID')->willReturn('uid1'); + $this->rosterPush->expects($this->once())->method('removeRosterItemForUsersInGroup')->with($group, 'uid1'); + } + + $this->rosterPush->expects($this->once())->method('removeUserFromGroup')->with($user, $group); + + $this->hooks->onRemoveUserFromGroup($group, $user); + } } diff --git a/tests/unit/NewContentContainerTest.php b/tests/unit/NewContentContainerTest.php index 6ee637f9..69df6277 100644 --- a/tests/unit/NewContentContainerTest.php +++ b/tests/unit/NewContentContainerTest.php @@ -20,7 +20,7 @@ public function setUp() $this->newContentContainer = new NewContentContainer(); } - public function testProvider() + public function datatestProvider() { $stanza1 = new Stanza(); $stanza1->setFrom('test@own.dev'); @@ -40,7 +40,7 @@ public function testProvider() } /** - * @dataProvider testProvider + * @dataProvider datatestProvider */ public function test($stanzas, $count) { diff --git a/tests/unit/RosterPushTest.php b/tests/unit/RosterPushTest.php index 4c45914d..48ed08d0 100644 --- a/tests/unit/RosterPushTest.php +++ b/tests/unit/RosterPushTest.php @@ -5,6 +5,7 @@ use OCA\OJSXC\Db\IQRosterPush; use OCA\OJSXC\Db\IQRosterPushMapper; use OCP\IDBConnection; +use OCP\IGroup; use OCP\IUserManager; use OCP\IUserSession; use PHPUnit\Framework\TestCase; @@ -37,6 +38,11 @@ class RosterPushTest extends TestCase */ private $db; + /** + * @var \PHPUnit_Framework_MockObject_MockObject | IUserProvider + */ + private $userProvider; + public function setUp() { $this->userManager = $this->getMockBuilder('OCP\IUserManager') @@ -51,12 +57,15 @@ public function setUp() $this->db = $this->getMockBuilder('OCP\IDbConnection') ->disableOriginalConstructor()->getMock(); + $this->userProvider = $this->getMockBuilder('OCA\OJSXC\IUserProvider')->disableOriginalConstructor()->getMock(); + $this->rosterPush = new RosterPush( $this->userManager, $this->userSession, 'localhost', $this->iqRosterPushMapper, - $this->db + $this->db, + $this->userProvider ); } @@ -65,7 +74,7 @@ public function testRefreshRoster() /** @var \PHPUnit_Framework_MockObject_MockObject | RosterPush $rosterPush */ $rosterPush = $this->getMockBuilder('OCA\OJSXC\RosterPush') - ->setConstructorArgs([$this->userManager, $this->userSession, 'host', $this->iqRosterPushMapper, $this->db]) + ->setConstructorArgs([$this->userManager, $this->userSession, 'host', $this->iqRosterPushMapper, $this->db, $this->userProvider]) ->setMethods(['createOrUpdateRosterItem', 'removeRosterItem'])->getMock(); $user1 = $this->getMockBuilder('OCP\IUser')->getMock(); @@ -140,7 +149,7 @@ public function testRefreshRosterThrowsDuringRemove() /** @var \PHPUnit_Framework_MockObject_MockObject | RosterPush $rosterPush */ $rosterPush = $this->getMockBuilder('OCA\OJSXC\RosterPush') - ->setConstructorArgs([$this->userManager, $this->userSession, 'host', $this->iqRosterPushMapper, $this->db]) + ->setConstructorArgs([$this->userManager, $this->userSession, 'host', $this->iqRosterPushMapper, $this->db, $this->userProvider]) ->setMethods(['createOrUpdateRosterItem', 'removeRosterItem'])->getMock(); $user1 = $this->getMockBuilder('OCP\IUser')->getMock(); @@ -218,7 +227,7 @@ public function testRemoveRosterItem() public function testCreateOrUpdateRosterItem() { $user1 = $this->getMockBuilder('OCP\IUser')->getMock(); - $user1->expects($this->exactly(5)) + $user1->expects($this->exactly(6)) ->method('getUID') ->willReturn('user1'); $user2 = $this->getMockBuilder('OCP\IUser')->getMock(); @@ -230,8 +239,8 @@ public function testCreateOrUpdateRosterItem() ->method('getUID') ->willReturn('user3'); - $this->userManager->expects($this->once()) - ->method('search') + $this->userProvider->expects($this->once()) + ->method('getAllUsersForUserByUID') ->willReturn([$user1, $user2, $user3]); $stanza1 = new IQRosterPush(); @@ -256,4 +265,6 @@ public function testCreateOrUpdateRosterItem() $this->rosterPush->createOrUpdateRosterItem($user1); } + + // removeRosterItemForUsersInGroup, addUserToGroup and removeUserFromGroup covered by integration tests } diff --git a/tests/unit/UserTest.php b/tests/unit/UserTest.php new file mode 100644 index 00000000..ae77bbeb --- /dev/null +++ b/tests/unit/UserTest.php @@ -0,0 +1,20 @@ +assertEquals($user1->getFullName(), 'Test123'); + $this->assertEquals($user1->getUid(), '_ojsxc_esc_space_test_ojsxc_esc_space__ojsxc_esc_at__ojsxc_esc_space__ojsxc_squote_space_abc'); + $user1->setUid('test1'); + $user1->setFullName('test2'); + $this->assertEquals($user1->getUid(), 'test1'); + $this->assertEquals($user1->getFullName(), 'test2'); + } +} diff --git a/tests/unit/controller/HttpBindControllerTest.php b/tests/unit/controller/HttpBindControllerTest.php index 6d08c75d..03451320 100644 --- a/tests/unit/controller/HttpBindControllerTest.php +++ b/tests/unit/controller/HttpBindControllerTest.php @@ -1,12 +1,11 @@ assertEquals($expResponse, $response); $this->assertEquals($expResponse->render(), $response->render()); } + + + public function testTerminateException() + { + $ex = new TerminateException(); + + $body = ' + + '; + $this->setUpController($body); + $this->mockLock(); + + $this->iqHandler->expects($this->once()) + ->method('handle') + ->will($this->throwException($ex)); + + $expResponse = new XMPPResponse($this->stanzaLogger); + $expResponse->terminate(); + + $response = $this->controller->index(); + + $this->assertEquals($expResponse, $response); + $this->assertEquals($expResponse->render(), $response->render()); + } } diff --git a/tests/unit/stanzahandlers/IQTest.php b/tests/unit/stanzahandlers/IQTest.php index f0931774..7aabd81b 100644 --- a/tests/unit/stanzahandlers/IQTest.php +++ b/tests/unit/stanzahandlers/IQTest.php @@ -3,8 +3,12 @@ namespace OCA\OJSXC\StanzaHandlers; use OCA\OJSXC\Db\IQRoster; +use OCA\OJSXC\Exceptions\TerminateException; +use OCA\OJSXC\IUserProvider; +use OCA\OJSXC\User; use OCP\IConfig; use PHPUnit\Framework\TestCase; +use OCP\IUserManager; use PHPUnit_Framework_MockObject_MockObject; use PHPUnit_Framework_TestCase; @@ -17,7 +21,7 @@ class IQTest extends TestCase private $iq; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var PHPUnit_Framework_MockObject_MockObject | IUserManager */ private $userManager; @@ -36,44 +40,42 @@ class IQTest extends TestCase */ private $config; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | IUserProvider + */ + private $userProvider; + public function setUp() { $this->host = 'localhost'; $this->userId = 'john'; $this->userManager = $this->getMockBuilder('OCP\IUserManager')->disableOriginalConstructor()->getMock(); $this->config = $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(); - $this->iq = new IQ($this->userId, $this->host, $this->userManager, $this->config); + $this->userProvider = $this->getMockBuilder('OCA\OJSXC\IUserProvider')->disableOriginalConstructor()->getMock(); + $this->iq = new IQ($this->userId, $this->host, $this->userManager, $this->config, $this->userProvider); } public function iqRosterProvider() { - $user1 = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); + $user1 = $this->getMockBuilder(User::class)->disableOriginalConstructor()->getMock(); $user1->expects($this->any()) ->method('getUID') ->will($this->returnValue('john')); $user1->expects($this->any()) - ->method('getDisplayName') + ->method('getFullName') ->will($this->returnValue('John')); - $user1->expects($this->any()) - ->method('isEnabled') - ->will($this->returnValue(true)); - - $user2 = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); + $user2 = $this->getMockBuilder(User::class)->disableOriginalConstructor()->getMock(); $user2->expects($this->any()) ->method('getUID') ->will($this->returnValue('richard')); $user2->expects($this->any()) - ->method('getDisplayName') + ->method('getFullName') ->will($this->returnValue('Richard')); - $user2->expects($this->any()) - ->method('isEnabled') - ->will($this->returnValue(true)); - - $expected1 = new IQRoster(); $expected1->setType('result'); $expected1->setTo('john'); @@ -167,9 +169,8 @@ public function testIqRoster(array $stanza, array $users, $searchCount, $expecte ->with('debug') ->will($this->returnValue(false)); - $this->userManager->expects($searchCount) - ->method('search') - ->with('') + $this->userProvider->expects($searchCount) + ->method('getAllUsers') ->will($this->returnValue($users)); $result = $this->iq->handle($stanza); @@ -187,76 +188,46 @@ public function testIqRoster(array $stanza, array $users, $searchCount, $expecte } } - public function testIqRosterWithDisabledUsers() + public function testTerminateExceptionDiscoItems() { - $user1 = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); - $user1->expects($this->any()) - ->method('getUID') - ->will($this->returnValue('jan')); - - $user1->expects($this->any()) - ->method('getDisplayName') - ->will($this->returnValue('Jan')); + $stanza = ['name' => '{jabber:client}iq', + 'value' => [0 => [ + 'name' => '{http://jabber.org/protocol/disco#items}query', + 'value' => null, + 'attributes' => [ + 'node' => 'undefined#undefined', + ], + ]], + ]; - $user1->expects($this->any()) - ->method('isEnabled') + $this->userProvider->expects($this->once()) + ->method('isUserExcluded') + ->with('john') ->will($this->returnValue(true)); - $user2 = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock(); - $user2->expects($this->any()) - ->method('getUID') - ->will($this->returnValue('richard')); - - $user2->expects($this->any()) - ->method('getDisplayName') - ->will($this->returnValue('Richard')); - - $user2->expects($this->any()) - ->method('isEnabled') - ->will($this->returnValue(false)); - - $expected = new IQRoster(); - $expected->setType('result'); - $expected->setTo('john'); - $expected->setQid('f9a26583-3c59-4f09-89be-964ce265fbfd:sendIQ'); - $expected->addItem('jan@localhost', 'Jan'); + $this->expectException(TerminateException::class); + $this->iq->handle($stanza); + } - $this->config->expects($this->once()) - ->method('getSystemValue') - ->with('debug') - ->will($this->returnValue(false)); + public function testTerminateExceptionDiscoInfo() + { + $stanza = ['name' => '{jabber:client}iq', + 'value' => [0 => [ + 'name' => '{http://jabber.org/protocol/disco#info}query', + 'value' => null, + 'attributes' => [ + 'node' => 'undefined#undefined', + ], + ]], + ]; - $this->userManager->expects($this->once()) - ->method('search') - ->with('') - ->will($this->returnValue([$user1, $user2])); - $result = $this->iq->handle( - [ - 'name' => '{jabber:client}iq', - 'value' => - [ - 0 => - [ - 'name' => '{jabber:iq:roster}query', - 'value' => null, - 'attributes' => [] - ] - ], - 'attributes' => - [ - 'type' => 'get', - 'id' => 'f9a26583-3c59-4f09-89be-964ce265fbfd:sendIQ', - ], - ] - ); + $this->userProvider->expects($this->once()) + ->method('isUserExcluded') + ->with('john') + ->will($this->returnValue(true)); - $this->assertEquals($expected->getFrom(), $result->getFrom()); - $this->assertEquals($expected->getId(), $result->getId()); - $this->assertEquals($expected->getItems(), $result->getItems()); - $this->assertEquals($expected->getQid(), $result->getQid()); - $this->assertEquals($expected->getTo(), $result->getTo()); - $this->assertEquals($expected->getType(), $result->getType()); - $this->assertEquals($expected->getStanza(), $result->getStanza()); + $this->expectException(TerminateException::class); + $this->iq->handle($stanza); } } diff --git a/tests/unit/stanzahandlers/MessageTest.php b/tests/unit/stanzahandlers/MessageTest.php index 36eb31aa..455636c4 100644 --- a/tests/unit/stanzahandlers/MessageTest.php +++ b/tests/unit/stanzahandlers/MessageTest.php @@ -4,6 +4,9 @@ use OCA\OJSXC\Db\Message as MessageEntity; use PHPUnit\Framework\TestCase; +use OCA\OJSXC\Db\MessageMapper; +use OCA\OJSXC\IUserProvider; +use OCP\ILogger; use PHPUnit_Framework_TestCase; use PHPUnit_Framework_MockObject_MockObject; @@ -16,7 +19,7 @@ class MessageTest extends TestCase private $message; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var PHPUnit_Framework_MockObject_MockObject | MessageMapper */ private $messageMapper; @@ -26,16 +29,28 @@ class MessageTest extends TestCase private $userId; /** - * @var string $host ; + * @var string $host */ private $host; + /** + * @var PHPUnit_Framework_MockObject_MockObject | IUserProvider + */ + private $userProvider; + + /** + * @var PHPUnit_Framework_MockObject_MockObject | ILogger + */ + private $logger; + public function setUp() { $this->host = 'localhost'; $this->userId = 'john'; $this->messageMapper = $this->getMockBuilder('OCA\OJSXC\Db\MessageMapper')->disableOriginalConstructor()->getMock(); - $this->message = new Message($this->userId, $this->host, $this->messageMapper); + $this->userProvider = $this->getMockBuilder('OCA\OJSXC\IUserProvider')->disableOriginalConstructor()->getMock(); + $this->logger = $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(); + $this->message = new Message($this->userId, $this->host, $this->messageMapper, $this->userProvider, $this->logger); } public function messageProvider() @@ -88,6 +103,38 @@ public function testMessage(array $stanza, $expected) ->method('insert') ->with($expected); + $this->userProvider->expects($this->once()) + ->method('hasUserByUID') + ->with('derp') + ->willReturn(true); + + $this->message->handle($stanza); + } + + public function testNotAllowedToChat() + { + $this->messageMapper->expects($this->never()) + ->method('insert'); + + $this->userProvider->expects($this->once()) + ->method('hasUserByUID') + ->with('derp') + ->willReturn(false); + + $stanza = [ + 'name' => '{jabber:client}message', + 'value' => + [ + '{jabber:client}body' => 'abcèé³e¹³€{ë', + '{urn:xmpp:receipts}request' => null, + ], + 'attributes' => + [ + 'to' => 'derp@own.dev', + 'type' => 'chat', + ], + ]; + $this->message->handle($stanza); } } diff --git a/tests/unit/stanzahandlers/PresenceTest.php b/tests/unit/stanzahandlers/PresenceTest.php index f5c6cf9c..82a197d4 100644 --- a/tests/unit/stanzahandlers/PresenceTest.php +++ b/tests/unit/stanzahandlers/PresenceTest.php @@ -6,7 +6,6 @@ use OCA\OJSXC\Db\Presence as PresenceEntity; use PHPUnit\Framework\TestCase; use PHPUnit_Framework_MockObject_MockObject; -use PHPUnit_Framework_TestCase; class PresenceTest extends TestCase {