diff --git a/.env.example b/.env.example index 369616c..a9a285c 100644 --- a/.env.example +++ b/.env.example @@ -8,4 +8,6 @@ DB_COLLATION=utf8_unicode_ci DB_PREFIX='' VIEWS_PATH=/views -VIEWS_CACHE_PATH=/views_cache \ No newline at end of file +VIEWS_CACHE_PATH=/views_cache + +SECRET_KEY='' \ No newline at end of file diff --git a/app/modules/module_shop/controllers/ModuleShopRestController.php b/app/modules/module_shop/controllers/ModuleShopRestController.php index b53a7ba..760c4ea 100644 --- a/app/modules/module_shop/controllers/ModuleShopRestController.php +++ b/app/modules/module_shop/controllers/ModuleShopRestController.php @@ -3,6 +3,7 @@ namespace app\modules\module_shop\controllers; use app\modules\module_shop\models\ModuleShop; +use kernel\Request; use kernel\RestController; class ModuleShopRestController extends RestController @@ -13,4 +14,30 @@ class ModuleShopRestController extends RestController $this->model = new ModuleShop(); } + public function actionIndex(): void + { + $request = new Request(); + $page = $request->get('page') ?? 1; + $perPage = $request->get('per_page') ?? 10; + $query = $this->model->query(); + + if ($page > 1) { + $query->skip(($page - 1) * $perPage)->take($perPage); + } else { + $query->take($perPage); + } + + $query->groupBy("slug")->orderBy("id", "ASC"); + $expand = $this->expand(); + $expandParams = explode( ",", $request->get('expand') ?? ""); + $finalExpand = array_intersect($expandParams, $expand); + if ($finalExpand) { + $res = $query->get()->load($finalExpand)->toArray(); + } else { + $res = $query->get()->toArray(); + } + + $this->renderApi($res); + } + } \ No newline at end of file diff --git a/app/modules/module_shop/routs/ms.php b/app/modules/module_shop/routs/ms.php index a2c1be9..d64a2b2 100644 --- a/app/modules/module_shop/routs/ms.php +++ b/app/modules/module_shop/routs/ms.php @@ -3,6 +3,8 @@ use kernel\App; use kernel\CgRouteCollector; +App::$collector->filter('bearer', [\kernel\modules\secure\middlewares\BearerAuthMiddleware::class, "handler"]); + App::$collector->group(["prefix" => "admin"], function (CgRouteCollector $router) { App::$collector->group(["prefix" => "module_shop"], function (CgRouteCollector $router){ App::$collector->get('/', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionIndex']); @@ -18,5 +20,7 @@ App::$collector->group(["prefix" => "admin"], function (CgRouteCollector $router }); App::$collector->group(["prefix" => "api"], function (CgRouteCollector $router){ - $router->rest("module_shop", [\app\modules\module_shop\controllers\ModuleShopRestController::class]); + App::$collector->group(['before' => 'bearer'], function (CgRouteCollector $router){ + $router->rest("module_shop", [\app\modules\module_shop\controllers\ModuleShopRestController::class]); + }); }); \ No newline at end of file diff --git a/bootstrap.php b/bootstrap.php index da9207e..0a85d73 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -6,6 +6,7 @@ $dotenv->load(); include_once __DIR__ . "/bootstrap/db.php"; include_once __DIR__ . "/bootstrap/header.php"; +include_once __DIR__ . "/bootstrap/secure.php"; const ROOT_DIR = __DIR__; const KERNEL_DIR = __DIR__ . "/kernel"; const KERNEL_MODULES_DIR = __DIR__ . "/kernel/modules"; diff --git a/bootstrap/secure.php b/bootstrap/secure.php new file mode 100644 index 0000000..a800dda --- /dev/null +++ b/bootstrap/secure.php @@ -0,0 +1,8 @@ + 'JWT', // random_bytes, md5, crypt, hash, JWT + 'token_expired_time' => "+30 days", // +1 day +]; + +\kernel\App::$secure = $secure_config; \ No newline at end of file diff --git a/composer.json b/composer.json index cf14432..c4a4b2f 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,9 @@ "samejack/php-argv": "dev-master", "itguild/eloquent-table": "^0.4.1", "ext-zip": "*", - "josantonius/session": "^2.0" + "josantonius/session": "^2.0", + "firebase/php-jwt": "^6.10", + "k-adam/env-editor": "^2.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 7dd7d6d..2757482 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e4f9dc9c939855869a503f576ef50d53", + "content-hash": "da3890f2b5b477bf758306141b8c8583", "packages": [ { "name": "brick/math", @@ -273,6 +273,69 @@ ], "time": "2024-02-18T20:23:39+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v6.10.1", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "500501c2ce893c824c801da135d02661199f60c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", + "reference": "500501c2ce893c824c801da135d02661199f60c5", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" + }, + "time": "2024-05-18T18:05:11+00:00" + }, { "name": "graham-campbell/result-type", "version": "v1.1.3", @@ -337,16 +400,16 @@ }, { "name": "illuminate/collections", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "4d333ea19a27230b424b9af56f34cd658b5bbce2" + "reference": "2d99ccbb19e34450508ff3ab2f62ba90aa2e9793" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/4d333ea19a27230b424b9af56f34cd658b5bbce2", - "reference": "4d333ea19a27230b424b9af56f34cd658b5bbce2", + "url": "https://api.github.com/repos/illuminate/collections/zipball/2d99ccbb19e34450508ff3ab2f62ba90aa2e9793", + "reference": "2d99ccbb19e34450508ff3ab2f62ba90aa2e9793", "shasum": "" }, "require": { @@ -388,11 +451,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-09-27T14:54:48+00:00" + "time": "2024-10-10T19:23:07+00:00" }, { "name": "illuminate/conditionable", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -438,16 +501,16 @@ }, { "name": "illuminate/container", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "bc49d144a20b0d432e1ac812c9e056594b6c6480" + "reference": "06dfc614aff58384b28ba5ad191f6a02d6b192cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/bc49d144a20b0d432e1ac812c9e056594b6c6480", - "reference": "bc49d144a20b0d432e1ac812c9e056594b6c6480", + "url": "https://api.github.com/repos/illuminate/container/zipball/06dfc614aff58384b28ba5ad191f6a02d6b192cb", + "reference": "06dfc614aff58384b28ba5ad191f6a02d6b192cb", "shasum": "" }, "require": { @@ -485,11 +548,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-10-08T13:34:53+00:00" + "time": "2024-10-11T15:30:11+00:00" }, { "name": "illuminate/contracts", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", @@ -672,7 +735,7 @@ }, { "name": "illuminate/macroable", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -718,16 +781,16 @@ }, { "name": "illuminate/support", - "version": "v11.27.2", + "version": "v11.29.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "a567431e4820363d0bc28bdf14914ab16a2e63ef" + "reference": "fc86f3de6640a0fb204bf13e76037a7f191232d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/a567431e4820363d0bc28bdf14914ab16a2e63ef", - "reference": "a567431e4820363d0bc28bdf14914ab16a2e63ef", + "url": "https://api.github.com/repos/illuminate/support/zipball/fc86f3de6640a0fb204bf13e76037a7f191232d7", + "reference": "fc86f3de6640a0fb204bf13e76037a7f191232d7", "shasum": "" }, "require": { @@ -790,7 +853,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-10-08T18:54:07+00:00" + "time": "2024-10-22T13:59:47+00:00" }, { "name": "itguild/eloquent-table", @@ -975,6 +1038,57 @@ ], "time": "2024-05-20T09:12:44+00:00" }, + { + "name": "k-adam/env-editor", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/K-Adam/php-env-editor.git", + "reference": "894855dff5df4e6fce3c83dd00941a19f99fc5d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/K-Adam/php-env-editor/zipball/894855dff5df4e6fce3c83dd00941a19f99fc5d5", + "reference": "894855dff5df4e6fce3c83dd00941a19f99fc5d5", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "phpunit/phpunit": "9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "EnvEditor\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Adam Kecskes", + "email": "kecskes.adam@outlook.com" + } + ], + "description": ".env editor library", + "keywords": [ + "dot-env", + "env", + "env-editor", + "env-loader", + "env-php", + "env-writer" + ], + "support": { + "issues": "https://github.com/K-Adam/php-env-editor/issues", + "source": "https://github.com/K-Adam/php-env-editor/tree/2.0.0" + }, + "time": "2022-06-05T11:17:23+00:00" + }, { "name": "madesimple/php-arrays", "version": "v2.1.0", @@ -2562,5 +2676,5 @@ "ext-zip": "*" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/kernel/App.php b/kernel/App.php index 855e082..f185ce8 100644 --- a/kernel/App.php +++ b/kernel/App.php @@ -5,6 +5,7 @@ namespace kernel; use kernel\helpers\Debug; +use kernel\modules\user\models\User; use kernel\services\ModuleService; use Phroute\Phroute\Dispatcher; @@ -17,6 +18,10 @@ class App static Header $header; + static User $user; + + static array $secure; + public ModuleService $moduleService; public static Database $db; diff --git a/kernel/CgRouteCollector.php b/kernel/CgRouteCollector.php old mode 100755 new mode 100644 diff --git a/kernel/Database.php b/kernel/Database.php old mode 100755 new mode 100644 diff --git a/kernel/Header.php b/kernel/Header.php old mode 100755 new mode 100644 diff --git a/kernel/Middleware.php b/kernel/Middleware.php new file mode 100644 index 0000000..d26629d --- /dev/null +++ b/kernel/Middleware.php @@ -0,0 +1,10 @@ +renderApi($model->toArray()); } + #[NoReturn] public function returnError(int $code): void + { + http_response_code($code); + die('Forbidden'); + } + #[NoReturn] protected function renderApi(array $data): void { header("Content-Type: application/json"); @@ -108,4 +114,6 @@ class RestController exit(); } + + } \ No newline at end of file diff --git a/kernel/admin_themes/default/layout/login.php b/kernel/admin_themes/default/layout/login.php index 7536d3f..e099ab3 100644 --- a/kernel/admin_themes/default/layout/login.php +++ b/kernel/admin_themes/default/layout/login.php @@ -18,9 +18,19 @@ -
- + +
+ + +
+ + +
+ + +
+
diff --git a/kernel/console/ConsoleApp.php b/kernel/console/ConsoleApp.php old mode 100755 new mode 100644 diff --git a/kernel/console/ConsoleController.php b/kernel/console/ConsoleController.php old mode 100755 new mode 100644 diff --git a/kernel/console/Out.php b/kernel/console/Out.php old mode 100755 new mode 100644 diff --git a/kernel/console/controllers/AdminConsoleController.php b/kernel/console/controllers/AdminConsoleController.php index e1c3bfe..4b1bce3 100644 --- a/kernel/console/controllers/AdminConsoleController.php +++ b/kernel/console/controllers/AdminConsoleController.php @@ -69,7 +69,7 @@ class AdminConsoleController extends ConsoleController $this->optionService->createFromParams( key: "active_modules", - value: "{\"modules\":[\"admin_themes\", \"secure\"]}", + value: "{\"modules\":[\"admin_themes\", \"secure\", \"user\", \"menu\"]}", label: "Активные модули" ); $this->out->r("create option active_modules", "green"); @@ -82,6 +82,25 @@ class AdminConsoleController extends ConsoleController ]); $this->out->r("create item menu module", "green"); + $this->menuService->createItem([ + "label" => "Пользователи", + "url" => "#", + "slug" => "user", + ]); + $this->menuService->createItem([ + "label" => "Список", + "url" => "/admin/user", + "slug" => "user_list", + "parent_slug" => "user", + ]); + $this->menuService->createItem([ + "label" => "Создать", + "url" => "/admin/user/create", + "slug" => "user_create", + "parent_slug" => "user", + ]); + $this->out->r("create item menu user", "green"); + $this->menuService->createItem([ "label" => "Настройки", "url" => "#", diff --git a/kernel/console/controllers/KernelController.php b/kernel/console/controllers/KernelController.php index 4b47ee6..c59d7f4 100644 --- a/kernel/console/controllers/KernelController.php +++ b/kernel/console/controllers/KernelController.php @@ -4,10 +4,17 @@ namespace kernel\console\controllers; use kernel\console\ConsoleController; use kernel\helpers\Files; -use kernel\services\KernelService; +use ZipArchive; class KernelController extends ConsoleController { + protected Files $files; + + public function __construct() + { + parent::__construct(); + $this->files = new Files(); + } /** * @throws \Exception @@ -19,19 +26,86 @@ class KernelController extends ConsoleController } if (file_exists(ROOT_DIR . $this->argv['path'])) { - - $tmpKernelDirFull = RESOURCES_DIR . '/tmp/ad/kernel/'; - - $fileHelper = new Files(); - $fileHelper->copy_folder(KERNEL_DIR, $tmpKernelDirFull); - - $fileHelper->pack($tmpKernelDirFull, RESOURCES_DIR . '/tmp/kernel/kernel.itguild'); - - $fileHelper->recursiveRemoveDir($tmpKernelDirFull); - $this->out->r("Ядро заархивировано", 'green'); + $tmpKernelDirFull = RESOURCES_DIR . '/tmp/ad/kernel/kernel'; + $this->files->copy_folder(KERNEL_DIR, $tmpKernelDirFull); + $this->out->r("Ядро скопировано во временную папку", 'green'); } else { $this->out->r("Ядро не найдено", 'red'); } + + if (file_exists(ROOT_DIR . '/bootstrap')) { + $tmpBootstrapDirFull = RESOURCES_DIR . '/tmp/ad/kernel/bootstrap'; + $this->files->copy_folder(ROOT_DIR . '/bootstrap', $tmpBootstrapDirFull); + $this->out->r("/bootstrap скопирован во временную папку", 'green'); + } else { + $this->out->r("/bootstrap не найден", 'red'); + } + + if (file_exists(ROOT_DIR . '/.env.example')) { + $tmpEnvDirFull = RESOURCES_DIR . '/tmp/ad/kernel/env.example'; + copy(ROOT_DIR . '/.env.example', $tmpEnvDirFull); + $this->out->r("/.env.example скопирован во временную папку", 'green'); + } else { + $this->out->r("/.env.example не найден", 'red'); + } + + if (file_exists(ROOT_DIR . '/composer.json')) { + $tmpComposerDirFull = RESOURCES_DIR . '/tmp/ad/kernel/composer.json'; + copy(ROOT_DIR . '/composer.json', $tmpComposerDirFull); + $this->out->r("/composer.json скопирован во временную папку", 'green'); + } else { + $this->out->r("/composer.json не найден", 'red'); + } + + if (!is_dir(RESOURCES_DIR . '/tmp/app')) { + mkdir(RESOURCES_DIR . '/tmp/app'); + } + + $this->files->pack(RESOURCES_DIR . '/tmp/ad/kernel/', RESOURCES_DIR . '/tmp/kernel/kernel.igk'); + $this->files->recursiveRemoveDir(RESOURCES_DIR . '/tmp/ad/kernel/'); + } + + /** + * @throws \Exception + */ + public function actionUpdateKernel(): void + { + if (!isset($this->argv['path'])) { + throw new \Exception('Missing kernel path "--path" specified'); + } + + $zip = new ZipArchive; + if (file_exists(ROOT_DIR . $this->argv['path'])) { + $tmpKernelDir = md5(time()); + $res = $zip->open(ROOT_DIR . $this->argv['path']); + if ($res === TRUE) { + $tmpKernelDirFull = RESOURCES_DIR . '/tmp/kernel/' . $tmpKernelDir . "/"; + $zip->extractTo($tmpKernelDirFull); + $zip->close(); + $this->files->recursiveRemoveKernelDir(); + $this->files->copy_folder($tmpKernelDirFull . 'kernel' , ROOT_DIR . "/kernel"); + + if (isset($this->argv['bootstrap'])) { + $this->files->recursiveRemoveDir(ROOT_DIR . '/bootstrap'); + $this->files->copy_folder($tmpKernelDirFull . 'bootstrap' , ROOT_DIR . '/bootstrap'); + } + + if (isset($this->argv['env'])) { + copy($tmpKernelDirFull . 'env.example', ROOT_DIR . '/.env.example'); + } + + if (isset($this->argv['composer'])) { + copy($tmpKernelDirFull . 'composer.json', ROOT_DIR . '/composer.json'); + } + + $this->files->recursiveRemoveDir($tmpKernelDirFull); + $this->out->r('Ядро обновлено.', 'green'); + } else { + $this->out->r('unable to open zip archive', 'red'); + } + } else { + $this->out->r("archive not found", 'red'); + } } } \ No newline at end of file diff --git a/kernel/console/controllers/SecureController.php b/kernel/console/controllers/SecureController.php new file mode 100644 index 0000000..b9638c5 --- /dev/null +++ b/kernel/console/controllers/SecureController.php @@ -0,0 +1,25 @@ +setValue("SECRET_KEY", TokenService::random_bytes(15)); + + $envFile->saveTo(ROOT_DIR . "/.env"); + $this->out->r("Secret key successfully created.", "green"); + } + +} \ No newline at end of file diff --git a/kernel/console/migrations/stubs/blank.stub b/kernel/console/migrations/stubs/blank.stub old mode 100755 new mode 100644 diff --git a/kernel/console/migrations/stubs/create.stub b/kernel/console/migrations/stubs/create.stub old mode 100755 new mode 100644 diff --git a/kernel/console/migrations/stubs/migration.create.stub b/kernel/console/migrations/stubs/migration.create.stub old mode 100755 new mode 100644 diff --git a/kernel/console/migrations/stubs/migration.stub b/kernel/console/migrations/stubs/migration.stub old mode 100755 new mode 100644 diff --git a/kernel/console/migrations/stubs/migration.update.stub b/kernel/console/migrations/stubs/migration.update.stub old mode 100755 new mode 100644 diff --git a/kernel/console/migrations/stubs/update.stub b/kernel/console/migrations/stubs/update.stub old mode 100755 new mode 100644 diff --git a/kernel/console/routs/cli.php b/kernel/console/routs/cli.php index e48f961..693ff3c 100644 --- a/kernel/console/routs/cli.php +++ b/kernel/console/routs/cli.php @@ -17,6 +17,10 @@ App::$collector->group(["prefix" => "admin-theme"], callback: function (RouteCol App::$collector->console('uninstall', [\kernel\console\controllers\AdminThemeController::class, 'actionUninstallTheme']); }); +App::$collector->group(["prefix" => "secure"], callback: function (RouteCollector $router){ + App::$collector->console('create-secret-key', [\kernel\console\controllers\SecureController::class, 'actionCreateSecretKey']); +}); + App::$collector->group(["prefix" => "admin"], callback: function (RouteCollector $router){ App::$collector->console('init', [\kernel\console\controllers\AdminConsoleController::class, 'actionInit']); }); diff --git a/kernel/controllers/ModuleController.php b/kernel/controllers/ModuleController.php index 799833d..323a537 100644 --- a/kernel/controllers/ModuleController.php +++ b/kernel/controllers/ModuleController.php @@ -41,8 +41,14 @@ class ModuleController extends AdminController foreach (new DirectoryIterator($dir) as $fileInfo) { $info = []; if($fileInfo->isDot()) continue; + $mi = $this->moduleService->getModuleInfo($fileInfo->getPathname()); + if (isset($mi['show_in_admin'])){ + if ($mi['show_in_admin'] == 0){ + continue; + } + } $info['id'] = $i; - $modules_info[] = array_merge($info, $this->moduleService->getModuleInfo($fileInfo->getPathname())); + $modules_info[] = array_merge($info, $mi); $i++; } } diff --git a/kernel/helpers/Files.php b/kernel/helpers/Files.php index 0027357..4cd710a 100644 --- a/kernel/helpers/Files.php +++ b/kernel/helpers/Files.php @@ -43,6 +43,21 @@ class Files rmdir($dir); } + public function recursiveRemoveKernelDir(): void + { + $includes = new FilesystemIterator(KERNEL_DIR); + foreach ($includes as $include) { + if ($include->getFilename() === 'app_modules') continue; + + if(is_dir($include) && !is_link($include)) { + $this->recursiveRemoveDir($include); + } + else { + unlink($include); + } + } + } + public function pack(string $source, string $destination/*, bool $include_source = true*/): void { $zip = new ZipArchive(); diff --git a/kernel/middlewares/AuthMiddleware.php b/kernel/middlewares/AuthMiddleware.php new file mode 100644 index 0000000..368ca3e --- /dev/null +++ b/kernel/middlewares/AuthMiddleware.php @@ -0,0 +1,19 @@ +group(["prefix" => "admin"], function (RouteCollector $router){ - App::$collector->group(["prefix" => "settings"], function (RouteCollector $router){ - App::$collector->group(["prefix" => "admin-themes"], function (RouteCollector $router){ - App::$collector->get('/', [AdminThemeController::class, 'actionIndex']); - App::$collector->get('/activate', [AdminThemeController::class, 'actionActivate']); - // App::$collector->get('/create', [\kernel\modules\menu\controllers\MenuController::class, 'actionCreate']); - // App::$collector->post("/", [\kernel\modules\menu\controllers\MenuController::class, 'actionAdd']); - // App::$collector->get('/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionView']); - // App::$collector->any('/update/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionUpdate']); - // App::$collector->any("/edit/{id}", [\kernel\modules\menu\controllers\MenuController::class, 'actionEdit']); - // App::$collector->get('/delete/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionDelete']); + App::$collector->group(["before" => "auth"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "settings"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "admin-themes"], function (RouteCollector $router) { + App::$collector->get('/', [AdminThemeController::class, 'actionIndex']); + App::$collector->get('/activate', [AdminThemeController::class, 'actionActivate']); + // App::$collector->get('/create', [\kernel\modules\menu\controllers\MenuController::class, 'actionCreate']); + // App::$collector->post("/", [\kernel\modules\menu\controllers\MenuController::class, 'actionAdd']); + // App::$collector->get('/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionView']); + // App::$collector->any('/update/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionUpdate']); + // App::$collector->any("/edit/{id}", [\kernel\modules\menu\controllers\MenuController::class, 'actionEdit']); + // App::$collector->get('/delete/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionDelete']); + }); }); }); }); \ No newline at end of file diff --git a/kernel/modules/menu/routs/menu.php b/kernel/modules/menu/routs/menu.php index 753f239..94ea806 100644 --- a/kernel/modules/menu/routs/menu.php +++ b/kernel/modules/menu/routs/menu.php @@ -4,19 +4,24 @@ use kernel\App; use kernel\CgRouteCollector; use Phroute\Phroute\RouteCollector; +App::$collector->filter("auth", [\kernel\middlewares\AuthMiddleware::class, "handler"]); + App::$collector->group(["prefix" => "admin"], function (RouteCollector $router) { - App::$collector->group(["prefix" => "settings"], function (RouteCollector $router){ - App::$collector->group(["prefix" => "menu"], function (RouteCollector $router){ - App::$collector->get('/', [\kernel\modules\menu\controllers\MenuController::class, 'actionIndex']); - App::$collector->get('/page/{page_number}', [\kernel\modules\menu\controllers\MenuController::class, 'actionIndex']); - App::$collector->get('/create', [\kernel\modules\menu\controllers\MenuController::class, 'actionCreate']); - App::$collector->post("/", [\kernel\modules\menu\controllers\MenuController::class, 'actionAdd']); - App::$collector->get('/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionView']); - App::$collector->any('/update/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionUpdate']); - App::$collector->any("/edit/{id}", [\kernel\modules\menu\controllers\MenuController::class, 'actionEdit']); - App::$collector->get('/delete/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionDelete']); + App::$collector->group(["before" => "auth"], function (RouteCollector $router){ + App::$collector->group(["prefix" => "settings"], function (RouteCollector $router){ + App::$collector->group(["prefix" => "menu"], function (RouteCollector $router){ + App::$collector->get('/', [\kernel\modules\menu\controllers\MenuController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\kernel\modules\menu\controllers\MenuController::class, 'actionIndex']); + App::$collector->get('/create', [\kernel\modules\menu\controllers\MenuController::class, 'actionCreate']); + App::$collector->post("/", [\kernel\modules\menu\controllers\MenuController::class, 'actionAdd']); + App::$collector->get('/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionView']); + App::$collector->any('/update/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\kernel\modules\menu\controllers\MenuController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionDelete']); + }); }); }); + }); App::$collector->group(["prefix" => "api"], function (CgRouteCollector $router){ diff --git a/kernel/modules/menu/table/columns/MenuDeleteActionColumn.php b/kernel/modules/menu/table/columns/MenuDeleteActionColumn.php new file mode 100644 index 0000000..c47f86a --- /dev/null +++ b/kernel/modules/menu/table/columns/MenuDeleteActionColumn.php @@ -0,0 +1,17 @@ +baseUrl . $this->prefix . $this->id; + return " Удалить "; + } +} \ No newline at end of file diff --git a/kernel/modules/menu/table/columns/MenuEditActionColumn.php b/kernel/modules/menu/table/columns/MenuEditActionColumn.php new file mode 100644 index 0000000..b7de57e --- /dev/null +++ b/kernel/modules/menu/table/columns/MenuEditActionColumn.php @@ -0,0 +1,17 @@ +baseUrl . $this->prefix . $this->id; + return " Редактировать "; + } +} \ No newline at end of file diff --git a/kernel/modules/menu/table/columns/MenuViewActionColumn.php b/kernel/modules/menu/table/columns/MenuViewActionColumn.php new file mode 100644 index 0000000..bb9f3ad --- /dev/null +++ b/kernel/modules/menu/table/columns/MenuViewActionColumn.php @@ -0,0 +1,17 @@ +baseUrl . $this->prefix . $this->id; + return " Просмотр "; + } +} \ No newline at end of file diff --git a/kernel/modules/option/controllers/OptionController.php b/kernel/modules/option/controllers/OptionController.php index db84e99..bc929df 100644 --- a/kernel/modules/option/controllers/OptionController.php +++ b/kernel/modules/option/controllers/OptionController.php @@ -4,6 +4,7 @@ namespace kernel\modules\option\controllers; use JetBrains\PhpStorm\NoReturn; use kernel\AdminController; +use kernel\Flash; use kernel\helpers\Debug; use kernel\modules\option\models\forms\CreateOptionForm; use kernel\modules\option\models\Option; @@ -33,9 +34,11 @@ class OptionController extends AdminController if ($optionForm->validate()) { $option = $this->optionService->create($optionForm); if ($option) { + Flash::setMessage("success", "Опция успешно создана."); $this->redirect('/admin/option'); } } + Flash::setMessage("error", $optionForm->getErrorsStr()); $this->redirect('/admin/option/create'); } @@ -95,6 +98,7 @@ class OptionController extends AdminController #[NoReturn] public function actionDelete(int $id): void { Option::find($id)->delete(); + Flash::setMessage("success", "Опция успешно удалена."); $this->redirect('/admin/option'); } diff --git a/kernel/modules/option/models/forms/CreateOptionForm.php b/kernel/modules/option/models/forms/CreateOptionForm.php index 28c9dbf..e6b09ab 100644 --- a/kernel/modules/option/models/forms/CreateOptionForm.php +++ b/kernel/modules/option/models/forms/CreateOptionForm.php @@ -16,7 +16,7 @@ class CreateOptionForm extends FormModel public function rules(): array { return [ - 'key' => 'required|min-str-len:1|max-str-len:50', + 'key' => 'required|min-str-len:3|max-str-len:50', 'value' => '', 'label' => '', 'status' => '' diff --git a/kernel/modules/option/routs/option.php b/kernel/modules/option/routs/option.php index 259d2b0..639becf 100644 --- a/kernel/modules/option/routs/option.php +++ b/kernel/modules/option/routs/option.php @@ -4,14 +4,16 @@ use kernel\App; use Phroute\Phroute\RouteCollector; App::$collector->group(["prefix" => "admin"], function (RouteCollector $router) { - App::$collector->group(["prefix" => "option"], callback: function (RouteCollector $router) { - App::$collector->get('/', [\kernel\modules\option\controllers\OptionController::class, 'actionIndex']); - App::$collector->get('/page/{page_number}', [\kernel\modules\option\controllers\OptionController::class, 'actionIndex']); - App::$collector->get('/create', [\kernel\modules\option\controllers\OptionController::class, 'actionCreate']); - App::$collector->post("/", [\kernel\modules\option\controllers\OptionController::class, 'actionAdd']); - App::$collector->get('/{id}', [\kernel\modules\option\controllers\OptionController::class, 'actionView']); - App::$collector->any('/update/{id}', [\kernel\modules\option\controllers\OptionController::class, 'actionUpdate']); - App::$collector->any("/edit/{id}", [\kernel\modules\option\controllers\OptionController::class, 'actionEdit']); - App::$collector->get('/delete/{id}', [\kernel\modules\option\controllers\OptionController::class, 'actionDelete']); + App::$collector->group(["before" => "auth"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "option"], callback: function (RouteCollector $router) { + App::$collector->get('/', [\kernel\modules\option\controllers\OptionController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\kernel\modules\option\controllers\OptionController::class, 'actionIndex']); + App::$collector->get('/create', [\kernel\modules\option\controllers\OptionController::class, 'actionCreate']); + App::$collector->post("/", [\kernel\modules\option\controllers\OptionController::class, 'actionAdd']); + App::$collector->get('/{id}', [\kernel\modules\option\controllers\OptionController::class, 'actionView']); + App::$collector->any('/update/{id}', [\kernel\modules\option\controllers\OptionController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\kernel\modules\option\controllers\OptionController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\kernel\modules\option\controllers\OptionController::class, 'actionDelete']); + }); }); }); \ No newline at end of file diff --git a/kernel/modules/option/table/columns/OptionDeleteActionColumn.php b/kernel/modules/option/table/columns/OptionDeleteActionColumn.php new file mode 100644 index 0000000..e7fda5b --- /dev/null +++ b/kernel/modules/option/table/columns/OptionDeleteActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Удалить "; + } +} \ No newline at end of file diff --git a/kernel/modules/option/table/columns/OptionEditActionColumn.php b/kernel/modules/option/table/columns/OptionEditActionColumn.php new file mode 100644 index 0000000..0ad8bfc --- /dev/null +++ b/kernel/modules/option/table/columns/OptionEditActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Редактировать "; + } +} \ No newline at end of file diff --git a/kernel/modules/option/table/columns/OptionViewActionColumn.php b/kernel/modules/option/table/columns/OptionViewActionColumn.php new file mode 100644 index 0000000..5c12242 --- /dev/null +++ b/kernel/modules/option/table/columns/OptionViewActionColumn.php @@ -0,0 +1,18 @@ +baseUrl . $this->prefix . $this->id; + return " Просмотр "; + } + +} \ No newline at end of file diff --git a/kernel/modules/post/controllers/PostRestController.php b/kernel/modules/post/controllers/PostRestController.php index c640608..4f79482 100644 --- a/kernel/modules/post/controllers/PostRestController.php +++ b/kernel/modules/post/controllers/PostRestController.php @@ -4,7 +4,10 @@ namespace kernel\modules\post\controllers; use Illuminate\Database\Eloquent\Model; use JetBrains\PhpStorm\NoReturn; +use kernel\App; +use kernel\helpers\Debug; use kernel\modules\post\models\Post; +use kernel\Request; use kernel\RestController; class PostRestController extends RestController @@ -19,4 +22,31 @@ class PostRestController extends RestController return ["user"]; } + public function actionIndex(): void + { + $request = new Request(); + $page = $request->get('page') ?? 1; + $perPage = $request->get('per_page') ?? 10; + $query = $this->model->query(); + if (App::$user){ + $query->where("user_id", App::$user->id); + } + + if ($page > 1) { + $query->skip(($page - 1) * $perPage)->take($perPage); + } else { + $query->take($perPage); + } + + $expand = $this->expand(); + $expandParams = explode( ",", $request->get('expand') ?? ""); + $finalExpand = array_intersect($expandParams, $expand); + if ($finalExpand) { + $res = $query->get()->load($finalExpand)->toArray(); + } else { + $res = $query->get()->toArray(); + } + + $this->renderApi($res); + } } \ No newline at end of file diff --git a/kernel/modules/post/routs/post.php b/kernel/modules/post/routs/post.php index 8d4755a..c52a2bb 100644 --- a/kernel/modules/post/routs/post.php +++ b/kernel/modules/post/routs/post.php @@ -4,20 +4,25 @@ use kernel\App; use kernel\CgRouteCollector; use Phroute\Phroute\RouteCollector; +App::$collector->filter('bearer', [\kernel\modules\secure\middlewares\BearerAuthMiddleware::class, "handler"]); App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ - App::$collector->group(["prefix" => "post"], function (RouteCollector $router){ - App::$collector->get('/', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); - App::$collector->get('/page/{page_number}', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); - App::$collector->get('/create', [\kernel\modules\post\controllers\PostController::class, 'actionCreate']); - App::$collector->post("/", [\kernel\modules\post\controllers\PostController::class, 'actionAdd']); - App::$collector->get('/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionView']); - App::$collector->any('/update/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionUpdate']); - App::$collector->any("/edit/{id}", [\kernel\modules\post\controllers\PostController::class, 'actionEdit']); - App::$collector->get('/delete/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionDelete']); + App::$collector->group(["before" => "auth"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "post"], function (RouteCollector $router) { + App::$collector->get('/', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); + App::$collector->get('/create', [\kernel\modules\post\controllers\PostController::class, 'actionCreate']); + App::$collector->post("/", [\kernel\modules\post\controllers\PostController::class, 'actionAdd']); + App::$collector->get('/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionView']); + App::$collector->any('/update/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\kernel\modules\post\controllers\PostController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionDelete']); + }); }); }); App::$collector->group(["prefix" => "api"], function (CgRouteCollector $router){ - $router->rest("post", [\kernel\modules\post\controllers\PostRestController::class]); + App::$collector->group(['before' => 'bearer'], function (CgRouteCollector $router){ + $router->rest("post", [\kernel\modules\post\controllers\PostRestController::class]); + }); }); \ No newline at end of file diff --git a/kernel/modules/post/table/columns/PostDeleteActionColumn.php b/kernel/modules/post/table/columns/PostDeleteActionColumn.php new file mode 100644 index 0000000..c04ee6b --- /dev/null +++ b/kernel/modules/post/table/columns/PostDeleteActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Удалить "; + } +} \ No newline at end of file diff --git a/kernel/modules/post/table/columns/PostEditActionColumn.php b/kernel/modules/post/table/columns/PostEditActionColumn.php new file mode 100644 index 0000000..d2802bb --- /dev/null +++ b/kernel/modules/post/table/columns/PostEditActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Редактировать "; + } +} \ No newline at end of file diff --git a/kernel/modules/post/table/columns/PostViewActionColumn.php b/kernel/modules/post/table/columns/PostViewActionColumn.php new file mode 100644 index 0000000..ecdec5d --- /dev/null +++ b/kernel/modules/post/table/columns/PostViewActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Просмотр "; + } +} \ No newline at end of file diff --git a/kernel/modules/secure/controllers/SecureController.php b/kernel/modules/secure/controllers/SecureController.php index bfdcd1c..e698424 100644 --- a/kernel/modules/secure/controllers/SecureController.php +++ b/kernel/modules/secure/controllers/SecureController.php @@ -4,6 +4,8 @@ namespace kernel\modules\secure\controllers; use JetBrains\PhpStorm\NoReturn; use kernel\AdminController; +use kernel\Flash; +use kernel\helpers\Debug; use kernel\modules\secure\models\forms\LoginForm; use kernel\modules\user\service\UserService; @@ -25,7 +27,7 @@ class SecureController extends AdminController $this->cgView->render('login.php'); } - public function actionAuth(): void + #[NoReturn] public function actionAuth(): void { $loginForm = new LoginForm(); $loginForm->load($_REQUEST); @@ -39,21 +41,23 @@ class SecureController extends AdminController $user = $this->userService->getByField($field, $loginForm->getItem("username")); if (!$user){ - throw new \Exception(message: "User not found"); + Flash::setMessage("error", "User not found."); + $this->redirect("/admin/login", code: 302); } if (password_verify($loginForm->getItem("password"), $user->password_hash)) { setcookie('user_id', $user->id, time()+60*60*24, '/', $_SERVER['SERVER_NAME'], false); - $this->redirect("/admin"); + $this->redirect("/admin", code: 302); } else { - $this->redirect("/admin/login"); + Flash::setMessage("error", "Username or password incorrect."); + $this->redirect("/admin/login", code: 302); } } #[NoReturn] public function actionLogout(): void { unset($_COOKIE['user_id']); - setcookie('user_id', "", -1, '/', $_SERVER['SERVER_NAME'], false); + setcookie('user_id', "", -1, '/', ".".$_SERVER['SERVER_NAME'], false); $this->redirect("/", code: 302); } diff --git a/kernel/modules/secure/controllers/SecureRestController.php b/kernel/modules/secure/controllers/SecureRestController.php new file mode 100644 index 0000000..42ede4a --- /dev/null +++ b/kernel/modules/secure/controllers/SecureRestController.php @@ -0,0 +1,54 @@ +model = new User(); + } + + /** + * @throws RandomException + */ + #[NoReturn] public function actionAuth(): void + { + $request = new Request(); + $data = $request->post(); + $model = $this->model->where('username', $data['username'])->first(); + $res = []; + if ($model) { + if (password_verify($data["password"], $model->password_hash)) { + $model->access_token_expires_at = date("Y-m-d H:i:s", strtotime(App::$secure['token_expired_time'])); + $model->access_token = match (App::$secure['token_type']) { + "JWT" => TokenService::JWT($_ENV['SECRET_KEY'], 'HS256'), + "md5" => TokenService::md5(), + "crypt" => TokenService::crypt(), + "hash" => TokenService::hash('sha256'), + default => TokenService::random_bytes(20), + }; + + $res = [ + "access_token" => $model->access_token, + "access_token_expires_at" => $model->access_token_expires_at, + ]; + } + $model->save(); + } + + $this->renderApi($res); + } + +} \ No newline at end of file diff --git a/kernel/modules/secure/manifest.json b/kernel/modules/secure/manifest.json index 70ec7cd..6d93a08 100644 --- a/kernel/modules/secure/manifest.json +++ b/kernel/modules/secure/manifest.json @@ -4,5 +4,7 @@ "author": "ITGuild", "slug": "secure", "description": "Secure module", - "routs": "routs/secure.php" + "routs": "routs/secure.php", + "dependence": "user", + "show_in_admin": 0 } \ No newline at end of file diff --git a/kernel/modules/secure/middlewares/BearerAuthMiddleware.php b/kernel/modules/secure/middlewares/BearerAuthMiddleware.php new file mode 100644 index 0000000..d77893d --- /dev/null +++ b/kernel/modules/secure/middlewares/BearerAuthMiddleware.php @@ -0,0 +1,48 @@ +userService = new UserService(); + } + + function handler(): void + { + $request = new Request(); + $authorization = $request->getHeader("Authorization"); + if ($authorization){ + $authorization = explode(" ", $authorization); + $type = $authorization[0]; + $token = $authorization[1]; + if ($type === "Bearer"){ + $user = $this->userService->getByAccessToken($token); + if ($user){ + if ($user->access_token_expires_at > date("Y-m-d")){ + App::$user = $user; + return; + } + } + } + } + + $this->returnError(403); + } + + #[NoReturn] public function returnError(int $code): void + { + http_response_code($code); + die('Forbidden'); + } +} \ No newline at end of file diff --git a/kernel/modules/secure/routs/secure.php b/kernel/modules/secure/routs/secure.php index 9cda940..84b37c3 100644 --- a/kernel/modules/secure/routs/secure.php +++ b/kernel/modules/secure/routs/secure.php @@ -1,16 +1,11 @@ filter("auth", function (){ - if(!isset($_COOKIE['user_id'])) - { - header('Location: /admin/login', true, 302); - - return false; - } -}); +App::$collector->filter("auth", [\kernel\middlewares\AuthMiddleware::class, "handler"]); +App::$collector->filter('bearer', [\kernel\modules\secure\middlewares\BearerAuthMiddleware::class, "handler"]); App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ App::$collector->group(["before" => "auth"], function (RouteCollector $router){ @@ -19,4 +14,11 @@ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ App::$collector->get('/login', [\kernel\modules\secure\controllers\SecureController::class, 'actionLogin']); App::$collector->get('/logout', [\kernel\modules\secure\controllers\SecureController::class, 'actionLogout']); App::$collector->post('/auth', [\kernel\modules\secure\controllers\SecureController::class, 'actionAuth']); -}); \ No newline at end of file +}); + +App::$collector->group(["prefix" => "api"], function (CgRouteCollector $router){ + App::$collector->group(["prefix" => "secure"], function (CgRouteCollector $router) { + App::$collector->post('/auth', [\kernel\modules\secure\controllers\SecureRestController::class, 'actionAuth']); + }); +}); + diff --git a/kernel/modules/user/manifest.json b/kernel/modules/user/manifest.json index 2ddffae..72e1b80 100644 --- a/kernel/modules/user/manifest.json +++ b/kernel/modules/user/manifest.json @@ -7,5 +7,5 @@ "module_class": "kernel\\modules\\user\\UserModule", "module_class_file": "{KERNEL_MODULES}/user/UserModule.php", "routs": "routs/user.php", - "dependence": "menu" + "dependence": "menu,secure" } \ No newline at end of file diff --git a/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php b/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php index 8f53302..774213a 100644 --- a/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php +++ b/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php @@ -19,6 +19,8 @@ return new class extends Migration $table->string('email', 255); $table->string('password_hash', 255); $table->integer('role')->default(1); + $table->string('access_token', 255)->nullable(true); + $table->dateTime('access_token_expires_at')->nullable(true); $table->timestamps(); }); } diff --git a/kernel/modules/user/models/User.php b/kernel/modules/user/models/User.php index 6663709..3dd03c1 100644 --- a/kernel/modules/user/models/User.php +++ b/kernel/modules/user/models/User.php @@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Model; * @property string $username * @property string $email * @property string $password_hash + * @property string $access_token + * @property string $access_token_expires_at * @method static find($id) */ class User extends Model { @@ -15,7 +17,7 @@ class User extends Model { const ADMIN_USER_ROLE = 9; protected $table = 'user'; - protected $fillable = ['username', 'email', 'password_hash', 'role']; + protected $fillable = ['username', 'email', 'password_hash', 'role', 'access_token', 'access_token_expires_at']; protected array $dates = ['deleted at']; public static function labels(): array @@ -24,7 +26,7 @@ class User extends Model { 'username' => 'Логин', 'email' => 'Email', 'created_at' => 'Создан', - 'updated_at' => 'Обновлен' + 'updated_at' => 'Обновлен', ]; } } diff --git a/kernel/modules/user/routs/user.php b/kernel/modules/user/routs/user.php index 5f5c74c..d7214fd 100644 --- a/kernel/modules/user/routs/user.php +++ b/kernel/modules/user/routs/user.php @@ -7,14 +7,16 @@ use Phroute\Phroute\RouteCollector; App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ - App::$collector->group(["prefix" => "user"], callback: function (RouteCollector $router){ - App::$collector->get('/', [\kernel\modules\user\controllers\UserController::class, 'actionIndex']); - App::$collector->get('/page/{page_number}', [\kernel\modules\user\controllers\UserController::class, 'actionIndex']); - App::$collector->get('/create', [\kernel\modules\user\controllers\UserController::class, 'actionCreate']); - App::$collector->post("/", [\kernel\modules\user\controllers\UserController::class, 'actionAdd']); - App::$collector->get('/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionView']); - App::$collector->any('/update/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionUpdate']); - App::$collector->any("/edit/{id}", [\kernel\modules\user\controllers\UserController::class, 'actionEdit']); - App::$collector->get('/delete/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionDelete']); + App::$collector->group(["before" => "auth"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "user"], callback: function (RouteCollector $router) { + App::$collector->get('/', [\kernel\modules\user\controllers\UserController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\kernel\modules\user\controllers\UserController::class, 'actionIndex']); + App::$collector->get('/create', [\kernel\modules\user\controllers\UserController::class, 'actionCreate']); + App::$collector->post("/", [\kernel\modules\user\controllers\UserController::class, 'actionAdd']); + App::$collector->get('/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionView']); + App::$collector->any('/update/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\kernel\modules\user\controllers\UserController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionDelete']); + }); }); }); \ No newline at end of file diff --git a/kernel/modules/user/service/UserService.php b/kernel/modules/user/service/UserService.php index 514675e..8619038 100644 --- a/kernel/modules/user/service/UserService.php +++ b/kernel/modules/user/service/UserService.php @@ -33,6 +33,11 @@ class UserService return false; } + /** + * @param string $field + * @param string $value + * @return mixed + */ public function getByField(string $field, string $value) { return User::where($field, $value)->first(); @@ -72,4 +77,9 @@ class UserService return ''; } + public function getByAccessToken(string $token) + { + return $this->getByField("access_token", $token); + } + } \ No newline at end of file diff --git a/kernel/modules/user/table/columns/UserDeleteActionColumn.php b/kernel/modules/user/table/columns/UserDeleteActionColumn.php new file mode 100644 index 0000000..641b26c --- /dev/null +++ b/kernel/modules/user/table/columns/UserDeleteActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Удалить "; + } +} \ No newline at end of file diff --git a/kernel/modules/user/table/columns/UserEditActionColumn.php b/kernel/modules/user/table/columns/UserEditActionColumn.php new file mode 100644 index 0000000..5dcdea3 --- /dev/null +++ b/kernel/modules/user/table/columns/UserEditActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Редактировать "; + } +} \ No newline at end of file diff --git a/kernel/modules/user/table/columns/UserViewActionColumn.php b/kernel/modules/user/table/columns/UserViewActionColumn.php new file mode 100644 index 0000000..aae3524 --- /dev/null +++ b/kernel/modules/user/table/columns/UserViewActionColumn.php @@ -0,0 +1,16 @@ +baseUrl . $this->prefix . $this->id; + return " Просмотр "; + } +} \ No newline at end of file diff --git a/kernel/routs/admin.php b/kernel/routs/admin.php index d144bd5..ddddeaf 100644 --- a/kernel/routs/admin.php +++ b/kernel/routs/admin.php @@ -3,6 +3,7 @@ use kernel\App; use Phroute\Phroute\RouteCollector; +App::$collector->filter("auth", [\kernel\middlewares\AuthMiddleware::class, "handler"]); App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ App::$collector->group(["before" => "auth"], function (RouteCollector $router){ diff --git a/kernel/services/TokenService.php b/kernel/services/TokenService.php new file mode 100644 index 0000000..de5a4dd --- /dev/null +++ b/kernel/services/TokenService.php @@ -0,0 +1,62 @@ +