Beta version
This commit is too large to list all changes.
This commit is contained in:
parent
d15c0cb12f
commit
5a8c080a31
@ -18,6 +18,9 @@ RECAPTCHA_PRIVATE_KEY=
|
||||
RECAPTCHA_VERIFY_URL="https://www.google.com/recaptcha/api/siteverify"
|
||||
# WARNING: Your contact form will be useless if you change this value. Only change this URL if Google updates it.
|
||||
|
||||
IPGEO_API_KEY=""
|
||||
IPGEO_API_URL=""
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
|
@ -94,10 +94,12 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sentry/sentry" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sentry/sentry-laravel" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-permission" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/swiftmailer/swiftmailer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/css-selector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/debug" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
||||
@ -108,14 +110,18 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-iconv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php72" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php73" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-uuid" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/routing" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
|
||||
|
@ -121,6 +121,12 @@
|
||||
<path value="$PROJECT_DIR$/vendor/clue/stream-filter" />
|
||||
<path value="$PROJECT_DIR$/vendor/jean85/pretty-package-versions" />
|
||||
<path value="$PROJECT_DIR$/vendor/http-interop/http-factory-guzzle" />
|
||||
<path value="$PROJECT_DIR$/vendor/spatie/laravel-permission" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/string" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.2" />
|
||||
|
22
.vscode/launch.json
vendored
Normal file
22
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Listen for XDebug",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"port": 9000
|
||||
},
|
||||
{
|
||||
"name": "Launch currently open script",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"cwd": "${fileDirname}",
|
||||
"port": 9000
|
||||
}
|
||||
]
|
||||
}
|
@ -15,6 +15,8 @@ class Application extends Model
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\User', 'applicantUserID', 'id');
|
||||
@ -35,6 +37,12 @@ class Application extends Model
|
||||
return $this->belongsToMany('App\Vote', 'votes_has_application');
|
||||
}
|
||||
|
||||
|
||||
public function comments()
|
||||
{
|
||||
return $this->hasMany('App\Comment', 'applicationID', 'id');
|
||||
}
|
||||
|
||||
public function setStatus($status)
|
||||
{
|
||||
return $this->update([
|
||||
|
@ -16,6 +16,7 @@ class Appointment extends Model
|
||||
|
||||
public function application()
|
||||
{
|
||||
// FIXME: Possible bug here, where laravel looks for the wrong column in the applications table.
|
||||
return $this->belongsTo('App\Application', 'id', 'applicationID');
|
||||
}
|
||||
|
||||
|
25
app/Ban.php
Normal file
25
app/Ban.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Ban extends Model
|
||||
{
|
||||
|
||||
public $fillable = [
|
||||
|
||||
'userID',
|
||||
'reason',
|
||||
'bannedUntil',
|
||||
'userAgent',
|
||||
'authorUserID'
|
||||
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\User', 'userID', 'id');
|
||||
}
|
||||
|
||||
}
|
26
app/Comment.php
Normal file
26
app/Comment.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Comment extends Model
|
||||
{
|
||||
|
||||
protected $fillable = [
|
||||
'authorID',
|
||||
'applicationID',
|
||||
'text'
|
||||
];
|
||||
|
||||
public function application()
|
||||
{
|
||||
return $this->belongsTo('App\Application', 'applicationID', 'id');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\User', 'authorID', 'id');
|
||||
}
|
||||
|
||||
}
|
@ -96,6 +96,9 @@ class CountVotes extends Command
|
||||
$this->info('✓ Dispatched promotion event for applicant ' . $application->user->name);
|
||||
if (!$this->option('dryrun'))
|
||||
{
|
||||
$application->response->vacancy->vacancyCount -= 1;
|
||||
$application->response->vacancy->save();
|
||||
|
||||
event(new ApplicationApprovedEvent(Application::find($application->id)));
|
||||
}
|
||||
else
|
||||
|
@ -4,6 +4,7 @@ namespace App\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
use App\Jobs\CleanBans;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
@ -27,7 +28,11 @@ class Kernel extends ConsoleKernel
|
||||
// $schedule->command('inspire')->hourly();
|
||||
|
||||
$schedule->command('vote:evaluate')
|
||||
->everyFiveMinutes();
|
||||
->daily();
|
||||
// Production value: Every day
|
||||
|
||||
$schedule->job(new CleanBans)
|
||||
->daily();
|
||||
// Production value: Every day
|
||||
}
|
||||
|
||||
|
42
app/CustomFacades/IP.php
Normal file
42
app/CustomFacades/IP.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\CustomFacades;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class IP
|
||||
{
|
||||
|
||||
/**
|
||||
* Looks up information on a specified IP address. Caches results automatically.
|
||||
* @param string $IP IP address to lookup
|
||||
* @return object
|
||||
*/
|
||||
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
|
||||
];
|
||||
|
||||
// TODO: Maybe unwrap this? Methods are chained here
|
||||
|
||||
return json_decode(Cache::remember($IP, 3600, function() use ($IP)
|
||||
{
|
||||
return Http::get(config('general.urls.ipapi.ipcheck'), [
|
||||
'apiKey' => config('general.keys.ipapi.apikey'),
|
||||
'ip' => $IP
|
||||
])->body();
|
||||
}));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
36
app/Events/NewApplicationEvent.php
Normal file
36
app/Events/NewApplicationEvent.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class NewApplicationEvent
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return \Illuminate\Broadcasting\Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
}
|
36
app/Events/UserBannedEvent.php
Normal file
36
app/Events/UserBannedEvent.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
use App\User;
|
||||
use App\Ban;
|
||||
|
||||
class UserBannedEvent
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
|
||||
public $user;
|
||||
|
||||
public $ban;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, Ban $ban)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->ban = $ban;
|
||||
}
|
||||
|
||||
}
|
13
app/Facades/IP.php
Normal file
13
app/Facades/IP.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class IP extends Facade
|
||||
{
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'ipInformationFacade';
|
||||
}
|
||||
}
|
13
app/Facades/UUID.php
Normal file
13
app/Facades/UUID.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class UUID extends Facade
|
||||
{
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'uuidConversionFacade';
|
||||
}
|
||||
}
|
@ -3,13 +3,20 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Application;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Response;
|
||||
use App\Vacancy;
|
||||
use App\User;
|
||||
|
||||
use App\Events\ApplicationDeniedEvent;
|
||||
use App\Notifications\NewApplicant;
|
||||
use App\Notifications\ApplicationMoved;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ApplicationController extends Controller
|
||||
{
|
||||
@ -21,15 +28,15 @@ class ApplicationController extends Controller
|
||||
{
|
||||
if ($vote->userID == Auth::user()->id)
|
||||
{
|
||||
Log::debug('Match');
|
||||
$allvotes->push($vote);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $allvotes->count() == 1;
|
||||
return ($allvotes->count() == 1) ? false : true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function showUserApps()
|
||||
{
|
||||
|
||||
@ -37,16 +44,22 @@ class ApplicationController extends Controller
|
||||
->with('applications', Auth::user()->applications);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function showUserApp(Request $request, $applicationID)
|
||||
{
|
||||
$application = Application::find($applicationID);
|
||||
|
||||
$this->authorize('view', $application);
|
||||
|
||||
if (!is_null($application))
|
||||
{
|
||||
return view('dashboard.user.viewapp')
|
||||
->with(
|
||||
[
|
||||
'application' => $application,
|
||||
'comments' => $application->comments,
|
||||
'structuredResponses' => json_decode($application->response->responseData, true),
|
||||
'formStructure' => $application->response->form,
|
||||
'vacancy' => $application->response->vacancy,
|
||||
@ -63,6 +76,8 @@ class ApplicationController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function showAllPendingApps()
|
||||
{
|
||||
return view('dashboard.appmanagement.outstandingapps')
|
||||
@ -70,6 +85,9 @@ class ApplicationController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function showPendingInterview()
|
||||
{
|
||||
$applications = Application::with('appointment', 'user')->get();
|
||||
@ -109,6 +127,8 @@ class ApplicationController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function showPeerReview()
|
||||
{
|
||||
return view('dashboard.appmanagement.peerreview')
|
||||
@ -116,11 +136,16 @@ class ApplicationController extends Controller
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function renderApplicationForm(Request $request, $vacancySlug)
|
||||
{
|
||||
// FIXME: Get rid of references to first(), this is a wonky query
|
||||
$vacancyWithForm = Vacancy::with('forms')->where('vacancySlug', $vacancySlug)->get();
|
||||
|
||||
if (!$vacancyWithForm->isEmpty())
|
||||
$firstVacancy = $vacancyWithForm->first();
|
||||
|
||||
if (!$vacancyWithForm->isEmpty() && $firstVacancy->vacancyCount !== 0 && $firstVacancy->vacancyStatus == 'OPEN')
|
||||
{
|
||||
|
||||
return view('dashboard.application-rendering.apply')
|
||||
@ -133,15 +158,25 @@ class ApplicationController extends Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
abort(404, 'We\'re ssssorry, but the application form you\'re looking for could not be found.');
|
||||
abort(404, 'The application you\'re looking for could not be found or it is currently unavailable.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function saveApplicationAnswers(Request $request, $vacancySlug)
|
||||
{
|
||||
$vacancy = Vacancy::with('forms')->where('vacancySlug', $vacancySlug)->get();
|
||||
|
||||
if ($vacancy->first()->vacancyCount == 0 || $vacancy->first()->vacancyStatus !== 'OPEN')
|
||||
{
|
||||
|
||||
$request->session()->flash('error', 'This application is unavailable.');
|
||||
return redirect()->back();
|
||||
|
||||
}
|
||||
|
||||
Log::info('Processing new application!');
|
||||
|
||||
$formStructure = json_decode($vacancy->first()->forms->formStructure, true);
|
||||
@ -179,7 +214,7 @@ class ApplicationController extends Controller
|
||||
|
||||
Log::info('Registered form response for user ' . Auth::user()->name . ' for vacancy ' . $vacancy->first()->vacancyName);
|
||||
|
||||
Application::create([
|
||||
$application = Application::create([
|
||||
'applicantUserID' => Auth::user()->id,
|
||||
'applicantFormResponseID' => $response->id,
|
||||
'applicationStatus' => 'STAGE_SUBMITTED',
|
||||
@ -187,6 +222,14 @@ class ApplicationController extends Controller
|
||||
|
||||
Log::info('Submitted application for user ' . Auth::user()->name . ' with response ID' . $response->id);
|
||||
|
||||
foreach(User::all() as $user)
|
||||
{
|
||||
if ($user->hasRole('admin'))
|
||||
{
|
||||
$user->notify((new NewApplicant($application, $vacancy->first()))->delay(now()->addSeconds(10)));
|
||||
}
|
||||
}
|
||||
|
||||
$request->session()->flash('success', 'Thank you for your application! It will be reviewed as soon as possible.');
|
||||
return redirect()->to(route('showUserApps'));
|
||||
}
|
||||
@ -210,15 +253,15 @@ class ApplicationController extends Controller
|
||||
{
|
||||
case 'deny':
|
||||
|
||||
Log::info('User ' . Auth::user()->name . ' has denied application ID ' . $application->id);
|
||||
$request->session()->flash('success', 'Application denied.');
|
||||
$application->setStatus('DENIED');
|
||||
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');
|
||||
|
||||
$application->user->notify(new ApplicationMoved());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -7,6 +7,8 @@ use App\Http\Requests\SaveNotesRequest;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Appointment;
|
||||
use App\Notifications\ApplicationMoved;
|
||||
use App\Notifications\AppointmentScheduled;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@ -47,7 +49,8 @@ class AppointmentController extends Controller
|
||||
'datetime' => $appointmentDate->toDateTimeString(),
|
||||
'scheduled' => now()
|
||||
]);
|
||||
|
||||
|
||||
$app->user->notify(new AppointmentScheduled($appointment));
|
||||
$request->session()->flash('success', 'Appointment successfully scheduled @ ' . $appointmentDate->toDateTimeString());
|
||||
|
||||
}
|
||||
@ -70,10 +73,12 @@ class AppointmentController extends Controller
|
||||
|
||||
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.');
|
||||
}
|
||||
|
@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\User;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
@ -19,7 +21,9 @@ class LoginController extends Controller
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesUsers;
|
||||
use AuthenticatesUsers {
|
||||
attemptLogin as protected originalAttemptLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
@ -37,4 +41,29 @@ class LoginController extends Controller
|
||||
{
|
||||
$this->middleware('guest')->except('logout');
|
||||
}
|
||||
|
||||
// We can't customise the error message, since that would imply overriding the login method, which is large.
|
||||
// Also, the user should never know that they're banned.
|
||||
public function attemptLogin(Request $request)
|
||||
{
|
||||
$user = User::where('email', $request->email)->first();
|
||||
|
||||
if ($user)
|
||||
{
|
||||
$isBanned = $user->isBanned();
|
||||
if ($isBanned)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->originalAttemptLogin($request);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->originalAttemptLogin($request);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -43,6 +43,21 @@ class RegisterController extends Controller
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
public function showRegistrationForm()
|
||||
{
|
||||
$users = User::where('originalIP', \request()->ip())->get();
|
||||
|
||||
foreach($users as $user)
|
||||
{
|
||||
if ($user && $user->isBanned())
|
||||
{
|
||||
abort(403, 'You do not have permission to access this page.');
|
||||
}
|
||||
}
|
||||
|
||||
return view('auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
@ -78,15 +93,10 @@ class RegisterController extends Controller
|
||||
'originalIP' => request()->ip()
|
||||
]);
|
||||
|
||||
Profile::create([
|
||||
|
||||
'profileShortBio' => 'Write a one-liner about you here!',
|
||||
'profileAboutMe' => 'Tell us a bit about you.',
|
||||
'socialLinks' => '{}',
|
||||
'userID' => $user->id
|
||||
|
||||
]);
|
||||
// It's not the registration controller's concern to create a profile for the user,
|
||||
// so this code has been moved to it's respective observer, following the separation of concerns pattern.
|
||||
|
||||
$user->assignRole('user');
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
91
app/Http/Controllers/BanController.php
Normal file
91
app/Http/Controllers/BanController.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Ban;
|
||||
use App\User;
|
||||
use App\Events\UserBannedEvent;
|
||||
use App\Http\Requests\BanUserRequest;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (is_null($user->bans))
|
||||
{
|
||||
|
||||
$reason = $request->reason;
|
||||
$duration = strtolower($request->durationOperator);
|
||||
$durationOperand = $request->durationOperand;
|
||||
|
||||
|
||||
if (!empty($duration))
|
||||
{
|
||||
$expiryDate = now();
|
||||
|
||||
switch($duration)
|
||||
{
|
||||
case 'days':
|
||||
$expiryDate->addDays($duration);
|
||||
break;
|
||||
|
||||
case 'weeks':
|
||||
$expiryDate->addWeeks($duration);
|
||||
break;
|
||||
|
||||
case 'months':
|
||||
$expiryDate->addMonths($duration);
|
||||
break;
|
||||
|
||||
case 'years':
|
||||
$expiryDate->addYears($duration);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$ban = Ban::create([
|
||||
'userID' => $user->id,
|
||||
'reason' => $request->reason,
|
||||
'bannedUntil' => $expiryDate->toDateTimeString() ?? null,
|
||||
'userAgent' => "Unknown",
|
||||
'authorUserID' => Auth::user()->id
|
||||
]);
|
||||
|
||||
event(new UserBannedEvent($user, $ban));
|
||||
$request->session()->flash('success', 'User banned successfully! Ban ID: #' . $ban->id);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'User already banned!');
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
|
||||
public function delete(Request $request, User $user)
|
||||
{
|
||||
if (!is_null($user->bans))
|
||||
{
|
||||
$user->bans->delete();
|
||||
$request->session()->flash('success', 'User unbanned successfully!');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'This user isn\'t banned!');
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
68
app/Http/Controllers/CommentController.php
Normal file
68
app/Http/Controllers/CommentController.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Requests\NewCommentRequest;
|
||||
|
||||
use App\Comment;
|
||||
use App\Application;
|
||||
use App\Notifications\NewComment;
|
||||
use App\User;
|
||||
|
||||
class CommentController extends Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function insert(NewCommentRequest $request, Application $application)
|
||||
{
|
||||
// Type hinting makes laravel automatically validate everything
|
||||
|
||||
$comment = Comment::create([
|
||||
'authorID' => Auth::user()->id,
|
||||
'applicationID' => $application->id,
|
||||
'text' => $request->comment
|
||||
]);
|
||||
|
||||
if ($comment)
|
||||
{
|
||||
|
||||
foreach (User::all() as $user)
|
||||
{
|
||||
if ($user->isStaffMember())
|
||||
{
|
||||
$user->notify(new NewComment($comment, $application));
|
||||
}
|
||||
}
|
||||
|
||||
$request->session()->flash('success', 'Comment posted! (:');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'Something went wrong while posting your comment!');
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
|
||||
}
|
||||
|
||||
public function delete(Request $request, Comment $comment)
|
||||
{
|
||||
if (Auth::user()->is($comment->user) || Auth::user()->hasRole('admin'))
|
||||
{
|
||||
$comment->delete();
|
||||
$request->session()->flash('success', 'Comment deleted!');
|
||||
}
|
||||
|
||||
$request->session()->flash('error', 'You do not have permission to delete this comment!');
|
||||
|
||||
return redirect()->back();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Vacancy;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
@ -17,7 +18,13 @@ class HomeController extends Controller
|
||||
// TODO: Relationships for Applications, Users and Responses
|
||||
// Also prevent apps if user already has one in the space of 30d
|
||||
// Display apps in the relevant menus
|
||||
|
||||
$positions = DB::table('vacancies')
|
||||
->where('vacancyStatus', 'OPEN')
|
||||
->where('vacancyCount', '!=', 0)
|
||||
->get();
|
||||
|
||||
return view('home')
|
||||
->with('positions', Vacancy::where('vacancyStatus', 'OPEN')->get());
|
||||
->with('positions', $positions);
|
||||
}
|
||||
}
|
||||
|
@ -5,15 +5,20 @@ namespace App\Http\Controllers;
|
||||
use App\Http\Requests\ProfileSave;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Profile;
|
||||
use App\User;
|
||||
use App\Facades\IP;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
public function showProfile()
|
||||
{
|
||||
|
||||
$socialMediaProfiles = json_decode(Auth::user()->profile->socialLinks, true);
|
||||
$socialLinks = Auth::user()->profile->socialLinks ?? "[]";
|
||||
$socialMediaProfiles = json_decode($socialLinks, true);
|
||||
|
||||
return view('dashboard.user.profile.userprofile')
|
||||
->with([
|
||||
@ -26,11 +31,56 @@ class ProfileController extends Controller
|
||||
|
||||
}
|
||||
|
||||
// Route model binding
|
||||
public function showSingleProfile(Request $request, User $user)
|
||||
{
|
||||
|
||||
$socialMediaProfiles = json_decode($user->profile->socialLinks, true);
|
||||
$createdDate = Carbon::parse($user->created_at);
|
||||
|
||||
$systemRoles = Role::all()->pluck('name')->all();
|
||||
$userRoles = $user->roles->pluck('name')->all();
|
||||
|
||||
$roleList = [];
|
||||
|
||||
|
||||
foreach($systemRoles as $role)
|
||||
{
|
||||
if (in_array($role, $userRoles))
|
||||
{
|
||||
$roleList[$role] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$roleList[$role] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Auth::user()->is($user) || Auth::user()->can('profiles.view.others'))
|
||||
{
|
||||
return view('dashboard.user.profile.displayprofile')
|
||||
->with([
|
||||
'profile' => $user->profile,
|
||||
'github' => $socialMediaProfiles['links']['github'] ?? 'UpdateMe',
|
||||
'twitter' => $socialMediaProfiles['links']['twitter'] ?? 'UpdateMe',
|
||||
'insta' => $socialMediaProfiles['links']['insta'] ?? 'UpdateMe',
|
||||
'discord' => $socialMediaProfiles['links']['discord'] ?? 'UpdateMe#12345',
|
||||
'since' => $createdDate->englishMonth . " " . $createdDate->year,
|
||||
'ipInfo' => IP::lookup($user->originalIP),
|
||||
'roles' => $roleList
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
abort(403, 'You cannot view someone else\'s profile.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function saveProfile(ProfileSave $request)
|
||||
{
|
||||
// TODO: Implement profile security policy for logged in users
|
||||
|
||||
$profile = Profile::find(Auth::user()->id);
|
||||
// TODO: Switch to route model binding
|
||||
$profile = User::find(Auth::user()->id)->profile;
|
||||
$social = [];
|
||||
|
||||
if (!is_null($profile))
|
||||
@ -57,7 +107,7 @@ class ProfileController extends Controller
|
||||
$profile->avatarPreference = $avatarPref;
|
||||
$profile->socialLinks = json_encode($social);
|
||||
|
||||
$profile->save();
|
||||
$newProfile = $profile->save();
|
||||
|
||||
$request->session()->flash('success', 'Profile settings saved successfully.');
|
||||
|
||||
|
@ -5,23 +5,117 @@ namespace App\Http\Controllers;
|
||||
use App\Http\Requests\ChangeEmailRequest;
|
||||
use App\Http\Requests\ChangePasswordRequest;
|
||||
use App\Http\Requests\FlushSessionsRequest;
|
||||
use App\Http\Requests\DeleteUserRequest;
|
||||
use App\Http\Requests\SearchPlayerRequest;
|
||||
use App\Http\Requests\UpdateUserRequest;
|
||||
|
||||
use App\User;
|
||||
use App\Ban;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Facades\UUID;
|
||||
use App\Notifications\EmailChanged;
|
||||
use App\Notifications\ChangedPassword;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
||||
public function showStaffMembers()
|
||||
{
|
||||
return view('dashboard.administration.staff-members');
|
||||
|
||||
$staffRoles = [
|
||||
'reviewer',
|
||||
'hiringManager',
|
||||
'admin'
|
||||
]; // TODO: Un-hardcode this, move to config/roles.php
|
||||
|
||||
if (Auth::user()->can('admin.stafflist'))
|
||||
{
|
||||
$users = User::with('roles')->get();
|
||||
$staffMembers = collect([]);
|
||||
|
||||
foreach($users as $user)
|
||||
{
|
||||
if (empty($user->roles))
|
||||
{
|
||||
Log::debug($user->role->name);
|
||||
Log::debug('Staff list: User without role detected; Ignoring');
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach($user->roles as $role)
|
||||
{
|
||||
if (in_array($role->name, $staffRoles))
|
||||
{
|
||||
$staffMembers->push($user);
|
||||
continue 2; // Skip directly to the next user instead of comparing more roles for the current user
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return view('dashboard.administration.staff-members')
|
||||
->with([
|
||||
'users' => $staffMembers
|
||||
]);
|
||||
}
|
||||
|
||||
abort(403, 'Forbidden');
|
||||
}
|
||||
|
||||
public function showPlayers()
|
||||
{
|
||||
return view('dashboard.administration.players');
|
||||
$users = User::with('roles')->get();
|
||||
$players = collect([]);
|
||||
|
||||
foreach($users as $user)
|
||||
{
|
||||
// TODO: Might be problematic if we don't check if the role is user
|
||||
if (count($user->roles) == 1)
|
||||
{
|
||||
$players->push($user);
|
||||
}
|
||||
}
|
||||
|
||||
if (Auth::user()->can('admin.userlist'))
|
||||
{
|
||||
return view('dashboard.administration.players')
|
||||
->with([
|
||||
'users' => $players,
|
||||
'bannedUserCount' => Ban::all()->count()
|
||||
]);
|
||||
}
|
||||
|
||||
abort(403, 'Forbidden');
|
||||
}
|
||||
|
||||
|
||||
public function showPlayersLike(SearchPlayerRequest $request)
|
||||
{
|
||||
$searchTerm = $request->searchTerm;
|
||||
|
||||
$matchingUsers = User::query()
|
||||
->where('name', 'LIKE', "%{$searchTerm}%")
|
||||
->orWhere('email', 'LIKE', "%{$searchTerm}%")
|
||||
->get();
|
||||
|
||||
if (!$matchingUsers->isEmpty())
|
||||
{ $request->session()->flash('success', 'There were ' . $matchingUsers->count() . ' user(s) matching your search.');
|
||||
|
||||
return view('dashboard.administration.players')
|
||||
->with([
|
||||
'users' => $matchingUsers,
|
||||
'bannedUserCount' => Ban::all()->count()
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'Your search term did not return any results.');
|
||||
return redirect(route('registeredPlayerList'));
|
||||
}
|
||||
}
|
||||
|
||||
public function showAccount()
|
||||
@ -62,9 +156,9 @@ class UserController extends Controller
|
||||
'userID' => $user->id,
|
||||
'timestamp' => now()
|
||||
]);
|
||||
Auth::logout();
|
||||
$user->notify(new ChangedPassword());
|
||||
|
||||
// After logout, the user gets caught by the auth filter, and it automatically redirects back to the previous page
|
||||
Auth::logout();
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
@ -84,6 +178,7 @@ class UserController extends Controller
|
||||
'userID' => $user->id,
|
||||
'timestamp' => now()
|
||||
]);
|
||||
$user->notify(new EmailChanged());
|
||||
|
||||
$request->session()->flash('success', 'Your email address has been changed!');
|
||||
}
|
||||
@ -95,4 +190,88 @@ class UserController extends Controller
|
||||
return redirect()->back();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function delete(DeleteUserRequest $request, User $user)
|
||||
{
|
||||
if ($request->confirmPrompt == 'DELETE ACCOUNT')
|
||||
{
|
||||
$user->delete();
|
||||
$request->session()->flash('success','User deleted successfully. PII has been erased.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'Wrong confirmation text! Try again.');
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('registeredPlayerList');
|
||||
}
|
||||
|
||||
public function update(UpdateUserRequest $request, User $user)
|
||||
{
|
||||
|
||||
// Mass update would not be possible here without extra code, making route model binding useless
|
||||
$user->email = $request->email;
|
||||
$user->name = $request->name;
|
||||
$user->uuid = $request->uuid;
|
||||
|
||||
$existingRoles = Role::all()
|
||||
->pluck('name')
|
||||
->all();
|
||||
|
||||
$roleDiff = array_diff($existingRoles, $request->roles);
|
||||
|
||||
// Adds roles that were selected. Removes roles that aren't selected if the user has them.
|
||||
foreach($roleDiff as $deselectedRole)
|
||||
{
|
||||
if ($user->hasRole($deselectedRole) && $deselectedRole !== 'user')
|
||||
{
|
||||
$user->removeRole($deselectedRole);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($request->roles as $role)
|
||||
{
|
||||
if (!$user->hasRole($role))
|
||||
{
|
||||
$user->assignRole($role);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$user->save();
|
||||
$request->session()->flash('success', 'User updated successfully!');
|
||||
|
||||
return redirect()->back();
|
||||
|
||||
}
|
||||
|
||||
public function terminate(Request $request, User $user)
|
||||
{
|
||||
$this->authorize('terminate', Auth::user());
|
||||
|
||||
if (!$user->isStaffMember() || $user->is(Auth::user()))
|
||||
{
|
||||
$request->session()->flash('error', 'You cannot terminate this user.');
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
foreach ($user->roles as $role)
|
||||
{
|
||||
if ($role->name == 'user')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$user->removeRole($role->name);
|
||||
}
|
||||
|
||||
Log::info('User ' . $user->name . ' has just been demoted.');
|
||||
$request->session()->flash('success', 'User terminated successfully.');
|
||||
|
||||
//TODO: Dispatch event
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,12 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Form;
|
||||
use App\Http\Requests\VacancyRequest;
|
||||
use App\Vacancy;
|
||||
use App\User;
|
||||
use App\Form;
|
||||
|
||||
use App\Notifications\VacancyClosed;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
@ -68,6 +71,13 @@ class VacancyController extends Controller
|
||||
$vacancy->close();
|
||||
$message = "Position successfully closed!";
|
||||
|
||||
foreach(User::all() as $user)
|
||||
{
|
||||
if ($user->isStaffMember())
|
||||
{
|
||||
$user->notify(new VacancyClosed($vacancy));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -63,6 +63,7 @@ class Kernel extends HttpKernel
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'eligibility' => \App\Http\Middleware\ApplicationEligibility::class,
|
||||
'usernameUUID' => \App\Http\Middleware\UsernameUUID::class
|
||||
'usernameUUID' => \App\Http\Middleware\UsernameUUID::class,
|
||||
'forcelogout' => \App\Http\Middleware\ForceLogoutMiddleware::class
|
||||
];
|
||||
}
|
||||
|
39
app/Http/Middleware/Bancheck.php
Normal file
39
app/Http/Middleware/Bancheck.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class Bancheck
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$userIP = $request->ip();
|
||||
$anonymousUser = User::where('ipAddress', $userIP)->get();
|
||||
|
||||
|
||||
if (Auth::check() && Auth::user()->isBanned())
|
||||
{
|
||||
View::share('isBanned', true);
|
||||
}
|
||||
elseif(!$anonymousUser->isEmpty() && User::find($anonymousUser->id)->isBanned())
|
||||
{
|
||||
View::share('isBanned', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
View::share('isBanned', false);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
29
app/Http/Middleware/ForceLogoutMiddleware.php
Normal file
29
app/Http/Middleware/ForceLogoutMiddleware.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ForceLogoutMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (Auth::user()->isBanned())
|
||||
{
|
||||
Auth::logout();
|
||||
|
||||
$request->session()->flash('error', 'Error: Your session has been forcefully terminated. Please try again in a few days.');
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
34
app/Http/Requests/BanUserRequest.php
Normal file
34
app/Http/Requests/BanUserRequest.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
||||
class BanUserRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::user()->hasRole('admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'reason' => 'required|string',
|
||||
'durationOperand' => 'nullable|integer',
|
||||
'durationOperator' => 'nullable|string'
|
||||
];
|
||||
}
|
||||
}
|
31
app/Http/Requests/DeleteUserRequest.php
Normal file
31
app/Http/Requests/DeleteUserRequest.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DeleteUserRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::user()->hasRole('admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'confirmPrompt' => 'required|string'
|
||||
];
|
||||
}
|
||||
}
|
33
app/Http/Requests/NewCommentRequest.php
Normal file
33
app/Http/Requests/NewCommentRequest.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
||||
class NewCommentRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
// TODO: Switch to permission checking when there are comment permission nodes
|
||||
return Auth::user()->hasAnyRole('reviewer', 'hiringManager', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'comment' => 'required|string|max:600|min:20'
|
||||
];
|
||||
}
|
||||
}
|
31
app/Http/Requests/SearchPlayerRequest.php
Normal file
31
app/Http/Requests/SearchPlayerRequest.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class SearchPlayerRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::user()->can('admin.userlist');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'searchTerm' => 'required|string|max:17' // max user char limit set by Mojang
|
||||
];
|
||||
}
|
||||
}
|
34
app/Http/Requests/UpdateUserRequest.php
Normal file
34
app/Http/Requests/UpdateUserRequest.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UpdateUserRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::user()->hasRole('admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email',
|
||||
'name' => 'required|string',
|
||||
'uuid' => 'required|max:32|min:32',
|
||||
'roles' => 'required_without_all'
|
||||
];
|
||||
}
|
||||
}
|
56
app/Jobs/CleanBans.php
Normal file
56
app/Jobs/CleanBans.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Ban;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class CleanBans implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
|
||||
public $bans;
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
Log::debug('Running automatic ban cleaner...');
|
||||
$bans = Ban::all();
|
||||
|
||||
if (!is_null($bans))
|
||||
{
|
||||
foreach($this->bans as $ban)
|
||||
{
|
||||
$bannedUntil = Carbon::parse($ban->bannedUntil);
|
||||
|
||||
if ($bannedUntil->equalTo(now()))
|
||||
{
|
||||
Log::debug('Deleted ban ' . $ban->id . ' belonging to ' . $ban->user->name);
|
||||
$ban->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\ApplicationDeniedEvent;
|
||||
use App\Notifications\ApplicationDenied;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@ -30,6 +31,7 @@ class DenyUser
|
||||
$event->application->setStatus('DENIED');
|
||||
Log::info('User ' . $event->application->user->name . ' just had their application denied.');
|
||||
|
||||
// Also dispatch other notifications
|
||||
$event->application->user->notify(new ApplicationDenied($event->application));
|
||||
|
||||
}
|
||||
}
|
||||
|
46
app/Listeners/OnUserBanned.php
Normal file
46
app/Listeners/OnUserBanned.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use App\Events\UserBannedEvent;
|
||||
use App\Notifications\UserBanned;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\User;
|
||||
|
||||
class OnUserBanned
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UserBannedEvent $event)
|
||||
{
|
||||
|
||||
Log::warning("User " . $event->user->name . " has just been banned from the site!");
|
||||
|
||||
foreach(User::all() as $user)
|
||||
{
|
||||
if ($user->isStaffMember())
|
||||
{
|
||||
$user->notify((new UserBanned($event->user, $event->ban))->delay(now()->addSeconds(10)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -7,6 +7,9 @@ use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
use App\User;
|
||||
use App\Notifications\NewUser;
|
||||
|
||||
class OnUserRegistration
|
||||
{
|
||||
/**
|
||||
@ -29,5 +32,13 @@ class OnUserRegistration
|
||||
{
|
||||
// TODO: Send push notification to online admins via browser (w/ pusher)
|
||||
Log::info('User ' . $event->user->name . ' has just registered for an account.');
|
||||
|
||||
foreach(User::all() as $user)
|
||||
{
|
||||
if ($user->hasRole('admin'))
|
||||
{
|
||||
$user->notify(new NewUser($event->user));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace App\Listeners;
|
||||
|
||||
use App\Events\ApplicationApprovedEvent;
|
||||
use App\StaffProfile;
|
||||
use App\Notifications\ApplicationApproved;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
@ -37,11 +38,15 @@ class PromoteUser
|
||||
'memberNotes' => 'Approved by staff members. Welcome them to the team!'
|
||||
]);
|
||||
|
||||
$event->application->user->assignRole('reviewer');
|
||||
|
||||
Log::info('User ' . $event->application->user->name . ' has just been promoted!', [
|
||||
'newRank' => $event->application->response->vacancy->permissionGroupName,
|
||||
'staffProfileID' => $staffProfile->id
|
||||
]);
|
||||
// TODO: Dispatch alert email and notifications for the user and staff members
|
||||
|
||||
$event->application->user->notify(new ApplicationApproved($event->application));
|
||||
// note: Also notify staff
|
||||
// TODO: Also assign new app role based on the permission group name
|
||||
|
||||
}
|
||||
|
93
app/Notifications/ApplicationApproved.php
Normal file
93
app/Notifications/ApplicationApproved.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use App\Application;
|
||||
|
||||
class ApplicationApproved extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $application;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail', 'slack'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - ' . $this->application->response->vacancy->vacancyName . ' application approved')
|
||||
->line('<br />')
|
||||
->line('Congratulations! Our Staff team has reviewed your application today, and your application has been approved.')
|
||||
->line('You have just received the Reviewer role, which allows you to view and vote on other applications.')
|
||||
->line('Your in-game rank should be updated network-wide in the next few minutes, allowing you to perform staff duties.')
|
||||
->line('Please join a voice channel when possible for your training meeting, if this has been mentioned by your interviewer.')
|
||||
->line('<br />')
|
||||
->line('Good luck and welcome aboard!')
|
||||
->action('Sign in', url(route('login')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
|
||||
$url = route('showSingleProfile', ['user' => $notifiable->id]);
|
||||
$roles = implode(', ', $notifiable->roles->pluck('name')->all());
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->content('A user has been approved on the team. Welcome aboard!')
|
||||
->attachment(function($attachment) use ($notifiable, $url, $roles){
|
||||
$attachment->title('New staff member')
|
||||
->fields([
|
||||
'Name' => $notifiable->name,
|
||||
'Email' => $notifiable->email,
|
||||
'Roles' => $roles
|
||||
])
|
||||
->action('View profile', $url);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
85
app/Notifications/ApplicationDenied.php
Normal file
85
app/Notifications/ApplicationDenied.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use App\Application;
|
||||
|
||||
class ApplicationDenied extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
|
||||
public $application;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail', 'slack'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - ' . $this->application->response->vacancy->vacancyName . ' application denied')
|
||||
->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])))
|
||||
->line('Better luck next time!');
|
||||
}
|
||||
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$notifiableName = $notifiable->name;
|
||||
|
||||
return (new SlackMessage)
|
||||
->error()
|
||||
->content('An application has just been denied.')
|
||||
->attachment(function($attachment) use ($notifiableName){
|
||||
$attachment->title('Application denied!')
|
||||
->content($notifiableName . '\'s application has just been denied. They can try again in 30 days.');
|
||||
});
|
||||
|
||||
}
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
64
app/Notifications/ApplicationMoved.php
Normal file
64
app/Notifications/ApplicationMoved.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ApplicationMoved extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - Application Updated')
|
||||
->line('Your most recent application has been moved up a stage.')
|
||||
->line('This means our team has reviewed it and an interview will be scheduled ASAP.')
|
||||
->action('Sign in', url(route('login')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
64
app/Notifications/AppointmentFinished.php
Normal file
64
app/Notifications/AppointmentFinished.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class AppointmentFinished extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - Appointment completed')
|
||||
->line('Your appointment has been marked as completed!')
|
||||
->line('Please allow an additional day for your application to be fully processed.')
|
||||
->action('View applications', url(route('showUserApps')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
71
app/Notifications/AppointmentScheduled.php
Normal file
71
app/Notifications/AppointmentScheduled.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
use App\Appointment;
|
||||
|
||||
class AppointmentScheduled extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
|
||||
protected $appointment;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Appointment $appointment)
|
||||
{
|
||||
$this->appointment = $appointment;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - Interview scheduled')
|
||||
->line('A voice interview has been scheduled for you @ ' . $this->appointment->appointmentDate . '.')
|
||||
->line('With the following details: ' . $this->appointment->appointmentDescription)
|
||||
->line('This meeting will take place @ ' . $this->appointment->appointmentLocation . '. You will receive an email soon with details on how to join this meeting.')
|
||||
->line('You are expected to show up at least 5 minutes before the scheduled date.')
|
||||
->action('Sign in', url(route('login')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
64
app/Notifications/ChangedPassword.php
Normal file
64
app/Notifications/ChangedPassword.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ChangedPassword extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - Account password changed')
|
||||
->line('The password for the account registered to this email address has just been changed.')
|
||||
->line('If this was not you, please contact an administrator immediately.')
|
||||
->action('Sign in', url(route('login')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
63
app/Notifications/EmailChanged.php
Normal file
63
app/Notifications/EmailChanged.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class EmailChanged extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - Email address changed')
|
||||
->line('The email address for your account has just been updated, either by you or an administrator.')
|
||||
->action('Sign in', url(route('login')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
98
app/Notifications/NewApplicant.php
Normal file
98
app/Notifications/NewApplicant.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use App\Application;
|
||||
use App\Vacancy;
|
||||
|
||||
class NewApplicant extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
|
||||
protected $application;
|
||||
|
||||
|
||||
protected $vacancy;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Application $application, Vacancy $vacancy)
|
||||
{
|
||||
$this->application = $application;
|
||||
$this->vacancy = $vacancy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['slack'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->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])))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
|
||||
$vacancyDetails = [];
|
||||
$vacancyDetails['name'] = $this->vacancy->vacancyName;
|
||||
$vacancyDetails['slots'] = $this->vacancy->vacancyCount;
|
||||
|
||||
$url = route('showUserApp', ['id' => $this->application->id]);
|
||||
$applicant = $this->application->user->name;
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->content('Notice: New application coming through. Please review as soon as possible.')
|
||||
->attachment(function($attachment) use ($vacancyDetails, $url, $applicant){
|
||||
$attachment->title('Application details')
|
||||
->fields([
|
||||
'Applied for' => $vacancyDetails['name'],
|
||||
'Avaiable positions' => $vacancyDetails['slots'],
|
||||
'Applicant' => $applicant
|
||||
])
|
||||
->action('Review application', $url);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
69
app/Notifications/NewComment.php
Normal file
69
app/Notifications/NewComment.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use App\Comment;
|
||||
use App\Application;
|
||||
|
||||
class NewComment extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
|
||||
protected $application;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Comment $comment, Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->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])))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
100
app/Notifications/NewUser.php
Normal file
100
app/Notifications/NewUser.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
|
||||
use App\User;
|
||||
use App\Facades\UUID;
|
||||
|
||||
class NewUser extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ($notifiable->isStaffMember())
|
||||
? ['slack', 'mail']
|
||||
: ['mail'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - New user')
|
||||
->line($this->user->name . ' has just registered to our site.')
|
||||
->line('You are receiving this email because you opted to receive new user notifications.')
|
||||
->action('View profile', url(route('showSingleProfile', ['user' => $this->user->id])))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$user = [];
|
||||
|
||||
$user['name'] = $this->user->name;
|
||||
$user['email'] = $this->user->email;
|
||||
$user['username'] = UUID::toUsername($this->user->uuid);
|
||||
|
||||
$date = \Carbon\Carbon::parse($this->user->created_at);
|
||||
$user['created_at'] = $date->englishMonth . ' ' . $date->day . ' ' . $date->year;
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->content('A new user has signed up!')
|
||||
->attachment(function($attachment) use ($user){
|
||||
|
||||
$attachment->title('User details')
|
||||
->fields([
|
||||
'Email address' => $user['email'],
|
||||
'Name' => $user['name'],
|
||||
'Minecraft Username' => $user['username'],
|
||||
'Registration date' => $user['created_at']
|
||||
]);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
71
app/Notifications/UserBanned.php
Normal file
71
app/Notifications/UserBanned.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
use App\User;
|
||||
use App\Ban;
|
||||
|
||||
class UserBanned extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
protected $user;
|
||||
|
||||
protected $ban;
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, Ban $ban)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->ban = $ban;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail']; // slack
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->line('Hello, ')
|
||||
->line('Moderators have just banned user ' . $this->user->name . ' for ' . $this->ban->reason)
|
||||
->line('This ban will remain in effect until ' . $this->ban->bannedUntil . '.')
|
||||
->action('View profile', url(route('showSingleProfile', ['user' => $this->user->id])))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
68
app/Notifications/VacancyClosed.php
Normal file
68
app/Notifications/VacancyClosed.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
use App\Vacancy;
|
||||
|
||||
class VacancyClosed extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
protected $vacancy;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Vacancy $vacancy)
|
||||
{
|
||||
$this->vacancy = $vacancy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||
->subject(config('app.name') . ' - Vacancy Closed')
|
||||
->line('The vacancy ' . $this->vacancy->vacancyName . ', with ' . $this->vacancy->vacancyCount . ' remaining slots, has just been closed.')
|
||||
->line('Please be aware that this position may be deleted/reopened any time.')
|
||||
->action('View positions', url(route('showPositions')))
|
||||
->line('Thank you!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
116
app/Observers/UserObserver.php
Normal file
116
app/Observers/UserObserver.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Profile;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UserObserver
|
||||
{
|
||||
/**
|
||||
* Handle the user "created" event.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function created(User $user)
|
||||
{
|
||||
Profile::create([
|
||||
|
||||
'profileShortBio' => 'Write a one-liner about you here!',
|
||||
'profileAboutMe' => 'Tell us a bit about you.',
|
||||
'socialLinks' => '{}',
|
||||
'userID' => $user->id
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user "updated" event.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function updated(User $user)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function deleting(User $user)
|
||||
{
|
||||
$user->profile()->delete();
|
||||
Log::debug('Referential integrity cleanup: Deleted profile!');
|
||||
$applications = $user->applications;
|
||||
|
||||
if (!$applications->isEmpty())
|
||||
{
|
||||
Log::debug('RIC: Now trying to delete applications and responses...');
|
||||
foreach($applications as $application)
|
||||
{
|
||||
$application->response()->delete();
|
||||
$votes = $application->votes;
|
||||
|
||||
foreach ($votes as $vote)
|
||||
{
|
||||
Log::debug('RIC: Deleting and detaching vote ' . $vote->id);
|
||||
$vote->application()->detach($application->id);
|
||||
$vote->delete();
|
||||
}
|
||||
|
||||
if (!is_null($application->appointment))
|
||||
{
|
||||
Log::debug('RIC: Deleting appointment!');
|
||||
$application->appointment()->delete();
|
||||
}
|
||||
|
||||
if (!$application->comments->isEmpty())
|
||||
{
|
||||
Log::debug('RIC: Deleting comments!');
|
||||
foreach($application->comments as $comment)
|
||||
{
|
||||
$comment->delete();
|
||||
}
|
||||
}
|
||||
Log::debug('RIC: Deleting application ' . $application->id);
|
||||
$application->delete();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Log::debug('RIC: Cleanup done!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user "deleted" event.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function deleted(User $user)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user "restored" event.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function restored(User $user)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user "force deleted" event.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function forceDeleted(User $user)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
33
app/Policies/ApplicationPolicy.php
Normal file
33
app/Policies/ApplicationPolicy.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Application;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
use App\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class ApplicationPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Create a new policy instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function view(User $user, Application $application)
|
||||
{
|
||||
if ($user->is($application->user) && $user->can('applications.view.own') || $user->can('applications.view.all'))
|
||||
{
|
||||
return Response::allow();
|
||||
}
|
||||
|
||||
return Response::deny('You are not authorised to view this application');
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Profile;
|
||||
use App\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
@ -16,6 +17,11 @@ class ProfilePolicy
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
public function edit(User $user, Profile $profile)
|
||||
{
|
||||
return $user->is($profile->user);
|
||||
}
|
||||
}
|
||||
|
41
app/Policies/UserPolicy.php
Normal file
41
app/Policies/UserPolicy.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class UserPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Create a new policy instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function edit(User $authUser, User $user)
|
||||
{
|
||||
return $authUser->is($user) || $authUser->hasRole('admin');
|
||||
}
|
||||
|
||||
public function viewStaff(User $user)
|
||||
{
|
||||
return $user->can('admin.stafflist');
|
||||
}
|
||||
|
||||
public function viewPlayers(User $user)
|
||||
{
|
||||
return $user->can('admin.userlist');
|
||||
}
|
||||
|
||||
public function terminate(User $authUser)
|
||||
{
|
||||
return $authUser->hasRole('admin');
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Observers\UserObserver;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
@ -25,5 +27,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
public function boot()
|
||||
{
|
||||
Schema::defaultStringLength(191);
|
||||
User::observe(UserObserver::class);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Http\Controllers\ProfileController;
|
||||
use App\Policies\ProfilePolicy;
|
||||
use App\Policies\UserPolicy;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
@ -14,6 +18,9 @@ class AuthServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Model' => 'App\Policies\ModelPolicy',
|
||||
'App\Application' => 'App\Policies\ApplicationPolicy',
|
||||
ProfileController::class => ProfilePolicy::class,
|
||||
User::class => UserPolicy::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
],
|
||||
'App\Events\ApplicationDeniedEvent' => [
|
||||
'App\Listeners\DenyUser'
|
||||
],
|
||||
'App\Events\UserBannedEvent' => [
|
||||
'App\Listeners\OnUserBanned'
|
||||
]
|
||||
];
|
||||
|
||||
|
33
app/Providers/IPInfoProvider.php
Normal file
33
app/Providers/IPInfoProvider.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App;
|
||||
|
||||
class IPInfoProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
App::bind('ipInformationFacade', function(){
|
||||
|
||||
return new App\CustomFacades\IP();
|
||||
|
||||
});
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
|
||||
Route::model('user', \App\User::class);
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
|
33
app/Providers/UUIDConversionProvider.php
Normal file
33
app/Providers/UUIDConversionProvider.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App;
|
||||
|
||||
class UUIDConversionProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
App::bind('uuidConversionFacade', function(){
|
||||
|
||||
return new App\UUID\UUID();
|
||||
|
||||
});
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ class Response extends Model
|
||||
'responseData'
|
||||
];
|
||||
|
||||
|
||||
public function form()
|
||||
{
|
||||
return $this->hasOne('App\Form', 'id', 'responseFormID');
|
||||
|
53
app/UUID/UUID.php
Normal file
53
app/UUID/UUID.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace App\UUID;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UUID
|
||||
{
|
||||
|
||||
// Caching would not be needed here since this method won't be used in pages that loop over a collection of usernames.
|
||||
public function toUUID($username)
|
||||
{
|
||||
if (is_null($username))
|
||||
{
|
||||
throw new \LogicException('Argument username for ' . __METHOD__ . ' cannot be null!');
|
||||
}
|
||||
|
||||
$response = json_decode(Http::post(config('general.urls.mojang.api') . '/profiles/minecraft', [
|
||||
$username
|
||||
])->body(), true);
|
||||
|
||||
return $response[0]['id'];
|
||||
}
|
||||
|
||||
// Note: Caching could simply be assigning the username to it's UUID, however, to make this work, we'd need to loop over all cache items, which would be slighly ineffective
|
||||
public function toUsername($uuid)
|
||||
{
|
||||
|
||||
if (is_null($uuid))
|
||||
{
|
||||
throw new \LogicException('Argument uuid for ' . __METHOD__ . ' cannot be null!');
|
||||
}
|
||||
|
||||
$shortUUID = substr($uuid, 0, 8);
|
||||
$username = Cache::remember('uuid_' . $shortUUID, now()->addDays(30), function() use ($shortUUID, $uuid) {
|
||||
|
||||
$response = json_decode(Http::get(config('general.urls.mojang.session') . '/session/minecraft/profile/' . $uuid)->body(), true);
|
||||
|
||||
Log::debug('Caching ' . $shortUUID . 'for thirty days');
|
||||
return $response['name'];
|
||||
|
||||
});
|
||||
|
||||
return $username;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
34
app/User.php
34
app/User.php
@ -5,10 +5,13 @@ namespace App;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use Notifiable;
|
||||
use HasRoles;
|
||||
//use MustVerifyEmail;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@ -37,6 +40,8 @@ class User extends Authenticatable
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
|
||||
//
|
||||
public function applications()
|
||||
{
|
||||
return $this->hasMany('App\Application', 'applicantUserID', 'id');
|
||||
@ -52,4 +57,33 @@ class User extends Authenticatable
|
||||
return $this->hasOne('App\Profile', 'userID', 'id');
|
||||
}
|
||||
|
||||
public function bans()
|
||||
{
|
||||
return $this->hasOne('App\Ban', 'userID', 'id');
|
||||
}
|
||||
|
||||
public function comments()
|
||||
{
|
||||
return $this->hasMany('App\Comment', 'authorID', 'id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function isBanned()
|
||||
{
|
||||
return !$this->bans()->get()->isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public function isStaffMember()
|
||||
{
|
||||
return $this->hasAnyRole('reviewer', 'admin', 'hiringManager');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function routeNotificationForSlack($notification)
|
||||
{
|
||||
return config('slack.webhook.integrationURL');
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,18 @@
|
||||
"require": {
|
||||
"php": "^7.2.5",
|
||||
"ext-json": "*",
|
||||
"arcanedev/log-viewer": "^7.0",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"fideloper/proxy": "^4.2",
|
||||
"fruitcake/laravel-cors": "^1.0",
|
||||
"guzzlehttp/guzzle": "^6.5",
|
||||
"jeroennoten/laravel-adminlte": "^3.2",
|
||||
"laravel/framework": "^7.0",
|
||||
"laravel/slack-notification-channel": "^2.0",
|
||||
"laravel/tinker": "^2.0",
|
||||
"laravel/ui": "^2.0",
|
||||
"sentry/sentry-laravel": "1.7.1"
|
||||
"sentry/sentry-laravel": "1.7.1",
|
||||
"spatie/laravel-permission": "^3.13"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.3",
|
||||
|
1221
composer.lock
generated
1221
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -45,12 +45,12 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'logo' => '<b>Admin</b>LTE',
|
||||
'logo_img' => 'vendor/adminlte/dist/img/AdminLTELogo.png',
|
||||
'logo' => 'RaspberryNet Staff',
|
||||
'logo_img' => 'https://www.raspberrypi.org/app/uploads/2020/05/Raspberry-Pi-OS-downloads-image-150x150-1.png',
|
||||
'logo_img_class' => 'brand-image img-circle elevation-3',
|
||||
'logo_img_xl' => null,
|
||||
'logo_img_xl_class' => 'brand-image-xs',
|
||||
'logo_img_alt' => 'AdminLTE',
|
||||
'logo_img_alt' => 'Raspberry Network Staff Temporary Logo',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -208,10 +208,14 @@ return [
|
||||
*/
|
||||
|
||||
'menu' => [
|
||||
'Applications',
|
||||
[
|
||||
'header' => 'Applications',
|
||||
'can' => 'applications.view.own'
|
||||
],
|
||||
[
|
||||
'text' => 'My Applications',
|
||||
'icon' => 'fas fa-fw fa-list-ul',
|
||||
'can' => 'applications.view.own',
|
||||
'submenu' => [
|
||||
[
|
||||
'text' => 'Current Applications',
|
||||
@ -232,36 +236,54 @@ return [
|
||||
'icon' => 'fas fa-user-circle',
|
||||
'url' => '/profile/settings/account'
|
||||
],
|
||||
'Application Management',
|
||||
[
|
||||
'header' => 'Application Management',
|
||||
'can' => ['applications.view.all', 'applications.vote']
|
||||
],
|
||||
[
|
||||
'text' => 'Outstanding Applications',
|
||||
'url' => '/applications/staff/outstanding',
|
||||
'icon' => 'far fa-folder-open'
|
||||
'icon' => 'far fa-folder-open',
|
||||
'can' => 'applications.view.all'
|
||||
],
|
||||
[
|
||||
'text' => 'Interview Queue',
|
||||
'url' => '/applications/staff/pending-interview',
|
||||
'icon' => 'fas fa-fw fa-microphone-alt'
|
||||
'icon' => 'fas fa-fw fa-microphone-alt',
|
||||
'can' => 'applications.view.all'
|
||||
],
|
||||
[
|
||||
'text' => 'Peer Approval Queue',
|
||||
'url' => '/applications/staff/peer-review',
|
||||
'icon' => 'fas fa-fw fa-search'
|
||||
'icon' => 'fas fa-fw fa-search',
|
||||
'can' => 'applications.view.all'
|
||||
],
|
||||
[
|
||||
'header' => 'Administration',
|
||||
'can' => [ // may need to be modified
|
||||
'admin.hiring.*',
|
||||
'admin.userlist',
|
||||
'admin.stafflist',
|
||||
'admin.hiring.*',
|
||||
'admin.notificationsettings.*'
|
||||
]
|
||||
],
|
||||
'Administration',
|
||||
[
|
||||
'text' => 'Staff Members',
|
||||
'icon' => 'fas fa-fw fa-users',
|
||||
'url' => '/hr/staff-members'
|
||||
'url' => '/hr/staff-members',
|
||||
'can' => 'admin.stafflist'
|
||||
],
|
||||
[ // players who haven't been promoted yet
|
||||
'text' => 'Registered Players',
|
||||
'icon' => 'fas fa-fw fa-user-friends',
|
||||
'url' => '/hr/players'
|
||||
'url' => '/hr/players',
|
||||
'can' => 'admin.userlist'
|
||||
],
|
||||
[
|
||||
'text' => 'Hiring Management',
|
||||
'icon' => 'far fa-calendar-plus',
|
||||
'can' => 'admin.hiring.*',
|
||||
'submenu' => [
|
||||
[
|
||||
'text' => 'Open Positions',
|
||||
@ -289,23 +311,27 @@ return [
|
||||
[
|
||||
'text' => 'App Settings',
|
||||
'icon' => 'fas fa-fw fa-cog',
|
||||
'can' => 'admin.notificationsettings',
|
||||
'submenu' => [
|
||||
[
|
||||
'text' => 'Global Notification Settings',
|
||||
'icon' => 'far fa-bell',
|
||||
'url' => '/admin/notifications'
|
||||
'url' => '/admin/notifications',
|
||||
'can' => 'admin.notificationsettings.edit'
|
||||
],
|
||||
[
|
||||
'text' => 'Developer Tools',
|
||||
'icon' => 'fas fa-code',
|
||||
'url' => '/admin/devtools'
|
||||
]
|
||||
'url' => '/admin/devtools',
|
||||
'can' => 'admin.developertools.use'
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'text' => 'Activity Logs',
|
||||
'url' => '/admin/logs',
|
||||
'icon' => 'fas fa-clipboard-list'
|
||||
'text' => 'System Logs',
|
||||
'url' => '/admin/maintenance/system-logs',
|
||||
'icon' => 'fas fa-clipboard-list',
|
||||
'can' => 'admin.maintenance.logs.view'
|
||||
]
|
||||
],
|
||||
|
||||
|
@ -171,6 +171,8 @@ return [
|
||||
*/
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\AuthServiceProvider::class,
|
||||
App\Providers\UUIDConversionProvider::class,
|
||||
App\Providers\IPInfoProvider::class,
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
@ -227,6 +229,8 @@ return [
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
'UUID' => App\Facades\UUID::class,
|
||||
'IP' => App\Facades\IP::class
|
||||
|
||||
],
|
||||
|
||||
|
@ -8,9 +8,20 @@ return [
|
||||
'mojang' => [
|
||||
|
||||
'statuscheck' => env('MOJANG_STATUS_URL') ?? 'https://status.mojang.com/check',
|
||||
'api' => env('MOJANG_API_URL') ?? ' https://api.mojang.com'
|
||||
'api' => env('MOJANG_API_URL') ?? ' https://api.mojang.com',
|
||||
'session' => env('MOJANG_SESSIONAPI_URL') ?? 'https://sessionserver.mojang.com'
|
||||
|
||||
],
|
||||
'ipapi' => [
|
||||
'ipcheck' => env('IPGEO_API_URL') ?? 'https://api.ipgeolocation.io/ipgeo'
|
||||
]
|
||||
],
|
||||
'keys' => [
|
||||
|
||||
'ipapi' => [
|
||||
'apikey' => env('IPGEO_API_KEY')
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
];
|
||||
|
141
config/log-viewer.php
Normal file
141
config/log-viewer.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
use Arcanedev\LogViewer\Contracts\Utilities\Filesystem;
|
||||
|
||||
return [
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Log files storage path
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'storage-path' => storage_path('logs'),
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Log files pattern
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'pattern' => [
|
||||
'prefix' => Filesystem::PATTERN_PREFIX, // 'laravel-'
|
||||
'date' => Filesystem::PATTERN_DATE, // '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
|
||||
'extension' => Filesystem::PATTERN_EXTENSION, // '.log'
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Locale
|
||||
| -----------------------------------------------------------------
|
||||
| Supported locales :
|
||||
| 'auto', 'ar', 'bg', 'de', 'en', 'es', 'et', 'fa', 'fr', 'hu', 'hy', 'id', 'it', 'ja', 'ko', 'nl',
|
||||
| 'pl', 'pt-BR', 'ro', 'ru', 'sv', 'th', 'tr', 'zh-TW', 'zh'
|
||||
*/
|
||||
|
||||
'locale' => 'auto',
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Theme
|
||||
| -----------------------------------------------------------------
|
||||
| Supported themes :
|
||||
| 'bootstrap-3', 'bootstrap-4'
|
||||
| Make your own theme by adding a folder to the views directory and specifying it here.
|
||||
*/
|
||||
|
||||
'theme' => 'bootstrap-4',
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Route settings
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'route' => [
|
||||
'enabled' => true,
|
||||
|
||||
'attributes' => [
|
||||
'prefix' => 'admin/maintenance/system-logs',
|
||||
|
||||
'middleware' => env('ARCANEDEV_LOGVIEWER_MIDDLEWARE') ? explode(',', env('ARCANEDEV_LOGVIEWER_MIDDLEWARE')) : null,
|
||||
],
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Log entries per page
|
||||
| -----------------------------------------------------------------
|
||||
| This defines how many logs & entries are displayed per page.
|
||||
*/
|
||||
|
||||
'per-page' => 30,
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Download settings
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'download' => [
|
||||
'prefix' => 'rpnetlog-',
|
||||
|
||||
'extension' => 'log',
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Menu settings
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'menu' => [
|
||||
'filter-route' => 'log-viewer::logs.filter',
|
||||
|
||||
'icons-enabled' => true,
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Icons
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'icons' => [
|
||||
/**
|
||||
* Font awesome >= 4.3
|
||||
* http://fontawesome.io/icons/
|
||||
*/
|
||||
'all' => 'fa fa-fw fa-list', // http://fontawesome.io/icon/list/
|
||||
'emergency' => 'fa fa-fw fa-bug', // http://fontawesome.io/icon/bug/
|
||||
'alert' => 'fa fa-fw fa-bullhorn', // http://fontawesome.io/icon/bullhorn/
|
||||
'critical' => 'fa fa-fw fa-heartbeat', // http://fontawesome.io/icon/heartbeat/
|
||||
'error' => 'fa fa-fw fa-times-circle', // http://fontawesome.io/icon/times-circle/
|
||||
'warning' => 'fa fa-fw fa-exclamation-triangle', // http://fontawesome.io/icon/exclamation-triangle/
|
||||
'notice' => 'fa fa-fw fa-exclamation-circle', // http://fontawesome.io/icon/exclamation-circle/
|
||||
'info' => 'fa fa-fw fa-info-circle', // http://fontawesome.io/icon/info-circle/
|
||||
'debug' => 'fa fa-fw fa-life-ring', // http://fontawesome.io/icon/life-ring/
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Colors
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'colors' => [
|
||||
'levels' => [
|
||||
'empty' => '#D1D1D1',
|
||||
'all' => '#8A8A8A',
|
||||
'emergency' => '#B71C1C',
|
||||
'alert' => '#D32F2F',
|
||||
'critical' => '#F44336',
|
||||
'error' => '#FF5722',
|
||||
'warning' => '#FF9100',
|
||||
'notice' => '#4CAF50',
|
||||
'info' => '#1976D2',
|
||||
'debug' => '#90CAF9',
|
||||
],
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Strings to highlight in stack trace
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'highlight' => [
|
||||
'^#\d+',
|
||||
'^Stack trace:',
|
||||
],
|
||||
|
||||
];
|
12
config/notification.php
Normal file
12
config/notification.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'sender' => [
|
||||
|
||||
'address' => 'teams@spacejewel-hosting.com',
|
||||
'name' => 'RaspberryNet Teams'
|
||||
|
||||
]
|
||||
|
||||
];
|
143
config/permission.php
Normal file
143
config/permission.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'models' => [
|
||||
|
||||
/*
|
||||
* When using the "HasPermissions" trait from this package, we need to know which
|
||||
* Eloquent model should be used to retrieve your permissions. Of course, it
|
||||
* is often just the "Permission" model but you may use whatever you like.
|
||||
*
|
||||
* The model you want to use as a Permission model needs to implement the
|
||||
* `Spatie\Permission\Contracts\Permission` contract.
|
||||
*/
|
||||
|
||||
'permission' => Spatie\Permission\Models\Permission::class,
|
||||
|
||||
/*
|
||||
* When using the "HasRoles" trait from this package, we need to know which
|
||||
* Eloquent model should be used to retrieve your roles. Of course, it
|
||||
* is often just the "Role" model but you may use whatever you like.
|
||||
*
|
||||
* The model you want to use as a Role model needs to implement the
|
||||
* `Spatie\Permission\Contracts\Role` contract.
|
||||
*/
|
||||
|
||||
'role' => Spatie\Permission\Models\Role::class,
|
||||
|
||||
],
|
||||
|
||||
'table_names' => [
|
||||
|
||||
/*
|
||||
* When using the "HasRoles" trait from this package, we need to know which
|
||||
* table should be used to retrieve your roles. We have chosen a basic
|
||||
* default value but you may easily change it to any table you like.
|
||||
*/
|
||||
|
||||
'roles' => 'roles',
|
||||
|
||||
/*
|
||||
* When using the "HasPermissions" trait from this package, we need to know which
|
||||
* table should be used to retrieve your permissions. We have chosen a basic
|
||||
* default value but you may easily change it to any table you like.
|
||||
*/
|
||||
|
||||
'permissions' => 'permissions',
|
||||
|
||||
/*
|
||||
* When using the "HasPermissions" trait from this package, we need to know which
|
||||
* table should be used to retrieve your models permissions. We have chosen a
|
||||
* basic default value but you may easily change it to any table you like.
|
||||
*/
|
||||
|
||||
'model_has_permissions' => 'model_has_permissions',
|
||||
|
||||
/*
|
||||
* When using the "HasRoles" trait from this package, we need to know which
|
||||
* table should be used to retrieve your models roles. We have chosen a
|
||||
* basic default value but you may easily change it to any table you like.
|
||||
*/
|
||||
|
||||
'model_has_roles' => 'model_has_roles',
|
||||
|
||||
/*
|
||||
* When using the "HasRoles" trait from this package, we need to know which
|
||||
* table should be used to retrieve your roles permissions. We have chosen a
|
||||
* basic default value but you may easily change it to any table you like.
|
||||
*/
|
||||
|
||||
'role_has_permissions' => 'role_has_permissions',
|
||||
],
|
||||
|
||||
'column_names' => [
|
||||
|
||||
/*
|
||||
* Change this if you want to name the related model primary key other than
|
||||
* `model_id`.
|
||||
*
|
||||
* For example, this would be nice if your primary keys are all UUIDs. In
|
||||
* that case, name this `model_uuid`.
|
||||
*/
|
||||
|
||||
'model_morph_key' => 'model_id',
|
||||
],
|
||||
|
||||
/*
|
||||
* When set to true, the required permission names are added to the exception
|
||||
* message. This could be considered an information leak in some contexts, so
|
||||
* the default setting is false here for optimum safety.
|
||||
*/
|
||||
|
||||
'display_permission_in_exception' => false,
|
||||
|
||||
/*
|
||||
* When set to true, the required role names are added to the exception
|
||||
* message. This could be considered an information leak in some contexts, so
|
||||
* the default setting is false here for optimum safety.
|
||||
*/
|
||||
|
||||
'display_role_in_exception' => false,
|
||||
|
||||
/*
|
||||
* By default wildcard permission lookups are disabled.
|
||||
*/
|
||||
|
||||
'enable_wildcard_permission' => true,
|
||||
|
||||
'cache' => [
|
||||
|
||||
/*
|
||||
* By default all permissions are cached for 24 hours to speed up performance.
|
||||
* When permissions or roles are updated the cache is flushed automatically.
|
||||
*/
|
||||
|
||||
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
|
||||
|
||||
/*
|
||||
* The cache key used to store all permissions.
|
||||
*/
|
||||
|
||||
'key' => 'spatie.permission.cache',
|
||||
|
||||
/*
|
||||
* When checking for a permission against a model by passing a Permission
|
||||
* instance to the check, this key determines what attribute on the
|
||||
* Permissions model is used to cache against.
|
||||
*
|
||||
* Ideally, this should match your preferred way of checking permissions, eg:
|
||||
* `$user->can('view-posts')` would be 'name'.
|
||||
*/
|
||||
|
||||
'model_key' => 'name',
|
||||
|
||||
/*
|
||||
* You may optionally indicate a specific cache driver to use for permission and
|
||||
* role caching using any of the `store` drivers listed in the cache.php config
|
||||
* file. Using 'default' here means to use the `default` set in cache.php.
|
||||
*/
|
||||
|
||||
'store' => 'default',
|
||||
],
|
||||
];
|
12
config/slack.php
Normal file
12
config/slack.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'webhook' => [
|
||||
|
||||
'integrationURL' => env('SLACK_INTEGRATION_WEBHOOK')
|
||||
|
||||
]
|
||||
|
||||
|
||||
];
|
@ -27,8 +27,7 @@ class CreateProfilesTable extends Migration
|
||||
|
||||
$table->foreign('userID')
|
||||
->references('id')
|
||||
->on('users')
|
||||
->onDelete('cascade');
|
||||
->on('users');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,10 @@ class CreateApplicationsTable extends Migration
|
||||
'DENIED'
|
||||
])->default('STAGE_SUBMITTED');
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('applicantUserID')
|
||||
->references('id')
|
||||
->on('users');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,9 @@ class CreateVotesTable extends Migration
|
||||
]);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('userID')->references('id')->on('users');
|
||||
$table->foreign('userID')
|
||||
->references('id')
|
||||
->on('users');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,10 @@ class CreateAppointmentsTable extends Migration
|
||||
$table->boolean('userAccepted')->default(false);
|
||||
$table->longText('meetingNotes')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('applicationID')
|
||||
->references('id')
|
||||
->on('applications');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,10 @@ class CreateVacanciesTable extends Migration
|
||||
$table->integer('vacancyCount')->default(3);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('vacancyFormID')->references('id')->on('forms');
|
||||
$table->foreign('vacancyFormID')
|
||||
->references('id')
|
||||
->on('forms');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@ class CreateStaffProfilesTable extends Migration
|
||||
$table->dateTime('resignationDate')->nullable();
|
||||
$table->text('memberNotes')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('userID')
|
||||
->references('id')
|
||||
->on('users');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,12 @@ class CreateResponsesTable extends Migration
|
||||
$table->bigInteger('responseFormID')->unsigned();
|
||||
$table->longText('responseData');
|
||||
$table->timestamps();
|
||||
|
||||
// A better way would be to link responses directly to vacancies, that subsquently have a form
|
||||
$table->foreign('responseFormID')
|
||||
->references('id')
|
||||
->on('forms');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,5 @@ class ChangeFormStructureLength extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('forms', function (Blueprint $schema){
|
||||
$schema->string('formStructure')->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreatePermissionTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$tableNames = config('permission.table_names');
|
||||
$columnNames = config('permission.column_names');
|
||||
|
||||
if (empty($tableNames)) {
|
||||
throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||
}
|
||||
|
||||
Schema::create($tableNames['permissions'], function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('name');
|
||||
$table->string('guard_name');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create($tableNames['roles'], function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('name');
|
||||
$table->string('guard_name');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames) {
|
||||
$table->unsignedBigInteger('permission_id');
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
|
||||
|
||||
$table->foreign('permission_id')
|
||||
->references('id')
|
||||
->on($tableNames['permissions'])
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->primary(['permission_id', $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames) {
|
||||
$table->unsignedBigInteger('role_id');
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
|
||||
|
||||
$table->foreign('role_id')
|
||||
->references('id')
|
||||
->on($tableNames['roles'])
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->primary(['role_id', $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
});
|
||||
|
||||
Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) {
|
||||
$table->unsignedBigInteger('permission_id');
|
||||
$table->unsignedBigInteger('role_id');
|
||||
|
||||
$table->foreign('permission_id')
|
||||
->references('id')
|
||||
->on($tableNames['permissions'])
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->foreign('role_id')
|
||||
->references('id')
|
||||
->on($tableNames['roles'])
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->primary(['permission_id', 'role_id'], 'role_has_permissions_permission_id_role_id_primary');
|
||||
});
|
||||
|
||||
app('cache')
|
||||
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
|
||||
->forget(config('permission.cache.key'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$tableNames = config('permission.table_names');
|
||||
|
||||
if (empty($tableNames)) {
|
||||
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
|
||||
}
|
||||
|
||||
Schema::drop($tableNames['role_has_permissions']);
|
||||
Schema::drop($tableNames['model_has_roles']);
|
||||
Schema::drop($tableNames['model_has_permissions']);
|
||||
Schema::drop($tableNames['roles']);
|
||||
Schema::drop($tableNames['permissions']);
|
||||
}
|
||||
}
|
41
database/migrations/2020_06_08_153602_create_bans_table.php
Normal file
41
database/migrations/2020_06_08_153602_create_bans_table.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateBansTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('bans', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->bigInteger('userID')->unsigned();
|
||||
$table->string('reason');
|
||||
$table->timestamp('bannedUntil')->nullable();
|
||||
$table->string('userAgent');
|
||||
$table->bigInteger('authorUserID');
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('userID')
|
||||
->references('id')
|
||||
->on('users');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('bans');
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCommentsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('comments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->bigInteger('authorID')->unsigned();
|
||||
$table->bigInteger('applicationID')->unsigned();
|
||||
$table->mediumText('text');
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('authorID')
|
||||
->references('id')
|
||||
->on('users');
|
||||
|
||||
$table->foreign('applicationID')
|
||||
->references('id')
|
||||
->on('applications');
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('comments');
|
||||
}
|
||||
}
|
36
database/migrations/2020_06_25_093708_create_jobs_table.php
Normal file
36
database/migrations/2020_06_25_093708_create_jobs_table.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateJobsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('jobs', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('queue')->index();
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('jobs');
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ class DatabaseSeeder extends Seeder
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// $this->call(UserSeeder::class);
|
||||
$this->call(PermissionSeeder::class);
|
||||
$this->call(UserSeeder::class);
|
||||
}
|
||||
}
|
||||
|
98
database/seeds/PermissionSeeder.php
Normal file
98
database/seeds/PermissionSeeder.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class PermissionSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
//
|
||||
$user = Role::create(
|
||||
[
|
||||
'name' => 'user'
|
||||
]
|
||||
);
|
||||
|
||||
$reviewer = Role::create(
|
||||
[
|
||||
'name' => 'reviewer'
|
||||
]
|
||||
);
|
||||
|
||||
$hiringManager = Role::create(
|
||||
[
|
||||
'name' => 'hiringManager'
|
||||
]
|
||||
);
|
||||
|
||||
$admin = Role::create([
|
||||
'name' => 'admin'
|
||||
]);
|
||||
|
||||
// Spatie wildcard permissions (same concept of MC permissions)
|
||||
|
||||
Permission::create(['name' => 'applications.submit']);
|
||||
Permission::create(['name' => 'applications.stages.deny']);
|
||||
Permission::create(['name' => 'applications.stages.approve']);
|
||||
Permission::create(['name' => 'applications.view.all']);
|
||||
Permission::create(['name' => 'applications.view.own']);
|
||||
Permission::create(['name' => 'applications.vote']);
|
||||
Permission::create(['name' => 'appointments.schedule']);
|
||||
Permission::create(['name' => 'appointments.schedule.edit']);
|
||||
Permission::create(['name' => 'appointments.schedule.cancel']);
|
||||
Permission::create(['name' => 'applications.*']);
|
||||
Permission::create(['name' => 'appointments.*']);
|
||||
|
||||
Permission::create(['name' => 'profiles.view.others']);
|
||||
Permission::create(['name' => 'profiles.edit.others']);
|
||||
|
||||
Permission::create(['name' => 'admin.userlist']);
|
||||
Permission::create(['name' => 'admin.stafflist']);
|
||||
Permission::create(['name' => 'admin.hiring.forms']);
|
||||
Permission::create(['name' => 'admin.hiring.formbuilder']);
|
||||
Permission::create(['name' => 'admin.hiring.vacancy']);
|
||||
Permission::create(['name' => 'admin.hiring.vacancy.edit,delete']);
|
||||
Permission::create(['name' => 'admin.notificationsettings']);
|
||||
Permission::create(['name' => 'admin.notificationsettings.edit']);
|
||||
Permission::create(['name' => 'admin.hiring.*']);
|
||||
Permission::create(['name' => 'admin.notificationsettings.*']);
|
||||
Permission::create(['name' => 'admin.maintenance.logs.view']);
|
||||
|
||||
|
||||
Permission::create(['name' => 'admin.developertools.use']);
|
||||
|
||||
$user->givePermissionTo([
|
||||
'applications.submit',
|
||||
'applications.view.own',
|
||||
'profiles.view.others'
|
||||
]);
|
||||
|
||||
// Able to view applications and vote on them once they reach the right stage, but not approve applications up to said stage
|
||||
$reviewer->givePermissionTo([
|
||||
'applications.view.all',
|
||||
'applications.vote'
|
||||
]);
|
||||
|
||||
$hiringManager->givePermissionTo('appointments.*', 'applications.*', 'admin.hiring.*');
|
||||
|
||||
$admin->givePermissionTo([
|
||||
'appointments.*',
|
||||
'admin.userlist',
|
||||
'admin.stafflist',
|
||||
'admin.hiring.*',
|
||||
'admin.notificationsettings.*',
|
||||
'profiles.view.others',
|
||||
'profiles.edit.others',
|
||||
'admin.maintenance.logs.view'
|
||||
]);
|
||||
}
|
||||
}
|
146
database/seeds/UserSeeder.php
Normal file
146
database/seeds/UserSeeder.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
use App\Profile;
|
||||
use App\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UserSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$staffUsers = [
|
||||
|
||||
[
|
||||
'uuid' => 'd2b321b56ff1445db9d7794701983cad',
|
||||
'name' => 'Robot 1',
|
||||
'email' => 'tester1@example.com',
|
||||
'username' => 'tester1',
|
||||
'originalIP' => '99.18.146.235',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => 'ab22b5da02644953ace969fce85c0819',
|
||||
'name' => 'Robot 2',
|
||||
'email' => 'tester2@example.com',
|
||||
'username' => 'tester2',
|
||||
'originalIP' => '141.239.229.53',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => 'df38e6bf762944d3a600ded59a693ad1',
|
||||
'name' => 'Robot 3',
|
||||
'email' => 'tester3@example.com',
|
||||
'username' => 'tester3',
|
||||
'originalIP' => '25.63.20.97',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => '689e446484824f6bad5064e3df0aaa96',
|
||||
'name' => 'Robot 4',
|
||||
'email' => 'tester4@example.com',
|
||||
'username' => 'tester4',
|
||||
'originalIP' => '220.105.223.142',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => '172391f917bf418ab1c40ebc041ed5ba',
|
||||
'name' => 'Robot 5',
|
||||
'email' => 'tester5@example.com',
|
||||
'username' => 'tester5',
|
||||
'originalIP' => '224.66.76.60',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => '371f34dcce2a4457bf385ab9417a2345',
|
||||
'name' => 'Robot 6',
|
||||
'email' => 'tester6@example.com',
|
||||
'username' => 'tester6',
|
||||
'originalIP' => '97.113.131.0',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => '89aa5222855542bebe7a7780248ef5f9',
|
||||
'name' => 'Robot 7',
|
||||
'email' => 'tester7@example.com',
|
||||
'username' => 'tester7',
|
||||
'originalIP' => '15.160.137.222',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
$regularUsers = [
|
||||
|
||||
[
|
||||
'uuid' => '20f69f47e72f463493b5b91d1c05452f',
|
||||
'name' => 'User 1',
|
||||
'email' => 'user1@example.com',
|
||||
'username' => 'user1',
|
||||
'originalIP' => '253.25.237.78',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => '5f900018241e4aaba7883f2d5c5c2357',
|
||||
'name' => 'User 2',
|
||||
'email' => 'user2@example.com',
|
||||
'username' => 'user2',
|
||||
'originalIP' => '82.92.156.176',
|
||||
'password' => Hash::make('password')
|
||||
],
|
||||
[
|
||||
'uuid' => 'ba9780c3270745c6840eaabe1bf8aa14',
|
||||
'name' => 'User 3',
|
||||
'email' => 'user3@example.com',
|
||||
'username' => 'user3',
|
||||
'originalIP' => '224.123.129.17',
|
||||
'password' => Hash::make('password')
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
foreach ($regularUsers as $regularUser)
|
||||
{
|
||||
$user = User::create($regularUser);
|
||||
Profile::create([
|
||||
'profileShortBio' => 'Random data ' . rand(0,1000),
|
||||
'profileAboutMe' => 'Random data ' . rand(0, 1000),
|
||||
'socialLinks' => "[]", // empty json set, not an array
|
||||
'avatarPreference' => 'gravatar',
|
||||
'userID' => $user->id
|
||||
]);
|
||||
}
|
||||
|
||||
foreach($staffUsers as $staffUser)
|
||||
{
|
||||
$user = User::create($staffUser);
|
||||
Profile::create([
|
||||
'profileShortBio' => 'Random data ' . rand(0,1000),
|
||||
'profileAboutMe' => 'Random data ' . rand(0, 1000),
|
||||
'socialLinks' => "[]",
|
||||
'avatarPreference' => 'gravatar',
|
||||
'userID' => $user->id
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
User::create([
|
||||
'uuid' => '6102256abd284dd7b68e4c96ef313734',
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@example.com',
|
||||
'username' => 'admin',
|
||||
'originalIP' => '192.168.1.2',
|
||||
'password' => Hash::make('password')
|
||||
]);
|
||||
|
||||
foreach (User::all() as $user)
|
||||
{
|
||||
$user->assignRole('reviewer', 'user');
|
||||
}
|
||||
}
|
||||
}
|
38
public/css/comments.css
vendored
Normal file
38
public/css/comments.css
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
blockquote {
|
||||
background: #f9f9f9;
|
||||
border-left: 10px solid #ccc;
|
||||
margin: 1.5em 10px;
|
||||
padding: 0.5em 10px;
|
||||
quotes: "\201C""\201D""\2018""\2019";
|
||||
}
|
||||
blockquote:before {
|
||||
color: #ccc;
|
||||
content: open-quote;
|
||||
font-size: 4em;
|
||||
line-height: 0.1em;
|
||||
margin-right: 0.25em;
|
||||
vertical-align: -0.4em;
|
||||
}
|
||||
blockquote p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.comment {
|
||||
border-radius: 30px;
|
||||
}
|
||||
|
||||
.comment-header {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.comment-footer {
|
||||
|
||||
border: none;
|
||||
|
||||
}
|
||||
|
||||
.commenter {
|
||||
font-size: large;
|
||||
color: darkgrey;
|
||||
font-weight: bold;
|
||||
}
|
3
public/css/picker.css
vendored
Normal file
3
public/css/picker.css
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.flatpickr-calendar.open {
|
||||
z-index: 10000;
|
||||
}
|
12223
public/js/app.js
vendored
12223
public/js/app.js
vendored
File diff suppressed because it is too large
Load Diff
30
resources/js/app.js
vendored
30
resources/js/app.js
vendored
@ -7,10 +7,6 @@
|
||||
require('chart.js');
|
||||
require('./bootstrap');
|
||||
|
||||
import { Calendar } from '@fullcalendar/core';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
import listPlugin from '@fullcalendar/list';
|
||||
import flatpickr from "flatpickr";
|
||||
|
||||
|
||||
@ -21,6 +17,32 @@ flatpickr("#appointmentDateTime", {
|
||||
static: false
|
||||
});
|
||||
|
||||
$("#banAccountTrigger").on("click", function(event){
|
||||
|
||||
$("#banAccountModal").modal('show');
|
||||
|
||||
});
|
||||
|
||||
$("#durationDropdown").dropdown();
|
||||
|
||||
$(".dropdown-menu a").on("click", function(e){
|
||||
|
||||
$(".duration-btn").text(this.innerHTML);
|
||||
$("#operator").val(this.innerHTML);
|
||||
|
||||
});
|
||||
|
||||
$("#banAccountButton").on("click", function(){
|
||||
$("#banAccountForm").submit();
|
||||
});
|
||||
|
||||
$("#comment").keyup(function(){
|
||||
$("#charcount").text($("#comment").val().length);
|
||||
});
|
||||
|
||||
$("#submitComment").on('click', function(){
|
||||
$("#newComment").submit();
|
||||
});
|
||||
|
||||
window.Vue = require('vue');
|
||||
|
||||
|
13
resources/lang/vendor/log-viewer/ar.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/ar.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "تاريخ",
|
||||
"The list of logs is empty!": "قائمة سجلات فارغة!",
|
||||
"All": "الجميع",
|
||||
"Emergency": "حالات الطوارئ",
|
||||
"Alert": "إنذار",
|
||||
"Critical": "حرج",
|
||||
"Error": "خطأ",
|
||||
"Warning": "تحذير",
|
||||
"Notice": "ملاحظة",
|
||||
"Info": "المعلومات",
|
||||
"Debug": "التصحيح"
|
||||
}
|
13
resources/lang/vendor/log-viewer/bg.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/bg.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Дата",
|
||||
"The list of logs is empty!": "Не са намерени логове!",
|
||||
"All": "Всички",
|
||||
"Emergency": "Emergency",
|
||||
"Alert": "Alert",
|
||||
"Critical": "Critical",
|
||||
"Error": "Error",
|
||||
"Warning": "Warning",
|
||||
"Notice": "Notice",
|
||||
"Info": "Info",
|
||||
"Debug": "Debug"
|
||||
}
|
13
resources/lang/vendor/log-viewer/de.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/de.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Datum",
|
||||
"The list of logs is empty!": "KeineLogDateiengefunden!",
|
||||
"All": "Alle",
|
||||
"Emergency": "Notfall",
|
||||
"Alert": "Alarm",
|
||||
"Critical": "Kritisch",
|
||||
"Error": "Fehler",
|
||||
"Warning": "Warnung",
|
||||
"Notice": "Hinweis",
|
||||
"Info": "Info",
|
||||
"Debug": "Debug"
|
||||
}
|
13
resources/lang/vendor/log-viewer/es.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/es.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Fecha",
|
||||
"The list of logs is empty!": "La lista del log está vacía!",
|
||||
"All": "Todos",
|
||||
"Emergency": "Emergencia",
|
||||
"Alert": "Alerta",
|
||||
"Critical": "Criticos",
|
||||
"Error": "Errores",
|
||||
"Warning": "Advertencia",
|
||||
"Notice": "Aviso",
|
||||
"Info": "Info",
|
||||
"Debug": "Debug"
|
||||
}
|
13
resources/lang/vendor/log-viewer/et.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/et.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Kuupäev",
|
||||
"The list of logs is empty!": "Logide nimekiri on tühi!",
|
||||
"All": "Kõik",
|
||||
"Emergency": "Erakorraline",
|
||||
"Alert": "Häire",
|
||||
"Critical": "Kriitiline",
|
||||
"Error": "Viga",
|
||||
"Warning": "Hoiatus",
|
||||
"Notice": "Teade",
|
||||
"Info": "Info",
|
||||
"Debug": "Silumine"
|
||||
}
|
13
resources/lang/vendor/log-viewer/fa.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/fa.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "تاریخ",
|
||||
"The list of logs is empty!": "چیزی برای نمایش وجود ندارد!",
|
||||
"All": "همه",
|
||||
"Emergency": "اورژانسی",
|
||||
"Alert": "اخطار",
|
||||
"Critical": "بحرانی",
|
||||
"Error": "خطا",
|
||||
"Warning": "هشدار",
|
||||
"Notice": "اعلان",
|
||||
"Info": "اطلاعات",
|
||||
"Debug": "دیباگ"
|
||||
}
|
13
resources/lang/vendor/log-viewer/fr.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/fr.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Date",
|
||||
"The list of logs is empty!": "La liste des logs est vide!",
|
||||
"All": "Tous",
|
||||
"Emergency": "Urgence",
|
||||
"Alert": "Alerte",
|
||||
"Critical": "Critique",
|
||||
"Error": "Erreur",
|
||||
"Warning": "Avertissement",
|
||||
"Notice": "Notice",
|
||||
"Info": "Info",
|
||||
"Debug": "Debug"
|
||||
}
|
13
resources/lang/vendor/log-viewer/hu.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/hu.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Dátum",
|
||||
"The list of logs is empty!": "A naplók listája üres!",
|
||||
"All": "Összes",
|
||||
"Emergency": "Vészhelyzet",
|
||||
"Alert": "Riasztás",
|
||||
"Critical": "Kritikus",
|
||||
"Error": "Hiba",
|
||||
"Warning": "Figyelmeztetés",
|
||||
"Notice": "Értesítés",
|
||||
"Info": "Információ",
|
||||
"Debug": "Hibakeresés"
|
||||
}
|
13
resources/lang/vendor/log-viewer/hy.json
vendored
Normal file
13
resources/lang/vendor/log-viewer/hy.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Date": "Ամսաթիվ",
|
||||
"The list of logs is empty!": "Լոգերի ցուցակը դատարկ է։",
|
||||
"All": "Բոլորը",
|
||||
"Emergency": "Վթարային",
|
||||
"Alert": "Նախազգուշացում",
|
||||
"Critical": "Կրիտիկական",
|
||||
"Error": "Սխալ",
|
||||
"Warning": "Նախազգուշացում",
|
||||
"Notice": "Ծանուցում",
|
||||
"Info": "Տեղեկատվություն",
|
||||
"Debug": "Կարգաբերում"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user