Files
biiproject-kit-v1/app/Models/User.php
T

215 lines
5.6 KiB
PHP

<?php
/**
* ============================================================
*
* @project biiproject
*
* @author Andika Debi Putra
*
* @email andikadebiputra@gmail.com
*
* @website https://biiproject.com
*
* @copyright Copyright (c) 2026 Andika Debi Putra
* @license Proprietary - All Rights Reserved
*
* @version 1.0.0
*
* @created 2026-05-01
* ============================================================
*
* Unauthorized copying, modification, distribution, or use
* of this file is strictly prohibited without prior written
* permission from the author.
* ============================================================
*/
namespace App\Models;
use App\Notifications\Auth\ResetPasswordNotification;
use App\Notifications\Auth\VerifyEmailNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable as WebAuthnContract;
use Laragear\WebAuthn\WebAuthnAuthentication;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements HasMedia, WebAuthnContract
{
use HasApiTokens, HasFactory, HasRoles, InteractsWithMedia, LogsActivity, Notifiable, SoftDeletes, WebAuthnAuthentication;
protected string $guard_name = 'web';
/**
* Spatie Activitylog configuration
*/
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->useLogName('user-management')
->logOnly(['name', 'username', 'email', 'phone_number', 'is_active'])
->logOnlyDirty()
->dontSubmitEmptyLogs();
}
/**
* The attributes that are mass assignable.
*/
protected $fillable = [
'name',
'username',
'email',
'phone_number',
'password',
'google_id',
'facebook_id',
'github_id',
'is_active',
'password_changed_at',
'last_session_id',
'created_by',
'updated_by',
];
/**
* Hidden fields
*/
protected $hidden = [
'password',
'remember_token',
'media', // Hide raw media relation
];
/**
* Appended attributes
*/
protected $appends = ['avatar'];
/**
* Avatar Accessor (using Media Library)
*/
public function getAvatarAttribute(): ?string
{
return $this->getFirstMediaUrl('avatar') ?: null;
}
/**
* The attributes that should be cast.
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'is_active' => 'boolean',
'password_changed_at' => 'datetime',
];
/**
* Password History Relation
*/
public function passwordHistories()
{
return $this->hasMany(PasswordHistory::class);
}
/**
* Trusted Devices Relation
*/
public function trustedDevices()
{
return $this->hasMany(UserTrustedDevice::class);
}
/**
* ==========================================
* DISABLE RESET PASSWORD FOR SOCIAL USERS
* ==========================================
*/
public function sendPasswordResetNotification($token)
{
// ❌ OAuth user → BLOCK reset password
if ($this->google_id || $this->facebook_id || $this->github_id) {
return;
}
// ✅ User manual → normal
$this->notify(new ResetPasswordNotification($token));
}
/**
* Use our branded email verification template.
*/
public function sendEmailVerificationNotification()
{
$this->notify(new VerifyEmailNotification);
}
/**
* Helpers
*/
public function isSocialUser(): bool
{
return ! is_null($this->google_id) || ! is_null($this->facebook_id) || ! is_null($this->github_id);
}
/**
* Consents Relation
*/
public function consents()
{
return $this->hasMany(UserConsent::class);
}
/**
* Check if user has agreed to the current version of a document.
*/
public function hasAgreedToCurrentLegal(string $type): bool
{
// Settings use 'pdp' prefix for Privacy Policy, while code uses 'privacy' type
$keyPrefix = ($type === 'privacy' || $type === 'pdp') ? 'pdp' : $type;
$currentVersion = (int) get_setting("{$keyPrefix}_document_version", 1);
return $this->consents()
->where(function ($q) use ($type) {
$q->where('consent_type', $type)
->orWhere('consent_type', 'privacy')
->orWhere('consent_type', 'pdp');
})
->where('version_id', '>=', $currentVersion)
->exists();
}
/**
* Notifications this user has interacted with (including personal read/deleted status).
*/
public function broadcastNotifications()
{
return $this->belongsToMany(Notification::class, 'system_notification_user')
->withPivot('read_at', 'deleted_at')
->withTimestamps();
}
/**
* Get the user who created this record.
*/
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* Get the user who last updated this record.
*/
public function updater()
{
return $this->belongsTo(User::class, 'updated_by');
}
}