Merge pull request #4175 from nextcloud/backport/4059/stable23

This commit is contained in:
Julius Härtl
2022-10-31 21:17:45 +01:00
committed by GitHub
24 changed files with 700 additions and 271 deletions

View File

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

View File

@@ -36,6 +36,7 @@ use OCA\Deck\NoPermissionException;
use OCA\Deck\NotFoundException; use OCA\Deck\NotFoundException;
use OCA\Deck\Cache\AttachmentCacheHelper; use OCA\Deck\Cache\AttachmentCacheHelper;
use OCA\Deck\StatusException; use OCA\Deck\StatusException;
use OCA\Deck\Validators\AttachmentServiceValidator;
use OCP\AppFramework\Db\IMapperException; use OCP\AppFramework\Db\IMapperException;
use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\Response;
use OCP\IL10N; use OCP\IL10N;
@@ -58,8 +59,10 @@ class AttachmentService {
private $activityManager; private $activityManager;
/** @var ChangeHelper */ /** @var ChangeHelper */
private $changeHelper; private $changeHelper;
/** @var AttachmentServiceValidator */
private $attachmentServiceValidator;
public function __construct(AttachmentMapper $attachmentMapper, CardMapper $cardMapper, ChangeHelper $changeHelper, PermissionService $permissionService, Application $application, AttachmentCacheHelper $attachmentCacheHelper, $userId, IL10N $l10n, ActivityManager $activityManager) { public function __construct(AttachmentMapper $attachmentMapper, CardMapper $cardMapper, ChangeHelper $changeHelper, PermissionService $permissionService, Application $application, AttachmentCacheHelper $attachmentCacheHelper, $userId, IL10N $l10n, ActivityManager $activityManager, AttachmentServiceValidator $attachmentServiceValidator) {
$this->attachmentMapper = $attachmentMapper; $this->attachmentMapper = $attachmentMapper;
$this->cardMapper = $cardMapper; $this->cardMapper = $cardMapper;
$this->permissionService = $permissionService; $this->permissionService = $permissionService;
@@ -69,6 +72,7 @@ class AttachmentService {
$this->l10n = $l10n; $this->l10n = $l10n;
$this->activityManager = $activityManager; $this->activityManager = $activityManager;
$this->changeHelper = $changeHelper; $this->changeHelper = $changeHelper;
$this->attachmentServiceValidator = $attachmentServiceValidator;
// Register shipped attachment services // Register shipped attachment services
// TODO: move this to a plugin based approach once we have different types of attachments // TODO: move this to a plugin based approach once we have different types of attachments
@@ -174,17 +178,7 @@ class AttachmentService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function create($cardId, $type, $data) { public function create($cardId, $type, $data) {
if (is_numeric($cardId) === false) { $this->attachmentServiceValidator->check(compact('cardId', 'type', 'data'));
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->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
@@ -269,6 +263,8 @@ class AttachmentService {
* @throws NoPermissionException * @throws NoPermissionException
*/ */
public function update($cardId, $attachmentId, $data, $type = 'deck_file') { public function update($cardId, $attachmentId, $data, $type = 'deck_file') {
$this->attachmentServiceValidator->check(compact('cardId', 'type', 'data'));
try { try {
$service = $this->getService($type); $service = $this->getService($type);
} catch (InvalidAttachmentType $e) { } catch (InvalidAttachmentType $e) {
@@ -290,9 +286,6 @@ class AttachmentService {
} }
} }
if ($data === false || $data === null) {
//throw new BadRequestException('data must be provided');
}
try { try {
$attachment = $this->attachmentMapper->find($attachmentId); $attachment = $this->attachmentMapper->find($attachmentId);
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@@ -52,6 +52,7 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper; use OCA\Deck\Db\LabelMapper;
use OCP\IUserManager; use OCP\IUserManager;
use OCA\Deck\BadRequestException; use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\BoardServiceValidator;
use OCP\IURLGenerator; use OCP\IURLGenerator;
class BoardService { class BoardService {
@@ -75,6 +76,7 @@ class BoardService {
private $boardsCache = null; private $boardsCache = null;
private $urlGenerator; private $urlGenerator;
private $boardServiceValidator;
public function __construct( public function __construct(
@@ -94,6 +96,7 @@ class BoardService {
IEventDispatcher $eventDispatcher, IEventDispatcher $eventDispatcher,
ChangeHelper $changeHelper, ChangeHelper $changeHelper,
IURLGenerator $urlGenerator, IURLGenerator $urlGenerator,
BoardServiceValidator $boardServiceValidator,
$userId $userId
) { ) {
$this->boardMapper = $boardMapper; $this->boardMapper = $boardMapper;
@@ -113,6 +116,7 @@ class BoardService {
$this->userId = $userId; $this->userId = $userId;
$this->urlGenerator = $urlGenerator; $this->urlGenerator = $urlGenerator;
$this->cardMapper = $cardMapper; $this->cardMapper = $cardMapper;
$this->boardServiceValidator = $boardServiceValidator;
} }
/** /**
@@ -177,6 +181,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function find($boardId) { public function find($boardId) {
$this->boardServiceValidator->check(compact('boardId'));
if ($this->boardsCache && isset($this->boardsCache[$boardId])) { if ($this->boardsCache && isset($this->boardsCache[$boardId])) {
return $this->boardsCache[$boardId]; return $this->boardsCache[$boardId];
} }
@@ -231,9 +236,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function isArchived($mapper, $id) { public function isArchived($mapper, $id) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id'));
throw new BadRequestException('id must be a number');
}
try { try {
$boardId = $id; $boardId = $id;
@@ -260,13 +263,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function isDeleted($mapper, $id) { public function isDeleted($mapper, $id) {
if ($mapper === false || $mapper === null) { $this->boardServiceValidator->check(compact('mapper', 'id'));
throw new BadRequestException('mapper must be provided');
}
if (is_numeric($id) === false) {
throw new BadRequestException('id must be a number');
}
try { try {
$boardId = $id; $boardId = $id;
@@ -292,17 +289,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function create($title, $userId, $color) { public function create($title, $userId, $color) {
if ($title === false || $title === null) { $this->boardServiceValidator->check(compact('title', 'userId', 'color'));
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');
}
if (!$this->permissionService->canCreate()) { if (!$this->permissionService->canCreate()) {
throw new NoPermissionException('Creating boards has been disabled for your account.'); throw new NoPermissionException('Creating boards has been disabled for your account.');
@@ -353,9 +340,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function delete($id) { public function delete($id) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id'));
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id); $board = $this->find($id);
@@ -378,9 +363,7 @@ class BoardService {
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/ */
public function deleteUndo($id) { public function deleteUndo($id) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id'));
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id); $board = $this->find($id);
@@ -401,9 +384,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function deleteForce($id) { public function deleteForce($id) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id'));
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id); $board = $this->find($id);
@@ -424,21 +405,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function update($id, $title, $color, $archived) { public function update($id, $title, $color, $archived) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id', 'title', 'color', 'archived'));
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->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
$board = $this->find($id); $board = $this->find($id);
@@ -488,29 +455,7 @@ class BoardService {
* @throws \OCA\Deck\NoPermissionException * @throws \OCA\Deck\NoPermissionException
*/ */
public function addAcl($boardId, $type, $participant, $edit, $share, $manage) { public function addAcl($boardId, $type, $participant, $edit, $share, $manage) {
if (is_numeric($boardId) === false) { $this->boardServiceValidator->check(compact('boardId', 'type', 'participant', 'edit', 'share', 'manage'));
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->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_SHARE); $this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_SHARE);
[$edit, $share, $manage] = $this->applyPermissions($boardId, $edit, $share, $manage); [$edit, $share, $manage] = $this->applyPermissions($boardId, $edit, $share, $manage);
@@ -556,21 +501,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function updateAcl($id, $edit, $share, $manage) { public function updateAcl($id, $edit, $share, $manage) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id', 'edit', 'share', 'manage'));
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->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE); $this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
@@ -642,9 +573,7 @@ class BoardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function clone($id, $userId) { public function clone($id, $userId) {
if (is_numeric($id) === false) { $this->boardServiceValidator->check(compact('id', 'userId'));
throw new BadRequestException('board id must be a number');
}
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ); $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\Db\LabelMapper;
use OCA\Deck\StatusException; use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException; use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\CardServiceValidator;
use OCP\Comments\ICommentsManager; use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUserManager; use OCP\IUserManager;
@@ -65,6 +66,7 @@ class CardService {
private $eventDispatcher; private $eventDispatcher;
private $userManager; private $userManager;
private $urlGenerator; private $urlGenerator;
private $cardServiceValidator;
public function __construct( public function __construct(
CardMapper $cardMapper, CardMapper $cardMapper,
@@ -82,6 +84,7 @@ class CardService {
ChangeHelper $changeHelper, ChangeHelper $changeHelper,
IEventDispatcher $eventDispatcher, IEventDispatcher $eventDispatcher,
IURLGenerator $urlGenerator, IURLGenerator $urlGenerator,
CardServiceValidator $cardServiceValidator,
$userId $userId
) { ) {
$this->cardMapper = $cardMapper; $this->cardMapper = $cardMapper;
@@ -100,6 +103,7 @@ class CardService {
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->currentUser = $userId; $this->currentUser = $userId;
$this->urlGenerator = $urlGenerator; $this->urlGenerator = $urlGenerator;
$this->cardServiceValidator = $cardServiceValidator;
} }
public function enrich($card) { public function enrich($card) {
@@ -122,6 +126,7 @@ class CardService {
} }
public function fetchDeleted($boardId) { public function fetchDeleted($boardId) {
$this->cardServiceValidator->check(compact('boardId'));
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ); $this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
$cards = $this->cardMapper->findDeleted($boardId); $cards = $this->cardMapper->findDeleted($boardId);
foreach ($cards as $card) { foreach ($cards as $card) {
@@ -187,29 +192,7 @@ class CardService {
* @throws BadrequestException * @throws BadrequestException
*/ */
public function create($title, $stackId, $type, $order, $owner, $description = '', $duedate = null) { public function create($title, $stackId, $type, $order, $owner, $description = '', $duedate = null) {
if ($title === 'false' || $title === null) { $this->cardServiceValidator->check(compact('title', 'stackId', 'type', 'order', 'owner'));
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->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->stackMapper, $stackId)) { if ($this->boardService->isArchived($this->stackMapper, $stackId)) {
@@ -279,29 +262,7 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function update($id, $title, $stackId, $type, $owner, $description = '', $order = 0, $duedate = null, $deletedAt = null, $archived = null) { public function update($id, $title, $stackId, $type, $owner, $description = '', $order = 0, $duedate = null, $deletedAt = null, $archived = null) {
if (is_numeric($id) === false) { $this->cardServiceValidator->check(compact('id', 'title', 'stackId', 'type', 'owner', 'order'));
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->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
@@ -384,17 +345,7 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function rename($id, $title) { public function rename($id, $title) {
if (is_numeric($id) === false) { $this->cardServiceValidator->check(compact('id', 'title'));
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->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) { if ($this->boardService->isArchived($this->cardMapper, $id)) {
@@ -425,17 +376,8 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function reorder($id, $stackId, $order) { public function reorder($id, $stackId, $order) {
if (is_numeric($id) === false) { $this->cardServiceValidator->check(compact('id', 'stackId', 'order'));
throw new BadRequestException('card id must be a number');
}
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->cardMapper, $id, Acl::PERMISSION_EDIT);
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
@@ -490,9 +432,8 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function archive($id) { public function archive($id) {
if (is_numeric($id) === false) { $this->cardServiceValidator->check(compact('id'));
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) { if ($this->boardService->isArchived($this->cardMapper, $id)) {
@@ -520,9 +461,8 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function unarchive($id) { public function unarchive($id) {
if (is_numeric($id) === false) { $this->cardServiceValidator->check(compact('id'));
throw new BadRequestException('id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) { if ($this->boardService->isArchived($this->cardMapper, $id)) {
@@ -549,13 +489,8 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function assignLabel($cardId, $labelId) { public function assignLabel($cardId, $labelId) {
if (is_numeric($cardId) === false) { $this->cardServiceValidator->check(compact('cardId', 'labelId'));
throw new BadRequestException('card id must be a number');
}
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $cardId)) { if ($this->boardService->isArchived($this->cardMapper, $cardId)) {
@@ -583,13 +518,8 @@ class CardService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function removeLabel($cardId, $labelId) { public function removeLabel($cardId, $labelId) {
if (is_numeric($cardId) === false) { $this->cardServiceValidator->check(compact('cardId', 'labelId'));
throw new BadRequestException('card id must be a number');
}
if (is_numeric($labelId) === false) {
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $cardId)) { 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\Db\LabelMapper;
use OCA\Deck\StatusException; use OCA\Deck\StatusException;
use OCA\Deck\BadRequestException; use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\LabelServiceValidator;
class LabelService { class LabelService {
@@ -40,12 +41,21 @@ class LabelService {
private $boardService; private $boardService;
/** @var ChangeHelper */ /** @var ChangeHelper */
private $changeHelper; private $changeHelper;
/** @var LabelServiceValidator */
private $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->labelMapper = $labelMapper;
$this->permissionService = $permissionService; $this->permissionService = $permissionService;
$this->boardService = $boardService; $this->boardService = $boardService;
$this->changeHelper = $changeHelper; $this->changeHelper = $changeHelper;
$this->labelServiceValidator = $labelServiceValidator;
} }
/** /**
@@ -76,17 +86,7 @@ class LabelService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function create($title, $color, $boardId) { public function create($title, $color, $boardId) {
if ($title === false || $title === null) { $this->labelServiceValidator->check(compact('title', 'color', 'boardId'));
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->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
@@ -121,9 +121,7 @@ class LabelService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function delete($id) { public function delete($id) {
if (is_numeric($id) === false) { $this->labelServiceValidator->check(compact('id'));
throw new BadRequestException('label id must be a number');
}
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived($this->labelMapper, $id)) { if ($this->boardService->isArchived($this->labelMapper, $id)) {
@@ -146,17 +144,7 @@ class LabelService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function update($id, $title, $color) { public function update($id, $title, $color) {
if (is_numeric($id) === false) { $this->labelServiceValidator->check(compact('title', 'color', 'id'));
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->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);

View File

@@ -37,6 +37,7 @@ use OCA\Deck\Db\Stack;
use OCA\Deck\Db\StackMapper; use OCA\Deck\Db\StackMapper;
use OCA\Deck\NoPermissionException; use OCA\Deck\NoPermissionException;
use OCA\Deck\StatusException; use OCA\Deck\StatusException;
use OCA\Deck\Validators\StackServiceValidator;
class StackService { class StackService {
private $stackMapper; private $stackMapper;
@@ -50,6 +51,7 @@ class StackService {
private $attachmentService; private $attachmentService;
private $activityManager; private $activityManager;
private $changeHelper; private $changeHelper;
private $stackServiceValidator;
public function __construct( public function __construct(
StackMapper $stackMapper, StackMapper $stackMapper,
@@ -62,6 +64,7 @@ class StackService {
AssignmentMapper $assignedUsersMapper, AssignmentMapper $assignedUsersMapper,
AttachmentService $attachmentService, AttachmentService $attachmentService,
ActivityManager $activityManager, ActivityManager $activityManager,
StackServiceValidator $stackServiceValidator,
ChangeHelper $changeHelper ChangeHelper $changeHelper
) { ) {
$this->stackMapper = $stackMapper; $this->stackMapper = $stackMapper;
@@ -75,6 +78,7 @@ class StackService {
$this->attachmentService = $attachmentService; $this->attachmentService = $attachmentService;
$this->activityManager = $activityManager; $this->activityManager = $activityManager;
$this->changeHelper = $changeHelper; $this->changeHelper = $changeHelper;
$this->stackServiceValidator = $stackServiceValidator;
} }
private function enrichStackWithCards($stack, $since = -1) { private function enrichStackWithCards($stack, $since = -1) {
@@ -202,17 +206,7 @@ class StackService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function create($title, $boardId, $order) { public function create($title, $boardId, $order) {
if ($title === false || $title === null) { $this->stackServiceValidator->check(compact('title', 'boardId', 'order'));
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->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
if ($this->boardService->isArchived(null, $boardId)) { if ($this->boardService->isArchived(null, $boardId)) {
@@ -275,21 +269,7 @@ class StackService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function update($id, $title, $boardId, $order, $deletedAt) { public function update($id, $title, $boardId, $order, $deletedAt) {
if (is_numeric($id) === false) { $this->stackServiceValidator->check(compact('id', 'title', 'boardId', 'order'));
throw new BadRequestException('stack id must be a number');
}
if ($title === false || $title === null) {
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->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE);
@@ -325,13 +305,7 @@ class StackService {
* @throws BadRequestException * @throws BadRequestException
*/ */
public function reorder($id, $order) { public function reorder($id, $order) {
if (is_numeric($id) === false) { $this->stackServiceValidator->check(compact('id', 'order'));
throw new BadRquestException('id must be a number');
}
if ($order === false || $order === null) {
throw new BadRequestException('order must be provided');
}
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
$stackToSort = $this->stackMapper->find($id); $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) { startCreateBoard(e) {
this.editing = true this.editing = true
}, },
createBoard(e) { async createBoard(e) {
const title = e.currentTarget.childNodes[0].value const title = e.currentTarget.childNodes[0].value
this.$store.dispatch('createBoard', { await this.$store.dispatch('createBoard', {
title, title,
color: this.color.substring(1), color: this.color.substring(1),
}) })

View File

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

View File

@@ -13,3 +13,22 @@ Feature: decks
|key|value| |key|value|
|title|MyBoard| |title|MyBoard|
|color|000000| |color|000000|
Scenario: Fail to create a board with invalid parameters
Given acting as user "user0"
When creates a board named "This is a very ong name that exceeds the maximum length of a deck board created which is longer than 100 characters" with color "ff0000"
Then the response should have a status code 400
When creates a board named "Example board" with color "invalid"
Then the response should have a status code 400
Scenario: Fail to create a list with invalid parameters
Given acting as user "user0"
And creates a board named "MyBoard" with color "000000"
When create a stack named "This is a very ong name that exceeds the maximum length of a deck board created which is longer than 100 characters"
Then the response should have a status code 400
Scenario: Fail to create a card with invalid parameters
Given acting as user "user0"
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"

View File

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

View File

@@ -34,6 +34,7 @@ use OCA\Deck\Db\ChangeHelper;
use OCA\Deck\InvalidAttachmentType; use OCA\Deck\InvalidAttachmentType;
use OCA\Deck\NoPermissionException; use OCA\Deck\NoPermissionException;
use OCA\Deck\NotFoundException; use OCA\Deck\NotFoundException;
use OCA\Deck\Validators\AttachmentServiceValidator;
use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\Response;
use OCP\AppFramework\IAppContainer; use OCP\AppFramework\IAppContainer;
use OCP\IL10N; use OCP\IL10N;
@@ -86,6 +87,10 @@ class AttachmentServiceTest extends TestCase {
* @var IAttachmentService|MockObject * @var IAttachmentService|MockObject
*/ */
private $filesAppServiceImpl; private $filesAppServiceImpl;
/**
* @var AttachmentServiceValidator
*/
private $attachmentServiceValidator;
/** /**
* @throws \OCP\AppFramework\QueryException * @throws \OCP\AppFramework\QueryException
@@ -122,6 +127,7 @@ class AttachmentServiceTest extends TestCase {
$this->l10n = $this->createMock(IL10N::class); $this->l10n = $this->createMock(IL10N::class);
$this->changeHelper = $this->createMock(ChangeHelper::class); $this->changeHelper = $this->createMock(ChangeHelper::class);
$this->attachmentServiceValidator = $this->createMock(AttachmentServiceValidator::class);
$this->attachmentService = new AttachmentService( $this->attachmentService = new AttachmentService(
$this->attachmentMapper, $this->attachmentMapper,
@@ -132,7 +138,8 @@ class AttachmentServiceTest extends TestCase {
$this->attachmentCacheHelper, $this->attachmentCacheHelper,
$this->userId, $this->userId,
$this->l10n, $this->l10n,
$this->activityManager $this->activityManager,
$this->attachmentServiceValidator
); );
} }
@@ -158,7 +165,7 @@ class AttachmentServiceTest extends TestCase {
$application->expects($this->any()) $application->expects($this->any())
->method('getContainer') ->method('getContainer')
->willReturn($appContainer); ->willReturn($appContainer);
$attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager); $attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager, $this->attachmentServiceValidator);
$attachmentService->registerAttachmentService('custom', MyAttachmentService::class); $attachmentService->registerAttachmentService('custom', MyAttachmentService::class);
$this->assertEquals($fileServiceMock, $attachmentService->getService('deck_file')); $this->assertEquals($fileServiceMock, $attachmentService->getService('deck_file'));
$this->assertEquals(MyAttachmentService::class, get_class($attachmentService->getService('custom'))); $this->assertEquals(MyAttachmentService::class, get_class($attachmentService->getService('custom')));
@@ -188,7 +195,7 @@ class AttachmentServiceTest extends TestCase {
->method('getContainer') ->method('getContainer')
->willReturn($appContainer); ->willReturn($appContainer);
$attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager); $attachmentService = new AttachmentService($this->attachmentMapper, $this->cardMapper, $this->changeHelper, $this->permissionService, $application, $this->attachmentCacheHelper, $this->userId, $this->l10n, $this->activityManager, $this->attachmentServiceValidator);
$attachmentService->registerAttachmentService('custom', MyAttachmentService::class); $attachmentService->registerAttachmentService('custom', MyAttachmentService::class);
$attachmentService->getService('deck_file_invalid'); $attachmentService->getService('deck_file_invalid');
} }

View File

@@ -44,6 +44,7 @@ use OCP\IUserManager;
use OCP\IGroupManager; use OCP\IGroupManager;
use \Test\TestCase; use \Test\TestCase;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use OCA\Deck\Validators\BoardServiceValidator;
class BoardServiceTest extends TestCase { class BoardServiceTest extends TestCase {
@@ -80,6 +81,8 @@ class BoardServiceTest extends TestCase {
private $userId = 'admin'; private $userId = 'admin';
/** @var IURLGenerator */ /** @var IURLGenerator */
private $urlGenerator; private $urlGenerator;
/** @var BoardServiceValidator */
private $boardServiceValidator;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
@@ -99,6 +102,7 @@ class BoardServiceTest extends TestCase {
$this->changeHelper = $this->createMock(ChangeHelper::class); $this->changeHelper = $this->createMock(ChangeHelper::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class); $this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->boardServiceValidator = $this->createMock(BoardServiceValidator::class);
$this->service = new BoardService( $this->service = new BoardService(
$this->boardMapper, $this->boardMapper,
@@ -117,6 +121,7 @@ class BoardServiceTest extends TestCase {
$this->eventDispatcher, $this->eventDispatcher,
$this->changeHelper, $this->changeHelper,
$this->urlGenerator, $this->urlGenerator,
$this->boardServiceValidator,
$this->userId $this->userId
); );

View File

@@ -35,6 +35,7 @@ use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\LabelMapper; use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Notification\NotificationHelper; use OCA\Deck\Notification\NotificationHelper;
use OCA\Deck\StatusException; use OCA\Deck\StatusException;
use OCA\Deck\Validators\CardServiceValidator;
use OCP\Activity\IEvent; use OCP\Activity\IEvent;
use OCP\Comments\ICommentsManager; use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventDispatcher;
@@ -79,6 +80,8 @@ class CardServiceTest extends TestCase {
/** @var IURLGenerator|MockObject */ /** @var IURLGenerator|MockObject */
private $urlGenerator; private $urlGenerator;
/** @var CardServiceValidator|MockObject */
private $cardServiceValidator;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
@@ -97,6 +100,8 @@ class CardServiceTest extends TestCase {
$this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->changeHelper = $this->createMock(ChangeHelper::class); $this->changeHelper = $this->createMock(ChangeHelper::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class); $this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->cardServiceValidator = $this->createMock(CardServiceValidator::class);
$this->cardService = new CardService( $this->cardService = new CardService(
$this->cardMapper, $this->cardMapper,
$this->stackMapper, $this->stackMapper,
@@ -113,6 +118,7 @@ class CardServiceTest extends TestCase {
$this->changeHelper, $this->changeHelper,
$this->eventDispatcher, $this->eventDispatcher,
$this->urlGenerator, $this->urlGenerator,
$this->cardServiceValidator,
'user1' 'user1'
); );
} }

View File

@@ -26,6 +26,7 @@ namespace OCA\Deck\Service;
use OCA\Deck\Db\ChangeHelper; use OCA\Deck\Db\ChangeHelper;
use OCA\Deck\Db\Label; use OCA\Deck\Db\Label;
use OCA\Deck\Db\LabelMapper; use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Validators\LabelServiceValidator;
use Test\TestCase; use Test\TestCase;
class LabelServiceTest extends TestCase { class LabelServiceTest extends TestCase {
@@ -40,6 +41,8 @@ class LabelServiceTest extends TestCase {
private $boardService; private $boardService;
/** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */ /** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */
private $changeHelper; private $changeHelper;
/** @var LabelServiceValidator\MockObject */
private $labelServiceValidator;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
@@ -49,11 +52,14 @@ class LabelServiceTest extends TestCase {
->disableOriginalConstructor()->getMock(); ->disableOriginalConstructor()->getMock();
$this->boardService = $this->createMock(BoardService::class); $this->boardService = $this->createMock(BoardService::class);
$this->changeHelper = $this->createMock(ChangeHelper::class); $this->changeHelper = $this->createMock(ChangeHelper::class);
$this->labelServiceValidator = $this->createMock(LabelServiceValidator::class);
$this->labelService = new LabelService( $this->labelService = new LabelService(
$this->labelMapper, $this->labelMapper,
$this->permissionService, $this->permissionService,
$this->boardService, $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\LabelMapper;
use OCA\Deck\Db\Stack; use OCA\Deck\Db\Stack;
use OCA\Deck\Db\StackMapper; use OCA\Deck\Db\StackMapper;
use OCA\Deck\Validators\StackServiceValidator;
use \Test\TestCase; use \Test\TestCase;
/** /**
@@ -67,6 +68,8 @@ class StackServiceTest extends TestCase {
private $activityManager; private $activityManager;
/** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */ /** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */
private $changeHelper; private $changeHelper;
/** @var StackServiceValidator|\PHPUnit\Framework\MockObject\MockObject */
private $stackServiceValidator;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
@@ -81,6 +84,7 @@ class StackServiceTest extends TestCase {
$this->labelMapper = $this->createMock(LabelMapper::class); $this->labelMapper = $this->createMock(LabelMapper::class);
$this->activityManager = $this->createMock(ActivityManager::class); $this->activityManager = $this->createMock(ActivityManager::class);
$this->changeHelper = $this->createMock(ChangeHelper::class); $this->changeHelper = $this->createMock(ChangeHelper::class);
$this->stackServiceValidator = $this->createMock(StackServiceValidator::class);
$this->stackService = new StackService( $this->stackService = new StackService(
$this->stackMapper, $this->stackMapper,
@@ -93,6 +97,7 @@ class StackServiceTest extends TestCase {
$this->assignedUsersMapper, $this->assignedUsersMapper,
$this->attachmentService, $this->attachmentService,
$this->activityManager, $this->activityManager,
$this->stackServiceValidator,
$this->changeHelper $this->changeHelper
); );
} }

View File

@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @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/>.
*/
namespace OCA\Deck\Validators;
use OCA\Deck\Tests\unit\Validators\ValidatorTestBase;
class StackServiceValidatorTest extends ValidatorTestBase {
public function setUp(): void {
parent::setUpValidatorTest(StackServiceValidator::class);
}
public function testTitle() {
$this->assertPass([
'title' => 'Short title',
]);
$this->assertPass([
'title' => str_repeat('A', 100)
]);
$this->assertFail([
'title' => str_repeat('A', 101)
]);
$this->assertFail([
'title' => '',
]);
$this->assertFail([
'title' => null,
]);
}
public function testId() {
$this->assertPass([ 'id' => 1234 ]);
$this->assertPass([ 'id' => '1234' ]);
$this->assertFail([ 'id' => 'a1234' ]);
$this->assertFail([ 'id' => '' ]);
$this->assertFail([ 'id' => null ]);
}
public function testBoardId() {
$this->assertPass([ 'boardId' => 1234 ]);
$this->assertPass([ 'boardId' => '1234' ]);
$this->assertFail([ 'boardId' => 'a1234' ]);
$this->assertFail([ 'boardId' => '' ]);
$this->assertFail([ 'boardId' => null ]);
}
public function testOrder() {
$this->assertPass([ 'order' => 1234 ]);
$this->assertPass([ 'order' => '1234' ]);
$this->assertFail([ 'order' => 'a1234' ]);
$this->assertFail([ 'order' => '' ]);
$this->assertFail([ 'order' => null ]);
}
}

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @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/>.
*/
namespace OCA\Deck\Tests\unit\Validators;
use OCA\Deck\BadRequestException;
use OCA\Deck\Validators\BaseValidator;
abstract class ValidatorTestBase extends \PHPUnit\Framework\TestCase {
/** @var BaseValidator */
protected $validator;
public function setUpValidatorTest($class = null): void {
parent::setUp();
$this->validator = new $class();
}
protected function assertPass($values) {
self::assertTrue($this->check($values));
}
protected function assertFail($values) {
self::assertFalse($this->check($values));
}
private function check($values) {
try {
$this->validator->check($values);
return true;
} catch (BadRequestException $e) {
return false;
}
}
}