mirror of
https://github.com/dyzulk/trustlab-api.git
synced 2026-01-26 13:22:05 +07:00
First commit
This commit is contained in:
36
app/Models/ActivityLog.php
Normal file
36
app/Models/ActivityLog.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Helpers\UuidHelper;
|
||||
|
||||
class ActivityLog extends Model
|
||||
{
|
||||
protected $primaryKey = 'id';
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'user_id',
|
||||
'action',
|
||||
'description',
|
||||
'ip_address',
|
||||
'user_agent'
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->id)) {
|
||||
$model->id = UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
55
app/Models/ApiKey.php
Normal file
55
app/Models/ApiKey.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ApiKey extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $primaryKey = 'id';
|
||||
protected $keyType = 'string';
|
||||
public $incrementing = false;
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->id)) {
|
||||
$model->id = \App\Helpers\UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'name',
|
||||
'key',
|
||||
'last_used_at',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'last_used_at' => 'datetime',
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique API Key.
|
||||
*/
|
||||
public static function generate()
|
||||
{
|
||||
do {
|
||||
$key = 'dvp_' . Str::random(56); // Prefix (4) + Random (56) = 60 chars
|
||||
} while (static::where('key', $key)->exists());
|
||||
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
42
app/Models/CaCertificate.php
Normal file
42
app/Models/CaCertificate.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Helpers\UuidHelper;
|
||||
|
||||
class CaCertificate extends Model
|
||||
{
|
||||
protected $primaryKey = 'uuid';
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected $fillable = [
|
||||
'uuid',
|
||||
'ca_type',
|
||||
'cert_content',
|
||||
'key_content',
|
||||
'serial_number',
|
||||
'common_name',
|
||||
'organization',
|
||||
'valid_from',
|
||||
'valid_to',
|
||||
'download_count',
|
||||
'last_downloaded_at'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'valid_from' => 'datetime',
|
||||
'valid_to' => 'datetime',
|
||||
'last_downloaded_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->uuid)) {
|
||||
$model->uuid = UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
82
app/Models/Certificate.php
Normal file
82
app/Models/Certificate.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Helpers\UuidHelper;
|
||||
|
||||
class Certificate extends Model
|
||||
{
|
||||
protected $primaryKey = 'uuid';
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected $fillable = [
|
||||
'uuid', 'user_id', 'common_name', 'organization', 'locality',
|
||||
'state', 'country', 'san', 'key_bits', 'serial_number',
|
||||
'cert_content', 'key_content', 'csr_content',
|
||||
'valid_from', 'valid_to', 'expired_notification_sent_at'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'valid_from' => 'datetime',
|
||||
'valid_to' => 'datetime',
|
||||
'expired_notification_sent_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'expired_notification_sent_at',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'ssl_status',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->uuid)) {
|
||||
$model->uuid = UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function getSslStatusAttribute()
|
||||
{
|
||||
if ($this->valid_to && $this->valid_to->isPast()) {
|
||||
return 'EXPIRED';
|
||||
}
|
||||
return 'ACTIVE';
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
$array = parent::toArray();
|
||||
$ordered = [];
|
||||
|
||||
// Define the preferred order of keys
|
||||
$paramOrder = [
|
||||
'uuid', 'user_id', 'common_name', 'organization', 'locality',
|
||||
'state', 'country', 'san', 'status', 'key_bits', 'serial_number',
|
||||
'ssl_status', // <--- Inserted here (before content)
|
||||
'cert_content', 'key_content', 'csr_content',
|
||||
'valid_from', 'valid_to', 'created_at', 'updated_at'
|
||||
];
|
||||
|
||||
// Reconstruct query based on paramOrder
|
||||
foreach ($paramOrder as $key) {
|
||||
if (array_key_exists($key, $array)) {
|
||||
$ordered[$key] = $array[$key];
|
||||
unset($array[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Append any remaining keys (that weren't in our explicit list)
|
||||
return array_merge($ordered, $array);
|
||||
}
|
||||
}
|
||||
38
app/Models/Inquiry.php
Normal file
38
app/Models/Inquiry.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class Inquiry extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'category',
|
||||
'subject',
|
||||
'message',
|
||||
'status',
|
||||
'replied_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'replied_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->{$model->getKeyName()})) {
|
||||
$model->{$model->getKeyName()} = \App\Helpers\UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
32
app/Models/LegalPage.php
Normal file
32
app/Models/LegalPage.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
|
||||
class LegalPage extends Model
|
||||
{
|
||||
use HasFactory, HasUuids;
|
||||
|
||||
protected $fillable = ['title', 'slug', 'is_active'];
|
||||
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
public function revisions()
|
||||
{
|
||||
return $this->hasMany(LegalPageRevision::class);
|
||||
}
|
||||
|
||||
public function latestRevision()
|
||||
{
|
||||
return $this->hasOne(LegalPageRevision::class)->latestOfMany('created_at');
|
||||
}
|
||||
|
||||
public function currentRevision()
|
||||
{
|
||||
return $this->hasOne(LegalPageRevision::class)->where('is_active', true)->latest();
|
||||
}
|
||||
}
|
||||
35
app/Models/LegalPageRevision.php
Normal file
35
app/Models/LegalPageRevision.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
|
||||
class LegalPageRevision extends Model
|
||||
{
|
||||
use HasFactory, HasUuids;
|
||||
|
||||
protected $fillable = [
|
||||
'legal_page_id',
|
||||
'content',
|
||||
'major', 'minor', 'patch',
|
||||
'status', 'published_at',
|
||||
'change_log', 'is_active', 'created_by'
|
||||
];
|
||||
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected $appends = ['version'];
|
||||
|
||||
public function getVersionAttribute()
|
||||
{
|
||||
return "{$this->major}.{$this->minor}.{$this->patch}";
|
||||
}
|
||||
|
||||
public function legalPage()
|
||||
{
|
||||
return $this->belongsTo(LegalPage::class);
|
||||
}
|
||||
}
|
||||
41
app/Models/LoginHistory.php
Normal file
41
app/Models/LoginHistory.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class LoginHistory extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $primaryKey = 'id';
|
||||
protected $keyType = 'string';
|
||||
public $incrementing = false;
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->id)) {
|
||||
$model->id = \App\Helpers\UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'ip_address',
|
||||
'user_agent',
|
||||
'device_type',
|
||||
'os',
|
||||
'browser',
|
||||
'city',
|
||||
'country',
|
||||
'country_code',
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
40
app/Models/SocialAccount.php
Normal file
40
app/Models/SocialAccount.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SocialAccount extends Model
|
||||
{
|
||||
protected $primaryKey = 'id';
|
||||
protected $keyType = 'string';
|
||||
public $incrementing = false;
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->id)) {
|
||||
$model->id = \App\Helpers\UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'provider',
|
||||
'provider_id',
|
||||
'provider_email',
|
||||
'avatar',
|
||||
'token',
|
||||
'refresh_token',
|
||||
'expires_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'expires_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
45
app/Models/Ticket.php
Normal file
45
app/Models/Ticket.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
|
||||
class Ticket extends Model
|
||||
{
|
||||
use HasFactory, HasUuids;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'ticket_number',
|
||||
'subject',
|
||||
'category',
|
||||
'priority',
|
||||
'status',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the user that owns the ticket.
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the replies for the ticket.
|
||||
*/
|
||||
public function replies()
|
||||
{
|
||||
return $this->hasMany(TicketReply::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to generate a unique ticket number.
|
||||
*/
|
||||
public static function generateTicketNumber()
|
||||
{
|
||||
return 'TKT-' . strtoupper(bin2hex(random_bytes(3)));
|
||||
}
|
||||
}
|
||||
25
app/Models/TicketAttachment.php
Normal file
25
app/Models/TicketAttachment.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TicketAttachment extends Model
|
||||
{
|
||||
use HasFactory, HasUuids;
|
||||
|
||||
protected $fillable = [
|
||||
'ticket_reply_id',
|
||||
'file_name',
|
||||
'file_path',
|
||||
'file_type',
|
||||
'file_size',
|
||||
];
|
||||
|
||||
public function reply()
|
||||
{
|
||||
return $this->belongsTo(TicketReply::class, 'ticket_reply_id');
|
||||
}
|
||||
}
|
||||
40
app/Models/TicketReply.php
Normal file
40
app/Models/TicketReply.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
|
||||
class TicketReply extends Model
|
||||
{
|
||||
use HasFactory, HasUuids;
|
||||
|
||||
protected $fillable = [
|
||||
'ticket_id',
|
||||
'user_id',
|
||||
'message',
|
||||
'attachment_path',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the ticket that owns the reply.
|
||||
*/
|
||||
public function ticket()
|
||||
{
|
||||
return $this->belongsTo(Ticket::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user that wrote the reply.
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function attachments()
|
||||
{
|
||||
return $this->hasMany(TicketAttachment::class);
|
||||
}
|
||||
}
|
||||
189
app/Models/User.php
Normal file
189
app/Models/User.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable implements MustVerifyEmail
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
|
||||
public const ROLE_OWNER = 'owner';
|
||||
public const ROLE_ADMIN = 'admin';
|
||||
public const ROLE_CUSTOMER = 'customer';
|
||||
|
||||
/**
|
||||
* The channels the user receives notification broadcasts on.
|
||||
*/
|
||||
public function receivesBroadcastNotificationsOn(): string
|
||||
{
|
||||
return 'App.Models.User.' . $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the API keys for the user.
|
||||
*/
|
||||
public function apiKeys()
|
||||
{
|
||||
return $this->hasMany(ApiKey::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login history for the user.
|
||||
*/
|
||||
public function loginHistories()
|
||||
{
|
||||
return $this->hasMany(LoginHistory::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tickets for the user.
|
||||
*/
|
||||
public function tickets()
|
||||
{
|
||||
return $this->hasMany(Ticket::class);
|
||||
}
|
||||
|
||||
public $incrementing = false;
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->{$model->getKeyName()})) {
|
||||
$model->{$model->getKeyName()} = \App\Helpers\UuidHelper::generate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'pending_email',
|
||||
'password',
|
||||
'avatar',
|
||||
'role',
|
||||
'phone',
|
||||
'bio',
|
||||
'job_title',
|
||||
'location',
|
||||
'country',
|
||||
'city_state',
|
||||
'postal_code',
|
||||
'tax_id',
|
||||
'settings_email_alerts',
|
||||
'settings_certificate_renewal',
|
||||
'default_landing_page',
|
||||
'theme',
|
||||
'language',
|
||||
'email_verified_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the social accounts for the user.
|
||||
*/
|
||||
public function socialAccounts()
|
||||
{
|
||||
return $this->hasMany(SocialAccount::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is owner.
|
||||
*/
|
||||
public function isOwner(): bool
|
||||
{
|
||||
return $this->role === self::ROLE_OWNER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is admin.
|
||||
*/
|
||||
public function isAdmin(): bool
|
||||
{
|
||||
return $this->role === self::ROLE_ADMIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is admin or owner.
|
||||
*/
|
||||
public function isAdminOrOwner(): bool
|
||||
{
|
||||
return in_array($this->role, [self::ROLE_OWNER, self::ROLE_ADMIN]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the avatar URL with cache busting timestamp.
|
||||
*/
|
||||
public function getAvatarAttribute($value)
|
||||
{
|
||||
if (!$value) return $value;
|
||||
|
||||
// If it's already a full R2 URL, append timestamp
|
||||
if (str_contains($value, 'cdn.trustlab.dyzulk.com')) {
|
||||
$separator = str_contains($value, '?') ? '&' : '?';
|
||||
return $value . $separator . 't=' . ($this->updated_at ? $this->updated_at->timestamp : time());
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'settings_email_alerts' => 'boolean',
|
||||
'settings_certificate_renewal' => 'boolean',
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Send the email verification notification.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendEmailVerificationNotification()
|
||||
{
|
||||
$this->notify(new \App\Notifications\VerifyEmailNotification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route notifications for the mail channel.
|
||||
*
|
||||
* @param \Illuminate\Notifications\Notification $notification
|
||||
* @return array|string
|
||||
*/
|
||||
public function routeNotificationForMail($notification)
|
||||
{
|
||||
if ($notification instanceof \App\Notifications\PendingEmailVerificationNotification) {
|
||||
return $this->pending_email;
|
||||
}
|
||||
|
||||
return $this->email;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user