Files
crewli/api/app/Models/EmailChangeRequest.php
bert.hausmans 836cffa232 feat: password reset, email change with verification, and password change
Password reset: multi-app support with custom notification linking to correct
frontend (app/portal/admin). Email change: self-service with password
confirmation and admin-initiated, both sending verification to new address
with 24h expiry. Confirmation sent to old email on completion. Password
change: authenticated endpoint revoking other sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:38:54 +02:00

59 lines
1.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Models;
use App\Enums\EmailChangeStatus;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
final class EmailChangeRequest extends Model
{
use HasUlids;
protected $fillable = [
'user_id',
'current_email',
'new_email',
'token',
'requested_by_user_id',
'status',
'expires_at',
'verified_at',
];
protected $hidden = ['token'];
protected function casts(): array
{
return [
'status' => EmailChangeStatus::class,
'expires_at' => 'datetime',
'verified_at' => 'datetime',
];
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function requestedBy(): BelongsTo
{
return $this->belongsTo(User::class, 'requested_by_user_id');
}
public function isExpired(): bool
{
return $this->expires_at->isPast();
}
public function scopePending($query)
{
return $query->where('status', EmailChangeStatus::PENDING)
->where('expires_at', '>', now());
}
}