Skip to content

fix: grant MANAGE_AUTOMATIONS permission to org members - #436

Closed
lilagrc wants to merge 2 commits into
mainfrom
fix/member-automation-create-permission
Closed

lilagrc wants to merge 2 commits into
mainfrom
fix/member-automation-create-permission

Conversation

@lilagrc

@lilagrc lilagrc commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes the bug where organization members cannot create automations.

After PR #415 in the automation service split permissions into view_automations and manage_automations, the enterprise repo only granted members VIEW_AUTOMATIONS. This prevented members from creating automations because the automation service requires manage_automations permission on the create endpoint.

Solution

This PR introduces a three-tier permission model for automations:

  1. VIEW_AUTOMATIONS - Read-only access (all roles)
  2. MANAGE_AUTOMATIONS - Create and manage own automations (all roles)
  3. MANAGE_ALL_AUTOMATIONS - Manage any automation in the org (admins/owners only)

Permission Distribution

Permission Member Admin Owner
VIEW_AUTOMATIONS ✅ ✅ ✅
MANAGE_AUTOMATIONS ✅ ✅ ✅
MANAGE_ALL_AUTOMATIONS ❌ ✅ ✅

Why This Approach?

This permission split is OSS-compatible:

  • Enterprise: Maps roles → permissions (as shown above)
  • OSS: Grants all three permissions to everyone (no org concept)
  • Automation Service: Uses permissions only, no knowledge of roles required

Changes in This PR

File Change
server/auth/authorization.py Add MANAGE_ALL_AUTOMATIONS permission enum
server/auth/authorization.py Grant MANAGE_AUTOMATIONS to members, admins, owners
server/auth/authorization.py Grant MANAGE_ALL_AUTOMATIONS to admins and owners only
tests/unit/test_authorization.py Update tests to verify permission distribution

Required Changes in Automation Service

Repository: OpenHands/automation

File: openhands/automation/router.py

The automation service needs to update ownership checks to use manage_all_automations instead of relying solely on user_id matching:

1. Update update_automation endpoint

Current code (from PR #427):

if auto.user_id != user.user_id and update_data != {"enabled": False}:
    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail="Only the automation creator can edit it; admins and owners can only turn it off or delete it"
    )

Should become:

if auto.user_id != user.user_id and update_data != {"enabled": False}:
    # Non-creator editing - check if they have admin/owner privileges
    if "manage_all_automations" not in user.permissions:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You can only edit your own automations"
        )

2. Update delete_automation endpoint

Currently uses _assert_can_manage which allows anyone with manage_automations. After this PR, members will have that permission, so we need to add an ownership check:

async def delete_automation(...):
    auto = await _get_org_automation(session, automation_id, user.org_id)
    await _assert_can_manage(auto, user)
    
    # Add: Only creator or admin/owner can delete
    if auto.user_id != user.user_id:
        if "manage_all_automations" not in user.permissions:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You can only delete your own automations"
            )
    
    # ... rest of delete logic

3. Update dispatch_automation endpoint

Same pattern - add ownership check:

async def dispatch_automation(...):
    auto = await _get_org_automation(session, automation_id, user.org_id)
    await _assert_can_manage(auto, user)
    
    # Add: Only creator or admin/owner can dispatch
    if auto.user_id != user.user_id:
        if "manage_all_automations" not in user.permissions:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You can only dispatch your own automations"
            )
    
    # ... rest of dispatch logic

4. Update cancel_run endpoint

Same pattern:

async def cancel_run(...):
    run = await get_run(session, run_id)
    auto = await _get_org_automation(session, run.automation_id, user.org_id)
    await _assert_can_manage(auto, user)
    
    # Add: Only creator or admin/owner can cancel
    if auto.user_id != user.user_id:
        if "manage_all_automations" not in user.permissions:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You can only cancel runs of your own automations"
            )
    
    # ... rest of cancel logic

5. Update tests

File: tests/test_router.py

Update the test fixtures and add new tests:

  • Mock users should include manage_all_automations in permissions for admin/owner
  • Add tests verifying members cannot edit/delete/dispatch others' automations
  • Update existing tests in TestPermissionEnforcement that expect admins/owners to be blocked

Expected Behavior After Both PRs

Role Create View All Edit Own Edit Others Delete Own Delete Others Dispatch Own Dispatch Others
Member ✅ ✅ ✅ ❌ ✅ ❌ ✅ ❌
Admin ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Owner ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅

Related Issues

Test Plan

  • Ruff format and check passed
  • Authorization unit tests pass
  • Manual test: Member can create automation
  • Manual test: Member can view all automations
  • Manual test: Member can edit/delete/dispatch their own automation
  • Manual test: Member cannot edit/delete/dispatch another member's automation
  • Manual test (after automation service update): Admin can edit/delete/dispatch any automation

This PR was created by an AI agent (OpenHands) on behalf of the user.


Enterprise server image for this PR:

ghcr.io/openhands/enterprise-server:sha-b39bf4b

Members can now create automations and manage their own. The automation
service enforces ownership checks: members can only edit/delete automations
where automation.user_id == user.user_id. Admins and owners can edit/delete
any automation in their organization.

Changes:
- Add MANAGE_AUTOMATIONS to RoleName.MEMBER permission set
- Update comments to clarify ownership-based access control model
- Update tests to expect MANAGE_AUTOMATIONS for members

Fixes the bug where org members could not create automations at all.

Co-authored-by: openhands <openhands@all-hands.dev>
@lilagrc
lilagrc marked this pull request as ready for review September 17, 2026 19:13
@lilagrc
lilagrc requested review from saurya and tofarr September 17, 2026 19:13
@github-actions github-actions Bot added the type: fix A bug fix label Sep 17, 2026
@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  server/auth
  authorization.py
Project Total  

This report was generated by python-coverage-comment-action

Add MANAGE_ALL_AUTOMATIONS permission to distinguish between:
- Members: can manage their own automations only
- Admins/Owners: can manage any automation in the org

This approach is OSS-compatible because OSS deployments can grant
all permissions without needing to understand organizational roles.

Changes:
- Add Permission.MANAGE_ALL_AUTOMATIONS to authorization.py
- Grant to owner and admin roles only (not members)
- Update tests to verify permission distribution

Co-authored-by: openhands <openhands@all-hands.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: fix A bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants