[Domain Control] Clean up domain adminship#86815
Conversation
… in domain from the domain onyx daya
…VP_PRIVATE_ADMIN_ACCESS key and replacing it with isAdminSelector for domain admin checks across various components.
…recated access checks with domain key based validation and adding mock for current user details
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 287c733239
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const shouldShowFullScreenLoadingIndicator = isLoadingOnyxValue(domainMetadata); | ||
|
|
||
| useEffect(() => { | ||
| if (shouldShowFullScreenLoadingIndicator || (domain && isAdmin)) { |
There was a problem hiding this comment.
Delay domain redirect until current user ID is loaded
isAdmin now depends on currentUserAccountID, which is 0 until session/personal details hydration completes, but this page’s loading gate only checks domainMetadata. On a refresh/deeplink where domain is already loaded but user identity is not, this effect runs with isAdmin === false and immediately calls Navigation.goBack, so real domain admins can be bounced out of Domain Initial before their account ID arrives. Please gate this redirect on user identity readiness (or equivalent admin-status loading) to avoid this startup race.
Useful? React with 👍 / 👎.
joekaufmanexpensify
left a comment
There was a problem hiding this comment.
Design doc issue
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari2026-04-15.13.33.35.mov |
|
@rayane-d |
@ZhenjaHorbach - done |
|
Thanks! |
|
LGTM! |
|
@rayane-d sorry more conflicts, can you please ping me in slack when you resolve them? |
Resolved |
mountiny
left a comment
There was a problem hiding this comment.
Thanks for this clean up and for adding such thorough tests!
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/mountiny in version: 9.3.61-0 🚀
Bundle Size Analysis (Sentry): |
|
Hi @rayane-d We are checking PR steps and and [Domain control] [Release 1] Remove Admins "beta" - add Admins button #79765 (comment). |
|
This PR failing (Step 20) because of the issue #88506 Video.mp4 |
|
@rayane-d @ZhenjaHorbach @joekaufmanexpensify @mountiny Could you please confirm if it's WAD? When an admin adds a new member under an unverified domain, the account is immediately suspended, and the new user is unable to log in. suspended.mp4 |
This is a pre-existing issue, also reproducible in production, and not related to this PR. |
@jponikarchuk - Is the email used in this test a valid inbox? This also seems unrelated to this PR. |
Explanation of Change
Removes the
sharedNVP_private_admin_access_<domainAccountID>Onyx key and derives admin status from the existingexpensify_adminPermissions_*entries already present indomain_<domainAccountID>. A newisAdminSelectoronyx selector checks whether the current user's account ID appears in any admin permission entry in the domain data.Fixed Issues
$ #80137
PROPOSAL:
Tests
This PR should not introduce any behavior changes compared to the previous version. Regression tests:
Domain admin accessing domain pages:
1.mov
Non-admin domain member access:
8. Log in as a member (but not an admin) of an unverified domain
9. Go to the Workspaces tab
10. Verify the Domains section does not show a "Not verified" badge, no three-dot menu is visible, and clicking the row is disabled
Screen.Recording.2026-04-06.at.7.21.14.PM.mov
2.mov
Unverified domain admin flow:
14. Log in as an admin of an unverified domain
15. Go to the Workspaces tab
16. Verify you see a "Not verified" badge next to your domain
17. Click the three-dot menu and verify you see "Verify domain"
18. Click "Verify domain" and verify the verification RHP opens with a verification code displayed
4.mov
Domain page deeplink:
19. While logged in as a domain admin, open a direct URL to the domain page (e.g.
/domain/<domainAccountID>)20. Verify the Domain Initial Page loads correctly
5.mov
6.mov
7.mov
Company card assignment:
25. Log in as a domain admin who has access to a workspace "A" with a domain-level card feed
26. Go to that workspace > Company Cards
27. Verify the "Assign card" button is enabled
28. Create another workspace "B"
29. In the new workspace "B", Go to Company Cards
30. Verify the "Assign card" button is not available
31. Log in as another domain admin that is a policy admin of workspace "A"
32. Go to Company Cards
33. Verify the "Assign card" button is enabled
9.mov
Domain creation flow:
34. Log in with an account that has a corporate policy
35. Go to Workspaces tab > Add domain
36. Enter a valid domain name and submit
37. Verify the "Domain Added" confirmation page appears and the "Configure" button navigates to domain settings
10.mov
Add and revoke domain admin:
38. Log in as a domain admin (User A)
39. Go to the domain > Admins page
40. Click "Add admin" and enter a valid email from the domain
41. Click "Invite" and verify the new admin appears in the list
42. In a separate session, log in as the newly added admin (User B)
43. Go to the Workspaces tab, tap the domain, and verify you can access domain settings
44. As User A, click on User B in the admin list and click "Revoke admin access"
45. Confirm the revocation
46. Verify User B is removed from the admin list
47. As User B, refresh and verify you can no longer access domain settings (redirected away or see access restricted page)
12.mov
SAML page admin gate:
48. Log in as a domain admin
49. Go to the domain > SAML page
50. Verify the page loads correctly showing SAML configuration or the feature list (depending on whether the domain is verified)
51. Verify that toggling SAML settings works as expected
13.mov
Domain members (admin gate):
52. Log in as a domain admin
53. Go to the domain > Members page
54. Verify the member list loads with avatars, names, and emails
55. Click on a member row and verify the member details page opens
14.mov
Offline tests
15.mov
16.mov
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
Same as tests.
Please perform these regression tests:
[Domain control] [Release 1] Remove
Admins"beta" - addAdminsbutton #79765 (comment)[Release 2] Test and release the members page for customers #79901 (comment)
[Test cases] Domain Control - Release 3 #84809 (comment)
Verify that no errors appear in the JS console
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari