From 7323ffec2b877fd7e78f285993f79cab68703d09 Mon Sep 17 00:00:00 2001 From: Miguel Nogueira Date: Tue, 8 Dec 2020 02:58:10 +0000 Subject: [PATCH] Added Team Authorization Policy --- app/Http/Controllers/TeamController.php | 36 +++++++--------- app/Policies/TeamPolicy.php | 56 +++++++++++++++++++++++++ app/Providers/AuthServiceProvider.php | 3 ++ app/User.php | 15 +++++++ routes/web.php | 1 + 5 files changed, 90 insertions(+), 21 deletions(-) create mode 100644 app/Policies/TeamPolicy.php diff --git a/app/Http/Controllers/TeamController.php b/app/Http/Controllers/TeamController.php index 905f7d2..30b217a 100755 --- a/app/Http/Controllers/TeamController.php +++ b/app/Http/Controllers/TeamController.php @@ -44,22 +44,14 @@ class TeamController extends Controller */ public function index() { + $this->authorize('index'); + $teams = Team::with('users.roles')->get(); return view('dashboard.teams.teams') ->with('teams', $teams); } - /** - * Show the form for creating a new resource. - * - * @return \Illuminate\Http\Response - */ - public function create() - { - // - } - /** * Store a newly created resource in storage. * @@ -68,6 +60,8 @@ class TeamController extends Controller */ public function store(NewTeamRequest $request) { + $this->authorize('create'); + $team = Team::create([ 'name' => $request->teamName, 'owner_id' => Auth::user()->id, @@ -80,17 +74,6 @@ class TeamController extends Controller return redirect()->back(); } - /** - * Display the specified resource. - * - * @param int $id - * @return \Illuminate\Http\Response - */ - public function show($id) - { - // - } - /** * Show the form for editing the specified resource. * @@ -99,6 +82,8 @@ class TeamController extends Controller */ public function edit(Team $team) { + $this->authorize('update', $team); + return view('dashboard.teams.edit-team') ->with('team', $team) ->with('users', User::all()) @@ -114,6 +99,9 @@ class TeamController extends Controller */ public function update(EditTeamRequest $request, Team $team) { + $this->authorize('update', $team); + + $team->description = $request->teamDescription; $team->openJoin = $request->joinType; @@ -137,6 +125,8 @@ class TeamController extends Controller public function invite(SendInviteRequest $request, Team $team) { + $this->authorize('invite', $team); + $user = User::findOrFail($request->user); if (! $team->openJoin) { @@ -196,6 +186,8 @@ class TeamController extends Controller public function switchTeam(Request $request, Team $team) { + $this->authorize('switchTeam', $team); + try { Auth::user()->switchTeam($team); @@ -210,6 +202,8 @@ class TeamController extends Controller // Since it's a separate form, we shouldn't use the same update method public function assignVacancies(Request $request, Team $team) { + $this->authorize('update', $team); + // P.S. To future developers // This method gave me a lot of trouble lol. It's hard to write code when you're half asleep. // There may be an n+1 query in the view and I don't think there's a way to avoid that without writing a lot of extra code. diff --git a/app/Policies/TeamPolicy.php b/app/Policies/TeamPolicy.php new file mode 100644 index 0000000..ad135cf --- /dev/null +++ b/app/Policies/TeamPolicy.php @@ -0,0 +1,56 @@ +hasPermissionTo('teams.view'); + } + + public function create(User $user) + { + return $user->hasPermissionTo('teams.create'); + } + + public function update(User $user, Team $team) + { + // Team owners can update their team regardless of perm. + // This perm would let admins change all teams + return $user->isOwnerOfTeam($team) || $user->hasPermissionTo('teams.update'); + } + + + public function invite(User $user, Team $team) + { + if (!$team->openJoin && $user->isOwnerOfTeam($team) || !$team->openJoin && $user->hasPermissionTo('teams.invite')) + { + return true; + } + + return false; + } + + public function switchTeam(User $user, Team $team): bool + { + // is the user in the team they're trying to switch to? + return $user->hasTeam($team); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index ee9ecfd..74d7a56 100755 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -30,9 +30,11 @@ use App\Policies\AppointmentPolicy; use App\Policies\BanPolicy; use App\Policies\FormPolicy; use App\Policies\ProfilePolicy; +use App\Policies\TeamPolicy; use App\Policies\UserPolicy; use App\Policies\VacancyPolicy; use App\Policies\VotePolicy; +use App\Team; use App\User; use App\Vacancy; use App\Vote; @@ -56,6 +58,7 @@ class AuthServiceProvider extends ServiceProvider Vote::class => VotePolicy::class, Ban::class => BanPolicy::class, Appointment::class => AppointmentPolicy::class, + Team::class => TeamPolicy::class ]; /** diff --git a/app/User.php b/app/User.php index 7ab469f..a39fb5e 100755 --- a/app/User.php +++ b/app/User.php @@ -109,6 +109,21 @@ class User extends Authenticatable implements MustVerifyEmail return ! is_null($this->twofa_secret); } + public function hasTeam($team): bool + { + if ($team instanceof Team || is_int($team)) + { + return $this->teams->contains($team); + } + else + { + /** + * In PHP 8, we can just use union types and let PHP enforce this for us. + */ + throw new \InvalidArgumentException('Please pass either a Team object or an integer identifying a Team.'); + } + } + public function routeNotificationForSlack($notification) { return config('slack.webhook.integrationURL'); diff --git a/routes/web.php b/routes/web.php index f6fef98..25f1b08 100755 --- a/routes/web.php +++ b/routes/web.php @@ -35,6 +35,7 @@ use App\Http\Controllers\TeamFileController; use App\Http\Controllers\UserController; use App\Http\Controllers\VacancyController; use App\Http\Controllers\VoteController; +use App\Http\Controllers\OptionsController; use Illuminate\Support\Facades\Route; use Mcamara\LaravelLocalization\Facades\LaravelLocalization;