Merge pull request #5450 from nextcloud/backport/5449/stable23
[stable23] Fix deleted card/board issues
This commit is contained in:
19
.github/workflows/fixup.yml
vendored
19
.github/workflows/fixup.yml
vendored
@@ -3,18 +3,31 @@
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
|
||||
name: Pull request checks
|
||||
name: Block fixup and squash commits
|
||||
|
||||
on: pull_request
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, ready_for_review, reopened, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: fixup-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
commit-message-check:
|
||||
if: github.event.pull_request.draft == false
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
name: Block fixup and squash commits
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Run check
|
||||
uses: xt0rted/block-autosquash-commits-action@v2
|
||||
uses: skjnldsv/block-fixup-merge-action@42d26e1b536ce61e5cf467d65fb76caf4aa85acf # v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
7
.github/workflows/integration.yml
vendored
7
.github/workflows/integration.yml
vendored
@@ -60,6 +60,13 @@ jobs:
|
||||
with:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Checkout activity
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
with:
|
||||
repository: nextcloud/activity
|
||||
ref: ${{ matrix.server-versions }}
|
||||
path: apps/activity
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
"@test:integration"
|
||||
],
|
||||
"test:unit": "phpunit -c tests/phpunit.xml",
|
||||
"test:integration": "phpunit -c tests/phpunit.integration.xml && cd tests/integration && ./run.sh"
|
||||
"test:integration": "phpunit -c tests/phpunit.integration.xml",
|
||||
"test:api": "cd tests/integration && ./run.sh"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
|
||||
@@ -39,6 +39,7 @@ use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Db\StackMapper;
|
||||
use OCA\Deck\NoPermissionException;
|
||||
use OCA\Deck\Service\PermissionService;
|
||||
use OCP\Activity\IEvent;
|
||||
use OCP\Activity\IManager;
|
||||
@@ -543,4 +544,24 @@ class ActivityManager {
|
||||
'board' => $board
|
||||
];
|
||||
}
|
||||
|
||||
public function canSeeCardActivity(int $cardId): bool {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
return $card->getDeletedAt() === 0;
|
||||
} catch (NoPermissionException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function canSeeBoardActivity(int $boardId): bool {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
$board = $this->boardMapper->find($boardId);
|
||||
return $board->getDeletedAt() === 0;
|
||||
} catch (NoPermissionException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,9 @@ class DeckProvider implements IProvider {
|
||||
$event->setAuthor($author);
|
||||
}
|
||||
if ($event->getObjectType() === ActivityManager::DECK_OBJECT_BOARD) {
|
||||
if (!$this->activityManager->canSeeBoardActivity($event->getObjectId())) {
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
if (isset($subjectParams['board']) && $event->getObjectName() === '') {
|
||||
$event->setObject($event->getObjectType(), $event->getObjectId(), $subjectParams['board']['title']);
|
||||
}
|
||||
@@ -125,6 +128,9 @@ class DeckProvider implements IProvider {
|
||||
}
|
||||
|
||||
if (isset($subjectParams['card']) && $event->getObjectType() === ActivityManager::DECK_OBJECT_CARD) {
|
||||
if (!$this->activityManager->canSeeCardActivity($event->getObjectId())) {
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
if ($event->getObjectName() === '') {
|
||||
$event->setObject($event->getObjectType(), $event->getObjectId(), $subjectParams['card']['title']);
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ class BoardService {
|
||||
$newAcl = $this->aclMapper->insert($acl);
|
||||
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $newAcl, ActivityManager::SUBJECT_BOARD_SHARE, [], $this->userId);
|
||||
$this->notificationHelper->sendBoardShared((int)$boardId, $acl);
|
||||
$this->notificationHelper->sendBoardShared($boardId, $acl);
|
||||
$this->boardMapper->mapAcl($newAcl);
|
||||
$this->changeHelper->boardChanged($boardId);
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ class CardService {
|
||||
public function update($id, $title, $stackId, $type, $owner, $description = '', $order = 0, $duedate = null, $deletedAt = null, $archived = null) {
|
||||
$this->cardServiceValidator->check(compact('id', 'title', 'stackId', 'type', 'owner', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT, null, true);
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
|
||||
|
||||
if ($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
@@ -276,9 +276,9 @@ class CardService {
|
||||
}
|
||||
|
||||
if ($card->getDeletedAt() !== 0) {
|
||||
if ($deletedAt === null) {
|
||||
if ($deletedAt === null || $deletedAt > 0) {
|
||||
// Only allow operations when restoring the card
|
||||
throw new StatusException('Operation not allowed. This card was deleted.');
|
||||
throw new NoPermissionException('Operation not allowed. This card was deleted.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,24 +83,17 @@ class CommentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cardId
|
||||
* @param string $message
|
||||
* @param string $replyTo
|
||||
* @return DataResponse
|
||||
* @throws BadRequestException
|
||||
* @throws NotFoundException|NoPermissionException
|
||||
*/
|
||||
public function create(string $cardId, string $message, string $replyTo = '0'): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
public function create(int $cardId, string $message, string $replyTo = '0'): DataResponse {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
// Check if parent is a comment on the same card
|
||||
if ($replyTo !== '0') {
|
||||
try {
|
||||
$comment = $this->commentsManager->get($replyTo);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$comment->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
} catch (CommentNotFoundException $e) {
|
||||
@@ -109,7 +102,7 @@ class CommentService {
|
||||
}
|
||||
|
||||
try {
|
||||
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, $cardId);
|
||||
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, (string)$cardId);
|
||||
$comment->setMessage($message);
|
||||
$comment->setVerb('comment');
|
||||
$comment->setParentId($replyTo);
|
||||
@@ -145,7 +138,7 @@ class CommentService {
|
||||
throw new NoPermissionException('Only authors are allowed to edit their comment.');
|
||||
}
|
||||
if ($comment->getParentId() !== '0') {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $comment->getParentId(), Acl::PERMISSION_READ);
|
||||
$this->permissionService->checkPermission($this->cardMapper, (int)$comment->getParentId(), Acl::PERMISSION_READ);
|
||||
}
|
||||
|
||||
$comment->setMessage($message);
|
||||
|
||||
@@ -29,6 +29,7 @@ use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\AclMapper;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\IPermissionMapper;
|
||||
use OCA\Deck\Db\User;
|
||||
use OCA\Deck\NoPermissionException;
|
||||
@@ -97,13 +98,18 @@ class PermissionService {
|
||||
* @param $boardId
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getPermissions($boardId) {
|
||||
public function getPermissions($boardId, ?string $userId = null) {
|
||||
if ($userId === null) {
|
||||
$userId = $this->userId;
|
||||
}
|
||||
|
||||
if ($cached = $this->permissionCache->get($boardId)) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$owner = $this->userIsBoardOwner($boardId);
|
||||
$acls = $this->aclMapper->findAll($boardId);
|
||||
$board = $this->getBoard($boardId);
|
||||
$owner = $this->userIsBoardOwner($boardId, $userId);
|
||||
$acls = $board->getDeletedAt() === 0 ? $this->aclMapper->findAll($boardId) : [];
|
||||
$permissions = [
|
||||
Acl::PERMISSION_READ => $owner || $this->userCan($acls, Acl::PERMISSION_READ),
|
||||
Acl::PERMISSION_EDIT => $owner || $this->userCan($acls, Acl::PERMISSION_EDIT),
|
||||
@@ -111,7 +117,7 @@ class PermissionService {
|
||||
Acl::PERMISSION_SHARE => ($owner || $this->userCan($acls, Acl::PERMISSION_SHARE))
|
||||
&& (!$this->shareManager->sharingDisabledForUser($this->userId))
|
||||
];
|
||||
$this->permissionCache->set($boardId, $permissions);
|
||||
$this->permissionCache->set((string)$boardId, $permissions);
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
@@ -137,13 +143,10 @@ class PermissionService {
|
||||
/**
|
||||
* check permissions for replacing dark magic middleware
|
||||
*
|
||||
* @param $mapper IPermissionMapper|null null if $id is a boardId
|
||||
* @param $id int unique identifier of the Entity
|
||||
* @param $permission int
|
||||
* @return bool
|
||||
* @param numeric $id
|
||||
* @throws NoPermissionException
|
||||
*/
|
||||
public function checkPermission($mapper, $id, $permission, $userId = null) {
|
||||
public function checkPermission($mapper, $id, $permission, $userId = null, bool $allowDeletedCard = false) {
|
||||
$boardId = $id;
|
||||
if ($mapper instanceof IPermissionMapper && !($mapper instanceof BoardMapper)) {
|
||||
$boardId = $mapper->findBoardId($id);
|
||||
@@ -157,12 +160,20 @@ class PermissionService {
|
||||
throw new NoPermissionException('Permission denied');
|
||||
}
|
||||
|
||||
if ($this->userIsBoardOwner($boardId, $userId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$acls = $this->getBoard($boardId)->getAcl() ?? [];
|
||||
$permissions = $this->getPermissions($boardId, $userId);
|
||||
if ($permissions[$permission] === true) {
|
||||
if (!$allowDeletedCard && $mapper instanceof CardMapper) {
|
||||
$card = $mapper->find($id);
|
||||
if ($card->getDeletedAt() > 0) {
|
||||
throw new NoPermissionException('Card is deleted');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$acls = $this->getBoard((int)$boardId)->getAcl() ?? [];
|
||||
$result = $this->userCan($acls, $permission, $userId);
|
||||
if ($result) {
|
||||
return true;
|
||||
|
||||
@@ -115,7 +115,7 @@ class ShareAPIHelper {
|
||||
*/
|
||||
public function canAccessShare(IShare $share, string $user): bool {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $share->getSharedWith(), Acl::PERMISSION_READ, $user);
|
||||
$this->permissionService->checkPermission($this->cardMapper, (int)$share->getSharedWith(), Acl::PERMISSION_READ, $user);
|
||||
} catch (NoPermissionException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -90,3 +90,53 @@ Feature: acl
|
||||
And the current user should not have "edit" permissions on the board
|
||||
And the current user should have "share" permissions on the board
|
||||
And the current user should not have "manage" permissions on the board
|
||||
|
||||
Scenario: Share a board multiple times
|
||||
Given Logging in using web as "user0"
|
||||
And creates a board named "Double shared board" with color "ff0000"
|
||||
And shares the board with user "user1"
|
||||
And shares the board with group "group1"
|
||||
And creates a board named "Single shared board" with color "00ff00"
|
||||
And shares the board with user "user1"
|
||||
When Logging in using web as "user1"
|
||||
And fetching the board list
|
||||
Then the response should have a status code "200"
|
||||
And the response should be a list of objects
|
||||
And the response should contain an element with the properties
|
||||
| property | value |
|
||||
| title | Double shared board |
|
||||
|
||||
|
||||
Scenario: Deleted board is inaccessible to share recipients
|
||||
Given acting as user "user0"
|
||||
When creates a board with example content
|
||||
And remember the last card as "user0-card"
|
||||
When post a comment with content "hello comment" on the card
|
||||
And uploads an attachment to the last used card
|
||||
And remember the last attachment as "user0-attachment"
|
||||
And shares the board with user "user1"
|
||||
Then the HTTP status code should be "200"
|
||||
And delete the board
|
||||
|
||||
Given acting as user "user1"
|
||||
When fetching the attachments for the card "user0-card"
|
||||
Then the response should have a status code 403
|
||||
|
||||
When get the comments on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When update a comment with content "hello deleted" on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When delete the comment on the card
|
||||
Then the response should have a status code 403
|
||||
# 644
|
||||
When post a comment with content "hello deleted" on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When get the card details
|
||||
Then the response should have a status code 403
|
||||
When fetching the attachment "user0-attachment" for the card "user0-card"
|
||||
Then the response should have a status code 403
|
||||
When deleting the attachment "user0-attachment" for the card "user0-card"
|
||||
Then the response should have a status code 403
|
||||
|
||||
@@ -87,4 +87,14 @@ class AttachmentContext implements Context {
|
||||
|
||||
$this->requestContext->sendPlainRequest('GET', '/index.php/apps/deck/cards/' . $cardId . '/attachment/file:' . $attachmentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When fetching the attachments for the card :cardReference
|
||||
*/
|
||||
public function fetchingTheAttachmentsForTheCard($cardReference) {
|
||||
$cardId = $this->boardContext->getRememberedCard($cardReference)['id'] ?? null;
|
||||
Assert::assertNotNull($cardId, 'Card needs to be available');
|
||||
|
||||
$this->requestContext->sendPlainRequest('GET', '/index.php/apps/deck/cards/' . $cardId . '/attachments');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ class BoardContext implements Context {
|
||||
/** @var array last card response */
|
||||
private $card = null;
|
||||
private $storedCards = [];
|
||||
private $activities = null;
|
||||
|
||||
/** @var ServerContext */
|
||||
private $serverContext;
|
||||
|
||||
/** @BeforeScenario */
|
||||
@@ -186,7 +186,9 @@ class BoardContext implements Context {
|
||||
['description' => $description]
|
||||
));
|
||||
$this->requestContext->getResponse()->getBody()->seek(0);
|
||||
$this->card = json_decode((string)$this->getResponse()->getBody(), true);
|
||||
if ($this->requestContext->getResponse()->getStatusCode() === 200) {
|
||||
$this->card = json_decode((string)$this->getResponse()->getBody(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +200,22 @@ class BoardContext implements Context {
|
||||
[$attribute => $value]
|
||||
));
|
||||
$this->requestContext->getResponse()->getBody()->seek(0);
|
||||
$this->card = json_decode((string)$this->getResponse()->getBody(), true);
|
||||
if ($this->requestContext->getResponse()->getStatusCode() === 200) {
|
||||
$this->card = json_decode((string)$this->getResponse()->getBody(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^get the card details$/
|
||||
*/
|
||||
public function getCard() {
|
||||
$this->requestContext->sendJSONrequest('GET', '/index.php/apps/deck/cards/' . $this->card['id'], array_merge(
|
||||
$this->card
|
||||
));
|
||||
$this->requestContext->getResponse()->getBody()->seek(0);
|
||||
if ($this->requestContext->getResponse()->getStatusCode() === 200) {
|
||||
$this->card = json_decode((string)$this->getResponse()->getBody(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,4 +270,36 @@ class BoardContext implements Context {
|
||||
public function getRememberedCard($arg1) {
|
||||
return $this->storedCards[$arg1] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^delete the card$/
|
||||
*/
|
||||
public function deleteTheCard() {
|
||||
$this->requestContext->sendJSONrequest('DELETE', '/index.php/apps/deck/cards/' . $this->card['id']);
|
||||
$this->card['deletedAt'] = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^delete the board/
|
||||
*/
|
||||
public function deleteTheBoard() {
|
||||
$this->requestContext->sendJSONrequest('DELETE', '/index.php/apps/deck/boards/' . $this->board['id']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Given /^get the activities for the last card$/
|
||||
*/
|
||||
public function getActivitiesForTheLastCard() {
|
||||
$card = $this->getLastUsedCard();
|
||||
$this->requestContext->sendOCSRequest('GET', '/apps/activity/api/v2/activity/filter?format=json&type=deck&since=0&object_type=deck_card&object_id=' . $card['id'] . '&limit=50');
|
||||
$this->activities = json_decode((string)$this->getResponse()->getBody(), true)['ocs']['data'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the fetched activities should have :count entries
|
||||
*/
|
||||
public function theFetchedActivitiesShouldHaveEntries($count) {
|
||||
Assert::assertEquals($count, count($this->activities ?? []));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ class CommentContext implements Context {
|
||||
/** @var BoardContext */
|
||||
protected $boardContext;
|
||||
|
||||
private $lastComment = null;
|
||||
|
||||
/** @BeforeScenario */
|
||||
public function gatherContexts(BeforeScenarioScope $scope) {
|
||||
$environment = $scope->getEnvironment();
|
||||
@@ -27,5 +29,33 @@ class CommentContext implements Context {
|
||||
'message' => $content,
|
||||
'parentId' => null
|
||||
]);
|
||||
$this->lastComment = $this->requestContext->getResponseBodyFromJson()['ocs']['data'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^get the comments on the card$/
|
||||
*/
|
||||
public function getCommentsOnTheCard() {
|
||||
$card = $this->boardContext->getLastUsedCard();
|
||||
$this->requestContext->sendOCSRequest('GET', '/apps/deck/api/v1.0/cards/' . $card['id'] . '/comments');
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^update a comment with content "([^"]*)" on the card$/
|
||||
*/
|
||||
public function updateACommentWithContentOnTheCard($content) {
|
||||
$card = $this->boardContext->getLastUsedCard();
|
||||
$this->requestContext->sendOCSRequest('PUT', '/apps/deck/api/v1.0/cards/' . $card['id'] . '/comments/'. $this->lastComment['id'], [
|
||||
'message' => $content,
|
||||
'parentId' => null
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^delete the comment on the card$/
|
||||
*/
|
||||
public function deleteTheCommentOnTheCard() {
|
||||
$card = $this->boardContext->getLastUsedCard();
|
||||
$this->requestContext->sendOCSRequest('DELETE', '/apps/deck/api/v1.0/cards/' . $card['id'] . '/comments/'. $this->lastComment['id']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,29 @@ class RequestContext implements Context {
|
||||
$this->getResponse()->getBody()->seek(0);
|
||||
return json_decode((string)$this->getResponse()->getBody(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^the response should be a list of objects$/
|
||||
*/
|
||||
public function theResponseShouldBeAListOfObjects() {
|
||||
$jsonResponse = $this->getResponseBodyFromJson();
|
||||
Assert::assertEquals(array_keys($jsonResponse), range(0, count($jsonResponse) - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the response should contain an element with the properties$/
|
||||
*/
|
||||
public function responseContainsElement(TableNode $element) {
|
||||
$json = $this->getResponseBodyFromJson();
|
||||
$found = array_filter($json, function ($board) use ($element) {
|
||||
foreach ($element as $row) {
|
||||
if ($row['value'] !== $board[$row['property']]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
Assert::assertEquals(1, count($found));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,15 +10,15 @@ class ServerContext implements Context {
|
||||
WebDav::__construct as private __tConstruct;
|
||||
}
|
||||
|
||||
private $rawBaseUrl;
|
||||
private $mappedUserId;
|
||||
private $lastInsertIds = [];
|
||||
|
||||
public function __construct($baseUrl) {
|
||||
$this->rawBaseUrl = $baseUrl;
|
||||
$this->__tConstruct($baseUrl . '/index.php/ocs/', ['admin', 'admin'], '123456');
|
||||
}
|
||||
|
||||
/** @var string */
|
||||
private $mappedUserId;
|
||||
|
||||
private $lastInsertIds = [];
|
||||
|
||||
/**
|
||||
* @BeforeSuite
|
||||
|
||||
@@ -32,3 +32,80 @@ Feature: decks
|
||||
And creates a board named "MyBoard" with color "000000"
|
||||
And create a stack named "ToDo"
|
||||
When create a card named "This is a very ong name that exceeds the maximum length of a deck board created which is longer than 255 characters This is a very ong name that exceeds the maximum length of a deck board created which is longer than 255 characters This is a very ong name that exceeds the maximum length of a deck board created which is longer than 255 characters"
|
||||
|
||||
Scenario: Cannot access card on a deleted board
|
||||
Given acting as user "user0"
|
||||
And creates a board named "MyBoard" with color "000000"
|
||||
And create a stack named "ToDo"
|
||||
And create a card named "Overdue task"
|
||||
And remember the last card as "deletedCard"
|
||||
And uploads an attachment to the last used card
|
||||
And remember the last attachment as "my-attachment"
|
||||
And post a comment with content "My first comment" on the card
|
||||
And delete the board
|
||||
|
||||
When fetching the attachment "my-attachment" for the card "deletedCard"
|
||||
Then the response should have a status code 403
|
||||
|
||||
When get the comments on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When post a comment with content "My second comment" on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When uploads an attachment to the last used card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When set the description to "Update some text"
|
||||
Then the response should have a status code 403
|
||||
|
||||
When get the card details
|
||||
Then the response should have a status code 403
|
||||
|
||||
When create a card named "Overdue task"
|
||||
Then the response should have a status code 403
|
||||
|
||||
When create a stack named "ToDo"
|
||||
Then the response should have a status code 403
|
||||
|
||||
Scenario: Cannot access card on a deleted card
|
||||
Given acting as user "user0"
|
||||
And creates a board named "MyBoard" with color "000000"
|
||||
And create a stack named "ToDo"
|
||||
And create a card named "Overdue task"
|
||||
And remember the last card as "deletedCard"
|
||||
And uploads an attachment to the last used card
|
||||
And remember the last attachment as "my-attachment"
|
||||
And post a comment with content "My first comment" on the card
|
||||
When get the activities for the last card
|
||||
Then the fetched activities should have 3 entries
|
||||
And delete the card
|
||||
|
||||
When get the activities for the last card
|
||||
Then the fetched activities should have 0 entries
|
||||
|
||||
When fetching the attachment "my-attachment" for the card "deletedCard"
|
||||
Then the response should have a status code 403
|
||||
|
||||
When get the comments on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When post a comment with content "My second comment" on the card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When deleting the attachment "my-attachment" for the card "deletedCard"
|
||||
Then the response should have a status code 403
|
||||
|
||||
When uploads an attachment to the last used card
|
||||
Then the response should have a status code 403
|
||||
|
||||
When get the card details
|
||||
Then the response should have a status code 403
|
||||
|
||||
# We currently still expect to be able to update the card as this is used to undo deletion
|
||||
When set the description to "Update some text"
|
||||
Then the response should have a status code 403
|
||||
When set the card attribute "deletedAt" to "0"
|
||||
Then the response should have a status code 200
|
||||
When set the description to "Update some text"
|
||||
Then the response should have a status code 200
|
||||
|
||||
@@ -74,6 +74,9 @@ class DeckProviderTest extends TestCase {
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->cardService = $this->createMock(CardService::class);
|
||||
$this->provider = new DeckProvider($this->urlGenerator, $this->activityManager, $this->userManager, $this->commentsManager, $this->l10nFactory, $this->config, $this->userId, $this->cardService);
|
||||
|
||||
$this->activityManager->method('canSeeCardActivity')->willReturn(true);
|
||||
$this->activityManager->method('canSeeBoardActivity')->willReturn(true);
|
||||
}
|
||||
|
||||
private function mockEvent($objectType, $objectId, $objectName, $subject, $subjectParameters = []) {
|
||||
|
||||
@@ -240,6 +240,8 @@ class PermissionServiceTest extends \Test\TestCase {
|
||||
->method('sharingDisabledForUser')
|
||||
->willReturn(false);
|
||||
|
||||
$this->aclMapper->method('findAll')->willReturn([]);
|
||||
|
||||
if ($result) {
|
||||
$actual = $this->service->checkPermission($mapper, 1234, $permission);
|
||||
$this->assertTrue($actual);
|
||||
@@ -262,6 +264,8 @@ class PermissionServiceTest extends \Test\TestCase {
|
||||
$this->boardMapper->expects($this->any())->method('find')->willReturn($board);
|
||||
}
|
||||
|
||||
$this->aclMapper->method('findAll')->willReturn([]);
|
||||
|
||||
if ($result) {
|
||||
$actual = $this->service->checkPermission($mapper, 1234, $permission);
|
||||
$this->assertTrue($actual);
|
||||
|
||||
Reference in New Issue
Block a user