feat: add app and database modules
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user