Skip to content

Commit

Permalink
Merge branch 'dev' into 1723-Expenses
Browse files Browse the repository at this point in the history
  • Loading branch information
nabeelio authored Feb 5, 2024
2 parents f34d51f + 225c437 commit 75e40aa
Show file tree
Hide file tree
Showing 61 changed files with 1,588 additions and 211 deletions.
6 changes: 6 additions & 0 deletions app/Console/Cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

namespace App\Console;

use App\Console\Cron\Backups\BackupClean;
use App\Console\Cron\Backups\BackupMonitor;
use App\Console\Cron\Backups\BackupRun;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
Expand Down Expand Up @@ -33,6 +36,9 @@ class Cron
Nightly::class,
Weekly::class,
Monthly::class,
BackupRun::class,
BackupClean::class,
BackupMonitor::class,
];

/**
Expand Down
28 changes: 28 additions & 0 deletions app/Console/Cron/Backups/BackupClean.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Console\Cron\Backups;

use App\Contracts\CronCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;

class BackupClean extends CronCommand
{
protected $signature = 'cron:backup-clean';
protected $description = 'Clean up old backups';

public function handle(): void
{
$this->callEvent();
}

public function callEvent(): void
{
Artisan::call('backup:clean');

$output = trim(Artisan::output());
if (!empty($output)) {
Log::info($output);
}
}
}
28 changes: 28 additions & 0 deletions app/Console/Cron/Backups/BackupMonitor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Console\Cron\Backups;

use App\Contracts\CronCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;

class BackupMonitor extends CronCommand
{
protected $signature = 'cron:backup-monitor';
protected $description = 'Monitor backups health';

public function handle(): void
{
$this->callEvent();
}

public function callEvent(): void
{
Artisan::call('backup:monitor');

$output = trim(Artisan::output());
if (!empty($output)) {
Log::info($output);
}
}
}
28 changes: 28 additions & 0 deletions app/Console/Cron/Backups/BackupRun.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Console\Cron\Backups;

use App\Contracts\CronCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;

class BackupRun extends CronCommand
{
protected $signature = 'cron:backup-run';
protected $description = 'Create a new backup';

public function handle(): void
{
$this->callEvent();
}

public function callEvent(): void
{
Artisan::call('backup:run');

$output = trim(Artisan::output());
if (!empty($output)) {
Log::info($output);
}
}
}
9 changes: 6 additions & 3 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace App\Console;

use App\Console\Cron\Backups\BackupClean;
use App\Console\Cron\Backups\BackupMonitor;
use App\Console\Cron\Backups\BackupRun;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
Expand Down Expand Up @@ -52,9 +55,9 @@ protected function schedule(Schedule $schedule): void

// When spatie-backups runs
if (config('backup.backup.enabled', false) === true) {
$schedule->command('backup:run')->daily()->at('01:00');
$schedule->command('backup:clean')->daily()->at('01:20');
$schedule->command('backup:monitor')->daily()->at('01:30');
$schedule->command(BackupRun::class)->daily()->at('01:10');
$schedule->command(BackupClean::class)->daily()->at('01:20');
$schedule->command(BackupMonitor::class)->daily()->at('01:30');
}

// Update the last time the cron was run
Expand Down
33 changes: 33 additions & 0 deletions app/Cron/Hourly/ClearExpiredInvites.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\Cron\Hourly;

use App\Contracts\Listener;
use App\Events\CronHourly;
use App\Models\Invite;
use Illuminate\Support\Facades\Log;

/**
* Clear any expired invites
*/
class ClearExpiredInvites extends Listener
{
/**
* @param CronHourly $event
*/
public function handle(CronHourly $event): void
{
Log::info('Hourly: Removing expired invites');
$invites = Invite::all();

foreach ($invites as $invite) {
if ($invite->expires_at && $invite->expires_at->isPast()) {
$invite->delete();
}

if ($invite->usage_limit && $invite->usage_count >= $invite->usage_limit) {
$invite->delete();
}
}
}
}
1 change: 1 addition & 0 deletions app/Database/factories/UserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function definition(): array
'state' => UserState::ACTIVE,
'remember_token' => $this->faker->unique()->text(5),
'email_verified_at' => now(),
'avatar' => '',
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class() extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('user_oauth_tokens', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('user_id');
$table->string('provider');
$table->string('token');
$table->string('refresh_token');
$table->dateTime('last_refreshed_at')->nullable();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_oauth_tokens');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class() extends Migration {
public function up(): void
{
Schema::table('user_oauth_tokens', function (Blueprint $table) {
$foreignKeys = Schema::getForeignKeys('user_oauth_tokens');

foreach ($foreignKeys as $foreignKey) {
if (in_array('user_id', $foreignKey['columns'], true)) {
$table->dropForeign(['user_id']);
break;
}
}
});
}

public function down(): void
{
//
}
};
25 changes: 25 additions & 0 deletions app/Database/migrations/2023_12_27_112456_create_invites_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class() extends Migration {
public function up(): void
{
Schema::create('invites', function (Blueprint $table) {
$table->id();
$table->string('email')->nullable();
$table->string('token');
$table->integer('usage_count')->default(0);
$table->integer('usage_limit')->nullable();
$table->dateTime('expires_at')->nullable();
$table->timestamps();
});
}

public function down(): void
{
Schema::dropIfExists('invites');
}
};
14 changes: 14 additions & 0 deletions app/Database/seeds/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@
options: ''
type: boolean
description: Record the user's IP address on register/login
- key: general.invite_only_registrations
name: 'Invite Only Registrations'
group: general
value: false
options: ''
type: boolean
description: If checked, only users with an invite can register
- key: general.disable_registrations
name: 'Disable registrations'
group: general
value: false
options: ''
type: boolean
description: If checked, registrations will be disabled and only admins can add pilots
- key: captcha.enabled
name: 'hCaptcha Enabled'
group: captcha
Expand Down
84 changes: 84 additions & 0 deletions app/Http/Controllers/Admin/InviteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace App\Http\Controllers\Admin;

use App\Contracts\Controller;
use App\Http\Requests\CreateInviteRequest;
use App\Models\Invite;
use App\Notifications\Messages\InviteLink;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Notification;
use Illuminate\View\View;
use Laracasts\Flash\Flash;

class InviteController extends Controller
{
public function index(): RedirectResponse|View
{
if (!setting('general.invite_only_registrations', false)) {
Flash::error('Registration is not on invite only');
return redirect(route('admin.users.index'));
}

$invites = Invite::all();

return view('admin.invites.index', [
'invites' => $invites,
]);
}

public function create(): RedirectResponse|View
{
if (!setting('general.invite_only_registrations', false)) {
Flash::error('Registration is not on invite only');
return redirect(route('admin.users.index'));
}

return view('admin.invites.create');
}

public function store(CreateInviteRequest $request): RedirectResponse
{
if (!setting('general.invite_only_registrations', false)) {
Flash::error('Registration is not on invite only');
return redirect(route('admin.users.index'));
}

$invite = Invite::create([
'email' => $request->get('email'),
'token' => sha1(hrtime(true).str_random()),
'usage_count' => 0,
'usage_limit' => !is_null($request->get('email')) ? 1 : $request->get('usage_limit'),
'expires_at' => $request->get('expires_at'),
]);

if (!is_null($request->get('email')) && get_truth_state($request->get('email_link'))) {
Notification::route('mail', $request->get('email'))
->notify(new InviteLink($invite));
}

Flash::success('Invite created successfully. The link is: '.$invite->link);

return redirect(route('admin.invites.index'));
}

public function destroy(int $id): RedirectResponse
{
if (!setting('general.invite_only_registrations', false)) {
Flash::error('Registration is not on invite only');
return redirect(route('admin.users.index'));
}

$invite = Invite::find($id);

if (!$invite) {
Flash::error('Invite not found');
return redirect(route('admin.invites.index'));
}

$invite->delete();

Flash::success('Invite deleted successfully');
return redirect(route('admin.invites.index'));
}
}
14 changes: 10 additions & 4 deletions app/Http/Controllers/Admin/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,17 @@ public function create(): View
*/
public function store(CreateUserRequest $request): RedirectResponse
{
$input = $request->all();
$user = $this->userRepo->create($input);
$opts = $request->all();
$opts['password'] = Hash::make($opts['password']);

Flash::success('User saved successfully.');
return redirect(route('admin.users.index'));
if (isset($opts['transfer_time'])) {
$opts['transfer_time'] *= 60;
}

$user = $this->userSvc->createUser($opts, $opts['roles'] ?? [], $opts['state'] ?? null);

Flash::success('User created successfully.');
return redirect(route('admin.users.edit', [$user->id]));
}

/**
Expand Down
Loading

0 comments on commit 75e40aa

Please sign in to comment.