135 lines
5.2 KiB
PHP
135 lines
5.2 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\SystemSettings;
|
|
|
|
use App\Models\Auth\DingTalkBindingRequest;
|
|
use App\Models\Auth\DingTalkIdentity;
|
|
use App\Models\Auth\Role;
|
|
use App\Models\Auth\User;
|
|
use App\Utilities\SystemAccess;
|
|
use Tests\Feature\FeatureTestCase;
|
|
|
|
class DingTalkBindingsTest extends FeatureTestCase
|
|
{
|
|
public function test_super_admin_can_review_masked_pending_requests_and_bind_existing_user(): void
|
|
{
|
|
$bindingRequest = $this->pendingRequest();
|
|
|
|
$this->loginAs()
|
|
->get(route('system-settings.dingtalk-bindings.index'))
|
|
->assertOk()
|
|
->assertSeeText('钉钉账号绑定')
|
|
->assertSeeText('企***@example.test')
|
|
->assertSeeText('*******8000')
|
|
->assertDontSee('enterprise-user@example.test')
|
|
->assertDontSee('13800138000');
|
|
|
|
$this->post(route('system-settings.dingtalk-bindings.approve', $bindingRequest->id), [
|
|
'user_id' => $this->user->id,
|
|
])->assertRedirect(route('system-settings.dingtalk-bindings.index'));
|
|
|
|
$this->assertDatabaseHas('dingtalk_identities', [
|
|
'user_id' => $this->user->id,
|
|
'union_id' => 'union-pending-admin',
|
|
'bound_by' => $this->user->id,
|
|
]);
|
|
$this->assertDatabaseHas('dingtalk_binding_requests', [
|
|
'id' => $bindingRequest->id,
|
|
'status' => DingTalkBindingRequest::APPROVED,
|
|
'matched_user_id' => $this->user->id,
|
|
'reviewed_by' => $this->user->id,
|
|
]);
|
|
$this->assertDatabaseHas('dingtalk_auth_audits', [
|
|
'event' => 'binding_admin_approved',
|
|
'outcome' => 'success',
|
|
'user_id' => $this->user->id,
|
|
'actor_user_id' => $this->user->id,
|
|
]);
|
|
}
|
|
|
|
public function test_admin_can_reject_pending_request_without_creating_identity(): void
|
|
{
|
|
$bindingRequest = $this->pendingRequest();
|
|
|
|
$this->loginAs()
|
|
->post(route('system-settings.dingtalk-bindings.reject', $bindingRequest->id))
|
|
->assertRedirect(route('system-settings.dingtalk-bindings.index'));
|
|
|
|
$this->assertDatabaseHas('dingtalk_binding_requests', [
|
|
'id' => $bindingRequest->id,
|
|
'status' => DingTalkBindingRequest::REJECTED,
|
|
]);
|
|
$this->assertDatabaseMissing('dingtalk_identities', ['union_id' => 'union-pending-admin']);
|
|
$this->assertDatabaseHas('dingtalk_auth_audits', [
|
|
'event' => 'binding_rejected',
|
|
'outcome' => 'denied',
|
|
]);
|
|
}
|
|
|
|
public function test_admin_can_revoke_binding_and_audit_the_action(): void
|
|
{
|
|
$bindingRequest = $this->pendingRequest(['status' => DingTalkBindingRequest::APPROVED]);
|
|
$identity = DingTalkIdentity::query()->create([
|
|
'user_id' => $this->user->id,
|
|
'union_id' => $bindingRequest->union_id,
|
|
'open_id' => $bindingRequest->open_id,
|
|
'dingtalk_user_id' => $bindingRequest->dingtalk_user_id,
|
|
'nickname' => $bindingRequest->nickname,
|
|
'bound_at' => now(),
|
|
]);
|
|
|
|
$this->loginAs()
|
|
->delete(route('system-settings.dingtalk-bindings.destroy', $identity->id))
|
|
->assertRedirect(route('system-settings.dingtalk-bindings.index'));
|
|
|
|
$this->assertDatabaseMissing('dingtalk_identities', ['id' => $identity->id]);
|
|
$this->assertDatabaseHas('dingtalk_binding_requests', [
|
|
'id' => $bindingRequest->id,
|
|
'status' => DingTalkBindingRequest::REVOKED,
|
|
]);
|
|
$this->assertDatabaseHas('dingtalk_auth_audits', [
|
|
'event' => 'binding_revoked',
|
|
'outcome' => 'success',
|
|
'user_id' => $this->user->id,
|
|
]);
|
|
}
|
|
|
|
public function test_regular_user_cannot_open_binding_administration(): void
|
|
{
|
|
$regularUser = User::query()->create([
|
|
'name' => '普通用户',
|
|
'email' => 'regular-user@example.test',
|
|
'password' => 'KnownPassword123!',
|
|
'locale' => 'zh-CN',
|
|
'enabled' => true,
|
|
'landing_page' => 'dashboard',
|
|
'created_by' => $this->user->id,
|
|
'created_from' => 'test',
|
|
]);
|
|
$regularUser->roles()->attach(Role::where('name', SystemAccess::USER)->firstOrFail()->id);
|
|
$regularUser->companies()->attach($this->company->id);
|
|
$this->withExceptionHandling();
|
|
|
|
$this->loginAs($regularUser)
|
|
->get(route('system-settings.dingtalk-bindings.index'))
|
|
->assertForbidden();
|
|
}
|
|
|
|
private function pendingRequest(array $overrides = []): DingTalkBindingRequest
|
|
{
|
|
return DingTalkBindingRequest::query()->create(array_merge([
|
|
'union_id' => 'union-pending-admin',
|
|
'open_id' => 'open-pending-admin',
|
|
'dingtalk_user_id' => 'ding-user-pending-admin',
|
|
'nickname' => '企业员工',
|
|
'email_hash' => hash('sha256', 'enterprise-user@example.test'),
|
|
'mobile_hash' => hash('sha256', '13800138000'),
|
|
'email_hint' => '企***@example.test',
|
|
'mobile_hint' => '*******8000',
|
|
'status' => DingTalkBindingRequest::PENDING,
|
|
'match_reason' => 'no_unique_account',
|
|
'last_attempted_at' => now(),
|
|
], $overrides));
|
|
}
|
|
}
|