Просмотр исходного кода

Merge pull request #2389 from SSPanel-UIM/dev

Dev 20240307
M1Screw 1 год назад
Родитель
Сommit
6fb92d2375

+ 61 - 57
composer.lock

@@ -124,16 +124,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.300.9",
+            "version": "3.300.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "2704b9b10b42d53066eb383f47541124296db77c"
+                "reference": "b1c05a5d3cb429aa5d9ffa69066ce46e3d7aca52"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2704b9b10b42d53066eb383f47541124296db77c",
-                "reference": "2704b9b10b42d53066eb383f47541124296db77c",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b1c05a5d3cb429aa5d9ffa69066ce46e3d7aca52",
+                "reference": "b1c05a5d3cb429aa5d9ffa69066ce46e3d7aca52",
                 "shasum": ""
             },
             "require": {
@@ -213,9 +213,9 @@
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.300.9"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.300.11"
             },
-            "time": "2024-03-01T19:04:32+00:00"
+            "time": "2024-03-05T19:08:14+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -747,16 +747,16 @@
         },
         {
             "name": "endroid/qr-code",
-            "version": "5.0.4",
+            "version": "5.0.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/endroid/qr-code.git",
-                "reference": "0efd071a3640af323e23c94122fe92cfd5199833"
+                "reference": "739fc545bfade2470765219dc2a615a6f1e94987"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/endroid/qr-code/zipball/0efd071a3640af323e23c94122fe92cfd5199833",
-                "reference": "0efd071a3640af323e23c94122fe92cfd5199833",
+                "url": "https://api.github.com/repos/endroid/qr-code/zipball/739fc545bfade2470765219dc2a615a6f1e94987",
+                "reference": "739fc545bfade2470765219dc2a615a6f1e94987",
                 "shasum": ""
             },
             "require": {
@@ -810,7 +810,7 @@
             ],
             "support": {
                 "issues": "https://github.com/endroid/qr-code/issues",
-                "source": "https://github.com/endroid/qr-code/tree/5.0.4"
+                "source": "https://github.com/endroid/qr-code/tree/5.0.5"
             },
             "funding": [
                 {
@@ -818,14 +818,14 @@
                     "type": "github"
                 }
             ],
-            "time": "2023-12-24T13:47:07+00:00"
+            "time": "2024-03-03T18:17:54+00:00"
         },
         {
             "name": "geoip2/geoip2",
             "version": "v3.0.0",
             "source": {
                 "type": "git",
-                "url": "[email protected]:maxmind/GeoIP2-php.git",
+                "url": "https://github.com/maxmind/GeoIP2-php.git",
                 "reference": "1a802ce9356cdd1c6b681c030fd9563750e11e6a"
             },
             "dist": {
@@ -872,6 +872,10 @@
                 "geolocation",
                 "maxmind"
             ],
+            "support": {
+                "issues": "https://github.com/maxmind/GeoIP2-php/issues",
+                "source": "https://github.com/maxmind/GeoIP2-php/tree/v3.0.0"
+            },
             "time": "2023-12-04T17:16:34+00:00"
         },
         {
@@ -1201,16 +1205,16 @@
         },
         {
             "name": "illuminate/collections",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/collections.git",
-                "reference": "dd0c652dfac0901c17bcfac94fe792e615b56e12"
+                "reference": "7bc2e907285b6a38acb3b386dcc577b185bf3d73"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/collections/zipball/dd0c652dfac0901c17bcfac94fe792e615b56e12",
-                "reference": "dd0c652dfac0901c17bcfac94fe792e615b56e12",
+                "url": "https://api.github.com/repos/illuminate/collections/zipball/7bc2e907285b6a38acb3b386dcc577b185bf3d73",
+                "reference": "7bc2e907285b6a38acb3b386dcc577b185bf3d73",
                 "shasum": ""
             },
             "require": {
@@ -1252,11 +1256,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-02-21T14:18:14+00:00"
+            "time": "2024-03-04T18:11:18+00:00"
         },
         {
             "name": "illuminate/conditionable",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/conditionable.git",
@@ -1302,7 +1306,7 @@
         },
         {
             "name": "illuminate/container",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/container.git",
@@ -1353,7 +1357,7 @@
         },
         {
             "name": "illuminate/contracts",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/contracts.git",
@@ -1401,16 +1405,16 @@
         },
         {
             "name": "illuminate/database",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/database.git",
-                "reference": "d756278a38541ec2f25c75e2553398b37a6d4e42"
+                "reference": "385a67f5351be38c5c6f28d58f7d76cbaffcaa02"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/database/zipball/d756278a38541ec2f25c75e2553398b37a6d4e42",
-                "reference": "d756278a38541ec2f25c75e2553398b37a6d4e42",
+                "url": "https://api.github.com/repos/illuminate/database/zipball/385a67f5351be38c5c6f28d58f7d76cbaffcaa02",
+                "reference": "385a67f5351be38c5c6f28d58f7d76cbaffcaa02",
                 "shasum": ""
             },
             "require": {
@@ -1470,11 +1474,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-02-26T16:14:36+00:00"
+            "time": "2024-03-04T21:32:24+00:00"
         },
         {
             "name": "illuminate/macroable",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/macroable.git",
@@ -1520,7 +1524,7 @@
         },
         {
             "name": "illuminate/pagination",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/pagination.git",
@@ -1570,16 +1574,16 @@
         },
         {
             "name": "illuminate/support",
-            "version": "v10.46.0",
+            "version": "v10.47.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/support.git",
-                "reference": "96d4512df39bee8cb60d50783f944a48242ea862"
+                "reference": "a98f849a2a0f36fbcbec77d07cae680e240ccdc1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/support/zipball/96d4512df39bee8cb60d50783f944a48242ea862",
-                "reference": "96d4512df39bee8cb60d50783f944a48242ea862",
+                "url": "https://api.github.com/repos/illuminate/support/zipball/a98f849a2a0f36fbcbec77d07cae680e240ccdc1",
+                "reference": "a98f849a2a0f36fbcbec77d07cae680e240ccdc1",
                 "shasum": ""
             },
             "require": {
@@ -1637,7 +1641,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-02-26T22:20:06+00:00"
+            "time": "2024-03-02T00:22:09+00:00"
         },
         {
             "name": "irazasyed/telegram-bot-sdk",
@@ -4186,16 +4190,16 @@
         },
         {
             "name": "slim/slim",
-            "version": "4.12.0",
+            "version": "4.13.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/slimphp/Slim.git",
-                "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18"
+                "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/slimphp/Slim/zipball/e9e99c2b24398b967841c6c4c3048622cc7e2b18",
-                "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18",
+                "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17",
+                "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17",
                 "shasum": ""
             },
             "require": {
@@ -4204,7 +4208,7 @@
                 "php": "^7.4 || ^8.0",
                 "psr/container": "^1.0 || ^2.0",
                 "psr/http-factory": "^1.0",
-                "psr/http-message": "^1.1",
+                "psr/http-message": "^1.1 || ^2.0",
                 "psr/http-server-handler": "^1.0",
                 "psr/http-server-middleware": "^1.0",
                 "psr/log": "^1.1 || ^2.0 || ^3.0"
@@ -4212,19 +4216,19 @@
             "require-dev": {
                 "adriansuter/php-autoload-override": "^1.4",
                 "ext-simplexml": "*",
-                "guzzlehttp/psr7": "^2.5",
+                "guzzlehttp/psr7": "^2.6",
                 "httpsoft/http-message": "^1.1",
                 "httpsoft/http-server-request": "^1.1",
-                "laminas/laminas-diactoros": "^2.17",
+                "laminas/laminas-diactoros": "^2.17 || ^3",
                 "nyholm/psr7": "^1.8",
-                "nyholm/psr7-server": "^1.0",
-                "phpspec/prophecy": "^1.17",
-                "phpspec/prophecy-phpunit": "^2.0",
+                "nyholm/psr7-server": "^1.1",
+                "phpspec/prophecy": "^1.19",
+                "phpspec/prophecy-phpunit": "^2.1",
                 "phpstan/phpstan": "^1.10",
                 "phpunit/phpunit": "^9.6",
                 "slim/http": "^1.3",
                 "slim/psr7": "^1.6",
-                "squizlabs/php_codesniffer": "^3.7"
+                "squizlabs/php_codesniffer": "^3.9"
             },
             "suggest": {
                 "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware",
@@ -4297,7 +4301,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-07-23T04:54:29+00:00"
+            "time": "2024-03-03T21:25:30+00:00"
         },
         {
             "name": "smarty/smarty",
@@ -4602,16 +4606,16 @@
         },
         {
             "name": "symfony/http-client",
-            "version": "v7.0.4",
+            "version": "v7.0.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-client.git",
-                "reference": "8384876f49a2316a63f88a9cd12436de6936bee6"
+                "reference": "425f462a59d8030703ee04a9e1c666575ed5db3b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-client/zipball/8384876f49a2316a63f88a9cd12436de6936bee6",
-                "reference": "8384876f49a2316a63f88a9cd12436de6936bee6",
+                "url": "https://api.github.com/repos/symfony/http-client/zipball/425f462a59d8030703ee04a9e1c666575ed5db3b",
+                "reference": "425f462a59d8030703ee04a9e1c666575ed5db3b",
                 "shasum": ""
             },
             "require": {
@@ -4674,7 +4678,7 @@
                 "http"
             ],
             "support": {
-                "source": "https://github.com/symfony/http-client/tree/v7.0.4"
+                "source": "https://github.com/symfony/http-client/tree/v7.0.5"
             },
             "funding": [
                 {
@@ -4690,7 +4694,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-02-15T11:33:06+00:00"
+            "time": "2024-03-02T12:46:12+00:00"
         },
         {
             "name": "symfony/http-client-contracts",
@@ -6864,16 +6868,16 @@
         },
         {
             "name": "nikic/php-parser",
-            "version": "v5.0.1",
+            "version": "v5.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69"
+                "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69",
-                "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
+                "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
                 "shasum": ""
             },
             "require": {
@@ -6916,9 +6920,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
             },
-            "time": "2024-02-21T19:24:10+00:00"
+            "time": "2024-03-05T20:51:40+00:00"
         },
         {
             "name": "nunomaduro/phpinsights",

+ 2 - 2
db/migrations/2024030300-update_node_ip.php

@@ -9,8 +9,8 @@ return new class() implements MigrationInterface {
     public function up(): int
     {
         DB::getPdo()->exec("
-            ALTER TABLE node ADD COLUMN IF NOT EXISTS `ipv4` INET4 NOT NULL DEFAULT '127.0.0.1' COMMENT 'IPv4地址';
-            ALTER TABLE node ADD COLUMN IF NOT EXISTS `ipv6` INET6 NOT NULL DEFAULT '::1' COMMENT 'IPv6地址';
+            ALTER TABLE node ADD COLUMN IF NOT EXISTS `ipv4` inet4 NOT NULL DEFAULT '127.0.0.1' COMMENT 'IPv4地址';
+            ALTER TABLE node ADD COLUMN IF NOT EXISTS `ipv6` inet6 NOT NULL DEFAULT '::1' COMMENT 'IPv6地址';
             ALTER TABLE node DROP COLUMN IF EXISTS `node_ip`;
         ");
 

+ 1 - 1
resources/views/tabler/admin/user/edit.tpl

@@ -223,7 +223,7 @@
                             <div class="form-group mb-3 row">
                                 <label class="form-label col-3 col-form-label">密码</label>
                                 <div class="col">
-                                    <input id="passwd" type="text" class="form-control" value="{$edit_user->passwd}">
+                                    <input id="passwd" type="text" class="form-control" value="{$edit_user->passwd}" disabled/>
                                 </div>
                             </div>
                             <div class="form-group mb-3 row">

+ 3 - 3
resources/views/tabler/auth/login.tpl

@@ -23,7 +23,7 @@
                             </span>
                     </label>
                     <div class="input-group input-group-flat">
-                        <input id="passwd" type="password" class="form-control" autocomplete="off">
+                        <input id="password" type="password" class="form-control" autocomplete="off">
                     </div>
                 </div>
                 <div class="mb-2">
@@ -44,7 +44,7 @@
                     </div>
                 </div>
                 <div class="form-footer">
-                    <button id="login" class="btn btn-primary w-100"
+                    <button class="btn btn-primary w-100"
                             hx-post="/auth/login" hx-swap="none" hx-vals='js:{
                                 {if $public_setting['enable_login_captcha']}
                                     {if $public_setting['captcha_provider'] === 'turnstile'}
@@ -55,7 +55,7 @@
                                     {/if}
                                 {/if}
                                 email: document.getElementById("email").value,
-                                passwd: document.getElementById("passwd").value,
+                                password: document.getElementById("password").value,
                                 mfa_code: document.getElementById("mfa_code").value,
                                 remember_me: document.getElementById("remember_me").checked,
                              }'>

+ 5 - 5
resources/views/tabler/auth/register.tpl

@@ -20,12 +20,12 @@
                     </div>
                     <div class="mb-3">
                         <div class="input-group input-group-flat">
-                            <input id="passwd" type="password" class="form-control" placeholder="登录密码">
+                            <input id="password" type="password" class="form-control" placeholder="登录密码">
                         </div>
                     </div>
                     <div class="mb-3">
                         <div class="input-group input-group-flat">
-                            <input id="repasswd" type="password" class="form-control" placeholder="重复登录密码">
+                            <input id="confirm_password" type="password" class="form-control" placeholder="重复登录密码">
                         </div>
                     </div>
                     {if $public_setting['reg_mode'] !== 'close' }
@@ -65,7 +65,7 @@
                         </div>
                     </div>
                     <div class="form-footer">
-                        <button id="register" class="btn btn-primary w-100"
+                        <button class="btn btn-primary w-100"
                                 hx-post="/auth/register" hx-swap="none" hx-vals='js:{
                                     {if $public_setting['reg_email_verify']}
                                         emailcode: document.getElementById("emailcode").value,
@@ -80,8 +80,8 @@
                                     {/if}
                                     name: document.getElementById("name").value,
                                     email: document.getElementById("email").value,
-                                    passwd: document.getElementById("passwd").value,
-                                    repasswd: document.getElementById("repasswd").value,
+                                    password: document.getElementById("password").value,
+                                    confirm_password: document.getElementById("confirm_password").value,
                                     invite_code: document.getElementById("invite_code").value,
                                     tos: document.getElementById("tos").checked,
                                  }'>

+ 3 - 3
resources/views/tabler/password/token.tpl

@@ -17,14 +17,14 @@
                 </div>
                 <div class="mb-3">
                     <label class="form-label">再次输入新密码</label>
-                    <input id="repasswd" type="password" class="form-control" placeholder="请再次输入新密码">
+                    <input id="confirm_password" type="password" class="form-control" placeholder="请再次输入新密码">
                 </div>
                 <div class="form-footer">
-                    <button id="reset" class="btn btn-primary w-100"
+                    <button class="btn btn-primary w-100"
                             hx-post="{ location.pathname }" hx-swap="none"
                             hx-vals='js:{
                             password: document.getElementById("password").value,
-                            repasswd: document.getElementById("repasswd").value, }'>
+                            confirm_password: document.getElementById("confirm_password").value, }'>
                         <i class="ti ti-key icon"></i>
                         重置
                     </button>

+ 24 - 24
resources/views/tabler/user/edit.tpl

@@ -76,12 +76,12 @@
                                                 <div class="card-footer">
                                                     <div class="d-flex">
                                                         {if $public_setting['reg_email_verify'] && $config['enable_change_email']}
-                                                            <button id="email-verify" class="btn btn-link"
+                                                            <button class="btn btn-link"
                                                                     hx-post="/user/send" hx-swap="none"
                                                                     hx-vals='js:{ email: document.getElementById("newemail").value }'>
                                                                 获取验证码
                                                             </button>
-                                                            <button id="modify-email" class="btn btn-primary ms-auto"
+                                                            <button class="btn btn-primary ms-auto"
                                                                     hx-post="/user/email" hx-swap="none"
                                                                     hx-vals='js:{
                                                                         newemail: document.getElementById("new-email").value,
@@ -90,13 +90,13 @@
                                                                 修改
                                                             </button>
                                                         {elseif $config['enable_change_email']}
-                                                            <button id="modify-email" class="btn btn-primary ms-auto"
+                                                            <button class="btn btn-primary ms-auto"
                                                                     hx-post="/user/email" hx-swap="none"
                                                                     hx-vals='js:{ newemail: document.getElementById("new-email").value }'>
                                                                 修改
                                                             </button>
                                                         {else}
-                                                            <button id="modify-email" class="btn btn-primary ms-auto"
+                                                            <button class="btn btn-primary ms-auto"
                                                                     disabled>不允许修改
                                                             </button>
                                                         {/if}
@@ -116,7 +116,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="modify-username" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                            hx-post="/user/username" hx-swap="none"
                                                            hx-vals='js:{ newusername: document.getElementById("new-username").value }'>
                                                             修改
@@ -174,7 +174,7 @@
                                                 {if $user->im_type !== 0}
                                                     <div class="card-footer">
                                                         <div class="d-flex">
-                                                            <button id="unbind-im" class="btn btn-red ms-auto"
+                                                            <button class="btn btn-red ms-auto"
                                                                     hx-post="/user/unbind_im" hx-swap="none">
                                                                 解绑
                                                             </button>
@@ -238,16 +238,16 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="reset-2fa" class="btn btn-link"
+                                                        <button class="btn btn-link"
                                                                 hx-post="/user/ga_reset" hx-swap="none" >
                                                             重置
                                                         </button>
-                                                        <button id="test-2fa" class="btn btn-link"
+                                                        <button class="btn btn-link"
                                                                 hx-post="/user/ga_check" hx-swap="none"
                                                                 hx-vals='js:{ code: document.getElementById("ga-test-code").value }'>
                                                             测试
                                                         </button>
-                                                        <button id="save-2fa" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                                 hx-post="/user/ga_set" hx-swap="none"
                                                                 hx-vals='js:{ enable: document.getElementById("ga-enable").value }'>
                                                             设置
@@ -268,14 +268,14 @@
                                                     </div>
                                                     <div class="mb-3">
                                                         <form>
-                                                            <input id="new-password" type="password"
+                                                            <input id="new_password" type="password"
                                                                    class="form-control" placeholder="输入新密码"
                                                                    autocomplete="off">
                                                         </form>
                                                     </div>
                                                     <div class="mb-3">
                                                         <form>
-                                                            <input id="repeat-new-password" type="password"
+                                                            <input id="confirm_new_password" type="password"
                                                                    class="form-control" placeholder="再次输入新密码"
                                                                    autocomplete="off">
                                                         </form>
@@ -283,12 +283,12 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="modify-login-passwd" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                                 hx-post="/user/password" hx-swap="none"
                                                                 hx-vals='js:{
-                                                                    pwd: document.getElementById("new-password").value,
-                                                                    repwd: document.getElementById("repeat-new-password").value,
-                                                                    oldpwd: document.getElementById("password").value
+                                                                    new_password: document.getElementById("new_password").value,
+                                                                    confirm_new_password: document.getElementById("confirm_new_password").value,
+                                                                    password: document.getElementById("password").value
                                                                 }'>
                                                             修改
                                                         </button>
@@ -319,7 +319,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="modify-user-method" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                                 hx-post="/user/method" hx-swap="none"
                                                                 hx-vals='js:{ method: document.getElementById("user-method").value }'>
                                                             修改
@@ -337,7 +337,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="reset-sub-url" class="btn btn-primary ms-auto bg-red"
+                                                        <button class="btn btn-primary ms-auto bg-red"
                                                                 hx-post="/user/url_reset" hx-swap="none">
                                                             重置
                                                         </button>
@@ -355,7 +355,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="reset-passwd" class="btn btn-primary ms-auto bg-red"
+                                                        <button class="btn btn-primary ms-auto bg-red"
                                                                 hx-post="/user/passwd_reset" hx-swap="none">
                                                             重置
                                                         </button>
@@ -390,7 +390,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="modify-daily-mail" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                                 hx-post="/user/daily_mail" hx-swap="none"
                                                                 hx-vals='js:{ mail: document.getElementById("daily-mail").value }'>
                                                             修改
@@ -419,7 +419,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="modify-contact-method" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                                 hx-post="/user/contact_method" hx-swap="none"
                                                                 hx-vals='js:{ contact: document.getElementById("contact-method").value }'>
                                                             修改
@@ -444,7 +444,7 @@
                                                 </div>
                                                 <div class="card-footer">
                                                     <div class="d-flex">
-                                                        <button id="modify-user-theme" class="btn btn-primary ms-auto"
+                                                        <button class="btn btn-primary ms-auto"
                                                                 hx-post="/user/theme" hx-swap="none"
                                                                 hx-vals='js:{ theme: document.getElementById("user-theme").value }'>
                                                             修改
@@ -498,7 +498,7 @@
                         </div>
                         <div class="py-3">
                             <form>
-                                <input id="confirm-passwd" type="password" class="form-control"
+                                <input id="confirm_kill_password" type="password" class="form-control"
                                        placeholder="输入登录密码" autocomplete="off">
                             </form>
                         </div>
@@ -512,9 +512,9 @@
                                     </button>
                                 </div>
                                 <div class="col">
-                                    <button href="#" id="confirm-kill" class="btn btn-danger w-100" data-bs-dismiss="modal"
+                                    <button href="#" class="btn btn-danger w-100" data-bs-dismiss="modal"
                                             hx-post="/user/kill" hx-swap="none"
-                                            hx-vals='js:{ passwd: document.getElementById("confirm-passwd").value }'>
+                                            hx-vals='js:{ password: document.getElementById("confirm_kill_password").value }'>
                                         确认
                                     </button>
                                 </div>

+ 19 - 3
src/Command/Tool.php

@@ -45,7 +45,8 @@ final class Tool extends Command
 │ ├─ resetNodeBandwidth      - 重置所有节点流量
 │ ├─ resetPort               - 重置所有用户端口
 │ ├─ resetBandwidth          - 重置所有用户流量
-│ ├─ resetPassword           - 重置所有用户密码
+│ ├─ resetPassword           - 重置所有用户登录密码
+│ ├─ resetPasswd             - 重置所有用户连接密码
 │ ├─ clearSubToken           - 清除用户 Sub Token
 │ ├─ generateUUID            - 为所有用户生成新的 UUID
 │ ├─ generateGa              - 为所有用户生成新的 Ga Secret
@@ -240,7 +241,7 @@ EOL;
     }
 
     /**
-     * 重置所有用户密码
+     * 重置所有用户登录密码
      */
     public function resetPassword(): void
     {
@@ -251,7 +252,22 @@ EOL;
             $user->save();
         }
 
-        echo '已重置所有用户密码' . PHP_EOL;
+        echo '已重置所有用户登录密码' . PHP_EOL;
+    }
+
+    /**
+     * 重置所有用户连接密码
+     */
+    public function resetPasswd(): void
+    {
+        $users = ModelsUser::all();
+
+        foreach ($users as $user) {
+            $user->passwd = Tools::genRandomChar(16);
+            $user->save();
+        }
+
+        echo '已重置所有用户连接密码' . PHP_EOL;
     }
 
     /**

+ 0 - 1
src/Controllers/Admin/UserController.php

@@ -201,7 +201,6 @@ final class UserController extends BaseController
         $user->node_speedlimit = $request->getParam('node_speedlimit');
         $user->node_iplimit = $request->getParam('node_iplimit');
         $user->port = $request->getParam('port');
-        $user->passwd = $request->getParam('passwd');
         $user->method = $request->getParam('method');
         $user->forbidden_ip = str_replace(PHP_EOL, ',', $request->getParam('forbidden_ip'));
         $user->forbidden_port = str_replace(PHP_EOL, ',', $request->getParam('forbidden_port'));

+ 17 - 17
src/Controllers/AuthController.php

@@ -63,7 +63,7 @@ final class AuthController extends BaseController
         }
 
         $mfa_code = $this->antiXss->xss_clean($request->getParam('mfa_code'));
-        $passwd = $request->getParam('passwd');
+        $password = $request->getParam('password');
         $rememberMe = $request->getParam('remember_me') === 'true' ? 1 : 0;
         $email = strtolower(trim($this->antiXss->xss_clean($request->getParam('email'))));
         $redir = $this->antiXss->xss_clean(Cookie::get('redir')) ?? '/user';
@@ -79,7 +79,7 @@ final class AuthController extends BaseController
             ]);
         }
 
-        if (! Hash::checkPassword($user->pass, $passwd)) {
+        if (! Hash::checkPassword($user->pass, $password)) {
             $loginIp->collectLoginIP($_SERVER['REMOTE_ADDR'], 1, $user->id);
 
             return $response->withJson([
@@ -198,7 +198,7 @@ final class AuthController extends BaseController
         Response $response,
         $name,
         $email,
-        $passwd,
+        $password,
         $invite_code,
         $imtype,
         $imvalue,
@@ -213,7 +213,7 @@ final class AuthController extends BaseController
         $user->user_name = $name;
         $user->email = $email;
         $user->remark = '';
-        $user->pass = Hash::passwordHash($passwd);
+        $user->pass = Hash::passwordHash($password);
         $user->passwd = Tools::genRandomChar(16);
         $user->uuid = Uuid::uuid4();
         $user->api_token = Uuid::uuid4();
@@ -298,14 +298,22 @@ final class AuthController extends BaseController
         $tos = $request->getParam('tos') === 'true' ? 1 : 0;
         $email = strtolower(trim($this->antiXss->xss_clean($request->getParam('email'))));
         $name = $this->antiXss->xss_clean($request->getParam('name'));
-        $passwd = $request->getParam('passwd');
-        $repasswd = $request->getParam('repasswd');
+        $password = $request->getParam('password');
+        $confirm_password = $request->getParam('confirm_password');
         $invite_code = $this->antiXss->xss_clean(trim($request->getParam('invite_code')));
-        // Check TOS agreement
+
         if (! $tos) {
             return ResponseHelper::error($response, '请同意服务条款');
         }
-        // Check Invite Code
+
+        if (strlen($password) < 8) {
+            return ResponseHelper::error($response, '密码请大于8位');
+        }
+
+        if ($password !== $confirm_password) {
+            return ResponseHelper::error($response, '两次密码输入不符');
+        }
+
         if ($invite_code === '' && Config::obtain('reg_mode') === 'invite') {
             return ResponseHelper::error($response, '邀请码不能为空');
         }
@@ -339,14 +347,6 @@ final class AuthController extends BaseController
         if ($user !== null) {
             return ResponseHelper::error($response, '邮箱已经被注册了');
         }
-        // check pwd length
-        if (strlen($passwd) < 8) {
-            return ResponseHelper::error($response, '密码请大于8位');
-        }
-        // check pwd re
-        if ($passwd !== $repasswd) {
-            return ResponseHelper::error($response, '两次密码输入不符');
-        }
 
         if (Config::obtain('reg_email_verify')) {
             $redis = (new Cache())->initRedis();
@@ -360,7 +360,7 @@ final class AuthController extends BaseController
             $redis->del('email_verify:' . $email_verify_code);
         }
 
-        return $this->registerHelper($response, $name, $email, $passwd, $invite_code, $imtype, $imvalue, 0, 0);
+        return $this->registerHelper($response, $name, $email, $password, $invite_code, $imtype, $imvalue, 0, 0);
     }
 
     public function logout(ServerRequest $request, Response $response, $next): Response

+ 4 - 4
src/Controllers/PasswordController.php

@@ -63,13 +63,13 @@ final class PasswordController extends BaseController
         }
 
         $user = (new User())->where('email', $email)->first();
-        $msg = '如果你的账户存在于我们的数据库中,那么重置密码的链接将会发送到你账户所对应的邮箱';
+        $msg = '如果你的账户存在于我们的数据库中,那么重置密码的链接将会发送到你账户所对应的邮箱';
 
         if ($user !== null) {
             try {
                 Password::sendResetEmail($email);
             } catch (ClientExceptionInterface|RedisException $e) {
-                $msg = '邮件发送失败,请联系网站管理员。';
+                $msg = '邮件发送失败';
             }
         }
 
@@ -101,9 +101,9 @@ final class PasswordController extends BaseController
     {
         $token = $this->antiXss->xss_clean($args['token']);
         $password = $request->getParam('password');
-        $repasswd = $request->getParam('repasswd');
+        $confirm_password = $request->getParam('confirm_password');
 
-        if ($password !== $repasswd) {
+        if ($password !== $confirm_password) {
             return ResponseHelper::error($response, '两次输入不符合');
         }
 

+ 13 - 15
src/Controllers/User/InfoController.php

@@ -144,28 +144,30 @@ final class InfoController extends BaseController
 
     public function updatePassword(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
-        $oldpwd = $request->getParam('oldpwd');
-        $pwd = $request->getParam('pwd');
-        $repwd = $request->getParam('repwd');
+        $password = $request->getParam('password');
+        $new_password = $request->getParam('new_password');
+        $confirm_new_password = $request->getParam('confirm_new_password');
         $user = $this->user;
 
-        if ($oldpwd === '' || $pwd === '' || $repwd === '') {
+        if ($password === '' || $new_password === '' || $confirm_new_password === '') {
             return ResponseHelper::error($response, '密码不能为空');
         }
 
-        if (! Hash::checkPassword($user->pass, $oldpwd)) {
+        if (! Hash::checkPassword($user->pass, $password)) {
             return ResponseHelper::error($response, '旧密码错误');
         }
 
-        if ($pwd !== $repwd) {
+        if ($new_password !== $confirm_new_password) {
             return ResponseHelper::error($response, '两次输入不符合');
         }
 
-        if (strlen($pwd) < 8) {
+        if (strlen($new_password) < 8) {
             return ResponseHelper::error($response, '密码太短啦');
         }
 
-        if (! $user->updatePassword($pwd)) {
+        $user->pass = Hash::passwordHash($new_password);
+
+        if (! $user->save()) {
             return ResponseHelper::error($response, '修改失败');
         }
 
@@ -312,13 +314,9 @@ final class InfoController extends BaseController
     public function sendToGulag(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
         $user = $this->user;
-        $passwd = $request->getParam('passwd');
-
-        if ($passwd === '') {
-            return ResponseHelper::error($response, '密码不能为空');
-        }
+        $password = $request->getParam('password');
 
-        if (! Hash::checkPassword($user->pass, $passwd)) {
+        if ($password === '' || ! Hash::checkPassword($user->pass, $password)) {
             return ResponseHelper::error($response, '密码错误');
         }
 
@@ -328,7 +326,7 @@ final class InfoController extends BaseController
 
             return $response->withHeader('HX-Refresh', 'true')->withJson([
                 'ret' => 1,
-                'msg' => '你的帐号已被送去古拉格劳动改造,再见',
+                'msg' => '你将被送去古拉格接受劳动改造,再见',
             ]);
         }
 

+ 5 - 5
src/Controllers/WebAPI/UserController.php

@@ -110,13 +110,13 @@ final class UserController extends BaseController
 
             if ($node->sort === 1) {
                 $method = json_decode($node->custom_config)->method ?? '2022-blake3-aes-128-gcm';
+                $user_pk = Tools::genSs2022UserPk($user_raw->passwd, $method);
 
-                $pk_len = match ($method) {
-                    '2022-blake3-aes-128-gcm' => 16,
-                    default => 32,
-                };
+                if (! $user_pk) {
+                    continue;
+                }
 
-                $user_raw->passwd = Tools::genSs2022UserPk($user_raw->passwd, $pk_len);
+                $user_raw->passwd = $user_pk;
             }
 
             foreach ($keys_unset as $key) {

+ 0 - 10
src/Models/Model.php

@@ -10,14 +10,4 @@ abstract class Model extends EloquentModel
 {
     public $timestamps = false;
     protected $guarded = [];
-
-    /**
-     * 获取表名
-     */
-    public static function getTableName(): string
-    {
-        $class = static::class;
-
-        return (new $class())->getTable();
-    }
 }

+ 1 - 0
src/Models/Node.php

@@ -78,6 +78,7 @@ final class Node extends Model
             0 => 'Shadowsocks',
             1 => 'Shadowsocks2022',
             2 => 'TUIC',
+            3 => 'WireGuard',
             11 => 'Vmess',
             14 => 'Trojan',
             default => '未知',

+ 0 - 11
src/Models/User.php

@@ -5,7 +5,6 @@ declare(strict_types=1);
 namespace App\Models;
 
 use App\Services\IM;
-use App\Utils\Hash;
 use App\Utils\Tools;
 use GuzzleHttp\Exception\GuzzleException;
 use Illuminate\Database\Query\Builder;
@@ -135,16 +134,6 @@ final class User extends Model
         return $this->last_check_in_time === 0 ? '从未签到' : Tools::toDateTime($this->last_check_in_time);
     }
 
-    /**
-     * 更新密码
-     */
-    public function updatePassword(string $pwd): bool
-    {
-        $this->pass = Hash::passwordHash($pwd);
-
-        return $this->save();
-    }
-
     /**
      * 生成新的 API Token
      */

+ 8 - 6
src/Services/Subscribe/Clash.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Services\Subscribe;
 
 use App\Services\Subscribe;
+use App\Utils\Tools;
 use function array_merge;
 use function json_decode;
 use function yaml_emit;
@@ -47,22 +48,23 @@ final class Clash extends Base
                     $ss_2022_port = $node_custom_config['offset_port_user'] ??
                         ($node_custom_config['offset_port_node'] ?? 443);
                     $method = $node_custom_config['method'] ?? '2022-blake3-aes-128-gcm';
+                    $user_pk = Tools::genSs2022UserPk($user->passwd, $method);
 
-                    $pk_len = match ($method) {
-                        '2022-blake3-aes-128-gcm' => 16,
-                        default => 32,
-                    };
+                    if (! $user_pk) {
+                        $node = [];
+                        break;
+                    }
 
-                    $user_pk = $user->getSs2022Pk($pk_len);
                     // Clash 特定配置
                     $udp = $node_custom_config['udp'] ?? true;
+                    $server_key = $node_custom_config['server_key'] ?? '';
 
                     $node = [
                         'name' => $node_raw->name,
                         'type' => 'ss',
                         'server' => $node_raw->server,
                         'port' => (int) $ss_2022_port,
-                        'password' => $user_pk,
+                        'password' => $server_key === '' ? $user_pk : $server_key . ':' .$user_pk,
                         'cipher' => $method,
                         'udp' => (bool) $udp,
                     ];

+ 6 - 5
src/Services/Subscribe/SingBox.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Services\Subscribe;
 
 use App\Services\Subscribe;
+use App\Utils\Tools;
 use function array_filter;
 use function array_merge;
 use function json_decode;
@@ -37,13 +38,13 @@ final class SingBox extends Base
                     $ss_2022_port = $node_custom_config['offset_port_user'] ??
                         ($node_custom_config['offset_port_node'] ?? 443);
                     $method = $node_custom_config['method'] ?? '2022-blake3-aes-128-gcm';
+                    $user_pk = Tools::genSs2022UserPk($user->passwd, $method);
 
-                    $pk_len = match ($method) {
-                        '2022-blake3-aes-128-gcm' => 16,
-                        default => 32,
-                    };
+                    if (! $user_pk) {
+                        $node = [];
+                        break;
+                    }
 
-                    $user_pk = $user->getSs2022Pk($pk_len);
                     $server_key = $node_custom_config['server_key'] ?? '';
 
                     $node = [

+ 8 - 6
src/Services/Subscribe/V2RayJson.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Services\Subscribe;
 
 use App\Services\Subscribe;
+use App\Utils\Tools;
 use function array_filter;
 use function array_merge;
 use function json_decode;
@@ -38,13 +39,14 @@ final class V2RayJson extends Base
                 case 1:
                     $ss_2022_port = $node_custom_config['offset_port_user'] ?? ($node_custom_config['offset_port_node'] ?? 443);
                     $method = $node_custom_config['method'] ?? '2022-blake3-aes-128-gcm';
+                    $user_pk = Tools::genSs2022UserPk($user->passwd, $method);
 
-                    $pk_len = match ($method) {
-                        '2022-blake3-aes-128-gcm' => 16,
-                        default => 32,
-                    };
+                    if (! $user_pk) {
+                        $node = [];
+                        break;
+                    }
 
-                    $user_pk = $user->getSs2022Pk($pk_len);
+                    $server_key = $node_custom_config['server_key'] ?? '';
 
                     $node = [
                         'protocol' => 'shadowsocks2022',
@@ -52,7 +54,7 @@ final class V2RayJson extends Base
                             'address' => $node_raw->server,
                             'port' => (int) $ss_2022_port,
                             'method' => $user->method,
-                            'psk' => $user_pk,
+                            'psk' => $server_key === '' ? $user_pk : $server_key . ':' .$user_pk,
                         ],
                         'tag' => $node_raw->name,
                     ];

+ 0 - 7
src/Utils/Hash.php

@@ -6,7 +6,6 @@ namespace App\Utils;
 
 use function hash;
 use function in_array;
-use function md5;
 use function password_hash;
 use function password_verify;
 use function substr;
@@ -45,7 +44,6 @@ final class Hash
         $method = $_ENV['pwdMethod'];
 
         return match ($method) {
-            'md5' => self::md5WithSalt($pass),
             'sha256' => self::sha256WithSalt($pass),
             'sha3' => self::sha3WithSalt($pass),
             'argon2i' => password_hash($pass, PASSWORD_ARGON2I),
@@ -54,11 +52,6 @@ final class Hash
         };
     }
 
-    public static function md5WithSalt($pwd): string
-    {
-        return md5($pwd . $_ENV['salt']);
-    }
-
     public static function sha256WithSalt($pwd): string
     {
         return hash('sha256', $pwd . $_ENV['salt']);

+ 17 - 6
src/Utils/Tools.php

@@ -189,14 +189,25 @@ final class Tools
         return bin2hex(openssl_random_pseudo_bytes($length / 2));
     }
 
-    public static function genSs2022UserPk($passwd, $len): string
+    public static function genSs2022UserPk(string $passwd, string $method): string|false
     {
-        $passwd_hash = hash('sha256', $passwd);
+        $ss2022_methods = [
+            '2022-blake3-aes-128-gcm',
+            '2022-blake3-aes-256-gcm',
+            '2022-blake3-chacha8-poly1305',
+            '2022-blake3-chacha12-poly1305',
+            '2022-blake3-chacha20-poly1305',
+        ];
+
+        if (! in_array($method, $ss2022_methods)) {
+            return false;
+        }
+
+        $passwd_hash = hash('sha3-256', $passwd);
 
-        $pk = match ($len) {
-            16 => mb_strcut($passwd_hash, 0, 16),
-            32 => mb_strcut($passwd_hash, 0, 32),
-            default => $passwd_hash,
+        $pk = match ($method) {
+            '2022-blake3-aes-128-gcm' => mb_strcut($passwd_hash, 0, 16),
+            default => mb_strcut($passwd_hash, 0, 32),
         };
 
         return base64_encode($pk);

+ 24 - 10
tests/App/Utils/HashTest.php

@@ -16,10 +16,11 @@ class HashTest extends TestCase
     {
         $_ENV['key'] = 'cookie_key';
         $passHash = 'password';
-        $expire_in = '1 hour';
+        $expire_in = 69420;
         $result = Hash::cookieHash($passHash, $expire_in);
         $this->assertIsString($result);
         $this->assertEquals(45, strlen($result));
+        $this->assertEquals('e91053c4a7d6cc7fa5eb900b1ad96df484483ceace12a', $result);
     }
 
     /**
@@ -29,11 +30,12 @@ class HashTest extends TestCase
     {
         $_ENV['key'] = 'cookie_key';
         $ip = '192.168.0.1';
-        $uid = 'user_id';
-        $expire_in = '1 hour';
+        $uid = 69;
+        $expire_in = 69420;
         $result = Hash::ipHash($ip, $uid, $expire_in);
         $this->assertIsString($result);
         $this->assertEquals(45, strlen($result));
+        $this->assertEquals('522b51095b778f9f107153f75be554be1f8a8f2c1f4b4', $result);
     }
 
     /**
@@ -43,17 +45,17 @@ class HashTest extends TestCase
     {
         $_ENV['key'] = 'cookie_key';
         $device = 'Firefox/119.0';
-        $uid = 'user_id';
-        $expire_in = '1 hour';
+        $uid = 69;
+        $expire_in = 69420;
         $result = Hash::deviceHash($device, $uid, $expire_in);
         $this->assertIsString($result);
         $this->assertEquals(45, strlen($result));
+        $this->assertEquals('1fd5a37cc8769c01a49f6eb9c167dc6ee6cc842913dba', $result);
     }
 
     /**
      * @covers App\Utils\Hash::checkPassword
      * @covers App\Utils\Hash::passwordHash
-     * @covers App\Utils\Hash::md5WithSalt
      * @covers App\Utils\Hash::sha256WithSalt
      * @covers App\Utils\Hash::sha3WithSalt
      */
@@ -65,9 +67,21 @@ class HashTest extends TestCase
         $hashedPassword = Hash::passwordHash($password);
         $this->assertTrue(Hash::checkPassword($hashedPassword, $password));
         $this->assertFalse(Hash::checkPassword($hashedPassword, 'wrong_password'));
-        $this->assertIsString(Hash::passwordHash($password));
-        $this->assertIsString(Hash::md5WithSalt($password));
-        $this->assertIsString(Hash::sha256WithSalt($password));
-        $this->assertIsString(Hash::sha3WithSalt($password));
+        $_ENV['pwdMethod'] = 'argon2i';
+        $hashedPassword = Hash::passwordHash($password);
+        $this->assertTrue(Hash::checkPassword($hashedPassword, $password));
+        $this->assertFalse(Hash::checkPassword($hashedPassword, 'wrong_password'));
+        $_ENV['pwdMethod'] = 'argon2id';
+        $hashedPassword = Hash::passwordHash($password);
+        $this->assertTrue(Hash::checkPassword($hashedPassword, $password));
+        $this->assertFalse(Hash::checkPassword($hashedPassword, 'wrong_password'));
+        $_ENV['pwdMethod'] = 'sha256';
+        $hashedPassword = Hash::passwordHash($password);
+        $this->assertTrue(Hash::checkPassword($hashedPassword, $password));
+        $this->assertFalse(Hash::checkPassword($hashedPassword, 'wrong_password'));
+        $_ENV['pwdMethod'] = 'sha3';
+        $hashedPassword = Hash::passwordHash($password);
+        $this->assertTrue(Hash::checkPassword($hashedPassword, $password));
+        $this->assertFalse(Hash::checkPassword($hashedPassword, 'wrong_password'));
     }
 }

+ 10 - 3
tests/App/Utils/ToolsTest.php

@@ -119,10 +119,17 @@ class ToolsTest extends TestCase
     public function testGenSs2022UserPk()
     {
         $passwd = 'password';
-        $length = 16;
-        $pk = Tools::genSs2022UserPk($passwd, $length);
+        $method = '2022-blake3-aes-128-gcm';
+        $pk = Tools::genSs2022UserPk($passwd, $method);
         $this->assertIsString($pk);
-        $this->assertEquals('NWU4ODQ4OThkYTI4MDQ3MQ==', $pk);
+        $this->assertEquals('YzAwNjdkNGFmNGU4N2YwMA==', $pk);
+        $method = '2022-blake3-aes-256-gcm';
+        $pk = Tools::genSs2022UserPk($passwd, $method);
+        $this->assertIsString($pk);
+        $this->assertEquals('YzAwNjdkNGFmNGU4N2YwMGRiYWM2M2I2MTU2ODI4MjM=', $pk);
+        $method = 'bomb_three_gorges_dam';
+        $pk = Tools::genSs2022UserPk($passwd, $method);
+        $this->assertFalse($pk);
     }
 
     /**