Commit 95525769 authored by o@ungehorsam.ch's avatar o@ungehorsam.ch
Browse files

Merge branch '8-shift-enumeration' into 'main'

Resolve "shift enumeration"

Closes #8

See merge request !7
parents bb3e5752 8ad9b5d2
......@@ -2,17 +2,42 @@
namespace App\Http\Controllers;
use App\Models\Plan;
use App\Models\Shift;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth;
class Controller extends BaseController
{
use DispatchesJobs, ValidatesRequests;
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
protected function auth(\App\Models\Plan $plan) {
if (!strpos(\Request::url(), $plan->edit_id))
/**
* Auth a plan over by the secrete Plan edit_id
* @param Plan $plan
*/
protected function auth(Plan $plan) {
if (!strpos(\Request::url(), $plan->edit_id)) {
abort(401);
}
// login the plan as a user. This is a hack to work with edit_id tokens only and the laravel auth Policies
Auth::login($plan, false);
}
/**
* Anonymous user can just subscribe to a known plan and shift
* @param Plan $plan
* @param Shift $shift
*/
protected function authSubscriber(Plan $plan, Shift $shift) {
// anonymous user can subscribe to the plan they have the link to
// we can't use auth Policies to check this
if($shift->plan->id !== $plan->id) {
abort(403);
}
}
}
......@@ -83,6 +83,7 @@ class PlanController extends Controller
$plans = Plan::where('owner_email', $email)->get();
if(count($plans) > 0) {
foreach ($plans as $plan) {
// todo: send just one email
$plan->sendLinksNotification();
}
}
......@@ -93,7 +94,7 @@ class PlanController extends Controller
/**
* Cleanup old plans.
*
* todo: we may want to delete this
*/
public function cron()
{
......@@ -118,6 +119,7 @@ class PlanController extends Controller
public function admin(Plan $plan)
{
$this->auth($plan);
$this->authorize("view", $plan);
return view('plan.admin')->with(['plan' => $plan]);
}
......@@ -130,6 +132,7 @@ class PlanController extends Controller
public function admin_subscriptions(Plan $plan)
{
$this->auth($plan);
$this->authorize("view", $plan);
return view('plan.admin_subscriptions')->with(['plan' => $plan]);
}
......@@ -142,6 +145,7 @@ class PlanController extends Controller
public function edit(Plan $plan)
{
$this->auth($plan);
$this->authorize("update", $plan);
return view('plan.create', ['plan' => $plan]);
}
......@@ -155,11 +159,8 @@ class PlanController extends Controller
public function update(UpdatePlanRequest $request, Plan $plan)
{
$this->auth($plan);
$this->authorize("update", $plan);
$data = $request->validated();
// prevent to be overridden
unset($data['edit_id']);
unset($data['view_id']);
unset($data['id']);
$plan->update($data);
// redirect to shifts overview
Session::flash('info', __('plan.successfullyUpdated'));
......@@ -175,6 +176,7 @@ class PlanController extends Controller
public function destroy(Plan $plan)
{
$this->auth($plan);
$this->authorize("forceDelete", $plan);
$plan->forceDelete();
Session::flash('info', __('plan.successfullyDestroyed'));
return \redirect()->route('home');
......
......@@ -4,7 +4,6 @@ namespace App\Http\Controllers;
use App\Http\Requests\StoreShiftRequest;
use App\Http\Requests\RepetitionType;
use App\Http\Requests\UpdateShiftRequest;
use App\Models\Plan;
use App\Models\Shift;
use Illuminate\Http\Response;
......@@ -15,12 +14,15 @@ class ShiftController extends Controller
/**
* Show the form for creating a new shift.
*
* @param Plan $plan
* @return Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Plan $plan)
{
$this->auth($plan);
// user needs access to plan to create a new shift
$this->auth($plan);
$this->authorize("create", Shift::class);
$groups = $this->getGroups($plan);
$shift = new Shift();
return view('shift.create', ['plan' => $plan, 'shift' => $shift, 'groups' => $groups,
......@@ -37,6 +39,7 @@ class ShiftController extends Controller
public function store(StoreShiftRequest $request, Plan $plan)
{
$this->auth($plan);
$this->authorize("create", Shift::class);
$data = $request->validated();
$plan->shifts()->create($data);
if ($data['repetition_type'] != RepetitionType::None) {
......@@ -60,6 +63,7 @@ class ShiftController extends Controller
public function edit(Plan $plan, Shift $shift)
{
$this->auth($plan);
$this->authorize('update', $shift);
$groups = $this->getGroups($plan);
return view('shift.create', ['shift' => $shift, 'plan' => $plan, 'groups' => $groups]);
}
......@@ -75,6 +79,7 @@ class ShiftController extends Controller
public function update(StoreShiftRequest $request, Plan $plan, Shift $shift)
{
$this->auth($plan);
$this->authorize('update',$shift);
$data = $request->validated();
$shift->update($data);
Session::flash('info', __('shift.successfullyUpdated'));
......@@ -91,6 +96,7 @@ class ShiftController extends Controller
public function destroy(Plan $plan, Shift $shift)
{
$this->auth($plan);
$this->authorize('forceDelete', $shift);
$shift->forceDelete();
Session::flash('info', __('shift.successfullyDestroyed'));
return redirect()->route('plan.admin', ['plan' => $plan]);
......
......@@ -7,7 +7,6 @@ use App\Models\Plan;
use App\Models\Shift;
use App\Models\Subscription;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
class SubscriptionController extends Controller
......@@ -21,6 +20,8 @@ class SubscriptionController extends Controller
* @return Response
*/
public function create(Plan $plan, Shift $shift) {
// anonymous users can just add a shift for the authorized plan
$this->authSubscriber($plan, $shift);
$subscription = new Subscription();
return view('subscription.create', ['plan' => $plan, 'shift' => $shift, 'subscription' => $subscription]);
}
......@@ -35,17 +36,15 @@ class SubscriptionController extends Controller
*/
public function store(StoreSubscriptionRequest $request, Plan $plan, Shift $shift)
{
// anonymous users can just add a shift for the authorized plan
$this->authSubscriber($plan, $shift);
// check if there are already enough subscriptions
if($shift->team_size <= $shift->subscriptions()->count()) {
Session::flash('fail', __('subscription.enoughSubscription'));
return redirect()->route('plan.show', ['plan' => $plan]);
}
// no specific authorization - everybody with the link can create a subscription
$data = $request->validated();
$subscription = $shift->subscriptions()->create($data);
// An anonymous user can edit her/his subscription as long as he/she use the same session
// For that reason we save those subscription in a session
Session::push('subscriptions', $subscription->id);
$shift->subscriptions()->create($data);
Session::flash('info', __('subscription.successfullyCreated'));
return redirect()->route('plan.show', ['plan' => $plan]);
}
......@@ -61,6 +60,7 @@ class SubscriptionController extends Controller
public function edit(Plan $plan, Shift $shift, Subscription $subscription)
{
$this->auth($plan);
$this->authorize('update', $subscription);
return view('subscription.create', ['plan' => $plan, 'shift' => $shift, 'subscription' => $subscription]);
}
......@@ -76,6 +76,7 @@ class SubscriptionController extends Controller
public function update(StoreSubscriptionRequest $request, Plan $plan, Shift $shift, Subscription $subscription)
{
$this->auth($plan);
$this->authorize('update', $subscription);
$data = $request->validated();
$subscription->update($data);
Session::flash('info', __('subscription.successfullyUpdated'));
......@@ -93,9 +94,8 @@ class SubscriptionController extends Controller
public function destroy(Plan $plan, Shift $shift, Subscription $subscription)
{
$this->auth($plan);
$this->authorize('forceDelete', $subscription);
$subscription->forceDelete();
// todo: check if this is working
Session::forget('subscriptions.'.$subscription->id);
Session::flash('info', __('subscription.successfullyDestroyed'));
return redirect()->route('plan.admin', ['plan' => $plan]);
}
......
......@@ -5,12 +5,18 @@ namespace App\Models;
use App\Notifications\SendLinksNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
class Plan extends Model
{
use HasFactory, Notifiable;
class Plan extends Model implements
AuthenticatableContract,
AuthorizableContract {
use Authorizable, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
......@@ -95,4 +101,33 @@ class Plan extends Model
$viewLink = route('plan.show', ['plan' => $this->view_id]);
$this->notify(new SendLinksNotification($this->title, $adminLink, $viewLink));
}
public function getAuthIdentifierName()
{
$this->edit_id;
}
public function getAuthIdentifier()
{
$this->edit_id;
}
public function getAuthPassword()
{
return null;
}
public function getRememberToken()
{
return null;
}
public function setRememberToken($value)
{
}
public function getRememberTokenName()
{
return null;
}
}
......@@ -13,6 +13,17 @@ class ShiftPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can create a shit.
*
* @param \App\Models\Plan $plan
* @return \Illuminate\Auth\Access\Response|bool
*/
public function create(Plan $plan)
{
return true;
}
/**
* Determine whether the user can update the model.
*
......
<?php
namespace App\Policies;
use App\Models\Plan;
use App\Models\Shift;
use App\Models\Subscription;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Support\Facades\Log;
class SubscriptionPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can update the model.
*
* @param \App\Models\Plan $plan
* @param \App\Models\Subscription $subscription
* @return \Illuminate\Auth\Access\Response|bool
*/
public function update(Plan $plan, Subscription $subscription)
{
return $subscription->shift->plan->id === $plan->id;
}
/**
* Determine whether the user can permanently delete the model.
*
* @param \App\Models\Plan $plan
* @param \App\Models\Subscription $subscription
* @return \Illuminate\Auth\Access\Response|bool
*/
public function forceDelete(Plan $plan, Subscription $subscription)
{
return $subscription->shift->plan->id === $plan->id;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment