Enforce REST API access controls based on internal/external user classification (SZ-99)
rk@tigase.net opened 1 week ago

Relates to: SZ-76 (Support for guests and community/customer users)


Summary

Implement server-side enforcement of permissions based on user_type, restricting external users (CUSTOMER, PARTNER, GUEST, COMMUNITY) to a defined set of read and limited write operations across the REST API.

Builds on the user_type field, comment visibility controls, and watermark UI delivered in 1.9.x. This issue closes the gap where an external user with a valid account could currently perform any operation an internal team member can.


Background

The users table already carries a user_type column (INTERNAL, CUSTOMER, PARTNER, GUEST, COMMUNITY) introduced in V06. Comment visibility is already filtered server-side based on this value. However, no other API endpoints currently check user_type, meaning an external user can create issues, merge pull requests, and delete repositories.


Permitted operations for external users

OperationAllowed
View issuesYes
Post comments on issuesYes (posted as EXTERNAL visibility, already enforced)
Change issue priorityYes (raise or lower, any issue)
View pull requestsYes (read-only)
View code / repositoriesYes (read-only)
Create issuesNo
Delete issuesNo
Change issue severity, status, assignee, title, descriptionNo
Create / update / merge pull requestsNo
Review or approve pull requestsNo
Create or delete repositoriesNo
Branch and project managementNo

Implementation

New component: ExternalUserPolicy

A single Spring @Component that is the sole enforcement point across all controllers. No inline user_type checks scattered through business logic.

com.sztab.policy.ExternalUserPolicy
  + resolveType(Authentication) : UserType
  + isExternal(Authentication)  : boolean
  + requireInternal(Authentication) : void  // throws AccessDeniedException -> 403

IssueUpdateDto

Add an overloaded applyTo(Issue, UserType) method. For external callers only the priority field is applied; all other fields in the request body are silently ignored. Internal callers delegate to the existing applyTo(Issue) — no behaviour change.

Controllers updated

IssueController

  • POST /api/issues — blocked for external users
  • GET /api/issues, GET /api/issues/{id}, GET /api/issues/by-key/{key} — allowed, requesterType threaded through to IssueDto.fromEntity (fixes comment visibility drift introduced since the original implementation)
  • PATCH /api/issues/{id} — allowed, but delegates to priority-only applyTo overload
  • DELETE /api/issues/{id} — blocked for external users
  • GET /api/issues/{id}/comments — allowed, requesterType applied
  • POST /api/issues/{id}/comments — allowed (visibility enforcement already in place)

PullRequestController

  • POST /api/pullrequests — blocked
  • PUT /api/pullrequests/{id} — blocked
  • POST /api/pullrequests/{id}/merge — blocked
  • POST /api/pullrequests/{prId}/reviews — blocked
  • PUT /api/pullrequests/{prId}/comments/{commentId} — blocked
  • All GET endpoints — allowed unchanged

GitRepoController

  • POST /api/repos — blocked
  • DELETE /api/repos/{id} — blocked
  • All GET endpoints — allowed unchanged

Out of scope

The following are tracked separately under the GitHub-style authorisation design issue:

  • Project-scoped roles (OWNER, MAINTAINER, DEVELOPER, REVIEWER, REPORTER, GUEST)
  • Branch protection rules
  • Git layer enforcement (Sztabina pre-receive hook)
  • Anonymous / public project access

Acceptance criteria

  • An external user receives 403 Forbidden on any blocked endpoint regardless of other role assignments
  • An external user PATCH /api/issues/{id} with a body containing severity, status, and priority — only priority is applied; severity and status unchanged
  • Internal users are completely unaffected
  • Comment visibility filtering is consistent across all issue GET endpoints
  • No user_type checks exist outside ExternalUserPolicy

Time estimate

TaskHours
ExternalUserPolicy component + IssueUpdateDto overload1.0
IssueController — 7 methods updated, requesterType drift fixed1.5
PullRequestController — 5 write endpoints blocked1.0
GitRepoController — 2 write endpoints blocked0.5
Build, integration test, end-to-end verify with external account1.0
Total5.0
  • rk@tigase.net commented 1 week ago
    rksuma@Ramakrishnans-MacBook-Pro sztab % git checkout -b feature/REST-API-access-controls-based-on-internal-external-user-classification 
    Switched to a new branch 'feature/REST-API-access-controls-based-on-internal-external-user-classification'
    rksuma@Ramakrishnans-MacBook-Pro sztab % 
    
    
  • rk@tigase.net changed state to 'In Progress' 1 week ago
    Previous Value Current Value
    Open
    In Progress
  • rk@tigase.net commented 7 days ago

    In 1.9.2

  • rk@tigase.net changed state to 'Closed' 7 days ago
    Previous Value Current Value
    In Progress
    Closed
issue 1 of 1
Type
New Feature
Priority
Normal
Assignee
Version
1.9.2
Sprints
n/a
Customer
n/a
Issue Votes (0)
Watchers (3)
Reference
SZ-99
Please wait...
Page is in error, reload to recover