Implement basic logging #62
|
|
@ -4,9 +4,12 @@ namespace App\Actions\Entries;
|
||||||
|
|
||||||
use App\Exceptions\ManageEntryException;
|
use App\Exceptions\ManageEntryException;
|
||||||
use App\Models\Audition;
|
use App\Models\Audition;
|
||||||
|
use App\Models\AuditLogEntry;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
use App\Models\Student;
|
use App\Models\Student;
|
||||||
|
|
||||||
|
use function auth;
|
||||||
|
|
||||||
class CreateEntry
|
class CreateEntry
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|
@ -46,6 +49,20 @@ class CreateEntry
|
||||||
'for_advancement' => $entry_for->contains('advancement'),
|
'for_advancement' => $entry_for->contains('advancement'),
|
||||||
]);
|
]);
|
||||||
$entry->save();
|
$entry->save();
|
||||||
|
if (auth()->user()) {
|
||||||
|
$message = 'Entered '.$entry->student->full_name().' from '.$entry->student->school->name.' in '.$entry->audition->name.'.';
|
||||||
|
AuditLogEntry::create([
|
||||||
|
'user' => auth()->user()->email,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'message' => $message,
|
||||||
|
'affected' => [
|
||||||
|
'entries' => [$entry->id],
|
||||||
|
'students' => [$entry->student_id],
|
||||||
|
'auditions' => [$entry->audition_id],
|
||||||
|
'schools' => [$entry->student->school_id],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,22 @@ namespace App\Actions\Entries;
|
||||||
|
|
||||||
use App\Exceptions\ManageEntryException;
|
use App\Exceptions\ManageEntryException;
|
||||||
use App\Models\Audition;
|
use App\Models\Audition;
|
||||||
|
use App\Models\AuditLogEntry;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
|
|
||||||
use function array_key_exists;
|
use function array_key_exists;
|
||||||
|
use function auditionSetting;
|
||||||
|
use function auth;
|
||||||
|
use function request;
|
||||||
|
|
||||||
class UpdateEntry
|
class UpdateEntry
|
||||||
{
|
{
|
||||||
protected Entry $entry;
|
protected Entry $entry;
|
||||||
|
|
||||||
|
protected string $log_message = '';
|
||||||
|
|
||||||
|
protected array $log_affected = [];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -48,8 +56,19 @@ class UpdateEntry
|
||||||
if (array_key_exists('audition', $updateData)) {
|
if (array_key_exists('audition', $updateData)) {
|
||||||
$this->updateAudition($updateData['audition']);
|
$this->updateAudition($updateData['audition']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->entry->save();
|
$this->entry->save();
|
||||||
|
if (auth()->user()) {
|
||||||
|
$this->log_affected['auditions'][] = $this->entry->audition_id;
|
||||||
|
$this->log_affected['entries'][] = $this->entry->id;
|
||||||
|
$this->log_affected['students'][] = $this->entry->student_id;
|
||||||
|
$this->log_affected['schools'][] = $this->entry->student->school_id;
|
||||||
|
AuditLogEntry::create([
|
||||||
|
'user' => auth()->user()->email,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'message' => $this->log_message,
|
||||||
|
'affected' => $this->log_affected,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,12 +110,20 @@ class UpdateEntry
|
||||||
->where('audition_id', $audition->id)->exists()) {
|
->where('audition_id', $audition->id)->exists()) {
|
||||||
throw new ManageEntryException('That student is already entered in that audition');
|
throw new ManageEntryException('That student is already entered in that audition');
|
||||||
}
|
}
|
||||||
|
// Escape if we're not actually making a change
|
||||||
|
if ($this->entry->audition_id == $audition->id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// OK we're allowed to change the audition
|
// OK we're allowed to change the audition
|
||||||
|
$oldAudition = $this->entry->audition;
|
||||||
$this->entry->audition_id = $audition->id;
|
$this->entry->audition_id = $audition->id;
|
||||||
|
$this->log_message .= 'Changed entry '.$this->entry->id.' from '.$oldAudition->name.' to '.$audition->name.'<br>';
|
||||||
|
$this->log_affected['auditions'][] = $oldAudition->id;
|
||||||
// Deal with our draw number
|
// Deal with our draw number
|
||||||
if ($audition->hasFlag('drawn')) {
|
if ($audition->hasFlag('drawn')) {
|
||||||
$draw_number = $audition->entries()->max('draw_number');
|
$draw_number = $audition->entries()->max('draw_number');
|
||||||
$this->entry->draw_number = $draw_number + 1;
|
$this->entry->draw_number = $draw_number + 1;
|
||||||
|
$this->log_message .= 'Entry '.$this->entry->id.' draw number set to '.$this->entry->draw_number.'<br>';
|
||||||
} else {
|
} else {
|
||||||
$this->entry->draw_number = null;
|
$this->entry->draw_number = null;
|
||||||
}
|
}
|
||||||
|
|
@ -115,11 +142,13 @@ class UpdateEntry
|
||||||
throw new ManageEntryException('Cannot add seating to an entry in an audition where seats are published');
|
throw new ManageEntryException('Cannot add seating to an entry in an audition where seats are published');
|
||||||
}
|
}
|
||||||
$this->entry->for_seating = 1;
|
$this->entry->for_seating = 1;
|
||||||
|
$this->log_message .= 'Entry '.$this->entry->id.' is entered for seating '.'<br>';
|
||||||
} else {
|
} else {
|
||||||
if ($this->entry->audition->hasFlag('seats_published')) {
|
if ($this->entry->audition->hasFlag('seats_published')) {
|
||||||
throw new ManageEntryException('Cannot remove seating from an entry in an audition where seats are published');
|
throw new ManageEntryException('Cannot remove seating from an entry in an audition where seats are published');
|
||||||
}
|
}
|
||||||
$this->entry->for_seating = 0;
|
$this->entry->for_seating = 0;
|
||||||
|
$this->log_message .= 'Entry '.$this->entry->id.' is NOT entered for seating '.'<br>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,11 +165,13 @@ class UpdateEntry
|
||||||
throw new ManageEntryException('Cannot add advancement to an entry in an audition where advancement is published');
|
throw new ManageEntryException('Cannot add advancement to an entry in an audition where advancement is published');
|
||||||
}
|
}
|
||||||
$this->entry->for_advancement = 1;
|
$this->entry->for_advancement = 1;
|
||||||
|
$this->log_message .= 'Entry '.$this->entry->id.' is entered for '.auditionSetting('advanceTo').'<br>';
|
||||||
} else {
|
} else {
|
||||||
if ($this->entry->audition->hasFlag('advancement_published')) {
|
if ($this->entry->audition->hasFlag('advancement_published')) {
|
||||||
throw new ManageEntryException('Cannot remove advancement from an entry in an audition where advancement is published');
|
throw new ManageEntryException('Cannot remove advancement from an entry in an audition where advancement is published');
|
||||||
}
|
}
|
||||||
$this->entry->for_advancement = 0;
|
$this->entry->for_advancement = 0;
|
||||||
|
$this->log_message .= 'Entry '.$this->entry->id.' is NOT entered for '.auditionSetting('advanceTo').'<br>';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use App\Actions\Tabulation\CalculateScoreSheetTotal;
|
||||||
use App\Exceptions\ManageEntryException;
|
use App\Exceptions\ManageEntryException;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Audition;
|
use App\Models\Audition;
|
||||||
|
use App\Models\AuditLogEntry;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
use App\Models\School;
|
use App\Models\School;
|
||||||
use App\Models\Seat;
|
use App\Models\Seat;
|
||||||
|
|
@ -202,9 +203,24 @@ class EntryController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($entry->scoreSheets()->count() > 0) {
|
if ($entry->scoreSheets()->count() > 0) {
|
||||||
return redirect()->route('admin.entries.index')->with('error', 'Cannot delete an entry that has been scored');
|
return redirect()->route('admin.entries.index')->with('error',
|
||||||
|
'Cannot delete an entry that has been scored');
|
||||||
|
}
|
||||||
|
if (auth()->user()) {
|
||||||
|
$message = 'Deleted entry '.$entry->id;
|
||||||
|
$affected = [
|
||||||
|
'entries' => [$entry->id],
|
||||||
|
'auditions' => [$entry->audition_id],
|
||||||
|
'schools' => [$entry->student->school_id],
|
||||||
|
'students' => [$entry->student_id],
|
||||||
|
];
|
||||||
|
AuditLogEntry::create([
|
||||||
|
'user' => auth()->user()->email,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'message' => $message,
|
||||||
|
'affected' => $affected,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry->delete();
|
$entry->delete();
|
||||||
|
|
||||||
return redirect()->route('admin.entries.index')->with('success', 'Entry Deleted');
|
return redirect()->route('admin.entries.index')->with('success', 'Entry Deleted');
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers;
|
||||||
use App\Actions\Entries\CreateEntry;
|
use App\Actions\Entries\CreateEntry;
|
||||||
use App\Exceptions\ManageEntryException;
|
use App\Exceptions\ManageEntryException;
|
||||||
use App\Models\Audition;
|
use App\Models\Audition;
|
||||||
|
use App\Models\AuditLogEntry;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
@ -65,9 +66,25 @@ class EntryController extends Controller
|
||||||
if ($request->user()->cannot('delete', $entry)) {
|
if ($request->user()->cannot('delete', $entry)) {
|
||||||
abort(403);
|
abort(403);
|
||||||
}
|
}
|
||||||
|
if (auth()->user()) {
|
||||||
|
$message = 'Deleted entry '.$entry->id;
|
||||||
|
$affected = [
|
||||||
|
'entries' => [$entry->id],
|
||||||
|
'auditions' => [$entry->audition_id],
|
||||||
|
'schools' => [$entry->student->school_id],
|
||||||
|
'students' => [$entry->student_id],
|
||||||
|
];
|
||||||
|
AuditLogEntry::create([
|
||||||
|
'user' => auth()->user()->email,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'message' => $message,
|
||||||
|
'affected' => $affected,
|
||||||
|
]);
|
||||||
|
}
|
||||||
$entry->delete();
|
$entry->delete();
|
||||||
|
|
||||||
return redirect()->route('entries.index')->with('success', 'The '.$entry->audition->name.'entry for '.$entry->student->full_name().'has been deleted.');
|
return redirect()->route('entries.index')->with('success',
|
||||||
|
'The '.$entry->audition->name.'entry for '.$entry->student->full_name().'has been deleted.');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Models\AuditLogEntry;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Events\Login;
|
||||||
|
|
||||||
|
class LogLogin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*/
|
||||||
|
public function handle(Login $event): void
|
||||||
|
{
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $event->user;
|
||||||
|
AuditLogEntry::create([
|
||||||
|
'user' => $user->email,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'message' => 'Logged In',
|
||||||
|
'affected' => ['users' => [$user->id]],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Models\AuditLogEntry;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Events\Logout;
|
||||||
|
|
||||||
|
class LogLogout
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*/
|
||||||
|
public function handle(Logout $event): void
|
||||||
|
{
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $event->user;
|
||||||
|
AuditLogEntry::create([
|
||||||
|
'user' => $user->email,
|
||||||
|
'ip_address' => request()->ip(),
|
||||||
|
'message' => 'Logged Out',
|
||||||
|
'affected' => ['users' => [$user->id]],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,4 +8,8 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
class AuditLogEntry extends Model
|
class AuditLogEntry extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
protected $casts = ['affected' => 'json'];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ return new class extends Migration
|
||||||
Schema::create('audit_log_entries', function (Blueprint $table) {
|
Schema::create('audit_log_entries', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('user');
|
$table->string('user');
|
||||||
|
$table->ipAddress('ip_address')->nullable();
|
||||||
$table->string('message');
|
$table->string('message');
|
||||||
$table->json('affected')->nullable();
|
$table->json('affected')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ it('has a field with forms for each audition setting', function () {
|
||||||
'name' => 'school_fee',
|
'name' => 'school_fee',
|
||||||
'value' => number_format(auditionSetting('school_fee') / 100, 2),
|
'value' => number_format(auditionSetting('school_fee') / 100, 2),
|
||||||
])
|
])
|
||||||
->containsInput([
|
->containsTextarea([
|
||||||
'name' => 'payment_address',
|
'name' => 'payment_address',
|
||||||
'value' => auditionSetting('payment_address'),
|
'value' => auditionSetting('payment_address'),
|
||||||
])
|
])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue