update P15
This commit is contained in:
@@ -287,7 +287,7 @@ class DataScopeController extends AbstractController
|
||||
? Company::query()->whereIn('id', $company_ids)->pluck('label', 'id')->toArray()
|
||||
: [];
|
||||
$platform_names = !empty($platform_ids)
|
||||
? Platform::query()->whereIn('id', $platform_ids)->pluck('id', 'id')->toArray()
|
||||
? Platform::query()->whereIn('id', $platform_ids)->pluck('name', 'id')->toArray()
|
||||
: [];
|
||||
$store_names = !empty($store_ids)
|
||||
? Store::query()->whereIn('id', $store_ids)->pluck('label', 'id')->toArray()
|
||||
@@ -297,7 +297,7 @@ class DataScopeController extends AbstractController
|
||||
return array_map(function (array $scope) use ($company_names, $platform_names, $store_names): array {
|
||||
$name = match ($scope['scope_type']) {
|
||||
'company' => $company_names[$scope['scope_id']] ?? null,
|
||||
'platform' => isset($platform_names[$scope['scope_id']]) ? "Platform #{$scope['scope_id']}" : null,
|
||||
'platform' => $platform_names[$scope['scope_id']] ?? null,
|
||||
'store' => $store_names[$scope['scope_id']] ?? null,
|
||||
default => null,
|
||||
};
|
||||
|
||||
@@ -22,12 +22,12 @@ class UserController extends AbstractController
|
||||
/**
|
||||
* 用户列表
|
||||
*
|
||||
* 支持分页、按 username/email 模糊搜索、按 status 精确筛选
|
||||
* 支持分页、按 username/email 模糊搜索、按 status/role_id 精确筛选
|
||||
*/
|
||||
#[OA\Get(
|
||||
path: '/users',
|
||||
summary: '用户列表',
|
||||
description: '获取用户列表,支持分页、按 username/email 模糊搜索、按 status 精确筛选',
|
||||
description: '获取用户列表,支持分页、按 username/email 模糊搜索、按 status/role_id 精确筛选',
|
||||
security: [['bearerAuth' => []]],
|
||||
tags: ['Users'],
|
||||
parameters: [
|
||||
@@ -36,6 +36,7 @@ class UserController extends AbstractController
|
||||
new OA\Parameter(name: 'username', in: 'query', required: false, description: '用户名模糊搜索', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'email', in: 'query', required: false, description: '邮箱模糊搜索', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'status', in: 'query', required: false, description: '状态筛选(0=禁用,1=启用)', schema: new OA\Schema(type: 'integer', enum: [0, 1])),
|
||||
new OA\Parameter(name: 'role_id', in: 'query', required: false, description: '按角色筛选', schema: new OA\Schema(type: 'integer')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
@@ -83,6 +84,12 @@ class UserController extends AbstractController
|
||||
$query->where('status', (int) $status);
|
||||
}
|
||||
|
||||
// 按 role_id 精确筛选
|
||||
$role_id = $this->request->input('role_id');
|
||||
if ($role_id !== null && $role_id !== '') {
|
||||
$query->where('role_id', (int) $role_id);
|
||||
}
|
||||
|
||||
// 按 created_at 降序排序
|
||||
$query->orderBy('created_at', 'desc');
|
||||
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HyperfTest\Cases\Integration\User;
|
||||
|
||||
use App\Model\Platform;
|
||||
use App\Model\Role;
|
||||
use App\Model\User;
|
||||
use App\Model\UserDataScope;
|
||||
use HyperfTest\TestCase;
|
||||
use Qbhy\HyperfAuth\AuthManager;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
class DataScopeControllerTest extends TestCase
|
||||
{
|
||||
protected function getAuthToken(): string
|
||||
{
|
||||
$admin_role = $this->fetchAdminRole();
|
||||
$user = $this->fetchUser(static function ($query) use ($admin_role): void {
|
||||
$query->where('status', 1)->where('role_id', $admin_role->id);
|
||||
});
|
||||
if (!$user) {
|
||||
$this->markTestSkipped('没有可用的 administrator 用户,无法测试');
|
||||
}
|
||||
|
||||
$auth = make(AuthManager::class);
|
||||
return $auth->guard('jwt')->login($user);
|
||||
}
|
||||
|
||||
protected function fetchAdminRole(): Role
|
||||
{
|
||||
if (\Swoole\Coroutine::getCid() > 0) {
|
||||
return Role::query()->where('name', 'administrator')->firstOrFail();
|
||||
}
|
||||
|
||||
$role = null;
|
||||
\Swoole\Coroutine\run(static function () use (&$role): void {
|
||||
$role = Role::query()->where('name', 'administrator')->firstOrFail();
|
||||
});
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
protected function authHeaders(): array
|
||||
{
|
||||
return ['Authorization' => 'Bearer ' . $this->getAuthToken()];
|
||||
}
|
||||
|
||||
protected function fetchUser(?callable $callback = null): ?User
|
||||
{
|
||||
if (\Swoole\Coroutine::getCid() > 0) {
|
||||
$query = User::query();
|
||||
if ($callback !== null) {
|
||||
$callback($query);
|
||||
}
|
||||
|
||||
return $query->first();
|
||||
}
|
||||
|
||||
$user = null;
|
||||
|
||||
\Swoole\Coroutine\run(static function () use ($callback, &$user): void {
|
||||
$query = User::query();
|
||||
if ($callback !== null) {
|
||||
$callback($query);
|
||||
}
|
||||
|
||||
$user = $query->first();
|
||||
});
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在协程内创建测试用户及 platform scope 数据
|
||||
*
|
||||
* @return array{user_id: int, platform_name: string}
|
||||
*/
|
||||
protected function createUserWithPlatformScope(): array
|
||||
{
|
||||
$run = static function (): array {
|
||||
$suffix = bin2hex(random_bytes(4));
|
||||
$user = User::query()->create([
|
||||
'username' => 'scope_test_' . $suffix,
|
||||
'password' => 'Pass_' . $suffix,
|
||||
'email' => 'scope_test_' . $suffix . '@example.com',
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
$platform = Platform::query()->first();
|
||||
|
||||
UserDataScope::query()->insert([
|
||||
'user_id' => $user->id,
|
||||
'scope_type' => 'platform',
|
||||
'scope_id' => $platform->id,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
return ['user_id' => $user->id, 'platform_name' => $platform->name];
|
||||
};
|
||||
|
||||
if (\Swoole\Coroutine::getCid() > 0) {
|
||||
return $run();
|
||||
}
|
||||
|
||||
$result = null;
|
||||
\Swoole\Coroutine\run(static function () use ($run, &$result): void {
|
||||
$result = $run();
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 platform scope 返回真实平台名称(而非 "Platform #ID")
|
||||
*/
|
||||
public function test_data_scope_returns_real_platform_name(): void
|
||||
{
|
||||
$setup = $this->createUserWithPlatformScope();
|
||||
|
||||
$response = $this->get('/api/v1/users/' . $setup['user_id'] . '/data-scope', [], $this->authHeaders());
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJsonPath('code', 0);
|
||||
|
||||
$body = json_decode($response->getContent(), true);
|
||||
$scopes = $body['data']['scopes'];
|
||||
|
||||
$this->assertNotEmpty($scopes);
|
||||
|
||||
$platform_scope = null;
|
||||
foreach ($scopes as $scope) {
|
||||
if ($scope['scope_type'] === 'platform') {
|
||||
$platform_scope = $scope;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertNotNull($platform_scope, '应包含 platform 类型的 scope');
|
||||
$this->assertSame($setup['platform_name'], $platform_scope['name'], '平台名称应为真实名称,而非 "Platform #ID"');
|
||||
$this->assertStringNotContainsString('Platform #', (string) $platform_scope['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试未认证请求返回 401
|
||||
*/
|
||||
public function test_data_scope_without_token_returns_401(): void
|
||||
{
|
||||
$response = $this->get('/api/v1/users/1/data-scope');
|
||||
|
||||
$response->assertStatus(401);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试不存在的用户返回 404
|
||||
*/
|
||||
public function test_data_scope_not_found_returns_404(): void
|
||||
{
|
||||
$response = $this->get('/api/v1/users/999999/data-scope', [], $this->authHeaders());
|
||||
|
||||
$response->assertStatus(404);
|
||||
$response->assertJsonPath('code', 404);
|
||||
}
|
||||
}
|
||||
@@ -201,6 +201,31 @@ class UserControllerTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function test_list_users_filter_by_role_id(): void
|
||||
{
|
||||
$admin_role = $this->fetchAdminRole();
|
||||
|
||||
$response = $this->get('/api/v1/users', ['role_id' => $admin_role->id], $this->authHeaders());
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJsonPath('code', 0);
|
||||
|
||||
$body = json_decode($response->getContent(), true);
|
||||
$this->assertGreaterThanOrEqual(1, $body['data']['total']);
|
||||
foreach ($body['data']['items'] as $item) {
|
||||
$this->assertSame($admin_role->id, $item['role_id']);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_list_users_filter_by_role_id_empty(): void
|
||||
{
|
||||
$response = $this->get('/api/v1/users', ['role_id' => 999999], $this->authHeaders());
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJsonPath('code', 0);
|
||||
$response->assertJsonPath('data.total', 0);
|
||||
}
|
||||
|
||||
// ========== 详情接口测试 ==========
|
||||
|
||||
public function test_show_user_returns_user_data(): void
|
||||
|
||||
Reference in New Issue
Block a user