- Updated AGENTS.md to clarify agent account restrictions and permissions. - Implemented checks in AgentNodeAdminUserStoreController and AgentNodeRoleStoreController to restrict admin user and role creation to the agent's own node. - Enhanced validation in AdminPlayerStoreController and AdminPlayerUpdateController to enforce credit limit and rebate rate rules based on player funding mode. - Refactored various request classes to utilize shared admin account field rules for consistency. - Improved error handling in services related to credit allocation and rebate limits to ensure proper validation and messaging.
153 lines
4.3 KiB
PHP
153 lines
4.3 KiB
PHP
<?php
|
||
|
||
namespace App\Support;
|
||
|
||
use App\Models\AdminUser;
|
||
use App\Models\AgentNode;
|
||
use Illuminate\Database\Query\Builder;
|
||
|
||
/**
|
||
* 站点 + 代理子树:用于报表等 Query Builder(players 表别名)。
|
||
*/
|
||
final class AdminDataScope
|
||
{
|
||
/**
|
||
* @param Builder<mixed> $query 已 join `players as {alias}`
|
||
*/
|
||
public static function applyToPlayersAlias(
|
||
Builder $query,
|
||
?AdminUser $admin,
|
||
string $alias = 'p',
|
||
?int $requestedAgentNodeId = null,
|
||
): void {
|
||
if ($admin === null) {
|
||
return;
|
||
}
|
||
|
||
if ($admin->isSuperAdmin()) {
|
||
if ($requestedAgentNodeId !== null && $requestedAgentNodeId > 0) {
|
||
self::applyAgentNodeIdOnAlias($query, $admin, $alias, $requestedAgentNodeId);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
$codes = AdminSiteScope::accessibleSiteCodes($admin);
|
||
if ($codes !== null) {
|
||
if ($codes === []) {
|
||
$query->whereRaw('0 = 1');
|
||
|
||
return;
|
||
}
|
||
|
||
$query->whereIn($alias.'.site_code', $codes);
|
||
}
|
||
|
||
// Check if admin is a platform account (bound via admin_user_site_roles)
|
||
$accessibleSiteIds = $admin->accessibleAdminSiteIds();
|
||
if ($accessibleSiteIds !== null) {
|
||
// Platform account (site admin) - no agent node filtering needed
|
||
if ($requestedAgentNodeId !== null && $requestedAgentNodeId > 0) {
|
||
self::applyAgentNodeIdOnAlias($query, $admin, $alias, $requestedAgentNodeId);
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Agent account (bound via agent node)
|
||
$actor = AdminAgentScope::primaryAgentNode($admin);
|
||
if ($actor === null) {
|
||
$query->whereRaw('0 = 1');
|
||
|
||
return;
|
||
}
|
||
|
||
if (! \Illuminate\Support\Facades\Schema::hasColumn('players', 'agent_node_id')) {
|
||
return;
|
||
}
|
||
|
||
$subtreeIds = AgentNode::query()
|
||
->where('path', 'like', $actor->path.'%')
|
||
->pluck('id')
|
||
->all();
|
||
|
||
if ($subtreeIds === []) {
|
||
$query->whereRaw('0 = 1');
|
||
|
||
return;
|
||
}
|
||
|
||
$query->whereIn($alias.'.agent_node_id', $subtreeIds);
|
||
|
||
if ($requestedAgentNodeId !== null && $requestedAgentNodeId > 0) {
|
||
self::applyAgentNodeIdOnAlias($query, $admin, $alias, $requestedAgentNodeId);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param Builder<mixed> $query
|
||
*/
|
||
private static function applyAgentNodeIdOnAlias(
|
||
Builder $query,
|
||
AdminUser $admin,
|
||
string $alias,
|
||
int $agentNodeId,
|
||
): void {
|
||
$node = AgentNode::query()->find($agentNodeId);
|
||
if ($node === null || ! AdminAgentScope::nodeVisibleTo($admin, $node)) {
|
||
$query->whereRaw('0 = 1');
|
||
|
||
return;
|
||
}
|
||
|
||
$subtreeIds = AgentNode::query()
|
||
->where('path', 'like', $node->path.'%')
|
||
->pluck('id')
|
||
->all();
|
||
|
||
if ($subtreeIds === []) {
|
||
$query->whereRaw('0 = 1');
|
||
|
||
return;
|
||
}
|
||
|
||
$query->whereIn($alias.'.agent_node_id', $subtreeIds);
|
||
}
|
||
|
||
/**
|
||
* Eloquent 模型经 player 关联做站点 + 代理子树过滤。
|
||
*
|
||
* @param \Illuminate\Database\Eloquent\Builder<mixed> $query
|
||
*/
|
||
public static function applyEloquentViaPlayer(
|
||
\Illuminate\Database\Eloquent\Builder $query,
|
||
AdminUser $admin,
|
||
string $relation = 'player',
|
||
): void {
|
||
if ($admin->isSuperAdmin()) {
|
||
return;
|
||
}
|
||
|
||
$query->whereHas($relation, static function (\Illuminate\Database\Eloquent\Builder $playerQuery) use ($admin): void {
|
||
AdminSiteScope::applyToPlayerQuery($playerQuery, $admin);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 约束 ticket_orders(别名 o)仅统计可见玩家。
|
||
*
|
||
* @param Builder<mixed> $query
|
||
*/
|
||
public static function applyToTicketOrdersViaPlayer(Builder $query, ?AdminUser $admin, string $orderAlias = 'o'): void
|
||
{
|
||
if ($admin === null || $admin->isSuperAdmin()) {
|
||
return;
|
||
}
|
||
|
||
$query->whereExists(function (Builder $sub) use ($admin, $orderAlias): void {
|
||
$sub->from('players as scope_p')
|
||
->whereColumn('scope_p.id', $orderAlias.'.player_id');
|
||
self::applyToPlayersAlias($sub, $admin, 'scope_p');
|
||
});
|
||
}
|
||
}
|