diff --git a/kernel/console/controllers/AdminConsoleController.php b/kernel/console/controllers/AdminConsoleController.php index bce72d6..0af6f7b 100644 --- a/kernel/console/controllers/AdminConsoleController.php +++ b/kernel/console/controllers/AdminConsoleController.php @@ -46,6 +46,9 @@ class AdminConsoleController extends ConsoleController $out = $this->migrationService->runAtPath("kernel/modules/post/migrations"); $this->out->r("create post table", "green"); + $out = $this->migrationService->runAtPath("kernel/modules/secure/migrations"); + $this->out->r("create secret_code table", "green"); + $this->optionService->createFromParams( key: "admin_theme_paths", value: "{\"paths\": [\"{KERNEL_ADMIN_THEMES}\", \"{APP}/admin_themes\"]}", diff --git a/kernel/modules/secure/controllers/SecureController.php b/kernel/modules/secure/controllers/SecureController.php index 299cead..8498c77 100644 --- a/kernel/modules/secure/controllers/SecureController.php +++ b/kernel/modules/secure/controllers/SecureController.php @@ -11,6 +11,7 @@ use kernel\Mailing; use kernel\modules\secure\models\forms\LoginEmailForm; use kernel\modules\secure\models\forms\LoginForm; use kernel\modules\secure\models\forms\RegisterForm; +use kernel\modules\secure\services\SecureService; use kernel\modules\user\models\User; use kernel\modules\user\service\UserService; use kernel\Request; @@ -86,17 +87,19 @@ class SecureController extends AdminController UserService::createUserByEmailAndPassword($email, $password); $user = $this->userService->getByField('email', $email); - $mailing->send_html("register_by_code.php", ['code' => $user->auth_code, 'password' => $password], [ + SecureService::createSecretCode($user); + $secretCode = SecureService::getByField("user_id", $user->id); + + + $mailing->send_html("register_by_code.php", ['code' => $secretCode->code, 'password' => $password], [ 'address' => $email, 'subject' => "Код регистрации", "from_name" => $_ENV['APP_NAME'] ]); } else { - $user->auth_code = mt_rand(100000, 999999);; - $user->auth_code_expires_at = date("Y-m-d H:i:s", strtotime("+5 minutes")); - $user->save(); - - $mailing->send_html("login_by_code.php", ['code' => $user->auth_code], [ + SecureService::updateSecretCode($user); + $secretCode = SecureService::getByField("user_id", $user->id); + $mailing->send_html("login_by_code.php", ['code' => $secretCode->code], [ 'address' => $email, 'subject' => "Код авторизации", "from_name" => $_ENV['APP_NAME'] @@ -120,7 +123,8 @@ class SecureController extends AdminController throw new exception("User not found."); } $code = $request->post("code"); - if ($user->auth_code == $code && time() <= strtotime($user->auth_code_expires_at)) { + $secretCode = SecureService::getByField("user_id", $user->id); + if ($secretCode->code == $code && time() <= strtotime($secretCode->code_expires_at)) { setcookie('user_id', $user->id, time() + 60 * 60 * 24, '/', $_SERVER['SERVER_NAME'], false); $this->redirect("/admin", code: 302); } else { diff --git a/kernel/modules/secure/controllers/SecureRestController.php b/kernel/modules/secure/controllers/SecureRestController.php index 7806f4b..7b59a36 100644 --- a/kernel/modules/secure/controllers/SecureRestController.php +++ b/kernel/modules/secure/controllers/SecureRestController.php @@ -7,10 +7,15 @@ use Firebase\JWT\Key; use JetBrains\PhpStorm\NoReturn; use kernel\App; use kernel\helpers\Debug; +use kernel\Mailing; +use kernel\modules\secure\models\SecretCode; +use kernel\modules\secure\services\SecureService; use kernel\modules\user\models\User; +use kernel\modules\user\service\UserService; use kernel\Request; use kernel\RestController; use kernel\services\TokenService; +use PHPMailer\PHPMailer\Exception; use Random\RandomException; class SecureRestController extends RestController @@ -51,32 +56,42 @@ class SecureRestController extends RestController $this->renderApi($res); } -// #[NoReturn] public function actionEmailAuth(): void -// { -// $request = new Request(); -// $data = $request->post(); -// $model = $this->model->where('email', $data['email'])->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); -// } + /** + * @throws Exception + * @throws RandomException + */ + #[NoReturn] public function actionEmailAuth(): void + { + $mailing = new Mailing(); + $request = new Request(); + $data = $request->post(); + $model = $this->model->where('email', $data['email'])->first(); -} \ No newline at end of file + if (!$model) { + $password = bin2hex(random_bytes(8)); + + UserService::createUserByEmailAndPassword($data['email'], $password); + $model = UserService::getByField('email', $data['email']); + + SecureService::createSecretCode($model); + $secretCode = SecureService::getByField("user_id", $model->id); + + + $mailing->send_html("register_by_code.php", ['code' => $secretCode->code, 'password' => $password], [ + 'address' => $data['email'], + 'subject' => "Код регистрации", + "from_name" => $_ENV['APP_NAME'] + ]); + } else { + SecureService::updateSecretCode($model); + $secretCode = SecureService::getByField("user_id", $model->id); + + $mailing->send_html("login_by_code.php", ['code' => $secretCode->code], [ + 'address' => $data['email'], + 'subject' => "Код авторизации", + "from_name" => $_ENV['APP_NAME'] + ]); + } + } + +} diff --git a/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php b/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php new file mode 100644 index 0000000..c5acce1 --- /dev/null +++ b/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php @@ -0,0 +1,31 @@ +schema->create('secret_code', function (Blueprint $table) { + $table->increments('id'); + $table->integer('user_id'); + $table->integer('code'); + $table->dateTime('code_expires_at')->nullable(true); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + \kernel\App::$db->schema->dropIfExists('secret_code'); + + } +}; diff --git a/kernel/modules/secure/models/SecretCode.php b/kernel/modules/secure/models/SecretCode.php new file mode 100644 index 0000000..0caaa60 --- /dev/null +++ b/kernel/modules/secure/models/SecretCode.php @@ -0,0 +1,25 @@ + 'Пользователь', + 'code' => 'Код', + 'code_expires_at' => 'Срок жизни кода', + ]; + } + +} diff --git a/kernel/modules/secure/routs/secure.php b/kernel/modules/secure/routs/secure.php index c1fa0fa..95c22d5 100644 --- a/kernel/modules/secure/routs/secure.php +++ b/kernel/modules/secure/routs/secure.php @@ -23,6 +23,7 @@ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ 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']); + App::$collector->post('/email_auth', [\kernel\modules\secure\controllers\SecureRestController::class, 'actionEmailAuth']); }); }); diff --git a/kernel/modules/secure/services/SecureService.php b/kernel/modules/secure/services/SecureService.php new file mode 100644 index 0000000..2f75b33 --- /dev/null +++ b/kernel/modules/secure/services/SecureService.php @@ -0,0 +1,40 @@ +user_id = $user->id; + $secretCode->code = mt_rand(100000, 999999); + $secretCode->code_expires_at = date("Y-m-d H:i:s", strtotime("+5 minutes"));; + $secretCode->save(); + } + + public static function updateSecretCode(User $user): void + { + $secretCode = SecretCode::where('user_id', $user->id)->first(); + $secretCode->code = mt_rand(100000, 999999); + $secretCode->save(); + } + + public static function getCodeByUserId(int $user_id) + { + return SecretCode::where('user_id', $user_id)->one()->code; + } + + public static function getByField(string $field, mixed $value) + { + return SecretCode::where($field, $value)->first(); + } + +} \ 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 4d2b7f5..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,8 +19,6 @@ return new class extends Migration $table->string('email', 255); $table->string('password_hash', 255); $table->integer('role')->default(1); - $table->integer('auth_code')->default(1); - $table->dateTime('auth_code_expires_at')->nullable(true); $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 4c9da2b..3dd03c1 100644 --- a/kernel/modules/user/models/User.php +++ b/kernel/modules/user/models/User.php @@ -7,8 +7,6 @@ use Illuminate\Database\Eloquent\Model; * @property string $username * @property string $email * @property string $password_hash - * @property int $auth_code - * @property string $auth_code_expires_at * @property string $access_token * @property string $access_token_expires_at * @method static find($id) @@ -19,7 +17,7 @@ class User extends Model { const ADMIN_USER_ROLE = 9; protected $table = 'user'; - protected $fillable = ['username', 'email', 'password_hash', 'role', 'auth_code', 'auth_code_expires_at', 'access_token', 'access_token_expires_at']; + protected $fillable = ['username', 'email', 'password_hash', 'role', 'access_token', 'access_token_expires_at']; protected array $dates = ['deleted at']; public static function labels(): array diff --git a/kernel/modules/user/service/UserService.php b/kernel/modules/user/service/UserService.php index a504ade..9e8dd5d 100644 --- a/kernel/modules/user/service/UserService.php +++ b/kernel/modules/user/service/UserService.php @@ -41,7 +41,7 @@ class UserService * @param string $value * @return mixed */ - public function getByField(string $field, string $value) + public static function getByField(string $field, string $value): mixed { return User::where($field, $value)->first(); } @@ -91,8 +91,6 @@ class UserService $user->email = $email; $user->username = $email; $user->password_hash = password_hash($password, PASSWORD_DEFAULT); - $user->auth_code = mt_rand(100000, 999999); - $user->auth_code_expires_at = date("Y-m-d H:i:s", strtotime("+5 minutes")); $user->save(); }