Add all files

This commit is contained in:
root
2025-11-30 11:57:22 +01:00
parent 2ee51cac4f
commit 044271db3d
1476 changed files with 142544 additions and 0 deletions

View File

@@ -0,0 +1,181 @@
<?php
namespace Paymenter\Extensions\Others\Security\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\User;
use Carbon\Carbon;
class BlockedIP extends Model
{
protected $table = 'ext_security_blocked_ips';
protected $fillable = [
'ip_address',
'reason',
'notes',
'is_permanent',
'blocked_at',
'blocked_until',
'blocked_by',
'unblocked_at',
'unblocked_by',
'is_active',
'failed_login_attempts',
'last_attempt_at',
];
protected $casts = [
'blocked_at' => 'datetime',
'blocked_until' => 'datetime',
'unblocked_at' => 'datetime',
'last_attempt_at' => 'datetime',
'is_permanent' => 'boolean',
'is_active' => 'boolean',
'failed_login_attempts' => 'integer',
];
public function blockedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'blocked_by');
}
public function unblockedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'unblocked_by');
}
/**
* Check if the IP block is currently active
*/
public function isCurrentlyActive(): bool
{
if (!$this->is_active) {
return false;
}
if ($this->is_permanent) {
return true;
}
if ($this->blocked_until && Carbon::now()->isAfter($this->blocked_until)) {
return false;
}
return true;
}
/**
* Unblock the IP
*/
public function unblock(?int $unblockedBy = null): void
{
$this->update([
'is_active' => false,
'unblocked_at' => now(),
'unblocked_by' => $unblockedBy,
]);
}
/**
* Get active block for an IP
*/
public static function getActiveBlock(string $ipAddress): ?self
{
return static::where('ip_address', $ipAddress)
->where('is_active', true)
->where(function ($query) {
$query->where('is_permanent', true)
->orWhere('blocked_until', '>', now())
->orWhereNull('blocked_until');
})
->first();
}
/**
* Check if an IP is blocked
*/
public static function isIPBlocked(string $ipAddress): bool
{
$block = static::getActiveBlock($ipAddress);
return $block && $block->isCurrentlyActive();
}
/**
* Block an IP address
*/
public static function blockIP(
string $ipAddress,
string $reason,
?int $blockedBy = null,
bool $isPermanent = false,
?Carbon $blockedUntil = null,
?string $notes = null
): self {
// Deactivate any existing blocks
static::where('ip_address', $ipAddress)
->where('is_active', true)
->update(['is_active' => false]);
return static::create([
'ip_address' => $ipAddress,
'reason' => $reason,
'notes' => $notes,
'is_permanent' => $isPermanent,
'blocked_at' => now(),
'blocked_until' => $blockedUntil,
'blocked_by' => $blockedBy,
'is_active' => true,
'failed_login_attempts' => 0,
]);
}
/**
* Record a failed login attempt
*/
public static function recordFailedAttempt(string $ipAddress): void
{
$existing = static::where('ip_address', $ipAddress)
->where('is_active', true)
->first();
if ($existing) {
$existing->increment('failed_login_attempts');
$existing->update(['last_attempt_at' => now()]);
} else {
static::create([
'ip_address' => $ipAddress,
'reason' => 'Failed login attempts',
'is_permanent' => false,
'blocked_at' => now(),
'is_active' => false, // Not blocked yet, just tracking attempts
'failed_login_attempts' => 1,
'last_attempt_at' => now(),
]);
}
}
/**
* Auto-block IP after too many failed attempts
*/
public static function autoBlockIfNeeded(string $ipAddress, int $maxAttempts, int $blockDurationMinutes): bool
{
$record = static::where('ip_address', $ipAddress)->first();
if (!$record || $record->failed_login_attempts < $maxAttempts) {
return false;
}
// Block the IP
static::blockIP(
$ipAddress,
"Auto-blocked after {$maxAttempts} failed login attempts",
null, // System blocked
false, // Not permanent
now()->addMinutes($blockDurationMinutes)
);
return true;
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace Paymenter\Extensions\Others\Security\Models;
use Illuminate\Database\Eloquent\Model;
class LoginAttempt extends Model
{
protected $table = 'ext_security_login_attempts';
protected $fillable = [
'ip_address',
'email',
'successful',
'user_agent',
'country',
'notes',
'attempted_at',
];
protected $casts = [
'successful' => 'boolean',
'attempted_at' => 'datetime',
];
/**
* Record a login attempt
*/
public static function recordAttempt(
string $ipAddress,
?string $email = null,
bool $successful = false,
?string $userAgent = null,
?string $country = null,
?string $notes = null
): self {
return static::create([
'ip_address' => $ipAddress,
'email' => $email,
'successful' => $successful,
'user_agent' => $userAgent,
'country' => $country,
'notes' => $notes,
'attempted_at' => now(),
]);
}
/**
* Get recent failed attempts for an IP
*/
public static function getRecentFailedAttempts(string $ipAddress, int $minutes = 60): int
{
return static::where('ip_address', $ipAddress)
->where('successful', false)
->where('attempted_at', '>', now()->subMinutes($minutes))
->count();
}
/**
* Get recent failed attempts for an email
*/
public static function getRecentFailedAttemptsForEmail(string $email, int $minutes = 60): int
{
return static::where('email', $email)
->where('successful', false)
->where('attempted_at', '>', now()->subMinutes($minutes))
->count();
}
}

View File

@@ -0,0 +1,133 @@
<?php
namespace Paymenter\Extensions\Others\Security\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\User;
use Carbon\Carbon;
class SuspendedAccount extends Model
{
protected $table = 'ext_security_suspended_accounts';
protected $fillable = [
'user_id',
'reason',
'notes',
'is_permanent',
'suspended_at',
'suspended_until',
'suspended_by',
'lifted_at',
'lifted_by',
'is_active',
];
protected $casts = [
'suspended_at' => 'datetime',
'suspended_until' => 'datetime',
'lifted_at' => 'datetime',
'is_permanent' => 'boolean',
'is_active' => 'boolean',
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function suspendedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'suspended_by');
}
public function liftedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'lifted_by');
}
/**
* Check if the suspension is currently active
*/
public function isCurrentlyActive(): bool
{
if (!$this->is_active) {
return false;
}
if ($this->is_permanent) {
return true;
}
if ($this->suspended_until && Carbon::now()->isAfter($this->suspended_until)) {
return false;
}
return true;
}
/**
* Lift the suspension
*/
public function lift(int $liftedBy): void
{
$this->update([
'is_active' => false,
'lifted_at' => now(),
'lifted_by' => $liftedBy,
]);
}
/**
* Get active suspension for a user
*/
public static function getActiveSuspension(int $userId): ?self
{
return static::where('user_id', $userId)
->where('is_active', true)
->where(function ($query) {
$query->where('is_permanent', true)
->orWhere('suspended_until', '>', now())
->orWhereNull('suspended_until');
})
->first();
}
/**
* Check if a user is suspended
*/
public static function isUserSuspended(int $userId): bool
{
$suspension = static::getActiveSuspension($userId);
return $suspension && $suspension->isCurrentlyActive();
}
/**
* Suspend a user
*/
public static function suspendUser(
int $userId,
string $reason,
int $suspendedBy,
bool $isPermanent = false,
?Carbon $suspendedUntil = null,
?string $notes = null
): self {
// Deactivate any existing suspensions
static::where('user_id', $userId)
->where('is_active', true)
->update(['is_active' => false]);
return static::create([
'user_id' => $userId,
'reason' => $reason,
'notes' => $notes,
'is_permanent' => $isPermanent,
'suspended_at' => now(),
'suspended_until' => $suspendedUntil,
'suspended_by' => $suspendedBy,
'is_active' => true,
]);
}
}