Skip to content

fix(update): restrict to global admin, register commands, add error handling#345

Merged
ModerRAS merged 1 commit into
masterfrom
fix/update-command-permissions
May 11, 2026
Merged

fix(update): restrict to global admin, register commands, add error handling#345
ModerRAS merged 1 commit into
masterfrom
fix/update-command-permissions

Conversation

@ModerRAS

@ModerRAS ModerRAS commented May 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix permission check: Updated /update and /checkupdate commands to require global admin (Env.AdminId) instead of any group manager, matching documented behavior
  • Register commands: Added /checkupdate and /update to Telegram bot command menu via SetMyCommands
  • Add error handling: Wrapped update handlers in try-catch, exceptions now reported back via bot message

Changes

  • TelegramSearchBot/Controller/Manage/UpdateController.cs - Permission check + exception handling
  • TelegramSearchBot/Service/BotAPI/TelegramCommandRegistryService.cs - Command registration
  • TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs - Test updates

Testing

  • All 67 update-related tests pass
  • Full solution: 555+ tests pass, 0 failures

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced /checkupdate command enabling users to check system update availability and status.
    • Introduced /update command allowing authorized users to initiate system updates.
  • Bug Fixes

    • Enhanced error handling for update operations with informative error messages displayed to users when issues occur during update checks or deployments.

Review Change Stack

…andling

- Change permission check from IsNormalAdmin to Env.AdminId (global admin only, matching docs)

- Register /checkupdate and /update in bot command menu via SetMyCommands

- Add try-catch with bot message reply for network/exceptions

- Update tests to match new constructor and remove AdminService mocking
@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR refactors update command authorization in UpdateController from an injected AdminService dependency to a direct global-admin check via Env.AdminId. Exception handling is added to both command handlers, new bot commands are registered, and tests are updated to match the new authorization pattern.

Changes

Update Command Authorization and Exception Handling

Layer / File(s) Summary
Authorization Mechanism Refactor
TelegramSearchBot/Controller/Manage/UpdateController.cs
Constructor removes AdminService parameter. Authorization check replaces IsNormalAdmin() call with direct message.From.Id == Env.AdminId comparison.
Exception Handling in Update Handlers
TelegramSearchBot/Controller/Manage/UpdateController.cs
/checkupdate and /update handlers are wrapped in try/catch blocks that reply with ❌ ...发生异常:{ex.Message} on exceptions.
Bot Command Registration
TelegramSearchBot/Service/BotAPI/TelegramCommandRegistryService.cs
Two new bot commands (checkupdate and update) with Chinese descriptions are added to the command registry.
Test Updates
TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs
Using directives updated to include TelegramSearchBot.Common. Class documentation rewritten for Env.AdminId authorization. _mockAdminService field, mock setup, and admin service injection in controller instantiation are removed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hoppy change, when authorization's clear,
No mocking dance, just Env.AdminId here!
Exceptions caught with grace and care,
New commands register in the air. 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the three main changes: permission restriction to global admin, command registration, and error handling implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/update-command-permissions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

PR Check Report

Summary

Test Results

Platform Status Details
Ubuntu Passed Tests passed, artifacts uploaded
Windows Passed Tests passed, artifacts uploaded

Code Quality

  • Code formatting check
  • Security vulnerability scan
  • Dependency analysis
  • Code coverage collection

Test Artifacts

  • Test results artifacts count: 2
  • Code coverage uploaded to Codecov

Links


This report is auto-generated by GitHub Actions

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs (2)

203-210: ⚡ Quick win

Update outdated comment referencing removed AdminService.

The comment at lines 208-209 still references AdminService.IsNormalAdmin, which was removed in this PR. The comment should be updated to reflect the new Env.AdminId authorization model.

Additionally, this test doesn't verify the permission check behavior. The test creates a user with ID 12345, but if Env.AdminId has a different value at test runtime, the command will be denied without the test detecting it.

📝 Suggested comment update
     [Fact]
     public async Task ExecuteAsync_CheckUpdateCommand_EntersCheckUpdateFlow()
     {
         var context = CreateContext("/checkupdate");
         await _controller.ExecuteAsync(context);
-        // RED: AdminService.IsNormalAdmin throw → test fails.
-        // GREEN: mock IsNormalAdmin → verify status reply sent.
+        // Note: This test assumes Env.AdminId matches the default userId (12345).
+        // Consider adding explicit permission verification tests.
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs` around
lines 203 - 210, The test comment and assertions need updating to reflect the
new Env.AdminId authorization model: replace the outdated reference to
AdminService.IsNormalAdmin with Env.AdminId, ensure the test sets Env.AdminId to
the test user ID (or otherwise arranges the environment so the created user ID
12345 is treated as admin) before calling UpdateController.ExecuteAsync, and add
an assertion that the expected status reply was sent (verifying the permission
check passed); locate this logic around the test method
ExecuteAsync_CheckUpdateCommand_EntersCheckUpdateFlow and the CreateContext
usage to make the change.

203-252: 🏗️ Heavy lift

Consider adding explicit authorization tests.

The integration tests verify that command patterns are recognized and don't throw exceptions, but they don't verify the permission check behavior or response messages. Since this PR introduces a significant authorization change (restricting to Env.AdminId only), consider adding tests that:

  1. Verify unauthorized users receive the permission denied message
  2. Verify authorized users (matching Env.AdminId) can execute commands
  3. Verify the bot's response content for different scenarios
💡 Example permission test structure
[Fact]
public async Task ExecuteAsync_CheckUpdate_UnauthorizedUser_SendsPermissionDenied()
{
    // Arrange: user ID != Env.AdminId
    long unauthorizedUserId = Env.AdminId + 1;
    var context = CreateContext("/checkupdate", userId: unauthorizedUserId);
    
    // Act
    await _controller.ExecuteAsync(context);
    
    // Assert: verify SendRequest was called with permission denied message
    _mockBotClient.Verify(
        x => x.SendRequest(
            It.Is<IRequest<Message>>(req => /* verify message contains "权限不足" */),
            It.IsAny<CancellationToken>()),
        Times.Once);
}

[Fact]
public async Task ExecuteAsync_CheckUpdate_AuthorizedUser_SendsStatusMessage()
{
    // Arrange: user ID == Env.AdminId
    var context = CreateContext("/checkupdate", userId: Env.AdminId);
    
    // Act & Assert
    await _controller.ExecuteAsync(context);
    
    // Verify SendRequest was called with status message
    _mockBotClient.Verify(
        x => x.SendRequest(
            It.IsAny<IRequest<Message>>(),
            It.IsAny<CancellationToken>()),
        Times.Once);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs` around
lines 203 - 252, Add explicit authorization unit tests for the update commands:
create one test that uses CreateContext("/checkupdate", userId: Env.AdminId + 1)
to assert an unauthorized user receives the "权限不足" (permission denied) reply by
verifying _mockBotClient.SendRequest was called with a request whose message
text contains that phrase; create a second test that uses
CreateContext("/checkupdate", userId: Env.AdminId) to assert the authorized flow
executes by verifying _mockBotClient.SendRequest was called once with any
IRequest<Message> (or with the expected status message) after calling
_controller.ExecuteAsync(context). Ensure tests reference Env.AdminId,
CreateContext, ExecuteAsync and verify via _mockBotClient.Verify.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@TelegramSearchBot/Controller/Manage/UpdateController.cs`:
- Around line 39-43: The Env static constructor must stop silently defaulting
AdminId=0: validate that Config.json exists and parses as valid JSON, log any
exceptions (including parse errors and missing file), and enforce AdminId>0 (log
a clear error and throw/terminate startup if invalid) so controllers like
UpdateController, EditOCRConfController, EditVisionConfController,
EditLLMConfController, EditMcpConfController, RefreshController and
CheckBanGroupController cannot invert permission checks; update Env (static ctor
and any config-loading helper) to perform these checks and emit explicit error
logs before failing fast rather than leaving AdminId at 0.

---

Nitpick comments:
In `@TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs`:
- Around line 203-210: The test comment and assertions need updating to reflect
the new Env.AdminId authorization model: replace the outdated reference to
AdminService.IsNormalAdmin with Env.AdminId, ensure the test sets Env.AdminId to
the test user ID (or otherwise arranges the environment so the created user ID
12345 is treated as admin) before calling UpdateController.ExecuteAsync, and add
an assertion that the expected status reply was sent (verifying the permission
check passed); locate this logic around the test method
ExecuteAsync_CheckUpdateCommand_EntersCheckUpdateFlow and the CreateContext
usage to make the change.
- Around line 203-252: Add explicit authorization unit tests for the update
commands: create one test that uses CreateContext("/checkupdate", userId:
Env.AdminId + 1) to assert an unauthorized user receives the "权限不足" (permission
denied) reply by verifying _mockBotClient.SendRequest was called with a request
whose message text contains that phrase; create a second test that uses
CreateContext("/checkupdate", userId: Env.AdminId) to assert the authorized flow
executes by verifying _mockBotClient.SendRequest was called once with any
IRequest<Message> (or with the expected status message) after calling
_controller.ExecuteAsync(context). Ensure tests reference Env.AdminId,
CreateContext, ExecuteAsync and verify via _mockBotClient.Verify.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fab96979-0d7b-491d-b183-d64844cf2a12

📥 Commits

Reviewing files that changed from the base of the PR and between 6845e70 and 3e6a95c.

📒 Files selected for processing (3)
  • TelegramSearchBot.Test/Controller/Manage/UpdateControllerTests.cs
  • TelegramSearchBot/Controller/Manage/UpdateController.cs
  • TelegramSearchBot/Service/BotAPI/TelegramCommandRegistryService.cs

Comment on lines +39 to 43
// 仅允许全局管理员使用更新指令
if (message.From.Id != Env.AdminId) {
await ReplyAsync(message, "❌ 权限不足:只有全局管理员才能使用更新指令。");
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify Env.AdminId initialization and usage patterns

# Check Env.AdminId declaration and initialization
ast-grep --pattern 'class Env {
  $$$
  AdminId
  $$$
}'

# Check for validation or initialization of AdminId
rg -nP --type=cs 'AdminId\s*[=:]' -A 2 -B 2

# Check if there's startup validation
rg -nP --type=cs 'AdminId.*==\s*0|AdminId.*validation|ValidateConfig' -C 3

Repository: ModerRAS/TelegramSearchBot

Length of output: 475


🏁 Script executed:

# Read full Env.cs to see AdminId property definition and type
cat -n TelegramSearchBot.Common/Env.cs | head -60

Repository: ModerRAS/TelegramSearchBot

Length of output: 3507


🏁 Script executed:

# Find where config is loaded and how it's validated
rg -n --type=cs 'config\s*=|ConfigProvider|LoadConfig|BotConfig' -A 3 -B 1 | head -100

Repository: ModerRAS/TelegramSearchBot

Length of output: 9677


🏁 Script executed:

# Check for BotConfig class definition to see AdminId field
fd -t f '*.cs' -x grep -l 'class.*BotConfig' {}

Repository: ModerRAS/TelegramSearchBot

Length of output: 354


🏁 Script executed:

# Find Config class - likely in same directory as Env.cs
fd -t f -x grep -l 'class Config' {} \; | head -5

Repository: ModerRAS/TelegramSearchBot

Length of output: 104


🏁 Script executed:

# Check for Config class in Common namespace
rg -n --type=cs 'class Config' -A 10 TelegramSearchBot.Common/

Repository: ModerRAS/TelegramSearchBot

Length of output: 1103


🏁 Script executed:

# Also check what the default Config looks like and AdminId initialization
rg -n --type=cs 'AdminId' -B 5 -A 5 | head -80

Repository: ModerRAS/TelegramSearchBot

Length of output: 7323


🏁 Script executed:

# Verify if there's any startup validation for AdminId
rg -n --type=cs 'AdminId.*0|AdminId.*validation|AdminId.*required' -B 2 -A 2

Repository: ModerRAS/TelegramSearchBot

Length of output: 52


🏁 Script executed:

# Check if Config.json existence is validated at startup
rg -n --type=cs 'Config\.json|WorkDir.*Config' -B 2 -A 2 | head -50

Repository: ModerRAS/TelegramSearchBot

Length of output: 523


Critical security issue: Env.AdminId defaults to zero when Config.json is missing, inverting permission checks across all management controllers.

The permission check if (message.From.Id != Env.AdminId) becomes if (message.From.Id != 0) when AdminId defaults to 0, allowing access to all users except user ID 0 instead of denying access to all except the configured admin. This occurs silently when Config.json is missing or contains invalid JSON (lines 14-21 of Env.cs catch exceptions without logging).

Add validation in the Env static constructor to: (1) require Config.json to exist and be valid JSON, (2) require AdminId > 0 with an explicit error message, and (3) log configuration failures. This vulnerability affects UpdateController, EditOCRConfController, EditVisionConfController, EditLLMConfController, EditMcpConfController, RefreshController, and CheckBanGroupController.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TelegramSearchBot/Controller/Manage/UpdateController.cs` around lines 39 -
43, The Env static constructor must stop silently defaulting AdminId=0: validate
that Config.json exists and parses as valid JSON, log any exceptions (including
parse errors and missing file), and enforce AdminId>0 (log a clear error and
throw/terminate startup if invalid) so controllers like UpdateController,
EditOCRConfController, EditVisionConfController, EditLLMConfController,
EditMcpConfController, RefreshController and CheckBanGroupController cannot
invert permission checks; update Env (static ctor and any config-loading helper)
to perform these checks and emit explicit error logs before failing fast rather
than leaving AdminId at 0.

@ModerRAS ModerRAS merged commit 28ab45e into master May 11, 2026
8 checks passed
@ModerRAS ModerRAS deleted the fix/update-command-permissions branch May 11, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant