Skip to content

Commit 1d2a868

Browse files
authored
Merge pull request #10662 from owncloud/test-auth-app-token-api
[tests-only][full-ci]add test for creating and listing auth token for an app using api
2 parents 1074b25 + 7546e47 commit 1d2a868

File tree

6 files changed

+292
-4
lines changed

6 files changed

+292
-4
lines changed

.drone.star

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,17 @@ config = {
242242
"GATEWAY_GRPC_ADDR": "0.0.0.0:9142",
243243
},
244244
},
245+
"authApp": {
246+
"suites": [
247+
"apiAuthApp",
248+
],
249+
"skip": False,
250+
"withRemotePhp": [True],
251+
"extraServerEnvironment": {
252+
"OCIS_ADD_RUN_SERVICES": "auth-app",
253+
"PROXY_ENABLE_APP_AUTH": True,
254+
},
255+
},
245256
"cliCommands": {
246257
"suites": [
247258
"cliCommands",
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php declare(strict_types=1);
2+
/**
3+
* ownCloud
4+
*
5+
* @author Niraj Acharya <[email protected]>
6+
* @copyright Copyright (c) 2024 Niraj Acharya [email protected]
7+
*
8+
* This code is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License,
10+
* as published by the Free Software Foundation;
11+
* either version 3 of the License, or any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License
19+
* along with this program. If not, see <http://www.gnu.org/licenses/>
20+
*
21+
*/
22+
23+
namespace TestHelpers;
24+
25+
use Psr\Http\Message\ResponseInterface;
26+
27+
/**
28+
* A helper class for managing Auth App API requests
29+
*/
30+
class AuthAppHelper {
31+
/**
32+
* @return string
33+
*/
34+
public static function getAuthAppEndpoint(): string {
35+
return "/auth-app/tokens";
36+
}
37+
38+
/**
39+
* @param string $baseUrl
40+
* @param string $user
41+
* @param string $password
42+
*
43+
* @return ResponseInterface
44+
*/
45+
public static function listAllAppAuthTokensForUser(string $baseUrl, string $user, string $password): ResponseInterface {
46+
$url = $baseUrl . self::getAuthAppEndpoint();
47+
return HttpRequestHelper::sendRequest(
48+
$url,
49+
null,
50+
"GET",
51+
$user,
52+
$password,
53+
);
54+
}
55+
56+
/**
57+
* @param string $baseUrl
58+
* @param string $user
59+
* @param string $password
60+
* @param string $expiration
61+
*
62+
* @return ResponseInterface
63+
*/
64+
public static function createAppAuthToken(string $baseUrl, string $user, string $password, string $expiration): ResponseInterface {
65+
$url = $baseUrl . self::getAuthAppEndpoint() . "?expiry=$expiration";
66+
return HttpRequestHelper::sendRequest(
67+
$url,
68+
null,
69+
"POST",
70+
$user,
71+
$password,
72+
);
73+
}
74+
75+
/**
76+
* @param string $baseUrl
77+
* @param string $user
78+
* @param string $password
79+
* @param string $token
80+
*
81+
* @return ResponseInterface
82+
*/
83+
public static function deleteAppAuthToken(string $baseUrl, string $user, string $password, string $token): ResponseInterface {
84+
$url = $baseUrl . self::getAuthAppEndpoint() . "?token=$token";
85+
return HttpRequestHelper::sendRequest(
86+
$url,
87+
null,
88+
"DELETE",
89+
$user,
90+
$password,
91+
);
92+
}
93+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php declare(strict_types=1);
2+
/**
3+
* ownCloud
4+
*
5+
* @author Niraj Acharya <[email protected]>
6+
* @copyright Copyright (c) 2024 Niraj Acharya [email protected]
7+
*
8+
* This code is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License,
10+
* as published by the Free Software Foundation;
11+
* either version 3 of the License, or any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License
19+
* along with this program. If not, see <http://www.gnu.org/licenses/>
20+
*
21+
*/
22+
23+
use Behat\Behat\Context\Context;
24+
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
25+
use TestHelpers\BehatHelper;
26+
use GuzzleHttp\Exception\GuzzleException;
27+
use TestHelpers\AuthAppHelper;
28+
29+
require_once 'bootstrap.php';
30+
31+
/**
32+
* AuthApp context
33+
*/
34+
class AuthAppContext implements Context {
35+
private FeatureContext $featureContext;
36+
37+
/**
38+
* @BeforeScenario
39+
*
40+
* @param BeforeScenarioScope $scope
41+
*
42+
* @return void
43+
*/
44+
public function before(BeforeScenarioScope $scope): void {
45+
// Get the environment
46+
$environment = $scope->getEnvironment();
47+
// Get all the contexts you need in this context
48+
$this->featureContext = BehatHelper::getContext($scope, $environment, 'FeatureContext');
49+
}
50+
51+
/**
52+
* @When user :user creates app token with expiration time :expiration using the auth-app API
53+
*
54+
* @param string $user
55+
* @param string $expiration
56+
*
57+
* @return void
58+
*/
59+
public function userCreatesAppTokenWithExpirationTimeUsingTheAuthAppApi(string $user, string $expiration): void {
60+
$this->featureContext->setResponse(
61+
AuthAppHelper::createAppAuthToken(
62+
$this->featureContext->getBaseUrl(),
63+
$this->featureContext->getActualUsername($user),
64+
$this->featureContext->getPasswordForUser($user),
65+
$expiration,
66+
)
67+
);
68+
}
69+
70+
/**
71+
* @Given user :user has created app token with expiration time :expiration
72+
*
73+
* @param string $user
74+
* @param string $expiration
75+
*
76+
* @return void
77+
*/
78+
public function userHasCreatedAppTokenWithExpirationTime(string $user, string $expiration): void {
79+
$response = AuthAppHelper::createAppAuthToken(
80+
$this->featureContext->getBaseUrl(),
81+
$this->featureContext->getActualUsername($user),
82+
$this->featureContext->getPasswordForUser($user),
83+
$expiration,
84+
);
85+
$this->featureContext->theHTTPStatusCodeShouldBe(200, "", $response);
86+
}
87+
88+
/**
89+
* @When user :user lists all created tokens using the auth-app API
90+
*
91+
* @param string $user
92+
*
93+
* @return void
94+
*/
95+
public function userListsAllCreatedTokensUsingTheAuthAppApi(string $user): void {
96+
$this->featureContext->setResponse(
97+
AuthAppHelper::listAllAppAuthTokensForUser(
98+
$this->featureContext->getBaseUrl(),
99+
$this->featureContext->getActualUsername($user),
100+
$this->featureContext->getPasswordForUser($user),
101+
)
102+
);
103+
}
104+
}

tests/acceptance/bootstrap/FeatureContext.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,9 +1132,11 @@ private function validateSchemaArray(JsonSchema $schemaObj): void {
11321132
Assert::fail("'$validator' should be an object not an array");
11331133
}
11341134
Assert::assertFalse($value->allOf || $value->anyOf, "'allOf' and 'anyOf' are not allowed in array");
1135-
Assert::assertNotNull($value->oneOf, "'oneOf' is required to assert more than one elements");
1136-
Assert::assertTrue(\is_array($value->oneOf), "'oneOf' should be an array");
1137-
Assert::assertEquals($schemaObj->maxItems, \count($value->oneOf), "Expected " . $schemaObj->maxItems . " 'oneOf' items but got " . \count($value->oneOf));
1135+
if ($value->oneOf) {
1136+
Assert::assertNotNull($value->oneOf, "'oneOf' is required to assert more than one elements");
1137+
Assert::assertTrue(\is_array($value->oneOf), "'oneOf' should be an array");
1138+
Assert::assertEquals($schemaObj->maxItems, \count($value->oneOf), "Expected " . $schemaObj->maxItems . " 'oneOf' items but got " . \count($value->oneOf));
1139+
}
11381140
}
11391141
Assert::assertTrue(\is_object($value), "'$validator' should be an object when expecting 1 element");
11401142
break;
@@ -1226,7 +1228,7 @@ public function throwJsonSchemaException(JsonSchemaException $e): void {
12261228
$errors = $this->getJsonSchemaErrors($e);
12271229
$messages = ["JSON Schema validation failed:"];
12281230

1229-
$previousPointer = '';
1231+
$previousPointer = null;
12301232
$errorCount = 0;
12311233
foreach ($errors as $error) {
12321234
$expected = $error->constraint;
@@ -1236,6 +1238,9 @@ public function throwJsonSchemaException(JsonSchemaException $e): void {
12361238
$dataPointer = \str_replace("/", ".", \trim($error->getDataPointer(), "/"));
12371239

12381240
$pointer = \str_contains($schemaPointer, "additionalProperties") ? $dataPointer : $schemaPointer;
1241+
if ($pointer === '') {
1242+
$pointer = "{root}";
1243+
}
12391244
if ($pointer === $previousPointer) {
12401245
continue;
12411246
}

tests/acceptance/config/behat.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,14 @@ default:
424424
- FeatureContext: *common_feature_context_params
425425
- OcisConfigContext:
426426

427+
apiAuthApp:
428+
paths:
429+
- "%paths.base%/../features/apiAuthApp"
430+
context: *common_ldap_suite_context
431+
contexts:
432+
- FeatureContext: *common_feature_context_params
433+
- AuthAppContext:
434+
427435
cliCommands:
428436
paths:
429437
- "%paths.base%/../features/cliCommands"
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
Feature: create auth token
2+
As a user
3+
I want to create App Tokens
4+
So that I can use 3rd party apps
5+
6+
Background:
7+
Given user "Alice" has been created with default attributes
8+
9+
10+
Scenario: user creates app token
11+
When user "Alice" creates app token with expiration time "72h" using the auth-app API
12+
Then the HTTP status code should be "200"
13+
And the JSON data of the response should match
14+
"""
15+
{
16+
"type": "object",
17+
"required": [
18+
"token",
19+
"expiration_date",
20+
"created_date",
21+
"label"
22+
],
23+
"properties": {
24+
"token": {
25+
"type": "string",
26+
"pattern": "^[a-zA-Z0-9]{16}$"
27+
},
28+
"label": {
29+
"const": "Generated via API"
30+
}
31+
}
32+
}
33+
"""
34+
35+
36+
Scenario: user lists app tokens
37+
Given user "Alice" has created app token with expiration time "72h"
38+
And user "Alice" has created app token with expiration time "2h"
39+
When user "Alice" lists all created tokens using the auth-app API
40+
Then the HTTP status code should be "200"
41+
And the JSON data of the response should match
42+
"""
43+
{
44+
"type": "array",
45+
"minItems": 2,
46+
"maxItems": 2,
47+
"uniqueItems": true,
48+
"items": {
49+
"type": "object",
50+
"required": [
51+
"token",
52+
"expiration_date",
53+
"created_date",
54+
"label"
55+
],
56+
"properties": {
57+
"token": {
58+
"type": "string",
59+
"pattern": "^\\$2a\\$11\\$[A-Za-z0-9./]{53}$"
60+
},
61+
"label": {
62+
"const": "Generated via API"
63+
}
64+
}
65+
}
66+
}
67+
"""

0 commit comments

Comments
 (0)