<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use Laravel\Sanctum\HasApiTokens;
/**
* @method static where(string $string, bool $true)
* @method getProvider($provider)
* @method providers()
* @method truncate()
* @method create(array $array)
* @method static find($end_by)
* @property mixed is_admin
* @property mixed first_name
* @property mixed last_name
* @property mixed id
* @property mixed roles
*/
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'first_name',
'last_name',
'api_token',
'password',
'image',
'email',
'status',
'is_admin',
'is_customer',
'active_portal',
'two_factor',
'two_factor_code',
'two_factor_expires_at',
'locale',
'sms_unit',
'timezone',
'provider',
'provider_id',
'email_verified_at',
'two_factor_backup_code',
'api_sending_server',
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = [
'last_access_at',
'two_factor_expires_at',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'is_admin' => 'boolean',
'is_customer' => 'boolean',
'status' => 'boolean',
'two_factor' => 'boolean',
];
/**
* Find item by uid.
*
* @param $uid
*
* @return object
*/
public static function findByUid($uid): object
{
return self::where('uid', $uid)->first();
}
public function customer(): HasOne
{
return $this->hasOne(Customer::class);
}
public function admin(): HasOne
{
return $this->hasOne(Admin::class);
}
public function systemJobs(): HasMany
{
return $this->hasMany(SystemJob::class)->orderBy('created_at', 'desc');
}
public static function boot()
{
parent::boot();
// Create uid when creating list.
static::creating(function ($item) {
// Create new uid
$uid = uniqid();
while (self::where('uid', $uid)->count() > 0) {
$uid = uniqid();
}
$item->uid = $uid;
if (config('app.two_factor')) {
$item->two_factor_backup_code = self::generateTwoFactorBackUpCode();
}
});
}
/**
* Check if user has admin account.
*/
public function isAdmin(): bool
{
return 1 == $this->is_admin;
}
/**
* Check if user has admin account.
*/
public function isCustomer(): bool
{
return 1 == $this->is_customer;
}
/*
* Display User Name
*/
public function displayName(): string
{
return $this->first_name.' '.$this->last_name;
}
/**
* generate two factor code
*/
public function generateTwoFactorCode()
{
$this->timestamps = false;
$this->two_factor_code = rand(100000, 999999);
$this->two_factor_expires_at = now()->addMinutes(10);
$this->save();
}
/**
* Reset two factor code
*/
public function resetTwoFactorCode()
{
$this->timestamps = false;
$this->two_factor_code = null;
$this->two_factor_expires_at = null;
$this->save();
}
/**
* generate two factor backup code
*
* @return false|string
*/
public static function generateTwoFactorBackUpCode()
{
$backUpCode = [];
for ($i = 0; $i < 8; $i++) {
$backUpCode[] = rand(100000, 999999);
}
return json_encode($backUpCode);
}
/**
* Upload and resize avatar.
*
* @return string
* @var void
*/
public function uploadImage($file): string
{
$path = 'app/profile/';
$upload_path = storage_path($path);
if ( ! file_exists($upload_path)) {
mkdir($upload_path, 0777, true);
}
$filename = 'avatar-'.$this->id.'.'.$file->getClientOriginalExtension();
// save to server
$file->move($upload_path, $filename);
// create thumbnails
$img = Image::make($upload_path.$filename);
$img->fit(120, 120, function ($c) {
$c->aspectRatio();
$c->upsize();
})->save($upload_path.$filename.'.thumb.jpg');
return $path.$filename;
}
/**
* Get image thumb path.
*
* @return string
* @var string
*/
public function imagePath(): string
{
if ( ! empty($this->image) && ! empty($this->id)) {
return storage_path($this->image).'.thumb.jpg';
} else {
return '';
}
}
/**
* Get image thumb path.
*
* @var string
*/
public function removeImage()
{
if ( ! empty($this->image) && ! empty($this->id)) {
$path = storage_path($this->image);
if (is_file($path)) {
unlink($path);
}
if (is_file($path.'.thumb.jpg')) {
unlink($path.'.thumb.jpg');
}
}
}
public function getCanEditAttribute(): bool
{
return 1 === auth()->id();
}
public function getCanDeleteAttribute(): bool
{
return $this->id !== auth()->id() && (Gate::check('delete customer'));
}
public function getIsSuperAdminAttribute(): bool
{
return 1 === $this->id;
}
/**
* Many-to-Many relations with Role.
*
* @return BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class);
}
/**
* @param $name
*
* @return bool
*/
public function hasRole($name): bool
{
return $this->roles->contains('name', $name);
}
/**
* @return Collection
*/
public function getPermissions(): Collection
{
$permissions = [];
foreach ($this->roles as $role) {
foreach ($role->permissions as $permission) {
if ( ! in_array($permission, $permissions, true)) {
$permissions[] = $permission;
}
}
}
return collect($permissions);
}
/**
* get route key by uid
*
* @return string
*/
public function getRouteKeyName(): string
{
return 'uid';
}
}