122 lines
6.0 KiB
PHP
122 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
$root = dirname(__DIR__, 2);
|
|
$logicPath = __DIR__ . '/../app/adminapi/logic/firstvisit/WecomPromotionLogic.php';
|
|
$customerLogicPath = __DIR__ . '/../app/adminapi/logic/firstvisit/WecomAcquisitionCustomerLogic.php';
|
|
$controllerPath = __DIR__ . '/../app/adminapi/controller/firstvisit/WecomPromotionController.php';
|
|
$operatorAccessPath = __DIR__ . '/../app/common/service/qywx/QywxPromotionOperatorAccess.php';
|
|
$authLogicPath = __DIR__ . '/../app/adminapi/logic/auth/AuthLogic.php';
|
|
$menuLogicPath = __DIR__ . '/../app/adminapi/logic/auth/MenuLogic.php';
|
|
$authMiddlewarePath = __DIR__ . '/../app/adminapi/http/middleware/AuthMiddleware.php';
|
|
$apiPath = $root . '/admin/src/api/first_visit.ts';
|
|
$viewPath = $root . '/admin/src/views/first_visit/wecom_promotion/index.vue';
|
|
$migrationPath = $root . '/server/sql/1.9.20260828/add_wecom_promotion_pool_operators.sql';
|
|
|
|
$sources = [];
|
|
foreach (compact(
|
|
'logicPath',
|
|
'customerLogicPath',
|
|
'controllerPath',
|
|
'operatorAccessPath',
|
|
'authLogicPath',
|
|
'menuLogicPath',
|
|
'authMiddlewarePath',
|
|
'apiPath',
|
|
'viewPath',
|
|
'migrationPath'
|
|
) as $name => $path) {
|
|
$source = file_get_contents($path);
|
|
if (!is_string($source)) {
|
|
throw new RuntimeException("无法读取 {$name}: {$path}");
|
|
}
|
|
$sources[$name] = $source;
|
|
}
|
|
|
|
$migration = $sources['migrationPath'];
|
|
foreach (['qywx_promotion_pool_operator', 'uk_pool_admin', 'granted_by_admin_id'] as $needle) {
|
|
if (!str_contains($migration, $needle)) {
|
|
throw new RuntimeException("共享操作人迁移缺少 {$needle}");
|
|
}
|
|
}
|
|
|
|
$logic = $sources['logicPath'];
|
|
foreach (['batchSetOperators', 'applyPoolAccessScope', 'isPoolOperator', 'can_manage_access', 'operator_options', 'clearOperatorAuthCaches'] as $needle) {
|
|
if (!str_contains($logic, $needle)) {
|
|
throw new RuntimeException("获客助手共享权限逻辑缺少 {$needle}");
|
|
}
|
|
}
|
|
$deleteStart = strpos($logic, 'public static function deletePool(');
|
|
$deleteEnd = strpos($logic, 'public static function batchSetOperators(', $deleteStart === false ? 0 : $deleteStart);
|
|
if ($deleteStart === false || $deleteEnd === false) {
|
|
throw new RuntimeException('无法定位 deletePool/batchSetOperators');
|
|
}
|
|
$deleteMethod = substr($logic, $deleteStart, $deleteEnd - $deleteStart);
|
|
if (!str_contains($deleteMethod, "assertScopedRow('qywx_promotion_pool', \$id, \$adminId, \$adminInfo, false)")) {
|
|
throw new RuntimeException('共享操作人不得永久删除分流方案');
|
|
}
|
|
if (!str_contains($deleteMethod, 'assertBasePagePermission($adminId, $adminInfo)')
|
|
|| !str_contains($deleteMethod, 'clearOperatorAuthCaches($operatorAdminIds)')) {
|
|
throw new RuntimeException('删除方案必须校验基础权限并清理共享账号权限缓存');
|
|
}
|
|
$batchStart = strpos($logic, 'public static function batchSetOperators(');
|
|
$batchEnd = strpos($logic, 'private static function isRemoteLinkAlreadyMissing(', $batchStart === false ? 0 : $batchStart);
|
|
if ($batchStart === false || $batchEnd === false) {
|
|
throw new RuntimeException('无法定位 batchSetOperators');
|
|
}
|
|
$batchMethod = substr($logic, $batchStart, $batchEnd - $batchStart);
|
|
foreach (['assertBasePagePermission($adminId, $adminInfo)', 'clearOperatorAuthCaches($operatorAdminIds)'] as $needle) {
|
|
if (!str_contains($batchMethod, $needle)) {
|
|
throw new RuntimeException("批量授权缺少安全边界 {$needle}");
|
|
}
|
|
}
|
|
if (str_contains($logic, 'promotionPagePermissionAdminIdSet')
|
|
|| str_contains($batchMethod, '尚未获得企业微信获客助手页面权限')
|
|
|| str_contains($batchMethod, '$operatorAdminId === $ownerAdminId')) {
|
|
throw new RuntimeException('批量授权仍存在预先页面权限或归属人跳过条件');
|
|
}
|
|
|
|
$operatorAccess = $sources['operatorAccessPath'];
|
|
foreach (['hasBasePagePermission', 'hasSharedPagePermission', 'hasPagePermission', 'visibleAdminIds', 'activePoolIds'] as $needle) {
|
|
if (!str_contains($operatorAccess, $needle)) {
|
|
throw new RuntimeException("共享页面权限服务缺少 {$needle}");
|
|
}
|
|
}
|
|
if (!str_contains($operatorAccess, "join('qywx_promotion_pool p', 'p.id = po.pool_id')")
|
|
|| !str_contains($operatorAccess, "whereNull('p.delete_time')")) {
|
|
throw new RuntimeException('共享页面权限未排除已删除方案');
|
|
}
|
|
|
|
if (!str_contains($sources['authLogicPath'], 'appendSharedPromotionPermission')
|
|
|| !str_contains($sources['menuLogicPath'], 'sharedPromotionMenuIds')) {
|
|
throw new RuntimeException('共享账号未动态获得页面权限或导航菜单');
|
|
}
|
|
if (!str_contains($sources['authMiddlewarePath'], "str_starts_with(\$accessUri, 'firstvisit.wecompromotion/')")
|
|
|| !str_contains($sources['authMiddlewarePath'], 'isKnownWecomPromotionAction')) {
|
|
throw new RuntimeException('获客助手子接口未统一纳入页面权限中间件');
|
|
}
|
|
|
|
if (!str_contains($sources['customerLogicPath'], 'operatorPoolIds($adminId)')
|
|
|| !str_contains($sources['customerLogicPath'], "whereOr('p.id', 'in', \$operatorPoolIds)")
|
|
|| !str_contains($sources['customerLogicPath'], 'QywxPromotionOperatorAccess::visibleAdminIds')) {
|
|
throw new RuntimeException('共享操作人尚未接入获客客户统计权限');
|
|
}
|
|
if (!str_contains($sources['controllerPath'], 'public function batchSetOperators()')) {
|
|
throw new RuntimeException('控制器缺少批量设置操作人接口');
|
|
}
|
|
if (!str_contains($sources['apiPath'], '/firstvisit.wecomPromotion/batchSetOperators')) {
|
|
throw new RuntimeException('前端 API 缺少批量设置操作人接口');
|
|
}
|
|
foreach (['批量设置访问操作', '添加操作人', '移除操作人', 'selectedPoolIds', 'can_manage_access'] as $needle) {
|
|
if (!str_contains($sources['viewPath'], $needle)) {
|
|
throw new RuntimeException("前端共享权限交互缺少 {$needle}");
|
|
}
|
|
}
|
|
if (str_contains($sources['viewPath'], '无页面权限')
|
|
|| !str_contains($sources['viewPath'], '授权后账号会自动获得本页面入口')) {
|
|
throw new RuntimeException('前端仍将预先拥有页面权限作为授权条件');
|
|
}
|
|
|
|
echo "WECOM_PROMOTION_POOL_OPERATOR_CONTRACT_OK\n";
|