Skip to content

Commit

Permalink
#2620 Now tracking user ips that access the site - I can then fight b…
Browse files Browse the repository at this point in the history
…ack against abusers of the site.
  • Loading branch information
Wotuu committed Nov 20, 2024
1 parent ee23da0 commit 7382c07
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 10 deletions.
2 changes: 1 addition & 1 deletion app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function report(Throwable $e): void

if ($e instanceof TooManyRequestsHttpException) {
$user = Auth::user();
$handlerLogging->tooManyRequests(request()?->ip() ?? 'unknown IP', $user?->id, $user?->name, $e);
$handlerLogging->tooManyRequests(request()?->ip() ?? 'unknown IP', request()?->path(), $user?->id, $user?->name, $e);
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/Exceptions/Logging/HandlerLogging.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

class HandlerLogging extends RollbarStructuredLogging implements HandlerLoggingInterface
{
public function tooManyRequests(string $ip, ?int $userId, ?string $username, Throwable $throwable): void
public function tooManyRequests(string $ip, string $uri, ?int $userId, ?string $username, Throwable $throwable): void
{
$this->error(__METHOD__, get_defined_vars());
}
Expand Down
2 changes: 1 addition & 1 deletion app/Exceptions/Logging/HandlerLoggingInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

interface HandlerLoggingInterface
{
public function tooManyRequests(string $ip, ?int $userId, ?string $username, \Throwable $throwable): void;
public function tooManyRequests(string $ip, string $uri, ?int $userId, ?string $username, \Throwable $throwable): void;
}
2 changes: 2 additions & 0 deletions app/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use App\Http\Middleware\OnlyAjax;
use App\Http\Middleware\ReadOnlyMode;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\TracksUserIpAddress;
use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\VerifyCsrfToken;
use App\Http\Middleware\ViewCacheBuster;
Expand Down Expand Up @@ -89,5 +90,6 @@ class Kernel extends HttpKernel
'debugbarmessagelogger' => DebugBarMessageLogger::class,
'debug_info_context_logger' => DebugInfoContextLogger::class,
'read_only_mode' => ReadOnlyMode::class,
'track_ip' => TracksUserIpAddress::class,
];
}
38 changes: 38 additions & 0 deletions app/Http/Middleware/TracksUserIpAddress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Http\Middleware;

use App\Models\User;
use App\Models\UserIpAddress;
use Auth;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;

class TracksUserIpAddress
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
// Maybe this should be handled differently? Idk how heavy these queries will be
if (!$request->ajax() && Auth::check()) {
/** @var User $user */
$user = Auth::user();
UserIpAddress::upsert(
[
'user_id' => $user->id,
'ip_address' => $request->ip(),
'count' => 1, // Default value for new rows
'updated_at' => now(), // Example of tracking when a row is updated
],
['user_id', 'ip_address'],
['count' => DB::raw('count + 1'), 'updated_at'] // Update these columns if a conflict occurs
);
}

return $next($request);
}
}
7 changes: 5 additions & 2 deletions app/Models/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;

Expand All @@ -23,6 +24,9 @@
* @property string $invite_code
* @property string $default_role
*
* @property Carbon $updated_at
* @property Carbon $created_at
*
* @property Collection<TeamUser> $teamUsers
* @property Collection<User> $members
* @property Collection<DungeonRoute> $dungeonroutes
Expand All @@ -32,13 +36,12 @@
class Team extends Model
{
use HasIconFile;
use GeneratesPublicKey;

protected $visible = ['name', 'description', 'public_key'];

protected $fillable = ['default_role'];

use GeneratesPublicKey;

/**
* https://stackoverflow.com/a/34485411/771270
*/
Expand Down
37 changes: 37 additions & 0 deletions app/Models/UserIpAddress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace App\Models;

use Eloquent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;

/**
* @property int $id
* @property int $user_id
* @property string $ip_address
* @property int $count
*
* @property Carbon $updated_at
* @property Carbon $created_at
*
* @property User $user
*
* @mixin Eloquent
*/
class UserIpAddress extends Model
{
protected $fillable = [
'user_id',
'ip_address',
'count',
'updated_at',
'created_at',
];

public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
5 changes: 3 additions & 2 deletions app/Models/UserReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
* @property string $message
* @property bool $contact_ok
* @property string $status
* @property User $author
*
* @property User $user
*
* @mixin Eloquent
*/
Expand All @@ -27,6 +28,6 @@ class UserReport extends Model

public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
return $this->belongsTo(User::class);
}
}
4 changes: 2 additions & 2 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot(
CloudflareServiceInterface $cloudflareService
): void
{
): void {

Model::preventLazyLoading(!app()->isProduction());

/** @var User|null $user */
Expand Down
Original file line number Diff line number Diff line change
@@ -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('user_ip_addresses', function (Blueprint $table) {
$table->id();
$table->integer('user_id');
$table->integer('count');
$table->string('ip_address');
$table->timestamps();

$table->index(['user_id', 'ip_address']);
$table->index(['ip_address']);
$table->unique(['user_id', 'ip_address']);
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_ip_addresses');
}
};
2 changes: 1 addition & 1 deletion routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
// Webhooks
Route::post('webhook/github', (new WebhookController())->github(...))->name('webhook.github');

Route::middleware(['viewcachebuster', 'language', 'debugbarmessagelogger', 'read_only_mode', 'debug_info_context_logger'])->group(static function () {
Route::middleware(['viewcachebuster', 'language', 'debugbarmessagelogger', 'read_only_mode', 'debug_info_context_logger', 'track_ip'])->group(static function () {
// Catch for hard-coded /home route in RedirectsUsers.php
Route::get('home', (new SiteController())->home(...));
Route::get('credits', (new SiteController())->credits(...))->name('misc.credits');
Expand Down

0 comments on commit 7382c07

Please sign in to comment.