|
@@ -14,7 +14,6 @@ namespace App\Controllers;
|
|
|
|
|
|
|
|
use App\Auth\SessionGuard;
|
|
use App\Auth\SessionGuard;
|
|
|
use App\Domain\SprintWeek;
|
|
use App\Domain\SprintWeek;
|
|
|
-use App\Domain\User;
|
|
|
|
|
use App\Http\Request;
|
|
use App\Http\Request;
|
|
|
use App\Http\Response;
|
|
use App\Http\Response;
|
|
|
use App\Http\View;
|
|
use App\Http\View;
|
|
@@ -90,13 +89,10 @@ final class SprintController
|
|
|
/** POST /sprints — create sprint + materialise weeks in one tx. */
|
|
/** POST /sprints — create sprint + materialise weeks in one tx. */
|
|
|
public function create(Request $req): Response
|
|
public function create(Request $req): Response
|
|
|
{
|
|
{
|
|
|
- $actor = SessionGuard::requireAdmin($this->users);
|
|
|
|
|
|
|
+ $actor = SessionGuard::requireAdminForm($req, $this->users);
|
|
|
if ($actor instanceof Response) {
|
|
if ($actor instanceof Response) {
|
|
|
return $actor;
|
|
return $actor;
|
|
|
}
|
|
}
|
|
|
- if (!SessionGuard::verifyCsrf($req)) {
|
|
|
|
|
- return Response::text('CSRF token invalid', 403);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
$name = trim($req->postString('name'));
|
|
$name = trim($req->postString('name'));
|
|
|
$start = $req->postString('start_date');
|
|
$start = $req->postString('start_date');
|
|
@@ -346,7 +342,7 @@ final class SprintController
|
|
|
/** PATCH /sprints/{id} — JSON — update name / dates / reserve_fraction. */
|
|
/** PATCH /sprints/{id} — JSON — update name / dates / reserve_fraction. */
|
|
|
public function updateMeta(Request $req, array $params): Response
|
|
public function updateMeta(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -507,7 +503,7 @@ final class SprintController
|
|
|
/** POST /sprints/{id}/weeks — JSON — resize the week set. */
|
|
/** POST /sprints/{id}/weeks — JSON — resize the week set. */
|
|
|
public function replaceWeeks(Request $req, array $params): Response
|
|
public function replaceWeeks(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -586,7 +582,7 @@ final class SprintController
|
|
|
/** POST /sprints/{id}/workers — JSON — add a worker to the sprint. */
|
|
/** POST /sprints/{id}/workers — JSON — add a worker to the sprint. */
|
|
|
public function addWorker(Request $req, array $params): Response
|
|
public function addWorker(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -646,7 +642,7 @@ final class SprintController
|
|
|
/** DELETE /sprints/{id}/workers/{sw_id} — JSON — remove a worker from the sprint. */
|
|
/** DELETE /sprints/{id}/workers/{sw_id} — JSON — remove a worker from the sprint. */
|
|
|
public function removeWorker(Request $req, array $params): Response
|
|
public function removeWorker(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -702,7 +698,7 @@ final class SprintController
|
|
|
/** POST /sprints/{id}/workers/reorder — JSON — apply an ordering. */
|
|
/** POST /sprints/{id}/workers/reorder — JSON — apply an ordering. */
|
|
|
public function reorderWorkers(Request $req, array $params): Response
|
|
public function reorderWorkers(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -759,7 +755,7 @@ final class SprintController
|
|
|
/** PATCH /sprints/{id}/workers/{sw_id} — JSON — edit RTB. */
|
|
/** PATCH /sprints/{id}/workers/{sw_id} — JSON — edit RTB. */
|
|
|
public function updateWorker(Request $req, array $params): Response
|
|
public function updateWorker(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -803,7 +799,7 @@ final class SprintController
|
|
|
/** PATCH /sprints/{id}/week-cells — JSON — batch upsert of sprint_worker_days. */
|
|
/** PATCH /sprints/{id}/week-cells — JSON — batch upsert of sprint_worker_days. */
|
|
|
public function updateWeekCells(Request $req, array $params): Response
|
|
public function updateWeekCells(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -925,7 +921,7 @@ final class SprintController
|
|
|
*/
|
|
*/
|
|
|
public function updateWeekDays(Request $req, array $params): Response
|
|
public function updateWeekDays(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $gate = $this->gateJsonAdmin($req);
|
|
|
|
|
|
|
+ $gate = SessionGuard::requireAdminJson($req, $this->users);
|
|
|
if ($gate instanceof Response) {
|
|
if ($gate instanceof Response) {
|
|
|
return $gate;
|
|
return $gate;
|
|
|
}
|
|
}
|
|
@@ -1017,13 +1013,10 @@ final class SprintController
|
|
|
*/
|
|
*/
|
|
|
public function delete(Request $req, array $params): Response
|
|
public function delete(Request $req, array $params): Response
|
|
|
{
|
|
{
|
|
|
- $actor = SessionGuard::requireAdmin($this->users);
|
|
|
|
|
|
|
+ $actor = SessionGuard::requireAdminForm($req, $this->users);
|
|
|
if ($actor instanceof Response) {
|
|
if ($actor instanceof Response) {
|
|
|
return $actor;
|
|
return $actor;
|
|
|
}
|
|
}
|
|
|
- if (!SessionGuard::verifyCsrf($req)) {
|
|
|
|
|
- return Response::text('CSRF token invalid', 403);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
$sprintId = (int) $params['id'];
|
|
$sprintId = (int) $params['id'];
|
|
|
$sprint = $this->sprints->find($sprintId);
|
|
$sprint = $this->sprints->find($sprintId);
|
|
@@ -1162,25 +1155,6 @@ final class SprintController
|
|
|
// Shared helpers
|
|
// Shared helpers
|
|
|
// ------------------------------------------------------------------
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * Admin gate for JSON endpoints. Returns the signed-in User on success,
|
|
|
|
|
- * or an `Response::err(...)` JSON envelope on failure. Also enforces CSRF.
|
|
|
|
|
- */
|
|
|
|
|
- private function gateJsonAdmin(Request $req): User|Response
|
|
|
|
|
- {
|
|
|
|
|
- $user = SessionGuard::currentUser($this->users);
|
|
|
|
|
- if ($user === null) {
|
|
|
|
|
- return Response::err('unauthenticated', 'Sign in required', 401);
|
|
|
|
|
- }
|
|
|
|
|
- if (!$user->isAdmin) {
|
|
|
|
|
- return Response::err('forbidden', 'Admin access required', 403);
|
|
|
|
|
- }
|
|
|
|
|
- if (!SessionGuard::verifyCsrf($req)) {
|
|
|
|
|
- return Response::err('csrf', 'CSRF token invalid', 403);
|
|
|
|
|
- }
|
|
|
|
|
- return $user;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private static function isIsoDate(string $s): bool
|
|
private static function isIsoDate(string $s): bool
|
|
|
{
|
|
{
|
|
|
$d = DateTimeImmutable::createFromFormat('Y-m-d', $s);
|
|
$d = DateTimeImmutable::createFromFormat('Y-m-d', $s);
|