5 Commits
0.5.1 ... 0.5.2

Author SHA1 Message Date
5f1f92a9ce Code review
This commit fixes some superficial instances of Broken Access Control 
(https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A5-Broken_Access_Control).
There may be some more instances of this, as authorization was only done 
after most of the controllers were done (big mistake).

Some refactoring was also performed, where Route Model Binding with DI 
(dependency injection) was used whenever possible, to increase 
testability of the codebase.
Some reused code was also moved to Helper classes as to enforce DRY; 
There may be some lines of code that are still copy-pasted from other 
parts of the codebase for reuse.

Non-breaking refactoring changes were made, but the app as a whole still 
needs full manual testing, and customised responses to HTTP 500 
responses. Some errors are also not handled gracefully and this wasn't 
checked in this commit.
2020-07-16 21:21:28 +01:00
9e2d571298 Fix homepage bg issue 2020-07-16 07:32:52 +01:00
e16be5dc46 Override styles for auth pages 2020-07-16 07:11:33 +01:00
1a04880489 Replace basic authentication pages 2020-07-16 06:50:59 +01:00
3693ce3431 Add footer to all dashboard pages 2020-07-16 06:46:20 +01:00
54 changed files with 441 additions and 577 deletions

View File

@@ -16,11 +16,6 @@ class IP
public function lookup(string $IP): object
{
if (empty($IP))
{
throw new LogicException(__METHOD__ . 'is missing parameter IP!');
}
$params = [
'apiKey' => config('general.keys.ipapi.apikey'),
'ip' => $IP

View File

@@ -7,6 +7,29 @@ use Illuminate\Support\Collection;
class ContextAwareValidator
{
/**
* The excludedNames array will make the validator ignore any of these names when including names into the rules.
* @var array
*/
private $excludedNames = [
'_token',
'_method',
'formName'
];
/**
* Utility wrapper for json_encode.
*
* @param array $value The array to be converted.
* @return string The JSON representation of $value
*/
private function encode(array $value) : string
{
return json_encode($value);
}
/**
* The getValidator() method will take an array of fields from the request body, iterates through them,
* and dynamically adds validation rules for them. Depending on parameters, it may or may not generate
@@ -30,12 +53,6 @@ class ContextAwareValidator
$formStructure = [];
$validator = [];
$excludedNames = [
'_token',
'_method',
'formName'
];
if ($includeFormName)
{
$validator['formName'] = 'required|string|max:100';
@@ -43,7 +60,7 @@ class ContextAwareValidator
foreach ($fields as $fieldName => $field)
{
if(!in_array($fieldName, $excludedNames))
if(!in_array($fieldName, $this->excludedNames))
{
$validator[$fieldName . ".0"] = 'required|string';
$validator[$fieldName . ".1"] = 'required|string';
@@ -62,11 +79,60 @@ class ContextAwareValidator
return ($generateStructure) ?
collect([
'validator' => $validatorInstance,
'structure' => json_encode($formStructure)
'structure' => $this->encode($formStructure)
])
: $validatorInstance;
}
/**
* The getResponseValidator method is similar to the getValidator method; It basically takes
* an array of fields from a previous form (that probably went through the other method) and adds validation
* to the field names.
*
* Also generates the storable response structure if you tell it to.
*
* @param array $fields The received fields
* @param array $formStructure The form structure - You must supply this if you want the response structure
* @param bool $generateResponseStructure Whether to generate the response structure
* @return Validator|Collection A collection or a validator, depending on the args. Will return validatior if only fields are supplied.
*/
public function getResponseValidator(array $fields, array $formStructure = [], bool $generateResponseStructure = true)
{
$responseStructure = [];
$validator = [];
if (empty($formStructure) && $generateResponseStructure)
{
throw new \InvalidArgumentException('Illegal combination of arguments supplied! Please check the method\'s documentation.');
}
foreach($fields as $fieldName => $value)
{
if(!in_array($fieldName, $this->excludedNames))
{
$validator[$fieldName] = 'required|string';
if ($generateResponseStructure)
{
$responseStructure['responses'][$fieldName]['type'] = $formStructure['fields'][$fieldName]['type'] ?? 'Unavailable';
$responseStructure['responses'][$fieldName]['title'] = $formStructure['fields'][$fieldName]['title'];
$responseStructure['responses'][$fieldName]['response'] = $value;
}
}
}
$validatorInstance = Validator::make($fields, $validator);
return ($generateResponseStructure) ?
collect([
'validator' => $validatorInstance,
'responseStructure' => $this->encode($responseStructure)
])
: $validatorInstance;
}
}

View File

@@ -18,8 +18,11 @@ use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use ContextAwareValidator;
class ApplicationController extends Controller
{
private function canVote($votes)
{
$allvotes = collect([]);
@@ -45,11 +48,8 @@ class ApplicationController extends Controller
}
public function showUserApp(Request $request, $applicationID)
public function showUserApp(Request $request, Application $application)
{
// TODO: Inject it instead (do this where there is no injection, not just here)
$application = Application::find($applicationID);
$this->authorize('view', $application);
if (!is_null($application))
@@ -78,6 +78,8 @@ class ApplicationController extends Controller
public function showAllApps()
{
$this->authorize('viewAny', Application::class);
return view('dashboard.appmanagement.all')
->with('applications', Application::paginate(6));
}
@@ -186,36 +188,16 @@ class ApplicationController extends Controller
Log::info('Processing new application!');
$formStructure = json_decode($vacancy->first()->forms->formStructure, true);
$responseStructure = [];
$excludedNames = [
'_token',
];
$validator = [];
foreach($request->all() as $fieldName => $value)
{
if(!in_array($fieldName, $excludedNames))
{
$validator[$fieldName] = 'required|string';
$responseStructure['responses'][$fieldName]['type'] = $formStructure['fields'][$fieldName]['type'] ?? 'Unavailable';
$responseStructure['responses'][$fieldName]['title'] = $formStructure['fields'][$fieldName]['title'];
$responseStructure['responses'][$fieldName]['response'] = $value;
}
}
$responseValidation = ContextAwareValidator::getResponseValidator($request->all(), $formStructure);
Log::info('Built response & validator structure!');
$validation = Validator::make($request->all(), $validator);
if (!$validation->fails())
if (!$responseValidation->get('validator')->fails())
{
$response = Response::create([
'responseFormID' => $vacancy->first()->forms->id,
'associatedVacancyID' => $vacancy->first()->id, // Since a form can be used by multiple vacancies, we can only know which specific vacancy this response ties to by using a vacancy ID
'responseData' => json_encode($responseStructure)
'responseData' => $responseValidation->get('responseStructure')
]);
Log::info('Registered form response for user ' . Auth::user()->name . ' for vacancy ' . $vacancy->first()->vacancyName);
@@ -249,35 +231,27 @@ class ApplicationController extends Controller
return redirect()->back();
}
public function updateApplicationStatus(Request $request, $applicationID, $newStatus)
public function updateApplicationStatus(Request $request, $application, $newStatus)
{
$application = Application::find($applicationID);
$this->authorize('update', Application::class);
if (!is_null($application))
switch ($newStatus)
{
switch ($newStatus)
{
case 'deny':
case 'deny':
event(new ApplicationDeniedEvent($application));
break;
event(new ApplicationDeniedEvent($application));
break;
case 'interview':
Log::info('User ' . Auth::user()->name . ' has moved application ID ' . $application->id . 'to interview stage');
$request->session()->flash('success', 'Application moved to interview stage! (:');
$application->setStatus('STAGE_INTERVIEW');
case 'interview':
Log::info('User ' . Auth::user()->name . ' has moved application ID ' . $application->id . 'to interview stage');
$request->session()->flash('success', 'Application moved to interview stage! (:');
$application->setStatus('STAGE_INTERVIEW');
$application->user->notify(new ApplicationMoved());
break;
$application->user->notify(new ApplicationMoved());
break;
default:
$request->session()->flash('error', 'There are no suitable statuses to update to. Do not mess with the URL.');
}
}
else
{
$request->session()->flash('The application you\'re trying to update does not exist.');
default:
$request->session()->flash('error', 'There are no suitable statuses to update to. Do not mess with the URL.');
}
return redirect()->back();
@@ -291,7 +265,7 @@ class ApplicationController extends Controller
$request->session()->flash('success', 'Application deleted. Comments, appointments and responses have also been deleted.');
return redirect()->back();
}
}

View File

@@ -24,84 +24,56 @@ class AppointmentController extends Controller
];
public function saveAppointment(Request $request, $applicationID)
public function saveAppointment(Request $request, Application $application)
{
// Unrelated TODO: change if's in application page to a switch statement, & have the row encompass it
$this->authorize('create', Appointment::class);
$appointmentDate = Carbon::parse($request->appointmentDateTime);
$app = Application::find($applicationID);
if (!is_null($app))
{
// make sure this is a valid date by parsing it first
$appointmentDate = Carbon::parse($request->appointmentDateTime);
$appointment = Appointment::create([
'appointmentDescription' => $request->appointmentDescription,
'appointmentDate' => $appointmentDate->toDateTimeString(),
'applicationID' => $application->id,
'appointmentLocation' => (in_array($request->appointmentLocation, $this->allowedPlatforms)) ? $request->appointmentLocation : 'DISCORD',
]);
$application->setStatus('STAGE_INTERVIEW_SCHEDULED');
$appointment = Appointment::create([
'appointmentDescription' => $request->appointmentDescription,
'appointmentDate' => $appointmentDate->toDateTimeString(),
'applicationID' => $applicationID,
'appointmentLocation' => (in_array($request->appointmentLocation, $this->allowedPlatforms)) ? $request->appointmentLocation : 'DISCORD',
]);
$app->setStatus('STAGE_INTERVIEW_SCHEDULED');
Log::info('User ' . Auth::user()->name . ' has scheduled an appointment with ' . $application->user->name . ' for application ID' . $application->id, [
'datetime' => $appointmentDate->toDateTimeString(),
'scheduled' => now()
]);
$application->user->notify(new AppointmentScheduled($appointment));
$request->session()->flash('success', 'Appointment successfully scheduled @ ' . $appointmentDate->toDateTimeString());
Log::info('User ' . Auth::user()->name . ' has scheduled an appointment with ' . $app->user->name . ' for application ID' . $app->id, [
'datetime' => $appointmentDate->toDateTimeString(),
'scheduled' => now()
]);
$app->user->notify(new AppointmentScheduled($appointment));
$request->session()->flash('success', 'Appointment successfully scheduled @ ' . $appointmentDate->toDateTimeString());
}
else
{
$request->session()->flash('error', 'Cant\'t schedule an appointment for an application that doesn\'t exist.');
}
return redirect()->back();
}
public function updateAppointment(Request $request, $applicationID, $status)
public function updateAppointment(Request $request, Application $application, $status)
{
$this->authorize('update', $application->appointment);
$application = Application::find($applicationID);
$validStatuses = [
'SCHEDULED',
'CONCLUDED'
];
$this->authorize('update', $application->appointment);
// NOTE: This is a little confusing, refactor
$application->appointment->appointmentStatus = (in_array($status, $validStatuses)) ? strtoupper($status) : 'SCHEDULED';
$application->appointment->save();
$application->setStatus('STAGE_PEERAPPROVAL');
$application->user->notify(new ApplicationMoved());
if (!is_null($application))
{
// NOTE: This is a little confusing, refactor
$application->appointment->appointmentStatus = (in_array($status, $validStatuses)) ? strtoupper($status) : 'SCHEDULED';
$application->appointment->save();
$application->setStatus('STAGE_PEERAPPROVAL');
$application->user->notify(new ApplicationMoved());
$request->session()->flash('success', 'Interview finished! Staff members can now vote on it.');
}
else
{
$request->session()->flash('error', 'The application you\'re trying to update doesn\'t exist or have an appointment.');
}
$request->session()->flash('success', 'Interview finished! Staff members can now vote on it.');
return redirect()->back();
}
// also updates
public function saveNotes(SaveNotesRequest $request, $applicationID)
public function saveNotes(SaveNotesRequest $request, $application)
{
$application = Application::find($applicationID);
if (!is_null($application))
{
$application->appointment->meetingNotes = $request->noteText;
@@ -111,7 +83,7 @@ class AppointmentController extends Controller
}
else
{
$request->session()->flash('error', 'Sanity check failed: There\'s no appointment to save notes to!');
$request->session()->flash('error', 'There\'s no appointment to save notes to!');
}
return redirect()->back();

View File

@@ -15,11 +15,7 @@ class BanController extends Controller
public function insert(BanUserRequest $request, User $user)
{
if ($user->is(Auth::user()))
{
$request->session()->flash('error', 'You can\'t ban yourself!');
return redirect()->back();
}
$this->authorize('create', Ban::class);
if (is_null($user->bans))
{

View File

@@ -22,7 +22,7 @@ class CommentController extends Controller
public function insert(NewCommentRequest $request, Application $application)
{
$this->authorize('create', Comment::class);
$comment = Comment::create([
'authorID' => Auth::user()->id,
'applicationID' => $application->id,
@@ -32,14 +32,6 @@ class CommentController extends Controller
if ($comment)
{
foreach (User::all() as $user)
{
if ($user->isStaffMember())
{
$user->notify(new NewComment($comment, $application));
}
}
$request->session()->flash('success', 'Comment posted! (:');
}
else

View File

@@ -4,11 +4,23 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp;
use App\Notifications\NewContact;
use Illuminate\Support\Facades\Http;
use App\User;
class ContactController extends Controller
{
protected $users;
public function __construct(User $users)
{
$this->users = $users;
}
public function create(Request $request)
{
$name = $request->name;
@@ -18,12 +30,14 @@ class ContactController extends Controller
$challenge = $request->input('captcha');
// TODO: now: add middleware for this verification, move to invisible captcha
$verifyrequest = Http::asForm()->post(config('recaptcha.verify.apiurl'), [
'secret' => config('recaptcha.keys.secret'),
'response' => $challenge,
'remoteip' => $_SERVER['REMOTE_ADDR']
'remoteip' => $request->ip()
]);
$response = json_decode($verifyrequest->getBody(), true);
if (!$response['success'])
@@ -32,7 +46,18 @@ class ContactController extends Controller
return redirect()->back();
}
// TODO: Send mail
foreach(User::all() as $user)
{
if ($user->hasRole('admin'))
{
$user->notify(new NewContact(collect([
'message' => $msg,
'ip' => $request->ip(),
'email' => $email
])));
}
}
$request->session()->flash('success', 'Message sent successfully! We usually respond within 48 hours.');
return redirect()->back();

View File

@@ -6,16 +6,30 @@ use App\Application;
use App\Events\ApplicationApprovedEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class DevToolsController extends Controller
{
// The use case for Laravel's gate and/or validation Requests is so tiny here that a full-blown policy would be overkill.
protected function isolatedAuthorise()
{
if (!Auth::user()->can('admin.developertools.use'))
{
abort(403, 'You\'re not authorized to access this page.');
}
}
public function index()
{
$this->isolatedAuthorise();
return view('dashboard.administration.devtools')
->with('applications', Application::where('applicationStatus', 'STAGE_PEERAPPROVAL')->get());
}
public function forceVoteCount(Request $request)
{
$this->isolatedAuthorise();
$application = Application::find($request->application);
if (!is_null($application))

View File

@@ -55,10 +55,8 @@ class FormController extends Controller
return redirect()->back();
}
public function destroy(Request $request, $id)
public function destroy(Request $request, Form $form)
{
$form = Form::find($id);
$this->authorize('delete', $form);
$deletable = true;
@@ -85,6 +83,8 @@ class FormController extends Controller
public function preview(Request $request, Form $form)
{
$this->authorize('viewAny', Form::class);
return view('dashboard.administration.formpreview')
->with('form', json_decode($form->formStructure, true))
->with('title', $form->formName)
@@ -93,6 +93,8 @@ class FormController extends Controller
public function edit(Request $request, Form $form)
{
$this->authorize('update', $form);
return view('dashboard.administration.editform')
->with('formStructure', json_decode($form->formStructure, true))
->with('title', $form->formName)
@@ -101,6 +103,8 @@ class FormController extends Controller
public function update(Request $request, Form $form)
{
$this->authorize('update', $form);
$contextValidation = ContextAwareValidator::getValidator($request->all(), true);
$this->authorize('update', $form);

View File

@@ -87,7 +87,6 @@ class ProfileController extends Controller
public function saveProfile(ProfileSave $request)
{
// TODO: Switch to route model binding
$profile = User::find(Auth::user()->id)->profile;
$social = [];
@@ -120,19 +119,6 @@ class ProfileController extends Controller
$request->session()->flash('success', 'Profile settings saved successfully.');
}
else
{
$gm = 'Guru Meditation #' . rand(0, 1000);
Log::alert('[GURU MEDITATION]: Could not find profile for authenticated user ' . Auth::user()->name . 'whilst trying to update it! Please verify that profiles are being created automatically during signup.',
[
'uuid' => Auth::user()->uuid,
'timestamp' => now(),
'route' => $request->route()->getName(),
'gmcode' => $gm // If this error is reported, the GM code, denoting a severe error, will help us find this entry in the logs
]);
$request->session()->flash('error', 'A technical error has occurred whilst trying to save your profile. Incident details have been recorded. Please report this incident to administrators with the following case number: ' . $gm);
}
return redirect()->back();

View File

@@ -189,6 +189,9 @@ class UserController extends Controller
public function delete(DeleteUserRequest $request, User $user)
{
$this->authorize('delete', $user);
if ($request->confirmPrompt == 'DELETE ACCOUNT')
{
$user->delete();
@@ -206,6 +209,8 @@ class UserController extends Controller
public function update(UpdateUserRequest $request, User $user)
{
$this->authorize('adminEdit', $user);
// Mass update would not be possible here without extra code, making route model binding useless
$user->email = $request->email;
$user->name = $request->name;

View File

@@ -64,10 +64,9 @@ class VacancyController extends Controller
}
public function updatePositionAvailability(Request $request, $status, $id)
public function updatePositionAvailability(Request $request, $status, Vacancy $vacancy)
{
$vacancy = Vacancy::find($id);
$this->authorize('update', $vacancy);
if (!is_null($vacancy))

View File

@@ -13,33 +13,23 @@ use Illuminate\Support\Facades\Log;
class VoteController extends Controller
{
public function vote(VoteRequest $voteRequest, $applicationID)
public function vote(VoteRequest $voteRequest, Application $application)
{
$application = Application::find($applicationID);
$this->authorize('create', Vote::class);
if (!is_null($application))
{
$vote = Vote::create([
'userID' => Auth::user()->id,
'allowedVoteType' => $voteRequest->voteType,
]);
$vote = Vote::create([
'userID' => Auth::user()->id,
'allowedVoteType' => $voteRequest->voteType,
]);
$vote->application()->attach($applicationID);
$vote->application()->attach($applicationID);
Log::info('User ' . Auth::user()->name . ' has voted in applicant ' . $application->user->name . '\'s application', [
'voteType' => $voteRequest->voteType
]);
$voteRequest->session()->flash('success', 'Your vote has been registered! You will now be notified about the outcome of this application.');
}
else
{
$voteRequest->session()->flash('error', 'Can\t vote a non existant application!');
}
Log::info('User ' . Auth::user()->name . ' has voted in applicant ' . $application->user->name . '\'s application', [
'voteType' => $voteRequest->voteType
]);
$voteRequest->session()->flash('success', 'Your vote has been registered!');
// Cron job will run command that processes votes
return redirect()->back();
}
}

View File

@@ -52,7 +52,7 @@ class ApplicationDenied extends Notification implements ShouldQueue
->line('Your most recent application has been denied.')
->line('Our review team denies applications for several reasons, including poor answers.')
->line('Please review your application and try again in 30 days.')
->action('Review application', url(route('showUserApp', ['id' => $this->application->id])))
->action('Review application', url(route('showUserApp', ['application' => $this->application->id])))
->line('Better luck next time!');
}

View File

@@ -55,7 +55,7 @@ class NewApplicant extends Notification implements ShouldQueue
->subject(config('app.name') . ' - New application')
->line('Someone has just applied for a position. Check it out!')
->line('You are receiving this because you\'re a staff member at ' . config('app.name') . '.')
->action('View Application', url(route('showUserApp', ['id' => $this->application->id])))
->action('View Application', url(route('showUserApp', ['application' => $this->application->id])))
->line('Thank you!');
}
@@ -67,7 +67,7 @@ class NewApplicant extends Notification implements ShouldQueue
$vacancyDetails['name'] = $this->vacancy->vacancyName;
$vacancyDetails['slots'] = $this->vacancy->vacancyCount;
$url = route('showUserApp', ['id' => $this->application->id]);
$url = route('showUserApp', ['application' => $this->application->id]);
$applicant = $this->application->user->name;
return (new SlackMessage)

View File

@@ -50,7 +50,7 @@ class NewComment extends Notification implements ShouldQueue
->subject(config('app.name') . ' - New comment')
->line('Someone has just posted a new comment on an application you follow.')
->line('You\'re receiving this email because you\'ve voted/commented on this application.')
->action('Check it out', url(route('showUserApp', ['id' => $this->application->id])))
->action('Check it out', url(route('showUserApp', ['application' => $this->application->id])))
->line('Thank you!');
}

View File

@@ -0,0 +1,78 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Collection;
class NewContact extends Notification
{
use Queueable;
public $message;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(Collection $message)
{
$this->message = $message;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
if ($this->message->has([
'message',
'ip',
'email'
]))
{
return (new MailMessage)
->line('We\'ve received a new contact form submission in the StaffManagement app center.')
->line('This is what they sent: ')
->line('')
->line($this->message->get('message'))
->line('')
->line('This message was received from ' . $this->message->get('ip') . ' and submitted by ' . $this->message->get('email') . '.')
->action('Sign in', url(route('login')))
->line('Thank you!');
}
throw new \InvalidArgumentException("Invalid arguments supplied to NewContact!");
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@@ -41,7 +41,7 @@ class BanPolicy
*/
public function create(User $user)
{
//
return $user->hasRole('admin') && $user->isNot(Auth::user());
}
/**
@@ -53,7 +53,7 @@ class BanPolicy
*/
public function update(User $user, Ban $ban)
{
//
return $user->hasRole('admin');
}
/**

View File

@@ -24,6 +24,12 @@ class UserPolicy
return $authUser->is($user) || $authUser->hasRole('admin');
}
// This refers to the admin tools that let staff update more information than users themselves can
public function adminEdit(User $authUser, User $user)
{
return $authUser->hasRole('admin') && $authUser->isNot($user);
}
public function viewStaff(User $user)
{
return $user->can('admin.stafflist');
@@ -38,4 +44,9 @@ class UserPolicy
{
return $authUser->hasRole('admin');
}
public function delete(User $authUser, User $subject)
{
return $authUser->hasRole('admin') && $authUser->isNot($subject);
}
}

View File

@@ -528,6 +528,16 @@ return [
]
]
],
[
'name' => 'AuthCustomisations',
'active' => true,
'files' => [
[
'type' => 'css',
'asset' => false,
'location' => '/css/authpages.css'
]
]
]
],
];

2
public/app.css vendored
View File

@@ -1,4 +1,4 @@
.page-bg {
.view {
background: url("/slides/06.png")no-repeat center center;
background-size: cover;
}

6
public/css/authpages.css vendored Normal file
View File

@@ -0,0 +1,6 @@
/* overrides customizations for the AdminLTE auth pages */
.login-page, .register-page {
background-image: url('/img/authbg.jpg') !important;
background-size: cover !important;
}

BIN
public/img/authbg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB

View File

@@ -1,73 +1 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<div class="col-md-6 offset-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">
{{ __('Remember Me') }}
</label>
</div>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('adminlte::auth.login')

View File

@@ -1,49 +1 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Confirm Password') }}</div>
<div class="card-body">
{{ __('Please confirm your password before continuing.') }}
<form method="POST" action="{{ route('password.confirm') }}">
@csrf
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Confirm Password') }}
</button>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('adminlte::auth.passwords.confirm')

View File

@@ -1,47 +1 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ route('password.email') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Send Password Reset Link') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('adminlte::auth.passwords.email')

View File

@@ -1,65 +1 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Reset Password') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('adminlte::auth.passwords.reset')

View File

@@ -1,104 +1 @@
@extends('layouts.app')
@section('content')
<x-global-errors></x-global-errors>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
@if (session()->has('error'))
<div class="alert alert-danger">
<i class="fas fa-exclamation"></i><b> Please verify your submission</b>
<p>
{{ session('error') }}
</p>
</div>
@endif
<div class="card">
<div class="card-header">{{ __('Register') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('register') }}">
@csrf
<div class="form-group row">
<label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>
<div class="col-md-6">
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
@error('name')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
</div>
</div>
<div class="form-group row mt-5">
<label for="minecraftUsername" class="col-md-4 col-form-label text-md-right">Minecraft Username</label>
<div class="col-md-6">
<input type="text" id="minecraftUsername" name="uuid" class="form-control @error('uuid') is-invalid @enderror" required>
@error('uuid')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Register') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('adminlte::auth.register')

View File

@@ -1,28 +1 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Verify Your Email Address') }}</div>
<div class="card-body">
@if (session('resent'))
<div class="alert alert-success" role="alert">
{{ __('A fresh verification link has been sent to your email address.') }}
</div>
@endif
{{ __('Before proceeding, please check your email for a verification link.') }}
{{ __('If you did not receive the email') }},
<form class="d-inline" method="POST" action="{{ route('verification.resend') }}">
@csrf
<button type="submit" class="btn btn-link p-0 m-0 align-baseline">{{ __('click here to request another') }}</button>.
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('adminlte::auth.verify')

View File

@@ -0,0 +1,25 @@
<div class="dashboard-footer">
<div class="row">
<div class="col">
<li class="d-inline-block">
<a class="mr-3" href="https://github.com/spacejewel-hosting/staffmanagement"><i class="fab fa-github"></i> Github</a>
<a class="mr-3" href="https://github.com/spacejewel-hosting/staffmanagement/issues"><i class="fas fa-bug"></i> Issue Tracker</a>
</li>
</div>
<div class="col-4 d-inline-block">
<p>&copy; Miguel N. 2020 &mdash; <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">GNU General Public License</a></p>
</div>
</div>
</div>

View File

@@ -96,7 +96,7 @@
<h5>Welcome to our team management center!</h5>
<br>
<p>Here, you can apply for open staff member positions, view your application status, and manage your profile. </p>
<p>Sign up with Twitch or Email to continue.</p>
<p>Sign up with Email to continue.</p>
</div>
</div>
</div>

View File

@@ -73,3 +73,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -101,3 +101,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -133,7 +133,7 @@
@if($vacancy->vacancyStatus == 'OPEN')
<form method="POST" action="{{ route('updatePositionAvailability', ['id' => $vacancy->id, 'status' => 'close']) }}" style="display: inline">
<form method="POST" action="{{ route('updatePositionAvailability', ['vacancy' => $vacancy->id, 'status' => 'close']) }}" style="display: inline">
@method('PATCH')
@csrf
<button type="submit" class="ml-4 btn btn-danger"><i class="fas fa-ban"></i> Close Position</button>
@@ -153,3 +153,7 @@
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -70,3 +70,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -77,3 +77,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -54,7 +54,7 @@
<td>{{$form->created_at}}</td>
<td>{{ $form->updated_at }}</td>
<td>
<form style="display: inline-block; white-space: nowrap" action="{{route('destroyForm', ['id' => $form->id])}}" method="POST">
<form style="display: inline-block; white-space: nowrap" action="{{route('destroyForm', ['form' => $form->id])}}" method="POST">
@method('DELETE')
@csrf
@@ -96,3 +96,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -176,3 +176,7 @@ I
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -195,7 +195,7 @@
@if ($vacancy->vacancyStatus == 'OPEN')
<form action="{{route('updatePositionAvailability', ['status' => 'close', 'id' => $vacancy->id])}}" method="POST" id="closePosition" style="display: inline">
<form action="{{route('updatePositionAvailability', ['status' => 'close', 'vacancy' => $vacancy->id])}}" method="POST" id="closePosition" style="display: inline">
@csrf
@method('PATCH')
<button type="submit" class="btn btn-sm btn-danger"><i class="fa fa-ban"></i></button>
@@ -203,7 +203,7 @@
@else
<form action="{{route('updatePositionAvailability', ['status' => 'open', 'id' => $vacancy->id])}}" method="POST" id="openPosition" style="display: inline">
<form action="{{route('updatePositionAvailability', ['status' => 'open', 'vacancy' => $vacancy->id])}}" method="POST" id="openPosition" style="display: inline">
@csrf
@method('PATCH')
<button type="submit" class="btn btn-sm btn-success"><i class="fa fa-check"></i></button>
@@ -244,3 +244,7 @@
<x-no-permission type="danger"></x-no-permission>
@endif
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -98,3 +98,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -126,3 +126,7 @@
@endif
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -191,7 +191,7 @@
</td>
<td>{{ $application->created_at }}</td>
<td>
<button type="button" class="btn btn-success btn-sm" onclick="window.location.href='{{ route('showUserApp', ['id' => $application->id]) }}'"><i class="fas fa-eye"></i> View</button>
<button type="button" class="btn btn-success btn-sm" onclick="window.location.href='{{ route('showUserApp', ['application' => $application->id]) }}'"><i class="fas fa-eye"></i> View</button>
<button type="button" class="btn btn-danger btn-sm ml-2" onclick="$('#deletionConfirmationModal-{{ $application->id }}').modal('show')"><i class="fa fa-trash"></i> Delete</button>
</td>
</tr>
@@ -241,3 +241,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -77,7 +77,7 @@
<td>{{$application->user->name}}</td>
<td><span class="badge-warning badge">{{($application->applicationStatus == 'STAGE_INTERVIEW') ? 'Pending Interview' : 'Unknown Status'}}</span></td>
<td>
<button type="button" class="btn btn-sm btn-success" onclick="window.location.href='{{route('showUserApp', ['id' => $application->id])}}'"><i class="fa fa-eye"></i> View</button>
<button type="button" class="btn btn-sm btn-success" onclick="window.location.href='{{route('showUserApp', ['application' => $application->id])}}'"><i class="fa fa-eye"></i> View</button>
<button type="button" class="btn btn-sm btn-warning"><i class="fa fa-clock"></i> Schedule</button>
</td>
</tr>
@@ -151,7 +151,7 @@
<td><span class="badge badge-success"><i class="fa fa-check"></i> {{ucfirst(strtolower($upcomingApp->appointment->appointmentLocation))}}</span></td>
@endif
<td>
<button type="button" class="btn btn-sm btn-success" onclick="window.location.href='{{route('showUserApp', ['id' => $upcomingApp->id])}}'"><i class="fa fa-eye"></i> View Details</button>
<button type="button" class="btn btn-sm btn-success" onclick="window.location.href='{{route('showUserApp', ['application' => $upcomingApp->id])}}'"><i class="fa fa-eye"></i> View Details</button>
</td>
</tr>
@@ -191,3 +191,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -70,7 +70,7 @@
<td>{{$application->created_at}}</td>
<td>{{$application->updated_at}}</td>
<td>
<button type="button" class="btn btn-sm btn-warning" onclick="window.location.href='{{route('showUserApp', ['id' => $application->id])}}'"><i class="fas fa-clipboard-check"></i> Review</button>
<button type="button" class="btn btn-sm btn-warning" onclick="window.location.href='{{route('showUserApp', ['application' => $application->id])}}'"><i class="fas fa-clipboard-check"></i> Review</button>
</td>
</tr>
@@ -104,3 +104,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -66,7 +66,7 @@
<td>{{$application->created_at}}</td>
<td><span class="badge badge-warning">{{($application->applicationStatus == 'STAGE_PEERAPPROVAL') ? 'Peer Review' : 'Unknown'}}</span></td>
<td>
<button type="button" class="btn btn-info btn-sm" onclick="window.location.href='{{route('showUserApp', ['id' => $application->id])}}'"><i class="far fa-clipboard"></i> Review</button>
<button type="button" class="btn btn-info btn-sm" onclick="window.location.href='{{route('showUserApp', ['application' => $application->id])}}'"><i class="far fa-clipboard"></i> Review</button>
</td>
@endforeach
@@ -92,3 +92,7 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -262,3 +262,6 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -109,7 +109,7 @@
</td>
<td>
<button type="button" class="btn btn-success" onclick="window.location.href='{{route('showUserApp', ['id' => $application->id])}}'"><i class="fa fa-eye"></i> View</button>
<button type="button" class="btn btn-success" onclick="window.location.href='{{route('showUserApp', ['application' => $application->id])}}'"><i class="fa fa-eye"></i> View</button>
</td>
</tr>
@@ -141,3 +141,6 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -105,3 +105,6 @@
@endif
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -405,7 +405,8 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -164,3 +164,6 @@
</div>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -215,3 +215,6 @@
</form>
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -38,7 +38,7 @@
<x-modal id="notes" modal-label="notes" modal-title="Shared Notepad" include-close-button="true">
<form id="meetingNotes" method="POST" action="{{route('saveNotes', ['applicationID' => $application->id])}}">
<form id="meetingNotes" method="POST" action="{{route('saveNotes', ['application' => $application->id])}}">
@csrf
@method('PATCH')
<textarea name="noteText" rows="5" class="form-control">{{$application->appointment->meetingNotes ?? 'There are no notes yet. Add some!'}}</textarea>
@@ -62,7 +62,7 @@
<x-slot name="modalFooter">
<form id="updateApplication" action="{{route('updateApplicationStatus', ['id' => $application->id, 'newStatus' => 'deny'])}}" method="POST">
<form id="updateApplication" action="{{route('updateApplicationStatus', ['application' => $application->id, 'newStatus' => 'deny'])}}" method="POST">
@csrf
@method('PATCH')
<button type="submit" class="btn btn-danger">Confirm: Deny Applicant</button>
@@ -200,7 +200,7 @@
</div>
<div class="col">
<form method="POST" action="{{route('updateApplicationStatus', ['id' => $application->id, 'newStatus' => 'interview'])}}">
<form method="POST" action="{{route('updateApplicationStatus', ['application' => $application->id, 'newStatus' => 'interview'])}}">
@csrf
@method('PATCH')
<button type="submit" class="btn btn-success" {{($application->applicationStatus == 'DENIED') ? 'disabled' : ''}}><i class="fas fa-arrow-right" ></i> Move to next stage</button>
@@ -230,7 +230,7 @@
</x-slot>
<form id="scheduleAppointment" action="{{route('scheduleAppointment', ['applicationID' => $application->id])}}" method="POST">
<form id="scheduleAppointment" action="{{route('scheduleAppointment', ['application' => $application->id])}}" method="POST">
@csrf
@@ -286,7 +286,7 @@
<x-slot name="cardFooter">
@can('appointments.schedule.edit')
<form style="white-space: nowrap;display:inline-block" class="footer-button" action="{{route('updateAppointment', ['applicationID' => $application->id, 'status' => 'concluded'])}}" method="POST">
<form style="white-space: nowrap;display:inline-block" class="footer-button" action="{{route('updateAppointment', ['application' => $application->id, 'status' => 'concluded'])}}" method="POST">
@csrf
@method('PATCH')
<button type="submit" class="btn btn-success">Finish Meeting</button>
@@ -322,12 +322,12 @@
@if($canVote)
<form class="d-inline-block" method="POST" action="{{route('voteApplication', ['id' => $application->id])}}">
<form class="d-inline-block" method="POST" action="{{route('voteApplication', ['application' => $application->id])}}">
@csrf
<input type="hidden" name="voteType" value="VOTE_APPROVE">
<button type="submit" class="btn btn-sm btn-warning">Vote: Approve Applicant</button>
</form>
<form class="d-inline-block" method="POST" action="{{route('voteApplication', ['id' => $application->id])}}">
<form class="d-inline-block" method="POST" action="{{route('voteApplication', ['application' => $application->id])}}">
@csrf
<input type="hidden" name="voteType" value="VOTE_DENY">
<button type="submit" class="btn btn-sm btn-warning">Vote: Deny Applicant</button>
@@ -500,4 +500,8 @@
@endif
@endhasanyrole
@endsection
@stop
@section('footer')
@include('breadcrumbs.dashboard.footer')
@stop

View File

@@ -59,7 +59,7 @@
<div class="col-md-4">
<div class="card">
<div class="card mt-3">
<div class="card-header text-center">
@@ -270,7 +270,7 @@
<div class="md-form">
<textarea rows="3" name="message" id="message" class="md-textarea form-control"></textarea>
<textarea rows="3" name="msg" id="message" class="md-textarea form-control"></textarea>
</div>

View File

@@ -40,7 +40,7 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
->name('showUserApps')
->middleware('eligibility');
Route::get('/view/{id}', 'ApplicationController@showUserApp')
Route::get('/view/{application}', 'ApplicationController@showUserApp')
->name('showUserApp');
Route::post('/{application}/comments', 'CommentController@insert')
@@ -54,7 +54,7 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
->name('saveNotes');
Route::patch('/update/{id}/{newStatus}', 'ApplicationController@updateApplicationStatus')
Route::patch('/update/{application}/{newStatus}', 'ApplicationController@updateApplicationStatus')
->name('updateApplicationStatus');
Route::delete('{application}/delete', 'ApplicationController@delete')
@@ -78,7 +78,7 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
Route::post('{id}/staff/vote', 'VoteController@vote')
Route::post('{application}/staff/vote', 'VoteController@vote')
->name('voteApplication');
@@ -86,10 +86,10 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
Route::group(['prefix' => 'appointments'], function (){
Route::post('schedule/appointments/{applicationID}', 'AppointmentController@saveAppointment')
Route::post('schedule/appointments/{application}', 'AppointmentController@saveAppointment')
->name('scheduleAppointment');
Route::patch('update/appointments/{applicationID}/{status}', 'AppointmentController@updateAppointment')
Route::patch('update/appointments/{application}/{status}', 'AppointmentController@updateAppointment')
->name('updateAppointment');
});
@@ -156,6 +156,8 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
Route::delete('players/unban/{user}', 'BanController@delete')
->name('unbanUser');
Route::delete('players/delete/{user}', 'UserController@delete')
->name('deleteUser');
@@ -178,7 +180,7 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
->name('updatePosition');
Route::patch('positions/availability/{status}/{id}', 'VacancyController@updatePositionAvailability')
Route::patch('positions/availability/{status}/{vacancy}', 'VacancyController@updatePositionAvailability')
->name('updatePositionAvailability');
@@ -214,5 +216,3 @@ Route::group(['middleware' => ['auth', 'forcelogout']], function(){
});
});
//Route::get('/dashboard/login', '');