chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
namespace addon\mqttbroker\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;
use ywxapp\service\AddonService;
use addon\mqttbroker\service\Auth;
/**
* ACL 实网决策验证:用真实 DB 规则校验 Auth::checkAcl 的放行/拒绝逻辑。
* php think mqttbroker:acltest
* 验证项:deny 发布拒绝、默认放行、用户定向拒绝、超管绕过、$SYS 只读。
* 不依赖运行中的 Broker,直接复用 Broker 实际调用的 Auth 逻辑。
*/
class TestAcl extends Command
{
protected function configure()
{
$this->setName('mqttbroker:acltest')
->setDescription('验证 ACL 发布/订阅权限决策(含 deny 拒绝)');
}
protected function execute(Input $input, Output $output)
{
// 配置:开启 ACL,默认放行
$saved = [];
try { $saved = AddonService::config('mqttbroker') ?: []; } catch (\Throwable $e) {}
$config = array_merge($saved, ['acl_enabled' => '1', 'acl_default' => 'allow']);
$auth = new Auth($config);
$auth->ensureTables();
// 插入临时规则(测试后清理)
$rows = [
['target_type' => 'member', 'target' => 'alice', 'topic' => 'alice/secret', 'access' => 2, 'allow' => 0, 'sort' => 5, 'remark' => 'tmp'],
['target_type' => 'all', 'target' => '', 'topic' => 'secret/#', 'access' => 2, 'allow' => 0, 'sort' => 10, 'remark' => 'tmp'],
['target_type' => 'all', 'target' => '', 'topic' => 'public/#', 'access' => 3, 'allow' => 1, 'sort' => 20, 'remark' => 'tmp'],
];
$ids = [];
foreach ($rows as $r) {
$ids[] = Db::name('mqttbroker_acl')->insertGetId(array_merge($r, ['create_at' => time()]));
}
$results = [];
$chk = function (string $case, bool $got, bool $expect) use (&$results) {
$results[$case] = ['got' => $got, 'expect' => $expect, 'ok' => $got === $expect];
};
// 1) deny 发布 secret/# 被拒
$chk('deny publish secret/#', $auth->checkAcl(null, 'c1', 'secret/data', Auth::ACT_PUB), false);
// 2) 同一主题仅 deny 发布,订阅走默认放行
$chk('subscribe secret/# default-allow', $auth->checkAcl(null, 'c1', 'secret/data', Auth::ACT_SUB), true);
// 3) allow 规则 public/# 发布放行
$chk('allow publish public/info', $auth->checkAcl(null, 'c1', 'public/info', Auth::ACT_PUB), true);
// 4) 未命中规则走默认放行
$chk('default allow other/topic', $auth->checkAcl(null, 'c1', 'other/topic', Auth::ACT_PUB), true);
// 5) 用户定向 denyalice 发布 alice/secret 被拒
$chk('user alice deny publish', $auth->checkAcl('alice', 'cA', 'alice/secret', Auth::ACT_PUB), false);
// 6) alice 订阅 alice/secretuser 规则仅限发布)走默认放行
$chk('user alice subscribe (rule is pub-only)', $auth->checkAcl('alice', 'cA', 'alice/secret', Auth::ACT_SUB), true);
// 7) 超管绕过 deny
$chk('superuser bypass deny', $auth->checkAcl('root', 'cR', 'secret/data', Auth::ACT_PUB, true), true);
// 8) $SYS 只读:订阅放行、发布拒绝
$chk('$SYS subscribe allowed', $auth->checkAcl(null, 'c2', '$SYS/broker/uptime', Auth::ACT_SUB), true);
$chk('$SYS publish denied', $auth->checkAcl(null, 'c2', '$SYS/broker/uptime', Auth::ACT_PUB), false);
// 清理临时规则
if ($ids) {
Db::name('mqttbroker_acl')->whereIn('id', $ids)->delete();
}
$pass = 0;
$fail = 0;
foreach ($results as $case => $r) {
$flag = $r['ok'] ? 'PASS' : 'FAIL';
if ($r['ok']) { $pass++; } else { $fail++; }
$output->writeln("[{$flag}] {$case} (got=" . var_export($r['got'], true) . " expect=" . var_export($r['expect'], true) . ")");
}
$output->writeln("");
$output->writeln("ACL 验证结果:PASS={$pass} FAIL={$fail}");
return $fail === 0 ? 0 : 1;
}
}