Skip to content

Fix #250: Reject empty/whitespace-only roleName in role create/update endpoints#561

Open
SasinduDilshara wants to merge 5 commits intowso2:mainfrom
SasinduDilshara:fix-250
Open

Fix #250: Reject empty/whitespace-only roleName in role create/update endpoints#561
SasinduDilshara wants to merge 5 commits intowso2:mainfrom
SasinduDilshara:fix-250

Conversation

@SasinduDilshara
Copy link
Copy Markdown

@SasinduDilshara SasinduDilshara commented Apr 5, 2026

Summary

  • Add roleName.trim().length() == 0 guard in POST /auth/orgs/{orgHandle}/roles handler (auth_service.bal:2506) to return HTTP 400 for empty or whitespace-only role names.
  • Apply the same validation to the PUT /auth/orgs/{orgHandle}/roles/{roleId} update handler, and add http:BadRequest to its return type union.
  • Add 5 new negative integration tests in auth_tests_v2.bal covering: empty name on create, whitespace-only name on create, tab/newline name on create, empty name on update, whitespace-only name on update.

Test plan

  • testCreateRoleWithEmptyName — POST with roleName:"", assert HTTP 400
  • testCreateRoleWithWhitespaceName — POST with roleName:" ", assert HTTP 400
  • testCreateRoleWithTabNewlineName — POST with roleName:"\t\n", assert HTTP 400
  • testUpdateRoleWithEmptyName — PUT with roleName:"", assert HTTP 400
  • testUpdateRoleWithWhitespaceName — PUT with roleName:" ", assert HTTP 400
  • Existing happy-path tests (testCreateRole, testUpdateRole) continue to pass

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Role names are now validated to prevent empty or whitespace-only values during creation and updates, ensuring data integrity and preventing invalid configurations.
  • Documentation

    • Introduced comprehensive reference documentation covering system architecture, contribution guidelines, deployment procedures, feature specifications, and testing standards to support development and operational workflows.

SasinduDilshara and others added 4 commits April 5, 2026 19:04
…ole endpoints

Add validation in `auth_service.bal` to trim and check `roleName` length
before persisting, returning HTTP 400 for empty or whitespace-only values.
Also add validation to the PUT update handler and extend `auth_tests_v2.bal`
with negative tests covering empty, whitespace-only, and tab/newline names
for both create and update paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@SasinduDilshara
Copy link
Copy Markdown
Author

Issue Analysis — [Issue #250]: POST /auth/orgs/{orgHandle}/roles accepts empty roleName

Classification

  • Type: Bug
  • Severity Assessment: Medium
  • Affected Component(s): Auth Service — icp_server/auth_service.bal; Storage layer — icp_server/modules/storage/auth_repository.bal; Types — icp_server/modules/types/auth_types.bal
  • Affected Feature(s): Role Management (RBAC V2)

Reproducibility

  • Reproducible: Yes
  • Environment:
    • Branch: main (commit 367ee85)
    • Ballerina: 2201.13.1 (Swan Lake Update 13)
    • OS: Darwin 24.0.0
    • DB: H2 (in-memory, default config)
  • Steps Executed:
    1. Start the server: bal run inside icp_server/
    2. Obtain a JWT: POST /auth/login with admin/admin
    3. Create role with empty roleName: POST /auth/orgs/default/roles with {"roleName":"","description":"empty"}
    4. Create role with whitespace-only roleName: POST /auth/orgs/default/roles with {"roleName":" ","description":"spaces"}
    5. List roles: GET /auth/orgs/default/roles
  • Expected Behavior: Both requests should be rejected with 400 Bad Request (e.g., "roleName must not be empty or blank")
  • Actual Behavior: Both requests return 201 Created. The malformed roles are persisted and appear in GET /auth/orgs/default/roles listings.
  • Logs/Evidence:
=== Test 1: Empty roleName ===
HTTP 201
{"roleId":"01f130fa-e78e-10e8-b810-46aa1aeff0c0","roleName":"","orgId":1,"description":"empty",...}

=== Test 2: Whitespace-only roleName ===
HTTP 201
{"roleId":"01f130fa-e78e-10e8-868e-2cdcf34b5179","roleName":"   ","orgId":1,"description":"spaces",...}

=== Test 3: Missing roleName (control — correctly rejected) ===
HTTP 400
{"message":"data binding failed: required field 'roleName' not present in JSON",...}

=== GET /auth/orgs/default/roles ===
Both bad roles appear in the listing alongside legitimate roles.

Root Cause Analysis

The endpoint handler at icp_server/auth_service.bal:2479 receives the roleInput payload after Ballerina's data-binding, which only validates that roleName is present (since it's a non-optional string field in RoleV2Input). There is no subsequent validation that the bound string is non-empty or non-blank before it is passed directly to storage:createRoleV2() at line 2517.

The storage function (icp_server/modules/storage/auth_repository.bal) also performs no validation — it inserts the value as-is into the roles_v2 table. The database schema defines role_name VARCHAR(255) NOT NULL, which blocks NULL but not empty strings or whitespace strings.

The fix must be applied in the resource function handler, between the permission check (line 2499) and the storage:createRoleV2 call (line 2517):

// Validate roleName is not empty or whitespace-only
string trimmedRoleName = roleInput.roleName.trim();
if trimmedRoleName.length() == 0 {
    return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}

Relevant files:

  • Handler: icp_server/auth_service.bal:2479–2547
  • Type definition: icp_server/modules/types/auth_types.bal:215–220
  • Storage function: icp_server/modules/storage/auth_repository.bal (createRoleV2)

Test Coverage Assessment

  • Existing tests covering this path:
    • icp_server/tests/auth_tests_v2.bal:311testCreateRole() (happy path only, valid name)
    • icp_server/tests/auth_tests_v2.bal:402testUpdateRole() (happy path only)
  • Coverage gaps identified:
    • No test for roleName = "" (empty string)
    • No test for roleName = " " (whitespace-only)
    • No test for roleName = "\t\n" (other whitespace characters)
    • No validation tests for the PUT /auth/orgs/{orgHandle}/roles/{roleId} update endpoint (same issue may apply)
  • Proposed test plan:
    • Unit test: Test roleName.trim().length() == 0 guard logic directly against the validation helper if extracted
    • Integration test (negative): testCreateRoleWithEmptyName() — POST with roleName:"", assert HTTP 400
    • Integration test (negative): testCreateRoleWithWhitespaceName() — POST with roleName:" ", assert HTTP 400
    • Integration test (negative): testUpdateRoleWithEmptyName() — PUT with roleName:"", assert HTTP 400 (check if the same gap exists in the update handler)
    • Edge case: roleName consisting solely of tab/newline characters — should also be rejected

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 5, 2026

Walkthrough

This PR introduces comprehensive project documentation (CLAUDE.md and five specs files covering architecture, contributing guidelines, deployment, features, and testing) and implements input validation for RBAC v2 role names (rejecting empty or whitespace-only values) with corresponding test coverage.

Changes

Cohort / File(s) Summary
Documentation & Project Guidance
CLAUDE.md, specs/Architecture.md, specs/Contributing.md, specs/Deployement.md, specs/Features.md, specs/Testing.md
New documentation files defining AI agent instructions, system architecture overview, contribution practices (tooling, naming conventions, backend/frontend rules, Git workflows), deployment procedures (prerequisites, build outputs, Docker Compose configs, authentication, TLS), feature references (domain model, API surface, GraphQL operations, frontend pages, scheduled tasks), and testing guidelines (Ballerina/React test conventions, local and CI environments, tooling versions).
RBAC v2 Role Name Validation
icp_server/auth_service.bal
Added input validation rejecting empty or whitespace-only roleName values in both role creation (POST /auth/orgs/{orgHandle}/roles) and update (PUT /auth/orgs/{orgHandle}/roles/{roleId}) endpoints. Updated return type signature of the update endpoint to include http:BadRequest.
Role Name Validation Tests
icp_server/tests/auth_tests_v2.bal
Added six new test functions covering role name validation for both creation and update operations, testing empty string, whitespace-only, and tab/newline-only roleName values. Each test verifies HTTP 400 response with a message field.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Poem

🐰 A bundle of docs hops into the fold,
RBAC roles now validate as told—
Empty names rejected with graceful care,
Tests ensure no whitespace snares,
The project's blueprint now shines so bright! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description addresses the fix implementation and test plan but deviates substantially from the repository's template by omitting most required sections (Purpose, Goals, Approach, User stories, Release notes, Documentation, Training, Certification, Marketing, Security checks, Samples, Related PRs, Migrations, Test environment, Learning). Fill in the missing template sections or provide justification for why this fix does not require them (e.g., 'N/A - minor input validation with no user-facing impact').
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically describes the main change: rejecting empty/whitespace-only roleName values in both role creation and update endpoints, directly addressing issue #250.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit 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.

Warning

⚠️ This pull request might be slop. It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

Comment on lines +2509 to +2512
// Validate roleName is not empty or whitespace-only
if roleInput.roleName.trim().length() == 0 {
return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 1

Suggested change
// Validate roleName is not empty or whitespace-only
if roleInput.roleName.trim().length() == 0 {
return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}
// Validate roleName is not empty or whitespace-only
if roleInput.roleName.trim().length() == 0 {
log:printWarn("Attempt to create role with empty or whitespace-only name", orgHandle = orgHandle);
return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}

Comment on lines +2670 to +2673
// Validate roleName is not empty or whitespace-only
if roleInput.roleName.trim().length() == 0 {
return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 2

Suggested change
// Validate roleName is not empty or whitespace-only
if roleInput.roleName.trim().length() == 0 {
return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}
// Validate roleName is not empty or whitespace-only
if roleInput.roleName.trim().length() == 0 {
log:printWarn("Attempt to update role with empty or whitespace-only name", orgHandle = orgHandle, roleId = roleId);
return utils:createBadRequestError("roleName must not be empty or whitespace-only");
}

Copy link
Copy Markdown
Contributor

@wso2-engineering wso2-engineering Bot left a comment

Choose a reason for hiding this comment

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

AI Agent Log Improvement Checklist

⚠️ Warning: AI-Generated Review Comments

  • The log-related comments and suggestions in this review were generated by an AI tool to assist with identifying potential improvements. Purpose of reviewing the code for log improvements is to improve the troubleshooting capabilities of our products.
  • Please make sure to manually review and validate all suggestions before applying any changes. Not every code suggestion would make sense or add value to our purpose. Therefore, you have the freedom to decide which of the suggestions are helpful.

✅ Before merging this pull request:

  • Review all AI-generated comments for accuracy and relevance.
  • Complete and verify the table below. We need your feedback to measure the accuracy of these suggestions and the value they add. If you are rejecting a certain code suggestion, please mention the reason briefly in the suggestion for us to capture it.
Comment Accepted (Y/N) Reason
#### Log Improvement Suggestion No: 1
#### Log Improvement Suggestion No: 2

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 (4)
specs/Architecture.md (1)

5-18: Consider adding language specifier to code block.

The connection diagram code block lacks a language identifier. Adding one (e.g., text or plaintext) improves rendering consistency and satisfies markdown linting.

Add language specifier
-```
+```text
 Browser -> ICP-AUTH/HB:9445
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@specs/Architecture.md` around lines 5 - 18, The fenced code block containing
the connection diagram (starting with the line "Browser -> ICP-AUTH/HB:9445")
lacks a language identifier; update the opening backticks to include a plain
text specifier (for example change ``` to ```text or ```plaintext) so the block
is rendered consistently and satisfies markdown linting, leaving the diagram
lines (e.g., "ICP-GraphQL -> DB:5432", "ICP-OBS-ADPT -> OpenSearch:9200")
unchanged.
CLAUDE.md (1)

29-29: Typo in filename: "Deployement" should be "Deployment".

The path references specs/Deployement.md which matches the actual filename, but both contain a typo. Consider renaming the file to specs/Deployment.md for correctness.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` at line 29, Update the typo in the referenced filename inside
CLAUDE.md by changing the string 'specs/Deployement.md' to the correct
'specs/Deployment.md' and rename the actual file on disk from Deployement.md to
Deployment.md so the link and filename match; ensure any other references to
'Deployement.md' in the repo are likewise updated to 'Deployment.md'.
specs/Deployement.md (1)

1-1: Typo in filename: "Deployement" should be "Deployment".

Consider renaming the file to specs/Deployment.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@specs/Deployement.md` at line 1, Rename the file "specs/Deployement.md" to
"specs/Deployment.md" to fix the typo; update any code, build scripts, README
links, imports, or CI references that point to "specs/Deployement.md" to use
"specs/Deployment.md" instead so no broken references remain (search for the
exact filename string "Deployement.md" across the repo and replace).
icp_server/tests/auth_tests_v2.bal (1)

495-535: Consider verifying specific error message content.

The tests assert responseBody.message is string but don't verify the message text matches the expected "roleName must not be empty or whitespace-only". This could help catch regressions where the validation exists but the message changes unexpectedly.

Optional: Assert specific message content
     test:assertEquals(response.statusCode, 400, "Expected 400 for empty roleName on update");
     json responseBody = check response.getJsonPayload();
     test:assertTrue(responseBody.message is string, "Error message should be present");
+    string message = check responseBody.message;
+    test:assertTrue(message.includes("roleName must not be empty"), "Error message should mention roleName validation");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@icp_server/tests/auth_tests_v2.bal` around lines 495 - 535, Update the two
tests testUpdateRoleWithEmptyName and testUpdateRoleWithWhitespaceName to assert
the exact validation message instead of only checking the type: after extracting
json responseBody (responseBody.message) replace the loose
test:assertTrue(responseBody.message is string) with an equality assertion that
responseBody.message equals the expected string "roleName must not be empty or
whitespace-only" (use your test framework's assertEquals or equivalent to
compare the message), so both tests validate the precise error text returned on
update.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@specs/Deployement.md`:
- Around line 54-57: The UI port is inconsistent: the "UI" section lists
https://localhost:9460 while the earlier spec lists "9445: Auth REST + SPA +
Heartbeat"; verify which port actually serves the web UI, update the "UI"
heading to the correct port (either change 9460 to 9445 or vice‑versa), and make
the deployment docs consistent by aligning the port number in the "UI" section
and the "9445: Auth REST + SPA + Heartbeat" entry and, if applicable, adjust the
corresponding deployment configuration (docker-compose/k8s service) to match the
corrected port.

---

Nitpick comments:
In `@CLAUDE.md`:
- Line 29: Update the typo in the referenced filename inside CLAUDE.md by
changing the string 'specs/Deployement.md' to the correct 'specs/Deployment.md'
and rename the actual file on disk from Deployement.md to Deployment.md so the
link and filename match; ensure any other references to 'Deployement.md' in the
repo are likewise updated to 'Deployment.md'.

In `@icp_server/tests/auth_tests_v2.bal`:
- Around line 495-535: Update the two tests testUpdateRoleWithEmptyName and
testUpdateRoleWithWhitespaceName to assert the exact validation message instead
of only checking the type: after extracting json responseBody
(responseBody.message) replace the loose test:assertTrue(responseBody.message is
string) with an equality assertion that responseBody.message equals the expected
string "roleName must not be empty or whitespace-only" (use your test
framework's assertEquals or equivalent to compare the message), so both tests
validate the precise error text returned on update.

In `@specs/Architecture.md`:
- Around line 5-18: The fenced code block containing the connection diagram
(starting with the line "Browser -> ICP-AUTH/HB:9445") lacks a language
identifier; update the opening backticks to include a plain text specifier (for
example change ``` to ```text or ```plaintext) so the block is rendered
consistently and satisfies markdown linting, leaving the diagram lines (e.g.,
"ICP-GraphQL -> DB:5432", "ICP-OBS-ADPT -> OpenSearch:9200") unchanged.

In `@specs/Deployement.md`:
- Line 1: Rename the file "specs/Deployement.md" to "specs/Deployment.md" to fix
the typo; update any code, build scripts, README links, imports, or CI
references that point to "specs/Deployement.md" to use "specs/Deployment.md"
instead so no broken references remain (search for the exact filename string
"Deployement.md" across the repo and replace).
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2d4c74c-5f15-4ffe-811c-73ea54d0f66f

📥 Commits

Reviewing files that changed from the base of the PR and between 834f36e and 191f5ef.

📒 Files selected for processing (8)
  • CLAUDE.md
  • icp_server/auth_service.bal
  • icp_server/tests/auth_tests_v2.bal
  • specs/Architecture.md
  • specs/Contributing.md
  • specs/Deployement.md
  • specs/Features.md
  • specs/Testing.md

Comment thread specs/Deployement.md Outdated
Comment on lines +54 to +57
## UI

`https://localhost:9460` admin:admin
Three levels: organizations → projects → components.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Port inconsistency with earlier documentation.

Line 20 states 9445: Auth REST + SPA + Heartbeat serves the frontend, but Line 56 references https://localhost:9460 for the UI. This inconsistency could confuse users. Please verify which port serves the web UI.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@specs/Deployement.md` around lines 54 - 57, The UI port is inconsistent: the
"UI" section lists https://localhost:9460 while the earlier spec lists "9445:
Auth REST + SPA + Heartbeat"; verify which port actually serves the web UI,
update the "UI" heading to the correct port (either change 9460 to 9445 or
vice‑versa), and make the deployment docs consistent by aligning the port number
in the "UI" section and the "9445: Auth REST + SPA + Heartbeat" entry and, if
applicable, adjust the corresponding deployment configuration
(docker-compose/k8s service) to match the corrected port.

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