将用户管理操作接入职务权限体系

This commit is contained in:
2026-04-21 18:00:02 +08:00
parent a066580014
commit b0028c515f
8 changed files with 462 additions and 85 deletions
+37
View File
@@ -215,6 +215,43 @@ class ChatControllerTest extends TestCase
$response->assertDontSee("runAdminAction('announce-message')", false);
}
/**
* 测试用户名片中的用户管理按钮会按职务权限显示。
*/
public function test_room_view_renders_only_granted_user_management_buttons(): void
{
$room = Room::create(['room_name' => 'usermenu']);
$user = $this->createUserWithPositionPermissions([
PositionPermissionRegistry::USER_WARN,
PositionPermissionRegistry::USER_MUTE,
]);
$response = $this->actingAs($user)->get(route('chat.room', $room->id));
$response->assertOk();
$response->assertSee('⚠️ 警告', false);
$response->assertSee('🔇 禁言', false);
$response->assertDontSee('🚫 踢出', false);
$response->assertDontSee('🧊 冻结', false);
}
/**
* 测试没有用户管理权限时,用户名片中不会渲染相关按钮。
*/
public function test_room_view_hides_user_management_buttons_without_permissions(): void
{
$room = Room::create(['room_name' => 'nousermenu']);
$user = $this->createUserWithPositionPermissions([]);
$response = $this->actingAs($user)->get(route('chat.room', $room->id));
$response->assertOk();
$response->assertDontSee('⚠️ 警告', false);
$response->assertDontSee('🚫 踢出', false);
$response->assertDontSee('🔇 禁言', false);
$response->assertDontSee('🧊 冻结', false);
}
/**
* 测试站长即使没有在职职务,也能看到管理菜单中的刷新全员按钮。
*/
@@ -139,7 +139,7 @@ class AdminCommandControllerTest extends TestCase
$this->assertNotNull($publicMessage);
$this->assertStringContainsString(
$admin->activePosition->position->department->name.$admin->activePosition->position->name,
$admin->activePosition->position->department->name.'·'.$admin->activePosition->position->name,
(string) $publicMessage['content']
);
$this->assertStringContainsString(
@@ -297,7 +297,7 @@ class AdminCommandControllerTest extends TestCase
'message' => "已警告 {$target->username}",
]);
$privateMessage = $this->findPrivateSystemMessage($room->id, $target->username, '管理员 <b>'.$admin->username.'</b> 警告了你');
$privateMessage = $this->findPrivateSystemMessage($room->id, $target->username, '站长</b> <b>'.$admin->username.'</b> 警告了你');
$this->assertNotNull($privateMessage);
$this->assertSame('⚠️ 收到警告', $privateMessage['toast_notification']['title'] ?? null);
@@ -336,6 +336,40 @@ class AdminCommandControllerTest extends TestCase
Queue::assertPushed(SaveMessageJob::class, 2);
}
/**
* 测试拥有警告权限的职务用户发送的文案会带上部门和职务。
*/
public function test_position_user_with_warn_permission_uses_department_and_position_in_message(): void
{
Queue::fake();
$admin = $this->createPositionedManager([
PositionPermissionRegistry::USER_WARN,
], departmentRank: 95, positionRank: 95);
$admin->load('activePosition.position.department');
$target = User::factory()->create([
'user_level' => 1,
]);
$room = Room::create([
'room_name' => '职务警告房',
]);
$response = $this->actingAs($admin)->postJson(route('command.warn'), [
'username' => $target->username,
'room_id' => $room->id,
'reason' => '请遵守秩序',
]);
$response->assertOk()->assertJson([
'status' => 'success',
]);
$identityText = $admin->activePosition->position->department->name.'·'.$admin->activePosition->position->name;
$privateMessage = $this->findPrivateSystemMessage($room->id, $target->username, "{$identityText}</b> <b>{$admin->username}</b> 警告了你");
$this->assertNotNull($privateMessage);
}
/**
* 测试踢出操作会给目标用户写入带 toast 的私聊提示。
*/
@@ -395,6 +429,91 @@ class AdminCommandControllerTest extends TestCase
Queue::assertPushed(SaveMessageJob::class, 2);
}
/**
* 测试缺少踢出权限的职务用户会被拒绝。
*/
public function test_position_user_without_kick_permission_cannot_kick_target(): void
{
$admin = $this->createPositionedManager([
PositionPermissionRegistry::USER_WARN,
]);
$target = User::factory()->create([
'user_level' => 1,
]);
$room = Room::create([
'room_name' => '无权踢人房',
]);
$response = $this->actingAs($admin)->postJson(route('command.kick'), [
'username' => $target->username,
'room_id' => $room->id,
'reason' => '测试',
]);
$response->assertStatus(403)->assertJson([
'status' => 'error',
'message' => '当前职务无权踢出用户',
]);
}
/**
* 测试不能处理部门位阶更高的目标用户。
*/
public function test_position_user_cannot_warn_target_from_higher_rank_department(): void
{
$admin = $this->createPositionedManager([
PositionPermissionRegistry::USER_WARN,
], departmentRank: 80, positionRank: 80);
$target = $this->createTargetUserWithPositionRanks(departmentRank: 90, positionRank: 70);
$room = Room::create([
'room_name' => '高部门位阶房',
]);
$response = $this->actingAs($admin)->postJson(route('command.warn'), [
'username' => $target->username,
'room_id' => $room->id,
'reason' => '测试',
]);
$response->assertStatus(403)->assertJson([
'status' => 'error',
'message' => '不能处理职务高于自己的用户',
]);
}
/**
* 测试同部门下不能处理职务位阶更高的目标用户。
*/
public function test_position_user_cannot_mute_target_with_higher_rank_in_same_department(): void
{
$department = Department::create([
'name' => '同部门位阶测试',
'rank' => 88,
'color' => '#0f766e',
'sort_order' => 1,
'description' => '同部门位阶限制测试',
]);
$admin = $this->createPositionedManager([
PositionPermissionRegistry::USER_MUTE,
], departmentRank: 88, positionRank: 60, existingDepartment: $department);
$target = $this->createTargetUserWithPositionRanks(departmentRank: 88, positionRank: 70, existingDepartment: $department);
$room = Room::create([
'room_name' => '同部门高位阶房',
]);
$response = $this->actingAs($admin)->postJson(route('command.mute'), [
'username' => $target->username,
'room_id' => $room->id,
'duration' => 10,
]);
$response->assertStatus(403)->assertJson([
'status' => 'error',
'message' => '不能处理职务高于自己的用户',
]);
}
/**
* 创建管理员命令测试共用的操作者、目标用户和房间。
*
@@ -421,15 +540,19 @@ class AdminCommandControllerTest extends TestCase
*
* @param list<string> $permissions
*/
private function createPositionedManager(array $permissions): User
{
private function createPositionedManager(
array $permissions,
int $departmentRank = 90,
int $positionRank = 90,
?Department $existingDepartment = null,
): User {
$user = User::factory()->create([
'user_level' => 90,
'user_level' => $positionRank,
]);
$department = Department::create([
$department = $existingDepartment ?? Department::create([
'name' => '命令权限部'.$user->id,
'rank' => 90,
'rank' => $departmentRank,
'color' => '#7c3aed',
'sort_order' => 1,
'description' => '聊天室命令权限测试',
@@ -439,8 +562,8 @@ class AdminCommandControllerTest extends TestCase
'department_id' => $department->id,
'name' => '命令权限职务'.$user->id,
'icon' => '🛠️',
'rank' => 90,
'level' => 90,
'rank' => $positionRank,
'level' => $positionRank,
'sort_order' => 1,
'permissions' => $permissions,
]);
@@ -457,6 +580,48 @@ class AdminCommandControllerTest extends TestCase
return $user->fresh();
}
/**
* 创建带指定部门/职务位阶的目标用户。
*/
private function createTargetUserWithPositionRanks(
int $departmentRank,
int $positionRank,
?Department $existingDepartment = null,
): User {
$user = User::factory()->create([
'user_level' => $positionRank,
]);
$department = $existingDepartment ?? Department::create([
'name' => '目标用户部门'.$user->id,
'rank' => $departmentRank,
'color' => '#1d4ed8',
'sort_order' => 1,
'description' => '目标用户位阶测试',
]);
$position = Position::create([
'department_id' => $department->id,
'name' => '目标用户职务'.$user->id,
'icon' => '🎖️',
'rank' => $positionRank,
'level' => $positionRank,
'sort_order' => 1,
'permissions' => [],
]);
UserPosition::create([
'user_id' => $user->id,
'position_id' => $position->id,
'appointed_by_user_id' => null,
'appointed_at' => now(),
'remark' => '目标用户位阶测试',
'is_active' => true,
]);
return $user->fresh();
}
/**
* 从房间消息缓存中定位目标用户收到的系统私聊提示。
*
@@ -157,6 +157,8 @@ class AdminPositionPermissionTest extends TestCase
$response->assertSee('权限管理');
$response->assertSee('设置公告');
$response->assertSee('礼包红包');
$response->assertSee('警告用户');
$response->assertSee('冻结用户');
}
/**