feat(votes): add permission check on committee Create Vote CTA click#997
feat(votes): add permission check on committee Create Vote CTA click#997MRashad26 wants to merge 2 commits into
Conversation
Replace routerLink on both Create Vote buttons (table-actions slot and empty-state) with an onCreateVote() click handler that fetches fresh committee permissions before navigating. If the member's role was downgraded from Manager to Member since the page loaded, the stale canEdit() signal would still show the button; the click handler catches this and redirects to /project/overview?_notice=votes so AppComponent shows the "Access Denied" toast — consistent with the writerGuard denial flow used for meetings. Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughBoth "Create Vote" buttons in ChangesCreate Vote permission-guarded navigation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.ts (1)
45-67: 💤 Low valueConsider disabling the button during the permission check to prevent duplicate requests.
While the implementation correctly fetches fresh permissions and handles denial/error cases, rapid clicks could trigger multiple concurrent API calls before navigation completes. Adding a brief loading state would improve UX.
♻️ Optional: Add loading guard
+ public creatingVote = signal<boolean>(false); + public onCreateVote(): void { + if (this.creatingVote()) return; + this.creatingVote.set(true); const committee = this.committee(); const denyParams: Record<string, string> = { _notice: 'votes' }; if (committee.project_slug) denyParams['project'] = committee.project_slug; - const deny = () => void this.router.navigate(['/project/overview'], { queryParams: denyParams }); + const deny = () => { + this.creatingVote.set(false); + void this.router.navigate(['/project/overview'], { queryParams: denyParams }); + }; this.committeeService .getCommittee(committee.uid) .pipe(take(1)) .subscribe({ next: (fresh) => { if (fresh?.writer !== true) { deny(); return; } void this.router.navigate(['/votes', 'create'], { queryParams: this.createVoteQueryParams() }); }, error: () => deny(), }); }Then in template:
[disabled]="creatingVote()"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.ts` around lines 45 - 67, To prevent duplicate API requests from rapid button clicks during the permission check in the onCreateVote method, add a loading state signal (named something like creatingVote) initialized to false. Set this signal to true before the getCommittee API call starts subscribing, then set it back to false in both the next and error callbacks of the subscribe handler to ensure it resets regardless of outcome. Finally, update the template to disable the button by binding [disabled]="creatingVote()" to the create vote button element.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.ts`:
- Around line 45-67: To prevent duplicate API requests from rapid button clicks
during the permission check in the onCreateVote method, add a loading state
signal (named something like creatingVote) initialized to false. Set this signal
to true before the getCommittee API call starts subscribing, then set it back to
false in both the next and error callbacks of the subscribe handler to ensure it
resets regardless of outcome. Finally, update the template to disable the button
by binding [disabled]="creatingVote()" to the create vote button element.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 98e32e74-2730-4773-8207-41ce2e0eecd4
📒 Files selected for processing (2)
apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.htmlapps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.ts
🚀 Deployment StatusYour branch has been deployed to: https://ui-pr-997.dev.v2.cluster.linuxfound.info Deployment Details:
The deployment will be automatically removed when this PR is closed. |
There was a problem hiding this comment.
Pull request overview
Adds a “fresh permission” check when a user clicks the Committee “Create Vote” CTA so that if their committee writer access is revoked after page load, they’re redirected through the same _notice=votes access-denied toast flow rather than relying solely on the route guard.
Changes:
- Added
onCreateVote()to re-fetch committee permissions viaCommitteeService.getCommittee()before navigating to the create vote route. - Updated both “Create Vote” buttons to call
(click)="onCreateVote()"instead of using[routerLink]+[queryParams].
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.ts | Adds click handler that re-checks committee writer permission and redirects with _notice=votes on denial. |
| apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.html | Routes both CTAs through the new click handler. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…rect Inject LensService and derive the overview path from the active lens so the access-denied redirect lands on /foundation/overview when the component is rendered under the foundation lens (/foundation/groups/...) rather than always redirecting to /project/overview — consistent with writerGuard's lens-aware denial behavior (per @copilot-pull-request-reviewer). Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
Review Feedback AddressedCommit: 1b0e903 Changes Made
No Change Needed
Threads Resolved1 of 1 unresolved threads addressed in this iteration. Follow-up
|
|
@MRashad26 I've opened a new pull request, #998, to work on those changes. Once the pull request is ready, I'll request review from you. |
Summary
canEdit()— derived fromcommittee.writerat page-load time. If the member's role is downgraded from Manager to Member after the page loads, the stale signal still shows the button. Clicking it without this fix would navigate directly to/votes/createand rely solely on thewriterGuardredirect, with no immediate UI feedback.onCreateVote(), which fetches fresh committee permissions viagetCommittee()before navigating. On denial, redirects to/project/overview?project=<slug>&_notice=votessoAppComponent.initAccessDeniedToast()shows the contextual "Access Denied" toast — consistent with thewriterGuarddenial flow from feat(meetings): add access-denied toast and fix meeting coordinator permissions #992.writerGuardon/votes/createremains as the final safety net for direct URL access.Changed files
committee-votes.component.tsCommitteeService+Router; addonCreateVote()click handler with fresh permission check and deny redirectcommittee-votes.component.html[routerLink]+[queryParams]on both Create Vote buttons with(click)="onCreateVote()"References
committee-meetings.component.tsfrom feat(meetings): add access-denied toast and fix meeting coordinator permissions #992Test plan
/votes/createwithcommittee_uidandprojectquery paramscanEdit()) but clicking it redirects to the project overview with an "Access Denied" toast/votes/create?committee_uid=...—writerGuardblocks and shows the toast