|
@@ -31,6 +31,13 @@ use Throwable;
|
|
|
*/
|
|
*/
|
|
|
final class TaskController
|
|
final class TaskController
|
|
|
{
|
|
{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * R01-N24: see SprintController::MAX_BATCH_ITEMS. Same rationale, same
|
|
|
|
|
+ * cap; reorder / assignments / status share the cell-style payload
|
|
|
|
|
+ * shape and need the same defence-in-depth bound.
|
|
|
|
|
+ */
|
|
|
|
|
+ public const MAX_BATCH_ITEMS = 5000;
|
|
|
|
|
+
|
|
|
public function __construct(
|
|
public function __construct(
|
|
|
private readonly PDO $pdo,
|
|
private readonly PDO $pdo,
|
|
|
private readonly UserRepository $users,
|
|
private readonly UserRepository $users,
|
|
@@ -267,6 +274,13 @@ final class TaskController
|
|
|
if (!is_array($body) || !array_is_list($body)) {
|
|
if (!is_array($body) || !array_is_list($body)) {
|
|
|
return Response::err('validation', 'body must be a list of {task_id, sort_order}', 422);
|
|
return Response::err('validation', 'body must be a list of {task_id, sort_order}', 422);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (count($body) > self::MAX_BATCH_ITEMS) {
|
|
|
|
|
+ return Response::err(
|
|
|
|
|
+ 'too_many_items',
|
|
|
|
|
+ 'reorder list exceeds ' . self::MAX_BATCH_ITEMS . '-item cap',
|
|
|
|
|
+ 413,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
$ordering = [];
|
|
$ordering = [];
|
|
|
$seenOrder = [];
|
|
$seenOrder = [];
|
|
@@ -327,6 +341,13 @@ final class TaskController
|
|
|
if ($body === []) {
|
|
if ($body === []) {
|
|
|
return Response::ok(['applied' => 0, 'noop' => 0]);
|
|
return Response::ok(['applied' => 0, 'noop' => 0]);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (count($body) > self::MAX_BATCH_ITEMS) {
|
|
|
|
|
+ return Response::err(
|
|
|
|
|
+ 'too_many_items',
|
|
|
|
|
+ 'assignment list exceeds ' . self::MAX_BATCH_ITEMS . '-item cap',
|
|
|
|
|
+ 413,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Cross-check sprint worker IDs belong to the task's sprint.
|
|
// Cross-check sprint worker IDs belong to the task's sprint.
|
|
|
$validSw = [];
|
|
$validSw = [];
|
|
@@ -430,6 +451,13 @@ final class TaskController
|
|
|
if ($body === []) {
|
|
if ($body === []) {
|
|
|
return Response::ok(['applied' => 0, 'noop' => 0]);
|
|
return Response::ok(['applied' => 0, 'noop' => 0]);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (count($body) > self::MAX_BATCH_ITEMS) {
|
|
|
|
|
+ return Response::err(
|
|
|
|
|
+ 'too_many_items',
|
|
|
|
|
+ 'status list exceeds ' . self::MAX_BATCH_ITEMS . '-item cap',
|
|
|
|
|
+ 413,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
$validSw = [];
|
|
$validSw = [];
|
|
|
foreach ($this->sprintWorkers->allForSprint($task->sprintId) as $sw) {
|
|
foreach ($this->sprintWorkers->allForSprint($task->sprintId) as $sw) {
|