143 lines
3.4 KiB
PHP

<?php namespace App\Models;
/**
* @copyright (c) 2025 Notsoweb Software (https://notsoweb.com) - All Rights Reserved
*/
use App\Helpers\EncryptionHelper;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
/**
* Modelo Arco RFID
*
* Representa un arco lector RFID físico identificado por su dirección IP
*
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
*
* @version 1.0.0
*/
class Arco extends Model
{
protected $table = 'arcos';
protected $fillable = [
'nombre',
'ip_address',
'ubicacion',
'activo',
'antena_1',
'antena_2',
'antena_3',
'antena_4'
];
protected $casts = [
'activo' => 'boolean',
'created_at' => 'datetime',
'updated_at' => 'datetime'
];
protected $hidden = [
'api_token'
];
protected static function boot()
{
parent::boot();
static::creating(function ($arco) {
if (!$arco->api_token) {
$plainToken = Str::random(64);
$arco->api_token = EncryptionHelper::encryptWithCustomKey(
$plainToken,
self::getEncryptionKey()
);
}
});
}
/**
* Obtener la clave de encriptación personalizada para tokens de arcos
*/
private static function getEncryptionKey(): string
{
$key = config('app.arco_token_encryption_key');
if (empty($key)) {
throw new \RuntimeException('ARCO_TOKEN_ENCRYPTION_KEY no está configurada en .env');
}
// Si la clave está en formato base64:xxxx, decodificarla
if (str_starts_with($key, 'base64:')) {
return base64_decode(substr($key, 7));
}
return $key;
}
/**
* Relación con detecciones
*/
public function detecciones(): HasMany
{
return $this->hasMany(Detection::class, 'arco_id');
}
/**
* Scope para obtener solo arcos activos
*/
public function scopeActivos($query)
{
return $query->where('activo', true);
}
/**
* Buscar arco por IP
*/
public static function buscarPorIp(string $ip): ?self
{
return self::where('ip_address', $ip)->first();
}
/**
* Buscar arco por API token (recibe token plano, busca desencriptando)
*/
public static function buscarPorToken(string $tokenPlano): ?self
{
$arcos = self::all();
foreach ($arcos as $arco) {
// Desencriptar el token de la BD y comparar con el token plano recibido
if (EncryptionHelper::verifyWithCustomKey($tokenPlano, $arco->api_token, self::getEncryptionKey())) {
return $arco;
}
}
return null;
}
/**
* Regenerar token encriptado
*/
public function regenerarToken(): string
{
$plainToken = Str::random(64);
$this->api_token = EncryptionHelper::encryptWithCustomKey(
$plainToken,
self::getEncryptionKey()
);
$this->save();
return $plainToken;
}
/**
* Obtener token desencriptado
*/
public function obtenerTokenDesencriptado(): ?string
{
return EncryptionHelper::decryptWithCustomKey($this->api_token, self::getEncryptionKey());
}
}