Add user action logs

This commit is contained in:
Matteo Gheza 2023-09-01 14:24:10 +02:00
parent fc9c8635a6
commit 045a311742
14 changed files with 178 additions and 16 deletions

View File

@ -6,6 +6,7 @@ use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\Utils\Logger;
class AuthController extends Controller
{
@ -27,6 +28,8 @@ class AuthController extends Controller
$token = $user->createToken('auth_token')->plainTextToken;
Logger::log("Creato utente $user->name ($user->username)", $user);
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
@ -47,6 +50,8 @@ class AuthController extends Controller
$token = $user->createToken('auth_token')->plainTextToken;
Logger::log("Login", $user, $user);
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
@ -56,6 +61,7 @@ class AuthController extends Controller
public function logout(Request $request)
{
//TODO: https://stackoverflow.com/a/73980629
Logger::log("Logout");
auth('web')->logout();
return;
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Http\Controllers;
use App\Models\Log;
use Illuminate\Http\Request;
class LogsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
return response()->json(
Log::join('users as changed_user', 'changed_user.id', '=', 'logs.changed_id')
->join('users as editor_user', 'editor_user.id', '=', 'logs.editor_id')
->select("logs.id", "logs.action", "logs.editor_id", "logs.changed_id", "logs.created_at", "changed_user.name as changed", "editor_user.name as editor")
->orderBy('created_at', 'desc')
->get()
);
}
}

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\ScheduleSlots;
use Illuminate\Http\Request;
use App\Utils\Logger;
class ScheduleSlotsController extends Controller
{
@ -29,6 +30,8 @@ class ScheduleSlotsController extends Controller
return $schedule;
}, $request->input('schedules'));
Logger::log("Aggiornata disponibilità oraria");
return ScheduleSlots::insert($schedules);
}
}

View File

@ -7,7 +7,7 @@ use App\Models\Service;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\DB;
use App\Utils\Logger;
class ServiceController extends Controller
{
@ -61,8 +61,6 @@ class ServiceController extends Controller
*/
public function createOrUpdate(Request $request)
{
DB::connection()->enableQueryLog();
$adding = !isset($request->id) || is_null($request->id);
$service = $adding ? new Service() : Service::find($request->id)->with('drivers')->with('crew')->first();
@ -134,7 +132,7 @@ class ServiceController extends Controller
));
User::whereIn('id', $usersToIncrement)->increment('services');
return response()->json(DB::getQueryLog());
Logger::log($adding ? "Intervento aggiunto" : "Intervento modificato");
}
/**
@ -146,5 +144,6 @@ class ServiceController extends Controller
$usersToDecrement = $this->extractServiceUsers($service);
User::whereIn('id', $usersToDecrement)->decrement('services');
$service->delete();
Logger::log("Intervento eliminato");
}
}

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\ServiceType;
use Illuminate\Http\Request;
use App\Utils\Logger;
class ServiceTypeController extends Controller
{
@ -26,6 +27,8 @@ class ServiceTypeController extends Controller
$serviceType->name = $request->name;
$serviceType->save();
Logger::log("Aggiunto tipo di intervento ($serviceType->name)");
return response()->json(
$serviceType
);

View File

@ -6,6 +6,7 @@ use Illuminate\Http\Request;
use App\Models\TelegramBotLogins;
use DefStudio\Telegraph\Models\TelegraphBot;
use Illuminate\Support\Str;
use App\Utils\Logger;
class TelegramController extends Controller
{
@ -21,6 +22,8 @@ class TelegramController extends Controller
$row->user = $request->user()->id;
$row->save();
Logger::log("Inizio procedura collegamento bot Telegram");
return [
"start_link" => "https://t.me/$telegramBotUsername?start=$telegramBotStartParameter"
];

View File

@ -0,0 +1,37 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Log extends Model
{
use HasFactory;
public $timestamps = ["created_at"];
const UPDATED_AT = null;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'action',
'ip',
'source_type',
'user_agent'
];
public function changed(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function editor(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@ -133,7 +133,7 @@ class WebhookController extends
return;
}
Availability::updateAvailability($user, true);
Availability::updateAvailability($user, true, true);
$this->reply("Disponibilità aggiornata con successo.\nOra sei <b>operativo</b>.");
}
@ -144,7 +144,7 @@ class WebhookController extends
return;
}
Availability::updateAvailability($user, false);
Availability::updateAvailability($user, false, true);
$this->reply("Disponibilità aggiornata con successo.\nOra sei <b>non operativo</b>.");
}
@ -155,7 +155,7 @@ class WebhookController extends
return;
}
Availability::updateAvailabilityManualMode($user, false);
Availability::updateAvailabilityManualMode($user, false, true);
$this->reply("Programmazione oraria <b>abilitata</b>.\nPer disabilitarla (e tornare in modalità manuale), cambiare la disponbilità usando i comandi \"/attiva\" e \"/disattiva\"");
}
@ -210,7 +210,7 @@ class WebhookController extends
$this->reply("⚠️ Il tuo account Allerta non è collegato con Telegram.", true);
return;
}
Availability::updateAvailabilityManualMode($user, false);
Availability::updateAvailabilityManualMode($user, false, true);
$this->reply("✅ Programmazione oraria abilitata", true);
//Delete the message that triggered the callback

View File

@ -5,9 +5,10 @@ namespace App\Utils;
use App\Models\User;
use App\Models\TelegramBotNotifications;
use DefStudio\Telegraph\Facades\Telegraph;
use App\Utils\Logger;
class Availability {
public static function updateAvailability(User|int $id, bool $available)
public static function updateAvailability(User|int $id, bool $available, bool $fromTelegram = false)
{
if(is_int($id)) {
$user = User::find($id);
@ -52,13 +53,20 @@ class Availability {
}
}
Logger::log(
"Disponibilità cambiata in ".($available ? "disponibile" : "non disponibile"),
$user,
$fromTelegram ? $user : null,
$fromTelegram ? "telegram" : "web"
);
return [
"updated_user_id" => $user->id,
"updated_user_name" => $user->name
];
}
public static function updateAvailabilityManualMode(User|int $id, bool $manual_mode)
public static function updateAvailabilityManualMode(User|int $id, bool $manual_mode, bool $fromTelegram = false)
{
if(is_int($id)) {
$user = User::find($id);
@ -68,6 +76,13 @@ class Availability {
$user->availability_manual_mode = $manual_mode;
$user->save();
Logger::log(
($manual_mode ? "Disattivazione" : "Attivazione")." programmazione oraria",
$user,
$fromTelegram ? $user : null,
$fromTelegram ? "telegram" : "web"
);
return;
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Utils;
use App\Models\User;
use App\Models\Log;
class Logger {
public static function log(string $action, User $changed = null, User $editor = null, $source_type = "web")
{
$log = new Log();
$log->action = $action;
$request = request();
if($source_type !== "web") {
$log->ip = null;
$log->source_type = $source_type;
$log->user_agent = null;
} else {
$log->source_type = "web";
$request = request();
if(!is_null($request)) {
$log->ip = $request->ip();
$log->user_agent = $request->userAgent();
} else {
$log->ip = null;
$log->user_agent = null;
}
}
if(is_null($changed)) $changed = auth()->user();
$log->changed()->associate($changed);
if(is_null($editor)) $editor = auth()->user();
$log->editor()->associate($editor);
$log->save();
}
}

View File

@ -0,0 +1,34 @@
<?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('logs', function (Blueprint $table) {
$table->id();
$table->string('action');
$table->string('ip')->nullable();
$table->string('source_type');
$table->string('user_agent')->nullable();
$table->foreignId('changed_id')->nullable()->constrained('users');
$table->foreignId('editor_id')->nullable()->constrained('users');
$table->timestamps();
$table->dropColumn('updated_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('logs');
}
};

View File

@ -5,6 +5,7 @@ use App\Http\Controllers\AuthController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ScheduleSlotsController;
use App\Http\Controllers\AvailabilityController;
use App\Http\Controllers\LogsController;
use App\Http\Controllers\TelegramController;
use App\Http\Controllers\ServiceController;
use App\Http\Controllers\PlacesController;
@ -23,10 +24,11 @@ use Illuminate\Support\Facades\Artisan;
|
*/
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:web')->group( function () {
//Route::post('/register', [AuthController::class, 'register']); //TODO: replace with admin only route
Route::get('/me', [AuthController::class, 'me']);
Route::post('/me', [AuthController::class, 'me']);
@ -52,6 +54,8 @@ Route::middleware('auth:web')->group( function () {
Route::get('/places/search', [PlacesController::class, 'search']);
Route::get('/places/{id}', [PlacesController::class, 'show']);
Route::get('/logs', [LogsController::class, 'index']);
Route::post('/telegram_login_token', [TelegramController::class, 'loginToken']);
Route::post('/logout', [AuthController::class, 'logout']);

View File

@ -52,7 +52,7 @@
<td>{{ row.action }}</td>
<td>{{ row.changed }}</td>
<td>{{ row.editor }}</td>
<td>{{ row.timestamp }}</td>
<td>{{ row.created_at | date: 'dd/MM/YYYY HH:mm:ss' }}</td>
</tr>
</tbody>
</table>

View File

@ -1,5 +1,2 @@
<owner-image></owner-image>
<app-table *ngIf="false" [sourceType]="'logs'" [refreshInterval]="1200000"></app-table>
<div class="alert alert-warning" role="alert">
Questa sezione di AllertaVVF è stata temporaneamente disabilitata per motivi di manutenzione. Ci scusiamo per il disagio.
</div>
<app-table [sourceType]="'logs'" [refreshInterval]="1200000"></app-table>