diff --git a/..env.swp b/..env.swp
new file mode 100644
index 0000000..61ad66a
Binary files /dev/null and b/..env.swp differ
diff --git a/.editorconfig b/.editorconfig
old mode 100644
new mode 100755
diff --git a/.env.example b/.env.example
old mode 100644
new mode 100755
index 2e9fddc..79807a8
--- a/.env.example
+++ b/.env.example
@@ -7,7 +7,15 @@ APP_LOGO="https://www.raspberrypi.org/app/uploads/2020/05/Raspberry-Pi-OS-downlo
APP_SITEHOMEPAGE=""
# This can be your main homepage, other than this site itself
-LOG_CHANNEL=stack
+# Forces ssl connections even if the environment is set to "local".
+# Void if env is production.
+NONPROD_FORCE_SECURE=false
+
+# Disables certain features for security purposes while running an open authentication system
+# Enable only for demonostration purposes
+DEMO_MODE=false
+
+LOG_CHANNEL=daily
DB_CONNECTION=mysql
DB_HOST=z
@@ -29,7 +37,7 @@ IPGEO_API_URL="https://api.ipgeolocation.io/ipgeo"
ARCANEDEV_LOGVIEWER_MIDDLEWARE=web,auth,can:admin.maintenance.logs.view
-RELEASE=staffmanagement@0.6.1
+RELEASE=0.6.2
SLACK_INTEGRATION_WEBHOOK=
diff --git a/.gitattributes b/.gitattributes
old mode 100644
new mode 100755
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
old mode 100644
new mode 100755
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
old mode 100644
new mode 100755
diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
diff --git a/.idea/hrm-mcserver.iml b/.idea/hrm-mcserver.iml
deleted file mode 100644
index bb20d72..0000000
--- a/.idea/hrm-mcserver.iml
+++ /dev/null
@@ -1,139 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/laravel-plugin.xml b/.idea/laravel-plugin.xml
old mode 100644
new mode 100755
diff --git a/.idea/misc.xml b/.idea/misc.xml
old mode 100644
new mode 100755
diff --git a/.idea/modules.xml b/.idea/modules.xml
old mode 100644
new mode 100755
index 1a22200..7ab5d51
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/php.xml b/.idea/php.xml
old mode 100644
new mode 100755
index afaedbf..f41ef1f
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -141,9 +141,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/.idea/phpunit.xml b/.idea/phpunit.xml
old mode 100644
new mode 100755
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
old mode 100644
new mode 100755
diff --git a/.phive/phars.xml b/.phive/phars.xml
old mode 100644
new mode 100755
diff --git a/.styleci.yml b/.styleci.yml
old mode 100644
new mode 100755
index 1db61d9..d534ee6
--- a/.styleci.yml
+++ b/.styleci.yml
@@ -1,13 +1,13 @@
-php:
- preset: laravel
- disabled:
- - unused_use
- finder:
- not-name:
- - index.php
- - server.php
-js:
- finder:
- not-name:
- - webpack.mix.js
-css: true
+risky: false
+version: 7
+preset: recommended
+finder:
+ exclude:
+ - "modules"
+ - "node_modules"
+ - "storage"
+ - "vendor"
+ name: "*.php"
+ not-name:
+ - "*.blade.php"
+ - "_ide_helper.php"
diff --git a/.vscode/launch.json b/.vscode/launch.json
old mode 100644
new mode 100755
index 612eaac..759926c
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,11 +4,15 @@
// 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
+ "port": 9000,
+ "ignore": [
+ "**/vendor/**/*.php"
+ ]
},
{
"name": "Launch currently open script",
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
old mode 100644
new mode 100755
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
old mode 100644
new mode 100755
diff --git a/LICENSE b/LICENSE
old mode 100644
new mode 100755
diff --git a/Procfile b/Procfile
old mode 100644
new mode 100755
diff --git a/SECURITY.md b/SECURITY.md
old mode 100644
new mode 100755
diff --git a/app/ApiKey.php b/app/ApiKey.php
new file mode 100644
index 0000000..0ed33ff
--- /dev/null
+++ b/app/ApiKey.php
@@ -0,0 +1,25 @@
+belongsTo('App\User', 'owner_user_id', 'id');
+ }
+}
diff --git a/app/Application.php b/app/Application.php
old mode 100644
new mode 100755
index f1066d8..5aa958a
--- a/app/Application.php
+++ b/app/Application.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -10,12 +29,14 @@ class Application extends Model
'applicantUserID',
'applicantFormResponseID',
- 'applicationStatus'
+ 'applicationStatus',
];
-
-
+ public function oneoffApplicant()
+ {
+ return $this->hasOne('App\OneoffApplicant', 'application_id', 'id');
+ }
public function user()
{
@@ -37,7 +58,6 @@ class Application extends Model
return $this->belongsToMany('App\Vote', 'votes_has_application');
}
-
public function comments()
{
return $this->hasMany('App\Comment', 'applicationID', 'id');
@@ -46,8 +66,15 @@ class Application extends Model
public function setStatus($status)
{
return $this->update([
- 'applicationStatus' => $status
+ 'applicationStatus' => $status,
]);
-
}
+
+
+ public function isOneoff()
+ {
+ return $this->user->id == 1; // ID 1 is always the ghost
+ }
+
+
}
diff --git a/app/Appointment.php b/app/Appointment.php
old mode 100644
new mode 100755
index d62e39a..a87c02f
--- a/app/Appointment.php
+++ b/app/Appointment.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -13,19 +32,19 @@ class Appointment extends Model
'appointmentStatus',
'appointmentLocation',
'meetingNotes',
- 'userAccepted'
+ 'userAccepted',
];
public function application()
{
- // FIXME: Possible bug here, where laravel looks for the wrong column in the applications table.
+ // FIXME: Possible bug here, where laravel looks for the wrong column in the applications table.
return $this->belongsTo('App\Application', 'id', 'applicationID');
}
public function setStatus($status)
{
$this->update([
- 'appointmentStatus' => $status
+ 'appointmentStatus' => $status,
]);
}
}
diff --git a/app/Ban.php b/app/Ban.php
old mode 100644
new mode 100755
index c1a6e90..f4c2dfb
--- a/app/Ban.php
+++ b/app/Ban.php
@@ -1,29 +1,46 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ban extends Model
{
-
public $fillable = [
'userID',
'reason',
'bannedUntil',
- 'userAgent',
- 'authorUserID'
+ 'isPermanent',
+ 'authorUserID',
];
public $dates = [
- 'bannedUntil'
+ 'suspendedUntil',
];
public function user()
{
return $this->belongsTo('App\User', 'userID', 'id');
}
-
}
diff --git a/app/Comment.php b/app/Comment.php
old mode 100644
new mode 100755
index c8dc8cc..ea4092b
--- a/app/Comment.php
+++ b/app/Comment.php
@@ -1,16 +1,34 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
-
protected $fillable = [
'authorID',
'applicationID',
- 'text'
+ 'text',
];
public function application()
@@ -22,5 +40,4 @@ class Comment extends Model
{
return $this->belongsTo('App\User', 'authorID', 'id');
}
-
}
diff --git a/app/Console/Commands/CountVotes.php b/app/Console/Commands/CountVotes.php
old mode 100644
new mode 100755
index a2a7c6d..c15ce68
--- a/app/Console/Commands/CountVotes.php
+++ b/app/Console/Commands/CountVotes.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Console\Commands;
use App\Application;
@@ -43,28 +62,23 @@ class CountVotes extends Command
$eligibleApps = Application::where('applicationStatus', 'STAGE_PEERAPPROVAL')->get();
$pbar = $this->output->createProgressBar($eligibleApps->count());
- if($eligibleApps->isEmpty())
- {
+ if ($eligibleApps->isEmpty()) {
$this->error('𐄂 There are no applications that need to be processed.');
return false;
}
- foreach ($eligibleApps as $application)
- {
+ foreach ($eligibleApps as $application) {
$votes = $application->votes;
$voteCount = $application->votes->count();
$positiveVotes = 0;
$negativeVotes = 0;
- if ($voteCount > 5)
- {
- $this->info('Counting votes for application ID ' . $application->id);
- foreach ($votes as $vote)
- {
- switch ($vote->allowedVoteType)
- {
+ if ($voteCount > 5) {
+ $this->info('Counting votes for application ID '.$application->id);
+ foreach ($votes as $vote) {
+ switch ($vote->allowedVoteType) {
case 'VOTE_APPROVE':
$positiveVotes++;
break;
@@ -74,7 +88,7 @@ class CountVotes extends Command
}
}
- $this->info('Total votes for application ID ' . $application->id . ': ' . $voteCount);
+ $this->info('Total votes for application ID '.$application->id.': '.$voteCount);
$this->info('Calculating criteria...');
$negativeVotePercent = floor(($negativeVotes / $voteCount) * 100);
$positiveVotePercent = floor(($positiveVotes / $voteCount) * 100);
@@ -83,54 +97,43 @@ class CountVotes extends Command
$this->table([
'% of approval votes',
- '% of denial votes'
+ '% of denial votes',
], [ // array of arrays, e.g. rows
[
- $positiveVotePercent . "%",
- $negativeVotePercent . "%"
- ]
+ $positiveVotePercent.'%',
+ $negativeVotePercent.'%',
+ ],
]);
- if ($pollResult)
- {
- $this->info('✓ Dispatched promotion event for applicant ' . $application->user->name);
- if (!$this->option('dryrun'))
- {
+ if ($pollResult) {
+ $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
- {
+ } else {
$this->warn('Dry run: Event won\'t be dispatched');
}
$pbar->advance();
-
- }
- else {
-
- if (!$this->option('dryrun'))
- {
+ } else {
+ if (! $this->option('dryrun')) {
event(new ApplicationDeniedEvent(Application::find($application->id)));
- }
- else {
+ } else {
$this->warn('Dry run: Event won\'t be dispatched');
}
$pbar->advance();
- $this->error('𐄂 Applicant ' . $application->user->name . ' does not meet vote criteria (Majority)');
+ $this->error('𐄂 Applicant '.$application->user->name.' does not meet vote criteria (Majority)');
}
+ } else {
+ $this->warn('Application ID'.$application->id.' did not have enough votes for processing (min 5)');
}
- else
- {
- $this->warn("Application ID" . $application->id . " did not have enough votes for processing (min 5)");
- }
-
}
$pbar->finish();
+
return true;
}
}
diff --git a/app/Console/Commands/CreateUser.php b/app/Console/Commands/CreateUser.php
new file mode 100755
index 0000000..eb98a8d
--- /dev/null
+++ b/app/Console/Commands/CreateUser.php
@@ -0,0 +1,140 @@
+.
+ */
+
+namespace App\Console\Commands;
+
+use App\Facades\UUID;
+use App\Profile;
+use App\User;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Hash;
+
+class CreateUser extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'users:create';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Creates an application user. Seeding the database is for testing environments, so use this command in production for your first admin user.';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ do {
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ system('cls');
+ } else {
+ system('clear');
+ }
+
+ $this->info('Welcome to the user account creation wizard. If you just installed the application, we recommend you create your first admin user here. If you don\'t, you won\'t gain admin privileges after creating an account in the web interface.');
+ $this->info('We\'ll ask some questions to get you started.');
+
+ $username = $this->ask('Username');
+ do {
+ $password = $this->secret('Password');
+ $password_confirm = $this->secret('Confirm Password');
+
+ if ($password === $password_confirm) {
+ $password = Hash::make($password);
+ $matches = true;
+ } else {
+ $this->error('Password doesn\'t match. Please try again.');
+ $matches = false;
+ }
+ } while (! $matches);
+
+ $email = $this->ask('E-mail address');
+ $name = $this->ask('First/Last Name');
+
+ do {
+ try {
+ $uuid = UUID::toUUID($this->ask('Minecraft username (Must be a valid Premium account)'));
+ } catch (\InvalidArgumentException $e) {
+ $this->error($e->getMessage());
+ $hasError = true;
+ }
+
+ if (isset($hasError)) {
+ $continue = true;
+ } else {
+ $continue = false;
+ }
+ unset($hasError);
+ } while ($continue);
+
+ $this->info('Please check if these details are correct: ');
+ $this->info('Username: '.$username);
+ $this->info('Email: '.$email);
+ $this->info('Name: '.$name);
+ } while (! $this->confirm('Create user now? You can go back to correct any details.'));
+
+ $user = User::create([
+ 'uuid' => $uuid,
+ 'name' => $name,
+ 'email' => $email,
+ 'username' => $username,
+ 'originalIP' => '127.0.0.1',
+ 'password' => $password,
+ ]);
+
+ if ($user) {
+ $user->assignRole('admin', 'reviewer', 'user', 'hiringManager');
+ Profile::create([
+ 'profileShortBio' => 'Random data '.rand(0, 1000),
+ 'profileAboutMe' => 'Random data '.rand(0, 1000),
+ 'socialLinks' => '[]',
+ 'avatarPreference' => 'gravatar',
+ 'userID' => $user->id,
+ ]);
+
+ $this->info('Account created! You may now login at '.route('login').'. Enjoy the app!');
+
+ return 0;
+ } else {
+ $this->error('There was an unknown problem creating the user. There might have been errors above. Please try again.');
+
+ return 1;
+ }
+ }
+}
diff --git a/app/Console/Commands/MakeFile.php b/app/Console/Commands/MakeFile.php
new file mode 100755
index 0000000..5d3cf40
--- /dev/null
+++ b/app/Console/Commands/MakeFile.php
@@ -0,0 +1,82 @@
+.
+ */
+
+namespace App\Console\Commands;
+
+use Faker\Factory;
+use Faker\Generator;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Storage;
+
+class MakeFile extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'files:make {count : How many test files to generate}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Generates test files for the TeamFile model. Use in conjunction with it\'s factory.';
+
+ /**
+ * The faker instance used to obtain dummy text.
+ *
+ * @var Generator
+ */
+ private $faker;
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->faker = Factory::create();
+
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $count = $this->argument('count');
+ $this->info('Creating '.$this->argument('count').' files!');
+
+ for ($max = 1; $max < $count; $max++) {
+ Storage::disk('local')->put('factory_files/testfile_'.rand(0, 5000).'.txt', $this->faker->paragraphs(40, true));
+ }
+
+ $this->info('Finished creating files! They will be randomly picked by the factory.');
+
+ return 0;
+ }
+}
diff --git a/app/Console/Commands/SetEnv.php b/app/Console/Commands/SetEnv.php
old mode 100644
new mode 100755
index 9125ffa..3c49403
--- a/app/Console/Commands/SetEnv.php
+++ b/app/Console/Commands/SetEnv.php
@@ -1,9 +1,28 @@
.
+ */
+
namespace App\Console\Commands;
-use Illuminate\Console\Command;
use GeoSot\EnvEditor\Facades\EnvEditor;
+use Illuminate\Console\Command;
class SetEnv extends Command
{
@@ -37,20 +56,16 @@ class SetEnv extends Command
*/
public function handle()
{
- $path = base_path('/.env');
- $key = $this->argument('key');
- $value = $this->argument('value');
+ $path = base_path('/.env');
+ $key = $this->argument('key');
+ $value = $this->argument('value');
+ if (file_exists($path)) {
+ EnvEditor::editKey($key, $value);
+ } else {
+ $this->error('Cannot update a file that doesn\'t exist! Please create .env first.');
-
- if (file_exists($path))
- {
- EnvEditor::editKey($key, $value);
- }
- else
- {
- $this->error('Cannot update a file that doesn\'t exist! Please create .env first.');
- return false;
- }
+ return false;
+ }
}
}
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
old mode 100644
new mode 100755
index fdf4d00..b50fa90
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -1,10 +1,29 @@
.
+ */
+
namespace App\Console;
+use App\Jobs\ProcessDueSuspensions;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
-use App\Jobs\CleanBans;
class Kernel extends ConsoleKernel
{
@@ -31,7 +50,7 @@ class Kernel extends ConsoleKernel
->daily();
// Production value: Every day
- $schedule->job(new CleanBans)
+ $schedule->job(new ProcessDueSuspensions)
->daily();
// Production value: Every day
}
diff --git a/app/CustomFacades/IP.php b/app/CustomFacades/IP.php
old mode 100644
new mode 100755
index 2b04064..6753e29
--- a/app/CustomFacades/IP.php
+++ b/app/CustomFacades/IP.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\CustomFacades;
use Illuminate\Support\Facades\Cache;
@@ -7,7 +26,6 @@ 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
@@ -15,23 +33,23 @@ class IP
*/
public function lookup(string $IP): object
{
-
- $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'), [
+ $params = [
'apiKey' => config('general.keys.ipapi.apikey'),
- 'ip' => $IP
- ])->body();
- }));
+ 'ip' => $IP,
+ ];
+ if (!config('demo.is_enabled')) {
+ 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();
+ }));
+ }
+
+ return new class {
+ public $message = "This feature is disabled.";
+ };
}
-
}
diff --git a/app/Events/ApplicationApprovedEvent.php b/app/Events/ApplicationApprovedEvent.php
old mode 100644
new mode 100755
index 4bb005c..066d83c
--- a/app/Events/ApplicationApprovedEvent.php
+++ b/app/Events/ApplicationApprovedEvent.php
@@ -1,13 +1,28 @@
.
+ */
+
namespace App\Events;
use App\Application;
-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;
@@ -26,6 +41,4 @@ class ApplicationApprovedEvent
{
$this->application = $application;
}
-
-
}
diff --git a/app/Events/ApplicationDeniedEvent.php b/app/Events/ApplicationDeniedEvent.php
old mode 100644
new mode 100755
index fb84a57..48951a3
--- a/app/Events/ApplicationDeniedEvent.php
+++ b/app/Events/ApplicationDeniedEvent.php
@@ -1,13 +1,28 @@
.
+ */
+
namespace App\Events;
use App\Application;
-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;
@@ -26,5 +41,4 @@ class ApplicationDeniedEvent
{
$this->application = $application;
}
-
}
diff --git a/app/Events/NewApplicationEvent.php b/app/Events/NewApplicationEvent.php
old mode 100644
new mode 100755
index bb67787..867ab50
--- a/app/Events/NewApplicationEvent.php
+++ b/app/Events/NewApplicationEvent.php
@@ -1,12 +1,28 @@
.
+ */
+
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;
diff --git a/app/Events/UserBannedEvent.php b/app/Events/UserBannedEvent.php
old mode 100644
new mode 100755
index 92addbf..05902ad
--- a/app/Events/UserBannedEvent.php
+++ b/app/Events/UserBannedEvent.php
@@ -1,23 +1,36 @@
.
+ */
+
namespace App\Events;
-use Illuminate\Broadcasting\Channel;
+use App\Ban;
+use App\User;
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;
@@ -32,5 +45,4 @@ class UserBannedEvent
$this->user = $user;
$this->ban = $ban;
}
-
}
diff --git a/app/Exceptions/ApplicationNotFoundException.php b/app/Exceptions/ApplicationNotFoundException.php
new file mode 100644
index 0000000..1fc29a9
--- /dev/null
+++ b/app/Exceptions/ApplicationNotFoundException.php
@@ -0,0 +1,11 @@
+.
+ */
+
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
diff --git a/app/Exceptions/IncompleteApplicationException.php b/app/Exceptions/IncompleteApplicationException.php
new file mode 100644
index 0000000..14966fc
--- /dev/null
+++ b/app/Exceptions/IncompleteApplicationException.php
@@ -0,0 +1,10 @@
+.
+ */
+
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class ContextAwareValidation extends Facade
{
-
- protected static function getFacadeAccessor()
- {
- return 'contextAwareValidator';
- }
-
+ protected static function getFacadeAccessor()
+ {
+ return 'contextAwareValidator';
+ }
}
diff --git a/app/Facades/DigitalStorageHelper.php b/app/Facades/DigitalStorageHelper.php
new file mode 100644
index 0000000..0ebdee0
--- /dev/null
+++ b/app/Facades/DigitalStorageHelper.php
@@ -0,0 +1,17 @@
+.
+ */
+
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
diff --git a/app/Facades/JSON.php b/app/Facades/JSON.php
new file mode 100644
index 0000000..ec06d71
--- /dev/null
+++ b/app/Facades/JSON.php
@@ -0,0 +1,17 @@
+.
+ */
namespace App\Facades;
-use \Illuminate\Support\Facades\Facade;
+
+use Illuminate\Support\Facades\Facade;
class Options extends Facade
{
diff --git a/app/Facades/UUID.php b/app/Facades/UUID.php
old mode 100644
new mode 100755
index 18699ee..b26e3a3
--- a/app/Facades/UUID.php
+++ b/app/Facades/UUID.php
@@ -1,13 +1,32 @@
.
+ */
+
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
-class UUID extends Facade
+class UUID extends Facade
{
protected static function getFacadeAccessor()
{
return 'uuidConversionFacade';
}
-}
\ No newline at end of file
+}
diff --git a/app/Form.php b/app/Form.php
old mode 100644
new mode 100755
index dc64af2..80220fc
--- a/app/Form.php
+++ b/app/Form.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -10,7 +29,7 @@ class Form extends Model
'formName',
'formStructure',
- 'formStatus'
+ 'formStatus',
];
diff --git a/app/Helpers/ContextAwareValidator.php b/app/Helpers/ContextAwareValidator.php
old mode 100644
new mode 100755
index f2ffb55..6257255
--- a/app/Helpers/ContextAwareValidator.php
+++ b/app/Helpers/ContextAwareValidator.php
@@ -1,138 +1,141 @@
.
+ */
+
namespace App\Helpers;
-use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\Validator;
class ContextAwareValidator
{
-
/**
- * The excludedNames array will make the validator ignore any of these names when including names into the rules.
- * @var array
- */
+ * The excludedNames array will make the validator ignore any of these names when including names into the rules.
+ * @var array
+ */
private $excludedNames = [
- '_token',
- '_method',
- 'formName'
+ '_token',
+ '_method',
+ 'formName',
];
-
/**
- * Utility wrapper for json_encode.
- *
- * @param array $value The array to be converted.
- * @return string The JSON representation of $value
- */
- private function encode(array $value) : string
+ * Utility wrapper for json_encode.
+ *
+ * @param array $value The array to be converted.
+ * @return string The JSON representation of $value
+ */
+ private function encode(array $value): string
{
- return json_encode($value);
+ return json_encode($value);
}
/**
- * The getValidator() method will take an array of fields from the request body, iterates through them,
- * and dynamically adds validation rules for them. Depending on parameters, it may or may not generate
- * a form structure for rendering purposes.
- *
- * This method is mostly meant by internal use by means of static proxies (Facades), in order to reduce code repetition;
- * Using it outside it's directed scope may cause unexpected results; For instance, the method expects inputs to be in array format, e.g. myFieldNameID1[],
- * myFieldNameID2[], and so on and so forth.
- *
- * This isn't checked by the code yet, but if you're implementing it this way in the HTML markup, make sure it's consistent (e.g. use a loop).
- *
- * P.S This method automatically ignores the CSRF token for validation.
- *
- * @param array $fields The request form fields
- * @param bool $generateStructure Whether to incldue a JSON-ready form structure for rendering
- * @param bool $includeFormName Whether to include formName in the list of validation rules
- * @return Validator|Collection A validator instance you can use to check for validity, or a Collection with a validator and structure (validator, structure)
- */
+ * The getValidator() method will take an array of fields from the request body, iterates through them,
+ * and dynamically adds validation rules for them. Depending on parameters, it may or may not generate
+ * a form structure for rendering purposes.
+ *
+ * This method is mostly meant by internal use by means of static proxies (Facades), in order to reduce code repetition;
+ * Using it outside it's directed scope may cause unexpected results; For instance, the method expects inputs to be in array format, e.g. myFieldNameID1[],
+ * myFieldNameID2[], and so on and so forth.
+ *
+ * This isn't checked by the code yet, but if you're implementing it this way in the HTML markup, make sure it's consistent (e.g. use a loop).
+ *
+ * P.S This method automatically ignores the CSRF token for validation.
+ *
+ * @param array $fields The request form fields
+ * @param bool $generateStructure Whether to incldue a JSON-ready form structure for rendering
+ * @param bool $includeFormName Whether to include formName in the list of validation rules
+ * @return Validator|Collection A validator instance you can use to check for validity, or a Collection with a validator and structure (validator, structure)
+ */
public function getValidator(array $fields, bool $generateStructure = false, bool $includeFormName = false)
{
$formStructure = [];
$validator = [];
- if ($includeFormName)
- {
- $validator['formName'] = 'required|string|max:100';
- }
+ if ($includeFormName) {
+ $validator['formName'] = 'required|string';
+ }
- foreach ($fields as $fieldName => $field)
- {
- if(!in_array($fieldName, $this->excludedNames))
- {
- $validator[$fieldName . ".0"] = 'required|string';
- $validator[$fieldName . ".1"] = 'required|string';
+ foreach ($fields as $fieldName => $field) {
+ if (! in_array($fieldName, $this->excludedNames)) {
+ $validator[$fieldName.'.0'] = 'required|string';
+ $validator[$fieldName.'.1'] = 'required|string';
- if ($generateStructure)
- {
+ if ($generateStructure) {
$formStructure['fields'][$fieldName]['title'] = $field[0];
$formStructure['fields'][$fieldName]['type'] = $field[1];
- }
+ }
+ }
+ }
- }
- }
+ $validatorInstance = Validator::make($fields, $validator);
- $validatorInstance = Validator::make($fields, $validator);
-
- return ($generateStructure) ?
+ return ($generateStructure) ?
collect([
- 'validator' => $validatorInstance,
- 'structure' => $this->encode($formStructure)
+ 'validator' => $validatorInstance,
+ 'structure' => $this->encode($formStructure),
])
: $validatorInstance;
-
-
}
/**
- * The getResponseValidator method is similar to the getValidator method; It basically takes
- * an array of fields from a previous form (that probably went through the other method) and adds validation
- * to the field names.
- *
- * Also generates the storable response structure if you tell it to.
- *
- * @param array $fields The received fields
- * @param array $formStructure The form structure - You must supply this if you want the response structure
- * @param bool $generateResponseStructure Whether to generate the response structure
- * @return Validator|Collection A collection or a validator, depending on the args. Will return validatior if only fields are supplied.
- */
+ * The getResponseValidator method is similar to the getValidator method; It basically takes
+ * an array of fields from a previous form (that probably went through the other method) and adds validation
+ * to the field names.
+ *
+ * Also generates the storable response structure if you tell it to.
+ *
+ * @param array $fields The received fields
+ * @param array $formStructure The form structure - You must supply this if you want the response structure
+ * @param bool $generateResponseStructure Whether to generate the response structure
+ * @return Validator|Collection A collection or a validator, depending on the args. Will return validatior if only fields are supplied.
+ */
public function getResponseValidator(array $fields, array $formStructure = [], bool $generateResponseStructure = true)
{
+ $responseStructure = [];
+ $validator = [];
- $responseStructure = [];
- $validator = [];
+ if (empty($formStructure) && $generateResponseStructure) {
+ throw new \InvalidArgumentException('Illegal combination of arguments supplied! Please check the method\'s documentation.');
+ }
- if (empty($formStructure) && $generateResponseStructure)
- {
- throw new \InvalidArgumentException('Illegal combination of arguments supplied! Please check the method\'s documentation.');
- }
+ foreach ($fields as $fieldName => $value) {
+ if (! in_array($fieldName, $this->excludedNames)) {
+ $validator[$fieldName] = 'required|string';
- foreach($fields as $fieldName => $value)
- {
- if(!in_array($fieldName, $this->excludedNames))
- {
- $validator[$fieldName] = 'required|string';
+ if ($generateResponseStructure) {
+ $responseStructure['responses'][$fieldName]['type'] = $formStructure['fields'][$fieldName]['type'] ?? 'Unavailable';
+ $responseStructure['responses'][$fieldName]['title'] = $formStructure['fields'][$fieldName]['title'];
+ $responseStructure['responses'][$fieldName]['response'] = $value;
+ }
+ }
+ }
- if ($generateResponseStructure)
- {
- $responseStructure['responses'][$fieldName]['type'] = $formStructure['fields'][$fieldName]['type'] ?? 'Unavailable';
- $responseStructure['responses'][$fieldName]['title'] = $formStructure['fields'][$fieldName]['title'];
- $responseStructure['responses'][$fieldName]['response'] = $value;
- }
- }
- }
+ $validatorInstance = Validator::make($fields, $validator);
- $validatorInstance = Validator::make($fields, $validator);
-
- return ($generateResponseStructure) ?
+ return ($generateResponseStructure) ?
collect([
- 'validator' => $validatorInstance,
- 'responseStructure' => $this->encode($responseStructure)
+ 'validator' => $validatorInstance,
+ 'responseStructure' => $this->encode($responseStructure),
])
: $validatorInstance;
-
}
-
}
diff --git a/app/Helpers/DigitalStorageHelper.php b/app/Helpers/DigitalStorageHelper.php
new file mode 100644
index 0000000..24637bc
--- /dev/null
+++ b/app/Helpers/DigitalStorageHelper.php
@@ -0,0 +1,107 @@
+value = $value;
+ return $this;
+ }
+
+
+ /**
+ * Converts the digital storage value to kilobytes.
+ *
+ * @return float|int
+ */
+ public function toKilobytes(): float
+ {
+ return $this->value / 1000;
+ }
+
+
+ /**
+ * Converts the digital storage value to megabytes.
+ *
+ * @return float|int
+ */
+ public function toMegabytes(): float
+ {
+ return $this->value / (1 * pow(10, 6)); // 1 times 10 to the power of 6
+ }
+
+
+ /**
+ * Convert the digital storage value to gigabytes. Might be an approximation
+ *
+ * @return float
+ */
+ public function toGigabytes(): float
+ {
+ return $this->value / (1 * pow(10, 9));
+ }
+
+
+ /**
+ * Convert the digital storage value to terabytes.
+ *
+ * @return float
+ */
+ public function toTerabytes(): float
+ {
+ return $this->value / (1 * pow(10, 12));
+ }
+
+
+ /**
+ * Format the digital storage value to one of the units: b, kb, mb, gb and tb.
+ * The method has been adapted to use both MiB and MB values.
+ *
+ * @param int $precision The rounding precision
+ * @param bool $si Use international system units. Defaults to false
+ * @return string The human readable digital storage value, in either, for instance, MB or MiB
+ * @see https://stackoverflow.com/a/2510459/11540218 StackOverflow question regarding unit conversion
+ * @since 7.3.23
+ */
+ public function formatBytes($precision = 2, $si = false): string
+ {
+ $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
+ if ($si)
+ $units = ['B', 'KB', 'MB', 'GB', 'TB'];
+
+ $bytes = max($this->value, 0);
+ $pow = floor(($bytes ? log($bytes) : 0) / log(($si) ? 1000 : 1024));
+ $pow = min($pow, count($units) - 1);
+
+ $bytes /= pow(($si) ? 1000 : 1024, $pow);
+
+ return round($bytes, $precision) . ' ' . $units[$pow];
+ }
+
+}
diff --git a/app/Helpers/JSON.php b/app/Helpers/JSON.php
new file mode 100644
index 0000000..334fb34
--- /dev/null
+++ b/app/Helpers/JSON.php
@@ -0,0 +1,142 @@
+type = $type;
+ return $this;
+ }
+
+ /**
+ * @param mixed $additional
+ */
+ public function setAdditional($additional)
+ {
+ $this->additional = $additional;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAdditional()
+ {
+ return $this->additional;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * @param mixed $status
+ * @return JSON
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ /**
+ * @param mixed $message
+ * @return JSON
+ */
+ public function setMessage($message)
+ {
+ $this->message = $message;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCode()
+ {
+ return $this->code;
+ }
+
+ /**
+ * @param mixed $code
+ * @return JSON
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getData()
+ {
+ return $this->data;
+ }
+
+ /**
+ * @param mixed $data
+ * @return JSON
+ */
+ public function setData($data)
+ {
+ $this->data = $data;
+ return $this;
+ }
+
+ public function build($headers = [])
+ {
+ // Uses the same structure as model resources, for consistency when they aren't used.
+ $response = [
+ 'data' => $this->getData(),
+ 'meta' => [
+ 'status' => $this->getStatus(),
+ 'message' => $this->getMessage(),
+ ]
+ ];
+
+ if (!empty($this->additional))
+ {
+ foreach($this->additional as $additionalKeyName => $key)
+ {
+ $response[$additionalKeyName] = $key;
+ }
+ }
+ return response($response, $this->getCode(), $headers);
+ }
+
+}
diff --git a/app/Helpers/Options.php b/app/Helpers/Options.php
old mode 100644
new mode 100755
index 13c416d..a1b35e8
--- a/app/Helpers/Options.php
+++ b/app/Helpers/Options.php
@@ -1,43 +1,88 @@
.
+ */
namespace App\Helpers;
+use App\Exceptions\EmptyOptionsException;
+use App\Exceptions\OptionNotFoundException;
use App\Options as Option;
+use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
+/**
+ * The options class. A simple wrapper around the model. Could be a repository, but we're not using that design pattern just yet
+ */
class Options
{
+ /**
+ * Returns an assortment of settings found in the mentioned category
+ *
+ * @param $category The category
+ * @return Collection The settings in this category
+ */
+ public function getCategory(string $category): Collection
+ {
+ $options = Option::where('option_category', $category)->get();
+ if ($options->isEmpty())
+ {
+ throw new EmptyOptionsException('There are no options in category ' . $category);
+ }
+ return $options;
+ }
+
+
public function getOption(string $option): string
{
$value = Cache::get($option);
- if (is_null($value))
- {
- Log::debug('Option ' . $option . 'not found in cache, refreshing from database');
- $value = Option::where('option_name', $option)->first();
- if (is_null($value))
- throw new \Exception('This option does not exist.');
- Cache::put($option, $value);
- Cache::put($option . '_desc', 'Undefined description');
+ if (is_null($value)) {
+ Log::debug('Option '.$option.'not found in cache, refreshing from database');
+ $value = Option::where('option_name', $option)->first();
+ if (is_null($value)) {
+ throw new OptionNotFoundException('This option does not exist.');
+ }
+ Cache::put($option, $value->option_value);
+ Cache::put($option.'_desc', 'Undefined description');
+
+ return $value->option_value;
}
- return $value->option_value;
+ return $value;
}
- public function setOption(string $option, string $value, string $description)
+ // Null categories are settings without categories and will appear ungrouped
+ public function setOption(string $option, string $value, string $description, string $category = null)
{
- Option::create([
- 'option_name' => $option,
- 'option_value' => $value,
- 'friendly_name' => $description
- ]);
+ Option::create([
+ 'option_name' => $option,
+ 'option_value' => $value,
+ 'friendly_name' => $description,
+ 'option_category' => $category
+ ]);
- Cache::put($option, $value, now()->addDay());
- Cache::put($option . '_desc', $description, now()->addDay());
+ Cache::put($option, $value, now()->addDay());
+ Cache::put($option.'_desc', $description, now()->addDay());
}
public function pullOption($option): array
@@ -48,7 +93,7 @@ class Options
// putMany is overkill here
return [
Cache::pull($option),
- Cache::pull($option . '_desc')
+ Cache::pull($option.'_desc'),
];
}
@@ -56,14 +101,13 @@ class Options
{
$dbOption = Option::where('option_name', $option);
- if ($dbOption->first())
- {
+ if ($dbOption->first()) {
$dbOptionInstance = Option::find($dbOption->first()->id);
Cache::forget($option);
Log::debug('Changing db configuration option', [
'old_value' => $dbOptionInstance->option_value,
- 'new_value' => $newValue
+ 'new_value' => $newValue,
]);
$dbOptionInstance->option_value = $newValue;
@@ -71,24 +115,20 @@ class Options
Log::debug('New db configuration option saved',
[
- 'option' => $dbOptionInstance->option_value
+ 'option' => $dbOptionInstance->option_value,
]);
Cache::put('option_name', $newValue, now()->addDay());
- }
- else
- {
- throw new \Exception('This option does not exist.');
+ } else {
+ throw new OptionNotFoundException('This option does not exist.');
}
}
-
public function optionExists(string $option): bool
{
$dbOption = Option::where('option_name', $option)->first();
$locallyCachedOption = Cache::get($option);
- return !is_null($dbOption) || !is_null($locallyCachedOption);
+ return ! is_null($dbOption) || ! is_null($locallyCachedOption);
}
-
}
diff --git a/app/Http/Controllers/ApiKeyController.php b/app/Http/Controllers/ApiKeyController.php
new file mode 100644
index 0000000..f725ec4
--- /dev/null
+++ b/app/Http/Controllers/ApiKeyController.php
@@ -0,0 +1,95 @@
+authorize('viewAny', ApiKey::class);
+
+ return view('dashboard.administration.keys')
+ ->with('keys', ApiKey::all());
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ *
+ * @param \Illuminate\Http\Request $request
+ */
+ public function store(CreateApiKeyRequest $request)
+ {
+ $this->authorize('create', ApiKey::class);
+
+ $discriminator = "#" . bin2hex(random_bytes(7));
+ $secret = bin2hex(random_bytes(32));
+
+ $key = ApiKey::create([
+ 'name' => $request->keyName,
+ 'discriminator' => $discriminator,
+ 'secret' => Hash::make($secret),
+ 'status' => 'active',
+ 'owner_user_id' => Auth::user()->id
+ ]);
+
+ if ($key)
+ {
+ $request->session()->flash('success', __('Key successfully registered!'));
+ $request->session()->flash('finalKey', $discriminator . '.' . $secret);
+
+ return redirect()
+ ->back();
+ }
+
+ return redirect()
+ ->back()
+ ->with('error', __('An error occurred whilst trying to create an API key.'));
+ }
+
+
+ public function revokeKey(Request $request, ApiKey $key)
+ {
+ $this->authorize('update', $key);
+
+ if ($key->status == 'active')
+ {
+ $key->status = 'disabled';
+ $key->save();
+ }
+ else
+ {
+ return redirect()
+ ->back()
+ ->with('error', __('Key already revoked.'));
+ }
+
+ return redirect()
+ ->back()
+ ->with('success', __('Key revoked. Apps using this key will stop working.'));
+
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ */
+ public function destroy($id)
+ {
+ $key = ApiKey::findOrFail($id);
+ $this->authorize('delete', $key);
+
+ $key->delete();
+
+ return redirect()
+ ->back()
+ ->with('success', __('Key deleted successfully. Apps using this key will stop working.'));
+
+ }
+}
diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php
old mode 100644
new mode 100755
index bcedc0a..fcb6dbf
--- a/app/Http/Controllers/ApplicationController.php
+++ b/app/Http/Controllers/ApplicationController.php
@@ -1,59 +1,57 @@
.
+ */
+
namespace App\Http\Controllers;
use App\Application;
-
-use App\Response;
-use App\Vacancy;
-use App\User;
-
-use App\Events\ApplicationDeniedEvent;
-use App\Notifications\NewApplicant;
-use App\Notifications\ApplicationMoved;
-
+use App\Exceptions\ApplicationNotFoundException;
+use App\Exceptions\IncompleteApplicationException;
+use App\Exceptions\UnavailableApplicationException;
+use App\Exceptions\VacancyNotFoundException;
+use App\Services\ApplicationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Validator;
-use Illuminate\Support\Facades\App;
-use Illuminate\Support\Facades\Log;
-
-use ContextAwareValidator;
class ApplicationController extends Controller
{
- private function canVote($votes)
- {
- $allvotes = collect([]);
+ private $applicationService;
- foreach ($votes as $vote)
- {
- if ($vote->userID == Auth::user()->id)
- {
- $allvotes->push($vote);
- }
- }
+ public function __construct(ApplicationService $applicationService) {
- return ($allvotes->count() == 1) ? false : true;
+ $this->applicationService = $applicationService;
}
-
public function showUserApps()
{
-
return view('dashboard.user.applications')
->with('applications', Auth::user()->applications);
}
-
public function showUserApp(Request $request, Application $application)
{
$this->authorize('view', $application);
- if (!is_null($application))
- {
+ if (!is_null($application)) {
return view('dashboard.user.viewapp')
->with(
[
@@ -62,210 +60,88 @@ class ApplicationController extends Controller
'structuredResponses' => json_decode($application->response->responseData, true),
'formStructure' => $application->response->form,
'vacancy' => $application->response->vacancy,
- 'canVote' => $this->canVote($application->votes)
+ 'canVote' => $this->applicationService->canVote($application->votes),
]
);
- }
- else
- {
- $request->session()->flash('error', 'The application you requested could not be found.');
+ } else {
+ $request->session()->flash('error', __('The application you requested could not be found.'));
}
return redirect()->back();
+
}
-
-
- public function showAllApps()
+ public function showAllApps(Request $request)
{
$this->authorize('viewAny', Application::class);
return view('dashboard.appmanagement.all')
- ->with('applications', Application::paginate(6));
+ ->with('applications', Application::all());
+
}
- public function showAllPendingApps()
+ public function renderApplicationForm($vacancySlug)
{
- $this->authorize('viewAny', Application::class);
-
- return view('dashboard.appmanagement.outstandingapps')
- ->with('applications', Application::where('applicationStatus', 'STAGE_SUBMITTED')->get());
- }
-
-
- public function showPendingInterview()
- {
- $this->authorize('viewAny', Application::class);
- $applications = Application::with('appointment', 'user')->get();
- $count = 0;
-
- $pendingInterviews = collect([]);
- $upcomingInterviews = collect([]);
-
-
- foreach ($applications as $application)
- {
- if (!is_null($application->appointment) && $application->appointment->appointmentStatus == 'CONCLUDED')
- {
- $count =+ 1;
- }
-
- switch ($application->applicationStatus)
- {
- case 'STAGE_INTERVIEW':
- $upcomingInterviews->push($application);
-
- break;
-
- case 'STAGE_INTERVIEW_SCHEDULED':
- $pendingInterviews->push($application);
-
- break;
- }
-
+ try {
+ return $this->applicationService->renderForm($vacancySlug);
}
-
- return view('dashboard.appmanagement.interview')
- ->with([
- 'finishedCount' => $count,
- 'applications' => $pendingInterviews,
- 'upcomingApplications' => $upcomingInterviews
- ]);
- }
-
-
-
- public function showPeerReview()
- {
- $this->authorize('viewAny', Application::class);
- return view('dashboard.appmanagement.peerreview')
- ->with('applications', Application::where('applicationStatus', 'STAGE_PEERAPPROVAL')->get());
-
- }
-
-
-
- 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();
-
- $firstVacancy = $vacancyWithForm->first();
-
- if (!$vacancyWithForm->isEmpty() && $firstVacancy->vacancyCount !== 0 && $firstVacancy->vacancyStatus == 'OPEN')
- {
-
- return view('dashboard.application-rendering.apply')
- ->with([
-
- 'vacancy' => $vacancyWithForm->first(),
- 'preprocessedForm' => json_decode($vacancyWithForm->first()->forms->formStructure, true)
-
- ]);
+ catch (ApplicationNotFoundException $ex) {
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
}
- else
- {
- 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();
+ try {
- if ($vacancy->first()->vacancyCount == 0 || $vacancy->first()->vacancyStatus !== 'OPEN')
- {
+ $this->applicationService->fillForm(Auth::user(), $request->all(), $vacancySlug);
- $request->session()->flash('error', 'This application is unavailable.');
- return redirect()->back();
+ } catch (VacancyNotFoundException | IncompleteApplicationException | UnavailableApplicationException $e) {
+ return redirect()
+ ->back()
+ ->with('error', $e->getMessage());
}
- Log::info('Processing new application!');
-
- $formStructure = json_decode($vacancy->first()->forms->formStructure, true);
- $responseValidation = ContextAwareValidator::getResponseValidator($request->all(), $formStructure);
-
- Log::info('Built response & validator structure!');
-
- if (!$responseValidation->get('validator')->fails())
- {
- $response = Response::create([
- 'responseFormID' => $vacancy->first()->forms->id,
- 'associatedVacancyID' => $vacancy->first()->id, // Since a form can be used by multiple vacancies, we can only know which specific vacancy this response ties to by using a vacancy ID
- 'responseData' => $responseValidation->get('responseStructure')
- ]);
-
- Log::info('Registered form response for user ' . Auth::user()->name . ' for vacancy ' . $vacancy->first()->vacancyName);
-
- $application = Application::create([
- 'applicantUserID' => Auth::user()->id,
- 'applicantFormResponseID' => $response->id,
- 'applicationStatus' => 'STAGE_SUBMITTED',
- ]);
-
- 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'));
- }
- else
- {
- Log::warning('Application form for ' . Auth::user()->name . ' contained errors, resetting!');
- $request->session()->flash('error', 'There are one or more errors in your application. Please make sure none of your fields are empty, since they are all required.');
-
- }
-
- return redirect()->back();
+ return redirect()
+ ->to(route('showUserApps'))
+ ->with('success', __('Thank you! Your application has been processed and our team will get to it shortly.'));
}
public function updateApplicationStatus(Request $request, Application $application, $newStatus)
{
+ $messageIsError = false;
$this->authorize('update', Application::class);
- switch ($newStatus)
+ try {
+ $status = $this->applicationService->updateStatus($application, $newStatus);
+ } catch (\LogicException $ex)
{
- case 'deny':
-
- 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:
- $request->session()->flash('error', 'There are no suitable statuses to update to. Do not mess with the URL.');
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
}
- return redirect()->back();
+ return redirect()
+ ->back()
+ ->with('success', $status);
}
+ /**
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ * @throws \Exception
+ */
public function delete(Request $request, Application $application)
{
+ $this->authorize('delete', $application);
+ $this->applicationService->delete($application);
- $this->authorize('delete', $application);
- $application->delete(); // observers will run, cleaning it up
-
- $request->session()->flash('success', 'Application deleted. Comments, appointments and responses have also been deleted.');
- return redirect()->back();
+ return redirect()
+ ->back()
+ ->with('success', __('Application deleted. Comments, appointments and responses have also been deleted.'));
}
-
}
diff --git a/app/Http/Controllers/AppointmentController.php b/app/Http/Controllers/AppointmentController.php
old mode 100644
new mode 100755
index 8ed2722..18efe1d
--- a/app/Http/Controllers/AppointmentController.php
+++ b/app/Http/Controllers/AppointmentController.php
@@ -1,94 +1,101 @@
.
+ */
+
namespace App\Http\Controllers;
use App\Application;
-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;
+use App\Exceptions\InvalidAppointmentException;
+use App\Exceptions\InvalidAppointmentStatusException;
+use App\Http\Requests\SaveNotesRequest;
+use App\Services\AppointmentService;
+use App\Services\MeetingNoteService;
+use Carbon\Carbon;
+use Illuminate\Auth\Access\AuthorizationException;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
class AppointmentController extends Controller
{
- private $allowedPlatforms = [
- 'ZOOM',
- 'DISCORD',
- 'SKYPE',
- 'MEET',
- 'TEAMSPEAK'
+ private $appointmentService;
+ private $meetingNoteService;
- ];
- public function saveAppointment(Request $request, Application $application)
+ public function __construct(AppointmentService $appointmentService, MeetingNoteService $meetingNoteService) {
+
+ $this->appointmentService = $appointmentService;
+ $this->meetingNoteService = $meetingNoteService;
+ }
+
+ public function saveAppointment(Request $request, Application $application): RedirectResponse
{
$this->authorize('create', Appointment::class);
+
$appointmentDate = Carbon::parse($request->appointmentDateTime);
+ $this->appointmentService->createAppointment($application, $appointmentDate, $request->appointmentDescription, $request->appointmentLocation);
- $appointment = Appointment::create([
- 'appointmentDescription' => $request->appointmentDescription,
- 'appointmentDate' => $appointmentDate->toDateTimeString(),
- 'applicationID' => $application->id,
- 'appointmentLocation' => (in_array($request->appointmentLocation, $this->allowedPlatforms)) ? $request->appointmentLocation : 'DISCORD',
- ]);
- $application->setStatus('STAGE_INTERVIEW_SCHEDULED');
-
-
- Log::info('User ' . Auth::user()->name . ' has scheduled an appointment with ' . $application->user->name . ' for application ID' . $application->id, [
- 'datetime' => $appointmentDate->toDateTimeString(),
- 'scheduled' => now()
- ]);
-
- $application->user->notify(new AppointmentScheduled($appointment));
- $request->session()->flash('success', 'Appointment successfully scheduled @ ' . $appointmentDate->toDateTimeString());
-
-
- return redirect()->back();
+ return redirect()
+ ->back()
+ ->with('success',__('Appointment successfully scheduled @ :appointmentTime', ['appointmentTime', $appointmentDate->toDateTimeString()]));
}
- public function updateAppointment(Request $request, Application $application, $status)
+ /**
+ * @throws AuthorizationException
+ */
+ public function updateAppointment(Application $application, $status): RedirectResponse
{
- $this->authorize('update', $application->appointment);
+ $this->authorize('update', $application->appointment);
- $validStatuses = [
- 'SCHEDULED',
- 'CONCLUDED'
- ];
+ try {
+ $this->appointmentService->updateAppointment($application, $status);
- // NOTE: This is a little confusing, refactor
- $application->appointment->appointmentStatus = (in_array($status, $validStatuses)) ? strtoupper($status) : 'SCHEDULED';
- $application->appointment->save();
+ return redirect()
+ ->back()
+ ->with('success', __("Interview finished! Staff members can now vote on it."));
- $application->setStatus('STAGE_PEERAPPROVAL');
- $application->user->notify(new ApplicationMoved());
+ }
+ catch (InvalidAppointmentStatusException $ex) {
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
+ }
- $request->session()->flash('success', 'Interview finished! Staff members can now vote on it.');
- return redirect()->back();
}
- // also updates
public function saveNotes(SaveNotesRequest $request, Application $application)
{
- if (!is_null($application))
- {
- $application->load('appointment');
+ try {
- $application->appointment->meetingNotes = $request->noteText;
- $application->appointment->save();
+ $this->meetingNoteService->addToApplication($application, $request->noteText);
- $request->session()->flash('success', 'Meeting notes have been saved.');
+ return redirect()
+ ->back()
+ ->with('success', 'Saved notes.');
+
+ } catch (InvalidAppointmentException $ex) {
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
}
- else
- {
- $request->session()->flash('error', 'There\'s no appointment to save notes to!');
- }
-
- return redirect()->back();
}
-
}
diff --git a/app/Http/Controllers/Auth/ConfirmPasswordController.php b/app/Http/Controllers/Auth/ConfirmPasswordController.php
old mode 100644
new mode 100755
index 71a9592..10760cc
--- a/app/Http/Controllers/Auth/ConfirmPasswordController.php
+++ b/app/Http/Controllers/Auth/ConfirmPasswordController.php
@@ -1,9 +1,27 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
-use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ConfirmsPasswords;
class ConfirmPasswordController extends Controller
diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php
old mode 100644
new mode 100755
index 465c39c..2ddd570
--- a/app/Http/Controllers/Auth/ForgotPasswordController.php
+++ b/app/Http/Controllers/Auth/ForgotPasswordController.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
old mode 100644
new mode 100755
index 47413e2..a97e63c
--- a/app/Http/Controllers/Auth/LoginController.php
+++ b/app/Http/Controllers/Auth/LoginController.php
@@ -1,12 +1,31 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
-use App\User;
use App\Http\Controllers\Controller;
-use App\Providers\RouteServiceProvider;
+use App\User;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
class LoginController extends Controller
{
@@ -48,22 +67,30 @@ class LoginController extends Controller
{
$user = User::where('email', $request->email)->first();
- if ($user)
- {
+ if ($user) {
$isBanned = $user->isBanned();
- if ($isBanned)
- {
+ if ($isBanned) {
return false;
- }
- else
- {
+ } else {
return $this->originalAttemptLogin($request);
}
}
return $this->originalAttemptLogin($request);
-
}
-
+ public function authenticated(Request $request, User $user)
+ {
+ if (!config('demo.is_enabled')) {
+ if ($user->originalIP !== $request->ip())
+ {
+ Log::alert('User IP address changed from last login. Updating.', [
+ 'prev' => $user->originalIP,
+ 'new' => $request->ip()
+ ]);
+ $user->originalIP = $request->ip();
+ $user->save();
+ }
+ }
+ }
}
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
old mode 100644
new mode 100755
index c6b3364..3140223
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -1,15 +1,33 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Profile;
-use App\Providers\RouteServiceProvider;
use App\User;
+use App\Facades\Options;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
-use function GuzzleHttp\Psr7\str;
class RegisterController extends Controller
{
@@ -47,10 +65,8 @@ class RegisterController extends Controller
{
$users = User::where('originalIP', \request()->ip())->get();
- foreach($users as $user)
- {
- if ($user && $user->isBanned())
- {
+ foreach ($users as $user) {
+ if ($user && $user->isBanned()) {
abort(403, 'You do not have permission to access this page.');
}
}
@@ -66,13 +82,32 @@ class RegisterController extends Controller
*/
protected function validator(array $data)
{
+ $password = ['required', 'string', 'confirmed'];
+
+ switch (Options::getOption('pw_security_policy'))
+ { // this could be better structured, switch doesn't feel right
+ case 'off':
+ $password = ['required', 'string', 'confirmed'];
+ break;
+ case 'low':
+ $password = ['required', 'string', 'min:10', 'confirmed'];
+ break;
+
+ case 'medium':
+ $password = ['required', 'string', 'confirmed', 'regex:/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[#?!@$%^&*-]).{12,}$/'];
+ break;
+
+ case 'high':
+ $password = ['required', 'string', 'confirmed', 'regex:/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{20,}$/'];
+ }
+
return Validator::make($data, [
- 'uuid' => ['required', 'string', 'unique:users', 'min:32', 'max:32'],
+ 'uuid' => (Options::getOption('requireGameLicense') && Options::getOption('currentGame') == 'MINECRAFT') ? ['required', 'string', 'unique:users', 'min:32', 'max:32'] : ['nullable', 'string'],
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
- 'password' => ['required', 'string', 'min:10', 'confirmed', 'regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\x])(?=.*[!$#%]).*$/'],
+ 'password' => $password,
], [
- 'uuid.required' => 'Please enter a valid (and Premium) Minecraft username! We do not support cracked users.'
+ 'uuid.required' => 'Please enter a valid (and Premium) Minecraft username! We do not support cracked users.',
]);
}
@@ -84,19 +119,19 @@ class RegisterController extends Controller
*/
protected function create(array $data)
{
-
$user = User::create([
'uuid' => $data['uuid'],
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
- 'originalIP' => request()->ip()
+ 'originalIP' => config('demo.is_enabled') ? '0.0.0.0' : request()->ip(),
]);
// 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.
+ // so this code has been moved to its respective observer, following the separation of concerns pattern.
$user->assignRole('user');
+
return $user;
}
}
diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php
old mode 100644
new mode 100755
index 6c0c13a..bbf75a7
--- a/app/Http/Controllers/Auth/ResetPasswordController.php
+++ b/app/Http/Controllers/Auth/ResetPasswordController.php
@@ -1,9 +1,27 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
-use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
diff --git a/app/Http/Controllers/Auth/TwofaController.php b/app/Http/Controllers/Auth/TwofaController.php
old mode 100644
new mode 100755
index a3ecac9..d8bad0e
--- a/app/Http/Controllers/Auth/TwofaController.php
+++ b/app/Http/Controllers/Auth/TwofaController.php
@@ -1,16 +1,32 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
-use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Traits\AuthenticatesTwoFactor;
class TwofaController extends Controller
{
- use AuthenticatesTwoFactor;
-
-
- protected $redirectTo = '/dashboard';
+ use AuthenticatesTwoFactor;
+ protected $redirectTo = '/dashboard';
}
diff --git a/app/Http/Controllers/Auth/VerificationController.php b/app/Http/Controllers/Auth/VerificationController.php
old mode 100644
new mode 100755
index 482a167..74be54b
--- a/app/Http/Controllers/Auth/VerificationController.php
+++ b/app/Http/Controllers/Auth/VerificationController.php
@@ -1,9 +1,27 @@
.
+ */
+
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
-use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\VerifiesEmails;
class VerificationController extends Controller
diff --git a/app/Http/Controllers/BanController.php b/app/Http/Controllers/BanController.php
old mode 100644
new mode 100755
index 3ae2a42..97075d3
--- a/app/Http/Controllers/BanController.php
+++ b/app/Http/Controllers/BanController.php
@@ -1,92 +1,86 @@
.
+ */
+
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;
+use App\Services\AccountSuspensionService;
+use App\User;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
class BanController extends Controller
{
+ protected $suspensionService;
+
+ public function __construct(AccountSuspensionService $suspensionService)
+ {
+ // Inject the service via DI
+ $this->suspensionService = $suspensionService;
+ }
+
public function insert(BanUserRequest $request, User $user)
{
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
$this->authorize('create', [Ban::class, $user]);
- if (is_null($user->bans))
- {
- $reason = $request->reason;
- $duration = strtolower($request->durationOperator);
- $durationOperand = $request->durationOperand;
+ if (!$this->suspensionService->isSuspended($user)) {
- $expiryDate = now();
+ $this->suspensionService->suspend($request->reason, $request->duration, $user, $request->suspensionType);
+ $request->session()->flash('success', __('Account suspended.'));
- if (!empty($duration))
- {
- switch($duration)
- {
- case 'days':
- $expiryDate->addDays($durationOperand);
- break;
+ } else {
- case 'weeks':
- $expiryDate->addWeeks($durationOperand);
- break;
-
- case 'months':
- $expiryDate->addMonths($durationOperand);
- break;
-
- case 'years':
- $expiryDate->addYears($durationOperand);
- break;
- }
- }
- else
- {
- // Essentially permanent
- $expiryDate->addYears(5);
- }
-
- $ban = Ban::create([
- 'userID' => $user->id,
- 'reason' => $reason,
- 'bannedUntil' => $expiryDate->format('Y-m-d H:i:s'),
- '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!');
+ $request->session()->flash('error', __('Account already suspended!'));
}
return redirect()->back();
}
-
public function delete(Request $request, User $user)
{
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
$this->authorize('delete', $user->bans);
- 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!');
+ if ($this->suspensionService->isSuspended($user)) {
+
+ $this->suspensionService->unsuspend($user);
+ $request->session()->flash('success', __('Account unsuspended successfully!'));
+
+ } else {
+ $request->session()->flash('error', __('This account isn\'t suspended!'));
}
return redirect()->back();
diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php
old mode 100644
new mode 100755
index 09d2aa2..609c0e3
--- a/app/Http/Controllers/CommentController.php
+++ b/app/Http/Controllers/CommentController.php
@@ -1,57 +1,62 @@
.
+ */
+
namespace App\Http\Controllers;
+use App\Application;
+use App\Comment;
+use App\Http\Requests\NewCommentRequest;
+use App\Services\CommentService;
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
{
+ private $commentService;
- public function index()
- {
- //
+ public function __construct(CommentService $commentService) {
+ $this->commentService = $commentService;
}
public function insert(NewCommentRequest $request, Application $application)
{
$this->authorize('create', Comment::class);
+ $comment = $this->commentService->addComment($application, $request->comment);
- $comment = Comment::create([
- 'authorID' => Auth::user()->id,
- 'applicationID' => $application->id,
- 'text' => $request->comment
- ]);
-
- if ($comment)
- {
-
- $request->session()->flash('success', 'Comment posted! (:');
- }
- else
- {
- $request->session()->flash('error', 'Something went wrong while posting your comment!');
+ if ($comment) {
+ $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)
{
$this->authorize('delete', $comment);
+ $this->commentService->deleteComment($comment);
- $comment->delete();
- $request->session()->flash('success', 'Comment deleted!');
-
- return redirect()->back();
-
+ return redirect()
+ ->back()
+ ->with('success', __('Comment deleted!'));
}
-
}
diff --git a/app/Http/Controllers/ContactController.php b/app/Http/Controllers/ContactController.php
old mode 100644
new mode 100755
index 7a2923f..b081aee
--- a/app/Http/Controllers/ContactController.php
+++ b/app/Http/Controllers/ContactController.php
@@ -1,65 +1,63 @@
.
+ */
+
namespace App\Http\Controllers;
-use Illuminate\Http\Request;
-use GuzzleHttp;
+use App\Exceptions\FailedCaptchaException;
use App\Notifications\NewContact;
-use Illuminate\Support\Facades\Http;
-
+use App\Services\ContactService;
use App\User;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Http;
class ContactController extends Controller
{
-
protected $users;
+ private $contactService;
- public function __construct(User $users)
+ public function __construct(User $users, ContactService $contactService)
{
+ $this->contactService = $contactService;
$this->users = $users;
}
-
public function create(Request $request)
{
- $name = $request->name;
- $email = $request->email;
- $subject = $request->subject;
- $msg = $request->msg;
+ try {
- $challenge = $request->input('captcha');
+ $email = $request->email;
+ $msg = $request->msg;
+ $challenge = $request->input('captcha');
- // TODO: now: add middleware for this verification, move to invisible captcha
- $verifyrequest = Http::asForm()->post(config('recaptcha.verify.apiurl'), [
- 'secret' => config('recaptcha.keys.secret'),
- 'response' => $challenge,
- 'remoteip' => $request->ip()
- ]);
+ $this->contactService->sendMessage($request->ip(), $msg, $email, $challenge);
+ return redirect()
+ ->back()
+ ->with('success',__('Message sent successfully! We usually respond within 48 hours.'));
- $response = json_decode($verifyrequest->getBody(), true);
-
- if (!$response['success'])
- {
- $request->session()->flash('error', 'Beep beep boop... Robot? Submission failed.');
- return redirect()->back();
+ } catch (FailedCaptchaException $ex) {
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
}
-
-
- foreach(User::all() as $user)
- {
- if ($user->hasRole('admin'))
- {
- $user->notify(new NewContact(collect([
- 'message' => $msg,
- 'ip' => $request->ip(),
- 'email' => $email
- ])));
- }
- }
-
- $request->session()->flash('success', 'Message sent successfully! We usually respond within 48 hours.');
- return redirect()->back();
}
}
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
old mode 100644
new mode 100755
index a0a2a8a..5f92f69
--- a/app/Http/Controllers/Controller.php
+++ b/app/Http/Controllers/Controller.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php
old mode 100644
new mode 100755
index d397d89..cb946e1
--- a/app/Http/Controllers/DashboardController.php
+++ b/app/Http/Controllers/DashboardController.php
@@ -1,31 +1,61 @@
.
+ */
+
namespace App\Http\Controllers;
-use Illuminate\Http\Request;
-use App\Vacancy;
-use App\User;
-use App\Ban;
use App\Application;
+use App\User;
+use App\Vacancy;
+use Illuminate\Support\Facades\Auth;
class DashboardController extends Controller
{
+ // Note: The dashboard doesn't need a service because it doesn't contain any significant business logic
public function index()
{
$totalPeerReview = Application::where('applicationStatus', 'STAGE_PEERAPPROVAL')->get()->count();
$totalNewApplications = Application::where('applicationStatus', 'STAGE_SUBMITTED')->get()->count();
$totalDenied = Application::where('applicationStatus', 'DENIED')->get()->count();
+ $vacancies = Vacancy::where('vacancyStatus', '<>', 'CLOSED')->get();
+
+ $totalDeniedSingle = Application::where([
+ ['applicationStatus', '=', 'DENIED'],
+ ['applicantUserID', '=', Auth::user()->id]
+ ])->get();
+
+ $totalNewSingle = Application::where([
+ ['applicationStatus', '=', 'STAGE_SUBMITTED'],
+ ['applicantUserID', '=', Auth::user()->id]
+ ])->get();
return view('dashboard.dashboard')
->with([
- 'vacancies' => Vacancy::all(),
- 'totalUserCount' => User::all()->count(),
- 'totalDenied' => $totalDenied,
- 'totalPeerReview' => $totalPeerReview,
- 'totalNewApplications' => $totalNewApplications
+ 'vacancies' => $vacancies,
+ 'totalUserCount' => User::all()->count(),
+ 'totalDenied' => $totalDenied,
+ 'totalPeerReview' => $totalPeerReview,
+ 'totalNewApplications' => $totalNewApplications,
+ 'totalNewSingle' => $totalNewSingle->count(),
+ 'totalDeniedSingle' => $totalDeniedSingle->count()
]);
-
}
-
}
diff --git a/app/Http/Controllers/DevToolsController.php b/app/Http/Controllers/DevToolsController.php
old mode 100644
new mode 100755
index 5c82d26..5badc77
--- a/app/Http/Controllers/DevToolsController.php
+++ b/app/Http/Controllers/DevToolsController.php
@@ -1,28 +1,45 @@
.
+ */
+
namespace App\Http\Controllers;
use App\Application;
use App\Events\ApplicationApprovedEvent;
use Illuminate\Http\Request;
-
use Illuminate\Support\Facades\Auth;
class DevToolsController extends Controller
{
-
// The use case for Laravel's gate and/or validation Requests is so tiny here that a full-blown policy would be overkill.
protected function isolatedAuthorise()
{
- if (!Auth::user()->can('admin.developertools.use'))
- {
- abort(403, 'You\'re not authorized to access this page.');
- }
+ if (! Auth::user()->can('admin.developertools.use')) {
+ abort(403, __('You\'re not authorized to access this page.'));
+ }
}
public function index()
{
$this->isolatedAuthorise();
+
return view('dashboard.administration.devtools')
->with('applications', Application::where('applicationStatus', 'STAGE_PEERAPPROVAL')->get());
}
@@ -32,15 +49,12 @@ class DevToolsController extends Controller
$this->isolatedAuthorise();
$application = Application::find($request->application);
- if (!is_null($application))
- {
+ if (! is_null($application)) {
event(new ApplicationApprovedEvent($application));
- $request->session()->flash('success', 'Event dispatched! Please check the debug logs for more info');
- }
- else
- {
- $request->session()->flash('error', 'Application doesn\'t exist!');
+ $request->session()->flash('success', __('Event dispatched! Please check the debug logs for more info'));
+ } else {
+ $request->session()->flash('error', __('Application doesn\'t exist!'));
}
return redirect()->back();
diff --git a/app/Http/Controllers/FormController.php b/app/Http/Controllers/FormController.php
old mode 100644
new mode 100755
index 27d40dd..366475f
--- a/app/Http/Controllers/FormController.php
+++ b/app/Http/Controllers/FormController.php
@@ -1,16 +1,40 @@
.
+ */
+
namespace App\Http\Controllers;
+use App\Exceptions\EmptyFormException;
+use App\Exceptions\FormHasConstraintsException;
use App\Form;
-use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Validator;
-use Illuminate\Support\Facades\Auth;
-
+use App\Services\FormManagementService;
use ContextAwareValidator;
+use Illuminate\Http\Request;
class FormController extends Controller
{
+ private $formService;
+
+ public function __construct(FormManagementService $formService) {
+ $this->formService = $formService;
+ }
public function index()
{
@@ -24,61 +48,52 @@ class FormController extends Controller
public function showFormBuilder()
{
$this->authorize('viewFormbuilder', Form::class);
+
return view('dashboard.administration.formbuilder');
}
public function saveForm(Request $request)
{
-
- $this->authorize('create', Form::class);
- $fields = $request->all();
-
- $contextValidation = ContextAwareValidator::getValidator($fields, true, true);
-
- if (!$contextValidation->get('validator')->fails())
+ try {
+ $form = $this->formService->addForm($request->all());
+ }
+ catch (EmptyFormException $ex)
{
- $storableFormStructure = $contextValidation->get('structure');
-
- Form::create(
- [
- 'formName' => $fields['formName'],
- 'formStructure' => $storableFormStructure,
- 'formStatus' => 'ACTIVE'
- ]
- );
-
- $request->session()->flash('success', 'Form created! You can now link this form to a vacancy.');
- return redirect()->to(route('showForms'));
+ return redirect()
+ ->back()
+ ->with('exception', $ex->getMessage());
}
- $request->session()->flash('errors', $contextValidation->get('validator')->errors()->getMessages());
- return redirect()->back();
+ // Form is boolean or array
+ if ($form)
+ {
+ return redirect()
+ ->back()
+ ->with('success', __('Form created!'));
+ }
+
+ return redirect()
+ ->back()
+ ->with('errors', $form);
}
public function destroy(Request $request, Form $form)
{
$this->authorize('delete', $form);
- $deletable = true;
+ try {
+ $this->formService->deleteForm($form);
+ return redirect()
+ ->back()
+ ->with('success', __('Form deleted successfuly'));
+
+ } catch (FormHasConstraintsException $ex) {
+
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
- if (!is_null($form) && !is_null($form->vacancies) && $form->vacancies->count() !== 0 || !is_null($form->responses))
- {
- $deletable = false;
}
-
- if ($deletable)
- {
- $form->delete();
-
- $request->session()->flash('success', 'Form deleted successfully.');
- }
- else
- {
- $request->session()->flash('error', 'You cannot delete this form because it\'s tied to one or more applications and ranks, or because it doesn\'t exist.');
- }
-
- return redirect()->back();
-
}
public function preview(Request $request, Form $form)
@@ -93,9 +108,9 @@ class FormController extends Controller
public function edit(Request $request, Form $form)
{
- $this->authorize('update', $form);
+ $this->authorize('update', $form);
- return view('dashboard.administration.editform')
+ return view('dashboard.administration.editform')
->with('formStructure', json_decode($form->formStructure, true))
->with('title', $form->formName)
->with('formID', $form->id);
@@ -103,29 +118,16 @@ class FormController extends Controller
public function update(Request $request, Form $form)
{
- $this->authorize('update', $form);
+ $this->authorize('update', $form);
+ $updatedForm = $this->formService->updateForm($form, $request->all());
- $contextValidation = ContextAwareValidator::getValidator($request->all(), true);
- $this->authorize('update', $form);
-
-
- if (!$contextValidation->get('validator')->fails())
- {
- // Add the new structure into the form. New, subsquent fields will be identified by the "new" prefix
- // This prefix doesn't actually change the app's behavior when it receives applications.
- // Additionally, old applications won't of course display new and updated fields, because we can't travel into the past and get data for them
- $form->formStructure = $contextValidation->get('structure');
- $form->save();
-
- $request->session()->flash('success', 'Hooray! Your form was updated. New applications for it\'s vacancy will use it.');
- }
- else
- {
- $request->session()->flash('errors', $contextValidation->get('validator')->errors()->getMessages());
- }
-
- return redirect()->to(route('previewForm', ['form' => $form->id]));
+ if ($updatedForm instanceof Form) {
+ return redirect()->to(route('previewForm', ['form' => $updatedForm->id]));
+ }
+ // array of errors
+ return redirect()
+ ->back()
+ ->with('errors', $updatedForm);
}
-
}
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
old mode 100644
new mode 100755
index 1afc222..9293dc9
--- a/app/Http/Controllers/HomeController.php
+++ b/app/Http/Controllers/HomeController.php
@@ -1,13 +1,32 @@
.
+ */
+
namespace App\Http\Controllers;
use App\Vacancy;
-use Illuminate\Http\Request;
-use Illuminate\Support\Facades\DB;
class HomeController extends Controller
{
+ // doesn't need a service, because it doesn't contain major logic.
+
/**
* Show the application dashboard.
*
@@ -15,12 +34,10 @@ class HomeController extends Controller
*/
public function index()
{
-
$positions = Vacancy::where('vacancyStatus', 'OPEN')
->where('vacancyCount', '<>', 0)
->get();
-
return view('home')
->with('positions', $positions);
}
diff --git a/app/Http/Controllers/OptionsController.php b/app/Http/Controllers/OptionsController.php
old mode 100644
new mode 100755
index c76a57c..10b03e7
--- a/app/Http/Controllers/OptionsController.php
+++ b/app/Http/Controllers/OptionsController.php
@@ -1,16 +1,45 @@
.
+ */
+
namespace App\Http\Controllers;
+use App\Exceptions\InvalidGamePreferenceException;
+use App\Exceptions\OptionNotFoundException;
use App\Facades\Options;
use App\Options as Option;
-
+use App\Services\ConfigurationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class OptionsController extends Controller
{
+ private $configurationService;
+
+ public function __construct(ConfigurationService $configurationService) {
+
+ $this->configurationService = $configurationService;
+
+ }
+
/**
* Display a listing of the resource.
*
@@ -18,60 +47,59 @@ class OptionsController extends Controller
*/
public function index()
{
- // TODO: Obtain this from the facade
- $options = Option::all();
-
-
+ // TODO: Replace with settings package
return view('dashboard.administration.settings')
- ->with('options', $options);
+ ->with([
+ 'options' => Options::getCategory('notifications'),
+ 'security' => [ // We could use the method above, but we need to set these names here for greater control in the template. This would nto be feasible for many options, we'd need to use a loop and the category method.
+ 'secPolicy' => Options::getOption('pw_security_policy'),
+ 'graceperiod' => Options::getOption('graceperiod'),
+ 'pwExpiry' => Options::getOption('password_expiry'),
+ 'requiresPMC' => Options::getOption('requireGameLicense'),
+ 'enforce2fa' => Options::getOption('force2fa')
+ ],
+ 'currentGame' => Options::getOption('currentGame')
+ ]);
}
- public function saveSettings(Request $request)
- {
- if (Auth::user()->can('admin.settings.edit'))
- {
- Log::debug('Updating application options', [
- 'ip' => $request->ip(),
- 'ua' => $request->userAgent(),
- 'username' => Auth::user()->username
- ]);
- foreach($request->all() as $optionName => $option)
- {
- try
- {
- Log::debug('Going through option ' . $optionName);
- if (Options::optionExists($optionName))
- {
- Log::debug('Option exists, updating to new values', [
- 'opt' => $optionName,
- 'new_value' => $option
- ]);
- Options::changeOption($optionName, $option);
- }
- }
- catch(\Exception $ex)
- {
- Log::error('Unable to update options!', [
- 'msg' => $ex->getMessage(),
- 'trace' => $ex->getTraceAsString()
- ]);
- report($ex);
+ public function saveSettings(Request $request): \Illuminate\Http\RedirectResponse
+ {
+ try {
- $errorCond = true;
- $request->session()->flash('error', 'An error occurred while trying to save settings: ' . $ex->getMessage());
- }
- }
+ if (Auth::user()->can('admin.settings.edit')) {
+ $this->configurationService->saveConfiguration($request->all());
- if (!isset($errorCond))
- {
- $request->session()->flash('success', 'Settings saved successfully!');
- }
- }
- else
- {
- $request->session()->flash('error', 'You do not have permission to update this resource.');
- }
+ return redirect()
+ ->back()
+ ->with('success', __('Options updated successfully!'));
+ }
- return redirect()->back();
- }
+ } catch (OptionNotFoundException | \Exception $ex) {
+
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
+
+ }
+
+ return redirect()
+ ->back()
+ ->with('error', __('You do not have permission to update this resource.'));
+ }
+
+ public function saveGameIntegration(Request $request)
+ {
+ try {
+
+ $this->configurationService->saveGameIntegration($request->gamePref);
+ return redirect()
+ ->back()
+ ->with('success', __('Game preference updated.'));
+
+ } catch (InvalidGamePreferenceException $ex) {
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
+ }
+ }
}
diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php
old mode 100644
new mode 100755
index 0fc063d..d77b028
--- a/app/Http/Controllers/ProfileController.php
+++ b/app/Http/Controllers/ProfileController.php
@@ -1,12 +1,30 @@
.
+ */
+
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 App\Http\Requests\ProfileSave;
+use App\Services\ProfileService;
+use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@@ -14,18 +32,22 @@ use Spatie\Permission\Models\Role;
class ProfileController extends Controller
{
+ private $profileService;
- public function index()
- {
+ public function __construct(ProfileService $profileService) {
+ $this->profileService = $profileService;
+ }
- return view('dashboard.user.directory')
+ public function index()
+ {
+ return view('dashboard.user.directory')
->with('users', User::with('profile', 'bans')->paginate(9));
- }
+ }
public function showProfile()
{
-
- $socialLinks = Auth::user()->profile->socialLinks ?? "[]";
+ // TODO: Come up with cleaner social media solution, e.g. social media object
+ $socialLinks = Auth::user()->profile->socialLinks ?? '[]';
$socialMediaProfiles = json_decode($socialLinks, true);
return view('dashboard.user.profile.userprofile')
@@ -36,13 +58,10 @@ class ProfileController extends Controller
'insta' => $socialMediaProfiles['links']['insta'] ?? 'UpdateMe',
'discord' => $socialMediaProfiles['links']['discord'] ?? 'UpdateMe#12345',
]);
-
}
- // Route model binding
- public function showSingleProfile(Request $request, User $user)
+ public function showSingleProfile(User $user)
{
-
$socialMediaProfiles = json_decode($user->profile->socialLinks, true);
$createdDate = Carbon::parse($user->created_at);
@@ -51,21 +70,26 @@ class ProfileController extends Controller
$roleList = [];
-
- foreach($systemRoles as $role)
- {
- if (in_array($role, $userRoles))
- {
- $roleList[$role] = true;
- }
- else
- {
- $roleList[$role] = false;
- }
+ 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'))
+ $suspensionInfo = null;
+ if ($user->isBanned())
{
+ $suspensionInfo = [
+
+ 'isPermanent' => $user->bans->isPermanent,
+ 'reason' => $user->bans->reason,
+ 'bannedUntil' => $user->bans->bannedUntil
+ ];
+ }
+
+ if (Auth::user()->is($user) || Auth::user()->can('profiles.view.others')) {
return view('dashboard.user.profile.displayprofile')
->with([
'profile' => $user->profile,
@@ -73,55 +97,21 @@ class ProfileController extends Controller
'twitter' => $socialMediaProfiles['links']['twitter'] ?? 'UpdateMe',
'insta' => $socialMediaProfiles['links']['insta'] ?? 'UpdateMe',
'discord' => $socialMediaProfiles['links']['discord'] ?? 'UpdateMe#12345',
- 'since' => $createdDate->englishMonth . " " . $createdDate->year,
+ 'since' => $createdDate->englishMonth.' '.$createdDate->year,
'ipInfo' => IP::lookup($user->originalIP),
- 'roles' => $roleList
+ 'roles' => $roleList,
+ 'suspensionInfo' => $suspensionInfo
]);
+ } else {
+ abort(403, __('You cannot view someone else\'s profile.'));
}
- else
- {
- abort(403, 'You cannot view someone else\'s profile.');
- }
-
}
public function saveProfile(ProfileSave $request)
{
- $profile = User::find(Auth::user()->id)->profile;
- $social = [];
-
- if (!is_null($profile))
- {
- switch ($request->avatarPref)
- {
- case 'MOJANG':
- $avatarPref = 'crafatar';
-
- break;
- case 'GRAVATAR':
- $avatarPref = strtolower($request->avatarPref);
-
- break;
- }
-
- $social['links']['github'] = $request->socialGithub;
- $social['links']['twitter'] = $request->socialTwitter;
- $social['links']['insta'] = $request->socialInsta;
- $social['links']['discord'] = $request->socialDiscord;
-
- $profile->profileShortBio = $request->shortBio;
- $profile->profileAboutMe = $request->aboutMe;
- $profile->avatarPreference = $avatarPref;
- $profile->socialLinks = json_encode($social);
-
- $newProfile = $profile->save();
-
- $request->session()->flash('success', 'Profile settings saved successfully.');
-
- }
-
- return redirect()->back();
-
+ $this->profileService->updateProfile(Auth::user()->id, $request);
+ return redirect()
+ ->back()
+ ->with('success', __('Profile updated.'));
}
-
}
diff --git a/app/Http/Controllers/ResponseController.php b/app/Http/Controllers/ResponseController.php
deleted file mode 100644
index 64037c9..0000000
--- a/app/Http/Controllers/ResponseController.php
+++ /dev/null
@@ -1,10 +0,0 @@
-securityService = $securityService;
+ }
+
+ public function save(SaveSecuritySettings $request)
+ {
+ $this->securityService->save($request->secPolicy, [
+ 'graceperiod' => $request->graceperiod,
+ 'pwExpiry' => $request->pwExpiry,
+ 'enforce2fa' => $request->enforce2fa,
+ 'requirePMC' => $request->requirePMC
+ ]);
+
+ return redirect()
+ ->back()
+ ->with('success', __('Settings saved.'));
+
+ }
+}
diff --git a/app/Http/Controllers/StaffProfileController.php b/app/Http/Controllers/StaffProfileController.php
deleted file mode 100644
index b20d4d1..0000000
--- a/app/Http/Controllers/StaffProfileController.php
+++ /dev/null
@@ -1,10 +0,0 @@
-.
+ */
+
+namespace App\Http\Controllers;
+
+use App\Exceptions\InvalidInviteException;
+use App\Exceptions\PublicTeamInviteException;
+use App\Exceptions\UserAlreadyInvitedException;
+use App\Http\Requests\EditTeamRequest;
+use App\Http\Requests\NewTeamRequest;
+use App\Http\Requests\SendInviteRequest;
+use App\Mail\InviteToTeam;
+use App\Services\TeamService;
+use App\Team;
+use App\User;
+use App\Vacancy;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Mail;
+use Mpociot\Teamwork\Exceptions\UserNotInTeamException;
+use Mpociot\Teamwork\Facades\Teamwork;
+use Mpociot\Teamwork\TeamInvite;
+
+class TeamController extends Controller
+{
+ private $teamService;
+
+ public function __construct(TeamService $teamService) {
+ $this->teamService = $teamService;
+ }
+
+ /**
+ * Display a listing of the resource.
+ *
+ */
+ public function index()
+ {
+ $this->authorize('index', Team::class);
+
+ $teams = Team::with('users.roles')->get();
+
+ return view('dashboard.teams.teams')
+ ->with('teams', $teams);
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ *
+ * @param NewTeamRequest $request
+ * @return RedirectResponse
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ */
+ public function store(NewTeamRequest $request)
+ {
+ $this->authorize('create', Team::class);
+ $this->teamService->createTeam($request->teamName, Auth::user()->id);
+
+ return redirect()
+ ->back()
+ ->with('success', __('Team successfully created.'));
+ }
+
+ /**
+ * Show the form for editing the specified resource.
+ *
+ * @param Team $team
+ * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\Response
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ */
+ public function edit(Team $team)
+ {
+ $this->authorize('update', $team);
+ return view('dashboard.teams.edit-team')
+ ->with([
+ 'team' => $team,
+ 'users' => User::all(),
+ 'vacancies' => Vacancy::with('teams')->get()->all()
+ ]);
+ }
+
+ /**
+ * Update the specified resource in storage.
+ *
+ * @param EditTeamRequest $request
+ * @param Team $team
+ * @return RedirectResponse
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ */
+ public function update(EditTeamRequest $request, Team $team): RedirectResponse
+ {
+ $this->authorize('update', $team);
+ $team = $this->teamService->updateTeam($team, $request->teamDescription, $request->joinType);
+
+
+ if ($team) {
+ return redirect()
+ ->to(route('teams.index'))
+ ->with('success', __('Team updated.'));
+ }
+
+ return redirect()
+ ->back()
+ ->with('error', __('An error ocurred while trying to update this team.'));
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ *
+ * @param int $id
+ * @return \Illuminate\Http\Response
+ */
+ public function destroy($id)
+ {
+ // wip
+ }
+
+ public function invite(SendInviteRequest $request, Team $team): RedirectResponse
+ {
+ $this->authorize('invite', $team);
+
+ try {
+
+ $this->teamService->inviteUser($team, $request->user);
+
+ return redirect()
+ ->back()
+ ->with('success', __('User invited successfully!'));
+
+ } catch (UserAlreadyInvitedException | PublicTeamInviteException $ex) {
+ return redirect()
+ ->back()
+ ->with('error', $ex->getMessage());
+ }
+ }
+
+ public function processInviteAction(Request $request, $action, $token): RedirectResponse
+ {
+ try {
+
+ $this->teamService->processInvite(Auth::user(), $action, $token);
+
+ return redirect()
+ ->to(route('teams.index'))
+ ->with('success', __('Invite processed successfully!'));
+
+ } catch (InvalidInviteException $e) {
+
+ return redirect()
+ ->back()
+ ->with('error', $e->getMessage());
+
+ }
+ }
+
+ public function switchTeam(Request $request, Team $team): RedirectResponse
+ {
+ $this->authorize('switchTeam', $team);
+
+ try {
+ Auth::user()->switchTeam($team);
+
+ $request->session()->flash('success', __('Switched teams! Your team dashboard will now use this context.'));
+ } catch (UserNotInTeamException $ex) {
+ $request->session()->flash('error', __('You can\'t switch to a team you don\'t belong to.'));
+ }
+
+ return redirect()->back();
+ }
+
+ // Since it's a separate form, we shouldn't use the same update method
+ public function assignVacancies(Request $request, Team $team): RedirectResponse
+ {
+ $this->authorize('update', $team);
+ $message = $this->teamService->updateVacancies($team, $request->assocVacancies);
+
+ return redirect()
+ ->back()
+ ->with('success', $message);
+ }
+}
diff --git a/app/Http/Controllers/TeamFileController.php b/app/Http/Controllers/TeamFileController.php
new file mode 100755
index 0000000..30c5994
--- /dev/null
+++ b/app/Http/Controllers/TeamFileController.php
@@ -0,0 +1,141 @@
+fileService = $fileService;
+ }
+
+ /**
+ * Display a listing of the resource.
+ *
+ * @param Request $request
+ */
+ public function index(Request $request)
+ {
+ $this->authorize('index', TeamFile::class);
+
+ if (is_null(Auth::user()->currentTeam))
+ {
+ $request->session()->flash('error', 'Please choose a team before viewing it\'s files.');
+ return redirect()->to(route('teams.index'));
+ }
+
+ return view('dashboard.teams.team-files')
+ ->with('files', TeamFile::with('team', 'uploader')->paginate(6));
+ }
+
+
+ /**
+ * Store a newly created resource in storage.
+ *
+ * @param UploadFileRequest $request
+ * @return RedirectResponse
+ */
+ public function store(UploadFileRequest $request)
+ {
+ $this->authorize('store', TeamFile::class);
+
+ if (config('demo.is_enabled'))
+ {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
+
+ try {
+ $caption = $request->caption;
+ $description = $request->description;
+
+ $this->fileService->addFile($request->file('file'), Auth::user()->id, Auth::user()->currentTeam->id, $caption, $description);
+
+ return redirect()
+ ->back()
+ ->with('success', __('File uploaded successfully.'));
+
+ } catch (FileUploadException $uploadException) {
+
+ return redirect()
+ ->back()
+ ->with('error', $uploadException->getMessage());
+
+ }
+
+ }
+
+
+ public function download(Request $request, TeamFile $teamFile)
+ {
+ $this->authorize('download', TeamFile::class);
+
+ try
+ {
+ return Storage::download($teamFile->fs_location, $teamFile->name);
+ }
+ catch (FileNotFoundException $ex)
+ {
+ $request->session()->flash('error', 'Sorry, but the requested file could not be found in storage. Sometimes, files may be physically deleted by admins, but not from the app\'s database.');
+ return redirect()->back();
+
+ }
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ *
+ * @param Request $request
+ * @param \App\TeamFile $teamFile
+ * @return RedirectResponse
+ */
+ public function destroy(Request $request, TeamFile $teamFile)
+ {
+ $this->authorize('delete', $teamFile);
+
+ if (config('demo.is_enabled'))
+ {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
+
+ try
+ {
+ Storage::delete($teamFile->fs_location);
+ $teamFile->delete();
+
+ $request->session()->flash('success', __('File deleted successfully.'));
+ }
+ catch (\Exception $ex)
+ {
+ $request->session()->flash('error', __('There was an error deleting the file: :msg', ['msg' => $ex->getMessage()]));
+ }
+
+ return redirect()->back();
+ }
+}
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
old mode 100644
new mode 100755
index cb494b6..2f0d2f4
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -1,33 +1,50 @@
.
+ */
+
namespace App\Http\Controllers;
+use App\Ban;
+use App\Http\Requests\Add2FASecretRequest;
use App\Http\Requests\ChangeEmailRequest;
use App\Http\Requests\ChangePasswordRequest;
-use App\Http\Requests\FlushSessionsRequest;
use App\Http\Requests\DeleteUserRequest;
+use App\Http\Requests\FlushSessionsRequest;
+use App\Http\Requests\Remove2FASecretRequest;
use App\Http\Requests\SearchPlayerRequest;
use App\Http\Requests\UpdateUserRequest;
-use App\Http\Requests\Add2FASecretRequest;
-use App\Http\Requests\Remove2FASecretRequest;
-
+use App\Notifications\ChangedPassword;
+use App\Notifications\EmailChanged;
+use App\Traits\DisablesFeatures;
+use App\Traits\ReceivesAccountTokens;
use App\User;
-use App\Ban;
-
+use Google2FA;
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;
-use Google2FA;
-
class UserController extends Controller
{
-
+ use ReceivesAccountTokens;
public function showStaffMembers()
{
@@ -36,24 +53,20 @@ class UserController extends Controller
$staffRoles = [
'reviewer',
'hiringManager',
- 'admin'
+ 'admin',
]; // TODO: Un-hardcode this, move to config/roles.php
$users = User::with('roles')->get();
$staffMembers = collect([]);
- foreach($users as $user)
- {
- if (empty($user->roles))
- {
+ 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))
- {
+ 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
}
@@ -62,7 +75,7 @@ class UserController extends Controller
return view('dashboard.administration.staff-members')
->with([
- 'users' => $staffMembers
+ 'users' => $staffMembers,
]);
}
@@ -73,11 +86,9 @@ class UserController extends Controller
$users = User::with('roles')->get();
$players = collect([]);
- foreach($users as $user)
- {
+ foreach ($users as $user) {
// TODO: Might be problematic if we don't check if the role is user
- if (count($user->roles) == 1)
- {
+ if (count($user->roles) == 1) {
$players->push($user);
}
}
@@ -85,11 +96,10 @@ class UserController extends Controller
return view('dashboard.administration.players')
->with([
'users' => $players,
- 'bannedUserCount' => Ban::all()->count()
+ 'bannedUserCount' => Ban::all()->count(),
]);
}
-
public function showPlayersLike(SearchPlayerRequest $request)
{
$this->authorize('viewPlayers', User::class);
@@ -100,18 +110,17 @@ class UserController extends Controller
->orWhere('email', 'LIKE', "%{$searchTerm}%")
->get();
- if (!$matchingUsers->isEmpty())
- { $request->session()->flash('success', 'There were ' . $matchingUsers->count() . ' user(s) matching your search.');
+ if (! $matchingUsers->isEmpty()) {
+ $request->session()->flash('success', __('There were :usersCount user(s) matching your search.', ['usersCount' => $matchingUsers->count()]));
return view('dashboard.administration.players')
->with([
'users' => $matchingUsers,
- 'bannedUserCount' => Ban::all()->count()
+ 'bannedUserCount' => Ban::all()->count(),
]);
- }
- else
- {
- $request->session()->flash('error', 'Your search term did not return any results.');
+ } else {
+ $request->session()->flash('error', __('Your search term did not return any results.'));
+
return redirect(route('registeredPlayerList'));
}
}
@@ -120,14 +129,10 @@ class UserController extends Controller
{
$QRCode = null;
- if (!$request->user()->has2FA())
- {
- if ($request->session()->has('twofaAttemptFailed'))
- {
+ if (! $request->user()->has2FA()) {
+ if ($request->session()->has('twofaAttemptFailed')) {
$twoFactorSecret = $request->session()->get('current2FA');
- }
- else
- {
+ } else {
$twoFactorSecret = Google2FA::generateSecretKey(32, '');
$request->session()->put('current2FA', $twoFactorSecret);
}
@@ -144,169 +149,177 @@ class UserController extends Controller
->with('twofaQRCode', $QRCode);
}
-
public function flushSessions(FlushSessionsRequest $request)
{
// TODO: Move all log calls to a listener, which binds to an event fired by each significant event, such as this one
// This will allow for other actions to be performed on certain events (like login failed event)
Auth::logoutOtherDevices($request->currentPasswordFlush);
- Log::notice('User ' . Auth::user()->name . ' has logged out other devices in their account',
+ Log::notice('User '.Auth::user()->name.' has logged out other devices in their account',
[
'originIPAddress' => $request->ip(),
'userID' => Auth::user()->id,
- 'timestamp' => now()
+ 'timestamp' => now(),
]);
- $request->session()->flash('success', 'Successfully logged out other devices. Remember to change your password if you think you\'ve been compromised.');
+ $request->session()->flash('success', __('Successfully logged out other devices. Remember to change your password if you think you\'ve been compromised.'));
+
return redirect()->back();
}
public function changePassword(ChangePasswordRequest $request)
{
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
$user = User::find(Auth::user()->id);
- if (!is_null($user))
- {
+ if (! is_null($user)) {
$user->password = Hash::make($request->newPassword);
+ $user->password_last_updated = now();
+
$user->save();
- Log::info('User ' . $user->name . ' has changed their password', [
+ Log::info('User '.$user->name.' has changed their password', [
'originIPAddress' => $request->ip(),
'userID' => $user->id,
- 'timestamp' => now()
+ 'timestamp' => now(),
]);
$user->notify(new ChangedPassword());
Auth::logout();
+
return redirect()->back();
}
-
}
public function changeEmail(ChangeEmailRequest $request)
{
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
+
$user = User::find(Auth::user()->id);
- if (!is_null($user))
- {
+ if (! is_null($user)) {
$user->email = $request->newEmail;
$user->save();
- Log::notice('User ' . $user->name . ' has just changed their contact email address', [
+ Log::notice('User '.$user->name.' has just changed their contact email address', [
'originIPAddress' => $request->ip(),
'userID' => $user->id,
- 'timestamp' => now()
+ 'timestamp' => now(),
]);
$user->notify(new EmailChanged());
- $request->session()->flash('success', 'Your email address has been changed!');
- }
- else
- {
- $request->session()->flash('error', 'There has been an error whilst trying to update your account. Please contact administrators.');
+ $request->session()->flash('success', __('Your email address has been changed!'));
+ } else {
+ $request->session()->flash('error', __('There has been an error whilst trying to update your account. Please contact administrators.'));
}
return redirect()->back();
-
}
-
-
public function delete(DeleteUserRequest $request, User $user)
{
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
$this->authorize('delete', $user);
- if ($request->confirmPrompt == 'DELETE ACCOUNT')
- {
- $user->delete();
- $request->session()->flash('success','User deleted successfully. PII has been erased.');
+ if ($request->confirmPrompt == 'DELETE ACCOUNT') {
+ $user->forceDelete();
+ $request->session()->flash('success', __('User deleted successfully.'));
+ } else {
+ $request->session()->flash('error', __('Wrong confirmation text! Try again.'));
}
- else
- {
- $request->session()->flash('error', 'Wrong confirmation text! Try again.');
- }
-
return redirect()->route('registeredPlayerList');
}
public function update(UpdateUserRequest $request, User $user)
{
-
- $this->authorize('adminEdit', $user);
-
- // Mass update would not be possible here without extra code, making route model binding useless
- $user->email = $request->email;
- $user->name = $request->name;
- $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);
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
}
- }
+ $this->authorize('adminEdit', $user);
- foreach($request->roles as $role)
- {
- if (!$user->hasRole($role))
- {
- $user->assignRole($role);
+ // 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();
+ $user->save();
+ $request->session()->flash('success', __('User updated successfully!'));
+ return redirect()->back();
}
public function add2FASecret(Add2FASecretRequest $request)
{
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
+
$currentSecret = $request->session()->get('current2FA');
$isValid = Google2FA::verifyKey($currentSecret, $request->otp);
- if ($isValid)
- {
- $request->user()->twofa_secret = $currentSecret;
- $request->user()->save();
+ if ($isValid) {
+ $request->user()->twofa_secret = $currentSecret;
+ $request->user()->save();
- Log::warning('SECURITY: User activated two-factor authentication', [
- 'initiator' => $request->user()->email,
- 'ip' => $request->ip()
- ]);
+ Log::warning('SECURITY: User activated two-factor authentication', [
+ 'initiator' => $request->user()->email,
+ 'ip' => $request->ip(),
+ ]);
- Google2FA::login();
+ Google2FA::login();
- Log::warning('SECURITY: Started two factor session automatically', [
- 'initiator' => $request->user()->email,
- 'ip' => $request->ip()
- ]);
+ Log::warning('SECURITY: Started two factor session automatically', [
+ 'initiator' => $request->user()->email,
+ 'ip' => $request->ip(),
+ ]);
- $request->session()->forget('current2FA');
+ $request->session()->forget('current2FA');
- if ($request->session()->has('twofaAttemptFailed'))
- $request->session()->forget('twofaAttemptFailed');
+ if ($request->session()->has('twofaAttemptFailed')) {
+ $request->session()->forget('twofaAttemptFailed');
+ }
-
- $request->session()->flash('success', '2FA succesfully enabled! You\'ll now be prompted for an OTP each time you log in.');
- }
- else
- {
- $request->session()->flash('error', 'Incorrect code. Please reopen the 2FA settings panel and try again.');
- $request->session()->put('twofaAttemptFailed', true);
+ $request->session()->flash('success', __('2FA succesfully enabled! You\'ll now be prompted for an OTP each time you log in.'));
+ } else {
+ $request->session()->flash('error', __('Incorrect code. Please reopen the 2FA settings panel and try again.'));
+ $request->session()->put('twofaAttemptFailed', true);
}
return redirect()->back();
@@ -315,43 +328,44 @@ class UserController extends Controller
public function remove2FASecret(Remove2FASecretRequest $request)
{
Log::warning('SECURITY: Disabling two factor authentication (user initiated)', [
- 'initiator' => $request->user()->email,
- 'ip' => $request->ip()
+ 'initiator' => $request->user()->email,
+ 'ip' => $request->ip(),
]);
$request->user()->twofa_secret = null;
$request->user()->save();
- $request->session()->flash('success', 'Two-factor authentication disabled.');
+ $request->session()->flash('success', __('Two-factor authentication disabled.'));
+
return redirect()->back();
}
-
-
-
public function terminate(Request $request, User $user)
{
$this->authorize('terminate', User::class);
+ if (config('demo.is_enabled')) {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
// TODO: move logic to policy
- if (!$user->isStaffMember() || $user->is(Auth::user()))
- {
- $request->session()->flash('error', 'You cannot terminate this 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;
- }
+ foreach ($user->roles as $role) {
+ if ($role->name == 'user') {
+ continue;
+ }
- $user->removeRole($role->name);
+ $user->removeRole($role->name);
}
- Log::info('User ' . $user->name . ' has just been demoted.');
- $request->session()->flash('success', 'User terminated successfully.');
+ Log::info('User '.$user->name.' has just been demoted.');
+ $request->session()->flash('success', __('User terminated successfully.'));
//TODO: Dispatch event
return redirect()->back();
diff --git a/app/Http/Controllers/VacancyController.php b/app/Http/Controllers/VacancyController.php
old mode 100644
new mode 100755
index fdb5ce0..64e1864
--- a/app/Http/Controllers/VacancyController.php
+++ b/app/Http/Controllers/VacancyController.php
@@ -1,45 +1,64 @@
.
+ */
+
namespace App\Http\Controllers;
-use App\Http\Requests\VacancyRequest;
-use App\Http\Requests\VacancyEditRequest;
-
-use App\Vacancy;
-use App\User;
+use App\Facades\JSON;
use App\Form;
-
+use App\Http\Requests\VacancyEditRequest;
+use App\Http\Requests\VacancyRequest;
use App\Notifications\VacancyClosed;
-
+use App\User;
+use App\Vacancy;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
-use Illuminate\Support\Facades\Auth;
-
class VacancyController extends Controller
{
public function index()
{
- $this->authorize('viewAny', Vacancy::class);
+ $this->authorize('viewAny', Vacancy::class);
+
return view('dashboard.administration.positions')
->with([
'forms' => Form::all(),
- 'vacancies' => Vacancy::all()
+ 'vacancies' => Vacancy::all(),
]);
}
public function store(VacancyRequest $request)
{
+ $messageIsError = false;
$this->authorize('create', Vacancy::class);
+
+
+
$form = Form::find($request->vacancyFormID);
- if (!is_null($form))
- {
- /* note: since we can't convert HTML back to Markdown, we'll have to do the converting when the user requests a page,
- * and leave the database with Markdown only so it can be used and edited everywhere.
- * for several vacancies, this would require looping through all of them and replacing MD with HTML, which is obviously not the most clean solution;
- * however, the Model can be configured to return MD instead of HTML on that specific field saving us from looping.
- */
+ if (! is_null($form)) {
+ /* note: since we can't convert HTML back to Markdown, we'll have to do the converting when the user requests a page,
+ * and leave the database with Markdown only so it can be used and edited everywhere.
+ * for several vacancies, this would require looping through all of them and replacing MD with HTML, which is obviously not the most clean solution;
+ * however, the Model can be configured to return MD instead of HTML on that specific field saving us from looping.
+ */
Vacancy::create([
'vacancyName' => $request->vacancyName,
@@ -49,90 +68,83 @@ class VacancyController extends Controller
'permissionGroupName' => $request->permissionGroup,
'discordRoleID' => $request->discordRole,
'vacancyFormID' => $request->vacancyFormID,
- 'vacancyCount' => $request->vacancyCount
+ 'vacancyCount' => $request->vacancyCount,
]);
- $request->session()->flash('success', 'Vacancy successfully opened. It will now show in the home page.');
- }
- else
- {
- $request->session()->flash('error', 'You cannot create a vacancy without a valid form.');
+ $message = __('Vacancy successfully opened. It will now show in the home page.');
+
+ } else {
+ $message = __('You cannot create a vacancy without a valid form.');
+ $messageIsError = true;
}
- return redirect()->back();
-
+ return redirect()
+ ->back()
+ ->with(($messageIsError) ? 'error' : 'success', $message);
}
public function updatePositionAvailability(Request $request, $status, Vacancy $vacancy)
{
-
$this->authorize('update', $vacancy);
- if (!is_null($vacancy))
- {
+ if (! is_null($vacancy)) {
$type = 'success';
- switch ($status)
- {
+ switch ($status) {
case 'open':
$vacancy->open();
- $message = "Position successfully opened!";
+ $message = __('Position successfully opened!');
break;
case 'close':
$vacancy->close();
- $message = "Position successfully closed!";
+ $message = __('Position successfully closed!');
- foreach(User::all() as $user)
- {
- if ($user->isStaffMember())
- {
- $user->notify(new VacancyClosed($vacancy));
- }
+ foreach (User::all() as $user) {
+ if ($user->isStaffMember()) {
+ $user->notify(new VacancyClosed($vacancy));
+ }
}
break;
default:
- $message = "Please do not tamper with the button's URLs. To report a bug, please contact an administrator.";
+ $message = __("Please do not tamper with the URLs. To report a bug, please contact an administrator.");
$type = 'error';
}
- }
- else
- {
- $message = "The position you're trying to update doesn't exist!";
- $type = "error";
+ } else {
+ $message = __("The position you're trying to update doesn't exist!");
+ $type = 'error';
}
- $request->session()->flash($type, $message);
- return redirect()->back();
+ return redirect()
+ ->back()
+ ->with($type, $message);
+
}
-
public function edit(Request $request, Vacancy $vacancy)
{
- $this->authorize('update', $vacancy);
+ $this->authorize('update', $vacancy);
+
return view('dashboard.administration.editposition')
->with('vacancy', $vacancy);
}
-
-
public function update(VacancyEditRequest $request, Vacancy $vacancy)
{
- $this->authorize('update', $vacancy);
+ $this->authorize('update', $vacancy);
- $vacancy->vacancyFullDescription = $request->vacancyFullDescription;
- $vacancy->vacancyDescription = $request->vacancyDescription;
- $vacancy->vacancyCount = $request->vacancyCount;
+ $vacancy->vacancyFullDescription = $request->vacancyFullDescription;
+ $vacancy->vacancyDescription = $request->vacancyDescription;
+ $vacancy->vacancyCount = $request->vacancyCount;
- $vacancy->save();
-
- $request->session()->flash('success', 'Vacancy successfully updated.');
- return redirect()->back();
+ $vacancy->save();
+ return redirect()
+ ->back()
+ ->with('success', __('Vacancy successfully updated.'));
}
-
}
diff --git a/app/Http/Controllers/VoteController.php b/app/Http/Controllers/VoteController.php
old mode 100644
new mode 100755
index eba3ae1..e2d3bf2
--- a/app/Http/Controllers/VoteController.php
+++ b/app/Http/Controllers/VoteController.php
@@ -1,18 +1,34 @@
.
+ */
+
namespace App\Http\Controllers;
use App\Application;
use App\Http\Requests\VoteRequest;
-use App\Jobs\ProcessVoteList;
use App\Vote;
-use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class VoteController extends Controller
{
-
public function vote(VoteRequest $voteRequest, Application $application)
{
$this->authorize('create', Vote::class);
@@ -23,11 +39,10 @@ class VoteController extends Controller
]);
$vote->application()->attach($application->id);
-
- Log::info('User ' . Auth::user()->name . ' has voted in applicant ' . $application->user->name . '\'s application', [
- 'voteType' => $voteRequest->voteType
+ Log::info('User '.Auth::user()->name.' has voted in applicant '.$application->user->name.'\'s application', [
+ 'voteType' => $voteRequest->voteType,
]);
- $voteRequest->session()->flash('success', 'Your vote has been registered!');
+ $voteRequest->session()->flash('success', __('Your vote has been counted!'));
// Cron job will run command that processes votes
return redirect()->back();
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
old mode 100644
new mode 100755
index 9a2a7f5..634033c
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -1,7 +1,27 @@
.
+ */
+
namespace App\Http;
+use App\Http\Middleware\APIAuthenticationMiddleware;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
@@ -41,6 +61,7 @@ class Kernel extends HttpKernel
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
+ APIAuthenticationMiddleware::class
],
];
@@ -66,10 +87,12 @@ class Kernel extends HttpKernel
'usernameUUID' => \App\Http\Middleware\UsernameUUID::class,
'forcelogout' => \App\Http\Middleware\ForceLogoutMiddleware::class,
'2fa' => \PragmaRX\Google2FALaravel\Middleware::class,
+ 'passwordexpiration' => \App\Http\Middleware\PasswordExpirationMiddleware::class,
+ 'passwordredirect' => \App\Http\Middleware\PasswordExpirationRedirectMiddleware::class,
'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
'localizationRedirect' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
'localeCookieRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
- 'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
+ 'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class,
];
}
diff --git a/app/Http/Middleware/APIAuthenticationMiddleware.php b/app/Http/Middleware/APIAuthenticationMiddleware.php
new file mode 100644
index 0000000..866fd83
--- /dev/null
+++ b/app/Http/Middleware/APIAuthenticationMiddleware.php
@@ -0,0 +1,65 @@
+bearerToken();
+
+ if (!is_null($key))
+ {
+ // we have a valid discriminator
+ $discriminator = Str::before($key, '.');
+ $loneKey = Str::after($key, '.');
+
+ $keyRecord = ApiKey::where('discriminator', $discriminator)->first();
+
+ if ($keyRecord && Hash::check($loneKey, $keyRecord->secret) && $keyRecord->status == 'active')
+ {
+ $keyRecord->last_used = Carbon::now();
+ $keyRecord->save();
+
+ Log::info('Recording API call, see context', [
+ 'uri' => $request->url(),
+ 'name' => Route::currentRouteName(),
+ 'discriminator' => $discriminator,
+ 'ip' => $request->ip()
+ ]);
+
+ return $next($request);
+ }
+
+ return JSON::setResponseType('error')
+ ->setStatus('authfail')
+ ->setMessage('Invalid / Revoked API key.')
+ ->setCode(401)
+ ->build();
+ }
+
+ return JSON::setResponseType('error')
+ ->setStatus('malformed_key')
+ ->setMessage('Missing or malformed API key.')
+ ->setCode(400)
+ ->build();
+
+ }
+}
diff --git a/app/Http/Middleware/ApplicationEligibility.php b/app/Http/Middleware/ApplicationEligibility.php
old mode 100644
new mode 100755
index f091d8e..13cb1da
--- a/app/Http/Middleware/ApplicationEligibility.php
+++ b/app/Http/Middleware/ApplicationEligibility.php
@@ -1,12 +1,31 @@
.
+ */
+
namespace App\Http\Middleware;
use App\Application;
-use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use Closure;
use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\View;
class ApplicationEligibility
@@ -23,37 +42,29 @@ class ApplicationEligibility
{
$curtime = new Carbon(now());
-
- if (Auth::check())
- {
+ if (Auth::check()) {
$applications = Application::where('applicantUserID', Auth::user()->id)->get();
$eligible = true;
$daysRemaining = 0;
- if (!$applications->isEmpty())
- {
- foreach ($applications as $application)
- {
+ if (! $applications->isEmpty()) {
+ foreach ($applications as $application) {
$appTime = Carbon::parse($application->created_at);
- if ($appTime->isSameMonth($curtime))
- {
-
- Log::warning('Notice: Application ID ' . $application->id . ' was found to be in the same month as today\'s time, making the user ' . Auth::user()->name . ' ineligible for application');
+ if ($appTime->isSameMonth($curtime)) {
+ Log::warning('Notice: Application ID '.$application->id.' was found to be in the same month as today\'s time, making the user '.Auth::user()->name.' ineligible for application');
$eligible = false;
}
}
$allowedTime = Carbon::parse($applications->last()->created_at)->addMonth();
$daysRemaining = $allowedTime->diffInDays(now());
-
}
View::share('isEligibleForApplication', $eligible);
View::share('eligibilityDaysRemaining', $daysRemaining);
}
-
return $next($request);
}
}
diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php
old mode 100644
new mode 100755
index 704089a..af34268
--- a/app/Http/Middleware/Authenticate.php
+++ b/app/Http/Middleware/Authenticate.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
diff --git a/app/Http/Middleware/Bancheck.php b/app/Http/Middleware/Bancheck.php
old mode 100644
new mode 100755
index 0eca7f7..6c8a8ef
--- a/app/Http/Middleware/Bancheck.php
+++ b/app/Http/Middleware/Bancheck.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Closure;
@@ -20,17 +39,11 @@ class Bancheck
$userIP = $request->ip();
$anonymousUser = User::where('ipAddress', $userIP)->get();
-
- if (Auth::check() && Auth::user()->isBanned())
- {
+ if (Auth::check() && Auth::user()->isBanned()) {
View::share('isBanned', true);
- }
- elseif(!$anonymousUser->isEmpty() && User::find($anonymousUser->id)->isBanned())
- {
+ } elseif (! $anonymousUser->isEmpty() && User::find($anonymousUser->id)->isBanned()) {
View::share('isBanned', true);
- }
- else
- {
+ } else {
View::share('isBanned', false);
}
diff --git a/app/Http/Middleware/CheckForMaintenanceMode.php b/app/Http/Middleware/CheckForMaintenanceMode.php
old mode 100644
new mode 100755
index 35b9824..c58ffff
--- a/app/Http/Middleware/CheckForMaintenanceMode.php
+++ b/app/Http/Middleware/CheckForMaintenanceMode.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php
old mode 100644
new mode 100755
index 033136a..140dd8d
--- a/app/Http/Middleware/EncryptCookies.php
+++ b/app/Http/Middleware/EncryptCookies.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
diff --git a/app/Http/Middleware/ForceLogoutMiddleware.php b/app/Http/Middleware/ForceLogoutMiddleware.php
old mode 100644
new mode 100755
index 551c287..7501cdd
--- a/app/Http/Middleware/ForceLogoutMiddleware.php
+++ b/app/Http/Middleware/ForceLogoutMiddleware.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Closure;
@@ -16,11 +35,11 @@ class ForceLogoutMiddleware
*/
public function handle($request, Closure $next)
{
- if (Auth::user()->isBanned())
- {
+ 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('/');
}
diff --git a/app/Http/Middleware/IPHistoryMiddleware.php b/app/Http/Middleware/IPHistoryMiddleware.php
new file mode 100644
index 0000000..eecadbf
--- /dev/null
+++ b/app/Http/Middleware/IPHistoryMiddleware.php
@@ -0,0 +1,21 @@
+password_last_updated)->diffInDays(now());
+ $updateThreshold = Options::getOption('password_expiry');
+
+ if ($updateThreshold !== 0 && $sinceUpdate > $updateThreshold)
+ {
+ session()->put('passwordExpired', true);
+ }
+ else
+ {
+ session()->put('passwordExpired', false);
+ }
+
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/PasswordExpirationRedirectMiddleware.php b/app/Http/Middleware/PasswordExpirationRedirectMiddleware.php
new file mode 100644
index 0000000..b4a687f
--- /dev/null
+++ b/app/Http/Middleware/PasswordExpirationRedirectMiddleware.php
@@ -0,0 +1,28 @@
+.
+ */
+
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php
old mode 100644
new mode 100755
index 5a50e7b..1698610
--- a/app/Http/Middleware/TrimStrings.php
+++ b/app/Http/Middleware/TrimStrings.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php
old mode 100644
new mode 100755
index 085cdb5..785351e
--- a/app/Http/Middleware/TrustProxies.php
+++ b/app/Http/Middleware/TrustProxies.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
@@ -12,7 +31,7 @@ class TrustProxies extends Middleware
*
* @var array|string
*/
- protected $proxies = "*";
+ protected $proxies = '*';
/**
* The headers that should be used to detect proxies.
diff --git a/app/Http/Middleware/UsernameUUID.php b/app/Http/Middleware/UsernameUUID.php
old mode 100644
new mode 100755
index 29a93cf..32c8a8e
--- a/app/Http/Middleware/UsernameUUID.php
+++ b/app/Http/Middleware/UsernameUUID.php
@@ -1,15 +1,33 @@
.
+ */
+
namespace App\Http\Middleware;
-use Closure;
use App\Facades\UUID;
-use Illuminate\Support\Facades\Http;
+use Closure;
class UsernameUUID
{
/**
- * Converts a Minecraft username found in the request body to a UUID
+ * Converts a Minecraft username found in the request body to a UUID.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
@@ -18,23 +36,21 @@ class UsernameUUID
public function handle($request, Closure $next)
{
$input = $request->all();
- if (isset($input['uuid']))
- {
- try
- {
- $username = $input['uuid'];
- $input['uuid'] = UUID::toUUID($username);
- }
- catch(\InvalidArgumentException $iae)
- {
+ if (isset($input['uuid'])) {
+ try {
+ $username = $input['uuid'];
+ $input['uuid'] = UUID::toUUID($username);
+ } catch (\InvalidArgumentException $iae) {
report($iae);
$request->session()->flash('error', $iae->getMessage());
+
return redirect(route('register'));
}
$request->replace($input);
}
+
return $next($request);
}
}
diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php
old mode 100644
new mode 100755
index 0c13b85..0b6761a
--- a/app/Http/Middleware/VerifyCsrfToken.php
+++ b/app/Http/Middleware/VerifyCsrfToken.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
diff --git a/app/Http/Requests/Add2FASecretRequest.php b/app/Http/Requests/Add2FASecretRequest.php
old mode 100644
new mode 100755
index 13fa9dd..f1b2ca4
--- a/app/Http/Requests/Add2FASecretRequest.php
+++ b/app/Http/Requests/Add2FASecretRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -13,7 +32,7 @@ class Add2FASecretRequest extends FormRequest
*/
public function authorize()
{
- // current logic only updates currently authenticated user
+ // current logic only updates currently authenticated user
return true;
}
@@ -25,7 +44,7 @@ class Add2FASecretRequest extends FormRequest
public function rules()
{
return [
- 'otp' => 'required|string|min:6|max:6'
+ 'otp' => 'required|string|min:6|max:6',
];
}
}
diff --git a/app/Http/Requests/BanUserRequest.php b/app/Http/Requests/BanUserRequest.php
old mode 100644
new mode 100755
index ba25c34..943bd90
--- a/app/Http/Requests/BanUserRequest.php
+++ b/app/Http/Requests/BanUserRequest.php
@@ -1,11 +1,29 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
-
class BanUserRequest extends FormRequest
{
/**
@@ -27,8 +45,15 @@ class BanUserRequest extends FormRequest
{
return [
'reason' => 'required|string',
- 'durationOperand' => 'nullable|string',
- 'durationOperator' => 'nullable|string'
+ 'suspensionType' => 'required|string',
+ 'duration' => 'required_if:suspensionType,on|nullable|integer',
+ ];
+ }
+
+ public function messages()
+ {
+ return [
+ 'duration.required_if' => __('You must provide a duration if the suspension is temporary.')
];
}
}
diff --git a/app/Http/Requests/ChangeEmailRequest.php b/app/Http/Requests/ChangeEmailRequest.php
old mode 100644
new mode 100755
index 128a3eb..c591f2b
--- a/app/Http/Requests/ChangeEmailRequest.php
+++ b/app/Http/Requests/ChangeEmailRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +44,7 @@ class ChangeEmailRequest extends FormRequest
{
return [
'currentPassword' => 'required|password',
- 'newEmail' => 'required|email|unique:users,email'
+ 'newEmail' => 'required|email|unique:users,email',
];
}
}
diff --git a/app/Http/Requests/ChangePasswordRequest.php b/app/Http/Requests/ChangePasswordRequest.php
old mode 100644
new mode 100755
index 3feb69b..f82dae3
--- a/app/Http/Requests/ChangePasswordRequest.php
+++ b/app/Http/Requests/ChangePasswordRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +44,7 @@ class ChangePasswordRequest extends FormRequest
{
return [
'newPassword' => 'required|string|confirmed',
- 'oldPassword' => 'required|string|password'
+ 'oldPassword' => 'required|string|password',
];
}
}
diff --git a/app/Http/Requests/CreateApiKeyRequest.php b/app/Http/Requests/CreateApiKeyRequest.php
new file mode 100644
index 0000000..d7bf22c
--- /dev/null
+++ b/app/Http/Requests/CreateApiKeyRequest.php
@@ -0,0 +1,30 @@
+ 'required|string'
+ ];
+ }
+}
diff --git a/app/Http/Requests/DeleteUserRequest.php b/app/Http/Requests/DeleteUserRequest.php
old mode 100644
new mode 100755
index 924635c..bdaaada
--- a/app/Http/Requests/DeleteUserRequest.php
+++ b/app/Http/Requests/DeleteUserRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +44,7 @@ class DeleteUserRequest extends FormRequest
public function rules()
{
return [
- 'confirmPrompt' => 'required|string'
+ 'confirmPrompt' => 'required|string',
];
}
}
diff --git a/app/Http/Requests/EditTeamRequest.php b/app/Http/Requests/EditTeamRequest.php
new file mode 100755
index 0000000..d2ad544
--- /dev/null
+++ b/app/Http/Requests/EditTeamRequest.php
@@ -0,0 +1,50 @@
+.
+ */
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class EditTeamRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ 'teamDescription' => 'required|string|max:200',
+ 'joinType' => 'required|boolean',
+ ];
+ }
+}
diff --git a/app/Http/Requests/FlushSessionsRequest.php b/app/Http/Requests/FlushSessionsRequest.php
old mode 100644
new mode 100755
index f274ebd..6f4c78e
--- a/app/Http/Requests/FlushSessionsRequest.php
+++ b/app/Http/Requests/FlushSessionsRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -24,7 +43,7 @@ class FlushSessionsRequest extends FormRequest
public function rules()
{
return [
- 'currentPasswordFlush' => 'required|password'
+ 'currentPasswordFlush' => 'required|password',
];
}
}
diff --git a/app/Http/Requests/NewCommentRequest.php b/app/Http/Requests/NewCommentRequest.php
old mode 100644
new mode 100755
index e1470bc..9d05a95
--- a/app/Http/Requests/NewCommentRequest.php
+++ b/app/Http/Requests/NewCommentRequest.php
@@ -1,11 +1,29 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
-
class NewCommentRequest extends FormRequest
{
/**
@@ -27,7 +45,7 @@ class NewCommentRequest extends FormRequest
public function rules()
{
return [
- 'comment' => 'required|string|max:600|min:20'
+ 'comment' => 'required|string|max:600|min:20',
];
}
}
diff --git a/app/Http/Requests/NewTeamRequest.php b/app/Http/Requests/NewTeamRequest.php
new file mode 100755
index 0000000..a4fcb4e
--- /dev/null
+++ b/app/Http/Requests/NewTeamRequest.php
@@ -0,0 +1,49 @@
+.
+ */
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class NewTeamRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ 'teamName' => 'required|max:200|string',
+ ];
+ }
+}
diff --git a/app/Http/Requests/ProfileSave.php b/app/Http/Requests/ProfileSave.php
old mode 100644
new mode 100755
index 75278be..7d79846
--- a/app/Http/Requests/ProfileSave.php
+++ b/app/Http/Requests/ProfileSave.php
@@ -1,10 +1,28 @@
.
+ */
+
namespace App\Http\Requests;
use App\Profile;
use Illuminate\Foundation\Http\FormRequest;
-use Illuminate\Support\Facades\Auth;
class ProfileSave extends FormRequest
{
@@ -33,7 +51,7 @@ class ProfileSave extends FormRequest
'socialInsta' => 'nullable|string',
'socialTwitter' => 'nullable|string',
'socialDiscord' => 'nullable|string',
- 'socialGithub' => 'nullable|string'
+ 'socialGithub' => 'nullable|string',
];
}
}
diff --git a/app/Http/Requests/Remove2FASecretRequest.php b/app/Http/Requests/Remove2FASecretRequest.php
old mode 100644
new mode 100755
index 6583b93..4cd69bb
--- a/app/Http/Requests/Remove2FASecretRequest.php
+++ b/app/Http/Requests/Remove2FASecretRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +44,7 @@ class Remove2FASecretRequest extends FormRequest
{
return [
'currentPassword' => 'required|password',
- 'consent' => 'required|accepted'
+ 'consent' => 'required|accepted',
];
}
}
diff --git a/app/Http/Requests/SaveNotesRequest.php b/app/Http/Requests/SaveNotesRequest.php
old mode 100644
new mode 100755
index b6dd782..7b89a98
--- a/app/Http/Requests/SaveNotesRequest.php
+++ b/app/Http/Requests/SaveNotesRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -24,7 +43,7 @@ class SaveNotesRequest extends FormRequest
public function rules()
{
return [
- 'noteText' => 'required|string'
+ 'noteText' => 'required|string',
];
}
}
diff --git a/app/Http/Requests/SaveSecuritySettings.php b/app/Http/Requests/SaveSecuritySettings.php
new file mode 100644
index 0000000..245d630
--- /dev/null
+++ b/app/Http/Requests/SaveSecuritySettings.php
@@ -0,0 +1,34 @@
+ 'required|string',
+ 'graceperiod' => 'required|integer',
+ 'pwExpiry' => 'required|integer',
+ 'enforce2fa' => 'required|boolean',
+ 'requirePMC' => 'required|boolean'
+ ];
+ }
+}
diff --git a/app/Http/Requests/SearchPlayerRequest.php b/app/Http/Requests/SearchPlayerRequest.php
old mode 100644
new mode 100755
index 4689a49..23c7e78
--- a/app/Http/Requests/SearchPlayerRequest.php
+++ b/app/Http/Requests/SearchPlayerRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +44,7 @@ class SearchPlayerRequest extends FormRequest
public function rules()
{
return [
- 'searchTerm' => 'required|string|max:17' // max user char limit set by Mojang
+ 'searchTerm' => 'required|string|max:17', // max user char limit set by Mojang
];
}
}
diff --git a/app/Http/Requests/SendInviteRequest.php b/app/Http/Requests/SendInviteRequest.php
new file mode 100755
index 0000000..234ed89
--- /dev/null
+++ b/app/Http/Requests/SendInviteRequest.php
@@ -0,0 +1,49 @@
+.
+ */
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class SendInviteRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ 'user' => 'required|integer',
+ ];
+ }
+}
diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php
old mode 100644
new mode 100755
index 99403b4..709f013
--- a/app/Http/Requests/UpdateUserRequest.php
+++ b/app/Http/Requests/UpdateUserRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -28,7 +47,7 @@ class UpdateUserRequest extends FormRequest
'email' => 'required|email',
'name' => 'required|string',
'uuid' => 'required|max:32|min:32',
- 'roles' => 'required_without_all'
+ 'roles' => 'required_without_all',
];
}
}
diff --git a/app/Http/Requests/UploadFileRequest.php b/app/Http/Requests/UploadFileRequest.php
new file mode 100644
index 0000000..46b5ea7
--- /dev/null
+++ b/app/Http/Requests/UploadFileRequest.php
@@ -0,0 +1,32 @@
+ 'required|string|max:100',
+ 'description' => 'required|string|max:800',
+ 'file' => 'required|file|mimes:jpeg,jpg,png,bmp,tiff,docx,doc,odt,ott,xls,xlsx,ods,ots,gif,pdf,mp3,mp4,pptx,ppt,odp,ppsx,pub,psd,svg'
+ ];
+ }
+}
diff --git a/app/Http/Requests/UserDeleteRequest.php b/app/Http/Requests/UserDeleteRequest.php
new file mode 100755
index 0000000..1d0774e
--- /dev/null
+++ b/app/Http/Requests/UserDeleteRequest.php
@@ -0,0 +1,57 @@
+.
+ */
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Auth;
+
+class UserDeleteRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ if (Auth::user()->has2FA()) {
+ return [
+ 'currentPassword' => 'required|password:web',
+ 'otp' => 'required|integer|max:6',
+ ];
+ }
+
+ return [
+ 'currentPassword' => 'required|password:web',
+ ];
+ }
+}
diff --git a/app/Http/Requests/VacancyEditRequest.php b/app/Http/Requests/VacancyEditRequest.php
old mode 100644
new mode 100755
index c7ba958..b9c4c3e
--- a/app/Http/Requests/VacancyEditRequest.php
+++ b/app/Http/Requests/VacancyEditRequest.php
@@ -1,11 +1,29 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
-
class VacancyEditRequest extends FormRequest
{
/**
@@ -28,7 +46,7 @@ class VacancyEditRequest extends FormRequest
return [
'vacancyDescription' => 'required|string',
'vacancyFullDescription' => 'nullable|string',
- 'vacancyCount' => 'required|integer|min:1'
+ 'vacancyCount' => 'required|integer|min:1',
];
}
}
diff --git a/app/Http/Requests/VacancyRequest.php b/app/Http/Requests/VacancyRequest.php
old mode 100644
new mode 100755
index 176610d..07e333c
--- a/app/Http/Requests/VacancyRequest.php
+++ b/app/Http/Requests/VacancyRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -30,7 +49,7 @@ class VacancyRequest extends FormRequest
'permissionGroup' => 'required|string',
'discordRole' => 'required|string',
'vacancyCount' => 'required|integer',
- 'vacancyFormID' => 'required|integer'
+ 'vacancyFormID' => 'required|integer',
];
}
}
diff --git a/app/Http/Requests/VoteRequest.php b/app/Http/Requests/VoteRequest.php
old mode 100644
new mode 100755
index fdcf8c9..67e30a9
--- a/app/Http/Requests/VoteRequest.php
+++ b/app/Http/Requests/VoteRequest.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
@@ -24,7 +43,7 @@ class VoteRequest extends FormRequest
public function rules()
{
return [
- 'voteType' => 'required|string|in:VOTE_DENY,VOTE_APPROVE'
+ 'voteType' => 'required|string|in:VOTE_DENY,VOTE_APPROVE',
];
}
}
diff --git a/app/Http/Resources/ApplicationResource.php b/app/Http/Resources/ApplicationResource.php
new file mode 100644
index 0000000..3994e00
--- /dev/null
+++ b/app/Http/Resources/ApplicationResource.php
@@ -0,0 +1,28 @@
+ $this->id,
+ 'applicationStatus' => $this->applicationStatus,
+ 'applicant' => new UserResource(User::findOrFail($this->applicantUserID)),
+ 'response' => new ResponseResource(Response::findOrFail($this->applicantFormResponseID)),
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at
+ ];
+ }
+}
diff --git a/app/Http/Resources/AppointmentResource.php b/app/Http/Resources/AppointmentResource.php
new file mode 100644
index 0000000..4b71947
--- /dev/null
+++ b/app/Http/Resources/AppointmentResource.php
@@ -0,0 +1,19 @@
+ $this->id,
+ 'formName' => $this->formName,
+ 'formStructure' => json_decode($this->formStructure),
+ 'formStatus' => $this->formStatus,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at
+ ];
+ }
+}
diff --git a/app/Http/Resources/OptionResource.php b/app/Http/Resources/OptionResource.php
new file mode 100644
index 0000000..0315068
--- /dev/null
+++ b/app/Http/Resources/OptionResource.php
@@ -0,0 +1,19 @@
+ $this->id,
+ 'form' => new FormResource(Form::findOrFail($this->responseFormID)),
+ 'responseData' => json_decode($this->responseData),
+ 'vacancy' => new VacancyResource(Vacancy::findOrFail($this->associatedVacancyID)),
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at
+ ];
+ }
+}
diff --git a/app/Http/Resources/TeamFileResource.php b/app/Http/Resources/TeamFileResource.php
new file mode 100644
index 0000000..efad411
--- /dev/null
+++ b/app/Http/Resources/TeamFileResource.php
@@ -0,0 +1,19 @@
+ $this->id,
+ 'uuid' => $this->uuid,
+ 'name' => $this->name,
+ 'email' => $this->email,
+ 'username' => $this->username,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ 'current_team_id' => $this->current_team_id
+ ];
+ }
+}
diff --git a/app/Http/Resources/VacancyResource.php b/app/Http/Resources/VacancyResource.php
new file mode 100644
index 0000000..dc87ae1
--- /dev/null
+++ b/app/Http/Resources/VacancyResource.php
@@ -0,0 +1,19 @@
+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();
- }
- }
- }
-
- }
-}
diff --git a/app/Jobs/ProcessDueSuspensions.php b/app/Jobs/ProcessDueSuspensions.php
new file mode 100755
index 0000000..c3d040d
--- /dev/null
+++ b/app/Jobs/ProcessDueSuspensions.php
@@ -0,0 +1,69 @@
+.
+ */
+
+namespace App\Jobs;
+
+use App\Ban;
+use Carbon\Carbon;
+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;
+
+class ProcessDueSuspensions 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 suspension cleaner...');
+ $bans = Ban::all();
+
+ if (! is_null($bans)) {
+ foreach ($this->bans as $ban) {
+ $bannedUntil = Carbon::parse($ban->bannedUntil);
+
+ if ($bannedUntil->isToday()) {
+ Log::debug('Lifted expired suspension ID '.$ban->id.' for '.$ban->user->name);
+ $ban->delete();
+ }
+ }
+ }
+ }
+}
diff --git a/app/Listeners/DenyUser.php b/app/Listeners/DenyUser.php
old mode 100644
new mode 100755
index 0670cc3..34095ca
--- a/app/Listeners/DenyUser.php
+++ b/app/Listeners/DenyUser.php
@@ -1,11 +1,28 @@
.
+ */
+
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;
class DenyUser
@@ -29,9 +46,8 @@ class DenyUser
public function handle(ApplicationDeniedEvent $event)
{
$event->application->setStatus('DENIED');
- Log::info('User ' . $event->application->user->name . ' just had their application denied.');
+ Log::info('User '.$event->application->user->name.' just had their application denied.');
$event->application->user->notify(new ApplicationDenied($event->application));
-
}
}
diff --git a/app/Listeners/LogAuthenticationFailure.php b/app/Listeners/LogAuthenticationFailure.php
old mode 100644
new mode 100755
index afe1fee..15ce404
--- a/app/Listeners/LogAuthenticationFailure.php
+++ b/app/Listeners/LogAuthenticationFailure.php
@@ -1,9 +1,26 @@
.
+ */
+
namespace App\Listeners;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class LogAuthenticationFailure
@@ -27,10 +44,9 @@ class LogAuthenticationFailure
public function handle($event)
{
$targetAccountID = 0;
- $originalIP = "0.0.0.0";
+ $originalIP = '0.0.0.0';
- if (isset($event->user->id))
- {
+ if (isset($event->user->id)) {
$targetAccountID = $event->user->id;
}
diff --git a/app/Listeners/LogAuthenticationSuccess.php b/app/Listeners/LogAuthenticationSuccess.php
old mode 100644
new mode 100755
index 40781d9..7dd3ef3
--- a/app/Listeners/LogAuthenticationSuccess.php
+++ b/app/Listeners/LogAuthenticationSuccess.php
@@ -1,9 +1,26 @@
.
+ */
+
namespace App\Listeners;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class LogAuthenticationSuccess
diff --git a/app/Listeners/OnUserBanned.php b/app/Listeners/OnUserBanned.php
old mode 100644
new mode 100755
index 897a280..804aac5
--- a/app/Listeners/OnUserBanned.php
+++ b/app/Listeners/OnUserBanned.php
@@ -1,15 +1,30 @@
.
+ */
+
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;
+use Illuminate\Support\Facades\Log;
class OnUserBanned
{
@@ -31,16 +46,12 @@ class OnUserBanned
*/
public function handle(UserBannedEvent $event)
{
+ Log::warning('User '.$event->user->name.' has just been banned from the site!');
- 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)));
- }
+ foreach (User::all() as $user) {
+ if ($user->isStaffMember()) {
+ $user->notify((new UserBanned($event->user, $event->ban))->delay(now()->addSeconds(10)));
+ }
}
-
}
}
diff --git a/app/Listeners/OnUserRegistration.php b/app/Listeners/OnUserRegistration.php
old mode 100644
new mode 100755
index 7ab08f9..f2fa814
--- a/app/Listeners/OnUserRegistration.php
+++ b/app/Listeners/OnUserRegistration.php
@@ -1,14 +1,30 @@
.
+ */
+
namespace App\Listeners;
-use Illuminate\Support\Facades\Log;
-use Illuminate\Auth\Events\Registered;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Queue\InteractsWithQueue;
-
-use App\User;
use App\Notifications\NewUser;
+use App\User;
+use Illuminate\Auth\Events\Registered;
+use Illuminate\Support\Facades\Log;
class OnUserRegistration
{
@@ -31,12 +47,10 @@ class OnUserRegistration
public function handle(Registered $event)
{
// TODO: Send push notification to online admins via browser (w/ pusher)
- Log::info('User ' . $event->user->name . ' has just registered for an account.');
+ Log::info('User '.$event->user->name.' has just registered for an account.');
- foreach(User::all() as $user)
- {
- if ($user->hasRole('admin'))
- {
+ foreach (User::all() as $user) {
+ if ($user->hasRole('admin')) {
$user->notify(new NewUser($event->user));
}
}
diff --git a/app/Listeners/PromoteUser.php b/app/Listeners/PromoteUser.php
old mode 100644
new mode 100755
index 62760b0..a3ca047
--- a/app/Listeners/PromoteUser.php
+++ b/app/Listeners/PromoteUser.php
@@ -1,13 +1,29 @@
.
+ */
+
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;
+use App\StaffProfile;
use Illuminate\Support\Facades\Log;
class PromoteUser
@@ -35,19 +51,18 @@ class PromoteUser
$staffProfile = StaffProfile::create([
'userID' => $event->application->user->id,
'approvalDate' => now()->toDateTimeString(),
- 'memberNotes' => 'Approved by staff members. Welcome them to the team!'
+ '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!', [
+ Log::info('User '.$event->application->user->name.' has just been promoted!', [
'newRank' => $event->application->response->vacancy->permissionGroupName,
- 'staffProfileID' => $staffProfile->id
+ 'staffProfileID' => $staffProfile->id,
]);
$event->application->user->notify(new ApplicationApproved($event->application));
// note: Also notify staff
// TODO: Also assign new app role based on the permission group name
-
}
}
diff --git a/app/Mail/InviteToTeam.php b/app/Mail/InviteToTeam.php
new file mode 100755
index 0000000..5e2714d
--- /dev/null
+++ b/app/Mail/InviteToTeam.php
@@ -0,0 +1,68 @@
+.
+ */
+
+namespace App\Mail;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Mail\Mailable;
+use Illuminate\Queue\SerializesModels;
+use Mpociot\Teamwork\TeamInvite;
+
+class InviteToTeam extends Mailable
+{
+ use Queueable, SerializesModels;
+
+ public $teamName;
+
+ public $name;
+
+ public $inviterName;
+
+ public $denyToken;
+
+ public $acceptToken;
+
+ /**
+ * Create a new message instance.
+ *
+ * @return void
+ */
+ public function __construct(TeamInvite $invite)
+ {
+ $this->teamName = $invite->team->name;
+ $this->name = $invite->user->name;
+ $this->inviterName = $invite->inviter->name;
+ $this->acceptToken = $invite->accept_token;
+ $this->denyToken = $invite->deny_token;
+ }
+
+ /**
+ * Build the message.
+ *
+ * @return $this
+ */
+ public function build()
+ {
+ return $this
+ ->subject('You have just been invited to '.$this->teamName)
+ ->view('mail.invited-to-team');
+ }
+}
diff --git a/app/Mail/NewContactSubmission.php b/app/Mail/NewContactSubmission.php
old mode 100644
new mode 100755
index 24373f8..15e2cdf
--- a/app/Mail/NewContactSubmission.php
+++ b/app/Mail/NewContactSubmission.php
@@ -1,9 +1,27 @@
.
+ */
+
namespace App\Mail;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
diff --git a/app/Mail/UserAccountDeleteConfirmation.php b/app/Mail/UserAccountDeleteConfirmation.php
new file mode 100755
index 0000000..33b021f
--- /dev/null
+++ b/app/Mail/UserAccountDeleteConfirmation.php
@@ -0,0 +1,67 @@
+.
+ */
+
+namespace App\Mail;
+
+use App\User;
+use Illuminate\Bus\Queueable;
+use Illuminate\Mail\Mailable;
+use Illuminate\Queue\SerializesModels;
+
+class UserAccountDeleteConfirmation extends Mailable
+{
+ use Queueable, SerializesModels;
+
+ public $deleteToken;
+
+ public $cancelToken;
+
+ public $originalIP;
+
+ public $name;
+
+ public $userID;
+
+ /**
+ * Create a new message instance.
+ *
+ * @return void
+ */
+ public function __construct(User $user, array $tokens, string $originalIP)
+ {
+ $this->deleteToken = $tokens['delete'];
+ $this->cancelToken = $tokens['cancel'];
+
+ $this->originalIP = $originalIP;
+ $this->name = $user->name;
+ $this->userID = $user->id;
+ }
+
+ /**
+ * Build the message.
+ *
+ * @return $this
+ */
+ public function build()
+ {
+ return $this->view('mail.deleted-account');
+ }
+}
diff --git a/app/Notifications/ApplicationApproved.php b/app/Notifications/ApplicationApproved.php
old mode 100644
new mode 100755
index bfde408..9c20eae
--- a/app/Notifications/ApplicationApproved.php
+++ b/app/Notifications/ApplicationApproved.php
@@ -1,7 +1,27 @@
.
+ */
+
namespace App\Notifications;
+use App\Application;
use App\Facades\Options;
use App\Traits\Cancellable;
use Illuminate\Bus\Queueable;
@@ -9,7 +29,6 @@ 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
{
@@ -45,10 +64,9 @@ class ApplicationApproved extends Notification implements ShouldQueue
*/
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')
+ ->subject(config('app.name').' - '.$this->application->response->vacancy->vacancyName.' application approved')
->line('
')
->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.')
@@ -62,19 +80,18 @@ class ApplicationApproved extends Notification implements ShouldQueue
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(function ($attachment) use ($notifiable, $url, $roles) {
$attachment->title('New staff member')
->fields([
'Name' => $notifiable->name,
'Email' => $notifiable->email,
- 'Roles' => $roles
+ 'Roles' => $roles,
])
->action('View profile', $url);
});
diff --git a/app/Notifications/ApplicationDenied.php b/app/Notifications/ApplicationDenied.php
old mode 100644
new mode 100755
index 03a4382..09233ad
--- a/app/Notifications/ApplicationDenied.php
+++ b/app/Notifications/ApplicationDenied.php
@@ -1,19 +1,37 @@
.
+ */
+
namespace App\Notifications;
+use App\Application;
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;
/**
@@ -45,10 +63,9 @@ class ApplicationDenied extends Notification implements ShouldQueue
*/
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')
+ ->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.')
@@ -56,20 +73,19 @@ class ApplicationDenied extends Notification implements ShouldQueue
->line('Better luck next time!');
}
-
public function toSlack($notifiable)
{
- $notifiableName = $notifiable->name;
+ $notifiableName = $notifiable->name;
- return (new SlackMessage)
+ return (new SlackMessage)
->error()
->content('An application has just been denied.')
- ->attachment(function($attachment) use ($notifiableName){
+ ->attachment(function ($attachment) use ($notifiableName) {
$attachment->title('Application denied!')
- ->content($notifiableName . '\'s application has just been denied. They can try again in 30 days.');
+ ->content($notifiableName.'\'s application has just been denied. They can try again in 30 days.');
});
-
}
+
/**
* Get the array representation of the notification.
*
diff --git a/app/Notifications/ApplicationMoved.php b/app/Notifications/ApplicationMoved.php
old mode 100644
new mode 100755
index 9598258..59c1c63
--- a/app/Notifications/ApplicationMoved.php
+++ b/app/Notifications/ApplicationMoved.php
@@ -1,13 +1,32 @@
.
+ */
+
namespace App\Notifications;
+use App\Facades\Options;
+use App\Traits\Cancellable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
-use App\Traits\Cancellable;
-use App\Facades\Options;
class ApplicationMoved extends Notification implements ShouldQueue
{
@@ -38,7 +57,7 @@ class ApplicationMoved extends Notification implements ShouldQueue
{
return (new MailMessage)
->from(config('notification.sender.address'), config('notification.sender.name'))
- ->subject(config('app.name') . ' - Application Updated')
+ ->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')))
diff --git a/app/Notifications/AppointmentFinished.php b/app/Notifications/AppointmentFinished.php
old mode 100644
new mode 100755
index c1e879a..76a54c8
--- a/app/Notifications/AppointmentFinished.php
+++ b/app/Notifications/AppointmentFinished.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Notifications;
use Illuminate\Bus\Queueable;
@@ -42,7 +61,7 @@ class AppointmentFinished extends Notification implements ShouldQueue
{
return (new MailMessage)
->from(config('notification.sender.address'), config('notification.sender.name'))
- ->subject(config('app.name') . ' - Appointment completed')
+ ->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')))
diff --git a/app/Notifications/AppointmentScheduled.php b/app/Notifications/AppointmentScheduled.php
old mode 100644
new mode 100755
index 3ad3f60..e77cd5d
--- a/app/Notifications/AppointmentScheduled.php
+++ b/app/Notifications/AppointmentScheduled.php
@@ -1,19 +1,36 @@
.
+ */
+
namespace App\Notifications;
+use App\Appointment;
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;
/**
@@ -47,10 +64,10 @@ class AppointmentScheduled extends Notification implements ShouldQueue
{
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.')
+ ->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!');
diff --git a/app/Notifications/ChangedPassword.php b/app/Notifications/ChangedPassword.php
old mode 100644
new mode 100755
index bc4cca5..6c9bd54
--- a/app/Notifications/ChangedPassword.php
+++ b/app/Notifications/ChangedPassword.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Notifications;
use Illuminate\Bus\Queueable;
@@ -42,7 +61,7 @@ class ChangedPassword extends Notification implements ShouldQueue
{
return (new MailMessage)
->from(config('notification.sender.address'), config('notification.sender.name'))
- ->subject(config('app.name') . ' - Account password changed')
+ ->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')))
diff --git a/app/Notifications/EmailChanged.php b/app/Notifications/EmailChanged.php
old mode 100644
new mode 100755
index e946102..6003cf6
--- a/app/Notifications/EmailChanged.php
+++ b/app/Notifications/EmailChanged.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Notifications;
use Illuminate\Bus\Queueable;
@@ -42,7 +61,7 @@ class EmailChanged extends Notification implements ShouldQueue
{
return (new MailMessage)
->from(config('notification.sender.address'), config('notification.sender.name'))
- ->subject(config('app.name') . ' - Email address changed')
+ ->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!');
diff --git a/app/Notifications/NewApplicant.php b/app/Notifications/NewApplicant.php
old mode 100644
new mode 100755
index 0fdbac9..7c93203
--- a/app/Notifications/NewApplicant.php
+++ b/app/Notifications/NewApplicant.php
@@ -1,26 +1,42 @@
.
+ */
+
namespace App\Notifications;
+use App\Application;
+use App\Facades\Options;
+use App\Traits\Cancellable;
+use App\Vacancy;
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;
-
-use App\Traits\Cancellable;
-use App\Facades\Options;
class NewApplicant extends Notification implements ShouldQueue
{
use Queueable, Cancellable;
-
protected $application;
-
protected $vacancy;
/**
@@ -36,8 +52,7 @@ class NewApplicant extends Notification implements ShouldQueue
public function channels()
{
- if (Options::getOption('enable_slack_notifications') == 1)
- {
+ if (Options::getOption('enable_slack_notifications') == 1) {
return ['slack'];
}
@@ -59,17 +74,15 @@ class NewApplicant extends Notification implements ShouldQueue
{
return (new MailMessage)
->from(config('notification.sender.address'), config('notification.sender.name'))
- ->subject(config('app.name') . ' - New application')
+ ->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') . '.')
+ ->line('You are receiving this because you\'re a staff member at '.config('app.name').'.')
->action('View Application', url(route('showUserApp', ['application' => $this->application->id])))
->line('Thank you!');
}
-
public function toSlack($notifiable)
{
-
$vacancyDetails = [];
$vacancyDetails['name'] = $this->vacancy->vacancyName;
$vacancyDetails['slots'] = $this->vacancy->vacancyCount;
@@ -80,16 +93,17 @@ class NewApplicant extends Notification implements ShouldQueue
return (new SlackMessage)
->success()
->content('Notice: New application coming through. Please review as soon as possible.')
- ->attachment(function($attachment) use ($vacancyDetails, $url, $applicant){
+ ->attachment(function ($attachment) use ($vacancyDetails, $url, $applicant) {
$attachment->title('Application details')
->fields([
- 'Applied for' => $vacancyDetails['name'],
- 'Avaiable positions' => $vacancyDetails['slots'],
- 'Applicant' => $applicant
+ 'Applied for' => $vacancyDetails['name'],
+ 'Available positions' => $vacancyDetails['slots'],
+ 'Applicant' => $applicant,
])
->action('Review application', $url);
});
}
+
/**
* Get the array representation of the notification.
*
diff --git a/app/Notifications/NewComment.php b/app/Notifications/NewComment.php
old mode 100644
new mode 100755
index 10c7bfc..48e55f9
--- a/app/Notifications/NewComment.php
+++ b/app/Notifications/NewComment.php
@@ -1,21 +1,39 @@
.
+ */
+
namespace App\Notifications;
+use App\Application;
+use App\Comment;
+use App\Facades\Options;
+use App\Traits\Cancellable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
-use App\Comment;
-use App\Application;
-use App\Traits\Cancellable;
-use App\Facades\Options;
class NewComment extends Notification implements ShouldQueue
{
use Queueable, Cancellable;
-
protected $application;
/**
@@ -43,7 +61,7 @@ class NewComment extends Notification implements ShouldQueue
{
return (new MailMessage)
->from(config('notification.sender.address'), config('notification.sender.name'))
- ->subject(config('app.name') . ' - New comment')
+ ->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', ['application' => $this->application->id])))
diff --git a/app/Notifications/NewContact.php b/app/Notifications/NewContact.php
old mode 100644
new mode 100755
index 761f27c..9526327
--- a/app/Notifications/NewContact.php
+++ b/app/Notifications/NewContact.php
@@ -1,9 +1,27 @@
.
+ */
+
namespace App\Notifications;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Collection;
@@ -44,23 +62,22 @@ class NewContact extends Notification
public function toMail($notifiable)
{
if ($this->message->has([
- 'message',
- 'ip',
- 'email'
- ]))
- {
- return (new MailMessage)
+ 'message',
+ 'ip',
+ 'email',
+ ])) {
+ return (new MailMessage)
->line('We\'ve received a new contact form submission in the StaffManagement app center.')
->line('This is what they sent: ')
->line('')
->line($this->message->get('message'))
->line('')
- ->line('This message was received from ' . $this->message->get('ip') . ' and submitted by ' . $this->message->get('email') . '.')
+ ->line('This message was received from '.$this->message->get('ip').' and submitted by '.$this->message->get('email').'.')
->action('Sign in', url(route('login')))
->line('Thank you!');
}
- throw new \InvalidArgumentException("Invalid arguments supplied to NewContact!");
+ throw new \InvalidArgumentException('Invalid arguments supplied to NewContact!');
}
/**
diff --git a/app/Notifications/NewUser.php b/app/Notifications/NewUser.php
old mode 100644
new mode 100755
index ec31cd6..1d0db11
--- a/app/Notifications/NewUser.php
+++ b/app/Notifications/NewUser.php
@@ -1,17 +1,35 @@
.
+ */
+
namespace App\Notifications;
+use App\Facades\Options;
+use App\Facades\UUID;
+use App\Traits\Cancellable;
+use App\User;
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;
-use App\Traits\Cancellable;
-use App\Facades\Options;
+use Illuminate\Notifications\Notification;
class NewUser extends Notification implements ShouldQueue
{
@@ -49,8 +67,8 @@ class NewUser extends Notification implements ShouldQueue
{
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.')
+ ->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!');
@@ -58,28 +76,26 @@ class NewUser extends Notification implements ShouldQueue
public function toSlack($notifiable)
{
- $user = [];
+ $user = [];
- $user['name'] = $this->user->name;
- $user['email'] = $this->user->email;
- $user['username'] = UUID::toUsername($this->user->uuid);
+ $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;
+ $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(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']
+ 'Email address' => $user['email'],
+ 'Name' => $user['name'],
+ 'Minecraft Username' => $user['username'],
+ 'Registration date' => $user['created_at'],
]);
-
});
}
diff --git a/app/Notifications/UserBanned.php b/app/Notifications/UserBanned.php
old mode 100644
new mode 100755
index f5d5c4e..c230580
--- a/app/Notifications/UserBanned.php
+++ b/app/Notifications/UserBanned.php
@@ -1,15 +1,33 @@
.
+ */
+
namespace App\Notifications;
+use App\Ban;
+use App\User;
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;
@@ -17,6 +35,7 @@ class UserBanned extends Notification implements ShouldQueue
protected $user;
protected $ban;
+
/**
* Create a new notification instance.
*
@@ -50,8 +69,8 @@ class UserBanned extends Notification implements ShouldQueue
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 . '.')
+ ->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!');
}
diff --git a/app/Notifications/VacancyClosed.php b/app/Notifications/VacancyClosed.php
old mode 100644
new mode 100755
index 8ae85e4..4016273
--- a/app/Notifications/VacancyClosed.php
+++ b/app/Notifications/VacancyClosed.php
@@ -1,17 +1,35 @@
.
+ */
+
namespace App\Notifications;
+use App\Facades\Options;
+use App\Traits\Cancellable;
+use App\Vacancy;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\SerializesModels;
-use App\Vacancy;
-use App\Facades\Options;
-use App\Traits\Cancellable;
-
class VacancyClosed extends Notification implements ShouldQueue
{
use Queueable, SerializesModels, Cancellable;
@@ -25,7 +43,7 @@ class VacancyClosed extends Notification implements ShouldQueue
*/
public function __construct(Vacancy $vacancy)
{
- $this->vacancy = $vacancy;
+ $this->vacancy = $vacancy;
}
public function optOut($notifiable)
@@ -43,8 +61,8 @@ class VacancyClosed extends Notification implements ShouldQueue
{
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.')
+ ->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!');
diff --git a/app/Observers/ApplicationObserver.php b/app/Observers/ApplicationObserver.php
old mode 100644
new mode 100755
index 8821414..16b6615
--- a/app/Observers/ApplicationObserver.php
+++ b/app/Observers/ApplicationObserver.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Observers;
use App\Application;
@@ -34,24 +53,20 @@ class ApplicationObserver
$application->response()->delete();
$votes = $application->votes;
- foreach ($votes as $vote)
- {
- Log::debug('Referential integrity cleanup: Deleting and detaching vote ' . $vote->id);
+ foreach ($votes as $vote) {
+ Log::debug('Referential integrity cleanup: Deleting and detaching vote '.$vote->id);
$vote->application()->detach($application->id);
$vote->delete();
}
- if (!is_null($application->appointment))
- {
+ if (! is_null($application->appointment)) {
Log::debug('RIC: Deleting appointment!');
$application->appointment()->delete();
}
- if (!$application->comments->isEmpty())
- {
+ if (! $application->comments->isEmpty()) {
Log::debug('RIC: Deleting comments!');
- foreach($application->comments as $comment)
- {
+ foreach ($application->comments as $comment) {
$comment->delete();
}
}
diff --git a/app/Observers/UserObserver.php b/app/Observers/UserObserver.php
old mode 100644
new mode 100755
index 38f7660..4e62976
--- a/app/Observers/UserObserver.php
+++ b/app/Observers/UserObserver.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Observers;
use App\Profile;
@@ -8,6 +27,11 @@ use Illuminate\Support\Facades\Log;
class UserObserver
{
+ public function __construct()
+ {
+ Log::debug('User observer has been initialised and ready for use!');
+ }
+
/**
* Handle the user "created" event.
*
@@ -21,7 +45,7 @@ class UserObserver
'profileShortBio' => 'Write a one-liner about you here!',
'profileAboutMe' => 'Tell us a bit about you.',
'socialLinks' => '{}',
- 'userID' => $user->id
+ 'userID' => $user->id,
]);
}
@@ -39,20 +63,21 @@ class UserObserver
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)
- {
- // code moved to Application observer, where it gets rid of attached elements individually
- Log::debug('RIC: Deleting application ' . $application->id);
- $application->delete();
+ if ($user->isForceDeleting()) {
+ $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) {
+ // code moved to Application observer, where it gets rid of attached elements individually
+ Log::debug('RIC: Deleting application '.$application->id);
+ $application->delete();
+ }
}
+ } else {
+ Log::debug('RIC: Not cleaning up soft deleted models!');
}
Log::debug('RIC: Cleanup done!');
@@ -66,7 +91,6 @@ class UserObserver
*/
public function deleted(User $user)
{
- //
}
/**
@@ -88,6 +112,8 @@ class UserObserver
*/
public function forceDeleted(User $user)
{
- //
+ Log::info('Model has been force deleted', [
+ 'modelID' => $user->id,
+ ]);
}
}
diff --git a/app/Observers/VacancyObserver.php b/app/Observers/VacancyObserver.php
old mode 100644
new mode 100755
index decf1f7..c363e15
--- a/app/Observers/VacancyObserver.php
+++ b/app/Observers/VacancyObserver.php
@@ -1,10 +1,28 @@
.
+ */
+
namespace App\Observers;
use App\Vacancy;
-
class VacancyObserver
{
/**
diff --git a/app/OneoffApplicant.php b/app/OneoffApplicant.php
new file mode 100644
index 0000000..9a25c9e
--- /dev/null
+++ b/app/OneoffApplicant.php
@@ -0,0 +1,17 @@
+belongsTo('App\Application', 'id', 'application_id');
+ }
+}
+
diff --git a/app/Options.php b/app/Options.php
old mode 100644
new mode 100755
index e650bbc..895fe88
--- a/app/Options.php
+++ b/app/Options.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -8,6 +27,6 @@ class Options extends Model
{
public $fillable = [
'option_name',
- 'option_value'
+ 'option_value',
];
}
diff --git a/app/Policies/ApiKeyPolicy.php b/app/Policies/ApiKeyPolicy.php
new file mode 100644
index 0000000..eb728bc
--- /dev/null
+++ b/app/Policies/ApiKeyPolicy.php
@@ -0,0 +1,72 @@
+hasRole('admin'))
+ return true;
+
+ return false;
+ }
+
+
+ /**
+ * Determine whether the user can create models.
+ *
+ * @param \App\User $user
+ * @return mixed
+ */
+ public function create(User $user)
+ {
+ if ($user->hasRole('admin'))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can update the model.
+ *
+ * @param \App\User $user
+ * @param \App\ApiKey $apiKey
+ * @return mixed
+ */
+ public function update(User $user, ApiKey $apiKey)
+ {
+ if ($user->hasRole('admin'))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can delete the model.
+ *
+ * @param \App\User $user
+ * @param \App\ApiKey $apiKey
+ * @return mixed
+ */
+ public function delete(User $user, ApiKey $apiKey)
+ {
+ if ($user->hasRole('admin'))
+ return true;
+
+ return false;
+ }
+
+}
diff --git a/app/Policies/ApplicationPolicy.php b/app/Policies/ApplicationPolicy.php
old mode 100644
new mode 100755
index 07edbca..6c7c2b9
--- a/app/Policies/ApplicationPolicy.php
+++ b/app/Policies/ApplicationPolicy.php
@@ -1,11 +1,30 @@
.
+ */
+
namespace App\Policies;
use App\Application;
-use Illuminate\Auth\Access\Response;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
+use Illuminate\Auth\Access\Response;
class ApplicationPolicy
{
@@ -23,22 +42,20 @@ class ApplicationPolicy
public function viewAny(User $user)
{
- if ($user->can('applications.view.all'))
- {
- return Response::allow();
- }
+ if ($user->can('applications.view.all')) {
+ return Response::allow();
+ }
- return Response::deny('Forbidden');
+ return Response::deny('Forbidden');
}
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();
- }
+ 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');
+ return Response::deny('You are not authorised to view this application');
}
public function update(User $user)
@@ -48,8 +65,6 @@ class ApplicationPolicy
public function delete(User $user, Application $application)
{
-
- return $user->hasRole('admin');
-
+ return $user->hasRole('admin');
}
}
diff --git a/app/Policies/AppointmentPolicy.php b/app/Policies/AppointmentPolicy.php
old mode 100644
new mode 100755
index e541e4c..29a5b50
--- a/app/Policies/AppointmentPolicy.php
+++ b/app/Policies/AppointmentPolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\Appointment;
diff --git a/app/Policies/BanPolicy.php b/app/Policies/BanPolicy.php
old mode 100644
new mode 100755
index 754458e..0eaa62e
--- a/app/Policies/BanPolicy.php
+++ b/app/Policies/BanPolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\Ban;
@@ -44,12 +63,13 @@ class BanPolicy
*/
public function create(User $user, User $targetUser)
{
- Log::debug("Authorization check started", [
+ Log::debug('Authorization check started', [
'requiredRoles' => 'admin',
'hasRequiredRole' => $user->hasRole('admin'),
'targetUser' => $targetUser->username,
- 'isCurrentUser' => Auth::user()->is($user)
+ 'isCurrentUser' => Auth::user()->is($user),
]);
+
return $user->hasRole('admin') && $user->isNot($targetUser);
}
diff --git a/app/Policies/CommentPolicy.php b/app/Policies/CommentPolicy.php
old mode 100644
new mode 100755
index 477b445..b9ce668
--- a/app/Policies/CommentPolicy.php
+++ b/app/Policies/CommentPolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\Comment;
@@ -65,8 +84,7 @@ class CommentPolicy
*/
public function delete(User $user, Comment $comment)
{
- if ($user->is($comment->user) || $user->hasRole('admin'))
- {
+ if ($user->is($comment->user) || $user->hasRole('admin')) {
return true;
}
diff --git a/app/Policies/FormPolicy.php b/app/Policies/FormPolicy.php
old mode 100644
new mode 100755
index c382190..ca6e808
--- a/app/Policies/FormPolicy.php
+++ b/app/Policies/FormPolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\Form;
@@ -35,8 +54,9 @@ class FormPolicy
public function viewFormbuilder(User $user)
{
- return $user->can('admin.hiring.formbuilder');
+ return $user->can('admin.hiring.formbuilder');
}
+
/**
* Determine whether the user can create models.
*
diff --git a/app/Policies/ProfilePolicy.php b/app/Policies/ProfilePolicy.php
old mode 100644
new mode 100755
index bd3bc01..d19801f
--- a/app/Policies/ProfilePolicy.php
+++ b/app/Policies/ProfilePolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\Profile;
@@ -17,7 +36,6 @@ class ProfilePolicy
*/
public function __construct()
{
-
}
public function edit(User $user, Profile $profile)
diff --git a/app/Policies/TeamFilePolicy.php b/app/Policies/TeamFilePolicy.php
new file mode 100644
index 0000000..494e34c
--- /dev/null
+++ b/app/Policies/TeamFilePolicy.php
@@ -0,0 +1,42 @@
+hasPermissionTo('teams.files.view');
+ }
+
+ public function store(User $user, Team $team)
+ {
+ return $user->hasPermissionTo('teams.files.upload') || $user->hasTeam($team);
+ }
+
+ public function download(User $user)
+ {
+ return $user->hasPermissionTo('teams.files.download');
+ }
+
+ public function delete(User $user)
+ {
+ return $user->hasPermissionTo('teams.files.delete');
+ }
+}
diff --git a/app/Policies/TeamPolicy.php b/app/Policies/TeamPolicy.php
new file mode 100644
index 0000000..ad135cf
--- /dev/null
+++ b/app/Policies/TeamPolicy.php
@@ -0,0 +1,56 @@
+hasPermissionTo('teams.view');
+ }
+
+ public function create(User $user)
+ {
+ return $user->hasPermissionTo('teams.create');
+ }
+
+ public function update(User $user, Team $team)
+ {
+ // Team owners can update their team regardless of perm.
+ // This perm would let admins change all teams
+ return $user->isOwnerOfTeam($team) || $user->hasPermissionTo('teams.update');
+ }
+
+
+ public function invite(User $user, Team $team)
+ {
+ if (!$team->openJoin && $user->isOwnerOfTeam($team) || !$team->openJoin && $user->hasPermissionTo('teams.invite'))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function switchTeam(User $user, Team $team): bool
+ {
+ // is the user in the team they're trying to switch to?
+ return $user->hasTeam($team);
+ }
+}
diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php
old mode 100644
new mode 100755
index b98f105..f87838a
--- a/app/Policies/UserPolicy.php
+++ b/app/Policies/UserPolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\User;
@@ -16,7 +35,6 @@ class UserPolicy
*/
public function __construct()
{
-
}
public function edit(User $authUser, User $user)
@@ -27,7 +45,7 @@ class UserPolicy
// This refers to the admin tools that let staff update more information than users themselves can
public function adminEdit(User $authUser, User $user)
{
- return $authUser->hasRole('admin') && $authUser->isNot($user);
+ return $authUser->hasRole('admin') && $authUser->isNot($user);
}
public function viewStaff(User $user)
@@ -42,11 +60,11 @@ class UserPolicy
public function terminate(User $authUser)
{
- return $authUser->hasRole('admin');
+ return $authUser->hasRole('admin');
}
public function delete(User $authUser, User $subject)
{
- return $authUser->hasRole('admin') && $authUser->isNot($subject);
+ return $authUser->hasRole('admin') && $authUser->isNot($subject);
}
}
diff --git a/app/Policies/VacancyPolicy.php b/app/Policies/VacancyPolicy.php
old mode 100644
new mode 100755
index 7e547f2..3ff57ad
--- a/app/Policies/VacancyPolicy.php
+++ b/app/Policies/VacancyPolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\User;
@@ -10,6 +29,7 @@ class VacancyPolicy
{
use HandlesAuthorization;
// TODO: Switch to permissions (there are no specific permissions yet)
+
/**
* Determine whether the user can view any models.
*
diff --git a/app/Policies/VotePolicy.php b/app/Policies/VotePolicy.php
old mode 100644
new mode 100755
index 9337aa4..570e145
--- a/app/Policies/VotePolicy.php
+++ b/app/Policies/VotePolicy.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Policies;
use App\User;
diff --git a/app/Profile.php b/app/Profile.php
old mode 100644
new mode 100755
index 9a64243..0367189
--- a/app/Profile.php
+++ b/app/Profile.php
@@ -1,19 +1,37 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
-
public $fillable = [
'profileShortBio',
'profileAboutMe',
'avatarPreference',
'socialLinks',
- 'userID'
+ 'userID',
];
@@ -21,5 +39,4 @@ class Profile extends Model
{
return $this->belongsTo('App\User', 'userID', 'id');
}
-
}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
old mode 100644
new mode 100755
index 8d8144e..2deea95
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -1,12 +1,33 @@
.
+ */
+
namespace App\Providers;
use App\Application;
use App\Observers\ApplicationObserver;
use App\Observers\UserObserver;
use App\User;
+use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Schema;
+use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Sentry;
@@ -30,14 +51,24 @@ class AppServiceProvider extends ServiceProvider
public function boot()
{
Sentry\init([
- 'release' => env('RELEASE')
+ 'release' => env('RELEASE'),
]);
Schema::defaultStringLength(191);
+ // Keep using Bootstrap; Laravel 8 has the paginator use Tailwind. Quite opinionated tbh
+ Paginator::useBootstrap();
+
User::observe(UserObserver::class);
Application::observe(ApplicationObserver::class);
- $this->app['request']->server->set('HTTPS', $this->app->environment() != 'local');
+
+ $https = ($this->app->environment() != 'local');
+ if(config('app.force_secure') && $this->app->environment() != 'production')
+ $https = true;
+
+ $this->app['request']->server->set('HTTPS', $https);
+
+ View::share('demoActive', config('demo.is_enabled'));
}
}
diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php
old mode 100644
new mode 100755
index 52563b4..fd42925
--- a/app/Providers/AuthServiceProvider.php
+++ b/app/Providers/AuthServiceProvider.php
@@ -1,27 +1,48 @@
.
+ */
+
namespace App\Providers;
-use App\Policies\ProfilePolicy;
-use App\Policies\VacancyPolicy;
-use App\Policies\UserPolicy;
-use App\Policies\BanPolicy;
-use App\Policies\FormPolicy;
-use App\Policies\VotePolicy;
-use App\Policies\ApplicationPolicy;
-use App\Policies\AppointmentPolicy;
-
-use App\User;
-use App\Form;
-use App\Vote;
-use App\Vacancy;
+use App\ApiKey;
use App\Application;
use App\Appointment;
use App\Ban;
-
-
+use App\Form;
+use App\Policies\ApiKeyPolicy;
+use App\Policies\ApplicationPolicy;
+use App\Policies\AppointmentPolicy;
+use App\Policies\BanPolicy;
+use App\Policies\FormPolicy;
+use App\Policies\ProfilePolicy;
+use App\Policies\TeamFilePolicy;
+use App\Policies\TeamPolicy;
+use App\Policies\UserPolicy;
+use App\Policies\VacancyPolicy;
+use App\Policies\VotePolicy;
+use App\Team;
+use App\TeamFile;
+use App\User;
+use App\Vacancy;
+use App\Vote;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
-use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
@@ -40,7 +61,10 @@ class AuthServiceProvider extends ServiceProvider
'App\Form' => 'App\Policies\FormPolicy',
Vote::class => VotePolicy::class,
Ban::class => BanPolicy::class,
- Appointment::class => AppointmentPolicy::class
+ Appointment::class => AppointmentPolicy::class,
+ Team::class => TeamPolicy::class,
+ TeamFile::class => TeamFilePolicy::class,
+ ApiKey::class => ApiKeyPolicy::class
];
/**
diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php
old mode 100644
new mode 100755
index 395c518..f3d62bd
--- a/app/Providers/BroadcastServiceProvider.php
+++ b/app/Providers/BroadcastServiceProvider.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
diff --git a/app/Providers/ContextAwareValidatorProvider.php b/app/Providers/ContextAwareValidatorProvider.php
old mode 100644
new mode 100755
index 749de88..bc4f309
--- a/app/Providers/ContextAwareValidatorProvider.php
+++ b/app/Providers/ContextAwareValidatorProvider.php
@@ -1,10 +1,28 @@
.
+ */
+
namespace App\Providers;
-use Illuminate\Support\ServiceProvider;
-
use App;
+use Illuminate\Support\ServiceProvider;
class ContextAwareValidatorProvider extends ServiceProvider
{
@@ -25,10 +43,8 @@ class ContextAwareValidatorProvider extends ServiceProvider
*/
public function boot()
{
- App::bind('contextAwareValidator', function(){
-
- return new App\Helpers\ContextAwareValidator();
-
- });
+ App::bind('contextAwareValidator', function () {
+ return new App\Helpers\ContextAwareValidator();
+ });
}
}
diff --git a/app/Providers/DigitalStorageProvider.php b/app/Providers/DigitalStorageProvider.php
new file mode 100644
index 0000000..fe594ef
--- /dev/null
+++ b/app/Providers/DigitalStorageProvider.php
@@ -0,0 +1,31 @@
+.
+ */
+
namespace App\Providers;
use App\Listeners\LogAuthenticationFailure;
@@ -22,23 +41,23 @@ class EventServiceProvider extends ServiceProvider
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
- OnUserRegistration::class
+ OnUserRegistration::class,
],
Failed::class => [
- LogAuthenticationFailure::class
+ LogAuthenticationFailure::class,
],
Login::class => [
- LogAuthenticationSuccess::class
+ LogAuthenticationSuccess::class,
],
'App\Events\ApplicationApprovedEvent' => [
- 'App\Listeners\PromoteUser'
+ 'App\Listeners\PromoteUser',
],
'App\Events\ApplicationDeniedEvent' => [
- 'App\Listeners\DenyUser'
+ 'App\Listeners\DenyUser',
],
'App\Events\UserBannedEvent' => [
- 'App\Listeners\OnUserBanned'
- ]
+ 'App\Listeners\OnUserBanned',
+ ],
];
/**
@@ -48,7 +67,6 @@ class EventServiceProvider extends ServiceProvider
*/
public function boot()
{
-
parent::boot();
//
diff --git a/app/Providers/IPInfoProvider.php b/app/Providers/IPInfoProvider.php
old mode 100644
new mode 100755
index 3b7150a..5ebe6f8
--- a/app/Providers/IPInfoProvider.php
+++ b/app/Providers/IPInfoProvider.php
@@ -1,9 +1,28 @@
.
+ */
+
namespace App\Providers;
-use Illuminate\Support\ServiceProvider;
use App;
+use Illuminate\Support\ServiceProvider;
class IPInfoProvider extends ServiceProvider
{
@@ -24,10 +43,8 @@ class IPInfoProvider extends ServiceProvider
*/
public function boot()
{
- App::bind('ipInformationFacade', function(){
-
+ App::bind('ipInformationFacade', function () {
return new App\CustomFacades\IP();
-
});
}
}
diff --git a/app/Providers/JSONProvider.php b/app/Providers/JSONProvider.php
new file mode 100644
index 0000000..b5ef403
--- /dev/null
+++ b/app/Providers/JSONProvider.php
@@ -0,0 +1,32 @@
+.
+ */
+
namespace App\Providers;
-use Illuminate\Support\ServiceProvider;
use App;
+use Illuminate\Support\ServiceProvider;
class OptionsProvider extends ServiceProvider
{
@@ -24,7 +43,7 @@ class OptionsProvider extends ServiceProvider
*/
public function boot()
{
- App::bind('smOptions', function (){
+ App::bind('smOptions', function () {
return new App\Helpers\Options();
});
}
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
old mode 100644
new mode 100755
index 1235909..1c5f6b7
--- a/app/Providers/RouteServiceProvider.php
+++ b/app/Providers/RouteServiceProvider.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
@@ -7,15 +26,6 @@ use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
- /**
- * This namespace is applied to your controller routes.
- *
- * In addition, it is set as the URL generator's root namespace.
- *
- * @var string
- */
- protected $namespace = 'App\Http\Controllers';
-
/**
* The path to the "home" route for your application.
*
@@ -59,7 +69,6 @@ class RouteServiceProvider extends ServiceProvider
protected function mapWebRoutes()
{
Route::middleware('web')
- ->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
diff --git a/app/Providers/UUIDConversionProvider.php b/app/Providers/UUIDConversionProvider.php
old mode 100644
new mode 100755
index 6ce7fad..7f26d6b
--- a/app/Providers/UUIDConversionProvider.php
+++ b/app/Providers/UUIDConversionProvider.php
@@ -1,9 +1,28 @@
.
+ */
+
namespace App\Providers;
-use Illuminate\Support\ServiceProvider;
use App;
+use Illuminate\Support\ServiceProvider;
class UUIDConversionProvider extends ServiceProvider
{
@@ -24,10 +43,8 @@ class UUIDConversionProvider extends ServiceProvider
*/
public function boot()
{
- App::bind('uuidConversionFacade', function(){
-
+ App::bind('uuidConversionFacade', function () {
return new App\UUID\UUID();
-
});
}
}
diff --git a/app/Response.php b/app/Response.php
old mode 100644
new mode 100755
index 08312ea..dfa96d0
--- a/app/Response.php
+++ b/app/Response.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -9,10 +28,9 @@ class Response extends Model
public $fillable = [
'responseFormID',
'associatedVacancyID',
- 'responseData'
+ 'responseData',
];
-
public function form()
{
return $this->hasOne('App\Form', 'id', 'responseFormID');
diff --git a/app/Services/AccountSuspensionService.php b/app/Services/AccountSuspensionService.php
new file mode 100644
index 0000000..54f1029
--- /dev/null
+++ b/app/Services/AccountSuspensionService.php
@@ -0,0 +1,53 @@
+ $target->id
+ ]);
+
+ if ($type == "on") {
+ $expiryDate = now()->addDays($duration);
+ }
+
+ $ban = Ban::create([
+ 'userID' => $target->id,
+ 'reason' => $reason,
+ 'bannedUntil' => ($type == "on") ? $expiryDate->format('Y-m-d H:i:s') : null,
+ 'authorUserID' => Auth::user()->id,
+ 'isPermanent' => ($type == "off") ? true : false
+ ]);
+
+ return $ban;
+ }
+
+ public function unsuspend(User $user): void {
+ $user->bans->delete();
+ }
+
+ public function isSuspended(User $user): bool {
+ return !is_null($user->bans);
+ }
+
+ public function makePermanent(Ban $ban): void {
+
+ $ban->bannedUntil = null;
+ $ban->isPermanent = true;
+
+ $ban->save();
+
+ }
+
+
+}
diff --git a/app/Services/ApplicationService.php b/app/Services/ApplicationService.php
new file mode 100644
index 0000000..a98da16
--- /dev/null
+++ b/app/Services/ApplicationService.php
@@ -0,0 +1,158 @@
+where('vacancySlug', $vacancySlug)->get();
+
+ $firstVacancy = $vacancyWithForm->first();
+
+ if (!$vacancyWithForm->isEmpty() && $firstVacancy->vacancyCount !== 0 && $firstVacancy->vacancyStatus == 'OPEN') {
+ return view('dashboard.application-rendering.apply')
+ ->with([
+ 'vacancy' => $vacancyWithForm->first(),
+ 'preprocessedForm' => json_decode($vacancyWithForm->first()->forms->formStructure, true),
+ ]);
+ } else {
+
+ throw new ApplicationNotFoundException('The application you\'re looking for could not be found or it is currently unavailable.', 404);
+
+ }
+ }
+
+ /**
+ * Fills a vacancy's form with submitted data.
+ *
+ * @throws UnavailableApplicationException Thrown when the application has no vacancies or is closed
+ * @throws VacancyNotFoundException Thrown when the associated vacancy is not found
+ * @throws IncompleteApplicationException Thrown when there are missing fields
+ */
+ public function fillForm(User $applicant, array $formData, $vacancySlug): bool
+ {
+ $vacancy = Vacancy::with('forms')->where('vacancySlug', $vacancySlug)->get();
+
+ if ($vacancy->isEmpty()) {
+
+ throw new VacancyNotFoundException('This vacancy doesn\'t exist; Please use the proper buttons to apply to one.', 404);
+
+ }
+
+ if ($vacancy->first()->vacancyCount == 0 || $vacancy->first()->vacancyStatus !== 'OPEN') {
+
+ throw new UnavailableApplicationException("This application is unavailable.");
+ }
+
+ Log::info('Processing new application!');
+
+ $formStructure = json_decode($vacancy->first()->forms->formStructure, true);
+ $responseValidation = ContextAwareValidator::getResponseValidator($formData, $formStructure);
+
+
+ Log::info('Built response & validator structure!');
+
+ if (!$responseValidation->get('validator')->fails()) {
+ $response = Response::create([
+ 'responseFormID' => $vacancy->first()->forms->id,
+ 'associatedVacancyID' => $vacancy->first()->id, // Since a form can be used by multiple vacancies, we can only know which specific vacancy this response ties to by using a vacancy ID
+ 'responseData' => $responseValidation->get('responseStructure'),
+ ]);
+
+ Log::info('Registered form response!', [
+ 'applicant' => $applicant->name,
+ 'vacancy' => $vacancy->first()->vacancyName
+ ]);
+
+ $application = Application::create([
+ 'applicantUserID' => $applicant->id,
+ 'applicantFormResponseID' => $response->id,
+ 'applicationStatus' => 'STAGE_SUBMITTED',
+ ]);
+
+ Log::info('Submitted an application!', [
+ 'responseID' => $response->id,
+ 'applicant' => $applicant->name
+ ]);
+
+ foreach (User::all() as $user) {
+ if ($user->hasRole('admin')) {
+ $user->notify((new NewApplicant($application, $vacancy->first()))->delay(now()->addSeconds(10)));
+ }
+ }
+
+ return true;
+
+ }
+
+ Log::warning('Application form for ' . $applicant->name . ' contained errors, resetting!');
+
+ throw new IncompleteApplicationException('There are one or more errors in your application. Please make sure none of your fields are empty, since they are all required.');
+ }
+
+ public function updateStatus(Application $application, $newStatus)
+ {
+ switch ($newStatus) {
+ case 'deny':
+
+ event(new ApplicationDeniedEvent($application));
+ $message = __("Application denied successfully.");
+
+ break;
+
+ case 'interview':
+ Log::info(' Moved application ID ' . $application->id . 'to interview stage!');
+ $message = __('Application moved to interview stage!');
+
+ $application->setStatus('STAGE_INTERVIEW');
+ $application->user->notify(new ApplicationMoved());
+
+ break;
+
+ default:
+ throw new \LogicException("Wrong status parameter. Please notify a developer.");
+ }
+
+ return $message;
+ }
+
+ /**
+ * @throws \Exception
+ */
+ public function delete(Application $application): ?bool
+ {
+ return $application->delete();
+ }
+
+
+ public function canVote($votes): bool
+ {
+ $allvotes = collect([]);
+
+ foreach ($votes as $vote) {
+ if ($vote->userID == Auth::user()->id) {
+ $allvotes->push($vote);
+ }
+ }
+
+ return !(($allvotes->count() == 1));
+ }
+}
diff --git a/app/Services/AppointmentService.php b/app/Services/AppointmentService.php
new file mode 100644
index 0000000..c00c666
--- /dev/null
+++ b/app/Services/AppointmentService.php
@@ -0,0 +1,85 @@
+ $appointmentDescription,
+ 'appointmentDate' => $appointmentDate->toDateTimeString(),
+ 'applicationID' => $application->id,
+ 'appointmentLocation' => (in_array($appointmentLocation, $this->allowedPlatforms)) ? $appointmentLocation : 'DISCORD',
+ ]);
+ $application->setStatus('STAGE_INTERVIEW_SCHEDULED');
+
+ Log::info('User '.Auth::user()->name.' has scheduled an appointment with '.$application->user->name.' for application ID'.$application->id, [
+ 'datetime' => $appointmentDate->toDateTimeString(),
+ 'scheduled' => now(),
+ ]);
+
+ $application->user->notify(new AppointmentScheduled($appointment));
+
+
+ return true;
+ }
+
+ /**
+ * Updates the appointment with the new $status.
+ * It also sets the application's status to peer approval.
+ *
+ * Set $updateApplication to false to only update its status
+ *
+ * @throws InvalidAppointmentStatusException
+ */
+ public function updateAppointment(Application $application, $status, $updateApplication = true)
+ {
+ if ($status == 'SCHEDULED' || $status == 'concluded')
+ {
+ $application->appointment->appointmentStatus = strtoupper($status);
+ $application->appointment->save();
+
+ if ($updateApplication)
+ {
+ $application->setStatus('STAGE_PEERAPPROVAL');
+ $application->user->notify(new ApplicationMoved());
+ }
+ }
+ else
+ {
+ throw new InvalidAppointmentStatusException("Invalid appointment status!");
+ }
+
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getAllowedPlatforms(): array
+ {
+ return $this->allowedPlatforms;
+ }
+
+}
diff --git a/app/Services/CommentService.php b/app/Services/CommentService.php
new file mode 100644
index 0000000..545d3d5
--- /dev/null
+++ b/app/Services/CommentService.php
@@ -0,0 +1,27 @@
+ Auth::user()->id,
+ 'applicationID' => $application->id,
+ 'text' => $comment,
+ ]);
+ }
+
+ public function deleteComment(Comment $comment): ?bool
+ {
+ return $comment->delete();
+ }
+
+}
diff --git a/app/Services/ConfigurationService.php b/app/Services/ConfigurationService.php
new file mode 100644
index 0000000..249a24d
--- /dev/null
+++ b/app/Services/ConfigurationService.php
@@ -0,0 +1,75 @@
+ $option) {
+ try {
+
+ Log::debug('Going through option '.$optionName);
+ if (Options::optionExists($optionName)) {
+ Log::debug('Option exists, updating to new values', [
+ 'opt' => $optionName,
+ 'new_value' => $option,
+ ]);
+ Options::changeOption($optionName, $option);
+ }
+
+ } catch (\Exception $ex) {
+
+ Log::error('Unable to update options!', [
+ 'msg' => $ex->getMessage(),
+ 'trace' => $ex->getTraceAsString(),
+ ]);
+
+ // Let service caller handle this without failing here
+ throw $ex;
+ }
+ }
+ }
+
+ /**
+ * Saves the chosen game integration
+ *
+ * @throws InvalidGamePreferenceException
+ * @returns bool
+ */
+ public function saveGameIntegration($gamePreference): bool
+ {
+
+ // TODO: Find solution to dynamically support games
+
+ $supportedGames = [
+ 'RUST',
+ 'MINECRAFT',
+ 'SE',
+ 'GMOD'
+ ];
+
+ if (!is_null($gamePreference) && in_array($gamePreference, $supportedGames))
+ {
+ Options::changeOption('currentGame', $gamePreference);
+ return true;
+ }
+
+ throw new InvalidGamePreferenceException("Unsupported game " . $gamePreference);
+ }
+
+}
diff --git a/app/Services/ContactService.php b/app/Services/ContactService.php
new file mode 100644
index 0000000..86c7938
--- /dev/null
+++ b/app/Services/ContactService.php
@@ -0,0 +1,47 @@
+post(config('recaptcha.verify.apiurl'), [
+ 'secret' => config('recaptcha.keys.secret'),
+ 'response' => $challenge,
+ 'remoteip' => $ipAddress,
+ ]);
+
+ $response = json_decode($verifyrequest->getBody(), true);
+
+ if (! $response['success']) {
+ throw new FailedCaptchaException('Beep beep boop... Robot? Submission failed.');
+ }
+
+ foreach (User::all() as $user) {
+ if ($user->hasRole('admin')) {
+ $user->notify(new NewContact(collect([
+ 'message' => $message,
+ 'ip' => $ipAddress,
+ 'email' => $email,
+ ])));
+ }
+ }
+ }
+
+
+}
diff --git a/app/Services/DemoService.php b/app/Services/DemoService.php
new file mode 100644
index 0000000..969de1d
--- /dev/null
+++ b/app/Services/DemoService.php
@@ -0,0 +1,11 @@
+get('validator')->fails()) {
+ $storableFormStructure = $contextValidation->get('structure');
+
+ Form::create(
+ [
+ 'formName' => $fields['formName'],
+ 'formStructure' => $storableFormStructure,
+ 'formStatus' => 'ACTIVE',
+ ]
+ );
+ return true;
+ }
+ return $contextValidation->get('validator')->errors()->getMessages();
+ }
+
+ public function deleteForm(Form $form) {
+
+ $deletable = true;
+
+ if (! is_null($form) && ! is_null($form->vacancies) && $form->vacancies->count() !== 0 || ! is_null($form->responses)) {
+ $deletable = false;
+ }
+
+ if ($deletable) {
+
+ $form->delete();
+ return true;
+
+ } else {
+
+ throw new FormHasConstraintsException(__('You cannot delete this form because it\'s tied to one or more applications and ranks, or because it doesn\'t exist.'));
+
+ }
+ }
+
+ public function updateForm(Form $form, $fields) {
+
+ $contextValidation = ContextAwareValidator::getValidator($fields, true);
+
+ if (! $contextValidation->get('validator')->fails()) {
+ // Add the new structure into the form. New, subsquent fields will be identified by the "new" prefix
+ // This prefix doesn't actually change the app's behavior when it receives applications.
+ // Additionally, old applications won't of course display new and updated fields, because we can't travel into the past and get data for them
+ $form->formStructure = $contextValidation->get('structure');
+ $form->save();
+
+ return $form;
+
+ } else {
+ return $contextValidation->get('validator')->errors()->getMessages();
+ }
+ }
+
+}
diff --git a/app/Services/MeetingNoteService.php b/app/Services/MeetingNoteService.php
new file mode 100644
index 0000000..e1136e9
--- /dev/null
+++ b/app/Services/MeetingNoteService.php
@@ -0,0 +1,36 @@
+load('appointment');
+
+ $application->appointment->meetingNotes = $noteText;
+ $application->appointment->save();
+
+ return true;
+
+ } else {
+ throw new InvalidAppointmentException('There\'s no appointment to save notes to!');
+ }
+
+ }
+
+}
diff --git a/app/Services/ProfileService.php b/app/Services/ProfileService.php
new file mode 100644
index 0000000..438527b
--- /dev/null
+++ b/app/Services/ProfileService.php
@@ -0,0 +1,50 @@
+profile;
+ $social = [];
+
+ if (! is_null($profile)) {
+ switch ($request->avatarPref) {
+ case 'MOJANG':
+ $avatarPref = 'crafatar';
+
+ break;
+ case 'GRAVATAR':
+ $avatarPref = strtolower($request->avatarPref);
+
+ break;
+ }
+
+ $social['links']['github'] = $request->socialGithub;
+ $social['links']['twitter'] = $request->socialTwitter;
+ $social['links']['insta'] = $request->socialInsta;
+ $social['links']['discord'] = $request->socialDiscord;
+
+ $profile->profileShortBio = $request->shortBio;
+ $profile->profileAboutMe = $request->aboutMe;
+ $profile->avatarPreference = $avatarPref;
+ $profile->socialLinks = json_encode($social);
+
+ return $profile->save();
+ }
+
+ throw new ProfileNotFoundException("This profile does not exist.");
+ }
+
+}
diff --git a/app/Services/SecuritySettingsService.php b/app/Services/SecuritySettingsService.php
new file mode 100644
index 0000000..1f84477
--- /dev/null
+++ b/app/Services/SecuritySettingsService.php
@@ -0,0 +1,54 @@
+ $policy
+ ]);
+ }
+ else
+ {
+ Log::debug('[WARN] Ignoring bogus policy', [
+ 'avaliable' => $validPolicies,
+ 'given' => $policy
+ ]);
+ }
+
+ Options::changeOption('graceperiod', $options['graceperiod']);
+ Options::changeOption('password_expiry', $options['pwExpiry']);
+ Options::changeOption('force2fa', $options['enforce2fa']);
+ Options::changeOption('requireGameLicense', $options['requirePMC']);
+
+ return true;
+
+ }
+
+}
diff --git a/app/Services/TeamFileService.php b/app/Services/TeamFileService.php
new file mode 100644
index 0000000..c94719c
--- /dev/null
+++ b/app/Services/TeamFileService.php
@@ -0,0 +1,42 @@
+store('uploads');
+ $originalFileName = $upload->getClientOriginalName();
+ $originalFileExtension = $upload->extension();
+ $originalFileSize = $upload->getSize();
+
+ $fileEntry = TeamFile::create([
+ 'uploaded_by' => $uploader,
+ 'team_id' => $team,
+ 'name' => $originalFileName,
+ 'caption' => $caption,
+ 'description' => $description,
+ 'fs_location' => $file,
+ 'extension' => $originalFileExtension,
+ 'size' => $originalFileSize
+ ]);
+
+ if ($fileEntry && !is_bool($file))
+ {
+ return $fileEntry;
+ }
+
+ throw new FileUploadException("There was an unknown error whilst trying to upload your file.");
+
+ }
+
+}
diff --git a/app/Services/TeamService.php b/app/Services/TeamService.php
new file mode 100644
index 0000000..9e7c8c0
--- /dev/null
+++ b/app/Services/TeamService.php
@@ -0,0 +1,165 @@
+ $teamName,
+ 'owner_id' => $ownerID,
+ ]);
+
+ Auth::user()->teams()->attach($team->id);
+
+ return $team;
+ }
+
+ public function updateTeam(Team $team, $teamDescription, $joinType): bool
+ {
+
+ $team->description = $teamDescription;
+ $team->openJoin = $joinType;
+
+ return $team->save();
+ }
+
+ /**
+ * Invites a user to a $team.
+ *
+ * @throws PublicTeamInviteException Thrown when trying to invite a user to a public team
+ * @throws UserAlreadyInvitedException Thrown when a user is already invited
+ */
+ public function inviteUser(Team $team, $userID): bool
+ {
+
+ $user = User::findOrFail($userID);
+
+ if (! $team->openJoin) {
+ if (! Teamwork::hasPendingInvite($user->email, $team)) {
+ Teamwork::inviteToTeam($user, $team, function (TeamInvite $invite) use ($user) {
+ Mail::to($user)->send(new InviteToTeam($invite));
+ });
+ return true;
+ } else {
+ throw new UserAlreadyInvitedException('This user has already been invited.');
+ }
+ } else {
+ throw new PublicTeamInviteException('You can\'t invite users to public teams.');
+ }
+
+ }
+
+ /**
+ * Accepts or denies a user invite
+ *
+ * @param Authenticatable $user
+ * @param $action
+ * @param $token
+ * @return bool True on success or exception on failure
+ * @throws InvalidInviteException Thrown when the invite code / url is invalid
+ */
+ public function processInvite(Authenticatable $user, $action, $token): bool {
+
+ switch ($action) {
+ case 'accept':
+
+ $invite = Teamwork::getInviteFromAcceptToken($token);
+
+ if ($invite && $invite->user->is($user)) {
+ Teamwork::acceptInvite($invite);
+
+ } else {
+
+ throw new InvalidInviteException('Invalid or expired invite URL.');
+ }
+
+ break;
+
+ case 'deny':
+
+ $invite = Teamwork::getInviteFromDenyToken($token);
+
+ if ($invite && $invite->user->is($user)) {
+
+ Teamwork::denyInvite($invite);
+
+ } else {
+
+ throw new InvalidInviteException('Invalid or expired invite URL.');
+ }
+
+ break;
+
+ default:
+ throw new InvalidInviteException('Sorry, but the invite URL you followed was malformed.');
+ }
+
+ return true;
+
+ }
+
+
+ /**
+ * @param Team $team
+ * @param $associatedVacancies
+ * @return string The success message, exception/bool if error
+ */
+ public function updateVacancies(Team $team, $associatedVacancies): string
+ {
+
+ // P.S. To future developers
+ // This method gave me a lot of trouble lol. It's hard to write code when you're half asleep.
+ // There may be an n+1 query in the view and I don't think there's a way to avoid that without writing a lot of extra code.
+
+ $requestVacancies = $associatedVacancies;
+ $currentVacancies = $team->vacancies->pluck('id')->all();
+
+ if (is_null($requestVacancies)) {
+ foreach ($team->vacancies as $vacancy) {
+ $team->vacancies()->detach($vacancy->id);
+ }
+
+ return 'Removed all vacancy associations.';
+ }
+
+ $vacancyDiff = array_diff($requestVacancies, $currentVacancies);
+ $deselectedDiff = array_diff($currentVacancies, $requestVacancies);
+
+ if (! empty($vacancyDiff) || ! empty($deselectedDiff)) {
+ foreach ($vacancyDiff as $selectedVacancy) {
+ $team->vacancies()->attach($selectedVacancy);
+ }
+
+ foreach ($deselectedDiff as $deselectedVacancy) {
+ $team->vacancies()->detach($deselectedVacancy);
+ }
+ } else {
+ $team->vacancies()->attach($requestVacancies);
+ }
+ return 'Assignments changed successfully.';
+ }
+}
diff --git a/app/Services/VacancyApplicationService.php b/app/Services/VacancyApplicationService.php
new file mode 100755
index 0000000..c1fbddc
--- /dev/null
+++ b/app/Services/VacancyApplicationService.php
@@ -0,0 +1,47 @@
+.
+ */
+
+namespace App\Services;
+
+use App\Application;
+use App\Vacancy;
+
+class VacancyApplicationService
+{
+ /**
+ * Finds all applications associated with $model.
+ *
+ * @param Vacancy $model The model you want to search through.
+ * @return Illuminate\Support\Collection A collection of applications
+ */
+ public function findApplications(Vacancy $model)
+ {
+ $applications = collect([]);
+
+ foreach (Application::all() as $application) {
+ if ($application->response->vacancy->id == $model->id) {
+ $applications->push($application);
+ }
+ }
+
+ return $applications;
+ }
+}
diff --git a/app/StaffProfile.php b/app/StaffProfile.php
old mode 100644
new mode 100755
index 8d6cfba..87d131b
--- a/app/StaffProfile.php
+++ b/app/StaffProfile.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -12,7 +31,7 @@ class StaffProfile extends Model
'approvalDate',
'terminationDate',
'resignationDate',
- 'memberNotes'
+ 'memberNotes',
];
}
diff --git a/app/Team.php b/app/Team.php
new file mode 100755
index 0000000..7705421
--- /dev/null
+++ b/app/Team.php
@@ -0,0 +1,46 @@
+.
+ */
+
+namespace App;
+
+use Mpociot\Teamwork\TeamworkTeam;
+
+class Team extends TeamworkTeam
+{
+ public $fillable = [
+ 'owner_id',
+ 'name',
+ 'description',
+ 'openJoin',
+ ];
+
+ public function vacancies()
+ {
+ return $this->belongsToMany('App\Vacancy', 'team_has_vacancy');
+ }
+
+
+
+ public function files()
+ {
+ return $this->hasMany('App\TeamFile', 'team_id');
+ }
+}
diff --git a/app/TeamFile.php b/app/TeamFile.php
new file mode 100755
index 0000000..8a5fedb
--- /dev/null
+++ b/app/TeamFile.php
@@ -0,0 +1,41 @@
+belongsTo('App\User', 'uploaded_by', 'id');
+ }
+
+ public function team()
+ {
+ return $this->belongsTo('App\Team');
+ }
+
+
+ public function getSizeAttribute($value)
+ {
+ return DigitalStorageHelper::setValue($value)->formatBytes(2, true);
+ }
+}
diff --git a/app/Traits/AuthenticatesTwoFactor.php b/app/Traits/AuthenticatesTwoFactor.php
old mode 100644
new mode 100755
index 4b6ab31..9a36d51
--- a/app/Traits/AuthenticatesTwoFactor.php
+++ b/app/Traits/AuthenticatesTwoFactor.php
@@ -1,40 +1,54 @@
.
+ */
+
namespace App\Traits;
-use Google2FA;
use App\Http\Requests\Add2FASecretRequest;
+use Google2FA;
use Illuminate\Support\Facades\Log;
-
trait AuthenticatesTwoFactor
{
-
public function verify2FA(Add2FASecretRequest $request)
{
$isValid = Google2FA::verifyKey($request->user()->twofa_secret, $request->otp);
- if ($isValid)
- {
- Google2FA::login();
+ if ($isValid) {
+ Google2FA::login();
- Log::info('SECURITY (postauth): One-time password verification succeeded', [
- 'initiator' => $request->user()->email,
- 'ip' => $request->ip()
- ]);
+ Log::info('SECURITY (postauth): One-time password verification succeeded', [
+ 'initiator' => $request->user()->email,
+ 'ip' => $request->ip(),
+ ]);
- return redirect()->to($this->redirectTo);
- }
- else
- {
- Log::warning('SECURITY (preauth): One-time password verification failed', [
- 'initiator' => $request->user()->email,
- 'ip' => $request->ip()
- ]);
+ return redirect()->to($this->redirectTo);
+ } else {
+ Log::warning('SECURITY (preauth): One-time password verification failed', [
+ 'initiator' => $request->user()->email,
+ 'ip' => $request->ip(),
+ ]);
- $request->session()->flash('error', 'Your one time password is invalid.');
- return redirect()->back();
+ $request->session()->flash('error', 'Your one time password is invalid.');
+
+ return redirect()->back();
}
}
-
}
diff --git a/app/Traits/Cancellable.php b/app/Traits/Cancellable.php
old mode 100644
new mode 100755
index cbccb67..53a9e37
--- a/app/Traits/Cancellable.php
+++ b/app/Traits/Cancellable.php
@@ -1,24 +1,37 @@
.
+ */
namespace App\Traits;
-
use App\Facades\Options;
trait Cancellable
{
-
public function chooseChannelsViaOptions()
{
$channels = [];
- if (Options::getOption('enable_slack_notifications') == 1)
- {
+ if (Options::getOption('enable_slack_notifications') == 1) {
array_push($channels, 'slack');
- }
- elseif(Options::getOption('enable_email_notifications') == 1)
- {
+ } elseif (Options::getOption('enable_email_notifications') == 1) {
array_push($channels, 'email');
}
@@ -32,18 +45,15 @@ trait Cancellable
public function via($notifiable)
{
- if ($this->optOut($notifiable))
- {
+ if ($this->optOut($notifiable)) {
return [];
}
return $this->channels();
}
-
public function optOut($notifiable)
{
return false;
}
-
}
diff --git a/app/Traits/HandlesAccountTokens.php b/app/Traits/HandlesAccountTokens.php
new file mode 100755
index 0000000..965e54a
--- /dev/null
+++ b/app/Traits/HandlesAccountTokens.php
@@ -0,0 +1,62 @@
+.
+ */
+
+namespace App\Traits;
+
+use Illuminate\Support\Facades\Hash;
+
+trait HandlesAccountTokens
+{
+ public function generateAccountTokens()
+ {
+ $deleteToken = bin2hex(openssl_random_pseudo_bytes(32));
+ $cancelToken = bin2hex(openssl_random_pseudo_bytes(32));
+
+ $tokens = [
+
+ 'delete' => Hash::make($deleteToken),
+ 'cancel' => Hash::make($cancelToken),
+
+ ];
+
+ $this->account_tokens = json_encode($tokens);
+ $this->save();
+
+ return [
+
+ 'delete' => $deleteToken,
+ 'cancel' => $cancelToken,
+ ];
+ }
+
+ public function verifyAccountToken(string $token, string $type): bool
+ {
+ $tokens = json_decode($this->account_tokens);
+
+ if ($type == 'deleteToken') {
+ return Hash::check($token, $tokens->delete);
+ } elseif ($type == 'cancelToken') {
+ return Hash::check($token, $tokens->cancel);
+ }
+
+ return false;
+ }
+}
diff --git a/app/Traits/ReceivesAccountTokens.php b/app/Traits/ReceivesAccountTokens.php
new file mode 100755
index 0000000..6599fa9
--- /dev/null
+++ b/app/Traits/ReceivesAccountTokens.php
@@ -0,0 +1,108 @@
+.
+ */
+
+namespace App\Traits;
+
+use App\Http\Requests\UserDeleteRequest;
+use App\Mail\UserAccountDeleteConfirmation;
+use App\User;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Mail;
+
+trait ReceivesAccountTokens
+{
+ public function userDelete(UserDeleteRequest $request)
+ {
+ if (config('demo.is_enabled'))
+ {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
+
+ // a little verbose
+ $user = User::find(Auth::user()->id);
+ $tokens = $user->generateAccountTokens();
+
+ Mail::to($user)->send(new UserAccountDeleteConfirmation($user, $tokens, $request->ip()));
+
+ $user->delete();
+ Auth::logout();
+
+ $request->session()->flash('success', __('Please check your email to finish deleting your account.'));
+
+ return redirect()->to('/');
+ }
+
+ public function processDeleteConfirmation(Request $request, $ID, $action, $token)
+ {
+ if (config('demo.is_enabled'))
+ {
+ return redirect()
+ ->back()
+ ->with('error', 'This feature is disabled');
+ }
+
+ // We can't rely on Laravel's route model injection, because it'll ignore soft-deleted models,
+ // so we have to use a special scope to find them ourselves.
+ $user = User::withTrashed()->findOrFail($ID);
+ $email = $user->email;
+
+ switch ($action) {
+ case 'confirm':
+
+ if ($user->verifyAccountToken($token, 'deleteToken')) {
+ Log::info('SECURITY: User deleted account!', [
+
+ 'confirmDeleteToken' => $token,
+ 'ipAddress' => $request->ip(),
+ 'email' => $user->email,
+
+ ]);
+
+ $user->forceDelete();
+
+ $request->session()->flash('success', __('Account permanently deleted. Thank you for using our service.'));
+
+ return redirect()->to('/');
+ }
+
+ break;
+
+ case 'cancel':
+
+ if ($user->verifyAccountToken($token, 'cancelToken')) {
+ $user->restore();
+ $request->session()->flash('success', __('Account deletion cancelled! You may now login.'));
+
+ return redirect()->to(route('login'));
+ }
+
+ break;
+
+ default:
+
+ abort(404, __('The page you were trying to access may not exist or may be expired.'));
+ }
+ }
+}
diff --git a/app/UUID/UUID.php b/app/UUID/UUID.php
old mode 100644
new mode 100755
index cee10d1..2a4de20
--- a/app/UUID/UUID.php
+++ b/app/UUID/UUID.php
@@ -1,59 +1,66 @@
.
+ */
namespace App\UUID;
-use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Http;
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!');
+ if (is_null($username)) {
+ throw new \LogicException('Argument username for '.__METHOD__.' cannot be null!');
}
- $response = json_decode(Http::post(trim(config('general.urls.mojang.api')) . '/profiles/minecraft', [
- $username
+ $response = json_decode(Http::post(trim(config('general.urls.mojang.api')).'/profiles/minecraft', [
+ $username,
])->body(), true);
- if (isset($response[0]))
- {
- return $response[0]['id'];
-
+ if (isset($response[0])) {
+ return $response[0]['id'];
}
- throw new \InvalidArgumentException("You must supply a valid, premium Minecraft account to sign up.");
+ throw new \InvalidArgumentException('You must supply a valid, premium Minecraft account to sign up.');
}
// 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!');
+ 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) {
+ $shortUUID = substr($uuid, 0, 8);
+ $username = Cache::remember('uuid_'.$shortUUID, now()->addDays(30), function () use ($shortUUID, $uuid) {
+ $response = json_decode(Http::get(trim(config('general.urls.mojang.session')).'/session/minecraft/profile/'.$uuid)->body(), true);
- $response = json_decode(Http::get(trim(config('general.urls.mojang.session')) . '/session/minecraft/profile/' . $uuid)->body(), true);
+ Log::debug('Caching '.$shortUUID.'for thirty days');
- Log::debug('Caching ' . $shortUUID . 'for thirty days');
return $response['name'];
+ });
- });
-
- return $username;
-
+ return $username;
}
-
-
}
diff --git a/app/User.php b/app/User.php
old mode 100644
new mode 100755
index 06f555f..e3907ba
--- a/app/User.php
+++ b/app/User.php
@@ -1,16 +1,37 @@
.
+ */
+
namespace App;
+use App\Traits\HandlesAccountTokens;
use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
+use Mpociot\Teamwork\Traits\UserHasTeams;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmail
{
- use Notifiable;
- use HasRoles;
+ use UserHasTeams, Notifiable, HasRoles, SoftDeletes, HandlesAccountTokens;
/**
* The attributes that are mass assignable.
@@ -18,7 +39,7 @@ class User extends Authenticatable implements MustVerifyEmail
* @var array
*/
protected $fillable = [
- 'name', 'email', 'password', 'originalIP', 'username', 'uuid', 'dob'
+ 'name', 'email', 'password', 'originalIP', 'username', 'uuid', 'dob',
];
/**
@@ -39,8 +60,8 @@ class User extends Authenticatable implements MustVerifyEmail
'email_verified_at' => 'datetime',
];
+ // RELATIONSHIPS
-//
public function applications()
{
return $this->hasMany('App\Application', 'applicantUserID', 'id');
@@ -66,15 +87,23 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->hasMany('App\Comment', 'authorID', 'id');
}
+ public function files()
+ {
+ return $this->hasMany('App\TeamFile', 'uploaded_by');
+ }
+
+ public function keys()
+ {
+ return $this->hasMany('App\ApiKey', 'owner_user_id');
+ }
+
+ // UTILITY LOGIC
public function isBanned()
{
- return !$this->bans()->get()->isEmpty();
+ return ! $this->bans()->get()->isEmpty();
}
-
-
-
public function isStaffMember()
{
return $this->hasAnyRole('reviewer', 'admin', 'hiringManager');
@@ -82,13 +111,26 @@ class User extends Authenticatable implements MustVerifyEmail
public function has2FA()
{
- return !is_null($this->twofa_secret);
+ return ! is_null($this->twofa_secret);
}
-
+ public function hasTeam($team): bool
+ {
+ if ($team instanceof Team || is_int($team))
+ {
+ return $this->teams->contains($team);
+ }
+ else
+ {
+ /**
+ * In PHP 8, we can just use union types and let PHP enforce this for us.
+ */
+ throw new \InvalidArgumentException('Please pass either a Team object or an integer identifying a Team.');
+ }
+ }
public function routeNotificationForSlack($notification)
{
- return config('slack.webhook.integrationURL');
+ return config('slack.webhook.integrationURL');
}
}
diff --git a/app/Vacancy.php b/app/Vacancy.php
old mode 100644
new mode 100755
index 1a84996..0829a4e
--- a/app/Vacancy.php
+++ b/app/Vacancy.php
@@ -1,16 +1,36 @@
.
+ */
+
namespace App;
+use GrahamCampbell\Markdown\Facades\Markdown;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
-
-use GrahamCampbell\Markdown\Facades\Markdown;
-
+use Mpociot\Teamwork\Traits\UsedByTeams;
class Vacancy extends Model
{
+ //use UsedByTeams;
+
public $fillable = [
'permissionGroupName',
@@ -21,29 +41,30 @@ class Vacancy extends Model
'vacancyFormID',
'vacancyCount',
'vacancyStatus',
- 'vacancySlug'
+ 'vacancySlug',
+ 'team_id',
];
-
/**
- * Get the HTML variant of the vacancyFullDescription attribute.
- *
- * @param string $value The original value
- * @return string
- */
+ * Get the HTML variant of the vacancyFullDescription attribute.
+ *
+ * @param string $value The original value
+ * @return string
+ */
public function getVacancyFullDescriptionAttribute($value)
{
- if (!is_null($value))
- {
- return Markdown::convertToHTML($value);
- }
- else
- {
- return null;
+ if (! is_null($value)) {
+ return Markdown::convertToHTML($value);
+ } else {
+ return null;
}
}
+ public function teams()
+ {
+ return $this->belongsToMany('App\Team', 'team_has_vacancy');
+ }
public function forms()
{
@@ -53,20 +74,42 @@ class Vacancy extends Model
public function open()
{
$this->update([
- 'vacancyStatus' => 'OPEN'
+ 'vacancyStatus' => 'OPEN',
]);
- Log::info("Vacancies: Vacancy " . $this->id . " (" . $this->vacancyName . ") opened by " . Auth::user()->name);
+ Log::info('Vacancies: Vacancy '.$this->id.' ('.$this->vacancyName.') opened by '.Auth::user()->name);
}
public function close()
{
$this->update([
- 'vacancyStatus' => 'CLOSED'
+ 'vacancyStatus' => 'CLOSED',
]);
- Log::warning("Vacancies: Vacancy " . $this->id . " (" . $this->vacancyName . ") closed by " . Auth::user()->name);
-
+ Log::warning('Vacancies: Vacancy '.$this->id.' ('.$this->vacancyName.') closed by '.Auth::user()->name);
}
+ /**
+ * Check if the Modal is attached to the $checkingTeam Model.
+ *
+ * @param Team $checkingTeam The mdoel you want to check against
+ * @return bool Whether the models are attached
+ */
+ public function hasTeam(Team $checkingTeam): bool
+ {
+ $myTeams = $this->teams;
+
+ if (empty($myTeams)) {
+ // no associated teams
+ return false;
+ }
+
+ foreach ($myTeams as $team) {
+ if ($team->id === $checkingTeam->id) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/app/View/Components/Alert.php b/app/View/Components/Alert.php
old mode 100644
new mode 100755
index 04b5f3c..be497b4
--- a/app/View/Components/Alert.php
+++ b/app/View/Components/Alert.php
@@ -1,12 +1,30 @@
.
+ */
+
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
-
public $alertType;
public $extraStyling;
diff --git a/app/View/Components/Card.php b/app/View/Components/Card.php
old mode 100644
new mode 100755
index 6a5a953..ee20d0d
--- a/app/View/Components/Card.php
+++ b/app/View/Components/Card.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\View\Components;
use Illuminate\View\Component;
@@ -8,14 +27,10 @@ class Card extends Component
{
public $id;
-
public $cardTitle;
-
-
public $footerStyle;
-
/**
* Create a new component instance.
*
diff --git a/app/View/Components/Form.php b/app/View/Components/Form.php
old mode 100644
new mode 100755
index 06e868d..821ea5d
--- a/app/View/Components/Form.php
+++ b/app/View/Components/Form.php
@@ -1,16 +1,34 @@
.
+ */
+
namespace App\View\Components;
use Illuminate\View\Component;
class Form extends Component
{
-
public $formFields;
-
public $disableFields = false;
+
/**
* Create a new component instance.
*
@@ -18,7 +36,7 @@ class Form extends Component
*/
public function __construct($disableFields = false)
{
- $this->disableFields = $disableFields;
+ $this->disableFields = $disableFields;
}
/**
diff --git a/app/View/Components/GlobalErrors.php b/app/View/Components/GlobalErrors.php
old mode 100644
new mode 100755
index ab130be..5360e13
--- a/app/View/Components/GlobalErrors.php
+++ b/app/View/Components/GlobalErrors.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\View\Components;
use Illuminate\View\Component;
diff --git a/app/View/Components/Modal.php b/app/View/Components/Modal.php
old mode 100644
new mode 100755
index 4ab43d3..fd23b3f
--- a/app/View/Components/Modal.php
+++ b/app/View/Components/Modal.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\View\Components;
use Illuminate\View\Component;
@@ -8,13 +27,10 @@ class Modal extends Component
{
public $id;
-
public $modalLabel;
-
public $modalTitle;
-
public $includeCloseButton;
/**
diff --git a/app/View/Components/NoPermission.php b/app/View/Components/NoPermission.php
old mode 100644
new mode 100755
index 6da51a1..f55f30a
--- a/app/View/Components/NoPermission.php
+++ b/app/View/Components/NoPermission.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App\View\Components;
use Illuminate\View\Component;
@@ -9,6 +28,7 @@ class NoPermission extends Component
public $type;
public $inDashboard;
+
/**
* Create a new component instance.
*
@@ -16,9 +36,9 @@ class NoPermission extends Component
*/
public function __construct($type, $inDashboard = true)
{
- $this->type = $type;
+ $this->type = $type;
- $this->inDashboard = $inDashboard;
+ $this->inDashboard = $inDashboard;
}
/**
diff --git a/app/Vote.php b/app/Vote.php
old mode 100644
new mode 100755
index 6a89b21..74a5aa0
--- a/app/Vote.php
+++ b/app/Vote.php
@@ -1,5 +1,24 @@
.
+ */
+
namespace App;
use Illuminate\Database\Eloquent\Model;
@@ -14,7 +33,7 @@ class Vote extends Model
];
public $touches = [
- 'application'
+ 'application',
];
public function user()
diff --git a/artisan b/artisan
old mode 100644
new mode 100755
diff --git a/bootstrap/app.php b/bootstrap/app.php
old mode 100644
new mode 100755
index 037e17d..c89db0b
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -1,15 +1,23 @@
.
+ */
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
diff --git a/composer.json b/composer.json
old mode 100644
new mode 100755
index 85eeb76..2429304
--- a/composer.json
+++ b/composer.json
@@ -16,14 +16,13 @@
"fideloper/proxy": "^4.2",
"fruitcake/laravel-cors": "^1.0",
"geo-sot/laravel-env-editor": "^0.9.9",
- "graham-campbell/markdown": "^13.1",
- "guzzlehttp/guzzle": "^7.0.1",
"jeroennoten/laravel-adminlte": "^3.2",
"laravel/framework": "^8.0",
"laravel/slack-notification-channel": "^2.0",
"laravel/tinker": "^2.0",
"laravel/ui": "^3.0",
"mcamara/laravel-localization": "^1.5",
+ "mpociot/teamwork": "^6.0",
"pragmarx/google2fa-laravel": "^1.3",
"sentry/sentry-laravel": "2.9.0",
"spatie/laravel-permission": "^3.13"
diff --git a/config/adminlte.php b/config/adminlte.php
old mode 100644
new mode 100755
index 9c71a48..6df80ce
--- a/config/adminlte.php
+++ b/config/adminlte.php
@@ -1,5 +1,24 @@
.
+ */
+
return [
/*
@@ -50,7 +69,7 @@ return [
'logo_img_class' => 'brand-image img-circle elevation-3',
'logo_img_xl' => null,
'logo_img_xl_class' => 'brand-image-xs',
- 'logo_img_alt' => env('APP_NAME') . '\'s Temporary Logo',
+ 'logo_img_alt' => env('APP_NAME').'\'s Temporary Logo',
/*
|--------------------------------------------------------------------------
@@ -211,17 +230,17 @@ return [
[
'text' => 'm_home',
'icon' => 'fas fa-home',
- 'url' => 'dashboard'
+ 'url' => 'dashboard',
],
[
'text' => 'm_directory',
'icon' => 'fas fa-users',
'url' => 'users/directory',
- 'can' => 'profiles.view.others'
+ 'can' => 'profiles.view.others',
],
[
'header' => 'h_applications',
- 'can' => 'applications.view.own'
+ 'can' => 'applications.view.own',
],
[
'text' => 'm_my_applications',
@@ -231,8 +250,8 @@ return [
[
'text' => 'm_curr_applications',
'icon' => 'fas fa-fw fa-check-double',
- 'url' => '/applications/my-applications'
- ]
+ 'url' => '/applications/my-applications',
+ ],
],
],
@@ -242,40 +261,42 @@ return [
[
'text' => 'm_profile_settings',
'url' => '/profile/settings',
- 'icon' => 'fas fa-fw fa-cog'
+ 'icon' => 'fas fa-fw fa-cog',
],
[
'text' => 'm_account_settings',
'icon' => 'fas fa-user-circle',
- 'url' => '/profile/settings/account'
+ 'url' => '/profile/settings/account',
],
[
'header' => 'h_app_management',
- 'can' => ['applications.view.all', 'applications.vote']
+ 'can' => ['applications.view.all', 'applications.vote'],
],
[
'text' => 'm_all_apps',
'url' => 'applications/staff/all',
'icon' => 'fas fa-list-ol',
- 'can' => 'applications.view.all'
+ 'can' => 'applications.view.all',
],
[
- 'text' => 'm_outstanding_apps',
- 'url' => '/applications/staff/outstanding',
- 'icon' => 'far fa-folder-open',
- 'can' => 'applications.view.all'
- ],
- [
- 'text' => 'm_interview_queue',
- 'url' => '/applications/staff/pending-interview',
- 'icon' => 'fas fa-fw fa-microphone-alt',
- 'can' => 'applications.view.all'
- ],
- [
- 'text' => 'm_peer_approval',
- 'url' => '/applications/staff/peer-review',
- 'icon' => 'fas fa-fw fa-search',
- 'can' => 'applications.view.all'
+ 'text' => 'Teams',
+ 'icon' => 'fas fa-user-friends',
+ 'url' => 'teams',
+ 'can' => 'teams.view',
+ 'submenu' => [
+ [
+ 'text' => 'Available Teams',
+ 'icon' => 'fas fa-clipboard',
+ 'url' => 'teams',
+ 'can' => 'teams.view'
+ ],
+ [
+ 'text' => 'Files',
+ 'icon' => 'fas fa-file-alt',
+ 'url' => 'team/files',
+ 'can' => 'teams.view'
+ ],
+ ]
],
[
'header' => 'h_admin',
@@ -284,20 +305,20 @@ return [
'admin.userlist',
'admin.stafflist',
'admin.hiring.*',
- 'admin.notificationsettings.*'
- ]
+ 'admin.notificationsettings.*',
+ ],
],
[
'text' => 'm_staff_m',
'icon' => 'fas fa-fw fa-users',
'url' => '/hr/staff-members',
- 'can' => 'admin.stafflist'
+ 'can' => 'admin.stafflist',
],
[ // players who haven't been promoted yet
'text' => 'm_reg_players',
'icon' => 'fas fa-fw fa-user-friends',
'url' => '/hr/players',
- 'can' => 'admin.userlist'
+ 'can' => 'admin.userlist',
],
[
'text' => 'sm_hiring_man',
@@ -307,7 +328,7 @@ return [
[
'text' => 'm_open_pos',
'icon' => 'fas fa-box-open',
- 'url' => '/admin/positions'
+ 'url' => '/admin/positions',
],
[
'text' => 'sm_forms',
@@ -316,16 +337,16 @@ return [
[
'text' => 'sm_all_forms',
'icon' => 'far fa-list-alt',
- 'url' => '/admin/forms'
+ 'url' => '/admin/forms',
],
[
'text' => 'm_form_builder',
'icon' => 'fas fa-fw fa-hammer',
- 'url' => '/admin/forms/builder'
- ]
- ]
- ]
- ]
+ 'url' => '/admin/forms/builder',
+ ],
+ ],
+ ],
+ ],
],
[
'text' => 'sm_app_settings',
@@ -336,22 +357,28 @@ return [
'text' => 'm_global_app_s',
'icon' => 'fas fa-cogs',
'url' => '/admin/settings',
- 'can' => 'admin.settings.view'
+ 'can' => 'admin.settings.view',
],
[
'text' => 'm_devtools',
'icon' => 'fas fa-code',
'url' => '/admin/devtools',
- 'can' => 'admin.developertools.use'
+ 'can' => 'admin.developertools.use',
+ ],
+ [
+ 'text' => 'API Keys',
+ 'icon' => 'fas fa-user-shield',
+ 'can' => 'admin.settings.view',
+ 'route' => 'keys.index'
]
- ]
+ ],
],
[
'text' => 'm_s_logs',
'url' => '/admin/maintenance/system-logs',
'icon' => 'fas fa-clipboard-list',
- 'can' => 'admin.maintenance.logs.view'
- ]
+ 'can' => 'admin.maintenance.logs.view',
+ ],
],
/*
@@ -417,9 +444,9 @@ return [
[
'type' => 'js',
'asset' => false,
- 'location' => '/js/formbuilder.js'
- ]
- ]
+ 'location' => '/js/formbuilder.js',
+ ],
+ ],
],
[
'name' => 'Select2',
@@ -482,14 +509,14 @@ return [
[
'type' => 'js',
'asset' => false,
- 'location' => 'https://cdn.jsdelivr.net/npm/toastr@2.1.4/toastr.min.js'
+ 'location' => 'https://cdn.jsdelivr.net/npm/toastr@2.1.4/toastr.min.js',
],
[
'type' => 'css',
'asset' => false,
- 'location' => 'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css'
- ]
- ]
+ 'location' => 'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css',
+ ],
+ ],
],
[
'name' => 'GlobalTooltip',
@@ -498,9 +525,9 @@ return [
[
'type' => 'js',
'asset' => false,
- 'location' => '/js/globaltooltip.js'
- ]
- ]
+ 'location' => '/js/globaltooltip.js',
+ ],
+ ],
],
[
'name' => 'DatePickApp',
@@ -509,36 +536,96 @@ return [
[
'type' => 'js',
'asset' => false,
- 'location' => '/js/datepick.js'
- ]
- ]
+ 'location' => '/js/datepick.js',
+ ],
+ ],
],
[
- 'name' => 'Fullcalendar',
- 'active' => true,
- 'files' => [
- [
- 'type' => 'js',
- 'asset' => false,
- 'location' => 'https://cdn.jsdelivr.net/npm/fullcalendar@5.0.1/main.min.js',
+ 'name' => 'Fullcalendar',
+ 'active' => true,
+ 'files' => [
+ [
+ 'type' => 'js',
+ 'asset' => false,
+ 'location' => 'https://cdn.jsdelivr.net/npm/fullcalendar@5.0.1/main.min.js',
+ ],
+ [
+ 'type' => 'css',
+ 'asset' => false,
+ 'location' => 'https://cdn.jsdelivr.net/npm/fullcalendar@5.0.1/main.min.css',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'CheckboxValues',
+ 'active' => true,
+ 'files' => [
+ [
+ 'type' => 'js',
+ 'asset' => false,
+ 'location' => '/js/switches.js',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'AuthCustomisations',
+ 'active' => true,
+ 'files' => [
+ [
+ 'type' => 'css',
+ 'asset' => false,
+ 'location' => '/css/authpages.css',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'BootstrapToggleButton',
+ 'active' => true,
+ 'files' => [
+ [
+ 'type' => 'css',
+ 'asset' => false,
+ 'location' => 'https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css',
+ ],
+ [
+ 'type' => 'js',
+ 'asset' => false,
+ 'location' => 'https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js',
+ ],
+ ],
],
[
- 'type' => 'css',
- 'asset' => false,
- 'location' => 'https://cdn.jsdelivr.net/npm/fullcalendar@5.0.1/main.min.css'
- ]
- ]
- ],
- [
- 'name' => 'AuthCustomisations',
- 'active' => true,
- 'files' => [
+ 'name' => 'BootstrapMultiselectDropdown',
+ 'active' => true,
+ 'files' => [
+ [
+ 'type' => 'js',
+ 'asset' => 'false',
+ 'location' => 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/js/bootstrap-multiselect.min.js',
+ ],
+ [
+ 'type' => 'css',
+ 'asset' => false,
+ 'location' => 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css',
+ ],
+ ],
+
+ ],
[
- 'type' => 'css',
- 'asset' => false,
- 'location' => '/css/authpages.css'
+ 'name' => 'BootstrapSwitch',
+ 'active' => true,
+ 'files' => [
+ [
+ 'type' => 'js',
+ 'asset' => false,
+ 'location' => 'https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js'
+ ],
+ [
+ 'type' => 'css',
+ 'asset' => false,
+ 'location' => 'https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css'
+ ]
+ ]
]
- ]
- ]
],
];
diff --git a/config/app.php b/config/app.php
old mode 100644
new mode 100755
index 96e5484..223f750
--- a/config/app.php
+++ b/config/app.php
@@ -1,5 +1,24 @@
.
+ */
+
return [
/*
@@ -15,7 +34,6 @@ return [
'name' => env('APP_NAME', 'Laravel'),
-
/*
|--------------------------------------------------------------------------
| Application Homepage
@@ -28,6 +46,37 @@ return [
*/
'sitehomepage' => env('APP_SITEHOMEPAGE', 'https://google.com'),
+
+
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Version
+ |--------------------------------------------------------------------------
+ |
+ | This value is the application's version.
+ | It's used for informational purposes, and it'll be used for an auto-update system
+ | in the near future.
+ | Should always be the latest minor release.
+ |
+ */
+ 'release' => env('RELEASE', '(unknown)'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | SSL for non-production environments
+ |--------------------------------------------------------------------------
+ |
+ | If you're a developer, and need to use SSL locally for testing,
+ | enable this setting.
+ | It forces Laravel to load all assets via HTTPS, even when the environment is
+ | set to "local". This setting is useless in production because it's already enforced.
+ | If you don't enable this when using SSL locally, the pages won't load properly.
+ | If you're a regular user, don't touch this setting.
+ |
+ */
+ 'force_secure' => env('NONPROD_FORCE_SECURE', false),
+
/*
|--------------------------------------------------------------------------
| Application Environment
@@ -193,7 +242,9 @@ return [
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
\App\Providers\MojangStatusProvider::class,
- \App\Providers\OptionsProvider::class
+ \App\Providers\OptionsProvider::class,
+ App\Providers\DigitalStorageProvider::class,
+ App\Providers\JSONProvider::class,
],
@@ -250,7 +301,8 @@ return [
'IP' => App\Facades\IP::class,
'Markdown' => GrahamCampbell\Markdown\Facades\Markdown::class,
'ContextAwareValidator' => App\Facades\ContextAwareValidation::class,
- 'Settings' => App\Facades\Options::class
+ 'Settings' => App\Facades\Options::class,
+ 'JSON' => App\Facades\JSON::class
],
diff --git a/config/auth.php b/config/auth.php
old mode 100644
new mode 100755
index aaf982b..071543c
--- a/config/auth.php
+++ b/config/auth.php
@@ -1,5 +1,24 @@
.
+ */
+
return [
/*
diff --git a/config/broadcasting.php b/config/broadcasting.php
old mode 100644
new mode 100755
index 3bba110..2fa0dee
--- a/config/broadcasting.php
+++ b/config/broadcasting.php
@@ -1,5 +1,24 @@
.
+ */
+
return [
/*
diff --git a/config/cache.php b/config/cache.php
old mode 100644
new mode 100755
index 4f41fdf..475421a
--- a/config/cache.php
+++ b/config/cache.php
@@ -1,5 +1,24 @@
.
+ */
+
use Illuminate\Support\Str;
return [
diff --git a/config/cors.php b/config/cors.php
old mode 100644
new mode 100755
index 558369d..c06d99f
--- a/config/cors.php
+++ b/config/cors.php
@@ -1,5 +1,24 @@
.
+ */
+
return [
/*
diff --git a/config/database.php b/config/database.php
old mode 100644
new mode 100755
index b42d9b3..493e1af
--- a/config/database.php
+++ b/config/database.php
@@ -1,5 +1,24 @@
.
+ */
+
use Illuminate\Support\Str;
return [
diff --git a/config/debugbar.php b/config/debugbar.php
new file mode 100755
index 0000000..87b003e
--- /dev/null
+++ b/config/debugbar.php
@@ -0,0 +1,235 @@
+.
+ */
+
+return [
+
+ /*
+ |--------------------------------------------------------------------------
+ | Debugbar Settings
+ |--------------------------------------------------------------------------
+ |
+ | Debugbar is enabled by default, when debug is set to true in app.php.
+ | You can override the value by setting enable to true or false instead of null.
+ |
+ | You can provide an array of URI's that must be ignored (eg. 'api/*')
+ |
+ */
+
+ 'enabled' => env('DEBUGBAR_ENABLED', null),
+ 'except' => [
+ 'telescope*',
+ 'horizon*',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Storage settings
+ |--------------------------------------------------------------------------
+ |
+ | DebugBar stores data for session/ajax requests.
+ | You can disable this, so the debugbar stores data in headers/session,
+ | but this can cause problems with large data collectors.
+ | By default, file storage (in the storage folder) is used. Redis and PDO
+ | can also be used. For PDO, run the package migrations first.
+ |
+ */
+ 'storage' => [
+ 'enabled' => true,
+ 'driver' => 'file', // redis, file, pdo, custom
+ 'path' => storage_path('debugbar'), // For file driver
+ 'connection' => null, // Leave null for default connection (Redis/PDO)
+ 'provider' => '', // Instance of StorageInterface for custom driver
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Vendors
+ |--------------------------------------------------------------------------
+ |
+ | Vendor files are included by default, but can be set to false.
+ | This can also be set to 'js' or 'css', to only include javascript or css vendor files.
+ | Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
+ | and for js: jquery and and highlight.js
+ | So if you want syntax highlighting, set it to true.
+ | jQuery is set to not conflict with existing jQuery scripts.
+ |
+ */
+
+ 'include_vendors' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Capture Ajax Requests
+ |--------------------------------------------------------------------------
+ |
+ | The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
+ | you can use this option to disable sending the data through the headers.
+ |
+ | Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools.
+ */
+
+ 'capture_ajax' => true,
+ 'add_ajax_timing' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Custom Error Handler for Deprecated warnings
+ |--------------------------------------------------------------------------
+ |
+ | When enabled, the Debugbar shows deprecated warnings for Symfony components
+ | in the Messages tab.
+ |
+ */
+ 'error_handler' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Clockwork integration
+ |--------------------------------------------------------------------------
+ |
+ | The Debugbar can emulate the Clockwork headers, so you can use the Chrome
+ | Extension, without the server-side code. It uses Debugbar collectors instead.
+ |
+ */
+ 'clockwork' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | DataCollectors
+ |--------------------------------------------------------------------------
+ |
+ | Enable/disable DataCollectors
+ |
+ */
+
+ 'collectors' => [
+ 'phpinfo' => true, // Php version
+ 'messages' => true, // Messages
+ 'time' => true, // Time Datalogger
+ 'memory' => true, // Memory usage
+ 'exceptions' => true, // Exception displayer
+ 'log' => true, // Logs from Monolog (merged in messages if enabled)
+ 'db' => true, // Show database (PDO) queries and bindings
+ 'views' => true, // Views with their data
+ 'route' => true, // Current route information
+ 'auth' => false, // Display Laravel authentication status
+ 'gate' => true, // Display Laravel Gate checks
+ 'session' => true, // Display session data
+ 'symfony_request' => true, // Only one can be enabled..
+ 'mail' => true, // Catch mail messages
+ 'laravel' => false, // Laravel version and environment
+ 'events' => false, // All events fired
+ 'default_request' => false, // Regular or special Symfony request logger
+ 'logs' => false, // Add the latest log messages
+ 'files' => false, // Show the included files
+ 'config' => false, // Display config settings
+ 'cache' => false, // Display cache events
+ 'models' => true, // Display models
+ 'livewire' => true, // Display Livewire (when available)
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Extra options
+ |--------------------------------------------------------------------------
+ |
+ | Configure some DataCollectors
+ |
+ */
+
+ 'options' => [
+ 'auth' => [
+ 'show_name' => true, // Also show the users name/email in the debugbar
+ ],
+ 'db' => [
+ 'with_params' => true, // Render SQL with the parameters substituted
+ 'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
+ 'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
+ 'timeline' => false, // Add the queries to the timeline
+ 'explain' => [ // Show EXPLAIN output on queries
+ 'enabled' => false,
+ 'types' => ['SELECT'], // Deprecated setting, is always only SELECT
+ ],
+ 'hints' => false, // Show hints for common mistakes
+ 'show_copy' => false, // Show copy button next to the query
+ ],
+ 'mail' => [
+ 'full_log' => false,
+ ],
+ 'views' => [
+ 'data' => false, //Note: Can slow down the application, because the data can be quite large..
+ ],
+ 'route' => [
+ 'label' => true, // show complete route on bar
+ ],
+ 'logs' => [
+ 'file' => null,
+ ],
+ 'cache' => [
+ 'values' => true, // collect cache values
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Inject Debugbar in Response
+ |--------------------------------------------------------------------------
+ |
+ | Usually, the debugbar is added just before