diff --git a/BD/Segundo Cuatrimestre/roles y permisos.docx b/BD/Segundo Cuatrimestre/roles y permisos.docx
new file mode 100644
index 0000000..65ad505
Binary files /dev/null and b/BD/Segundo Cuatrimestre/roles y permisos.docx differ
diff --git a/BD/taller_bd_ base de datos completa.sql b/BD/taller_bd_ base de datos completa.sql
new file mode 100644
index 0000000..763d050
--- /dev/null
+++ b/BD/taller_bd_ base de datos completa.sql
@@ -0,0 +1,477 @@
+-- phpMyAdmin SQL Dump
+-- version 5.2.1
+-- https://www.phpmyadmin.net/
+--
+-- Servidor: 127.0.0.1:3306
+-- Tiempo de generación: 15-10-2026 a las 11:48:19
+-- Versión del servidor: 9.1.0
+-- Versión de PHP: 8.2.26
+
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+START TRANSACTION;
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+--
+-- Base de datos: `taller_bd`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `categorias`
+--
+
+DROP TABLE IF EXISTS `categorias`;
+CREATE TABLE IF NOT EXISTS `categorias` (
+ `id_categoria` int NOT NULL AUTO_INCREMENT,
+ `nombre` varchar(255) DEFAULT NULL,
+ `descripcion` varchar(255) DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ `deleted_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id_categoria`)
+) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+--
+-- Volcado de datos para la tabla `categorias`
+--
+
+INSERT INTO `categorias` (`id_categoria`, `nombre`, `descripcion`, `created_at`, `updated_at`, `deleted_at`) VALUES
+(3, 'Vehiculos Y Mas', 'categoria numero 3', NULL, '2026-08-31 22:30:43', NULL),
+(4, 'Tecnología E Informatica', 'Productos y servicios Tecnologicos', NULL, '2026-08-30 23:30:07', NULL),
+(5, 'Educación Y Trabajo', 'Cursos, capacitaciones y formación', NULL, '2026-08-31 14:58:27', NULL),
+(6, 'Salud', 'Servicios médicos y bienestar', NULL, '2026-08-31 15:10:17', NULL),
+(7, 'Deportes', 'Actividades deportivas y recreativas', NULL, NULL, NULL),
+(8, 'Alimentos', 'Productos alimenticios', NULL, NULL, NULL),
+(9, 'Transporte', 'Servicios de movilidad y logística', NULL, NULL, NULL),
+(10, 'Turismo', 'Viajes, hospedaje y excursiones', NULL, NULL, NULL),
+(11, 'Finanzas', 'Servicios financieros y bancarios', NULL, NULL, NULL),
+(12, 'Entretenimiento', 'Cine, música y ocio', NULL, NULL, NULL),
+(13, 'Hogar', 'Productos y servicios para el hogar', NULL, NULL, NULL),
+(15, 'CRISTIANO', 'Pedido mes de febrero', NULL, NULL, NULL),
+(16, 'asdasd', 'sdfsawdq', NULL, NULL, NULL),
+(17, 'vehiculos', 'descripc vehiculos', '2026-05-26 22:46:28', '2026-06-02 16:08:41', NULL),
+(18, '12sdkjasj', '121jgsj', '2026-06-02 16:12:47', '2026-06-02 16:12:47', NULL),
+(19, 'kndwbyucgds', 'jldwhoichwsda', '2026-06-08 22:48:37', '2026-06-08 22:48:37', NULL),
+(20, 'ksijdsjf', 'jnaduiah', '2026-06-09 22:35:03', '2026-06-09 22:35:03', NULL),
+(21, NULL, NULL, '2026-06-09 22:36:01', '2026-06-09 22:36:01', NULL),
+(22, 'njadhcafiud', 'iohoiwhsed', '2026-06-09 23:00:07', '2026-06-09 23:00:07', NULL);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `codigo_barras`
+--
+
+DROP TABLE IF EXISTS `codigo_barras`;
+CREATE TABLE IF NOT EXISTS `codigo_barras` (
+ `id_codigo_barras` int NOT NULL AUTO_INCREMENT,
+ `codigo` varchar(45) DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `deleted_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id_codigo_barras`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+--
+-- Volcado de datos para la tabla `codigo_barras`
+--
+
+INSERT INTO `codigo_barras` (`id_codigo_barras`, `codigo`, `created_at`, `deleted_at`, `updated_at`) VALUES
+(1, '12345', NULL, NULL, NULL),
+(2, '98765', NULL, NULL, NULL),
+(3, '3', NULL, NULL, '2026-10-12 13:27:44'),
+(4, '80987374', '2026-09-29 23:29:03', NULL, '2026-09-29 23:29:03'),
+(5, '879627263', '2026-09-29 23:30:07', NULL, '2026-09-29 23:30:07'),
+(6, '843984', '2026-10-04 17:39:08', NULL, '2026-10-04 17:39:08'),
+(7, '843984', '2026-10-04 17:39:59', NULL, '2026-10-04 17:39:59'),
+(8, '2342343', '2026-10-04 17:40:46', NULL, '2026-10-04 17:40:46'),
+(9, '453453', '2026-10-04 20:20:43', NULL, '2026-10-04 20:20:43'),
+(10, '122324', '2026-10-06 22:24:23', NULL, '2026-10-06 22:24:23');
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `etiquetas`
+--
+
+DROP TABLE IF EXISTS `etiquetas`;
+CREATE TABLE IF NOT EXISTS `etiquetas` (
+ `id_etiqueta` int NOT NULL AUTO_INCREMENT,
+ `nombre` varchar(250) DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ `deleted_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id_etiqueta`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+--
+-- Volcado de datos para la tabla `etiquetas`
+--
+
+INSERT INTO `etiquetas` (`id_etiqueta`, `nombre`, `created_at`, `updated_at`, `deleted_at`) VALUES
+(1, 'Nuevo', NULL, NULL, NULL),
+(2, 'Liquidacion', NULL, NULL, NULL),
+(3, 'Oferta', NULL, NULL, NULL);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `failed_jobs`
+--
+
+DROP TABLE IF EXISTS `failed_jobs`;
+CREATE TABLE IF NOT EXISTS `failed_jobs` (
+ `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
+ `uuid` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `connection` text COLLATE utf8mb4_unicode_ci NOT NULL,
+ `queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
+ `payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
+ `exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
+ `failed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `migrations`
+--
+
+DROP TABLE IF EXISTS `migrations`;
+CREATE TABLE IF NOT EXISTS `migrations` (
+ `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
+ `migration` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `batch` int NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Volcado de datos para la tabla `migrations`
+--
+
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES
+(1, '2014_10_12_000000_create_users_table', 1),
+(2, '2014_10_12_100000_create_password_reset_tokens_table', 1),
+(3, '2014_10_12_100000_create_password_resets_table', 1),
+(4, '2019_08_19_000000_create_failed_jobs_table', 1),
+(5, '2019_12_14_000001_create_personal_access_tokens_table', 1),
+(6, '2026_10_12_114151_create_permission_tables', 2);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `model_has_permissions`
+--
+
+DROP TABLE IF EXISTS `model_has_permissions`;
+CREATE TABLE IF NOT EXISTS `model_has_permissions` (
+ `permission_id` bigint UNSIGNED NOT NULL,
+ `model_type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `model_id` bigint UNSIGNED NOT NULL,
+ PRIMARY KEY (`permission_id`,`model_id`,`model_type`),
+ KEY `model_has_permissions_model_id_model_type_index` (`model_id`,`model_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `model_has_roles`
+--
+
+DROP TABLE IF EXISTS `model_has_roles`;
+CREATE TABLE IF NOT EXISTS `model_has_roles` (
+ `role_id` bigint UNSIGNED NOT NULL,
+ `model_type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `model_id` bigint UNSIGNED NOT NULL,
+ PRIMARY KEY (`role_id`,`model_id`,`model_type`),
+ KEY `model_has_roles_model_id_model_type_index` (`model_id`,`model_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Volcado de datos para la tabla `model_has_roles`
+--
+
+INSERT INTO `model_has_roles` (`role_id`, `model_type`, `model_id`) VALUES
+(5, 'App\\Models\\User', 1),
+(6, 'App\\Models\\User', 2),
+(7, 'App\\Models\\User', 3);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `password_resets`
+--
+
+DROP TABLE IF EXISTS `password_resets`;
+CREATE TABLE IF NOT EXISTS `password_resets` (
+ `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `token` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ KEY `password_resets_email_index` (`email`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `password_reset_tokens`
+--
+
+DROP TABLE IF EXISTS `password_reset_tokens`;
+CREATE TABLE IF NOT EXISTS `password_reset_tokens` (
+ `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `token` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`email`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `permissions`
+--
+
+DROP TABLE IF EXISTS `permissions`;
+CREATE TABLE IF NOT EXISTS `permissions` (
+ `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `guard_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `permissions_name_guard_name_unique` (`name`,`guard_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Volcado de datos para la tabla `permissions`
+--
+
+INSERT INTO `permissions` (`id`, `name`, `guard_name`, `created_at`, `updated_at`) VALUES
+(8, 'permisos.abm', 'web', '2026-10-13 22:18:17', '2026-10-13 22:18:17'),
+(9, 'usuarios.abm', 'web', '2026-10-13 22:18:24', '2026-10-13 22:18:24'),
+(10, 'roles.abm', 'web', '2026-10-13 22:18:42', '2026-10-13 22:18:42'),
+(11, 'productos.crear', 'web', '2026-10-13 22:27:57', '2026-10-13 22:27:57'),
+(12, 'productos.ver', 'web', '2026-10-13 22:28:04', '2026-10-13 22:28:04'),
+(13, 'productos.editar', 'web', '2026-10-13 22:28:13', '2026-10-13 22:28:13'),
+(14, 'productos.borrar', 'web', '2026-10-13 22:28:23', '2026-10-13 22:28:23');
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `personal_access_tokens`
+--
+
+DROP TABLE IF EXISTS `personal_access_tokens`;
+CREATE TABLE IF NOT EXISTS `personal_access_tokens` (
+ `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
+ `tokenable_type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `tokenable_id` bigint UNSIGNED NOT NULL,
+ `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `token` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `abilities` text COLLATE utf8mb4_unicode_ci,
+ `last_used_at` timestamp NULL DEFAULT NULL,
+ `expires_at` timestamp NULL DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `personal_access_tokens_token_unique` (`token`),
+ KEY `personal_access_tokens_tokenable_type_tokenable_id_index` (`tokenable_type`,`tokenable_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `productos`
+--
+
+DROP TABLE IF EXISTS `productos`;
+CREATE TABLE IF NOT EXISTS `productos` (
+ `id_producto` int NOT NULL AUTO_INCREMENT,
+ `nombre` varchar(250) DEFAULT NULL,
+ `descripcion` text,
+ `precio` decimal(10,2) DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ `deleted_at` timestamp NULL DEFAULT NULL,
+ `categoria_id` int DEFAULT NULL,
+ `codigo_barras_id` int DEFAULT NULL,
+ PRIMARY KEY (`id_producto`),
+ KEY `fk_productos_categorias_idx` (`categoria_id`),
+ KEY `fk_productos_codigo_barras1_idx` (`codigo_barras_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+--
+-- Volcado de datos para la tabla `productos`
+--
+
+INSERT INTO `productos` (`id_producto`, `nombre`, `descripcion`, `precio`, `created_at`, `updated_at`, `deleted_at`, `categoria_id`, `codigo_barras_id`) VALUES
+(1, 'Iphone 17', 'descripcion del iphone', 1500000.00, NULL, '2026-10-12 13:29:20', '2026-10-12 13:29:20', 4, 1),
+(2, 'samsung a51', 'descripcion del samsung', 600000.00, NULL, '2026-10-13 22:41:28', '2026-10-13 22:41:28', 4, 2),
+(3, 'hjasyucags', 'kosnadiocsa', 625352.00, '2026-09-29 23:00:42', '2026-09-29 23:00:42', NULL, 6, 3),
+(4, 'kjhiuh', 'io89', 675545.00, '2026-09-29 23:30:07', '2026-10-12 13:29:14', '2026-10-12 13:29:14', 8, 5),
+(5, 'televisor 25', 'pojdpoaks', 213121.00, '2026-10-04 17:39:08', '2026-10-04 17:39:08', NULL, 4, 6),
+(6, 'televisor 25', 'pojdpoaks', 213121.00, '2026-10-04 17:40:00', '2026-10-04 17:40:00', NULL, 4, 7),
+(7, 'asdahiuh', 'uiahsiuda', 13212321.00, '2026-10-04 17:40:46', '2026-10-04 17:40:46', NULL, 4, 8),
+(8, 'ewffwef', 'dssd', 32132.00, '2026-10-04 20:20:43', '2026-10-04 20:20:43', NULL, 8, 9),
+(9, 'tv 24', 'JHIUGH', 67575.00, '2026-10-06 22:24:23', '2026-10-06 22:24:23', NULL, 4, 10);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `productos_etiquetas`
+--
+
+DROP TABLE IF EXISTS `productos_etiquetas`;
+CREATE TABLE IF NOT EXISTS `productos_etiquetas` (
+ `producto_id` int NOT NULL,
+ `etiqueta_id` int NOT NULL,
+ PRIMARY KEY (`producto_id`,`etiqueta_id`),
+ KEY `fk_productos_has_etiquetas_etiquetas1_idx` (`etiqueta_id`),
+ KEY `fk_productos_has_etiquetas_productos1_idx` (`producto_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+--
+-- Volcado de datos para la tabla `productos_etiquetas`
+--
+
+INSERT INTO `productos_etiquetas` (`producto_id`, `etiqueta_id`) VALUES
+(3, 1),
+(9, 1),
+(3, 3),
+(9, 3);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `roles`
+--
+
+DROP TABLE IF EXISTS `roles`;
+CREATE TABLE IF NOT EXISTS `roles` (
+ `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `guard_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `roles_name_guard_name_unique` (`name`,`guard_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Volcado de datos para la tabla `roles`
+--
+
+INSERT INTO `roles` (`id`, `name`, `guard_name`, `created_at`, `updated_at`) VALUES
+(5, 'administrador', 'web', '2026-10-13 22:19:38', '2026-10-13 22:19:38'),
+(6, 'supervisor', 'web', '2026-10-13 22:29:41', '2026-10-13 22:29:41'),
+(7, 'vendedor', 'web', '2026-10-13 22:30:04', '2026-10-13 22:30:04');
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `role_has_permissions`
+--
+
+DROP TABLE IF EXISTS `role_has_permissions`;
+CREATE TABLE IF NOT EXISTS `role_has_permissions` (
+ `permission_id` bigint UNSIGNED NOT NULL,
+ `role_id` bigint UNSIGNED NOT NULL,
+ PRIMARY KEY (`permission_id`,`role_id`),
+ KEY `role_has_permissions_role_id_foreign` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Volcado de datos para la tabla `role_has_permissions`
+--
+
+INSERT INTO `role_has_permissions` (`permission_id`, `role_id`) VALUES
+(8, 5),
+(9, 5),
+(10, 5),
+(11, 5),
+(12, 5),
+(13, 5),
+(14, 5),
+(11, 6),
+(12, 6),
+(13, 6),
+(12, 7);
+
+-- --------------------------------------------------------
+
+--
+-- Estructura de tabla para la tabla `users`
+--
+
+DROP TABLE IF EXISTS `users`;
+CREATE TABLE IF NOT EXISTS `users` (
+ `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `email_verified_at` timestamp NULL DEFAULT NULL,
+ `password` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `users_email_unique` (`email`)
+) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Volcado de datos para la tabla `users`
+--
+
+INSERT INTO `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`) VALUES
+(1, 'administrador', 'admin@admin.com', NULL, '$2y$12$dEXwqJGEupdCtcODIE2l1ugLHKN84/lpUg63ldd/weX9MgBfFmTc2', NULL, '2026-08-18 23:28:07', '2026-10-13 22:30:27'),
+(2, 'supervisor', 'supervisor@supervisor.com', NULL, '$2y$12$dEXwqJGEupdCtcODIE2l1ugLHKN84/lpUg63ldd/weX9MgBfFmTc2', NULL, '2026-08-24 14:13:07', '2026-10-13 22:30:49'),
+(3, 'vendedor', 'vendedor@vendedor.com', NULL, '$2y$12$wMALozxvqw2ueyRmaCFtzevx05XSaRIo9Vdv7YMSzLhfLFLA1lJT6', NULL, '2026-08-29 21:57:06', '2026-10-13 22:31:06'),
+(4, 'esteban ibañez', 'esteban@esteban.com', NULL, '$2y$12$tFicGd7fm/vwenynM.A/fOSfoM9kZ7VZghQTJga4irCeoqIhYVk/m', NULL, '2026-10-12 14:00:10', '2026-10-12 14:00:10');
+
+--
+-- Restricciones para tablas volcadas
+--
+
+--
+-- Filtros para la tabla `model_has_permissions`
+--
+ALTER TABLE `model_has_permissions`
+ ADD CONSTRAINT `model_has_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE;
+
+--
+-- Filtros para la tabla `model_has_roles`
+--
+ALTER TABLE `model_has_roles`
+ ADD CONSTRAINT `model_has_roles_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE;
+
+--
+-- Filtros para la tabla `productos`
+--
+ALTER TABLE `productos`
+ ADD CONSTRAINT `fk_productos_categorias` FOREIGN KEY (`categoria_id`) REFERENCES `categorias` (`id_categoria`),
+ ADD CONSTRAINT `fk_productos_codigo_barras1` FOREIGN KEY (`codigo_barras_id`) REFERENCES `codigo_barras` (`id_codigo_barras`);
+
+--
+-- Filtros para la tabla `productos_etiquetas`
+--
+ALTER TABLE `productos_etiquetas`
+ ADD CONSTRAINT `fk_productos_has_etiquetas_etiquetas1` FOREIGN KEY (`etiqueta_id`) REFERENCES `etiquetas` (`id_etiqueta`),
+ ADD CONSTRAINT `fk_productos_has_etiquetas_productos1` FOREIGN KEY (`producto_id`) REFERENCES `productos` (`id_producto`);
+
+--
+-- Filtros para la tabla `role_has_permissions`
+--
+ALTER TABLE `role_has_permissions`
+ ADD CONSTRAINT `role_has_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE,
+ ADD CONSTRAINT `role_has_permissions_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE;
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/app/Http/Controllers/PermisoController.php b/app/Http/Controllers/PermisoController.php
new file mode 100644
index 0000000..c701ace
--- /dev/null
+++ b/app/Http/Controllers/PermisoController.php
@@ -0,0 +1,92 @@
+validate([
+ 'name' => [
+ 'required',
+ 'string',
+ 'max:100',
+ Rule::unique('permissions', 'name')
+ ->where('guard_name', 'web'),
+ ],
+ ]);
+
+ $permiso = new Permission();
+
+ $permiso->name = $datos['name'];
+ $permiso->guard_name = 'web';
+
+ $permiso->save();
+
+ return redirect()->route('permisos.index')
+ ->with('mensaje-success', 'Permiso creado correctamente');
+ }
+
+ public function show($id)
+ {
+ $permiso = Permission::findOrFail($id);
+
+ return view('permisos.show', compact('permiso'));
+ }
+
+ public function edit($id)
+ {
+ $permiso = Permission::findOrFail($id);
+
+ return view('permisos.edit', compact('permiso'));
+ }
+
+ public function update(Request $request, $id)
+ {
+ $permiso = Permission::findOrFail($id);
+
+ $datos = $request->validate([
+ 'name' => [
+ 'required',
+ 'string',
+ 'max:100',
+ Rule::unique('permissions', 'name')
+ ->where('guard_name', $permiso->guard_name)
+ ->ignore($permiso->id),
+ ],
+ ]);
+
+ $permiso->name = $datos['name'];
+ $permiso->save();
+
+ return redirect()->route('permisos.index')
+ ->with('mensaje-success', 'Permiso actualizado correctamente');
+ }
+
+ public function destroy($id)
+ {
+ $permiso = Permission::findOrFail($id);
+
+ $permiso->delete();
+
+ return redirect()->route('permisos.index')
+ ->with('mensaje-success', 'Permiso eliminado correctamente');
+ }
+}
diff --git a/app/Http/Controllers/ProductoController.php b/app/Http/Controllers/ProductoController.php
index 3c293bf..e405fcd 100644
--- a/app/Http/Controllers/ProductoController.php
+++ b/app/Http/Controllers/ProductoController.php
@@ -9,6 +9,22 @@ use App\Models\CodigoBarras;
use App\Models\Etiquetas;
class ProductoController extends Controller
{
+
+ public function __construct()
+ {
+
+ $this->middleware('can:productos.ver')
+ ->only(['index', 'show']);
+
+ $this->middleware('can:productos.crear')
+ ->only(['create', 'store']);
+
+ $this->middleware('can:productos.editar')
+ ->only(['edit', 'update']);
+
+ $this->middleware('can:productos.borrar')
+ ->only(['destroy']);
+ }
public function index(Request $request){
$productos = Producto::with('categorias','codigo_barras','etiquetas')->get();
return view('productos.index', ["productos"=>$productos]);
diff --git a/app/Http/Controllers/RolController.php b/app/Http/Controllers/RolController.php
new file mode 100644
index 0000000..5b73acb
--- /dev/null
+++ b/app/Http/Controllers/RolController.php
@@ -0,0 +1,126 @@
+get();
+
+ return view('roles.index', compact('roles'));
+ }
+
+ public function create()
+ {
+ $permisos = Permission::where('guard_name', 'web')->get();
+ $usuarios = User::all();
+
+ return view('roles.create', compact('permisos', 'usuarios'));
+ }
+
+ public function store(Request $request)
+ {
+ $datos = $request->validate([
+ 'name' => 'required|string|max:100|unique:roles,name',
+ 'permisos' => 'nullable|array',
+ 'permisos.*' => 'exists:permissions,id',
+ 'usuarios' => 'nullable|array',
+ 'usuarios.*' => 'exists:users,id',
+ ]);
+
+ $rol = new Rol();
+ $rol->name = $datos['name'];
+ $rol->guard_name = 'web';
+ $rol->save();
+
+ // Relación muchos a muchos: Rol - Permisos
+ $rol->permissions()->sync($request->input('permisos', []));
+
+ // Relación muchos a muchos: Rol - Usuarios
+ $rol->usuarios()->sync($request->input('usuarios', []));
+
+ // Limpiar caché de permisos de Spatie
+ app(PermissionRegistrar::class)->forgetCachedPermissions();
+
+ return redirect()->route('roles.index')
+ ->with('mensaje-success', 'Rol creado correctamente');
+ }
+
+ public function show($id)
+ {
+ $rol = Rol::with(['permissions', 'usuarios'])->findOrFail($id);
+
+ return view('roles.show', compact('rol'));
+ }
+
+ public function edit($id)
+ {
+ $rol = Rol::with(['permissions', 'usuarios'])->findOrFail($id);
+
+ $permisos = Permission::where('guard_name', 'web')->get();
+ $usuarios = User::all();
+
+ $permisosSeleccionados = $rol->permissions->pluck('id')->toArray();
+ $usuariosSeleccionados = $rol->usuarios->pluck('id')->toArray();
+
+ return view('roles.edit', compact(
+ 'rol',
+ 'permisos',
+ 'usuarios',
+ 'permisosSeleccionados',
+ 'usuariosSeleccionados'
+ ));
+ }
+
+ public function update(Request $request, $id)
+ {
+ $rol = Rol::findOrFail($id);
+
+ $datos = $request->validate([
+ 'name' => [
+ 'required',
+ 'string',
+ 'max:100',
+ Rule::unique('roles', 'name')->ignore($rol->id),
+ ],
+ 'permisos' => 'nullable|array',
+ 'permisos.*' => 'exists:permissions,id',
+ 'usuarios' => 'nullable|array',
+ 'usuarios.*' => 'exists:users,id',
+ ]);
+
+ $rol->name = $datos['name'];
+ $rol->save();
+
+ // Actualizar permisos del rol
+ $rol->permissions()->sync($request->input('permisos', []));
+
+ // Actualizar usuarios del rol
+ $rol->usuarios()->sync($request->input('usuarios', []));
+
+ // Limpiar caché de permisos de Spatie
+ app(PermissionRegistrar::class)->forgetCachedPermissions();
+
+ return redirect()->route('roles.index')
+ ->with('mensaje-success', 'Rol actualizado correctamente');
+ }
+
+ public function destroy($id)
+ {
+ $rol = Rol::findOrFail($id);
+
+ $rol->delete();
+
+ return redirect()->route('roles.index')
+ ->with('mensaje-success', 'Rol eliminado correctamente');
+ }
+}
diff --git a/app/Http/Controllers/UsuarioController.php b/app/Http/Controllers/UsuarioController.php
index 46c5367..a0953ac 100644
--- a/app/Http/Controllers/UsuarioController.php
+++ b/app/Http/Controllers/UsuarioController.php
@@ -8,10 +8,6 @@ use Illuminate\Validation\Rule;
class UsuarioController extends Controller
{
- public function __construct()
- {
- $this->middleware('auth');
- }
public function index()
{
diff --git a/app/Models/Rol.php b/app/Models/Rol.php
new file mode 100644
index 0000000..0e5331b
--- /dev/null
+++ b/app/Models/Rol.php
@@ -0,0 +1,20 @@
+belongsToMany(
+ User::class,
+ 'model_has_roles',
+ 'role_id',
+ 'model_id'
+ )->wherePivot('model_type', User::class)
+ ->withPivotValue('model_type', User::class);
+ }
+}
\ No newline at end of file
diff --git a/app/Models/User.php b/app/Models/User.php
index 4d7f70f..c524c88 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -7,10 +7,10 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
-
+use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
- use HasApiTokens, HasFactory, Notifiable;
+ use HasApiTokens, HasFactory, Notifiable, HasRoles;
/**
* The attributes that are mass assignable.
diff --git a/composer.json b/composer.json
index 9e6d206..a7cffff 100644
--- a/composer.json
+++ b/composer.json
@@ -10,7 +10,8 @@
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8",
- "laravel/ui": "^4.6"
+ "laravel/ui": "^4.6",
+ "spatie/laravel-permission": "^6.0"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
diff --git a/composer.lock b/composer.lock
index b55f75f..229ba60 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "dcbbd52cf3c38d0f1b88e12d39e47db7",
+ "content-hash": "a569095a642b59b2017ec78897f97d5a",
"packages": [
{
"name": "brick/math",
@@ -3227,6 +3227,90 @@
},
"time": "2025-12-14T04:43:48+00:00"
},
+ {
+ "name": "spatie/laravel-permission",
+ "version": "6.25.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/spatie/laravel-permission.git",
+ "reference": "d7d4cb0d58616722f1afc90e0484e4825155b9b3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/d7d4cb0d58616722f1afc90e0484e4825155b9b3",
+ "reference": "d7d4cb0d58616722f1afc90e0484e4825155b9b3",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0",
+ "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0",
+ "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0",
+ "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0",
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "laravel/passport": "^11.0|^12.0|^13.0",
+ "laravel/pint": "^1.0",
+ "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0|^11.0",
+ "pestphp/pest": "^2.0|^3.0|^4.0",
+ "pestphp/pest-plugin-laravel": "^2.0|^3.0|^4.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Spatie\\Permission\\PermissionServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "6.x-dev",
+ "dev-master": "6.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Spatie\\Permission\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Freek Van der Herten",
+ "email": "freek@spatie.be",
+ "homepage": "https://spatie.be",
+ "role": "Developer"
+ }
+ ],
+ "description": "Permission handling for Laravel 8.0 and up",
+ "homepage": "https://github.com/spatie/laravel-permission",
+ "keywords": [
+ "acl",
+ "laravel",
+ "permission",
+ "permissions",
+ "rbac",
+ "roles",
+ "security",
+ "spatie"
+ ],
+ "support": {
+ "issues": "https://github.com/spatie/laravel-permission/issues",
+ "source": "https://github.com/spatie/laravel-permission/tree/6.25.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/spatie",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-17T22:46:46+00:00"
+ },
{
"name": "symfony/console",
"version": "v6.4.36",
diff --git a/config/permission.php b/config/permission.php
new file mode 100644
index 0000000..85b8832
--- /dev/null
+++ b/config/permission.php
@@ -0,0 +1,206 @@
+ [
+
+ /*
+ * When using the "HasPermissions" trait from this package, we need to know which
+ * Eloquent model should be used to retrieve your permissions. Of course, it
+ * is often just the "Permission" model but you may use whatever you like.
+ *
+ * The model you want to use as a Permission model needs to implement the
+ * `Spatie\Permission\Contracts\Permission` contract.
+ */
+
+ 'permission' => Permission::class,
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * Eloquent model should be used to retrieve your roles. Of course, it
+ * is often just the "Role" model but you may use whatever you like.
+ *
+ * The model you want to use as a Role model needs to implement the
+ * `Spatie\Permission\Contracts\Role` contract.
+ */
+
+ 'role' => Role::class,
+
+ ],
+
+ 'table_names' => [
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * table should be used to retrieve your roles. We have chosen a basic
+ * default value but you may easily change it to any table you like.
+ */
+
+ 'roles' => 'roles',
+
+ /*
+ * When using the "HasPermissions" trait from this package, we need to know which
+ * table should be used to retrieve your permissions. We have chosen a basic
+ * default value but you may easily change it to any table you like.
+ */
+
+ 'permissions' => 'permissions',
+
+ /*
+ * When using the "HasPermissions" trait from this package, we need to know which
+ * table should be used to retrieve your models permissions. We have chosen a
+ * basic default value but you may easily change it to any table you like.
+ */
+
+ 'model_has_permissions' => 'model_has_permissions',
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * table should be used to retrieve your models roles. We have chosen a
+ * basic default value but you may easily change it to any table you like.
+ */
+
+ 'model_has_roles' => 'model_has_roles',
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * table should be used to retrieve your roles permissions. We have chosen a
+ * basic default value but you may easily change it to any table you like.
+ */
+
+ 'role_has_permissions' => 'role_has_permissions',
+ ],
+
+ 'column_names' => [
+ /*
+ * Change this if you want to name the related pivots other than defaults
+ */
+ 'role_pivot_key' => null, // default 'role_id',
+ 'permission_pivot_key' => null, // default 'permission_id',
+
+ /*
+ * Change this if you want to name the related model primary key other than
+ * `model_id`.
+ *
+ * For example, this would be nice if your primary keys are all UUIDs. In
+ * that case, name this `model_uuid`.
+ */
+
+ 'model_morph_key' => 'model_id',
+
+ /*
+ * Change this if you want to use the teams feature and your related model's
+ * foreign key is other than `team_id`.
+ */
+
+ 'team_foreign_key' => 'team_id',
+ ],
+
+ /*
+ * When set to true, the method for checking permissions will be registered on the gate.
+ * Set this to false if you want to implement custom logic for checking permissions.
+ */
+
+ 'register_permission_check_method' => true,
+
+ /*
+ * When set to true, Laravel\Octane\Events\OperationTerminated event listener will be registered
+ * this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated
+ * NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it.
+ */
+ 'register_octane_reset_listener' => false,
+
+ /*
+ * Events will fire when a role or permission is assigned/unassigned:
+ * \Spatie\Permission\Events\RoleAttached
+ * \Spatie\Permission\Events\RoleDetached
+ * \Spatie\Permission\Events\PermissionAttached
+ * \Spatie\Permission\Events\PermissionDetached
+ *
+ * To enable, set to true, and then create listeners to watch these events.
+ */
+ 'events_enabled' => false,
+
+ /*
+ * Teams Feature.
+ * When set to true the package implements teams using the 'team_foreign_key'.
+ * If you want the migrations to register the 'team_foreign_key', you must
+ * set this to true before doing the migration.
+ * If you already did the migration then you must make a new migration to also
+ * add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions'
+ * (view the latest version of this package's migration file)
+ */
+
+ 'teams' => false,
+
+ /*
+ * The class to use to resolve the permissions team id
+ */
+ 'team_resolver' => DefaultTeamResolver::class,
+
+ /*
+ * Passport Client Credentials Grant
+ * When set to true the package will use Passports Client to check permissions
+ */
+
+ 'use_passport_client_credentials' => false,
+
+ /*
+ * When set to true, the required permission names are added to exception messages.
+ * This could be considered an information leak in some contexts, so the default
+ * setting is false here for optimum safety.
+ */
+
+ 'display_permission_in_exception' => false,
+
+ /*
+ * When set to true, the required role names are added to exception messages.
+ * This could be considered an information leak in some contexts, so the default
+ * setting is false here for optimum safety.
+ */
+
+ 'display_role_in_exception' => false,
+
+ /*
+ * By default wildcard permission lookups are disabled.
+ * See documentation to understand supported syntax.
+ */
+
+ 'enable_wildcard_permission' => false,
+
+ /*
+ * The class to use for interpreting wildcard permissions.
+ * If you need to modify delimiters, override the class and specify its name here.
+ */
+ // 'wildcard_permission' => Spatie\Permission\WildcardPermission::class,
+
+ /* Cache-specific settings */
+
+ 'cache' => [
+
+ /*
+ * By default all permissions are cached for 24 hours to speed up performance.
+ * When permissions or roles are updated the cache is flushed automatically.
+ */
+
+ 'expiration_time' => DateInterval::createFromDateString('24 hours'),
+
+ /*
+ * The cache key used to store all permissions.
+ */
+
+ 'key' => 'spatie.permission.cache',
+
+ /*
+ * You may optionally indicate a specific cache driver to use for permission and
+ * role caching using any of the `store` drivers listed in the cache.php config
+ * file. Using 'default' here means to use the `default` set in cache.php.
+ */
+
+ 'store' => 'default',
+ ],
+];
diff --git a/database/migrations/2026_10_12_114151_create_permission_tables.php b/database/migrations/2026_10_12_114151_create_permission_tables.php
new file mode 100644
index 0000000..66ce1f9
--- /dev/null
+++ b/database/migrations/2026_10_12_114151_create_permission_tables.php
@@ -0,0 +1,134 @@
+engine('InnoDB');
+ $table->bigIncrements('id'); // permission id
+ $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
+ $table->string('guard_name'); // For MyISAM use string('guard_name', 25);
+ $table->timestamps();
+
+ $table->unique(['name', 'guard_name']);
+ });
+
+ Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) {
+ // $table->engine('InnoDB');
+ $table->bigIncrements('id'); // role id
+ if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
+ $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
+ $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
+ }
+ $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
+ $table->string('guard_name'); // For MyISAM use string('guard_name', 25);
+ $table->timestamps();
+ if ($teams || config('permission.testing')) {
+ $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
+ } else {
+ $table->unique(['name', 'guard_name']);
+ }
+ });
+
+ Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
+ $table->unsignedBigInteger($pivotPermission);
+
+ $table->string('model_type');
+ $table->unsignedBigInteger($columnNames['model_morph_key']);
+ $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
+
+ $table->foreign($pivotPermission)
+ ->references('id') // permission id
+ ->on($tableNames['permissions'])
+ ->onDelete('cascade');
+ if ($teams) {
+ $table->unsignedBigInteger($columnNames['team_foreign_key']);
+ $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
+
+ $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_permissions_permission_model_type_primary');
+ } else {
+ $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_permissions_permission_model_type_primary');
+ }
+
+ });
+
+ Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
+ $table->unsignedBigInteger($pivotRole);
+
+ $table->string('model_type');
+ $table->unsignedBigInteger($columnNames['model_morph_key']);
+ $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
+
+ $table->foreign($pivotRole)
+ ->references('id') // role id
+ ->on($tableNames['roles'])
+ ->onDelete('cascade');
+ if ($teams) {
+ $table->unsignedBigInteger($columnNames['team_foreign_key']);
+ $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
+
+ $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_roles_role_model_type_primary');
+ } else {
+ $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_roles_role_model_type_primary');
+ }
+ });
+
+ Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
+ $table->unsignedBigInteger($pivotPermission);
+ $table->unsignedBigInteger($pivotRole);
+
+ $table->foreign($pivotPermission)
+ ->references('id') // permission id
+ ->on($tableNames['permissions'])
+ ->onDelete('cascade');
+
+ $table->foreign($pivotRole)
+ ->references('id') // role id
+ ->on($tableNames['roles'])
+ ->onDelete('cascade');
+
+ $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
+ });
+
+ app('cache')
+ ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
+ ->forget(config('permission.cache.key'));
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ $tableNames = config('permission.table_names');
+
+ throw_if(empty($tableNames), Exception::class, 'Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
+
+ Schema::drop($tableNames['role_has_permissions']);
+ Schema::drop($tableNames['model_has_roles']);
+ Schema::drop($tableNames['model_has_permissions']);
+ Schema::drop($tableNames['roles']);
+ Schema::drop($tableNames['permissions']);
+ }
+};
diff --git a/resources/views/gracias.blade.php b/resources/views/gracias.blade.php
new file mode 100644
index 0000000..1de9c70
--- /dev/null
+++ b/resources/views/gracias.blade.php
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+ Muchas Gracias
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/views/layouts/admin.blade.php b/resources/views/layouts/admin.blade.php
index 7370c4d..51111cb 100644
--- a/resources/views/layouts/admin.blade.php
+++ b/resources/views/layouts/admin.blade.php
@@ -53,11 +53,15 @@
Productos
-
+ @can('usuarios.abm')
Usuarios
@@ -67,7 +71,46 @@
Nuevo Usuario
+ @endcan
+@can('permisos.abm')
+
+
+ Permisos
+
+
+
+@endcan
+
+ @can('roles.abm')
+
+
+ Roles
+
+
+
+
+@endcan
@endauth
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index 47b782e..6d4b591 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -48,12 +48,13 @@
{{ __('Login') }}
@endif
-
-
+ @endif
+ -->
@else
diff --git a/resources/views/permisos/create.blade.php b/resources/views/permisos/create.blade.php
new file mode 100644
index 0000000..39ee969
--- /dev/null
+++ b/resources/views/permisos/create.blade.php
@@ -0,0 +1,48 @@
+
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Nuevo Permiso
+
+ @if($errors->any())
+
+
+ @foreach($errors->all() as $error)
+ - {{ $error }}
+ @endforeach
+
+
+ @endif
+
+
+
+
+
+@endsection
diff --git a/resources/views/permisos/edit.blade.php b/resources/views/permisos/edit.blade.php
new file mode 100644
index 0000000..48eea17
--- /dev/null
+++ b/resources/views/permisos/edit.blade.php
@@ -0,0 +1,49 @@
+
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Editar Permiso
+
+ @if($errors->any())
+
+
+ @foreach($errors->all() as $error)
+ - {{ $error }}
+ @endforeach
+
+
+ @endif
+
+
+
+
+
+@endsection
diff --git a/resources/views/permisos/index.blade.php b/resources/views/permisos/index.blade.php
new file mode 100644
index 0000000..0e2c9b0
--- /dev/null
+++ b/resources/views/permisos/index.blade.php
@@ -0,0 +1,71 @@
+
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Listado de Permisos
+
+
+ Nuevo Permiso
+
+
+ @if(session('mensaje-success'))
+
+ {{ session('mensaje-success') }}
+
+ @endif
+
+
+
+
+ | ID |
+ Nombre |
+ Guard |
+ Acciones |
+
+
+
+
+ @foreach($permisos as $permiso)
+
+ | {{ $permiso->id }} |
+ {{ $permiso->name }} |
+ {{ $permiso->guard_name }} |
+
+
+
+ Ver
+
+
+
+ Editar
+
+
+
+ |
+
+ @endforeach
+
+
+
+
+
+@endsection
diff --git a/resources/views/permisos/show.blade.php b/resources/views/permisos/show.blade.php
new file mode 100644
index 0000000..46eab2d
--- /dev/null
+++ b/resources/views/permisos/show.blade.php
@@ -0,0 +1,39 @@
+
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Detalle del Permiso
+
+
+
+ | ID |
+ {{ $permiso->id }} |
+
+
+
+ | Nombre |
+ {{ $permiso->name }} |
+
+
+
+ | Guard |
+ {{ $permiso->guard_name }} |
+
+
+
+
+ Editar
+
+
+
+ Salir
+
+
+
+
+@endsection
diff --git a/resources/views/productos/index.blade.php b/resources/views/productos/index.blade.php
index 463332b..2ef8c29 100644
--- a/resources/views/productos/index.blade.php
+++ b/resources/views/productos/index.blade.php
@@ -10,14 +10,16 @@
+ @can('productos.crear')
+ @endcan
@@ -66,26 +68,28 @@
@csrf
@method('DELETE')
-
+ @can('productos.ver')
+ @endcan
-
+ @can('productos.editar')
-
-
+ @endcan
+ @can('productos.borrar')
+ @endcan
diff --git a/resources/views/roles/create.blade.php b/resources/views/roles/create.blade.php
new file mode 100644
index 0000000..047f130
--- /dev/null
+++ b/resources/views/roles/create.blade.php
@@ -0,0 +1,109 @@
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Nuevo Rol
+
+ @if($errors->any())
+
+
+ @foreach($errors->all() as $error)
+ - {{ $error }}
+ @endforeach
+
+
+ @endif
+
+
+
+
+
+@endsection
+@push('styles')
+
+@endpush
+
+@push('scripts')
+
+
+@endpush
diff --git a/resources/views/roles/edit.blade.php b/resources/views/roles/edit.blade.php
new file mode 100644
index 0000000..1d4bfb1
--- /dev/null
+++ b/resources/views/roles/edit.blade.php
@@ -0,0 +1,110 @@
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Editar Rol
+
+ @if($errors->any())
+
+
+ @foreach($errors->all() as $error)
+ - {{ $error }}
+ @endforeach
+
+
+ @endif
+
+
+
+
+
+@endsection
+@push('styles')
+
+@endpush
+
+@push('scripts')
+
+
+@endpush
\ No newline at end of file
diff --git a/resources/views/roles/index.blade.php b/resources/views/roles/index.blade.php
new file mode 100644
index 0000000..7b8c9e5
--- /dev/null
+++ b/resources/views/roles/index.blade.php
@@ -0,0 +1,88 @@
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Listado de Roles
+
+
+ Nuevo Rol
+
+
+ @if(session('mensaje-success'))
+
+ {{ session('mensaje-success') }}
+
+ @endif
+
+
+
+
+ | ID |
+ Nombre |
+ Permisos |
+ Usuarios |
+ Acciones |
+
+
+
+
+ @foreach($roles as $rol)
+
+ | {{ $rol->id }} |
+ {{ $rol->name }} |
+
+
+ @forelse($rol->permissions as $permiso)
+
+ {{ $permiso->name }}
+
+ @empty
+ Sin permisos
+ @endforelse
+ |
+
+
+ @forelse($rol->usuarios as $usuario)
+
+ {{ $usuario->name }}
+
+ @empty
+ Sin usuarios
+ @endforelse
+ |
+
+
+
+ Ver
+
+
+
+ Editar
+
+
+
+ |
+
+ @endforeach
+
+
+
+
+
+@endsection
\ No newline at end of file
diff --git a/resources/views/roles/show.blade.php b/resources/views/roles/show.blade.php
new file mode 100644
index 0000000..9944e14
--- /dev/null
+++ b/resources/views/roles/show.blade.php
@@ -0,0 +1,61 @@
+@extends('layouts.admin')
+
+@section('contenido')
+
+
+
+
Detalle del Rol
+
+
+
+
+ | ID |
+ {{ $rol->id }} |
+
+
+
+ | Nombre |
+ {{ $rol->name }} |
+
+
+
+ | Permisos |
+
+ @forelse($rol->permissions as $permiso)
+
+ {{ $permiso->name }}
+
+ @empty
+ Sin permisos
+ @endforelse
+ |
+
+
+
+ | Usuarios |
+
+ @forelse($rol->usuarios as $usuario)
+
+ {{ $usuario->name }}
+
+ @empty
+ Sin usuarios asignados
+ @endforelse
+ |
+
+
+
+
+
+ Editar
+
+
+
+ Salir
+
+
+
+
+@endsection
\ No newline at end of file
diff --git a/routes/web.php b/routes/web.php
index 6dcce47..9a1ec8b 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -4,6 +4,10 @@ use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CategoriasController;
use App\Http\Controllers\ProductoController;
use App\Http\Controllers\UsuarioController;
+use App\Http\Controllers\PermisoController;
+use App\Http\Controllers\RolController;
+
+
/*
|--------------------------------------------------------------------------
@@ -30,10 +34,27 @@ Route::put('categorias/{categoria}', [CategoriasController::class, 'update'])->n
-Route::resource('categorias', CategoriasController::class)->middleware('auth');
-Route::resource('productos', ProductoController::class);
-Route::put('categorias/restaurar/{categoria}', [CategoriasController::class, 'restaurar'])->name('categorias.restaurar')->middleware('auth');
-Auth::routes(['register' => false]);
-Route::resource('usuarios', UsuarioController::class)
+Route::resource('categorias', CategoriasController::class)
->middleware('auth');
+
+Route::resource('productos', ProductoController::class)
+ ->middleware('auth');
+
+Route::resource('usuarios', UsuarioController::class)
+ ->middleware(['auth','can:usuarios.abm']);
+
+Route::resource('permisos', PermisoController::class)
+ ->middleware(['auth','can:permisos.abm']);
+
+Route::resource('roles', RolController::class)
+ ->middleware(['auth','can:roles.abm']);
+
+Route::put('categorias/restaurar/{categoria}', [CategoriasController::class, 'restaurar'])
+->name('categorias.restaurar')->middleware('auth');
+
+Auth::routes(['register'=> false]);
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
+
+Route::get('/gracias', function () {
+ return view('gracias');
+})->name('gracias');
\ No newline at end of file