feat: add validators to check values in services

Signed-off-by: Luka Trovic <luka@nextcloud.com>
This commit is contained in:
Luka Trovic
2022-09-13 19:14:59 +02:00
committed by Julius Härtl
parent f9acf7778f
commit 1217b37b19
22 changed files with 560 additions and 283 deletions

View File

@@ -13,7 +13,7 @@ describe('Board', function() {
})
it('Can create a board', function() {
const board = 'Test'
const board = 'TestBoard'
cy.intercept({
method: 'POST',

View File

@@ -35,6 +35,7 @@ use OCA\Deck\Event\CardUpdatedEvent;
use OCA\Deck\NoPermissionException;
use OCA\Deck\NotFoundException;
use OCA\Deck\Notification\NotificationHelper;
use OCA\Deck\Validators\AssignmentServiceValidator;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
@@ -76,6 +77,11 @@ class AssignmentService {
private $eventDispatcher;
/** @var string|null */
private $currentUser;
/**
* @var AssignmentServiceValidator
*/
private $assignmentServiceValidator;
public function __construct(
PermissionService $permissionService,
@@ -86,8 +92,10 @@ class AssignmentService {
ActivityManager $activityManager,
ChangeHelper $changeHelper,
IEventDispatcher $eventDispatcher,
AssignmentServiceValidator $assignmentServiceValidator,
$userId
) {
$this->assignmentServiceValidator = $assignmentServiceValidator;
$this->permissionService = $permissionService;
$this->cardMapper = $cardMapper;
$this->assignedUsersMapper = $assignedUsersMapper;
@@ -96,6 +104,8 @@ class AssignmentService {
$this->changeHelper = $changeHelper;
$this->activityManager = $activityManager;
$this->eventDispatcher = $eventDispatcher;
$this->assignmentServiceValidator->check(compact('userId'));
$this->currentUser = $userId;
}
@@ -109,13 +119,7 @@ class AssignmentService {
* @throws DoesNotExistException
*/
public function assignUser($cardId, $userId, int $type = Assignment::TYPE_USER) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('user id must be provided');
}
$this->assignmentServiceValidator->check(compact('cardId', 'userId'));
if ($type !== Assignment::TYPE_USER && $type !== Assignment::TYPE_GROUP) {
throw new BadRequestException('Invalid type provided for assignemnt');
@@ -168,16 +172,9 @@ class AssignmentService {
* @throws MultipleObjectsReturnedException
*/
public function unassignUser($cardId, $userId, $type = 0) {
$this->assignmentServiceValidator->check(compact('cardId', 'userId'));
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('user must be provided');
}
$assignments = $this->assignedUsersMapper->findAll($cardId);
foreach ($assignments as $assignment) {
if ($assignment->getParticipant() === $userId && $assignment->getType() === $type) {

View File

@@ -36,6 +36,7 @@ use OCA\Deck\NoPermissionException;
use OCA\Deck\NotFoundException;
use OCA\Deck\Cache\AttachmentCacheHelper;
use OCA\Deck\StatusException;
use OCA\Deck\Validators\AttachmentServiceValidator;
use OCP\AppFramework\Db\IMapperException;
use OCP\AppFramework\Http\Response;
use OCP\IL10N;
@@ -60,17 +61,22 @@ class AttachmentService {
/** @var ChangeHelper */
private $changeHelper;
private IUserManager $userManager;
/** @var AttachmentServiceValidator */
private AttachmentServiceValidator $attachmentServiceValidator;
public function __construct(AttachmentMapper $attachmentMapper,
CardMapper $cardMapper,
IUserManager $userManager,
ChangeHelper $changeHelper,
PermissionService $permissionService,
Application $application,
AttachmentCacheHelper $attachmentCacheHelper,
$userId,
IL10N $l10n,
ActivityManager $activityManager) {
public function __construct(
AttachmentMapper $attachmentMapper,
CardMapper $cardMapper,
IUserManager $userManager,
ChangeHelper $changeHelper,
PermissionService $permissionService,
Application $application,
AttachmentCacheHelper $attachmentCacheHelper,
$userId,
IL10N $l10n,
ActivityManager $activityManager,
AttachmentServiceValidator $attachmentServiceValidator
) {
$this->attachmentMapper = $attachmentMapper;
$this->cardMapper = $cardMapper;
$this->permissionService = $permissionService;
@@ -81,6 +87,7 @@ class AttachmentService {
$this->activityManager = $activityManager;
$this->changeHelper = $changeHelper;
$this->userManager = $userManager;
$this->attachmentServiceValidator = $attachmentServiceValidator;
// Register shipped attachment services
// TODO: move this to a plugin based approach once we have different types of attachments
@@ -187,17 +194,7 @@ class AttachmentService {
* @throws BadRequestException
*/
public function create($cardId, $type, $data) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
if ($type === false || $type === null) {
throw new BadRequestException('type must be provided');
}
if ($data === false || $data === null) {
//throw new BadRequestException('data must be provided');
}
$this->attachmentServiceValidator->check(compact('cardId', 'type', 'data'));
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
@@ -283,6 +280,8 @@ class AttachmentService {
* @throws NoPermissionException
*/
public function update($cardId, $attachmentId, $data, $type = 'deck_file') {
$this->attachmentServiceValidator->check(compact('cardId', 'type', 'data'));
try {
$service = $this->getService($type);
} catch (InvalidAttachmentType $e) {
@@ -304,9 +303,6 @@ class AttachmentService {
}
}
if ($data === false || $data === null) {
//throw new BadRequestException('data must be provided');
}
try {
$attachment = $this->attachmentMapper->find($attachmentId);
} catch (\Exception $e) {

View File

@@ -54,6 +54,7 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper;
use OCP\IUserManager;
use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\BoardServiceValidator;
use OCP\IURLGenerator;
use OCP\Server;
use Psr\Container\ContainerExceptionInterface;
@@ -79,6 +80,7 @@ class BoardService {
private ?array $boardsCache = null;
private IURLGenerator $urlGenerator;
private IDBConnection $connection;
private BoardServiceValidator $boardServiceValidator;
public function __construct(
BoardMapper $boardMapper,
@@ -98,6 +100,7 @@ class BoardService {
ChangeHelper $changeHelper,
IURLGenerator $urlGenerator,
IDBConnection $connection,
BoardServiceValidator $boardServiceValidator,
?string $userId
) {
$this->boardMapper = $boardMapper;
@@ -118,6 +121,7 @@ class BoardService {
$this->urlGenerator = $urlGenerator;
$this->cardMapper = $cardMapper;
$this->connection = $connection;
$this->boardServiceValidator = $boardServiceValidator;
}
/**
@@ -182,6 +186,7 @@ class BoardService {
* @throws BadRequestException
*/
public function find($boardId) {
$this->boardServiceValidator->check(compact('boardId'));
if ($this->boardsCache && isset($this->boardsCache[$boardId])) {
return $this->boardsCache[$boardId];
}
@@ -236,9 +241,7 @@ class BoardService {
* @throws BadRequestException
*/
public function isArchived($mapper, $id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->boardServiceValidator->check(compact('id'));
try {
$boardId = $id;
@@ -265,13 +268,7 @@ class BoardService {
* @throws BadRequestException
*/
public function isDeleted($mapper, $id) {
if ($mapper === false || $mapper === null) {
throw new BadRequestException('mapper must be provided');
}
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->boardServiceValidator->check(compact('mapper', 'id'));
try {
$boardId = $id;
@@ -297,17 +294,7 @@ class BoardService {
* @throws BadRequestException
*/
public function create($title, $userId, $color) {
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($userId === false || $userId === null) {
throw new BadRequestException('userId must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
$this->boardServiceValidator->check(compact('title', 'userId', 'color'));
if (!$this->permissionService->canCreate()) {
throw new NoPermissionException('Creating boards has been disabled for your account.');
@@ -358,9 +345,7 @@ class BoardService {
* @throws BadRequestException
*/
public function delete($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
$this->boardServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id);
@@ -383,9 +368,7 @@ class BoardService {
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/
public function deleteUndo($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
$this->boardServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id);
@@ -406,9 +389,7 @@ class BoardService {
* @throws BadRequestException
*/
public function deleteForce($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->boardServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id);
@@ -429,21 +410,7 @@ class BoardService {
* @throws BadRequestException
*/
public function update($id, $title, $color, $archived) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
if (is_bool($archived) === false) {
throw new BadRequestException('archived must be a boolean');
}
$this->boardServiceValidator->check(compact('id', 'title', 'color', 'archived'));
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id);
@@ -493,29 +460,7 @@ class BoardService {
* @throws \OCA\Deck\NoPermissionException
*/
public function addAcl($boardId, $type, $participant, $edit, $share, $manage) {
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
if ($type === false || $type === null) {
throw new BadRequestException('type must be provided');
}
if ($participant === false || $participant === null) {
throw new BadRequestException('participant must be provided');
}
if ($edit === null) {
throw new BadRequestException('edit must be provided');
}
if ($share === null) {
throw new BadRequestException('share must be provided');
}
if ($manage === null) {
throw new BadRequestException('manage must be provided');
}
$this->boardServiceValidator->check(compact('boardId', 'type', 'participant', 'edit', 'share', 'manage'));
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_SHARE);
[$edit, $share, $manage] = $this->applyPermissions($boardId, $edit, $share, $manage);
@@ -561,21 +506,7 @@ class BoardService {
* @throws BadRequestException
*/
public function updateAcl($id, $edit, $share, $manage) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
if ($edit === null) {
throw new BadRequestException('edit must be provided');
}
if ($share === null) {
throw new BadRequestException('share must be provided');
}
if ($manage === null) {
throw new BadRequestException('manage must be provided');
}
$this->boardServiceValidator->check(compact('id', 'edit', 'share', 'manage'));
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
@@ -643,9 +574,7 @@ class BoardService {
* @throws BadRequestException
*/
public function clone($id, $userId) {
if (is_numeric($id) === false) {
throw new BadRequestException('board id must be a number');
}
$this->boardServiceValidator->check(compact('id', 'userId'));
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);

View File

@@ -43,6 +43,7 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\CardServiceValidator;
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IRequest;
@@ -69,6 +70,7 @@ class CardService {
private IURLGenerator $urlGenerator;
private LoggerInterface $logger;
private IRequest $request;
private CardServiceValidator $cardServiceValidator;
public function __construct(
CardMapper $cardMapper,
@@ -88,6 +90,7 @@ class CardService {
IURLGenerator $urlGenerator,
LoggerInterface $logger,
IRequest $request,
CardServiceValidator $cardServiceValidator,
?string $userId
) {
$this->cardMapper = $cardMapper;
@@ -108,6 +111,7 @@ class CardService {
$this->urlGenerator = $urlGenerator;
$this->logger = $logger;
$this->request = $request;
$this->cardServiceValidator = $cardServiceValidator;
}
public function enrich($card) {
@@ -130,6 +134,7 @@ class CardService {
}
public function fetchDeleted($boardId) {
$this->cardServiceValidator->check(compact('boardId'));
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
$cards = $this->cardMapper->findDeleted($boardId);
foreach ($cards as $card) {
@@ -190,29 +195,7 @@ class CardService {
* @throws BadrequestException
*/
public function create($title, $stackId, $type, $order, $owner, $description = '', $duedate = null) {
if ($title === 'false' || $title === null) {
throw new BadRequestException('title must be provided');
}
if (mb_strlen($title) > Card::TITLE_MAX_LENGTH) {
throw new BadRequestException('The title cannot exceed 255 characters');
}
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number');
}
if ($type === 'false' || $type === null) {
throw new BadRequestException('type must be provided');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
if ($owner === false || $owner === null) {
throw new BadRequestException('owner must be provided');
}
$this->cardServiceValidator->check(compact('title', 'stackId', 'type', 'order', 'owner'));
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->stackMapper, $stackId)) {
@@ -282,29 +265,7 @@ class CardService {
* @throws BadRequestException
*/
public function update($id, $title, $stackId, $type, $owner, $description = '', $order = 0, $duedate = null, $deletedAt = null, $archived = null) {
if (is_numeric($id) === false) {
throw new BadRequestException('card id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if (mb_strlen($title) > Card::TITLE_MAX_LENGTH) {
throw new BadRequestException('The title cannot exceed 255 characters');
}
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number $$$');
}
if ($type === false || $type === null) {
throw new BadRequestException('type must be provided');
}
if ($owner === false || $owner === null) {
throw new BadRequestException('owner must be provided');
}
$this->cardServiceValidator->check(compact('id', 'title', 'stackId', 'type', 'owner', 'order'));
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
@@ -387,17 +348,7 @@ class CardService {
* @throws BadRequestException
*/
public function rename($id, $title) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if (mb_strlen($title) > Card::TITLE_MAX_LENGTH) {
throw new BadRequestException('The title cannot exceed 255 characters');
}
$this->cardServiceValidator->check(compact('id', 'title'));
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
@@ -428,17 +379,8 @@ class CardService {
* @throws BadRequestException
*/
public function reorder($id, $stackId, $order) {
if (is_numeric($id) === false) {
throw new BadRequestException('card id must be a number');
}
$this->cardServiceValidator->check(compact('id', 'stackId', 'order'));
if (is_numeric($stackId) === false) {
throw new BadRequestException('stack id must be a number');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
@@ -493,9 +435,8 @@ class CardService {
* @throws BadRequestException
*/
public function archive($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->cardServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
@@ -523,9 +464,8 @@ class CardService {
* @throws BadRequestException
*/
public function unarchive($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
$this->cardServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) {
@@ -552,13 +492,8 @@ class CardService {
* @throws BadRequestException
*/
public function assignLabel($cardId, $labelId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
$this->cardServiceValidator->check(compact('cardId', 'labelId'));
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
@@ -586,13 +521,8 @@ class CardService {
* @throws BadRequestException
*/
public function removeLabel($cardId, $labelId) {
if (is_numeric($cardId) === false) {
throw new BadRequestException('card id must be a number');
}
$this->cardServiceValidator->check(compact('cardId', 'labelId'));
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $cardId)) {

View File

@@ -29,6 +29,7 @@ use OCA\Deck\Db\Acl;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\LabelServiceValidator;
class LabelService {
@@ -40,12 +41,21 @@ class LabelService {
private $boardService;
/** @var ChangeHelper */
private $changeHelper;
/** @var LabelServiceValidator */
private LabelServiceValidator $labelServiceValidator;
public function __construct(LabelMapper $labelMapper, PermissionService $permissionService, BoardService $boardService, ChangeHelper $changeHelper) {
public function __construct(
LabelMapper $labelMapper,
PermissionService $permissionService,
BoardService $boardService,
ChangeHelper $changeHelper,
LabelServiceValidator $labelServiceValidator
) {
$this->labelMapper = $labelMapper;
$this->permissionService = $permissionService;
$this->boardService = $boardService;
$this->changeHelper = $changeHelper;
$this->labelServiceValidator = $labelServiceValidator;
}
/**
@@ -76,17 +86,7 @@ class LabelService {
* @throws BadRequestException
*/
public function create($title, $color, $boardId) {
if ($title === false || $title === null) {
throw new BadRequestException('title must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
$this->labelServiceValidator->check(compact('title', 'color', 'boardId'));
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
@@ -119,9 +119,7 @@ class LabelService {
* @throws BadRequestException
*/
public function delete($id) {
if (is_numeric($id) === false) {
throw new BadRequestException('label id must be a number');
}
$this->labelServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived($this->labelMapper, $id)) {
@@ -144,17 +142,7 @@ class LabelService {
* @throws BadRequestException
*/
public function update($id, $title, $color) {
if (is_numeric($id) === false) {
throw new BadRequestException('label id must be a number');
}
if ($title === false || $title === null || $title === "") {
throw new BadRequestException('title must be provided');
}
if ($color === false || $color === null) {
throw new BadRequestException('color must be provided');
}
$this->labelServiceValidator->check(compact('title', 'color', 'id'));
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);

View File

@@ -39,6 +39,7 @@ use OCA\Deck\Db\StackMapper;
use OCA\Deck\Model\CardDetails;
use OCA\Deck\NoPermissionException;
use OCA\Deck\StatusException;
use OCA\Deck\Validators\StackServiceValidator;
use Psr\Log\LoggerInterface;
class StackService {
@@ -54,6 +55,7 @@ class StackService {
private ActivityManager $activityManager;
private ChangeHelper $changeHelper;
private LoggerInterface $logger;
private StackServiceValidator $stackServiceValidator;
public function __construct(
StackMapper $stackMapper,
@@ -67,7 +69,8 @@ class StackService {
AttachmentService $attachmentService,
ActivityManager $activityManager,
ChangeHelper $changeHelper,
LoggerInterface $logger
LoggerInterface $logger,
StackServiceValidator $stackServiceValidator
) {
$this->stackMapper = $stackMapper;
$this->boardMapper = $boardMapper;
@@ -81,6 +84,7 @@ class StackService {
$this->activityManager = $activityManager;
$this->changeHelper = $changeHelper;
$this->logger = $logger;
$this->stackServiceValidator = $stackServiceValidator;
}
private function enrichStackWithCards($stack, $since = -1) {
@@ -218,17 +222,7 @@ class StackService {
* @throws BadRequestException
*/
public function create($title, $boardId, $order) {
if ($title === false || $title === null || mb_strlen($title) === 0) {
throw new BadRequestException('title must be provided');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
$this->stackServiceValidator->check(compact('title', 'boardId', 'order'));
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived(null, $boardId)) {
@@ -291,21 +285,7 @@ class StackService {
* @throws BadRequestException
*/
public function update($id, $title, $boardId, $order, $deletedAt) {
if (is_numeric($id) === false) {
throw new BadRequestException('stack id must be a number');
}
if ($title === false || $title === null || mb_strlen($title) === 0) {
throw new BadRequestException('title must be provided');
}
if (is_numeric($boardId) === false) {
throw new BadRequestException('board id must be a number');
}
if (is_numeric($order) === false) {
throw new BadRequestException('order must be a number');
}
$this->stackServiceValidator->check(compact('id', 'title', 'boardId', 'order'));
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE);
@@ -341,13 +321,7 @@ class StackService {
* @throws BadRequestException
*/
public function reorder($id, $order) {
if (is_numeric($id) === false) {
throw new BadRquestException('id must be a number');
}
if ($order === false || $order === null) {
throw new BadRequestException('order must be provided');
}
$this->stackServiceValidator->check(compact('id', 'order'));
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
$stackToSort = $this->stackMapper->find($id);

View File

@@ -0,0 +1,37 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
class AssignmentServiceValidator extends BaseValidator {
public function rules() {
return [
'cardId' => ['numeric'],
'userId' => ['not_empty', 'not_null', 'not_false', 'max:64'],
];
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
class AttachmentServiceValidator extends BaseValidator {
public function rules() {
return [
'cardId' => ['numeric'],
'type' => ['not_empty', 'not_null', 'not_false'],
'data' => ['not_empty', 'not_null', 'not_false', 'max:255'],
];
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
use Exception;
use OCA\Deck\BadRequestException;
abstract class BaseValidator {
/**
* @return array
*/
abstract public function rules();
/**
* Validate given entries
*
* @param array $data
* @return void
* @throws BadRequestException
*/
private function validate($data) {
$rules = $this->rules();
foreach ($data as $field => $value) {
$field_rule = $rules[$field];
if (is_array($field_rule)) {
foreach ($field_rule as $rule) {
// The format for specifying validation rules and parameters follows an
// easy {rule}:{parameters} formatting convention. For instance the
// rule "Max:3" states that the value may only be three letters.
if (strpos($rule, ':') !== false) {
[$rule, $parameter] = explode(':', $rule, 2);
if (!$this->{$rule}($value, $parameter)) {
throw new BadRequestException(
$this->getErrorMessage($rule, $field, $parameter));
}
} else {
if (!$this->{$rule}($value)) {
throw new BadRequestException(
$field . ' must be provided and must be '. str_replace("_", " ", $rule));
}
}
}
}
if (is_callable($field_rule) && !$field_rule($value)) {
throw new BadRequestException($field . ' must be provided');
}
}
}
/**
* @param array $data
* @return void
* @throws BadRequestException
*/
public function check(array $data) {
$this->validate($data);
}
/**
* @param $value
* @return bool
*/
private function numeric($value): bool {
return is_numeric($value);
}
/**
* @param $value
* @return bool
*/
private function bool($value): bool {
return is_bool($value);
}
/**
* @param $value
* @return bool
*/
private function not_false($value): bool {
return ($value !== false) && ($value !== 'false');
}
/**
* @param $value
* @return bool
*/
private function not_null($value): bool {
return !is_null($value);
}
/**
* @param $value
* @return bool
*/
private function not_empty($value): bool {
return !empty($value);
}
/**
* @throws Exception
*/
private function max($value, $limit): bool {
if (!$limit || !is_numeric($limit)) {
throw new Exception("Validation rule max requires at least 1 parameter. " . json_encode($limit));
}
return $this->getSize($value) <= $limit;
}
/**
* @throws Exception
*/
private function min($value, $limit): bool {
if (!$limit || !is_numeric($limit)) {
throw new Exception("Validation rule max requires at least 1 parameter.");
}
return $this->getSize($value) >= $limit;
}
/**
* Get the size of an attribute.
*
* @param mixed $value
* @return int
*/
protected function getSize($value): int {
// This method will determine if the attribute is a number or string and
// return the proper size accordingly. If it is a number, then number itself
// is the size.
if (is_int($value)) {
return $value;
} elseif (is_array($value)) {
return count($value);
}
return mb_strlen($value ?? '');
}
/**
* @param $rule
* @param $field
* @param $parameter
* @return string
*/
protected function getErrorMessage($rule, $field, $parameter = null): string {
if (in_array($rule, ['max', 'min'])) {
return $rule === 'max'
? $field . ' cannot be longer than '. $parameter . ' characters '
: $field . ' must be at least '. $parameter . ' characters long ';
}
return $field . ' must be provided and must be '. str_replace("_", " ", $rule);
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
class BoardServiceValidator extends BaseValidator {
public function rules() {
return [
'id' => ['numeric'],
'boardId' => ['numeric'],
'type' => ['numeric'],
'mapper' => ['not_empty', 'not_null', 'not_false'],
'title' => ['not_empty', 'not_null', 'not_false', 'max:100'],
'userId' => ['not_empty', 'not_null', 'not_false', 'max:64'],
'color' => ['not_empty', 'not_null', 'not_false', 'max:6'],
'participant' => ['not_empty', 'not_null', 'not_false', 'max:64'],
'edit' => ['not_null'],
'share' => ['not_null'],
'manage' => ['not_null'],
'archived' => ['bool']
];
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
class CardServiceValidator extends BaseValidator {
public function rules() {
return [
'id' => ['numeric'],
'title' => ['not_empty', 'not_null', 'not_false', 'max:255'],
'cardId' => ['numeric'],
'stackId' => ['numeric'],
'boardId' => ['numeric'],
'labelId' => ['numeric'],
'type' => ['not_empty', 'not_null', 'not_false', 'max:64'],
'order' => ['numeric'],
'owner' => ['not_empty', 'not_null', 'not_false', 'max:64'],
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
class LabelServiceValidator extends BaseValidator {
public function rules() {
return [
'id' => ['numeric'],
'title' => ['not_empty', 'not_null', 'not_false', 'max:100'],
'boardId' => ['numeric', 'not_null'],
'color' => ['not_empty', 'not_null', 'not_false', 'max:6']
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
* @author Maxence Lange <maxence@artificial-owl.com>
* @author Luka Trovic <luka.trovic@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
declare(strict_types=1);
namespace OCA\Deck\Validators;
class StackServiceValidator extends BaseValidator {
public function rules() {
return [
'id' => ['numeric'],
'title' => ['not_empty', 'not_null', 'not_false', 'max:100'],
'boardId' => ['numeric', 'not_null'],
'order' => ['numeric', 'not_null']
];
}
}

View File

@@ -70,9 +70,9 @@ export default {
startCreateBoard(e) {
this.editing = true
},
createBoard(e) {
async createBoard(e) {
const title = e.currentTarget.childNodes[0].value
this.$store.dispatch('createBoard', {
await this.$store.dispatch('createBoard', {
title,
color: this.color.substring(1),
})

View File

@@ -384,11 +384,13 @@ export default new Vuex.Store({
const storedBoard = await apiClient.updateBoard(board)
commit('addBoard', storedBoard)
},
createBoard({ commit }, boardData) {
apiClient.createBoard(boardData)
.then((board) => {
commit('addBoard', board)
})
async createBoard({ commit }, boardData) {
try {
const board = await apiClient.createBoard(boardData)
commit('addBoard', board)
} catch (err) {
return err
}
},
async cloneBoard({ commit }, boardData) {
try {

View File

@@ -32,6 +32,7 @@ use OCA\Deck\Db\CardMapper;
use OCA\Deck\Db\ChangeHelper;
use OCA\Deck\NotFoundException;
use OCA\Deck\Notification\NotificationHelper;
use OCA\Deck\Validators\AssignmentServiceValidator;
use OCP\Activity\IEvent;
use OCP\EventDispatcher\IEventDispatcher;
use PHPUnit\Framework\MockObject\MockObject;
@@ -76,6 +77,11 @@ class AssignmentServiceTest extends TestCase {
* @var AssignmentService
*/
private $assignmentService;
/**
* @var AssignmentServiceValidator
*/
private $assignmentServiceValidator;
public function setUp(): void {
parent::setUp();
@@ -87,6 +93,7 @@ class AssignmentServiceTest extends TestCase {
$this->activityManager = $this->createMock(ActivityManager::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->changeHelper = $this->createMock(ChangeHelper::class);
$this->assignmentServiceValidator = $this->createMock(AssignmentServiceValidator::class);
$this->assignmentService = new AssignmentService(
$this->permissionService,
$this->cardMapper,
@@ -96,6 +103,7 @@ class AssignmentServiceTest extends TestCase {
$this->activityManager,
$this->changeHelper,
$this->eventDispatcher,
$this->assignmentServiceValidator,
'admin'
);
}

View File

@@ -34,6 +34,7 @@ use OCA\Deck\Db\ChangeHelper;
use OCA\Deck\InvalidAttachmentType;
use OCA\Deck\NoPermissionException;
use OCA\Deck\NotFoundException;
use OCA\Deck\Validators\AttachmentServiceValidator;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\IAppContainer;
use OCP\IL10N;
@@ -89,6 +90,10 @@ class AttachmentServiceTest extends TestCase {
* @var IAttachmentService|MockObject
*/
private $filesAppServiceImpl;
/**
* @var AttachmentServiceValidator
*/
private $attachmentServiceValidator;
/**
* @throws \OCP\AppFramework\QueryException
@@ -126,6 +131,7 @@ class AttachmentServiceTest extends TestCase {
$this->l10n = $this->createMock(IL10N::class);
$this->changeHelper = $this->createMock(ChangeHelper::class);
$this->attachmentServiceValidator = $this->createMock(AttachmentServiceValidator::class);
$this->attachmentService = new AttachmentService(
$this->attachmentMapper,
@@ -137,7 +143,8 @@ class AttachmentServiceTest extends TestCase {
$this->attachmentCacheHelper,
$this->userId,
$this->l10n,
$this->activityManager
$this->activityManager,
$this->attachmentServiceValidator
);
}
@@ -163,7 +170,7 @@ class AttachmentServiceTest extends TestCase {
$application->expects($this->any())
->method('getContainer')
->willReturn($appContainer);
$attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->userManager, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager);
$attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->userManager, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager, $this->attachmentServiceValidator);
$attachmentService->registerAttachmentService('custom', MyAttachmentService::class);
$this->assertEquals($fileServiceMock, $attachmentService->getService('deck_file'));
$this->assertEquals(MyAttachmentService::class, get_class($attachmentService->getService('custom')));
@@ -193,7 +200,7 @@ class AttachmentServiceTest extends TestCase {
->method('getContainer')
->willReturn($appContainer);
$attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->userManager, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager);
$attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->userManager, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager, $this->attachmentServiceValidator);
$attachmentService->registerAttachmentService('custom', MyAttachmentService::class);
$attachmentService->getService('deck_file_invalid');
}

View File

@@ -46,6 +46,7 @@ use OCP\IGroupManager;
use PHPUnit\Framework\MockObject\MockObject;
use \Test\TestCase;
use OCP\IURLGenerator;
use OCA\Deck\Validators\BoardServiceValidator;
class BoardServiceTest extends TestCase {
@@ -84,6 +85,8 @@ class BoardServiceTest extends TestCase {
private $urlGenerator;
/** @var IDBConnection|MockObject */
private $connection;
/** @var BoardServiceValidator */
private $boardServiceValidator;
public function setUp(): void {
parent::setUp();
@@ -104,6 +107,7 @@ class BoardServiceTest extends TestCase {
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->connection = $this->createMock(IDBConnection::class);
$this->boardServiceValidator = $this->createMock(BoardServiceValidator::class);
$this->service = new BoardService(
$this->boardMapper,
@@ -123,6 +127,7 @@ class BoardServiceTest extends TestCase {
$this->changeHelper,
$this->urlGenerator,
$this->connection,
$this->boardServiceValidator,
$this->userId
);

View File

@@ -35,6 +35,7 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Notification\NotificationHelper;
use OCA\Deck\StatusException;
use OCA\Deck\Validators\CardServiceValidator;
use OCP\Activity\IEvent;
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
@@ -84,6 +85,8 @@ class CardServiceTest extends TestCase {
private $request;
/** @var LoggerInterface|MockObject */
private $logger;
/** @var CardServiceValidator|MockObject */
private $cardServiceValidator;
public function setUp(): void {
parent::setUp();
@@ -104,6 +107,7 @@ class CardServiceTest extends TestCase {
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->request = $this->createMock(IRequest::class);
$this->cardServiceValidator = $this->createMock(CardServiceValidator::class);
$this->logger->expects($this->any())->method('error');
@@ -125,6 +129,7 @@ class CardServiceTest extends TestCase {
$this->urlGenerator,
$this->logger,
$this->request,
$this->cardServiceValidator,
'user1'
);
}

View File

@@ -26,6 +26,7 @@ namespace OCA\Deck\Service;
use OCA\Deck\Db\ChangeHelper;
use OCA\Deck\Db\Label;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Validators\LabelServiceValidator;
use Test\TestCase;
class LabelServiceTest extends TestCase {
@@ -40,6 +41,8 @@ class LabelServiceTest extends TestCase {
private $boardService;
/** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */
private $changeHelper;
/** @var LabelServiceValidator\MockObject */
private $labelServiceValidator;
public function setUp(): void {
parent::setUp();
@@ -49,11 +52,14 @@ class LabelServiceTest extends TestCase {
->disableOriginalConstructor()->getMock();
$this->boardService = $this->createMock(BoardService::class);
$this->changeHelper = $this->createMock(ChangeHelper::class);
$this->labelServiceValidator = $this->createMock(LabelServiceValidator::class);
$this->labelService = new LabelService(
$this->labelMapper,
$this->permissionService,
$this->boardService,
$this->changeHelper
$this->changeHelper,
$this->labelServiceValidator,
);
}

View File

@@ -33,6 +33,7 @@ use OCA\Deck\Db\Label;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Db\Stack;
use OCA\Deck\Db\StackMapper;
use OCA\Deck\Validators\StackServiceValidator;
use Psr\Log\LoggerInterface;
use \Test\TestCase;
@@ -70,6 +71,8 @@ class StackServiceTest extends TestCase {
private $changeHelper;
/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
private $logger;
/** @var StackServiceValidator|\PHPUnit\Framework\MockObject\MockObject */
private $stackServiceValidator;
public function setUp(): void {
parent::setUp();
@@ -85,6 +88,7 @@ class StackServiceTest extends TestCase {
$this->activityManager = $this->createMock(ActivityManager::class);
$this->changeHelper = $this->createMock(ChangeHelper::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->stackServiceValidator = $this->createMock(StackServiceValidator::class);
$this->stackService = new StackService(
$this->stackMapper,
@@ -98,7 +102,8 @@ class StackServiceTest extends TestCase {
$this->attachmentService,
$this->activityManager,
$this->changeHelper,
$this->logger
$this->logger,
$this->stackServiceValidator
);
}