Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions apps/lfx-pcc/src/app/modules/meeting/meeting.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,7 @@ <h4 class="font-medium text-gray-900 font-sans">{{ user.name }}</h4>
<i class="fa-light fa-check-circle"></i>
<span class="font-sans">Ready to join as {{ user.name }}</span>
</div>
<lfx-button size="small" [href]="meeting().join_url" severity="primary" label="Join Meeting" icon="fa-light fa-sign-in"
>Join Meeting</lfx-button
>
<lfx-button size="small" [href]="meeting().join_url" severity="primary" label="Join Meeting" icon="fa-light fa-sign-in"></lfx-button>
</div>

<div class="text-center">
Expand Down Expand Up @@ -261,9 +259,7 @@ <h4 class="font-medium text-gray-900 font-sans">Enter your information</h4>

<div class="flex items-center justify-between pt-3">
<p class="text-sm text-gray-500 font-sans">Meeting invites and updates will be sent to your email</p>
<lfx-button size="small" [href]="meeting().join_url" severity="primary" label="Join Meeting" icon="fa-light fa-sign-in"
>Join Meeting</lfx-button
>
<lfx-button size="small" [href]="meeting().join_url" severity="primary" label="Join Meeting" icon="fa-light fa-sign-in"></lfx-button>
</div>
</form>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export class MeetingComponent {

private initializeReturnTo(): Signal<string | undefined> {
return computed(() => {
return `${environment.urls.home}/meeting/${this.meeting().uid}`;
return `${environment.urls.home}/meetings/${this.meeting().uid}`;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export class MeetingCommitteeModalComponent {

// If no changes, just close
const currentIds = this.meeting.committees?.map((c) => c.uid) || [];
const currentVotingStatuses = this.meeting.committees?.map((c) => c.allowed_voting_statuses) || [];
const currentVotingStatuses = this.meeting.committees?.flatMap((c) => c.allowed_voting_statuses || []) || [];
if (
JSON.stringify(selectedIds.sort()) === JSON.stringify(currentIds.sort()) &&
JSON.stringify(selectedVotingStatuses.sort()) === JSON.stringify(currentVotingStatuses.sort())
Expand Down
6 changes: 2 additions & 4 deletions apps/lfx-pcc/src/server/controllers/meeting.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ export class MeetingController {
const counts = await Promise.all(
meetings.map(async (m) => {
const registrants = await this.meetingService.getMeetingRegistrants(req, m.uid);
const directRegistrants = registrants.filter((r) => r.type === 'direct').length ?? 0;
const committeeMembers = registrants.filter((r) => r.type === 'committee').length ?? 0;

return {
individual_registrants_count: directRegistrants,
individual_registrants_count: registrants.length - committeeMembers,
committee_members_count: committeeMembers,
};
})
Expand Down Expand Up @@ -101,10 +100,9 @@ export class MeetingController {
// TODO: Remove this once we have a way to get the registrants count
try {
const registrants = await this.meetingService.getMeetingRegistrants(req, meeting.uid);
const directRegistrants = registrants.filter((r) => r.type === 'direct').length ?? 0;
const committeeMembers = registrants.filter((r) => r.type === 'committee').length ?? 0;

meeting.individual_registrants_count = directRegistrants;
meeting.individual_registrants_count = registrants.length - committeeMembers;
meeting.committee_members_count = committeeMembers;
} catch (error) {
// Log the error
Expand Down
2 changes: 1 addition & 1 deletion apps/lfx-pcc/src/server/services/access-check.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class AccessCheckService {
userAccessInfo.push({ resourceId: resource.id, username, hasAccess });
}

req.log.info(
req.log.debug(
Logger.sanitize({
operation: 'check_access',
request_count: resources.length,
Expand Down
15 changes: 10 additions & 5 deletions apps/lfx-pcc/src/server/services/meeting.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,16 @@ export class MeetingService {
// Get each committee
const committees = await Promise.all(
uniqueCommitteeUids.map(async (uid) => {
const committee = await this.committeeService.getCommitteeById(req, uid);
return {
uid: committee.uid,
name: committee.name,
};
try {
const committee = await this.committeeService.getCommitteeById(req, uid);
return { uid: committee.uid, name: committee.name };
} catch (error) {
req.log.warn(
{ operation: 'get_meeting_committees', committee_uid: uid, error: error instanceof Error ? error.message : String(error) },
'Committee enrichment failed; continuing without name'
);
return { uid, name: undefined };
}
})
);

Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/backend/public-meetings.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The meeting routes are configured to allow public access:
```typescript
// apps/lfx-pcc/src/app/app.routes.ts
{
path: 'meeting/:id',
path: 'meetings/:id',
loadComponent: () => import('./modules/meetings/meeting.component').then(m => m.MeetingComponent),
}
```
Expand Down Expand Up @@ -119,7 +119,7 @@ The protected routes middleware allows public meeting routes to bypass authentic

**Location**: `apps/lfx-pcc/src/server/middleware/protected-routes.middleware.ts`

- Uses an explicit allowlist for prefixes: `/public/api/meetings` (API) and SPA route `/meeting/:id`
- Uses an explicit allowlist for prefixes: `/public/api/meetings` (API) and SPA route `/meetings/:id`
- Bypasses only user–session auth for those allowlisted routes; server-to-server (M2M) calls still require auth
- Applies standard authentication to all other routes (avoid loose regexes like `/meeting.*`)
- Add unit tests verifying that only those exact prefixes bypass auth and that all similar prefixes remain protected
Expand Down