Skip to content

Hide Level column and system admin app identities from non-system-admin users#1271

Merged
minwoox merged 2 commits intoline:mainfrom
minwoox:fix_filter_appId
Mar 9, 2026
Merged

Hide Level column and system admin app identities from non-system-admin users#1271
minwoox merged 2 commits intoline:mainfrom
minwoox:fix_filter_appId

Conversation

@minwoox
Copy link
Contributor

@minwoox minwoox commented Mar 6, 2026

Motivation:
The App Identities settings page exposed the "Level" column (showing System Admin / User role) to all users, including non-system-admins who do not need visibility into that administrative distinction.

Modifications:

  • Filter out system admin app identities from the list returned to non-system-admin callers.
  • webapp/src/pages/app/settings/app-identities/index.tsx:
    • Moved the "Type" column after the "Application ID" column for better visual ordering.
    • Conditionally render the "Level" column only when the current user is a system admin.

Result:

Non-system-admin users will no longer see the "Level" column in the App Identities table, and system admin app identities will be excluded from the list served to them.

…in users

Motivation:
The App Identities settings page exposed the "Level" column (showing System Admin / User role) to all users, including non-system-admins who do not need visibility into that administrative distinction.

Modifications:
- Filter out system admin app identities from the list returned to non-system-admin callers.
- webapp/src/pages/app/settings/app-identities/index.tsx:
  - Moved the "Type" column after the "Application ID" column for better visual ordering.
  - Conditionally render the "Level" column only when the current user is a system admin.

Result:

Non-system-admin users will no longer see the "Level" column in the App Identities table, and system admin app identities will be excluded from the list served to them.
@minwoox minwoox added this to the 0.81.0 milestone Mar 6, 2026
@minwoox minwoox changed the title Hide Level column and system admin app identities from non-system-adm… Hide Level column and system admin app identities from non-system-admin users Mar 6, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

Backend now filters out system-admin app identities for non-admin callers; frontend conditionally shows an admin-only "Level" column based on user systemAdmin state and updates helper texts; tests added to verify conditional column rendering and row contents.

Changes

Cohort / File(s) Summary
Backend filtering
server/src/main/java/com/linecorp/centraldogma/server/internal/api/sysadmin/AppIdentityRegistryService.java
Added a stream-based filter so non-system-admin callers receive an immutable list excluding system-admin identities (previously included non-secret system-admin identities).
Frontend UI updates
webapp/src/dogma/features/app-identity/NewAppIdentity.tsx, webapp/src/pages/app/settings/app-identities/index.tsx
Shortened FormHelperText strings in NewAppIdentity; AppIdentityPage now reads systemAdmin via useAppSelector, always renders Type badge column, and conditionally injects a Level column visible only to system-admin users; memo dependency array updated to include systemAdmin.
Frontend tests
webapp/tests/pages/app/settings/app-identities/index.test.tsx
New tests that mock useGetAppIdentitiesQuery and auth state to verify Level column is hidden for non-admins, shown for admins, badges render for System Admin/User, and rows render expected identities.

Sequence Diagram

sequenceDiagram
    participant User as User (Non-Admin)
    participant Frontend as Frontend UI
    participant Backend as Backend API

    User->>Frontend: Navigate to App Identities page
    Frontend->>Backend: GET /app-identities
    Backend->>Backend: Filter out system-admin identities for non-admin callers
    Backend-->>Frontend: Return filtered identities
    Frontend->>Frontend: Read systemAdmin from store (false)
    Frontend-->>User: Render table without Level column

    Note over Frontend,Backend: For system-admin users the backend returns non-secret identities including admins and frontend renders Level column
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibble lines of code with care,

Filters hop in, hiding who's rare.
Admins see levels, others view less,
Helper texts trimmed for neatness.
Tests clap paws — the table's dressed!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: hiding the Level column and filtering system admin app identities from non-system-admin users.
Description check ✅ Passed The description provides clear motivation, details the modifications across relevant files, and explains the resulting user-facing changes, all directly related to the changeset.
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
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

Copy link

@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 (2)
server/src/main/java/com/linecorp/centraldogma/server/internal/api/sysadmin/AppIdentityRegistryService.java (1)

305-323: Consider applying the same filtering to the deprecated listTokens method for consistency.

The new listAppIdentities method filters out system-admin identities for non-admin callers, but the deprecated listTokens method (lines 314-322) only strips secrets without filtering out system-admin tokens. This inconsistency could allow non-admin users to see system-admin tokens via the deprecated endpoint.

If the deprecated endpoint is still accessible, consider applying the same filter:

🔧 Suggested fix
         } else {
             return mds.getAppIdentityRegistry()
-                      .appIds()
+                      .withoutSecret()
+                      .appIds()
                       .values()
                       .stream()
                       .filter(appIdentity -> appIdentity.type() == AppIdentityType.TOKEN)
+                      .filter(appIdentity -> !appIdentity.isSystemAdmin())
                       .map(appIdentity -> (Token) appIdentity)
-                      .map(Token::withoutSecret)
                       .collect(toImmutableList());
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/sysadmin/AppIdentityRegistryService.java`
around lines 305 - 323, The deprecated method listTokens currently returns all
TOKEN app identities with secrets stripped for non-admins but does not filter
out system-admin identities; update listTokens to apply the same non-admin
filtering used in listAppIdentities by filtering appIdentity ->
appIdentity.type() == AppIdentityType.TOKEN and excluding entries where
appIdentity.isSystemAdmin() (or equivalent check) for non-admin callers before
mapping to (Token) appIdentity and Token::withoutSecret, preserving the existing
behavior for system admins.
webapp/tests/pages/app/settings/app-identities/index.test.tsx (1)

55-91: Good test coverage for the Level column visibility feature.

The tests correctly verify:

  • Level column is hidden for non-system-admin users
  • Level column is shown for system-admin users
  • Badges render correctly within the Level column
  • Identity rows are displayed in the table

Consider adding a test for the new Type column to ensure Token/Certificate badges render correctly:

💡 Optional: Test for Type column badges
it('renders Type badges for identities', () => {
  const { getAllByText } = renderWithProviders(<AppIdentityPage />, {
    preloadedState: { auth: baseAuthState },
  });

  // Both mock identities are TOKEN type
  expect(getAllByText('Token')).toHaveLength(2);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@webapp/tests/pages/app/settings/app-identities/index.test.tsx` around lines
55 - 91, Add a new test in the same suite that renders AppIdentityPage with
renderWithProviders and preloadedState: { auth: baseAuthState } to assert the
Type column shows correct badges; specifically create a test titled like
"renders Type badges for identities" that calls getAllByText('Token') (or the
localized label used by the Type badge) and expects the length to match the two
mock identities (both TOKEN type) so the Token badges are rendered for each
identity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@webapp/src/pages/app/settings/app-identities/index.tsx`:
- Line 20: The code reads state.auth.user.systemAdmin directly in the
useAppSelector call (assigning to systemAdmin), which can throw if user is null;
change the selector to safely access state.auth.user (e.g., use optional
chaining and a default) so it returns a boolean when user is null (update the
useAppSelector selector that computes systemAdmin to use
state.auth.user?.systemAdmin ?? false or similar).

---

Nitpick comments:
In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/sysadmin/AppIdentityRegistryService.java`:
- Around line 305-323: The deprecated method listTokens currently returns all
TOKEN app identities with secrets stripped for non-admins but does not filter
out system-admin identities; update listTokens to apply the same non-admin
filtering used in listAppIdentities by filtering appIdentity ->
appIdentity.type() == AppIdentityType.TOKEN and excluding entries where
appIdentity.isSystemAdmin() (or equivalent check) for non-admin callers before
mapping to (Token) appIdentity and Token::withoutSecret, preserving the existing
behavior for system admins.

In `@webapp/tests/pages/app/settings/app-identities/index.test.tsx`:
- Around line 55-91: Add a new test in the same suite that renders
AppIdentityPage with renderWithProviders and preloadedState: { auth:
baseAuthState } to assert the Type column shows correct badges; specifically
create a test titled like "renders Type badges for identities" that calls
getAllByText('Token') (or the localized label used by the Type badge) and
expects the length to match the two mock identities (both TOKEN type) so the
Token badges are rendered for each identity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ef17aa22-6cd3-4098-9367-b739d104cd35

📥 Commits

Reviewing files that changed from the base of the PR and between f6e3d78 and 1dd1c1f.

📒 Files selected for processing (4)
  • server/src/main/java/com/linecorp/centraldogma/server/internal/api/sysadmin/AppIdentityRegistryService.java
  • webapp/src/dogma/features/app-identity/NewAppIdentity.tsx
  • webapp/src/pages/app/settings/app-identities/index.tsx
  • webapp/tests/pages/app/settings/app-identities/index.test.tsx

Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

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

👍 👍

Copy link
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

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

👍👍

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

@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.

🧹 Nitpick comments (1)
webapp/src/pages/app/settings/app-identities/index.tsx (1)

21-22: Consider moving columnHelper outside the component for effective memoization.

columnHelper is created inside the component (line 21), causing its reference to change on every render. Since it's included in the useMemo dependency array, the memoization becomes ineffective.

This is pre-existing behavior, but now that systemAdmin is properly tracked, the memoization could be made effective by moving columnHelper outside the component.

♻️ Suggested refactor
+const columnHelper = createColumnHelper<AppIdentityDto>();
+
 const AppIdentityPage = () => {
   const systemAdmin = useAppSelector((state) => state.auth.user?.systemAdmin ?? false);
-  const columnHelper = createColumnHelper<AppIdentityDto>();
   const columns = useMemo(
     () => [
       // ... columns definition
     ],
-    [columnHelper, systemAdmin],
+    [systemAdmin],
   );

Also applies to: 88-88

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

In `@webapp/src/pages/app/settings/app-identities/index.tsx` around lines 21 - 22,
The columnHelper is recreated each render because
createColumnHelper<AppIdentityDto>() is called inside the component,
invalidating the useMemo for columns; move the declaration of columnHelper (the
result of createColumnHelper<AppIdentityDto>()) to module scope (outside the
component) so its reference is stable, then update the useMemo that builds
columns (the columns variable) to remove columnHelper from its dependencies and
keep only truly reactive deps (e.g., systemAdmin), ensuring effective
memoization.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@webapp/src/pages/app/settings/app-identities/index.tsx`:
- Around line 21-22: The columnHelper is recreated each render because
createColumnHelper<AppIdentityDto>() is called inside the component,
invalidating the useMemo for columns; move the declaration of columnHelper (the
result of createColumnHelper<AppIdentityDto>()) to module scope (outside the
component) so its reference is stable, then update the useMemo that builds
columns (the columns variable) to remove columnHelper from its dependencies and
keep only truly reactive deps (e.g., systemAdmin), ensuring effective
memoization.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 918e42d3-8abb-422c-b7ea-44946684b50d

📥 Commits

Reviewing files that changed from the base of the PR and between 1dd1c1f and 8a8ff35.

📒 Files selected for processing (1)
  • webapp/src/pages/app/settings/app-identities/index.tsx

@minwoox minwoox merged commit 6dc6ac6 into line:main Mar 9, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants