mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-04-20 23:11:56 +02:00
Add base for activity logs (#466)
This commit is contained in:
parent
cce410eac3
commit
50a40e8914
10
app/Enums/ActivityLog.php
Normal file
10
app/Enums/ActivityLog.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
class ActivityLog
|
||||
{
|
||||
public const SYSTEM_CRON_TOKEN_REGENERATED = 'system.cron_token_regenerated';
|
||||
|
||||
public const USER_API_TOKEN_GENERATED = 'user.api_token_regenerated';
|
||||
}
|
@ -4,8 +4,8 @@ use App\Helper\Sharing;
|
||||
use App\Helper\WaybackMachine;
|
||||
use App\Models\Link;
|
||||
use App\Models\Setting;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@ -65,11 +65,11 @@ function systemsettings(string $key = '')
|
||||
/**
|
||||
* Output a correctly formatted date with the correct timezone
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @param CarbonInterface $date
|
||||
* @param bool $use_relational
|
||||
* @return string
|
||||
*/
|
||||
function formatDateTime(Carbon $date, bool $use_relational = false): string
|
||||
function formatDateTime(CarbonInterface $date, bool $use_relational = false): string
|
||||
{
|
||||
$timezone = config('app.timezone');
|
||||
|
||||
|
@ -6,11 +6,14 @@ use App\Http\Controllers\Controller;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use OwenIt\Auditing\Models\Audit;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class AuditController extends Controller
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
$activities = Activity::query()->with('causer')->latest()->paginate(pageName: 'activities_page');
|
||||
|
||||
$settingsHistory = Audit::where('auditable_type', Setting::class)->with('auditable')
|
||||
->latest()->paginate(pageName: 'settings_page');
|
||||
|
||||
@ -18,6 +21,7 @@ class AuditController extends Controller
|
||||
->latest()->paginate(pageName: 'user_page');
|
||||
|
||||
return view('app.audit-logs', [
|
||||
'activities' => $activities,
|
||||
'settings_history' => $settingsHistory,
|
||||
'user_history' => $userHistory,
|
||||
]);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers\App;
|
||||
|
||||
use App\Enums\ActivityLog;
|
||||
use App\Helper\UpdateHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\SystemSettingsUpdateRequest;
|
||||
@ -91,6 +92,8 @@ class SystemSettingsController extends Controller
|
||||
|
||||
Cache::forget('systemsettings');
|
||||
|
||||
activity()->by(auth()->user())->log(ActivityLog::SYSTEM_CRON_TOKEN_REGENERATED);
|
||||
|
||||
return response()->json([
|
||||
'new_token' => $newToken,
|
||||
]);
|
||||
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\App;
|
||||
|
||||
use App\Actions\Fortify\UpdateUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserProfileInformation;
|
||||
use App\Enums\ActivityLog;
|
||||
use App\Helper\LinkAce;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UserSettingsUpdateRequest;
|
||||
@ -118,6 +119,8 @@ class UserSettingsController extends Controller
|
||||
$request->user()->api_token = $new_token;
|
||||
$request->user()->save();
|
||||
|
||||
activity()->by(auth()->user())->log(ActivityLog::USER_API_TOKEN_GENERATED);
|
||||
|
||||
return response()->json([
|
||||
'new_token' => $new_token,
|
||||
]);
|
||||
|
43
app/View/Components/History/ActivityEntry.php
Normal file
43
app/View/Components/History/ActivityEntry.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components\History;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class ActivityEntry extends Component
|
||||
{
|
||||
private array $changes = [];
|
||||
private string $translateBase = 'audit.logs';
|
||||
|
||||
public function __construct(private Activity $activity)
|
||||
{
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$timestamp = formatDateTime($this->activity->created_at);
|
||||
|
||||
$this->processActivity();
|
||||
|
||||
return view('components.history-entry', [
|
||||
'timestamp' => $timestamp,
|
||||
'changes' => $this->changes,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function processActivity(): void
|
||||
{
|
||||
$change = trans($this->translateBase . '.' . $this->activity->description);
|
||||
|
||||
if ($this->activity->causer() !== null) {
|
||||
$this->changes[] = trans('audit.activity_entry_with_causer', [
|
||||
'change' => $change,
|
||||
'causer' => $this->activity->causer?->name ?: trans('user.unknown_user'),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->changes[] = $change;
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
"rap2hpoutre/laravel-log-viewer": "^2.2",
|
||||
"sentry/sentry-laravel": "^2.3",
|
||||
"shaarli/netscape-bookmark-parser": "^v3.2",
|
||||
"spatie/laravel-activitylog": "^4.5",
|
||||
"spatie/laravel-backup": "^8.1.2",
|
||||
"symfony/http-client": "^6.0",
|
||||
"symfony/mailgun-mailer": "^6.0"
|
||||
|
93
composer.lock
generated
93
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "0ab96c681f49e103b7c5e85954d29678",
|
||||
"content-hash": "2883267016653be160d0af84f30957f9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-crt-php",
|
||||
@ -5053,6 +5053,97 @@
|
||||
],
|
||||
"time": "2022-03-10T16:01:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-activitylog",
|
||||
"version": "4.5.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/laravel-activitylog.git",
|
||||
"reference": "feb1a37d649b03711e546807688fbea53469dfc3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/feb1a37d649b03711e546807688fbea53469dfc3",
|
||||
"reference": "feb1a37d649b03711e546807688fbea53469dfc3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/config": "^8.0 || ^9.0",
|
||||
"illuminate/database": "^8.53 || ^9.0",
|
||||
"illuminate/support": "^8.0 || ^9.0",
|
||||
"php": "^8.0",
|
||||
"spatie/laravel-package-tools": "^1.6.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"orchestra/testbench": "^6.23 || ^7.0",
|
||||
"pestphp/pest": "^1.20"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Spatie\\Activitylog\\ActivitylogServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Spatie\\Activitylog\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Freek Van der Herten",
|
||||
"email": "freek@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian De Deyne",
|
||||
"email": "sebastian@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Tom Witkowski",
|
||||
"email": "dev.gummibeer@gmail.com",
|
||||
"homepage": "https://gummibeer.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A very simple activity logger to monitor the users of your website or application",
|
||||
"homepage": "https://github.com/spatie/activitylog",
|
||||
"keywords": [
|
||||
"activity",
|
||||
"laravel",
|
||||
"log",
|
||||
"spatie",
|
||||
"user"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/laravel-activitylog/issues",
|
||||
"source": "https://github.com/spatie/laravel-activitylog/tree/4.5.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://spatie.be/open-source/support-us",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/spatie",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-31T10:01:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-backup",
|
||||
"version": "8.1.2",
|
||||
|
52
config/activitylog.php
Normal file
52
config/activitylog.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
* If set to false, no activities will be saved to the database.
|
||||
*/
|
||||
'enabled' => env('ACTIVITY_LOGGER_ENABLED', true),
|
||||
|
||||
/*
|
||||
* When the clean-command is executed, all recording activities older than
|
||||
* the number of days specified here will be deleted.
|
||||
*/
|
||||
'delete_records_older_than_days' => env('ACTIVITY_LOGGER_RECORD_DELETION_THRESHOLD', 365),
|
||||
|
||||
/*
|
||||
* If no log name is passed to the activity() helper
|
||||
* we use this default log name.
|
||||
*/
|
||||
'default_log_name' => 'default',
|
||||
|
||||
/*
|
||||
* You can specify an auth driver here that gets user models.
|
||||
* If this is null we'll use the current Laravel auth driver.
|
||||
*/
|
||||
'default_auth_driver' => null,
|
||||
|
||||
/*
|
||||
* If set to true, the subject returns soft deleted models.
|
||||
*/
|
||||
'subject_returns_soft_deleted_models' => false,
|
||||
|
||||
/*
|
||||
* This model will be used to log activity.
|
||||
* It should implement the Spatie\Activitylog\Contracts\Activity interface
|
||||
* and extend Illuminate\Database\Eloquent\Model.
|
||||
*/
|
||||
'activity_model' => \Spatie\Activitylog\Models\Activity::class,
|
||||
|
||||
/*
|
||||
* This is the name of the table that will be created by the migration and
|
||||
* used by the Activity model shipped with this package.
|
||||
*/
|
||||
'table_name' => 'activity_log',
|
||||
|
||||
/*
|
||||
* This is the database connection that will be used by the migration and
|
||||
* the Activity model shipped with this package. In case it's not set
|
||||
* Laravel's database.default will be used instead.
|
||||
*/
|
||||
'database_connection' => env('ACTIVITY_LOGGER_DB_CONNECTION'),
|
||||
];
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))
|
||||
->create(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('log_name')->nullable();
|
||||
$table->text('description');
|
||||
$table->nullableMorphs('subject', 'subject');
|
||||
$table->string('event')->nullable();
|
||||
$table->nullableMorphs('causer', 'causer');
|
||||
$table->json('properties')->nullable();
|
||||
$table->uuid('batch_uuid')->nullable();
|
||||
$table->timestamps();
|
||||
$table->index('log_name');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->dropIfExists(config('activitylog.table_name'));
|
||||
}
|
||||
}
|
@ -3,8 +3,21 @@
|
||||
return [
|
||||
|
||||
'log' => 'Audit Log',
|
||||
'system_events' => 'System Events',
|
||||
'settings_history' => 'Settings History',
|
||||
'user_history' => 'User History',
|
||||
'user_history_entry' => 'User :id: :change',
|
||||
|
||||
'no_logs_found' => 'No logs found',
|
||||
|
||||
'activity_entry_with_causer' => ':change by :causer',
|
||||
|
||||
'logs' => [
|
||||
'system' => [
|
||||
'cron_token_regenerated' => 'System: Cron Token was re-generated',
|
||||
],
|
||||
'user' => [
|
||||
'api_token_regenerated' => 'User: API Token was re-generated',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -13,4 +13,5 @@ return [
|
||||
|
||||
'hello' => 'Hello :user!',
|
||||
'for_user' => 'for User',
|
||||
'unknown_user' => 'unknown User',
|
||||
];
|
||||
|
@ -1,17 +1,38 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
@lang('audit.system_events')
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="history mb-4">
|
||||
@forelse($activities as $activity)
|
||||
<x-history.activity-entry :activity="$activity"/>
|
||||
@empty
|
||||
<div class="text-muted">@lang('audit.no_logs_found')</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
{!! $activities->onEachSide(1)->links() !!}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
@lang('audit.settings_history')
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="history mb-4">
|
||||
@foreach($settings_history as $entry)
|
||||
@forelse($settings_history as $entry)
|
||||
<x-history.settings-entry :entry="$entry"/>
|
||||
@endforeach
|
||||
|
||||
@empty
|
||||
<div class="text-muted">@lang('audit.no_logs_found')</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
{!! $settings_history->onEachSide(1)->links() !!}
|
||||
@ -26,9 +47,11 @@
|
||||
<div class="card-body">
|
||||
|
||||
<div class="history mb-4">
|
||||
@foreach($user_history as $entry)
|
||||
@forelse($user_history as $entry)
|
||||
<x-history.user-entry :entry="$entry"/>
|
||||
@endforeach
|
||||
@empty
|
||||
<div class="text-muted">@lang('audit.no_logs_found')</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
{!! $user_history->onEachSide(1)->links() !!}
|
||||
|
38
tests/Controller/App/AuditControllerTest.php
Normal file
38
tests/Controller/App/AuditControllerTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Controller\App;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AuditControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->user = User::factory()->create();
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
public function testAuditPage(): void
|
||||
{
|
||||
$response = $this->get('system/audit');
|
||||
|
||||
$response->assertOk()->assertSee('System Events');
|
||||
}
|
||||
|
||||
public function testAuditPageWithEntries(): void
|
||||
{
|
||||
$this->post('settings/generate-cron-token');
|
||||
|
||||
$response = $this->get('system/audit');
|
||||
$response->assertSee('System: Cron Token was re-generated');
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user