Skip to content

Commit abcdfa7

Browse files
committed
tests(Integration): extend sharing tests
also improves OpenAPI documentation against related endpoints Signed-off-by: Arthur Schiwon <[email protected]>
1 parent ffd13fe commit abcdfa7

File tree

5 files changed

+198
-37
lines changed

5 files changed

+198
-37
lines changed

lib/Controller/Api1Controller.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -464,11 +464,10 @@ public function deleteView(int $viewId): DataResponse {
464464
* Get a share object
465465
*
466466
* @param int $shareId Share ID
467-
* @return DataResponse<Http::STATUS_OK, TablesShare, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
467+
* @return DataResponse<Http::STATUS_OK, TablesShare, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
468468
*
469469
* 200: Share returned
470-
* 403: No permissions
471-
* 404: Not found
470+
* 404: Not found/No permissions
472471
*/
473472
#[NoAdminRequired]
474473
#[NoCSRFRequired]
@@ -480,7 +479,7 @@ public function getShare(int $shareId): DataResponse {
480479
} catch (PermissionError $e) {
481480
$this->logger->warning('A permission error occurred: ' . $e->getMessage(), ['exception' => $e]);
482481
$message = ['message' => $e->getMessage()];
483-
return new DataResponse($message, Http::STATUS_FORBIDDEN);
482+
return new DataResponse($message, Http::STATUS_NOT_FOUND);
484483
} catch (InternalError $e) {
485484
$this->logger->error('An internal error or exception occurred: ' . $e->getMessage(), ['exception' => $e]);
486485
$message = ['message' => $e->getMessage()];
@@ -497,13 +496,16 @@ public function getShare(int $shareId): DataResponse {
497496
* Will be empty if view does not exist
498497
*
499498
* @param int $viewId View ID
500-
* @return DataResponse<Http::STATUS_OK, list<TablesShare>, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
499+
* @return DataResponse<Http::STATUS_OK, list<TablesShare>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
501500
*
502501
* 200: Shares returned
502+
* 403: No permissions
503+
* 404: Not found
503504
*/
504505
#[NoAdminRequired]
505506
#[NoCSRFRequired]
506507
#[CORS]
508+
#[RequirePermission(permission: Application::PERMISSION_MANAGE, type: Application::NODE_TYPE_VIEW, idParam: 'viewId')]
507509
#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
508510
public function indexViewShares(int $viewId): DataResponse {
509511
try {
@@ -520,13 +522,16 @@ public function indexViewShares(int $viewId): DataResponse {
520522
* Will be empty if table does not exist
521523
*
522524
* @param int $tableId Table ID
523-
* @return DataResponse<Http::STATUS_OK, list<TablesShare>, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
525+
* @return DataResponse<Http::STATUS_OK, list<TablesShare>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
524526
*
525527
* 200: Shares returned
528+
* 403: No permissions
529+
* 404: Not found
526530
*/
527531
#[NoAdminRequired]
528532
#[NoCSRFRequired]
529533
#[CORS]
534+
#[RequirePermission(permission: Application::PERMISSION_MANAGE, type: Application::NODE_TYPE_TABLE, idParam: 'tableId')]
530535
#[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
531536
public function indexTableShares(int $tableId): DataResponse {
532537
try {

openapi.json

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,24 +2250,6 @@
22502250
}
22512251
}
22522252
},
2253-
"403": {
2254-
"description": "No permissions",
2255-
"content": {
2256-
"application/json": {
2257-
"schema": {
2258-
"type": "object",
2259-
"required": [
2260-
"message"
2261-
],
2262-
"properties": {
2263-
"message": {
2264-
"type": "string"
2265-
}
2266-
}
2267-
}
2268-
}
2269-
}
2270-
},
22712253
"500": {
22722254
"description": "",
22732255
"content": {
@@ -2287,7 +2269,7 @@
22872269
}
22882270
},
22892271
"404": {
2290-
"description": "Not found",
2272+
"description": "Not found/No permissions",
22912273
"content": {
22922274
"application/json": {
22932275
"schema": {
@@ -2606,6 +2588,42 @@
26062588
}
26072589
}
26082590
},
2591+
"403": {
2592+
"description": "No permissions",
2593+
"content": {
2594+
"application/json": {
2595+
"schema": {
2596+
"type": "object",
2597+
"required": [
2598+
"message"
2599+
],
2600+
"properties": {
2601+
"message": {
2602+
"type": "string"
2603+
}
2604+
}
2605+
}
2606+
}
2607+
}
2608+
},
2609+
"404": {
2610+
"description": "Not found",
2611+
"content": {
2612+
"application/json": {
2613+
"schema": {
2614+
"type": "object",
2615+
"required": [
2616+
"message"
2617+
],
2618+
"properties": {
2619+
"message": {
2620+
"type": "string"
2621+
}
2622+
}
2623+
}
2624+
}
2625+
}
2626+
},
26092627
"500": {
26102628
"description": "",
26112629
"content": {
@@ -2684,6 +2702,42 @@
26842702
}
26852703
}
26862704
},
2705+
"403": {
2706+
"description": "No permissions",
2707+
"content": {
2708+
"application/json": {
2709+
"schema": {
2710+
"type": "object",
2711+
"required": [
2712+
"message"
2713+
],
2714+
"properties": {
2715+
"message": {
2716+
"type": "string"
2717+
}
2718+
}
2719+
}
2720+
}
2721+
}
2722+
},
2723+
"404": {
2724+
"description": "Not found",
2725+
"content": {
2726+
"application/json": {
2727+
"schema": {
2728+
"type": "object",
2729+
"required": [
2730+
"message"
2731+
],
2732+
"properties": {
2733+
"message": {
2734+
"type": "string"
2735+
}
2736+
}
2737+
}
2738+
}
2739+
}
2740+
},
26872741
"500": {
26882742
"description": "",
26892743
"content": {

src/types/openapi/openapi.ts

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,18 +1870,7 @@ export interface operations {
18701870
};
18711871
};
18721872
};
1873-
/** @description No permissions */
1874-
readonly 403: {
1875-
headers: {
1876-
readonly [name: string]: unknown;
1877-
};
1878-
content: {
1879-
readonly "application/json": {
1880-
readonly message: string;
1881-
};
1882-
};
1883-
};
1884-
/** @description Not found */
1873+
/** @description Not found/No permissions */
18851874
readonly 404: {
18861875
headers: {
18871876
readonly [name: string]: unknown;
@@ -2077,6 +2066,28 @@ export interface operations {
20772066
};
20782067
};
20792068
};
2069+
/** @description No permissions */
2070+
readonly 403: {
2071+
headers: {
2072+
readonly [name: string]: unknown;
2073+
};
2074+
content: {
2075+
readonly "application/json": {
2076+
readonly message: string;
2077+
};
2078+
};
2079+
};
2080+
/** @description Not found */
2081+
readonly 404: {
2082+
headers: {
2083+
readonly [name: string]: unknown;
2084+
};
2085+
content: {
2086+
readonly "application/json": {
2087+
readonly message: string;
2088+
};
2089+
};
2090+
};
20802091
readonly 500: {
20812092
headers: {
20822093
readonly [name: string]: unknown;
@@ -2121,6 +2132,28 @@ export interface operations {
21212132
};
21222133
};
21232134
};
2135+
/** @description No permissions */
2136+
readonly 403: {
2137+
headers: {
2138+
readonly [name: string]: unknown;
2139+
};
2140+
content: {
2141+
readonly "application/json": {
2142+
readonly message: string;
2143+
};
2144+
};
2145+
};
2146+
/** @description Not found */
2147+
readonly 404: {
2148+
headers: {
2149+
readonly [name: string]: unknown;
2150+
};
2151+
content: {
2152+
readonly "application/json": {
2153+
readonly message: string;
2154+
};
2155+
};
2156+
};
21242157
readonly 500: {
21252158
headers: {
21262159
readonly [name: string]: unknown;

tests/integration/features/APIv2.feature

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Feature: APIv2
55
Given user "participant1-v2" exists
66
Given user "participant2-v2" exists
77
Given user "participant3-v2" exists
8+
Given user "participant4-v2" exists
89

910
@api2
1011
Scenario: Test initial setup
@@ -898,6 +899,53 @@ Feature: APIv2
898899
| five | [{"id": "admin", "type": 0}] |
899900
Then the reported status is 403
900901

902+
@api2 @sharing @tables
903+
Scenario: Create a shared table and check its permissions
904+
Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2
905+
And user "participant1-v2" shares table with user "participant2-v2"
906+
And user "participant1-v2" shares table with user "participant3-v2"
907+
Then user "participant3-v2" has the following permissions
908+
| read | 1 |
909+
| create | 1 |
910+
| update | 1 |
911+
| delete | 0 |
912+
| manage | 0 |
913+
# Current share-Id is set to the share towards participant3-v2!
914+
When user "participant3-v2" attempts to check the share permissions
915+
Then the reported status is 200
916+
When user "participant2-v2" attempts to check the share permissions
917+
Then the reported status is 404
918+
When user "participant4-v2" attempts to check the share permissions
919+
Then the reported status is 404
920+
# test against the share overview
921+
When user "participant1-v2" attempts to fetch all shares of table t1
922+
Then the reported status is 200
923+
When user "participant2-v2" attempts to fetch all shares of table t1
924+
Then the reported status is 403
925+
When user "participant4-v2" attempts to fetch all shares of table t1
926+
Then the reported status is 404
927+
928+
@api2 @sharing @views
929+
Scenario: Create a shared view and check its permissions
930+
Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2
931+
And user "participant1-v2" create view "v1" with emoji "⚡️" for "t1" as "v1"
932+
And user "participant1-v2" shares view "v1" with "participant2-v2"
933+
And user "participant1-v2" shares view "v1" with "participant3-v2"
934+
# Current share-Id is set to the share towards participant3-v2!
935+
When user "participant2-v2" attempts to check the share permissions
936+
Then the reported status is 404
937+
When user "participant3-v2" attempts to check the share permissions
938+
Then the reported status is 200
939+
When user "participant4-v2" attempts to check the share permissions
940+
Then the reported status is 404
941+
# test against the share overview
942+
When user "participant1-v2" attempts to fetch all shares of view v1
943+
Then the reported status is 200
944+
When user "participant2-v2" attempts to fetch all shares of view v1
945+
Then the reported status is 403
946+
When user "participant4-v2" attempts to fetch all shares of view v1
947+
Then the reported status is 404
948+
901949
@api2 @rows @views
902950
Scenario: Create rows on a view via v2 without access
903951
Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2

tests/integration/features/bootstrap/FeatureContext.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,27 @@ public function checkPermissionsOnNode(
12011201
}
12021202
}
12031203

1204+
/**
1205+
* @When user :user attempts to check the share permissions
1206+
*/
1207+
public function attemptToCheckSharePermissions(string $user): void {
1208+
$this->setCurrentUser($user);
1209+
$this->getShareById($this->shareId);
1210+
}
1211+
1212+
/**
1213+
* @When user :user attempts to fetch all shares of :element :alias
1214+
*/
1215+
public function attemptToFetchAllShares(string $user, string $element, string $alias): void {
1216+
$this->setCurrentUser($user);
1217+
$tableId = $this->collectionManager->getByAlias($element, $alias)['id'];
1218+
1219+
$this->sendRequest(
1220+
'GET',
1221+
sprintf('/apps/tables/api/1/%ss/%d/shares', $element, $tableId)
1222+
);
1223+
}
1224+
12041225
/**
12051226
* @Then user :user has the following permissions
12061227
*/

0 commit comments

Comments
 (0)