Fix/team security review #1

Merged
Twyco merged 7 commits from fix/team-security-review into main 2026-09-24 09:21:54 +00:00
4 changed files with 41 additions and 4 deletions
Showing only changes of commit d4434446ec - Show all commits
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Concerns;
trait ReservedSlugs
{
public function isReserved(string $slug): bool
{
return in_array($slug, $this->reservedSlugs());
}
public function reservedSlugs(): array
{
return [
'index',
'edit',
'update',
'create',
'store',
'delete',
'destroy',
'revoke',
'invite',
'accept',
];
}
}
+6 -2
View File
@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Concerns\ReservedSlugs;
use App\Enums\TeamMemberRole;
use App\Http\Requests\StoreTeamRequest;
use App\Http\Requests\UpdateTeamRequest;
@@ -19,6 +20,9 @@ use Inertia\Response;
class TeamController extends Controller
{
use ReservedSlugs;
/**
* Display a listing of the resource.
*/
@@ -112,7 +116,7 @@ class TeamController extends Controller
return response()->json([
'name' => $name,
'slug' => $slug,
'taken' => $slug === 'create' || ($slug !== $ignoredSlug && Team::whereSlug($slug)->exists()),
'taken' => $this->isReserved($slug) || ($slug !== $ignoredSlug && Team::whereSlug($slug)->exists()),
]);
}
@@ -138,7 +142,7 @@ class TeamController extends Controller
'email' => 'required|email|max:255',
]);
$teamInvite = $team->invites()->whereInvitedEmail($validated['email'])->firstOrFail();
$teamInvite = $team->invites()->whereInvitedEmail(Arr::get($validated,'email'))->firstOrFail();
try {
$teamInvite->delete();
+5 -1
View File
@@ -2,6 +2,7 @@
namespace App\Http\Requests;
use App\Concerns\ReservedSlugs;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Str;
@@ -9,6 +10,9 @@ use Illuminate\Validation\Rule;
class StoreTeamRequest extends FormRequest
{
use ReservedSlugs;
/**
* Get the validation rules that apply to the request.
*
@@ -18,7 +22,7 @@ class StoreTeamRequest extends FormRequest
{
return [
'name' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'max:255', Rule::notIn(['create']), Rule::unique('teams', 'slug')],
'slug' => ['required', 'string', 'max:255', Rule::notIn($this->reservedSlugs()), Rule::unique('teams', 'slug')],
'require_2fa' => ['required', 'boolean'],
];
}
+3 -1
View File
@@ -2,6 +2,7 @@
namespace App\Http\Requests;
use App\Concerns\ReservedSlugs;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Str;
@@ -9,6 +10,7 @@ use Illuminate\Validation\Rule;
class UpdateTeamRequest extends FormRequest
{
use ReservedSlugs;
/**
* Get the validation rules that apply to the request.
*
@@ -18,7 +20,7 @@ class UpdateTeamRequest extends FormRequest
{
return [
'name' => ['sometimes', 'required', 'string', 'max:255'],
'slug' => [Rule::excludeIf(! $this->has('name')), 'required', 'string', 'max:255', Rule::notIn(['create']), Rule::unique('teams', 'slug')->ignore($this->route('team'))],
'slug' => [Rule::excludeIf(! $this->has('name')), 'required', 'string', 'max:255', Rule::notIn($this->reservedSlugs()), Rule::unique('teams', 'slug')->ignore($this->route('team'))],
'require_2fa' => ['required', 'boolean'],
];
}