Compare commits

..
Author SHA1 Message Date
snyk-bot 0c492b62e3 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-FOLLOWREDIRECTS-2396346
2022-02-09 20:13:18 +00:00
65 changed files with 142 additions and 579 deletions
+1 -5
View File
@@ -22,11 +22,7 @@ class ProcessQueue extends Command
'--stop-when-empty' => null,
]);
$jobOutput = trim(Artisan::output());
if (!empty($jobOutput)) {
Log::info($jobOutput);
}
Log::info(Artisan::output());
///** @var App\Support\WorkCommand $queueWorker */
//$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store'));
-90
View File
@@ -1,90 +0,0 @@
<?php
/**
* This runs any of the cron tasks that are set to run according to the Laravel schedule
*/
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Contracts\Command;
use Illuminate\Console\Scheduling\Schedule;
class Cron
{
/** @var Schedule */
private $scheduler;
/**
* @var string[] The cron tasks which get called/run
*/
private $cronTasks = [
JobQueue::class,
FiveMinute::class,
FifteenMinute::class,
ThirtyMinute::class,
Hourly::class,
Nightly::class,
Weekly::class,
Monthly::class,
];
/**
* @var array Stores the instantiated cron tasks
*/
private $cronRunners = [];
/**
* @param Schedule $scheduler
*/
public function __construct(Schedule $scheduler)
{
$this->scheduler = $scheduler;
foreach ($this->cronTasks as $task) {
/** @var Command $cronTask */
$cronTask = app($task);
$signature = $cronTask->getSignature();
if (empty($signature)) {
continue;
}
$this->cronRunners[$signature] = $cronTask;
}
}
/**
* Try to figure out which commands are supposed to run right now
*
* @return array string of tasks that were run
*/
public function run(): array
{
$events = $this->scheduler->dueEvents(app());
if (empty($events)) {
return [];
}
$run = [];
/** @var \Illuminate\Console\Scheduling\Event $event */
foreach ($events as $event) {
foreach ($this->cronRunners as $signature => $task) {
if (!str_contains($event->command, $signature)) {
continue;
}
$task->callEvent();
$run[] = $signature;
}
}
return $run;
}
}
-26
View File
@@ -1,26 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFifteenMinute;
/**
* The actual cron tasks are in app/Cron
*/
class FifteenMinute extends CronCommand
{
protected $signature = 'cron:fifteen';
protected $description = 'Run the 15 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFifteenMinute());
}
}
-29
View File
@@ -1,29 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFiveMinute;
/**
* This just calls the CronNightly event, so all of the
* listeners, etc can just be called to run those tasks
*
* The actual cron tasks are in app/Cron
*/
class FiveMinute extends CronCommand
{
protected $signature = 'cron:five';
protected $description = 'Run the 5 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFiveMinute());
}
}
+3 -7
View File
@@ -2,14 +2,14 @@
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Contracts\Command;
use App\Events\CronHourly;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class Hourly extends CronCommand
class Hourly extends Command
{
protected $signature = 'cron:hourly';
protected $description = 'Run the hourly cron tasks';
@@ -17,11 +17,7 @@ class Hourly extends CronCommand
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
$this->redirectLoggingToFile('cron');
event(new CronHourly());
}
}
+5 -12
View File
@@ -2,14 +2,14 @@
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Contracts\Command;
use Illuminate\Support\Facades\Artisan;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class JobQueue extends CronCommand
class JobQueue extends Command
{
protected $signature = 'cron:queue';
protected $description = 'Run the cron queue tasks';
@@ -17,16 +17,9 @@ class JobQueue extends CronCommand
public function handle(): void
{
$this->callEvent();
$queueOutput = trim(Artisan::output());
if (!empty($queueOutput)) {
$this->info($queueOutput);
}
}
public function callEvent()
{
$this->redirectLoggingToFile('cron');
Artisan::call('queue:cron');
$this->info(Artisan::output());
}
}
+3 -7
View File
@@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Contracts\Command;
use App\Events\CronMonthly;
/**
@@ -11,7 +11,7 @@ use App\Events\CronMonthly;
*
* The actual cron tasks are in app/Cron
*/
class Monthly extends CronCommand
class Monthly extends Command
{
protected $signature = 'cron:monthly';
protected $description = 'Run the monthly cron tasks';
@@ -19,11 +19,7 @@ class Monthly extends CronCommand
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
$this->redirectLoggingToFile('cron');
event(new CronMonthly());
}
}
+3 -7
View File
@@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Contracts\Command;
use App\Events\CronNightly;
/**
@@ -11,7 +11,7 @@ use App\Events\CronNightly;
*
* The actual cron tasks are in app/Cron
*/
class Nightly extends CronCommand
class Nightly extends Command
{
protected $signature = 'cron:nightly';
protected $description = 'Run the nightly cron tasks';
@@ -19,11 +19,7 @@ class Nightly extends CronCommand
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
$this->redirectLoggingToFile('cron');
event(new CronNightly());
}
}
-26
View File
@@ -1,26 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronThirtyMinute;
/**
* The actual cron tasks are in app/Cron
*/
class ThirtyMinute extends CronCommand
{
protected $signature = 'cron:thirty';
protected $description = 'Run the 30 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronThirtyMinute());
}
}
+3 -7
View File
@@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Contracts\Command;
use App\Events\CronWeekly;
/**
@@ -11,7 +11,7 @@ use App\Events\CronWeekly;
*
* The actual cron tasks are in app/Cron
*/
class Weekly extends CronCommand
class Weekly extends Command
{
protected $signature = 'cron:weekly';
protected $description = 'Run the weekly cron tasks';
@@ -19,11 +19,7 @@ class Weekly extends CronCommand
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
$this->redirectLoggingToFile('cron');
event(new CronWeekly());
}
}
+1 -10
View File
@@ -2,13 +2,10 @@
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Services\CronService;
use Illuminate\Console\Scheduling\Schedule;
@@ -36,16 +33,10 @@ class Kernel extends ConsoleKernel
->withoutOverlapping();
}
/*
* NOTE: IF MORE TASKS ARE ADDED, THEY ALSO MUST BE ADDED TO THE CRON.PHP
*/
$schedule->command(FiveMinute::class)->everyFiveMinutes();
$schedule->command(FifteenMinute::class)->everyFifteenMinutes();
$schedule->command(ThirtyMinute::class)->everyThirtyMinutes();
$schedule->command(Nightly::class)->dailyAt('01:00');
$schedule->command(Hourly::class)->hourly();
$schedule->command(Weekly::class)->weeklyOn(0);
$schedule->command(Monthly::class)->monthlyOn(1);
$schedule->command(Hourly::class)->hourly();
// When spatie-backups runs
/*if (config('backup.backup.enabled', false) === true) {
-10
View File
@@ -29,16 +29,6 @@ abstract class Command extends \Illuminate\Console\Command
}*/
}
/**
* Return the signature of the command
*
* @return string
*/
public function getSignature(): string
{
return $this->signature;
}
/**
* Splice the logger and replace the active handlers with the handlers from the
* a stack in config/logging.php
+4 -5
View File
@@ -87,17 +87,16 @@ abstract class Controller extends \Illuminate\Routing\Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function message($message, $count = null, $attrs = [])
public function message($message, $count = null)
{
$ret = [
$attrs = [
'message' => $message,
'attrs' => $attrs,
];
if ($count !== null) {
$ret['count'] = $count;
$attrs['count'] = $count;
}
return response()->json($ret);
return response()->json($attrs);
}
}
-20
View File
@@ -1,20 +0,0 @@
<?php
namespace App\Contracts;
abstract class CronCommand extends Command
{
/**
* @return mixed
*/
abstract public function callEvent();
/**
* Adjust the logging depending on where we're running from
*/
public function __construct()
{
parent::__construct();
$this->redirectLoggingToFile('cron');
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ class ClearExpiredSimbrief extends Listener
}
/**
* @param CronHourly $event
* @param \App\Events\CronNightly $event
*/
public function handle(CronHourly $event): void
{
@@ -6,7 +6,6 @@ use App\Contracts\Listener;
use App\Events\CronHourly;
use App\Events\PirepCancelled;
use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus;
use App\Models\Pirep;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
@@ -32,7 +31,6 @@ class RemoveExpiredLiveFlights extends Listener
$date = Carbon::now('UTC')->subHours(setting('acars.live_time'));
$pireps = Pirep::where('updated_at', '<', $date)
->where('state', PirepState::IN_PROGRESS)
->where('status', '<>', PirepStatus::PAUSED)
->get();
foreach ($pireps as $pirep) {
@@ -1,15 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateUsersAddNotes extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->mediumText('notes')->nullable()->after('remember_token');
});
}
}
-35
View File
@@ -410,41 +410,6 @@
options: ''
type: text
description: The Discord Webhook URL for private notifications
- key: notifications.discord_pirep_status
name: Discord Pirep Messages (Public)
group: notifications
value: true
options: ''
type: boolean
description: Pirep status messages (Only key events are being sent)
- key: notifications.mail_pirep_admin
name: Pirep Filed (Admin)
group: notifications
value: true
options: ''
type: boolean
description: Pirep filed mails sent to admins
- key: notifications.mail_pirep_user_ack
name: Pirep Accepted (Pilot)
group: notifications
value: true
options: ''
type: boolean
description: Pirep Accepted mails sent to pilots
- key: notifications.mail_pirep_user_rej
name: Pirep Rejected (Pilot)
group: notifications
value: true
options: ''
type: boolean
description: Pirep Rejected mails sent to pilots
- key: notifications.mail_news
name: News Mails
group: notifications
value: true
options: ''
type: boolean
description: News mails sent to all members
- key: 'cron.random_id'
name: 'Cron Randomized ID'
group: 'cron'
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFifteenMinute extends Event
{
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFiveMinute extends Event
{
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronThirtyMinute extends Event
{
}
@@ -38,7 +38,7 @@ class AirlinesController extends Controller
public function index(Request $request)
{
$this->airlineRepo->pushCriteria(new RequestCriteria($request));
$airlines = $this->airlineRepo->orderby('name', 'asc')->get();
$airlines = $this->airlineRepo->all();
return view('admin.airlines.index', [
'airlines' => $airlines,
@@ -308,7 +308,7 @@ class FlightController extends Controller
$where['airline_id'] = $airline_id;
$file_name = 'flights-'.$airline_id.'.csv';
}
$flights = $this->flightRepo->where($where)->orderBy('airline_id')->orderBy('flight_number')->orderBy('route_code')->orderBy('route_leg')->get();
$flights = $this->flightRepo->where($where)->get();
$path = $exporter->exportFlights($flights);
return response()->download($path, $file_name, ['content-type' => 'text/csv'])->deleteFileAfterSend(true);
@@ -83,7 +83,7 @@ class SubfleetController extends Controller
public function index(Request $request)
{
$this->subfleetRepo->with(['airline'])->pushCriteria(new RequestCriteria($request));
$subfleets = $this->subfleetRepo->orderby('name', 'asc')->get();
$subfleets = $this->subfleetRepo->all();
return view('admin.subfleets.index', [
'subfleets' => $subfleets,
@@ -32,7 +32,7 @@ class TypeRatingController extends Controller
public function index(Request $request)
{
$this->typeratingRepo->pushCriteria(new RequestCriteria($request));
$typeratings = $this->typeratingRepo->orderby('type', 'asc')->get();
$typeratings = $this->typeratingRepo->all();
return view('admin.typeratings.index', [
'typeratings' => $typeratings,
@@ -50,6 +50,7 @@ class TypeRatingController extends Controller
$model = $this->typeratingRepo->create($input);
Flash::success('Type Rating saved successfully.');
// Cache::forget(config('cache.keys.RANKS_PILOT_LIST.key'));
return redirect(route('admin.typeratings.edit', [$model->id]));
}
@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api;
use App\Console\Cron;
use App\Contracts\Controller;
use App\Exceptions\CronInvalid;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
class MaintenanceController extends Controller
{
@@ -24,12 +24,12 @@ class MaintenanceController extends Controller
throw new CronInvalid();
}
$cron = app(Cron::class);
$run = $cron->run();
$output = '';
Artisan::call('schedule:run');
$output .= trim(Artisan::output());
return response()->json([
'count' => count($run),
'tasks' => $run,
return response([
'content' => $output,
]);
}
}
+3 -5
View File
@@ -334,18 +334,16 @@ class PirepController extends Controller
*
* @throws \Prettus\Validator\Exceptions\ValidatorException
*
* @return mixed
* @return PirepResource
*/
public function cancel($pirep_id, Request $request)
{
Log::info('PIREP '.$pirep_id.' Cancel, user '.Auth::id(), $request->post());
$pirep = Pirep::find($pirep_id);
if (!empty($pirep)) {
$this->pirepSvc->cancel($pirep);
}
$this->pirepSvc->cancel($pirep);
return $this->message('PIREP '.$pirep_id.' cancelled');
return new PirepResource($pirep);
}
/**
-10
View File
@@ -4,16 +4,6 @@ namespace App\Http\Resources;
use App\Contracts\Resource;
/**
* @mixin \App\Models\Aircraft
*/
class Aircraft extends Resource
{
public function toArray($request)
{
$res = parent::toArray($request);
$res['ident'] = $this->ident;
return $res;
}
}
-2
View File
@@ -88,7 +88,6 @@ class User extends Authenticatable
'toc_accepted',
'opt_in',
'last_ip',
'notes',
'created_at',
'updated_at',
];
@@ -105,7 +104,6 @@ class User extends Authenticatable
'password',
'last_ip',
'remember_token',
'notes',
];
protected $casts = [
@@ -11,16 +11,14 @@ use Carbon\Carbon;
*/
class DiscordMessage
{
const COLOR_SUCCESS = '0B6623';
const COLOR_WARNING = 'FD6A02';
const COLOR_ERROR = 'ED2939';
const COLOR_SUCCESS = '#0B6623';
const COLOR_WARNING = '#FD6A02';
const COLOR_ERROR = '#ED2939';
public $webhook_url;
protected $title;
protected $url;
protected $thumbnail = [];
protected $image = [];
protected $description;
protected $timestamp;
protected $footer;
@@ -28,43 +26,30 @@ class DiscordMessage
protected $author = [];
protected $fields = [];
// Supply the webhook URL that this should be going to
/**
* Supply the webhook URL that this should be going to
*/
public function webhook(string $url): self
{
$this->webhook_url = $url;
return $this;
}
// Title of the embed
/**
* Title of the notification
*/
public function title(string $title): self
{
$this->title = $title;
return $this;
}
// URL of the Title
public function url(string $url): self
{
$this->url = $url;
return $this;
}
// Thumbnail image (placed right side of embed)
// ['url' => '']
public function thumbnail(array $thumbnail): self
{
$this->thumbnail = $thumbnail;
return $this;
}
// Main image (placed bottom of embed)
// ['url' => '']
public function image(array $image): self
{
$this->image = $image;
return $this;
}
/**
* @param array|string $descriptionLines
*/
@@ -78,15 +63,22 @@ class DiscordMessage
return $this;
}
// Author details
// ['name' => '', 'url' => '', 'icon_url' => '']
/**
* Set the author information:
* [
* 'name' => '',
* 'url' => '',
* 'icon_url' => '',
*/
public function author(array $author): self
{
$this->author = $author;
return $this;
}
// Fields
/**
* Set the fields
*/
public function fields(array $fields): self
{
$this->fields = [];
@@ -107,45 +99,32 @@ class DiscordMessage
return $this;
}
// Fixed Success Color
public function success(): self
{
$this->color = hexdec('0B6623'); // static::COLOR_SUCCESS;
$this->color = static::COLOR_SUCCESS;
return $this;
}
// Fixed Warning
public function warning(): self
{
$this->color = hexdec('FD6A02'); // static::COLOR_WARNING;
$this->color = static::COLOR_WARNING;
return $this;
}
// Fixed Error
public function error(): self
{
$this->color = hexdec('ED2939'); // static::COLOR_ERROR;
return $this;
}
// Custom Color
public function color(string $embed_color): self
{
$this->color = hexdec($embed_color);
$this->color = static::COLOR_ERROR;
return $this;
}
public function toArray(): array
{
$embeds = [
'type' => 'rich',
'color' => $this->color,
'title' => $this->title,
'url' => $this->url,
'thumbnail' => $this->thumbnail,
'type' => 'rich',
'description' => $this->description,
'author' => $this->author,
'image' => $this->image,
'timestamp' => Carbon::now('UTC'),
];
@@ -31,7 +31,7 @@ class NewsAdded extends Notification implements ShouldQueue
public function toDiscordChannel($news): ?DiscordMessage
{
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
return $dm->url(setting('notifications.discord_public_webhook_url'))
->success()
->title('News: '.$news->subject)
->author([
@@ -43,10 +43,11 @@ class PirepFiled extends Notification implements ShouldQueue
{
$title = 'Flight '.$pirep->ident.' Filed';
$fields = [
'Dep.Airport' => $pirep->dpt_airport_id,
'Arr.Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
'Flight' => $pirep->ident,
'Departure Airport' => $pirep->dpt_airport_id,
'Arrival Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
];
if ($pirep->distance) {
@@ -62,19 +63,16 @@ class PirepFiled extends Notification implements ShouldQueue
}
}
// User avatar, somehow $pirep->user->resolveAvatarUrl() is not being accepted by Discord as thumbnail
$user_avatar = !empty($pirep->user->avatar) ? $pirep->user->avatar->url : $pirep->user->gravatar(256);
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
return $dm->url(setting('notifications.discord_public_webhook_url'))
->success()
->title($title)
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
->thumbnail(['url' => $user_avatar])
->image(['url' => $pirep->airline->logo])
->url(route('frontend.pireps.show', [$pirep->id]))
->author([
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
'icon_url' => $pirep->user->resolveAvatarUrl(),
])
->fields($fields);
}
@@ -9,9 +9,11 @@ use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Support\Units\Distance;
use App\Support\Units\Time;
use function config;
use Illuminate\Contracts\Queue\ShouldQueue;
use PhpUnitsOfMeasure\Exception\NonNumericValue;
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
use function route;
/**
* Send the PIREP accepted message to a particular user, can also be sent to Discord
@@ -73,16 +75,14 @@ class PirepStatusChanged extends Notification implements ShouldQueue
*/
public function toDiscordChannel($pirep): ?DiscordMessage
{
if (empty(setting('notifications.discord_public_webhook_url'))) {
return null;
}
$title = 'Flight '.$pirep->ident.' '.self::$verbs[$pirep->status];
$fields = [
'Dep.Airport' => $pirep->dpt_airport_id,
'Arr.Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
'Flight' => $pirep->ident,
'Departure Airport' => $pirep->dpt_airport_id,
'Arrival Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
];
// Show the distance, but include the planned distance if it's been set
@@ -109,29 +109,16 @@ class PirepStatusChanged extends Notification implements ShouldQueue
}
}
// User avatar, somehow $pirep->user->resolveAvatarUrl() is not being accepted by Discord as thumbnail
$user_avatar = !empty($pirep->user->avatar) ? $pirep->user->avatar->url : $pirep->user->gravatar(256);
// Proper coloring for the messages
// Pirep Filed > success, normals > warning, non-normals > error
$danger_types = [
PirepStatus::GRND_RTRN,
PirepStatus::DIVERTED,
PirepStatus::CANCELLED,
PirepStatus::PAUSED,
PirepStatus::EMERG_DESCENT,
];
$color = in_array($pirep->status, $danger_types, true) ? 'ED2939' : 'FD6A02';
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->color($color)
return $dm->url(setting('notifications.discord_public_webhook_url'))
->success()
->title($title)
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
->thumbnail(['url' => $user_avatar])
->url(route('frontend.pireps.show', [$pirep->id]))
->author([
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
'icon_url' => $pirep->user->resolveAvatarUrl(),
])
->fields($fields);
}
@@ -49,7 +49,7 @@ class UserRegistered extends Notification implements ShouldQueue
public function toDiscordChannel($notifiable): ?DiscordMessage
{
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_private_webhook_url'))
return $dm->url(setting('notifications.discord_private_webhook_url'))
->success()
->title('New User Registered: '.$this->user->ident)
->author([
+11 -37
View File
@@ -11,7 +11,6 @@ use App\Events\PirepRejected;
use App\Events\PirepStatusChange;
use App\Events\UserRegistered;
use App\Events\UserStateChanged;
use App\Models\Enums\PirepStatus;
use App\Models\Enums\UserState;
use App\Models\User;
use App\Notifications\Messages\UserRejected;
@@ -162,7 +161,7 @@ class NotificationEventsHandler extends Listener
}
/**
* Prefile notification. Disabled intentionally, No need to send it to Discord
* Prefile notification
*/
public function onPirepPrefile(PirepPrefiled $event): void
{
@@ -171,33 +170,16 @@ class NotificationEventsHandler extends Listener
/*
* Broadcast notifications
*/
// Notification::send([$event->pirep], new Messages\Broadcast\PirepPrefiled($event->pirep));
Notification::send([$event->pirep], new Messages\Broadcast\PirepPrefiled($event->pirep));
}
/**
* Status Change notification.
* Reduced the messages (Boarding, Pushback, TakeOff, Landing and non-normals only)
* If needed array can be tied to a setting at admin side for further customization
* Status Change notification. Disabled for now, too noisy
*/
public function onPirepStatusChange(PirepStatusChange $event): void
{
Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' status changed');
$message_types = [
PirepStatus::BOARDING,
PirepStatus::PUSHBACK_TOW,
PirepStatus::GRND_RTRN,
PirepStatus::TAKEOFF,
PirepStatus::LANDED,
PirepStatus::DIVERTED,
PirepStatus::CANCELLED,
PirepStatus::PAUSED,
PirepStatus::EMERG_DESCENT,
];
if (setting('notifications.discord_pirep_status', true) && in_array($event->pirep->status, $message_types, true)) {
Notification::send([$event->pirep], new Messages\Broadcast\PirepStatusChanged($event->pirep));
}
// Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' prefiled');
// Notification::send([$event->pirep], new Messages\Discord\PirepStatusChanged($event->pirep));
}
/**
@@ -208,9 +190,7 @@ class NotificationEventsHandler extends Listener
public function onPirepFile(PirepFiled $event): void
{
Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed');
if (setting('notifications.mail_pirep_admin', true)) {
$this->notifyAdmins(new Messages\PirepFiled($event->pirep));
}
$this->notifyAdmins(new Messages\PirepFiled($event->pirep));
/*
* Broadcast notifications
@@ -225,10 +205,8 @@ class NotificationEventsHandler extends Listener
*/
public function onPirepAccepted(PirepAccepted $event): void
{
if (setting('notifications.mail_pirep_user_ack', true)) {
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
$this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
}
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
$this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
}
/**
@@ -238,10 +216,8 @@ class NotificationEventsHandler extends Listener
*/
public function onPirepRejected(PirepRejected $event): void
{
if (setting('notifications.mail_pirep_user_rej', true)) {
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
$this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
}
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
$this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
}
/**
@@ -252,9 +228,7 @@ class NotificationEventsHandler extends Listener
public function onNewsAdded(NewsAdded $event): void
{
Log::info('NotificationEvents::onNewsAdded');
if (setting('notifications.mail_news', true)) {
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
}
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
/*
* Broadcast notifications
+9 -12
View File
@@ -12,12 +12,9 @@ use App\Cron\Nightly\PilotLeave;
use App\Cron\Nightly\RecalculateBalances;
use App\Cron\Nightly\RecalculateStats;
use App\Cron\Nightly\SetActiveFlights;
use App\Events\CronFifteenMinute;
use App\Events\CronFiveMinute;
use App\Events\CronHourly;
use App\Events\CronMonthly;
use App\Events\CronNightly;
use App\Events\CronThirtyMinute;
use App\Events\CronWeekly;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -27,15 +24,6 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvi
class CronServiceProvider extends ServiceProvider
{
protected $listen = [
CronFiveMinute::class => [],
CronFifteenMinute::class => [],
CronThirtyMinute::class => [],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
CronNightly::class => [
ApplyExpenses::class,
RecalculateBalances::class,
@@ -44,10 +32,19 @@ class CronServiceProvider extends ServiceProvider
RecalculateStats::class,
NewVersionCheck::class,
],
CronWeekly::class => [
],
CronMonthly::class => [
\App\Cron\Monthly\ApplyExpenses::class,
],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
];
}
+1 -3
View File
@@ -138,10 +138,8 @@ class BidService extends Service
throw new BidExistsForFlight($flight);
}
// This is already controlled above at line 114 with user bid count,
// To prevent or allow multiple bids. Should not be here at all
if (setting('bids.allow_multiple_bids') === false) {
// throw new BidExistsForFlight($flight);
throw new BidExistsForFlight($flight);
}
} else {
/* @noinspection NestedPositiveIfStatementsInspection */
+2 -1
View File
@@ -39,7 +39,8 @@ class CronService extends Service
$path = [
$php_exec,
base_path('bin/cron'),
base_path('artisan'),
'schedule:run',
];
return implode(' ', $path);
+2 -2
View File
@@ -485,8 +485,8 @@ class PirepService extends Service
$default_state = $pirep->state;
}
// If pirep is still at PENDING or DRAFT state decide the default behavior by looking at rank settings
if ($pirep->state === PirepState::PENDING || $pirep->state === PirepState::DRAFT) {
// If pirep is still at PENDING state decide the default behavior by looking at rank settings
if ($pirep->state === PirepState::PENDING) {
if ($pirep->source === PirepSource::ACARS && $pirep->user->rank->auto_approve_acars) {
$default_state = PirepState::ACCEPTED;
} elseif ($pirep->source === PirepSource::MANUAL && $pirep->user->rank->auto_approve_manual) {
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/env php
<?php
/**
* THIS CRON FILE IS A BACKUP METHOD IF YOUR SERVER DOES NOT HAVE PROC_OPEN ENABLED
* YOU SHOULD TRY USING THE DEFAULT INSTRUCTIONS OF USING ARTISAN SCHEDULE:RUN
*/
define('LARAVEL_START', microtime(true));
use App\Console\Cron;
use App\Console\Kernel;
require __DIR__.'/../vendor/autoload.php';
/** @var Application $app */
$app = require_once __DIR__.'/../bootstrap/app.php';
/** @var Kernel $kernel */
$kernel = $app->make(Kernel::class);
// Run a null artisan thing just so Laravel internals can be setup properly
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArrayInput([
'command' => 'version',
]),
new Symfony\Component\Console\Output\NullOutput()
);
/** @var Cron $cron */
$cron = app(Cron::class);
$run = $cron->run();
echo json_encode([
'count' => count($run),
'tasks' => $run,
]);
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "npm-proj-1647195469379-0.2625236740756156F6TT9D",
"name": "npm-proj-1644437580670-0.60402830570294548RynpF",
"lockfileVersion": 2,
"requires": true,
"packages": {
@@ -22,7 +22,7 @@ return [
'fieldsreadonly' => 'Una vez que se ha enviado un PIREP, ciertos campos pasan al modo de solo lectura.',
'flightinformations' => 'Información de vuelo',
'flightident' => 'Vuelo Número/Código/Etapa',
'block_fuel' => 'Combustible en calzos',
'block_fuel' => 'Bloque de Combustible',
'fuel_used' => 'Combustible Usado',
'codeoptional' => 'Código (opcional)',
'legoptional' => 'Etapa (opcional)',
+3 -10
View File
@@ -174,6 +174,7 @@
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-container">
@@ -259,9 +260,8 @@
<div class="row">
<div class="form-group col-sm-12">
{{ Form::textarea('notes', null, [
'id' => 'editor',
'class' => 'editor',
'style' => 'padding: 5px',
'class' => 'form-control input-text',
'style' => 'padding: 10px',
]) }}
<p class="text-danger">{{ $errors->first('notes') }}</p>
</div>
@@ -288,10 +288,3 @@
</div>
</div>
</div>
@section('scripts')
@parent
<script src="{{ public_asset('assets/vendor/ckeditor4/ckeditor.js') }}"></script>
<script>
$(document).ready(function () { CKEDITOR.replace('editor'); });
</script>
@endsection
+24 -16
View File
@@ -5,16 +5,19 @@
{{ Form::number('pilot_id', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('pilot_id') }}</p>
</div>
<div class="form-group col-sm-3">
{{ Form::label('name', 'Name:') }}
{{ Form::text('name', null, ['class' => 'form-control', 'autocomplete' => 'off']) }}
<p class="text-danger">{{ $errors->first('name') }}</p>
</div>
<div class="form-group col-sm-3">
{{ Form::label('email', 'Email:') }}
{{ Form::text('email', null, ['class' => 'form-control', 'autocomplete' => 'off']) }}
<p class="text-danger">{{ $errors->first('email') }}</p>
</div>
<div class="form-group col-sm-3">
{{ Form::label('password', 'Password:') }}
{{ Form::password('password', ['class' => 'form-control', 'autocomplete' => 'off']) }}
@@ -49,6 +52,7 @@
{{ Form::select('curr_airport_id', $airports, null , ['class' => 'form-control select2']) }}
<p class="text-danger">{{ $errors->first('curr_airport_id') }}</p>
</div>
</div>
<div class="row">
@@ -56,10 +60,12 @@
{{ Form::label('airline_id', 'Airline:') }}
{{ Form::select('airline_id', $airlines, null, ['class' => 'form-control select2', 'placeholder' => 'Select Airline']) }}
</div>
<div class="form-group col-sm-4">
{{ Form::label('rank_id', 'Rank:') }}
{{ Form::select('rank_id', $ranks, null, ['class' => 'form-control select2', 'placeholder' => 'Select Rank']) }}
</div>
<div class="form-group col-sm-4">
{{ Form::label('roles', 'Roles:') }}
{{ Form::select('roles[]', $roles, $user->roles->pluck('id'),
@@ -68,21 +74,17 @@
</div>
<div class="row">
<div class="form-group col-md-4">
<div class="form-group col-sm-6">
{{ Form::label('state', 'State:') }}
{{-- <label class="checkbox-inline"> --}}
{{ Form::select('state', UserState::labels(), null, ['class' => 'form-control select2', 'style' => 'width: 100%;']) }}
{{-- </label> --}}
<label class="checkbox-inline">
{{ Form::select('state', UserState::labels(), null, ['class' => 'form-control select2']) }}
</label>
</div>
<div class="form-group col-md-8">
{{ Form::label('notes', 'Management Notes:') }}
{{ Form::textarea('notes', null, ['class' => 'form-control', 'rows' => 4, 'autocomplete' => 'off']) }}
</div>
</div>
<div class="row">
<div class="form-group col-sm-12 text-right">
{{-- <a href="{{ route('admin.users.regen_apikey', [$user->id]) }}" class="btn btn-warning" onclick="return confirm('Are you sure? This will reset this user\'s API key.')">New API Key</a> --}}
<!-- Submit Field -->
<div class="form-group col-sm-6 text-right">
{{--<a href="{{ route('admin.users.regen_apikey', [$user->id]) }}" class="btn btn-warning"
onclick="return confirm('Are you sure? This will reset this user\'s API key.')">new api key</a>--}}
&nbsp;
{{ Form::button('Save', ['type' => 'submit', 'class' => 'btn btn-success']) }}
<a href="{{ route('admin.users.index') }}" class="btn btn-default">Cancel</a>
@@ -93,8 +95,10 @@
<div class="form-group col-sm-12">
<table class="table table-hover">
<tr>
<td colspan="2"><h5>User Details</h5></td>
</tr>
<td colspan="2">
<h5>User Details</h5>
</td>
</tr>
<tr>
<td>Total Flights</td>
<td>{{ $user->flights }}</td>
@@ -123,10 +127,14 @@
<td>@lang('profile.opt-in')</td>
<td>{{ $user->opt_in ? __('common.yes') : __('common.no') }}</td>
</tr>
@if($user->fields)
<tr>
<td colspan="2"><h5>Custom Fields</h5></td>
<td colspan="2">
<h5>Custom Fields</h5>
</td>
</tr>
{{-- Custom Fields --}}
@foreach($user->fields as $field)
<tr>
@@ -137,4 +145,4 @@
@endif
</table>
</div>
</div>
</div>
@@ -1,5 +1,5 @@
<h4>@lang('toc.title')</h4>
<textarea readonly class="form-control" style="height: 150px; border: 1px #ccc solid;">
<textarea class="form-control" style="height: 150px; border: 1px #ccc solid;">
{{ config('app.name') }} offers this Web site, including all information, software,
products and services available from this Web site or offered as part of or in conjunction
with this Web site (the “Web site”), to you, the user, conditioned upon your acceptance of
-7
View File
@@ -279,9 +279,6 @@ class ApiTest extends TestCase
}
$this->assertCount($size, $subfleet['aircraft']);
foreach ($subfleet['aircraft'] as $aircraft) {
$this->assertNotEmpty($aircraft['ident']);
}
}
}
@@ -317,7 +314,6 @@ class ApiTest extends TestCase
$this->assertEquals($body['id'], $aircraft->id);
$this->assertEquals($body['name'], $aircraft->name);
$this->assertNotEmpty($body['ident']);
$this->assertEquals($body['mtow'], $aircraft->mtow);
$this->assertEquals($body['zfw'], $aircraft->zfw);
@@ -329,9 +325,6 @@ class ApiTest extends TestCase
$this->assertEquals($body['mtow'], $aircraft->mtow);
$this->assertEquals($body['zfw'], $aircraft->zfw);
$this->assertNotEmpty($body['ident']);
$this->assertEquals($body['ident'], $aircraft->ident);
$resp = $this->get('/api/fleet/aircraft/'.$aircraft->id.'?icao='.$aircraft->icao);
$body = $resp->json()['data'];