Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/notifications.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2021-10-18 15:15:13 +0300
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>2021-10-19 12:35:27 +0300
commit292701479f3bf225fad6545a93be20c2c0c36c35 (patch)
tree9949803c038f26d125dcdee52a293a0d6b112847
parentb6167abff90e02d6b38c0e8c66fff23fb3647d30 (diff)
Add an integration test for push registration
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--tests/Integration/features/bootstrap/FeatureContext.php109
-rw-r--r--tests/Integration/features/push-registration.feature64
2 files changed, 169 insertions, 4 deletions
diff --git a/tests/Integration/features/bootstrap/FeatureContext.php b/tests/Integration/features/bootstrap/FeatureContext.php
index 51b66cb..6ecb6d9 100644
--- a/tests/Integration/features/bootstrap/FeatureContext.php
+++ b/tests/Integration/features/bootstrap/FeatureContext.php
@@ -56,6 +56,12 @@ class FeatureContext implements Context, SnippetAcceptingContext {
/** @var string */
protected $lastEtag;
+ /** @var resource */
+ protected $deviceKey;
+
+ /** @var string[] */
+ protected $appPasswords;
+
/**
* FeatureContext constructor.
*/
@@ -239,6 +245,99 @@ class FeatureContext implements Context, SnippetAcceptingContext {
}
/**
+ * @Then /^user "([^"]*)" unregisters from push notifications/
+ *
+ * @param string $user
+ */
+ public function unregisterForPushNotifications(string $user) {
+ $currentUser = $this->currentUser;
+ $this->setCurrentUser($user);
+ $this->sendingToWith('DELETE', '/apps/notifications/api/v2/push?format=json');
+ $this->setCurrentUser($currentUser);
+ }
+
+ /**
+ * @Then /^user "([^"]*)" registers for push notifications with$/
+ *
+ * @param string $user
+ * @param TableNode|null $formData
+ */
+ public function registerForPushNotifications(string $user, TableNode $formData) {
+ $data = $formData->getRowsHash();
+
+ if ($data['devicePublicKey'] === 'VALID_KEY') {
+ $config = [
+ 'digest_alg' => 'sha512',
+ 'private_key_bits' => 2048,
+ 'private_key_type' => OPENSSL_KEYTYPE_RSA,
+ ];
+ $this->deviceKey = openssl_pkey_new($config);
+ $keyDetails = openssl_pkey_get_details($this->deviceKey);
+ $publicKey = $keyDetails['key'];
+
+ $data['devicePublicKey'] = $publicKey;
+ }
+
+ $currentUser = $this->currentUser;
+ $this->setCurrentUser($user);
+ $this->sendingToWith('POST', '/apps/notifications/api/v2/push?format=json', $data);
+ $this->setCurrentUser($currentUser);
+ }
+
+ /**
+ * @Then /^can validate the response and signature$/
+ */
+ public function validateResponseAndSignature(): void {
+ $response = $this->getArrayOfNotificationsResponded($this->response);
+
+ Assert::assertStringStartsWith('-----BEGIN PUBLIC KEY-----' . "\n", $response['publicKey']);
+ Assert::assertStringEndsWith('-----END PUBLIC KEY-----' . "\n", $response['publicKey']);
+ Assert::assertNotEmpty($response['deviceIdentifier'], 'Device identifier should not be empty');
+ Assert::assertNotEmpty($response['signature'], 'Signature should not be empty');
+
+ $result = openssl_verify($response['deviceIdentifier'], base64_decode($response['signature']), $response['publicKey'], OPENSSL_ALGO_SHA512);
+ Assert::assertEquals(true, $result, 'Failed to verify the signature');
+ }
+
+ /**
+ * @Then /^user "([^"]*)" creates an app password$/
+ *
+ * @param string $user
+ */
+ public function createAppPassword(string $user) {
+ $currentUser = $this->currentUser;
+ $this->setCurrentUser($user);
+ $this->sendingToWith('GET', '/core/getapppassword?format=json');
+ $this->setCurrentUser($currentUser);
+
+ $response = $this->getArrayOfNotificationsResponded($this->response);
+ Assert::assertNotEquals('', $response['apppassword']);
+ $this->appPasswords[$user] = $response['apppassword'];
+ }
+
+ /**
+ * @Then /^user "([^"]*)" forgets the app password$/
+ *
+ * @param string $user
+ */
+ public function removeAppPassword(string $user) {
+ unset($this->appPasswords[$user]);
+ }
+
+ /**
+ * @Then /^error "([^"]*)" is expected with status code ([0-9]*)$/
+ *
+ * @param string $error
+ * @param int $statusCode
+ */
+ public function expectedErrorOnLastRequest(string $error, int $statusCode) {
+ $this->assertStatusCode($this->response, $statusCode);
+ $response = $this->getArrayOfNotificationsResponded($this->response);
+
+ Assert::assertEquals($error, $response['message']);
+ }
+
+ /**
* @Then /^status code is ([0-9]*)$/
*
* @param int $statusCode
@@ -366,15 +465,17 @@ class FeatureContext implements Context, SnippetAcceptingContext {
* @When /^sending "([^"]*)" to "([^"]*)" with$/
* @param string $verb
* @param string $url
- * @param TableNode $body
+ * @param TableNode|array|null $body
* @param array $headers
*/
- public function sendingToWith(string $verb, string $url, TableNode $body = null, array $headers = []) {
+ public function sendingToWith(string $verb, string $url, $body = null, array $headers = []) {
$fullUrl = $this->baseUrl . 'ocs/v2.php' . $url;
$client = new Client();
$options = [];
- if ($this->currentUser === 'admin') {
- $options['auth'] = ['admin', 'admin'];
+ if (isset($this->appPasswords[$this->currentUser])) {
+ $options['auth'] = [$this->currentUser, $this->appPasswords[$this->currentUser]];
+ } elseif ($this->currentUser === 'admin') {
+ $options['auth'] = [$this->currentUser, 'admin'];
} else {
$options['auth'] = [$this->currentUser, '123456'];
}
diff --git a/tests/Integration/features/push-registration.feature b/tests/Integration/features/push-registration.feature
new file mode 100644
index 0000000..3d1eea9
--- /dev/null
+++ b/tests/Integration/features/push-registration.feature
@@ -0,0 +1,64 @@
+Feature: Push registration
+ Background:
+ Given user "test1" exists
+ Given as user "test1"
+
+ Scenario: Invalid push token hash
+ Given user "test1" registers for push notifications with
+ | pushTokenHash | 12345 |
+ | devicePublicKey | INVALID_KEY |
+ | proxyServer | nextcloud |
+ Then error "INVALID_PUSHTOKEN_HASH" is expected with status code 400
+
+ Scenario: Invalid device key
+ Given user "test1" registers for push notifications with
+ | pushTokenHash | 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 |
+ | devicePublicKey | INVALID_KEY |
+ | proxyServer | nextcloud |
+ Then error "INVALID_DEVICE_KEY" is expected with status code 400
+
+ Scenario: Invalid proxy server
+ Given user "test1" registers for push notifications with
+ | pushTokenHash | 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 |
+ | devicePublicKey | VALID_KEY |
+ | proxyServer | nextcloud |
+ Then error "INVALID_PROXY_SERVER" is expected with status code 400
+
+ Scenario: Invalid session token: not using an app password
+ Given user "test1" registers for push notifications with
+ | pushTokenHash | 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 |
+ | devicePublicKey | VALID_KEY |
+ | proxyServer | https://push-notifications.nextcloud.com/ |
+ Then error "INVALID_SESSION_TOKEN" is expected with status code 400
+
+ Scenario: Successful registration
+ Given user "test1" creates an app password
+ Given user "test1" registers for push notifications with
+ | pushTokenHash | 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 |
+ | devicePublicKey | VALID_KEY |
+ | proxyServer | https://push-notifications.nextcloud.com/ |
+ Then status code is 201
+ And can validate the response and signature
+
+ Scenario: Unregistering from push notifications without app password
+ Given user "test1" forgets the app password
+ Given user "test1" unregisters from push notifications
+ Then error "INVALID_SESSION_TOKEN" is expected with status code 400
+
+ Scenario: Unregistering from push notifications successfully
+ Given user "test1" creates an app password
+ Given user "test1" registers for push notifications with
+ | pushTokenHash | 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 |
+ | devicePublicKey | VALID_KEY |
+ | proxyServer | https://push-notifications.nextcloud.com/ |
+ Then status code is 201
+ And can validate the response and signature
+ Given user "test1" unregisters from push notifications
+ Then status code is 202
+ Given user "test1" unregisters from push notifications
+ Then status code is 200
+
+ Scenario: Unregistering from push notifications without registering
+ Given user "test1" creates an app password
+ Given user "test1" unregisters from push notifications
+ Then status code is 200