2019-05-20 07:37:41 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App;
|
|
|
|
|
2020-11-05 22:54:06 +01:00
|
|
|
use Exception;
|
2020-01-24 12:56:38 +01:00
|
|
|
use OTPHP\HOTP;
|
|
|
|
use OTPHP\Factory;
|
2020-10-31 01:16:15 +01:00
|
|
|
use App\Classes\Options;
|
2020-03-25 21:58:05 +01:00
|
|
|
use Spatie\EloquentSortable\Sortable;
|
|
|
|
use Spatie\EloquentSortable\SortableTrait;
|
2019-05-20 07:37:41 +02:00
|
|
|
use Illuminate\Database\Eloquent\Model;
|
2020-01-08 17:03:41 +01:00
|
|
|
use Illuminate\Support\Facades\Storage;
|
2020-10-31 01:16:15 +01:00
|
|
|
use Illuminate\Support\Facades\Crypt;
|
2019-05-20 07:37:41 +02:00
|
|
|
|
2020-03-25 21:58:05 +01:00
|
|
|
class TwoFAccount extends Model implements Sortable
|
2019-05-20 07:37:41 +02:00
|
|
|
{
|
2020-03-25 21:58:05 +01:00
|
|
|
|
|
|
|
use SortableTrait;
|
|
|
|
|
|
|
|
|
2020-01-10 13:43:36 +01:00
|
|
|
/**
|
|
|
|
* model's array form.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $fillable = ['service', 'account', 'uri', 'icon'];
|
2019-05-24 14:44:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The table associated with the model.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $table = 'twofaccounts';
|
2020-01-08 17:03:41 +01:00
|
|
|
|
|
|
|
|
2020-01-24 12:56:38 +01:00
|
|
|
/**
|
|
|
|
* The accessors to append to the model's array form.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2020-11-06 21:49:43 +01:00
|
|
|
protected $appends = ['otpType', 'counter', 'isConsistent'];
|
2020-01-24 12:56:38 +01:00
|
|
|
|
|
|
|
|
2020-11-06 15:51:52 +01:00
|
|
|
/**
|
|
|
|
* The attributes that should be hidden for arrays.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $hidden = ['uri'];
|
|
|
|
|
|
|
|
|
2020-01-31 23:05:06 +01:00
|
|
|
/**
|
|
|
|
* Override The "booting" method of the model
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
protected static function boot()
|
|
|
|
{
|
|
|
|
parent::boot();
|
|
|
|
|
|
|
|
static::deleted(function ($model) {
|
|
|
|
Storage::delete('public/icons/' . $model->icon);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-25 23:51:50 +01:00
|
|
|
/**
|
|
|
|
* Scope a query to only include TwoFAccounts of a given group.
|
|
|
|
*
|
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
|
|
* @param mixed $groupId
|
|
|
|
* @return \Illuminate\Database\Eloquent\Builder
|
|
|
|
*/
|
|
|
|
public function scopeOfGroup($query, $groupId)
|
|
|
|
{
|
|
|
|
if( $groupId ) {
|
|
|
|
return $query->where('group_id', $groupId);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $query;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-25 21:58:05 +01:00
|
|
|
/**
|
|
|
|
* Sortable settings
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
public $sortable = [
|
|
|
|
'order_column_name' => 'order_column',
|
|
|
|
'sort_when_creating' => true,
|
|
|
|
];
|
|
|
|
|
|
|
|
|
2020-01-08 17:03:41 +01:00
|
|
|
/**
|
|
|
|
* Null empty icon resource has gone
|
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return string
|
2020-03-08 20:16:56 +01:00
|
|
|
*
|
|
|
|
* @codeCoverageIgnore
|
2020-01-08 17:03:41 +01:00
|
|
|
*/
|
|
|
|
public function getIconAttribute($value)
|
|
|
|
{
|
2020-01-10 13:43:36 +01:00
|
|
|
if (\App::environment('testing') == false) {
|
2020-01-27 21:44:29 +01:00
|
|
|
if( !Storage::exists('public/icons/' . $value) ) {
|
2020-01-08 17:03:41 +01:00
|
|
|
|
2020-01-10 13:43:36 +01:00
|
|
|
return '';
|
|
|
|
}
|
2020-01-08 17:03:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
}
|
2020-01-21 21:31:28 +01:00
|
|
|
|
2020-01-27 13:52:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prevent setting a missing icon
|
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return string
|
2020-03-08 20:16:56 +01:00
|
|
|
*
|
|
|
|
* @codeCoverageIgnore
|
2020-01-27 13:52:47 +01:00
|
|
|
*/
|
|
|
|
public function setIconAttribute($value)
|
|
|
|
{
|
|
|
|
|
2020-01-27 21:44:29 +01:00
|
|
|
if( !Storage::exists('public/icons/' . $value) && \App::environment('testing') == false ) {
|
2020-01-27 13:52:47 +01:00
|
|
|
|
|
|
|
$this->attributes['icon'] = '';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
$this->attributes['icon'] = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-01-24 12:56:38 +01:00
|
|
|
/**
|
2020-11-05 22:50:49 +01:00
|
|
|
* Get the account OTP type.
|
2020-01-24 12:56:38 +01:00
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2020-11-05 22:50:49 +01:00
|
|
|
public function getOtpTypeAttribute()
|
2020-01-24 12:56:38 +01:00
|
|
|
{
|
2020-11-05 22:50:49 +01:00
|
|
|
switch (substr( $this->uri, 0, 15 )) {
|
|
|
|
|
|
|
|
case "otpauth://totp/" :
|
|
|
|
return 'totp';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "otpauth://hotp/" :
|
|
|
|
return 'hotp';
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
2020-01-24 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the account counter in case of HOTP.
|
|
|
|
*
|
|
|
|
* @return integer
|
|
|
|
*/
|
|
|
|
public function getCounterAttribute()
|
|
|
|
{
|
|
|
|
|
2020-11-05 22:50:49 +01:00
|
|
|
if( $this->otpType === 'hotp' ) {
|
2020-01-24 12:56:38 +01:00
|
|
|
$otp = Factory::loadFromProvisioningUri($this->uri);
|
|
|
|
|
|
|
|
return $otp->getCounter();
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-21 21:31:28 +01:00
|
|
|
/**
|
2020-10-31 01:16:15 +01:00
|
|
|
* Set encrypted uri
|
2020-01-21 21:31:28 +01:00
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return void
|
|
|
|
*/
|
2020-10-31 01:16:15 +01:00
|
|
|
public function setUriAttribute($value)
|
|
|
|
{
|
|
|
|
$this->attributes['uri'] = Options::get('useEncryption') ? Crypt::encryptString($value) : $value;
|
|
|
|
}
|
2020-01-21 21:31:28 +01:00
|
|
|
|
|
|
|
/**
|
2020-10-31 01:16:15 +01:00
|
|
|
* Get decyphered uri
|
2020-01-21 21:31:28 +01:00
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return string
|
|
|
|
*/
|
2020-10-31 01:16:15 +01:00
|
|
|
public function getUriAttribute($value)
|
|
|
|
{
|
|
|
|
if( Options::get('useEncryption') )
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return Crypt::decryptString($value);
|
|
|
|
}
|
2020-11-05 22:54:06 +01:00
|
|
|
catch (Exception $e) {
|
2020-10-31 01:16:15 +01:00
|
|
|
return '*encrypted*';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
}
|
2020-01-21 21:31:28 +01:00
|
|
|
|
|
|
|
|
2020-10-31 01:16:15 +01:00
|
|
|
/**
|
|
|
|
* Set encrypted account
|
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function setAccountAttribute($value)
|
|
|
|
{
|
|
|
|
$this->attributes['account'] = Options::get('useEncryption') ? Crypt::encryptString($value) : $value;
|
|
|
|
}
|
2020-01-21 21:31:28 +01:00
|
|
|
|
2020-10-31 01:16:15 +01:00
|
|
|
/**
|
|
|
|
* Get decyphered account
|
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getAccountAttribute($value)
|
|
|
|
{
|
|
|
|
if( Options::get('useEncryption') )
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return Crypt::decryptString($value);
|
|
|
|
}
|
2020-11-05 22:54:06 +01:00
|
|
|
catch (Exception $e) {
|
2020-10-31 01:16:15 +01:00
|
|
|
return '*encrypted*';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
}
|
2020-01-21 21:31:28 +01:00
|
|
|
|
2020-11-06 21:49:43 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Null empty icon resource has gone
|
|
|
|
*
|
|
|
|
* @param string $value
|
|
|
|
* @return string
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function getIsConsistentAttribute($value)
|
|
|
|
{
|
|
|
|
return $this->uri === '*encrypted*' || $this->account === '*encrypted*' ? false : true;
|
|
|
|
}
|
|
|
|
|
2019-05-20 07:37:41 +02:00
|
|
|
}
|