feat(meetings): improve meeting join and registration filtering#198
feat(meetings): improve meeting join and registration filtering#198
Conversation
LFXV2-885 - Extract guest form into reusable component - Add error handling for restricted meeting email validation - Allow authenticated users to enter alternate email when their SSO email is not registered - Prioritize form-submitted email over OIDC user email in backend 🤖 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <asithade@gmail.com>
LFXV2-886 - Filter ALL meetings (public and private) by registration status - Writers have API access to all meetings, but my meetings shows only registered - Extract filterMeetingsByRegistration helper method for code reuse - Simplify getUserMeetings by removing writer-specific logic 🤖 Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <asithade@gmail.com>
WalkthroughThis PR introduces a guest form component for meeting join flows and refactors authentication/authorization paths. It removes the fallback join button from the dashboard, adds a new guest form component, revamps meeting join logic to support guest workflows, adjusts email handling priority, and refactors user service meeting filtering by registration status. Changes
Sequence DiagramssequenceDiagram
participant User as Guest User
participant UI as Meeting Join UI
participant GuestForm as Guest Form Component
participant Backend as Backend Service
participant Auth as Join URL Service
User->>UI: Attempts to join meeting (no auth)
activate UI
UI->>UI: showGuestForm = true
UI->>GuestForm: Render guest form
deactivate UI
User->>GuestForm: Enter name, email, organization
GuestForm->>GuestForm: Validate form
User->>GuestForm: Click "Join Meeting"
activate GuestForm
GuestForm->>Backend: Submit guest info + email
deactivate GuestForm
activate Backend
Backend->>Auth: Fetch join URL (guest email source)
activate Auth
Auth->>Auth: Check email registration (M2M API)
Note over Auth: Filters meetings by<br/>registration status
Auth-->>Backend: Return join URL or error
deactivate Auth
alt Join URL Available
Backend-->>GuestForm: joinUrl
GuestForm->>GuestForm: Open URL in new tab
GuestForm-->>User: Redirect to meeting
else Email Not Registered
Backend-->>UI: joinUrlError (email error)
UI->>UI: emailError signal = true
UI->>User: Show error + email action link
User->>UI: Click email error action
UI->>GuestForm: Reset and show form again
end
deactivate Backend
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
apps/lfx-one/src/server/services/user.service.ts (1)
560-608: Consider consolidating thevparameter.The query object sets
v: 1(number) on line 564, butDEFAULT_QUERY_PARAMSdefinesv: '1'(string). SinceDEFAULT_QUERY_PARAMSis spread afterward, the string version will override the number, but this creates redundancy. Remove the explicitv: 1sinceDEFAULT_QUERY_PARAMSalready provides it.const query = { - v: 1, type: 'meeting_registrant', parent: `meeting:${meeting.uid}`, tags_all: [`email:${email}`], ...DEFAULT_QUERY_PARAMS, };apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1)
1-3: Add Claude Code attribution comment.Per the PR description, this code was generated with Claude Code. As per coding guidelines, prepend the attribution comment.
// Copyright The Linux Foundation and each contributor to LFX. // SPDX-License-Identifier: MIT +// Generated with Claude Code (https://claude.ai/code)apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (2)
571-576: Consider using an error code instead of string matching.Matching error messages by string content is fragile—if the backend message changes, this detection will silently fail. Consider having the backend return a structured error with a stable error code (e.g.,
EMAIL_NOT_REGISTERED) that you can check reliably.If the error format cannot be changed, at minimum extract the expected message to a constant to avoid duplication and make updates easier:
+const EMAIL_NOT_REGISTERED_ERROR = 'email address is not registered for this restricted meeting'; + private initializeEmailError(): Signal<boolean> { return computed(() => { - return this.joinUrlError()?.toLowerCase().includes('email address is not registered for this restricted meeting') ?? false; + return this.joinUrlError()?.toLowerCase().includes(EMAIL_NOT_REGISTERED_ERROR) ?? false; }); }
1-3: Add Claude Code attribution per coding guidelines.Per the coding guidelines, files assisted with Claude Code should include an attribution comment. Since the PR description notes this was generated with Claude Code, consider adding:
// Copyright The Linux Foundation and each contributor to LFX. // SPDX-License-Identifier: MIT +// Generated with Claude Code (https://claude.ai/code)Based on coding guidelines.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html(0 hunks)apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.html(1 hunks)apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts(1 hunks)apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html(3 hunks)apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts(9 hunks)apps/lfx-one/src/server/controllers/public-meeting.controller.ts(1 hunks)apps/lfx-one/src/server/services/user.service.ts(4 hunks)
💤 Files with no reviewable changes (1)
- apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Always use direct imports for standalone components - no barrel exports
Use TypeScript interfaces instead of union types for better maintainability
Do not nest ternary expressions
Prefer interface for defining object shapes in TypeScript
Use path mappings and import aliases as configured in tsconfig.json for imports
Files:
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.tsapps/lfx-one/src/server/controllers/public-meeting.controller.tsapps/lfx-one/src/server/services/user.service.tsapps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
**/*.{html,ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always add data-testid attributes when creating new components for reliable test targeting
Files:
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.tsapps/lfx-one/src/server/controllers/public-meeting.controller.tsapps/lfx-one/src/server/services/user.service.tsapps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.htmlapps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.htmlapps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: License headers are required on all source files
Prepend 'Generated with Claude Code (https://claude.ai/code)' if assisted with the code
Files:
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.tsapps/lfx-one/src/server/controllers/public-meeting.controller.tsapps/lfx-one/src/server/services/user.service.tsapps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
**/*.component.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use Angular 19 zoneless change detection with signals for component state management
Files:
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.tsapps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts
apps/**/**/server/**/*.{ts,js}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/**/**/server/**/*.{ts,js}: Use Pino for structured JSON logs with sensitive data redaction in all backend services
Always use err field for errors to leverage Pino's error serializer - correct: req.log.error({ err: error, ...metadata }, 'message')
Log INFO level for business operation completions (created, updated, deleted) and successful data retrieval
Log WARN level for error conditions leading to exceptions and data quality issues
Log DEBUG level for internal operations, preparation steps, and intent statements
Log ERROR level for system failures, unhandled exceptions, and critical errors
Files:
apps/lfx-one/src/server/controllers/public-meeting.controller.tsapps/lfx-one/src/server/services/user.service.ts
apps/**/**/server/**/*controller*.{ts,js}
📄 CodeRabbit inference engine (CLAUDE.md)
All controller functions must use Logger helper methods: Logger.start(), Logger.success(), Logger.error(), Logger.warning(), Logger.validation()
Files:
apps/lfx-one/src/server/controllers/public-meeting.controller.ts
**/*.html
📄 CodeRabbit inference engine (CLAUDE.md)
Use data-testid naming convention - [section]-[component]-[element] for hierarchical structure
Files:
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.htmlapps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html
🧬 Code graph analysis (2)
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1)
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (1)
Component(46-577)
apps/lfx-one/src/server/services/user.service.ts (5)
packages/shared/src/interfaces/meeting.interface.ts (2)
Meeting(90-210)MeetingRegistrant(337-380)apps/lfx-one/src/server/utils/m2m-token.util.ts (1)
generateM2MToken(16-110)packages/shared/src/constants/api.constants.ts (1)
DEFAULT_QUERY_PARAMS(12-15)packages/shared/src/interfaces/api.interface.ts (1)
QueryServiceResponse(58-63)apps/lfx-one/src/server/helpers/logger.ts (1)
error(52-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Agent
🔇 Additional comments (14)
apps/lfx-one/src/server/controllers/public-meeting.controller.ts (1)
187-187: Email source priority change looks correct.The change correctly prioritizes form-submitted email over the OIDC user email, aligning with the guest form feature that allows authenticated users to join with an alternate email address.
apps/lfx-one/src/server/services/user.service.ts (2)
488-549: Refactored filtering logic looks good.The method now correctly filters all meetings by registration status, ensuring "my meetings" only shows meetings the user is registered for. The M2M token is generated once and reused for all registration checks.
571-576: V1 meeting handling logic is correct.The conditional correctly handles legacy v1 meetings by switching to the appropriate registrant type and tag format.
apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.ts (1)
16-23: Component implementation follows Angular 19 patterns.The component correctly uses Angular's new
input()signal API for reactive inputs, aligning with zoneless change detection guidelines. The required/optional input pattern is well-structured.apps/lfx-one/src/app/modules/meetings/components/guest-form/guest-form.component.html (1)
1-72: Template follows best practices with proper test IDs and security attributes.The template correctly uses data-testid attributes following the naming convention, and the external link button properly includes
rel="noopener noreferrer"for security.apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html (3)
114-148: Join button conditional logic correctly handles guest form state.The implementation properly shows the join button only when a URL is available and the guest form is not active, with appropriate error handling for restricted meeting email issues.
299-299: Verify form input binding syntax.The guest form component expects a
FormGroupviainput.required<FormGroup>(). Here,joinFormis passed directly without invoking it as a signal. Looking at the parent component,joinFormis declared asFormGroup(not a signal), so this binding is correct.
337-342: Guest form integration for unauthenticated users is consistent.The guest form and error handling mirror the authenticated flow, providing a consistent user experience.
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts (6)
37-43: LGTM on imports.The new imports for
GuestFormComponentandDialogService/DynamicDialogModuleare correctly structured using direct imports (no barrel exports) as per coding guidelines.
108-110: LGTM on signal declarations.Using
WritableSignalforshowGuestForm(mutable state) andSignalforemailError(computed/derived) correctly follows Angular 19 signal patterns for zoneless change detection.
183-186: LGTM ononEmailErrorClick.The method correctly clears the error state before showing the guest form, providing a clean UX when the user opts to enter an alternate email.
220-228: LGTM on auto-join logic.Correctly prevents automatic join when the user is entering an alternate email via guest form. The comment at line 220 clearly documents this intentional behavior.
304-310: LGTM on empty email initialization.Defaulting the email field to empty is correct for the guest form workflow. Authenticated users with matching emails auto-join (bypassing the form), while those using the guest form need to enter their alternate email.
423-445: LGTM on authenticated path condition.Adding
!this.showGuestForm()correctly allows authenticated users to fall through to the form-based email path when using an alternate email. This implements the requirement to prioritize form-submitted email over the OIDC email.
There was a problem hiding this comment.
Pull request overview
This pull request enhances meeting join functionality for authenticated users and refines the "my meetings" view to show only meetings where users are registered.
Key Changes:
- Allows authenticated users to join restricted meetings using an alternate email address when their SSO email is not registered
- Updates meeting filtering to show only registered meetings in "my meetings" view for all users, including writers
- Extracts guest form into a reusable component for better code organization
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
apps/lfx-one/src/server/services/user.service.ts |
Refactored getUserMeetings to filter ALL meetings by registration status (not just public ones), extracted filterMeetingsByRegistration helper method, and removed unused MeetingVisibility import |
apps/lfx-one/src/server/controllers/public-meeting.controller.ts |
Changed email priority to use form-submitted email before OIDC user email, enabling authenticated users to specify alternate emails |
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.ts |
Added guest form display logic for authenticated users, email error detection, and updated form initialization to not pre-fill email for authenticated users |
apps/lfx-one/src/app/modules/meetings/meeting-join/meeting-join.component.html |
Added UI for error handling with alternate email option, integrated guest form for both authenticated and unauthenticated users |
apps/lfx-one/src/app/modules/meetings/components/guest-form/ |
New reusable guest form component for email, name, and organization input with configurable submit button |
apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html |
Removed fallback join button that redirected to join page when no direct join URL was available |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Changes
LFXV2-885: Allow authenticated users to join with alternate email
guest-form/)LFXV2-886: Filter meetings by registration for my meetings view
filterMeetingsByRegistrationhelper method for code reuse🤖 Generated with Claude Code