stage 2 of oauth removal, switch to sanctum pat tokens completed, docs updated

This commit is contained in:
Codex Agent
2025-11-07 07:46:53 +01:00
parent 776da57ca9
commit 67affd3317
41 changed files with 124 additions and 2148 deletions

View File

@@ -1,39 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class OAuthClient extends Model
{
protected $table = 'oauth_clients';
protected $guarded = [];
protected $fillable = [
'id',
'client_id',
'client_secret',
'tenant_id',
'redirect_uris',
'scopes',
'is_active',
];
protected $casts = [
'id' => 'string',
'tenant_id' => 'integer',
'redirect_uris' => 'array',
'scopes' => 'array',
'is_active' => 'bool',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
}

View File

@@ -1,47 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class OAuthCode extends Model
{
protected $table = 'oauth_codes';
public $timestamps = false;
protected $guarded = [];
protected $fillable = [
'id',
'client_id',
'user_id',
'code',
'code_challenge',
'state',
'redirect_uri',
'scope',
'expires_at',
];
protected $casts = [
'expires_at' => 'datetime',
'created_at' => 'datetime',
];
public function client(): BelongsTo
{
return $this->belongsTo(OAuthClient::class, 'client_id', 'client_id');
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function isExpired(): bool
{
return $this->expires_at < now();
}
}

View File

@@ -1,120 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Http\Request;
class RefreshToken extends Model
{
public $incrementing = false;
protected $keyType = 'string';
public $timestamps = false;
protected $table = 'refresh_tokens';
protected $guarded = [];
protected $fillable = [
'id',
'tenant_id',
'client_id',
'token',
'access_token',
'expires_at',
'last_used_at',
'scope',
'ip_address',
'user_agent',
'revoked_at',
'revoked_reason',
];
protected $casts = [
'expires_at' => 'datetime',
'last_used_at' => 'datetime',
'revoked_at' => 'datetime',
'created_at' => 'datetime',
];
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
public function audits(): HasMany
{
return $this->hasMany(RefreshTokenAudit::class);
}
public function revoke(?string $reason = null, ?int $performedBy = null, ?Request $request = null, array $context = []): bool
{
$result = $this->update([
'revoked_at' => now(),
'revoked_reason' => $reason,
]);
$event = match ($reason) {
'rotated' => 'rotated',
'ip_mismatch' => 'ip_mismatch',
'expired' => 'expired',
'invalid_secret' => 'invalid_secret',
'tenant_missing' => 'tenant_missing',
'max_active_limit' => 'max_active_limit',
default => 'revoked',
};
$this->recordAudit(
$event,
array_merge([
'reason' => $reason,
], $context),
$performedBy,
$request
);
return $result;
}
public function isActive(): bool
{
if ($this->revoked_at !== null) {
return false;
}
return $this->expires_at === null || $this->expires_at->isFuture();
}
public function scopeActive($query)
{
return $query
->whereNull('revoked_at')
->where(function ($inner) {
$inner->whereNull('expires_at')
->orWhere('expires_at', '>', now());
});
}
public function scopeForTenant($query, string $tenantId)
{
return $query->where('tenant_id', $tenantId);
}
public function recordAudit(string $event, array $context = [], ?int $performedBy = null, ?Request $request = null): void
{
$request ??= request();
$this->audits()->create([
'tenant_id' => $this->tenant_id,
'client_id' => $this->client_id,
'event' => $event,
'context' => $context ?: null,
'ip_address' => $request?->ip(),
'user_agent' => $request?->userAgent(),
'performed_by' => $performedBy,
'created_at' => now(),
]);
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class RefreshTokenAudit extends Model
{
use HasFactory;
protected $fillable = [
'refresh_token_id',
'tenant_id',
'client_id',
'event',
'context',
'ip_address',
'user_agent',
'performed_by',
'created_at',
];
public $timestamps = false;
protected $casts = [
'context' => 'array',
'created_at' => 'datetime',
];
public function refreshToken(): BelongsTo
{
return $this->belongsTo(RefreshToken::class);
}
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
public function performedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'performed_by');
}
}

View File

@@ -1,51 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TenantToken extends Model
{
public $incrementing = false;
protected $keyType = 'string';
public $timestamps = false;
protected $table = 'tenant_tokens';
protected $guarded = [];
protected $fillable = [
'id',
'tenant_id',
'jti',
'token_type',
'expires_at',
'revoked_at',
];
protected $casts = [
'expires_at' => 'datetime',
'revoked_at' => 'datetime',
'created_at' => 'datetime',
];
public function scopeActive($query)
{
return $query->whereNull('revoked_at')->where('expires_at', '>', now());
}
public function scopeForTenant($query, string $tenantId)
{
return $query->where('tenant_id', $tenantId);
}
public function revoke(): bool
{
return $this->update(['revoked_at' => now()]);
}
public function isActive(): bool
{
return $this->revoked_at === null && $this->expires_at > now();
}
}