Skip to content

Add App Management tools and user-permission tests#32

Merged
oleksandr-nc merged 7 commits into
mainfrom
feature/p7-app-management-user-tests
Mar 30, 2026
Merged

Add App Management tools and user-permission tests#32
oleksandr-nc merged 7 commits into
mainfrom
feature/p7-app-management-user-tests

Conversation

@bigcat88

@bigcat88 bigcat88 commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Summary

App Management tools (4 tools):

Tool Permission Description
list_apps read List installed apps (enabled/disabled/all)
get_app_info read Get app details (name, version, status)
enable_app write Enable a Nextcloud app
disable_app destructive Disable a Nextcloud app

User-permission integration tests (new parallel CI job):

  • Tests that run as a non-admin user to verify proper 403 error handling
  • Verifies regular users can access their own data (files, status, user info)
  • Verifies admin-only operations (list_users, create_user, list_apps, enable/disable_app) return clear 403 errors
  • Runs in parallel with other CI jobs on NC 32 + NC 33

CI changes:

  • New test-user-permissions job (parallel, NC 32 + NC 33)
  • codecov after_n_builds updated to 9

Test plan

  • 14 app management tests pass locally
  • 9 user permission tests pass locally (NC 34 master)
  • CI passes on NC 32 + NC 33

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Nextcloud app management: list apps, view app details, enable/disable apps with permission controls.
  • Tests

    • Added integration suites for app management and a new user-permissions suite verifying non-admin vs admin access and cleanup behaviors.
  • Chores / CI

    • Added CI job for user-permissions integration tests, updated coverage reporting and progress/test-coverage summary; narrowed import-sorting lint scope.

@coderabbitai

coderabbitai Bot commented Mar 29, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6b34a901-92b3-4382-b6eb-a025de86750c

📥 Commits

Reviewing files that changed from the base of the PR and between 848856f and f6664da.

📒 Files selected for processing (2)
  • .github/workflows/lint.yml
  • tests/integration/test_user_permissions.py
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/lint.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integration/test_user_permissions.py

📝 Walkthrough

Walkthrough

Adds an App Management MCP module (list/get/enable/disable apps), registers those tools in the server, introduces integration tests for app management and user-permissions, adds a CI job for user-permissions tests, and adjusts Codecov and lint workflow settings.

Changes

Cohort / File(s) Summary
App Management Implementation
src/nc_mcp_server/server.py, src/nc_mcp_server/tools/app_management.py
New module provides MCP tools list_apps, get_app_info, enable_app, disable_app; normalizes OCS app metadata; enforces PermissionLevel (READ/WRITE/DESTRUCTIVE); server registers the module.
Integration Tests — App Management & Server
tests/integration/test_app_management.py, tests/integration/test_server.py
Adds integration tests for app management (filters, metadata, enable/disable flows, permission-scoped checks) and updates expected tool registry to include the new tools.
Integration Tests — User Permissions
tests/integration/test_user_permissions.py
New integration suite that provisions a CI non-admin user, creates a non-admin MCP client, verifies user-scoped tool access, and asserts admin-only tools return authorization errors.
CI / Coverage Config
.github/workflows/tests-integration.yml, codecov.yml
Adds test-user-permissions GitHub Actions job to run user-permissions integration tests and upload coverage-user-perms.xml; updates Codecov after_n_builds from 7→9.
Lint Workflow
.github/workflows/lint.yml
Narrows isort check to src/ only (isort --check src/).
Documentation / Progress
PROGRESS.md
Updates progress log and test-coverage table to include Collectives, App Management, and User Permissions and adjusts aggregate totals.

Sequence Diagram(s)

sequenceDiagram
    participant Client as MCP Client
    participant Server as MCP Server
    participant Auth as Permission Check
    participant OCS as Nextcloud OCS API

    Client->>Server: list_apps(filter="enabled")
    Server->>Auth: verify PermissionLevel.READ
    Auth-->>Server: allowed
    Server->>OCS: GET /ocs/v2.php/apps?filter=enabled
    OCS-->>Server: apps JSON
    Server-->>Client: formatted apps JSON

    Client->>Server: enable_app(app_id)
    Server->>Auth: verify PermissionLevel.WRITE
    Auth-->>Server: allowed
    Server->>OCS: POST /ocs/v2.php/apps/{app_id}
    OCS-->>Server: 200 OK
    Server-->>Client: confirmation string

    Client->>Server: disable_app(app_id)
    Server->>Auth: verify PermissionLevel.DESTRUCTIVE
    Auth-->>Server: denied (non-admin)
    Server-->>Client: ToolError (403 / Forbidden)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through code with tiny paws,
New tools to list and toggle apps because,
Users peek at files they call their own,
Admin gates stay closed—their thrones alone.
CI cheered, tests ran — I munched a carrot, then I dozed. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.51% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 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 main additions: App Management tools and user-permission tests, aligning directly with the changeset.

✏️ 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 feature/p7-app-management-user-tests

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.

@codecov

codecov Bot commented Mar 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.92%. Comparing base (1694d36) to head (f6664da).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #32      +/-   ##
==========================================
+ Coverage   95.80%   95.92%   +0.12%     
==========================================
  Files          22       23       +1     
  Lines        1501     1546      +45     
==========================================
+ Hits         1438     1483      +45     
  Misses         63       63              
Flag Coverage Δ
integration 94.30% <100.00%> (+0.17%) ⬆️
nc32 94.30% <100.00%> (+0.17%) ⬆️
nc33 94.30% <100.00%> (+0.17%) ⬆️
py3.12 11.83% <0.00%> (-0.36%) ⬇️
py3.13 11.83% <0.00%> (-0.36%) ⬇️
py3.14 11.83% <0.00%> (-0.36%) ⬇️
session-cache 28.71% <26.66%> (-0.07%) ⬇️
unit 11.83% <0.00%> (-0.36%) ⬇️
user-permissions 53.49% <86.66%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@oleksandr-nc oleksandr-nc marked this pull request as ready for review March 30, 2026 06:21

@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 (1)
tests/integration/test_user_permissions.py (1)

28-41: Consider narrowing exception handling in fixture.

The except NextcloudError block catches all Nextcloud errors, not just "user not found" (404). If the API call fails for other reasons (e.g., 500 server error), the fixture will still attempt to create the user. This is acceptable for CI robustness but could mask transient setup failures.

Optional: More explicit 404 handling
 `@pytest.fixture`(scope="module")
 async def _ensure_test_user() -> None:
     """Create the test user via admin client if it doesn't exist."""
     admin_config = Config(
         nextcloud_url=os.environ.get("NEXTCLOUD_URL", "http://nextcloud.ncmcp"),
         user=os.environ.get("NEXTCLOUD_USER", "admin"),
         password=os.environ.get("NEXTCLOUD_PASSWORD", "admin"),
     )
     client = NextcloudClient(admin_config)
     try:
         await client.ocs_get(f"cloud/users/{TEST_USER}")
     except NextcloudError:
-        await client.ocs_post("cloud/users", data={"userid": TEST_USER, "password": TEST_PASS})
+        # User doesn't exist (or API error) - try to create
+        try:
+            await client.ocs_post("cloud/users", data={"userid": TEST_USER, "password": TEST_PASS})
+        except NextcloudError:
+            pass  # User may already exist from previous run
     await client.close()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/test_user_permissions.py` around lines 28 - 41, The fixture
_ensure_test_user currently catches any NextcloudError from client.ocs_get and
proceeds to create the user; change this to only handle "user not found" (HTTP
404) errors: in the except block inspect the NextcloudError (or its underlying
response/status attribute) returned by NextcloudClient.ocs_get and if the status
indicates 404 then call client.ocs_post to create the user, otherwise re-raise
the exception so real server errors (e.g., 500) are not masked. Ensure you
reference _ensure_test_user, NextcloudClient, ocs_get, ocs_post, and
NextcloudError when making the conditional handling change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration/test_app_management.py`:
- Around line 88-94: In test_disable_returns_confirmation, capture the return
value from nc_mcp.call("disable_app", app_id=SAFE_APP) instead of discarding it,
then assert the response contains the expected confirmation (e.g., check it's
truthy and includes the word "disabled" or equals your project's expected
confirmation structure/constant). Keep the finally block that calls
nc_mcp.call("enable_app", app_id=SAFE_APP) to restore state; update the test to
use the captured result variable and add an assertion against that variable.

---

Nitpick comments:
In `@tests/integration/test_user_permissions.py`:
- Around line 28-41: The fixture _ensure_test_user currently catches any
NextcloudError from client.ocs_get and proceeds to create the user; change this
to only handle "user not found" (HTTP 404) errors: in the except block inspect
the NextcloudError (or its underlying response/status attribute) returned by
NextcloudClient.ocs_get and if the status indicates 404 then call
client.ocs_post to create the user, otherwise re-raise the exception so real
server errors (e.g., 500) are not masked. Ensure you reference
_ensure_test_user, NextcloudClient, ocs_get, ocs_post, and NextcloudError when
making the conditional handling change.
🪄 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: ef7881fe-8ac5-4d19-9ee9-f7450e9ba9bd

📥 Commits

Reviewing files that changed from the base of the PR and between 1694d36 and 526a1fa.

📒 Files selected for processing (7)
  • .github/workflows/tests-integration.yml
  • codecov.yml
  • src/nc_mcp_server/server.py
  • src/nc_mcp_server/tools/app_management.py
  • tests/integration/test_app_management.py
  • tests/integration/test_server.py
  • tests/integration/test_user_permissions.py

Comment thread tests/integration/test_app_management.py
- Remove enabled/type from _format_app (getAppInfo endpoint doesn't
  return active/type fields, so they were always null)
- Use ADDITIVE_IDEMPOTENT annotation for enable_app (idempotent op)
- Fix test_disable_returns_confirmation to actually assert the message
- Tighten user-permission tests: ToolError instead of bare Exception,
  regex matches actual Nextcloud error messages
- Update PROGRESS.md with app management and collectives entries

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration/test_user_permissions.py`:
- Around line 39-42: The current bare except NextcloudError around
client.ocs_get(...) swallows all HTTP errors; change it to catch NextcloudError
as e and only handle the "user not found" case (HTTP 404) — e.g., if
e.status_code == 404 (or inspect e.response.status_code) then call
client.ocs_post("cloud/users", data={"userid": TEST_USER, "password":
TEST_PASS}); otherwise re-raise the exception so
authentication/permission/server errors surface; reference the symbols
client.ocs_get, client.ocs_post, NextcloudError, TEST_USER and TEST_PASS when
making the change.
🪄 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: 0e7458d2-8d0a-4a9d-a26f-d38298737e66

📥 Commits

Reviewing files that changed from the base of the PR and between 526a1fa and 848856f.

📒 Files selected for processing (4)
  • PROGRESS.md
  • src/nc_mcp_server/tools/app_management.py
  • tests/integration/test_app_management.py
  • tests/integration/test_user_permissions.py
✅ Files skipped from review due to trivial changes (1)
  • PROGRESS.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integration/test_app_management.py

Comment on lines +39 to +42
try:
await client.ocs_get(f"cloud/users/{TEST_USER}")
except NextcloudError:
await client.ocs_post("cloud/users", data={"userid": TEST_USER, "password": TEST_PASS})

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 | 🟡 Minor

Narrow the exception handling to only catch "user not found" (404).

The bare except NextcloudError catches all non-2xx responses including authentication failures (401), permission denied (403), and server errors (500). If admin credentials are misconfigured, this will silently proceed to create_user which will also fail with a confusing error.

🛡️ Proposed fix to check status code
     try:
         await client.ocs_get(f"cloud/users/{TEST_USER}")
-    except NextcloudError:
-        await client.ocs_post("cloud/users", data={"userid": TEST_USER, "password": TEST_PASS})
+    except NextcloudError as e:
+        if e.status_code == 404:
+            await client.ocs_post("cloud/users", data={"userid": TEST_USER, "password": TEST_PASS})
+        else:
+            raise  # Re-raise auth/permission/server errors
     await client.close()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/test_user_permissions.py` around lines 39 - 42, The current
bare except NextcloudError around client.ocs_get(...) swallows all HTTP errors;
change it to catch NextcloudError as e and only handle the "user not found" case
(HTTP 404) — e.g., if e.status_code == 404 (or inspect e.response.status_code)
then call client.ocs_post("cloud/users", data={"userid": TEST_USER, "password":
TEST_PASS}); otherwise re-raise the exception so
authentication/permission/server errors surface; reference the symbols
client.ocs_get, client.ocs_post, NextcloudError, TEST_USER and TEST_PASS when
making the change.

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.

2 participants