feat: actualiza controladores y solicitudes para mejorar la gestión de permisos y validaciones

This commit is contained in:
Juan Felipe Zapata Moreno 2026-02-26 12:43:09 -06:00
parent 0faabb3026
commit ad6b19e9dd
15 changed files with 141 additions and 293 deletions

View File

@ -40,8 +40,13 @@ public function all()
*/ */
public function allWithPermissions() public function allWithPermissions()
{ {
$hidden = ['Actividad'];
return ApiResponse::OK->response([ return ApiResponse::OK->response([
'models' => PermissionType::with('permissions')->orderBy('name')->get() 'models' => PermissionType::with('permissions')
->whereNotIn('name', $hidden)
->orderBy('name')
->get()
]); ]);
} }
} }

View File

@ -103,8 +103,12 @@ public function destroy(Role $role)
*/ */
public function permissions(Role $role) public function permissions(Role $role)
{ {
$permissions = $role->id === 2
? $role->permissions->filter(fn($p) => !str_starts_with($p->name, 'activities.'))
: $role->permissions;
return ApiResponse::OK->response([ return ApiResponse::OK->response([
'permissions' => $role->permissions 'permissions' => $permissions->values()
]); ]);
} }

View File

@ -12,6 +12,7 @@
use App\Supports\QuerySupport; use App\Supports\QuerySupport;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Notsoweb\ApiResponse\Enums\ApiResponse; use Notsoweb\ApiResponse\Enums\ApiResponse;
use Illuminate\Routing\Controllers\HasMiddleware;
/** /**
* Controlador de usuarios * Controlador de usuarios
@ -22,8 +23,20 @@
* *
* @version 1.0.0 * @version 1.0.0
*/ */
class UserController extends Controller class UserController extends Controller implements HasMiddleware
{ {
/**
* Middleware
*/
public static function middleware(): array
{
return [
self::can('users.index', ['index']),
self::can('users.destroy', ['destroy']),
];
}
/** /**
* Listar * Listar
*/ */

View File

@ -12,24 +12,12 @@
use App\Models\CatalogCancellationReason; use App\Models\CatalogCancellationReason;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Notsoweb\ApiResponse\Enums\ApiResponse; use Notsoweb\ApiResponse\Enums\ApiResponse;
use Illuminate\Routing\Controllers\HasMiddleware;
/** /**
* Descripción * Descripción
*/ */
class CatalogController extends Controller implements HasMiddleware class CatalogController extends Controller
{ {
/**
* Middleware
*/
public static function middleware(): array
{
return [
self::can('catalogs.cancellation_reasons.index', ['index']),
self::can('catalogs.cancellation_reasons.show', ['show']),
self::can('catalogs.cancellation_reasons.destroy', ['destroy']),
];
}
public function index(Request $request) public function index(Request $request)
{ {

View File

@ -6,22 +6,10 @@
use App\Http\Requests\Repuve\CatalogNameImgUpdateRequest; use App\Http\Requests\Repuve\CatalogNameImgUpdateRequest;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\CatalogNameImg; use App\Models\CatalogNameImg;
use Illuminate\Routing\Controllers\HasMiddleware;
use Notsoweb\ApiResponse\Enums\ApiResponse; use Notsoweb\ApiResponse\Enums\ApiResponse;
class CatalogNameImgController extends Controller implements HasMiddleware class CatalogNameImgController extends Controller
{ {
/**
* Middleware
*/
public static function middleware(): array
{
return [
self::can('catalogs.name_img.index', ['index']),
self::can('catalogs.name_img.destroy', ['destroy']),
];
}
/** /**
* Listar * Listar
*/ */

View File

@ -29,8 +29,8 @@ class InscriptionController extends Controller implements HasMiddleware
public static function middleware(): array public static function middleware(): array
{ {
return [ return [
self::can('repuve.search_records', ['searchRecord']), self::can('inscription.search', ['searchRecord']),
self::can('repuve.check_stolen', ['stolen']), self::can('inscription.search.national', ['stolen']),
]; ];
} }

View File

@ -21,9 +21,10 @@ class RecordController extends Controller implements HasMiddleware
public static function middleware(): array public static function middleware(): array
{ {
return [ return [
self::can('records.index', ['index']), self::can('records.generate_pdf', ['generatePdf']),
self::can('records.show', ['show']), self::can('records.generate_pdf_form', ['generatePdfForm']),
self::can('records.generate_pdf', ['generatePdf', 'generatePdfVerification', 'generatePdfConstancia', 'generatePdfImages', 'generatePdfForm']), self::can('records.generate_pdf_constancia', ['generatePdfConstancia']),
self::can('records.generate_pdf_verification', ['generatePdfVerification']),
]; ];
} }

View File

@ -33,8 +33,9 @@ class UpdateController extends Controller implements HasMiddleware
public static function middleware(): array public static function middleware(): array
{ {
return [ return [
self::can('records.update', ['updateData']), self::can('updates.vehicle-data', ['vehicleUpdate']),
self::can('records.update', ['tagSubstitution']), self::can('updates.vehicle-update', ['updateData']),
self::can('updates.resend-to-repuve', ['resendToRepuve']),
]; ];
} }

View File

@ -7,7 +7,7 @@ class CatalogCancellationReasonStoreRequest extends FormRequest
public function authorize(): bool public function authorize(): bool
{ {
return auth()->user()->can('catalogs.cancellation_reasons.create'); return true;
} }
public function rules(): array public function rules(): array

View File

@ -7,7 +7,7 @@ class CatalogCancellationReasonUpdateRequest extends FormRequest
public function authorize(): bool public function authorize(): bool
{ {
return auth()->user()->can('catalogs.cancellation_reasons.edit'); return true;
} }
public function rules(): array public function rules(): array

View File

@ -1,50 +0,0 @@
<?php namespace App\Http\Requests\Repuve;
use Illuminate\Foundation\Http\FormRequest;
class RecordSearchRequest extends FormRequest
{
public function authorize(): bool
{
return auth()->user()->can('repuve.records.search');
}
public function rules(): array
{
return [
'folio' => ['nullable', 'string', 'max:50'],
'niv' => ['nullable', 'string', 'max:50'],
'numero_serie' => ['nullable', 'string', 'max:50'],
'fecha_desde' => ['nullable', 'date', 'date_format:Y-m-d'],
'fecha_hasta' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:fecha_desde'],
];
}
public function messages(): array
{
return [
'folio.string' => 'El folio debe ser una cadena de texto',
'niv.string' => 'El NIV debe ser una cadena de texto',
'numero_serie.string' => 'El número de serie debe ser una cadena de texto',
'fecha_desde.date' => 'La fecha desde debe ser una fecha válida',
'fecha_desde.date_format' => 'La fecha desde debe tener el formato Y-m-d',
'fecha_hasta.date' => 'La fecha hasta debe ser una fecha válida',
'fecha_hasta.after_or_equal' => 'La fecha hasta debe ser posterior o igual a la fecha desde',
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
if (!$this->filled('folio') &&
!$this->filled('niv') &&
!$this->filled('numero_serie') &&
!$this->filled('fecha_desde')) {
$validator->errors()->add(
'search',
'Debe proporcionar al menos un criterio de búsqueda (folio, niv o fecha_desde)'
);
}
});
}
}

View File

@ -7,7 +7,7 @@ class VehicleStoreRequest extends FormRequest
public function authorize(): bool public function authorize(): bool
{ {
return auth()->user()->can('vehicles.create'); return auth()->user()->can('inscription.vehicle');
} }
public function rules(): array public function rules(): array

View File

@ -9,7 +9,7 @@ class VehicleUpdateRequest extends FormRequest
public function authorize(): bool public function authorize(): bool
{ {
return auth()->user()->can('vehicles.edit'); return auth()->user()->can('updates.vehicle-update');
} }
public function rules(): array public function rules(): array

View File

@ -28,9 +28,8 @@ class RoleSeeder extends Seeder
*/ */
public function run(): void public function run(): void
{ {
$users = PermissionType::firstOrCreate([ // === USUARIOS ===
'name' => 'Usuarios' $users = PermissionType::firstOrCreate(['name' => 'Usuarios']);
]);
[ [
$userIndex, $userIndex,
@ -39,11 +38,8 @@ public function run(): void
$userDestroy $userDestroy
] = $this->onCRUD('users', $users, 'api'); ] = $this->onCRUD('users', $users, 'api');
$userSettings = $this->onPermission('users.settings', 'Configuración de usuarios', $users, 'api'); // === ROLES ===
$roles = PermissionType::firstOrCreate(['name' => 'Roles']);
$roles = PermissionType::firstOrCreate([
'name' => 'Roles'
]);
[ [
$roleIndex, $roleIndex,
@ -51,11 +47,11 @@ public function run(): void
$roleEdit, $roleEdit,
$roleDestroy $roleDestroy
] = $this->onCRUD('roles', $roles, 'api'); ] = $this->onCRUD('roles', $roles, 'api');
$rolePermissions = $this->onPermission('roles.permissions', 'Permisos de roles', $roles, 'api'); $rolePermissions = $this->onPermission('roles.permissions', 'Permisos de roles', $roles, 'api');
$modules = PermissionType::firstOrCreate([ // Modulos // === MÓDULOS ===
'name' => 'Módulos' $modules = PermissionType::firstOrCreate(['name' => 'Módulos']);
]);
[ [
$moduleIndex, $moduleIndex,
@ -64,16 +60,10 @@ public function run(): void
$moduleDestroy $moduleDestroy
] = $this->onCRUD('modules', $modules, 'api'); ] = $this->onCRUD('modules', $modules, 'api');
$moduleToggleStatus = $this->onPermission( $moduleToggleStatus = $this->onPermission('modules.toggle_status', 'Cambiar estado del módulo', $modules, 'api');
'modules.toggle_status',
'Cambiar estado del módulo',
$modules,
'api'
);
$devices = PermissionType::firstOrCreate([ //Dispositivos // === DISPOSITIVOS MÓVILES ===
'name' => 'Dispositivos Móviles' $devices = PermissionType::firstOrCreate(['name' => 'Dispositivos Móviles']);
]);
[ [
$deviceIndex, $deviceIndex,
@ -82,103 +72,51 @@ public function run(): void
$deviceDestroy $deviceDestroy
] = $this->onCRUD('devices', $devices, 'api'); ] = $this->onCRUD('devices', $devices, 'api');
$inscriptions = PermissionType::firstOrCreate([ // Inscripciones de vehículos $deviceToggleStatus = $this->onPermission('devices.toggle_status', 'Cambiar estado del dispositivo', $devices, 'api');
'name' => 'Proceso de Sustitución por primera vez'
]);
$inscriptionVehicle = $this->onPermission( // === INSCRIPCIONES ===
'inscription.vehicle', $inscriptions = PermissionType::firstOrCreate(['name' => 'Proceso de Sustitución por primera vez']);
'Inscribir vehículo',
$inscriptions,
'api'
);
$inscriptionSearch = $this->onPermission( $inscriptionVehicle = $this->onPermission('inscription.vehicle', 'Inscribir vehículo', $inscriptions, 'api');
'inscription.search.national', $inscriptionSearchNational = $this->onPermission('inscription.search.national', 'Buscar en consulta nacional', $inscriptions, 'api');
'Buscar en consulta nacional', $inscriptionSearch = $this->onPermission('inscription.search', 'Buscar en consulta', $inscriptions, 'api');
$inscriptions,
'api'
);
$inscriptionBusqueda = $this->onPermission( // === CANCELACIONES ===
'inscription.search', $cancellations = PermissionType::firstOrCreate(['name' => 'Cancelaciones']);
'Buscar en consulta',
$inscriptions,
'api'
);
$cancellations = PermissionType::firstOrCreate([ $cancellationTagNoAsignado = $this->onPermission('cancellations.cancel_tag_no_asignado', 'Cancelar constancia no asignada', $cancellations, 'api');
'name' => 'Cancelaciones'
]);
// === ACTUALIZAR REGISTRO ===
$updates = PermissionType::firstOrCreate(['name' => 'Actualizar Registro']);
$cancellationTagNoAsignado = $this->onPermission( $updateVehicleData = $this->onPermission('updates.vehicle-data', 'Actualizar datos de vehículo por formulario', $updates, 'api');
'cancellations.tag_no_asignado', $updateVehicleUpdate = $this->onPermission('updates.vehicle-update', 'Actualizar datos de vehículo', $updates, 'api');
'Cancelar constancia no asignada', $updateResendToRepuve = $this->onPermission('updates.resend-to-repuve', 'Reenviar a REPUVE', $updates, 'api');
$cancellations,
'api'
);
$updates = PermissionType::firstOrCreate([ // === GENERAR FORMATOS ===
'name' => 'Actualizar Registro' $formats = PermissionType::firstOrCreate(['name' => 'Generar Formatos']);
]);
$updateVehicleData = $this->onPermission( $recordGeneratePdf = $this->onPermission('records.generate_pdf', 'Generar Hoja de recepción', $formats, 'api');
'updates.vehicle-data', $recordGeneratePdfForm = $this->onPermission('records.generate_pdf_form', 'Generar solicitud de sustitución', $formats, 'api');
'Consultar datos de vehículo', $recordGeneratePdfVerification = $this->onPermission('records.generate_pdf_verification', 'Generar Hoja de verificación', $formats, 'api');
$updates, $recordGeneratePdfConstancia = $this->onPermission('records.generate_pdf_constancia', 'Generar Impresión en la constancia', $formats, 'api');
'api'
);
$updateVehicleUpdate = $this->onPermission( // === REPORTES ===
'updates.vehicle-update', $reports = PermissionType::firstOrCreate(['name' => 'Reportes - Excel']);
'Actualizar datos de vehículo',
$updates,
'api'
);
$records = PermissionType::firstOrCreate([ $reportVehicleUpdates = $this->onPermission('reports.vehicle_updates.index', 'Reporte de actualizaciones', $reports, 'api');
'name' => 'Generar Formatos' $reportSubstitutions = $this->onPermission('reports.substitutions.index', 'Reporte de sustituciones', $reports, 'api');
]); $reportCancellations = $this->onPermission('reports.cancellations.index', 'Reporte de cancelaciones', $reports, 'api');
$reportGeneral = $this->onPermission('reports.general.index', 'Reporte general', $reports, 'api');
$reportSearchRecords = $this->onPermission('reports.search_records.index', 'Reporte de consulta nacional', $reports, 'api');
$recordGeneratePdf = $this->onPermission( // === ACTIVIDAD ===
'records.generate_pdf', $activities = PermissionType::firstOrCreate(['name' => 'Actividad']);
'Generar Hoja de recepción',
$records,
'api'
);
$recordGeneratePdfVerification = $this->onPermission( $activityIndex = $this->onPermission('activities.index', 'Ver actividad de usuarios', $activities, 'api');
'records.generate_pdf_verification',
'Generar Hoja de verificación',
$records,
'api'
);
$recordGeneratePdfConstancia = $this->onPermission( // === CAJAS ===
'records.generate_pdf_constancia', $packages = PermissionType::firstOrCreate(['name' => 'Cajas']);
'Generar Impresión en la constancia',
$records,
'api'
);
$recordGeneratePdfSubtitution = $this->onPermission(
'records.generate_pdf_substitution',
'Generar Solicitud de sustitución',
$records,
'api'
);
$recordGeneratePdfDamaged = $this->onPermission(
'records.generate_pdf_damaged',
'Generar PDF constancia dañada',
$records,
'api'
);
$packages = PermissionType::firstOrCreate([
'name' => 'Cajas'
]);
[ [
$packageIndex, $packageIndex,
@ -187,9 +125,10 @@ public function run(): void
$packageDestroy $packageDestroy
] = $this->onCRUD('packages', $packages, 'api'); ] = $this->onCRUD('packages', $packages, 'api');
$tags = PermissionType::firstOrCreate([ $packageBoxTags = $this->onPermission('packages.box_tags', 'Ver constancias de caja', $packages, 'api');
'name' => 'Constancias de Inscripción'
]); // === CONSTANCIAS DE INSCRIPCIÓN ===
$tags = PermissionType::firstOrCreate(['name' => 'Constancias de Inscripción']);
[ [
$tagIndex, $tagIndex,
@ -198,125 +137,83 @@ public function run(): void
$tagDestroy, $tagDestroy,
] = $this->onCRUD('tags', $tags, 'api'); ] = $this->onCRUD('tags', $tags, 'api');
$tagAssignToModule = $this->onPermission( $tagAssignToModule = $this->onPermission('tags.assign_to_module', 'Asignar etiquetas a módulo', $tags, 'api');
'tags.assign_to_module',
'Asignar etiquetas a módulo',
$tags,
'api'
);
// =========================================================
// ROLES
// =========================================================
// Desarrollador // Desarrollador
Role::updateOrCreate([ Role::updateOrCreate([
'name' => 'developer', 'name' => 'developer',
'description' => 'Desarrollador',
'guard_name' => 'api' 'guard_name' => 'api'
])->syncPermissions(Permission::all()); ], ['description' => 'Desarrollador'])->syncPermissions(Permission::all());
// Administrador // Administrador
Role::updateOrCreate([ Role::updateOrCreate([
'name' => 'admin', 'name' => 'admin',
'description' => 'Administrador',
'guard_name' => 'api' 'guard_name' => 'api'
])->syncPermissions( ], ['description' => 'Administrador'])->syncPermissions(
$userIndex, // Usuarios
$userCreate, $userIndex, $userCreate, $userEdit, $userDestroy,
$userEdit, // Roles
$userDestroy, $roleIndex, $roleCreate, $roleEdit, $roleDestroy, $rolePermissions,
$userSettings, // Módulos
$roleIndex, $moduleIndex, $moduleCreate, $moduleEdit, $moduleDestroy, $moduleToggleStatus,
$roleCreate, // Dispositivos
$roleEdit, $deviceIndex, $deviceCreate, $deviceEdit, $deviceDestroy, $deviceToggleStatus,
$roleDestroy, // Inscripciones
$rolePermissions, $inscriptionVehicle, $inscriptionSearch, $inscriptionSearchNational,
$moduleIndex, //Módulos // Cancelaciones
$moduleCreate, $cancellationTagNoAsignado,
$moduleEdit, // Actualizaciones
$moduleDestroy, $updateVehicleData, $updateVehicleUpdate, $updateResendToRepuve,
$moduleToggleStatus, // Generar formatos
$deviceIndex, //Dispositivos $recordGeneratePdf, $recordGeneratePdfVerification, $recordGeneratePdfConstancia, $recordGeneratePdfForm,
$deviceCreate, // Reportes
$deviceEdit, $reportVehicleUpdates, $reportSubstitutions, $reportCancellations,
$deviceDestroy, $reportGeneral, $reportSearchRecords,
$inscriptionVehicle, //Inscripcion de vehículos // Cajas
$inscriptionSearch, $packageIndex, $packageCreate, $packageEdit, $packageDestroy, $packageBoxTags,
$inscriptionBusqueda, // Constancias
$cancellationTagNoAsignado, //Cancelacion de constancia no asignada $tagIndex, $tagCreate, $tagEdit, $tagDestroy,
$updateVehicleData, //Actualizaciones de vehículo
$updateVehicleUpdate,
$recordGeneratePdf, //Expedientes
$recordGeneratePdfVerification,
$recordGeneratePdfConstancia,
$recordGeneratePdfSubtitution,
$recordGeneratePdfDamaged,
$packageIndex, //Paquetes
$packageCreate,
$packageEdit,
$packageDestroy,
$tagIndex, //Etiquetas
$tagCreate,
$tagEdit,
$tagDestroy
); );
// Encargado // Encargado
Role::updateOrCreate([ Role::updateOrCreate([
'name' => 'encargado', 'name' => 'encargado',
'description' => 'Encargado',
'guard_name' => 'api' 'guard_name' => 'api'
])->syncPermissions( ], ['description' => 'Encargado'])->syncPermissions(
$userIndex, // Dispositivos
$roleIndex, $deviceIndex, $deviceCreate, $deviceEdit, $deviceDestroy, $deviceToggleStatus,
// Inscripciones
$deviceIndex, //Dispositivos $inscriptionVehicle, $inscriptionSearch, $inscriptionSearchNational,
$deviceCreate, // Cancelaciones
$deviceEdit, $cancellationTagNoAsignado,
$deviceDestroy, // Actualizaciones
$inscriptionVehicle, //Inscripcion de vehículos $updateVehicleData, $updateVehicleUpdate,
$inscriptionSearch, // Generar formatos
$updateVehicleData, //Actualizaciones de vehículo $recordGeneratePdf, $recordGeneratePdfVerification, $recordGeneratePdfConstancia, $recordGeneratePdfForm,
$updateVehicleUpdate, // Reportes
$recordGeneratePdf, //Expedientes $reportVehicleUpdates, $reportSubstitutions, $reportCancellations,
$recordGeneratePdfVerification, $reportGeneral, $reportSearchRecords,
$recordGeneratePdfConstancia, // Cajas
$recordGeneratePdfSubtitution, $packageIndex, $packageCreate, $packageEdit, $packageDestroy, $packageBoxTags,
$recordGeneratePdfDamaged, // Constancias
$packageIndex, //Paquetes $tagIndex, $tagCreate, $tagEdit, $tagDestroy, $tagAssignToModule,
$packageCreate,
$packageEdit,
$packageDestroy,
$tagIndex, //Etiquetas
$tagCreate,
$tagEdit,
$tagDestroy,
$tagAssignToModule
);
// Capturista
Role::updateOrCreate([
'name' => 'capturista',
'description' => 'Capturista',
'guard_name' => 'api'
])->syncPermissions(
$userIndex,
$inscriptionVehicle, //Inscripcion de vehículos
$inscriptionSearch,
$updateVehicleData, //Actualizaciones de vehículo
$updateVehicleUpdate,
); );
// Perito // Perito
Role::updateOrCreate([ Role::updateOrCreate([
'name' => 'perito', 'name' => 'perito',
'description' => 'Perito',
'guard_name' => 'api' 'guard_name' => 'api'
])->syncPermissions( ], ['description' => 'Perito'])->syncPermissions(
$userIndex, // Generar formatos
$inscriptionVehicle, //Inscripcion de vehículos $recordGeneratePdf, $recordGeneratePdfVerification, $recordGeneratePdfConstancia, $recordGeneratePdfForm,
$inscriptionSearch, // Cajas
$updateVehicleData, //Actualizaciones de vehículo $packageIndex, $packageBoxTags,
$updateVehicleUpdate, // Constancias
$tagIndex,
); );
} }
} }

View File

@ -34,6 +34,7 @@ RUN chown -R www-data:www-data /var/www/repuve-backend-v1/storage /var/www/repuv
RUN chmod -R 775 /var/www/repuve-backend-v1/storage /var/www/repuve-backend-v1/bootstrap/cache RUN chmod -R 775 /var/www/repuve-backend-v1/storage /var/www/repuve-backend-v1/bootstrap/cache
EXPOSE 9000 EXPOSE 9000
EXPOSE 3306
ENTRYPOINT ["/usr/local/bin/entrypoint-dev.sh"] ENTRYPOINT ["/usr/local/bin/entrypoint-dev.sh"]
CMD ["php-fpm"] CMD ["php-fpm"]