Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions lib/Controller/Api1Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -441,11 +441,10 @@ public function deleteView(int $viewId): DataResponse {
* Get a share object
*
* @param int $shareId Share ID
* @return DataResponse<Http::STATUS_OK, TablesShare, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
* @return DataResponse<Http::STATUS_OK, TablesShare, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
*
* 200: Share returned
* 403: No permissions
* 404: Not found
* 404: Not found/No permissions
*/
#[NoAdminRequired]
#[NoCSRFRequired]
Expand All @@ -456,7 +455,7 @@ public function getShare(int $shareId): DataResponse {
} catch (PermissionError $e) {
$this->logger->warning('A permission error occurred: '.$e->getMessage(), ['exception' => $e]);
$message = ['message' => $e->getMessage()];
return new DataResponse($message, Http::STATUS_FORBIDDEN);
return new DataResponse($message, Http::STATUS_NOT_FOUND);
} catch (InternalError $e) {
$this->logger->error('An internal error or exception occurred: '.$e->getMessage(), ['exception' => $e]);
$message = ['message' => $e->getMessage()];
Expand All @@ -473,13 +472,16 @@ public function getShare(int $shareId): DataResponse {
* Will be empty if view does not exist
*
* @param int $viewId View ID
* @return DataResponse<Http::STATUS_OK, TablesShare[], array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
* @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{}>
*
* 200: Shares returned
* 403: No permissions
* 404: Not found
*/
#[NoAdminRequired]
#[NoCSRFRequired]
#[CORS]
#[RequirePermission(permission: Application::PERMISSION_MANAGE, type: Application::NODE_TYPE_VIEW, idParam: 'viewId')]
public function indexViewShares(int $viewId): DataResponse {
try {
return new DataResponse($this->shareService->formatShares($this->shareService->findAll('view', $viewId)));
Expand All @@ -495,13 +497,16 @@ public function indexViewShares(int $viewId): DataResponse {
* Will be empty if table does not exist
*
* @param int $tableId Table ID
* @return DataResponse<Http::STATUS_OK, TablesShare[], array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
* @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{}>
*
* 200: Shares returned
* 403: No permissions
* 404: Not found
*/
#[NoAdminRequired]
#[NoCSRFRequired]
#[CORS]
#[RequirePermission(permission: Application::PERMISSION_MANAGE, type: Application::NODE_TYPE_TABLE, idParam: 'tableId')]
public function indexTableShares(int $tableId): DataResponse {
try {
return new DataResponse($this->shareService->formatShares($this->shareService->findAll('table', $tableId)));
Expand Down
92 changes: 73 additions & 19 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1933,24 +1933,6 @@
}
}
},
"403": {
"description": "No permissions",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
},
"500": {
"description": "",
"content": {
Expand All @@ -1970,7 +1952,7 @@
}
},
"404": {
"description": "Not found",
"description": "Not found/No permissions",
"content": {
"application/json": {
"schema": {
Expand Down Expand Up @@ -2232,6 +2214,42 @@
}
}
},
"403": {
"description": "No permissions",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
},
"500": {
"description": "",
"content": {
Expand Down Expand Up @@ -2291,6 +2309,42 @@
}
}
},
"403": {
"description": "No permissions",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
},
"500": {
"description": "",
"content": {
Expand Down
57 changes: 45 additions & 12 deletions src/types/openapi/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1586,18 +1586,7 @@ export interface operations {
readonly "application/json": components["schemas"]["Share"];
};
};
/** @description No permissions */
readonly 403: {
headers: {
readonly [name: string]: unknown;
};
content: {
readonly "application/json": {
readonly message: string;
};
};
};
/** @description Not found */
/** @description Not found/No permissions */
readonly 404: {
headers: {
readonly [name: string]: unknown;
Expand Down Expand Up @@ -1760,6 +1749,28 @@ export interface operations {
readonly "application/json": readonly components["schemas"]["Share"][];
};
};
/** @description No permissions */
readonly 403: {
headers: {
readonly [name: string]: unknown;
};
content: {
readonly "application/json": {
readonly message: string;
};
};
};
/** @description Not found */
readonly 404: {
headers: {
readonly [name: string]: unknown;
};
content: {
readonly "application/json": {
readonly message: string;
};
};
};
readonly 500: {
headers: {
readonly [name: string]: unknown;
Expand Down Expand Up @@ -1793,6 +1804,28 @@ export interface operations {
readonly "application/json": readonly components["schemas"]["Share"][];
};
};
/** @description No permissions */
readonly 403: {
headers: {
readonly [name: string]: unknown;
};
content: {
readonly "application/json": {
readonly message: string;
};
};
};
/** @description Not found */
readonly 404: {
headers: {
readonly [name: string]: unknown;
};
content: {
readonly "application/json": {
readonly message: string;
};
};
};
readonly 500: {
headers: {
readonly [name: string]: unknown;
Expand Down
48 changes: 48 additions & 0 deletions tests/integration/features/APIv2.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Feature: APIv2
Given user "participant1-v2" exists
Given user "participant2-v2" exists
Given user "participant3-v2" exists
Given user "participant4-v2" exists

@api2
Scenario: Test initial setup
Expand Down Expand Up @@ -888,6 +889,53 @@ Feature: APIv2
| five | [{"id": "admin", "type": 0}] |
Then the reported status is 403

@api2 @sharing @tables
Scenario: Create a shared table and check its permissions
Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2
And user "participant1-v2" shares table with user "participant2-v2"
And user "participant1-v2" shares table with user "participant3-v2"
Then user "participant3-v2" has the following permissions
| read | 1 |
| create | 1 |
| update | 1 |
| delete | 0 |
| manage | 0 |
# Current share-Id is set to the share towards participant3-v2!
When user "participant3-v2" attempts to check the share permissions
Then the reported status is 200
When user "participant2-v2" attempts to check the share permissions
Then the reported status is 404
When user "participant4-v2" attempts to check the share permissions
Then the reported status is 404
# test against the share overview
When user "participant1-v2" attempts to fetch all shares of table t1
Then the reported status is 200
When user "participant2-v2" attempts to fetch all shares of table t1
Then the reported status is 403
When user "participant4-v2" attempts to fetch all shares of table t1
Then the reported status is 404

@api2 @sharing @views
Scenario: Create a shared view and check its permissions
Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2
And user "participant1-v2" create view "v1" with emoji "⚡️" for "t1" as "v1"
And user "participant1-v2" shares view "v1" with "participant2-v2"
And user "participant1-v2" shares view "v1" with "participant3-v2"
# Current share-Id is set to the share towards participant3-v2!
When user "participant2-v2" attempts to check the share permissions
Then the reported status is 404
When user "participant3-v2" attempts to check the share permissions
Then the reported status is 200
When user "participant4-v2" attempts to check the share permissions
Then the reported status is 404
# test against the share overview
When user "participant1-v2" attempts to fetch all shares of view v1
Then the reported status is 200
When user "participant2-v2" attempts to fetch all shares of view v1
Then the reported status is 403
When user "participant4-v2" attempts to fetch all shares of view v1
Then the reported status is 404

@api2 @rows @views
Scenario: Create rows on a view via v2 without access
Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2
Expand Down
21 changes: 21 additions & 0 deletions tests/integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,27 @@ private function getShareById(int $shareId): array {
return $this->getDataFromResponse($this->response);
}

/**
* @When user :user attempts to check the share permissions
*/
public function attemptToCheckSharePermissions(string $user): void {
$this->setCurrentUser($user);
$this->getShareById($this->shareId);
}

/**
* @When user :user attempts to fetch all shares of :element :alias
*/
public function attemptToFetchAllShares(string $user, string $element, string $alias): void {
$this->setCurrentUser($user);
$tableId = $this->collectionManager->getByAlias($element, $alias)['id'];

$this->sendRequest(
'GET',
sprintf('/apps/tables/api/1/%ss/%d/shares', $element, $tableId)
);
}

/**
* @Then user :user has the following permissions
*/
Expand Down
Loading