From 0d0c182df87ee554e35ae12297cba9db9309c009 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 17:12:55 -0500 Subject: [PATCH 1/9] Foundation work for user flags Work on #64 --- app/Enums/UserFlags.php | 8 +++++ app/Models/User.php | 29 ++++++++++++++++++ app/Models/UserFlag.php | 21 +++++++++++++ ...4_08_10_214837_create_user_flags_table.php | 30 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 app/Enums/UserFlags.php create mode 100644 app/Models/UserFlag.php create mode 100644 database/migrations/2024_08_10_214837_create_user_flags_table.php diff --git a/app/Enums/UserFlags.php b/app/Enums/UserFlags.php new file mode 100644 index 0000000..aa174d4 --- /dev/null +++ b/app/Enums/UserFlags.php @@ -0,0 +1,8 @@ +hasMany(ScoreSheet::class); } + public function flags(): HasMany + { + return $this->hasMany(UserFlag::class); + } + + public function hasFlag($flag): bool + { + $flags = []; + foreach ($this->flags as $checkFlag) { + $flags[] = $checkFlag->flag_name->value; + } + + return in_array($flag, $flags); + + } + + public function addFlag($flag): void + { + if ($this->hasFlag($flag)) { + return; + } + $enum = match ($flag) { + 'head_director' => UserFlags::HEAD_DIRECTOR, + }; + $this->flags()->create(['flag_name' => $enum]); + $this->load('flags'); + } + public function scoresForEntry($entry) { return $this->scoreSheets->where('entry_id', '=', $entry)->first()?->subscores; diff --git a/app/Models/UserFlag.php b/app/Models/UserFlag.php new file mode 100644 index 0000000..f2e616d --- /dev/null +++ b/app/Models/UserFlag.php @@ -0,0 +1,21 @@ + UserFlags::class, + ]; + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } +} diff --git a/database/migrations/2024_08_10_214837_create_user_flags_table.php b/database/migrations/2024_08_10_214837_create_user_flags_table.php new file mode 100644 index 0000000..9de75e2 --- /dev/null +++ b/database/migrations/2024_08_10_214837_create_user_flags_table.php @@ -0,0 +1,30 @@ +id(); + $table->foreignIdFor(User::class)->constrained()->cascadeOnUpdate()->cascadeOnDelete(); + $table->string('flag_name'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_flags'); + } +}; -- 2.39.5 From 5862d05f351b80c3a9557bf612bcd7487b51c6b9 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 17:25:35 -0500 Subject: [PATCH 2/9] When a user creates a school, make them the head Work on #64 --- app/Http/Controllers/SchoolController.php | 9 +++++++++ resources/views/schools/create.blade.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/SchoolController.php b/app/Http/Controllers/SchoolController.php index fa4bf75..9d03f96 100644 --- a/app/Http/Controllers/SchoolController.php +++ b/app/Http/Controllers/SchoolController.php @@ -70,6 +70,15 @@ class SchoolController extends Controller 'schools' => [$school->id], ], ]); + + auth()->user()->addFlag('head_director'); // If user is creating a school, they are initially the head + AuditLogEntry::create([ + 'user' => auth()->user()->email, + 'ip_address' => request()->ip(), + 'message' => 'Marked '.auth()->user()->full_name().' as head director for '.$school->name, + 'affected' => ['schools' => [$school->id], 'users' => [auth()->user()->id]], + ]); + } return redirect('/schools/'.$school->id); diff --git a/resources/views/schools/create.blade.php b/resources/views/schools/create.blade.php index 6487e05..b93a776 100644 --- a/resources/views/schools/create.blade.php +++ b/resources/views/schools/create.blade.php @@ -5,7 +5,7 @@ - + -- 2.39.5 From df9b64a4e2321b1241a4b5a16b798fce6fbf6d7a Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 18:09:32 -0500 Subject: [PATCH 3/9] When a user creates a school, make them the head Work on #64 --- app/Actions/Schools/SetHeadDirector.php | 40 +++++++++++++++ app/Exceptions/AuditionAdminException.php | 10 ++++ app/Http/Controllers/SchoolController.php | 18 +++---- app/Models/User.php | 7 +++ app/Providers/AppServiceProvider.php | 8 ++- app/helpers.php | 12 +++++ tests/Feature/Actions/SetHeadDirectorTest.php | 51 +++++++++++++++++++ 7 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 app/Actions/Schools/SetHeadDirector.php create mode 100644 app/Exceptions/AuditionAdminException.php create mode 100644 tests/Feature/Actions/SetHeadDirectorTest.php diff --git a/app/Actions/Schools/SetHeadDirector.php b/app/Actions/Schools/SetHeadDirector.php new file mode 100644 index 0000000..75377e7 --- /dev/null +++ b/app/Actions/Schools/SetHeadDirector.php @@ -0,0 +1,40 @@ +setHeadDirector($user, $school); + } + + /** + * @throws AuditionAdminException + */ + public function setHeadDirector(User $user): void + { + if (is_null($user->school_id)) { + throw new AuditionAdminException('User is not associated with a school'); + } + foreach ($user->school->directors as $director) { + $director->removeFlag('head_director'); + } + $user->addFlag('head_director'); + + $logMessage = 'Set '.$user->full_name().' as head director at '.$user->school->name; + $logAffected = ['users' => [$user->id], 'schools' => [$user->school_id]]; + auditionLog($logMessage, $logAffected); + } +} diff --git a/app/Exceptions/AuditionAdminException.php b/app/Exceptions/AuditionAdminException.php new file mode 100644 index 0000000..7f6ebba --- /dev/null +++ b/app/Exceptions/AuditionAdminException.php @@ -0,0 +1,10 @@ +user()->cannot('create', School::class)) { abort(403); @@ -70,14 +72,12 @@ class SchoolController extends Controller 'schools' => [$school->id], ], ]); - - auth()->user()->addFlag('head_director'); // If user is creating a school, they are initially the head - AuditLogEntry::create([ - 'user' => auth()->user()->email, - 'ip_address' => request()->ip(), - 'message' => 'Marked '.auth()->user()->full_name().' as head director for '.$school->name, - 'affected' => ['schools' => [$school->id], 'users' => [auth()->user()->id]], - ]); + auth()->user()->refresh(); + try { + $headSetter->setHeadDirector(auth()->user()); + } catch (AuditionAdminException $e) { + redirect(route('schools.show', $school))->with('error', 'Could not set as head director'); + } } diff --git a/app/Models/User.php b/app/Models/User.php index adbbb4f..21b0722 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -187,6 +187,13 @@ class User extends Authenticatable implements MustVerifyEmail $this->load('flags'); } + public function removeFlag($flag): void + { + // remove related userFlag where flag_name = $flag + $this->flags()->where('flag_name', $flag)->delete(); + $this->load('flags'); + } + public function scoresForEntry($entry) { return $this->scoreSheets->where('entry_id', '=', $entry)->first()?->subscores; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 6b048c4..f1e8467 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,9 @@ namespace App\Providers; +use App\Actions\Entries\CreateEntry; +use App\Actions\Entries\UpdateEntry; +use App\Actions\Schools\SetHeadDirector; use App\Actions\Tabulation\AllowForOlympicScoring; use App\Actions\Tabulation\CalculateEntryScore; use App\Actions\Tabulation\CalculateScoreSheetTotal; @@ -32,7 +35,6 @@ use App\Services\DoublerService; use App\Services\DrawService; use App\Services\EntryService; use App\Services\ScoreService; -use App\Services\StudentService; use App\Services\UserService; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; @@ -52,6 +54,10 @@ class AppServiceProvider extends ServiceProvider $this->app->singleton(ScoreService::class, ScoreService::class); $this->app->singleton(UserService::class, UserService::class); $this->app->singleton(DoublerService::class, DoublerService::class); + $this->app->singleton(CreateEntry::class, CreateEntry::class); + $this->app->singleton(UpdateEntry::class, UpdateEntry::class); + $this->app->singleton(SetHeadDirector::class, SetHeadDirector::class); + } /** diff --git a/app/helpers.php b/app/helpers.php index 09e1327..ae6332d 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -2,6 +2,7 @@ use App\Actions\Tabulation\EnterScore; use App\Exceptions\ScoreEntryException; +use App\Models\AuditLogEntry; use App\Models\Entry; use App\Models\User; use App\Settings; @@ -35,11 +36,22 @@ function auditionSetting($key) return Settings::get($key); } +function auditionLog(string $message, array $affected) +{ + AuditLogEntry::create([ + 'user' => auth()->user()->email ?? 'no user', + 'ip_address' => request()->ip(), + 'message' => $message, + 'affected' => $affected, + ]); +} + /** * @throws ScoreEntryException */ function enterScore(User $user, Entry $entry, array $scores): \App\Models\ScoreSheet { $scoreEntry = App::make(EnterScore::class); + return $scoreEntry($user, $entry, $scores); } diff --git a/tests/Feature/Actions/SetHeadDirectorTest.php b/tests/Feature/Actions/SetHeadDirectorTest.php new file mode 100644 index 0000000..3f5fd97 --- /dev/null +++ b/tests/Feature/Actions/SetHeadDirectorTest.php @@ -0,0 +1,51 @@ +setter = app(SetHeadDirector::class); +}); + +it('sets a head director flag for a user with a school', function () { + // Arrange + $school = School::factory()->create(); + $user = User::factory()->create(['school_id' => $school->id]); + $this->setter->setHeadDirector($user); + $this->assertDatabaseHas('user_flags', [ + 'user_id' => $user->id, + 'flag_name' => 'head_director', + ]); +}); +it('throws an error if the user has no school', function () { + // Arrange + $user = User::factory()->create(); + // Act & Assert + $this->setter->setHeadDirector($user); +})->throws(AuditionAdminException::class, 'User is not associated with a school'); +it('removes the head director flag from any other users as the school', function () { + // Arrange + $school = School::factory()->create(); + $oldHead = User::factory()->create(['school_id' => $school->id]); + $newHead = User::factory()->create(['school_id' => $school->id]); + $oldHead->addFlag('head_director'); + $this->assertDatabaseHas('user_flags', [ + 'user_id' => $oldHead->id, + 'flag_name' => 'head_director', + ]); + // Act + $this->setter->setHeadDirector($newHead); + $this->assertDatabaseHas('user_flags', [ + 'user_id' => $newHead->id, + 'flag_name' => 'head_director', + ]); + $this->assertDatabaseMissing('user_flags', [ + 'user_id' => $oldHead->id, + 'flag_name' => 'head_director', + ]); +}); -- 2.39.5 From 46441268c909b609962d4f4cb8a2a0f883654d22 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 18:59:30 -0500 Subject: [PATCH 4/9] Administrators can make a user head director Work on #64 --- app/Http/Controllers/Admin/UserController.php | 26 ++++++++++++++----- resources/views/admin/users/edit.blade.php | 7 ++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index 82a804e..76c4793 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Admin; +use App\Actions\Schools\SetHeadDirector; use App\Http\Controllers\Controller; use App\Mail\NewUserPassword; use App\Models\AuditLogEntry; @@ -13,6 +14,8 @@ use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Str; +use function auditionLog; + class UserController extends Controller { public function index() @@ -45,7 +48,7 @@ class UserController extends Controller return view('admin.users.create', ['schools' => $schools]); } - public function update(Request $request, User $user) + public function update(Request $request, User $user, SetHeadDirector $headSetter) { if (! Auth::user()->is_admin) { abort(403); @@ -63,6 +66,7 @@ class UserController extends Controller ]); $validData['is_admin'] = $request->get('is_admin') == 'on' ? 1 : 0; $validData['is_tab'] = $request->get('is_tab') == 'on' ? 1 : 0; + $validData['is_head'] = $request->get('is_head') == 'on' ? 1 : 0; $user->update([ 'first_name' => $validData['first_name'], 'last_name' => $validData['last_name'], @@ -76,11 +80,11 @@ class UserController extends Controller $user->refresh(); $logged_school = $user->school_id ? $user->school->name : 'No School'; $message = 'Updated user #'.$user->id.' - '.$oldEmail - .'
Name: '.$user->full_name() - .'
Email: '.$user->email - .'
Cell Phone: '.$user->cell_phone - .'
Judging Pref: '.$user->judging_preference - .'
School: '.$logged_school; + .'
Name: '.$user->full_name() + .'
Email: '.$user->email + .'
Cell Phone: '.$user->cell_phone + .'
Judging Pref: '.$user->judging_preference + .'
School: '.$logged_school; AuditLogEntry::create([ 'user' => auth()->user()->email, @@ -106,6 +110,16 @@ class UserController extends Controller 'affected' => ['users' => [$user->id]], ]); } + if ($user->hasFlag('head_director') != $validData['is_head'] && ! is_null($user->school_id)) { + if ($validData['is_head']) { + $headSetter->setHeadDirector($user); + } else { + $user->removeFlag('head_director'); + $logMessage = 'Removed '.$user->full_name().' as head director at '.$user->school->name; + $logAffected = ['users' => [$user->id], 'schools' => [$user->school_id]]; + auditionLog($logMessage, $logAffected); + } + } return redirect('/admin/users'); } diff --git a/resources/views/admin/users/edit.blade.php b/resources/views/admin/users/edit.blade.php index f0afd81..9ac2c34 100644 --- a/resources/views/admin/users/edit.blade.php +++ b/resources/views/admin/users/edit.blade.php @@ -22,7 +22,7 @@ - + School @foreach ($schools as $school) @@ -31,6 +31,11 @@ @endforeach +
+ + Head Director + +
Administrator -- 2.39.5 From 9f71e5e3f588b0bfb1ebc39202146bc64bfb1ba4 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 20:23:14 -0500 Subject: [PATCH 5/9] Administrators can make a user head director from school page Work on #64 --- app/Http/Controllers/Admin/SchoolController.php | 12 ++++++++++++ resources/views/admin/schools/show.blade.php | 11 ++++++++++- routes/admin.php | 1 + tests/Feature/Pages/Admin/UsersEditTest.php | 5 +++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Admin/SchoolController.php b/app/Http/Controllers/Admin/SchoolController.php index 702b602..a224006 100644 --- a/app/Http/Controllers/Admin/SchoolController.php +++ b/app/Http/Controllers/Admin/SchoolController.php @@ -2,10 +2,12 @@ namespace App\Http\Controllers\Admin; +use App\Actions\Schools\SetHeadDirector; use App\Http\Controllers\Controller; use App\Models\AuditLogEntry; use App\Models\School; use App\Models\SchoolEmailDomain; +use App\Models\User; use App\Services\Invoice\InvoiceDataService; use Illuminate\Support\Facades\Auth; @@ -176,4 +178,14 @@ class SchoolController extends Controller return view('dashboard.invoice', compact('school', 'invoiceData')); } + + public function setHeadDirector(School $school, User $user, SetHeadDirector $headSetter) + { + if ($user->school_id !== $school->id) { + return redirect()->back()->with('error', 'That user is not at that school'); + } + $headSetter->setHeadDirector($user); + + return redirect()->back()->with('success', 'Head director set'); + } } diff --git a/resources/views/admin/schools/show.blade.php b/resources/views/admin/schools/show.blade.php index 8f1b7e0..6ae3d6f 100644 --- a/resources/views/admin/schools/show.blade.php +++ b/resources/views/admin/schools/show.blade.php @@ -37,7 +37,16 @@
@foreach($school->directors as $director) - {{ $director->full_name() }} + + {{ $director->full_name() }} + @if($director->hasFlag('head_director')) + Head Director + @else + + [ Make Head Director ] + + @endif +

{{ $director->cell_phone }}

diff --git a/routes/admin.php b/routes/admin.php index 11529cb..87de676 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -150,6 +150,7 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')-> Route::post('/', 'store')->name('admin.schools.store'); Route::delete('/domain/{domain}', 'destroy_domain')->name('admin.schools.destroy_domain'); Route::delete('/{school}', 'destroy')->name('admin.schools.destroy'); + Route::get('/{school}/set_head_director/{user}', 'setHeadDirector')->name('admin.schools.set_head_director'); }); diff --git a/tests/Feature/Pages/Admin/UsersEditTest.php b/tests/Feature/Pages/Admin/UsersEditTest.php index 260a368..3c36588 100644 --- a/tests/Feature/Pages/Admin/UsersEditTest.php +++ b/tests/Feature/Pages/Admin/UsersEditTest.php @@ -7,6 +7,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use function Pest\Laravel\actingAs; use function Pest\Laravel\assertDatabaseHas; use function Pest\Laravel\delete; +use function Pest\Laravel\from; use function Pest\Laravel\get; use function Pest\Laravel\patch; @@ -150,7 +151,7 @@ it('allows an administrator to modify a user', function () { 'school_id' => $newSchool->id, ]; // Act - $response = patch(route('admin.users.update', $this->users[0]), $newData); + $response = from(route('admin.users.index'))->patch(route('admin.users.update', $this->users[0]), $newData); /** @noinspection PhpUnhandledExceptionInspection */ $response ->assertSessionHasNoErrors() @@ -186,7 +187,7 @@ it('allows a users school to be set to no school', function () { ]; actAsAdmin(); // Act & Assert - $response = patch(route('admin.users.update', $user), $newData); + $response = from(route('admin.users.index'))->patch(route('admin.users.update', $user), $newData); /** @noinspection PhpUnhandledExceptionInspection */ $response ->assertSessionHasNoErrors() -- 2.39.5 From d9f80a44f1edd41467b20c3cb549f04f8de96f7f Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 21:42:36 -0500 Subject: [PATCH 6/9] Head directors can add user accounts Work on #64 --- app/Http/Controllers/SchoolController.php | 41 +++++++ .../views/emails/new_user_password.blade.php | 3 +- resources/views/schools/show.blade.php | 101 ++++++++++++------ routes/user.php | 1 + 4 files changed, 111 insertions(+), 35 deletions(-) diff --git a/app/Http/Controllers/SchoolController.php b/app/Http/Controllers/SchoolController.php index d419036..1f78afc 100644 --- a/app/Http/Controllers/SchoolController.php +++ b/app/Http/Controllers/SchoolController.php @@ -4,14 +4,20 @@ namespace App\Http\Controllers; use App\Actions\Schools\SetHeadDirector; use App\Exceptions\AuditionAdminException; +use App\Mail\NewUserPassword; use App\Models\AuditLogEntry; use App\Models\School; use App\Models\SchoolEmailDomain; +use App\Models\User; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Str; use function abort; +use function auditionLog; use function redirect; use function request; @@ -150,4 +156,39 @@ class SchoolController extends Controller return redirect('/schools/create'); } + + public function addDirector(School $school) + { + + if (auth()->user()->school_id !== $school->id) { + return redirect()->back()->with('error', 'No adding directors to another school'); + } + if (! auth()->user()->hasFlag('head_director')) { + return redirect()->back()->with('error', 'Only the head director can add directors to a school'); + } + $validData = request()->validate([ + 'first_name' => ['required'], + 'last_name' => ['required'], + 'email' => ['required', 'email', 'unique:users'], + 'cell_phone' => ['required'], + 'judging_preference' => ['required'], + ]); + // Generate a random password + $randomPassword = Str::random(12); + $newUser = User::create([ + 'first_name' => $validData['first_name'], + 'last_name' => $validData['last_name'], + 'email' => $validData['email'], + 'cell_phone' => $validData['cell_phone'], + 'judging_preference' => $validData['judging_preference'], + 'password' => Hash::make($randomPassword), + 'school_id' => auth()->user()->school_id, + ]); + $logMessage = 'Created user '.$newUser->full_name().' - '.$newUser->email.' as a director at '.$newUser->school->name; + $logAffected = ['users' => [$newUser->id], 'schools' => [$newUser->school_id]]; + auditionLog($logMessage, $logAffected); + Mail::to($newUser->email)->send(new NewUserPassword($newUser, $randomPassword)); + + return redirect()->back()->with('success', 'Director added'); + } } diff --git a/resources/views/emails/new_user_password.blade.php b/resources/views/emails/new_user_password.blade.php index a9519d9..990ac82 100644 --- a/resources/views/emails/new_user_password.blade.php +++ b/resources/views/emails/new_user_password.blade.php @@ -5,9 +5,10 @@

Hello, {{ $user->first_name }} {{ $user->last_name }}

-

Your account has been created. Here are your login details:

+

Your AuditionAdmin account for {{ auditionSetting('auditionAbbreviation') }} has been created. Here are your login details:

Email: {{ $user->email }}

Password: {{ $password }}

+

Login at: {{route('login')}}

Please change your password after logging in for the first time.

diff --git a/resources/views/schools/show.blade.php b/resources/views/schools/show.blade.php index df818e2..d074753 100644 --- a/resources/views/schools/show.blade.php +++ b/resources/views/schools/show.blade.php @@ -1,39 +1,72 @@ - - School Info - {{ $school->name }} +
+ + School Info - {{ $school->name }} -
- - - -
-
- {{ $school->name }}
- {{ $school->address }}
- {{ $school->city }}, {{ $school->state }} {{ $school->zip }} +
+ + + +
+
+ {{ $school->name }}
+ {{ $school->address }}
+ {{ $school->city }}, {{ $school->state }} {{ $school->zip }} +
+
- -
- + - -
    - @foreach($school->directors as $director) -
  • {{ $director->full_name() }} - {{ $director->email }}
  • - @endforeach -
-
+ +
    + @foreach($school->directors as $director) +
  • + {{ $director->full_name() }} + @if($director->hasFlag('head_director')) (head) @endif + - + {{ $director->email }} +
  • + @endforeach +
+ @if(auth()->user()->hasFlag('head_director')) +
+ Add Director + Change Head +
+ @endif +
- -
    - @foreach($school->emailDomains as $domain) -
  • {{ $domain->domain }}
  • - @endforeach -
-
- - -
+ +
    + @foreach($school->emailDomains as $domain) +
  • {{ $domain->domain }}
  • + @endforeach +
+
+ + +
- + + + @if(auth()->user()->hasFlag('head_director')) + + Add Director + + + + + + + + + + + + + + Change Head Director + + @endif +
diff --git a/routes/user.php b/routes/user.php index a210d90..1c30eb5 100644 --- a/routes/user.php +++ b/routes/user.php @@ -52,6 +52,7 @@ Route::middleware(['auth', 'verified'])->controller(SchoolController::class)->gr Route::get('/schools/{school}/edit', 'edit')->name('schools.edit'); Route::get('/schools/{school}', 'show')->name('schools.show'); Route::patch('/schools/{school}', 'update')->name('schools.update'); + Route::post('schools/{school}/add_director', 'addDirector')->name('schools.add_director'); }); // Doubler Related Routes -- 2.39.5 From 4d3369fb11de284b211b78098c26d006d08747d8 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 22:18:20 -0500 Subject: [PATCH 7/9] Head directors can add user accounts Work on #64 Work on #66 --- app/Http/Controllers/SchoolController.php | 20 ++++++++++++++++ resources/views/schools/show.blade.php | 28 +++++++++++++++++++++++ routes/user.php | 1 + 3 files changed, 49 insertions(+) diff --git a/app/Http/Controllers/SchoolController.php b/app/Http/Controllers/SchoolController.php index 1f78afc..f9ef6f1 100644 --- a/app/Http/Controllers/SchoolController.php +++ b/app/Http/Controllers/SchoolController.php @@ -191,4 +191,24 @@ class SchoolController extends Controller return redirect()->back()->with('success', 'Director added'); } + + public function setHeadDirector(School $school, User $user, SetHeadDirector $headSetter) + { + if (auth()->user()->school_id !== $school->id) { + return redirect()->back()->with('error', 'No setting the head director for another school'); + } + if (! auth()->user()->hasFlag('head_director')) { + return redirect()->back()->with('error', 'Only the head director can name a new head director'); + } + if ($school->id !== $user->school_id) { + return redirect()->back()->with('error', 'The proposed head director must be at your school'); + } + try { + $headSetter->setHeadDirector($user); + } catch (AuditionAdminException $e) { + return redirect()->back()->with('error', $e->getMessage()); + } + + return redirect()->back()->with('success', 'New head director set'); + } } diff --git a/resources/views/schools/show.blade.php b/resources/views/schools/show.blade.php index d074753..18713b6 100644 --- a/resources/views/schools/show.blade.php +++ b/resources/views/schools/show.blade.php @@ -67,6 +67,34 @@ Change Head Director + {{-- Warming Message --}} +
+
+
+ +
+
+

WARNING!!!

+
+

After making another director head, you will no longer have access to head director functions

+

This action cannot be undone

+
+
+
+
+

Which director should be the head director at {{$school->name}}? (click to set)

+ + @foreach($school->directors as $director) + @continue($director->id === auth()->user()->id) + + + {{ $director->full_name() }} < {{$director->email }} > + + + @endforeach +
@endif
diff --git a/routes/user.php b/routes/user.php index 1c30eb5..c95d462 100644 --- a/routes/user.php +++ b/routes/user.php @@ -53,6 +53,7 @@ Route::middleware(['auth', 'verified'])->controller(SchoolController::class)->gr Route::get('/schools/{school}', 'show')->name('schools.show'); Route::patch('/schools/{school}', 'update')->name('schools.update'); Route::post('schools/{school}/add_director', 'addDirector')->name('schools.add_director'); + Route::get('/schools/{school}/set_head_director/{user}', 'setHeadDirector')->name('schools.set_head_director'); }); // Doubler Related Routes -- 2.39.5 From 1100e711f859f460e9765a14a4bb98c4dc85f702 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 23:08:13 -0500 Subject: [PATCH 8/9] Head directors can manage school email domains Work on #64 Work on #66 --- app/Http/Controllers/SchoolController.php | 43 +++++++++++++++++++++++ resources/views/schools/show.blade.php | 33 ++++++++++++----- routes/user.php | 2 ++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/SchoolController.php b/app/Http/Controllers/SchoolController.php index f9ef6f1..5acfddf 100644 --- a/app/Http/Controllers/SchoolController.php +++ b/app/Http/Controllers/SchoolController.php @@ -9,6 +9,7 @@ use App\Models\AuditLogEntry; use App\Models\School; use App\Models\SchoolEmailDomain; use App\Models\User; +use Illuminate\Database\UniqueConstraintViolationException; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -211,4 +212,46 @@ class SchoolController extends Controller return redirect()->back()->with('success', 'New head director set'); } + + public function addDomain(School $school) + { + if (auth()->user()->school_id !== $school->id) { + return redirect()->back()->with('error', 'No adding domains for another school'); + } + if (! auth()->user()->hasFlag('head_director')) { + return redirect()->back()->with('error', 'Only the head director can add domains'); + } + $verifiedData = request()->validate([ + 'domain' => ['required'], + ]); + try { + SchoolEmailDomain::create([ + 'school_id' => $school->id, + 'domain' => $verifiedData['domain'], + ]); + } catch (UniqueConstraintViolationException $e) { + return redirect()->back()->with('error', 'That domain is already associated with your school'); + } + $logMessage = 'Added domain '.$verifiedData['domain'].' to school '.$school->name; + $logAffected = ['schools' => [$school->id]]; + auditionLog($logMessage, $logAffected); + + return redirect()->back()->with('success', 'Domain added'); + } + + public function deleteDomain(SchoolEmailDomain $domain) + { + if (auth()->user()->school_id !== $domain->school_id) { + return redirect()->back()->with('error', 'No deleting domains for another school'); + } + if (! auth()->user()->hasFlag('head_director')) { + return redirect()->back()->with('error', 'Only the head director can delete domains'); + } + $logMessage = 'Deleted domain '.$domain->domain.' from school '.$domain->school->name; + $logAffected = ['schools' => [$domain->school_id]]; + auditionLog($logMessage, $logAffected); + $domain->delete(); + + return redirect()->back()->with('success', 'Domain deleted'); + } } diff --git a/resources/views/schools/show.blade.php b/resources/views/schools/show.blade.php index 18713b6..742f8d4 100644 --- a/resources/views/schools/show.blade.php +++ b/resources/views/schools/show.blade.php @@ -36,14 +36,31 @@
@endif - - -
    - @foreach($school->emailDomains as $domain) -
  • {{ $domain->domain }}
  • - @endforeach -
-
+ @if(auth()->user()->hasFlag('head_director')) + +

Users with emails in these domains (the part after the @) that don't already have a school + will be able to join your school.

+
    + @foreach($school->emailDomains as $domain) +
  • + + + + {{ $domain->domain }} +
  • + @endforeach +
  • +

    Add Domain

    + +
    + + Add +
    +
    +
  • +
+
+ @endif
diff --git a/routes/user.php b/routes/user.php index c95d462..e9a0c71 100644 --- a/routes/user.php +++ b/routes/user.php @@ -54,6 +54,8 @@ Route::middleware(['auth', 'verified'])->controller(SchoolController::class)->gr Route::patch('/schools/{school}', 'update')->name('schools.update'); Route::post('schools/{school}/add_director', 'addDirector')->name('schools.add_director'); Route::get('/schools/{school}/set_head_director/{user}', 'setHeadDirector')->name('schools.set_head_director'); + Route::post('/schools/{school}/add_domain', 'addDomain')->name('schools.add_domain'); + Route::get('/schools/delete_domain/{domain}', 'deleteDomain')->name('schools.delete_domain'); }); // Doubler Related Routes -- 2.39.5 From 31d3beea863220d8344c7e4e4eae49e8669c112d Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sat, 10 Aug 2024 23:13:47 -0500 Subject: [PATCH 9/9] Flag head director status on judge assignment screen Work on #64 Work on #66 --- .../views/admin/bonus-scores/judge-assignments.blade.php | 2 +- resources/views/admin/rooms/judge_assignments.blade.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/views/admin/bonus-scores/judge-assignments.blade.php b/resources/views/admin/bonus-scores/judge-assignments.blade.php index 116d14d..8f3f425 100644 --- a/resources/views/admin/bonus-scores/judge-assignments.blade.php +++ b/resources/views/admin/bonus-scores/judge-assignments.blade.php @@ -98,7 +98,7 @@ @if($bonusScore->judges->contains($judge->id)) @continue @endif - @endforeach diff --git a/resources/views/admin/rooms/judge_assignments.blade.php b/resources/views/admin/rooms/judge_assignments.blade.php index eada06f..274c480 100644 --- a/resources/views/admin/rooms/judge_assignments.blade.php +++ b/resources/views/admin/rooms/judge_assignments.blade.php @@ -102,7 +102,7 @@ @foreach($usersWithoutRooms as $judge) {{-- skip judges alrady assigned to this audition --}} - @endforeach @@ -111,7 +111,7 @@ @if($room->judges->contains($judge->id)) @continue @endif - @endforeach -- 2.39.5