将用户管理操作接入职务权限体系
This commit is contained in:
@@ -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('冻结用户');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user