From 0b988a4b99d4282216f4b06416836744d0d8cb70 Mon Sep 17 00:00:00 2001 From: WuYongJie <549727955@qq.com> Date: Tue, 8 Sep 2026 11:29:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=AA=E9=85=8D=E7=BD=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=9A=84=E9=92=89=E9=92=89=E7=94=A8=E6=88=B7=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=AE=8C=E6=95=B4=E4=B8=9A=E5=8A=A1=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=20(#117)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Utilities/SidebarPermissions.php | 3 --- docs/钉钉花名册登录.md | 2 +- tests/Feature/Auth/DingTalkLoginTest.php | 23 +++++++++++++++++------ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/Utilities/SidebarPermissions.php b/app/Utilities/SidebarPermissions.php index 2738c115..0c36a020 100644 --- a/app/Utilities/SidebarPermissions.php +++ b/app/Utilities/SidebarPermissions.php @@ -35,9 +35,6 @@ class SidebarPermissions $subject = self::subjectKey($user); if (! in_array($subject, $settings['configured'] ?? [], true)) { - if ($user->created_from === 'dingtalk_roster' && SystemAccess::roleName($user) === SystemAccess::USER) { - return []; - } return null; } diff --git a/docs/钉钉花名册登录.md b/docs/钉钉花名册登录.md index 18b201c3..6a94f5ff 100644 --- a/docs/钉钉花名册登录.md +++ b/docs/钉钉花名册登录.md @@ -15,7 +15,7 @@ 新账号使用钉钉接口返回的姓名、可用邮箱和手机号;邮箱缺失或已被其他账号使用时,生成稳定的 `@dingtalk.invalid` 内部占位地址。系统生成不可预知的随机本地密码,不展示或发送密码,不发送注册邀请。花名册显示名仅作为姓名缺失时的后备。 -新账号赋予现有 `user` 角色及进入应用外壳所需的 `read-admin-panel` 权限,不添加管理权限。业务访问继承管理员明确配置的普通用户权限;尚无配置时默认无业务权限,进入“你已登录,等待分配业务权限”的工作台。管理员可在“侧边栏管理”中为普通用户角色或指定账号配置业务范围。 +新账号赋予现有 `user` 角色及进入应用外壳所需的 `read-admin-panel` 权限,不添加管理权限。按负责人最新要求,尚无页面权限配置时默认显示完整业务导航;主管理员随后可在“侧边栏管理”中设置指定用户的业务范围。配置优先级为指定用户、角色、默认完整导航;显式配置为空时没有业务页面,不回退到完整导航。管理员专属操作(包括店铺密码读取)继续单独鉴权。 ## 只读数据契约 diff --git a/tests/Feature/Auth/DingTalkLoginTest.php b/tests/Feature/Auth/DingTalkLoginTest.php index 0a6bbc8b..5a50b178 100644 --- a/tests/Feature/Auth/DingTalkLoginTest.php +++ b/tests/Feature/Auth/DingTalkLoginTest.php @@ -111,7 +111,8 @@ class DingTalkLoginTest extends FeatureTestCase $this->assertNotSame($this->user->id, $created->id); $this->assertTrue($created->hasRole('user')); $this->assertFalse($created->hasRole('super_admin')); - $this->assertSame([], SidebarPermissions::allowedKeys($created)); + $this->assertNull(SidebarPermissions::allowedKeys($created)); + $this->assertTrue(collect(SidebarPermissions::navigationFor($created))->contains('slug', 'store-management')); $this->assertDatabaseHas('dingtalk_identities', [ 'user_id' => $created->id, 'union_id' => 'union-auto', @@ -127,8 +128,7 @@ class DingTalkLoginTest extends FeatureTestCase 'outcome' => 'success', 'user_id' => $created->id, ]); - $this->get(route('dashboard', ['company_id' => $this->company->id]))->assertOk() - ->assertSeeText('你已登录')->assertSeeText('无需再次注册'); + $this->get(route('dashboard', ['company_id' => $this->company->id]))->assertRedirectContains('/workspace/'); } public function test_shared_mobile_does_not_claim_an_existing_account(): void @@ -430,14 +430,13 @@ class DingTalkLoginTest extends FeatureTestCase public function test_admin_can_assign_business_access_to_the_automatically_created_user(): void { + app('url')->defaults(['company_id' => $this->company->id]); Http::preventStrayRequests(); Http::fake($this->dingtalkResponses('union-grant', 'open-grant')); $state = $this->startAuthorization(); $this->get(route('login.dingtalk.callback', ['code' => 'fake-code', 'state' => $state])); $created = auth()->user(); - $this->withExceptionHandling()->get(route('business.pages.show', [ - 'company_id' => $this->company->id, 'section' => 'store-management', 'page' => 'basic-information', - ]))->assertForbidden(); + $this->assertNull(SidebarPermissions::allowedKeys($created)); auth()->logout(); session()->invalidate(); $this->actingAs($this->user)->get(route('system-settings.sidebar.edit', ['subject' => 'user_'.$created->id])) ->assertOk()->assertSee('value="user_'.$created->id.'"', false); @@ -447,6 +446,18 @@ class DingTalkLoginTest extends FeatureTestCase $this->assertSame(['store-management/basic-information'], SidebarPermissions::allowedKeys($created)); $this->actingAs($created)->withSession(['dingtalk_identity_id' => $created->dingtalkIdentity->id, 'dingtalk_roster_checked_at' => now()->timestamp]) ->get(route('dashboard'))->assertRedirectContains('/workspace/store-management/basic-information'); + $this->withExceptionHandling()->get(route('business.pages.show', [ + 'company_id' => $this->company->id, 'section' => 'company-management', 'page' => 'basic-information', + ]))->assertForbidden(); + } + + public function test_explicit_empty_user_scope_does_not_fall_back_to_all_pages(): void + { + setting()->set('system.sidebar_permissions', [ + 'configured' => ['user_'.$this->user->id], 'subjects' => ['user_'.$this->user->id => []], + ]); + $this->assertSame([], SidebarPermissions::navigationFor($this->user)); + $this->loginAs()->get(route('dashboard', ['company_id' => $this->company->id]))->assertOk()->assertSeeText('尚未分配业务权限'); } protected function startAuthorization(): string