fix(pres_mgmt): restore POC + Presenter sign-in email and copy link flows

POC (session) sign-in was silently broken:
- sign_in_out.svelte calls session_sign_in() only when session_id is a query
  param; the URL was missing &session_id=... so the function never fired.
- Fixed in: email_sign_in__event_session URL and poc_sign_in_url derivation
  in session_view.svelte.

Presenter email routed to wrong page:
- email_sign_in__event_presenter built a URL to /presenter/[id] which has no
  sign-in handler. Changed to route to /session/[session_id] (same as the
  existing copy-link on the presenter page), including presenter_id and
  presentation_id params so presenter_sign_in() fires correctly.

Multi-session/multi-presentation person-centric auth:
- poc_is_authed in session_view.svelte now also checks
  auth__person.id === poc_person_id, so a POC signed in via any of their
  session links is automatically auth'd on all sessions where they are the POC.
- presenter_is_authed derived bool added to presenter page; includes person_id
  match so a presenter is recognised on all their presentations after one
  sign-in. All file upload and file list auth gates now use it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-06-12 16:27:45 -04:00
parent 10f7f04fbc
commit e05602b87b
4 changed files with 35 additions and 24 deletions

View File

@@ -116,6 +116,19 @@ let lq__auth__event_presenter_obj = $derived(
})
);
// True if this person is authed as the presenter for this specific record.
// Also matches by person_id so a presenter signed in via one presentation link is
// automatically recognised on their other presentations at the same event.
let presenter_is_authed = $derived(
$ae_loc.trusted_access ||
!!events_auth_loc.current.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id ?? ''] ||
!!events_auth_loc.current.auth__kv.session[$lq__event_presenter_obj?.event_session_id ?? ''] ||
(
!!events_auth_loc.current.auth__person.id &&
events_auth_loc.current.auth__person.id === $lq__event_presenter_obj?.person_id
)
);
// if (browser && $lq__event_presenter_obj) {
// console.log('Pres Mgmt [page]: +presenter.svelte');
// $events_slct.event_presenter_obj = $lq__event_presenter_obj;
@@ -202,7 +215,7 @@ let lq__auth__event_presenter_obj = $derived(
<span
class="flex flex-col items-end justify-center gap-0.25 font-normal">
<span class="text-sm text-gray-600 dark:text-gray-400">
{#if !$ae_loc.trusted_access && !events_auth_loc.current.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id] && !events_auth_loc.current.auth__kv.session[$lq__event_presenter_obj.event_session_id]}
{#if !presenter_is_authed}
<!-- Only show the domain name of the email address. -->
<!-- ( -->
<!-- {$lq__event_presenter_obj.email.replace(/@.*$/, '@...')} -->
@@ -349,7 +362,7 @@ let lq__auth__event_presenter_obj = $derived(
</h3>
<!-- Yes... This is a duplicate of what is shown when they press "Presenter Files" button. It can be cleaned up later. -->
{#if $ae_loc.trusted_access || events_auth_loc.current.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id]}
{#if presenter_is_authed}
<Comp_event_files_upload
class_li="border border-surface-200-800 rounded-xl p-4 bg-surface-50-900 hover:bg-surface-100-900 transition-colors duration-200"
link_to_type="event_presenter"
@@ -380,15 +393,8 @@ let lq__auth__event_presenter_obj = $derived(
<Element_manage_event_file_li_wrap
link_to_type={'event_presenter'}
link_to_id={$lq__event_presenter_obj?.event_presenter_id}
allow_basic={events_auth_loc.current.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
] ||
events_auth_loc.current.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
allow_moderator={events_auth_loc.current.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
allow_basic={presenter_is_authed}
allow_moderator={presenter_is_authed}
container_class_li={''} />
</div>
{:else if pres_mgmt_loc.current.show_content__presenter_view == 'manage_files' && $ae_loc.authenticated_access}
@@ -405,7 +411,7 @@ let lq__auth__event_presenter_obj = $derived(
</span>
</h3>
{#if $ae_loc.public_access || events_auth_loc.current.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id]}
{#if presenter_is_authed || $ae_loc.public_access}
<Comp_event_files_upload
class_li="border border-surface-200-800 rounded-xl p-4 bg-surface-50-900 hover:bg-surface-100-900 transition-colors duration-200"
link_to_type="event_presenter"
@@ -437,13 +443,8 @@ let lq__auth__event_presenter_obj = $derived(
<Element_manage_event_file_li_wrap
link_to_type={'event_presenter'}
link_to_id={$lq__event_presenter_obj?.event_presenter_id}
allow_basic={$ae_loc.public_access ||
events_auth_loc.current.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
allow_moderator={events_auth_loc.current.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
allow_basic={presenter_is_authed || $ae_loc.public_access}
allow_moderator={presenter_is_authed}
container_class_li={''} />
</div>
</div>

View File

@@ -145,10 +145,11 @@ let default_end_datetime = $derived(event_start_date ? `${event_start_date}T09:0
// Derived helpers for the POC sign-in URL (used by both copy link and email).
// WHY: poc_person_passcode gates access for the session POC without requiring a full account.
// session_id is required as a query param so sign_in_out.svelte calls session_sign_in().
let poc_sign_in_url = $derived(
$lq__event_session_obj?.poc_person_id && $lq__event_session_obj?.poc_person_passcode
? encodeURI(
`${$ae_loc.url_origin}/events/${$lq__event_session_obj.event_id}/session/${$lq__event_session_obj.event_session_id}?person_id=${$lq__event_session_obj.poc_person_id}&person_pass=${$lq__event_session_obj.poc_person_passcode}`
`${$ae_loc.url_origin}/events/${$lq__event_session_obj.event_id}/session/${$lq__event_session_obj.event_session_id}?person_id=${$lq__event_session_obj.poc_person_id}&person_pass=${$lq__event_session_obj.poc_person_passcode}&session_id=${$lq__event_session_obj.event_session_id}`
)
: null
);
@@ -158,8 +159,14 @@ let poc_sign_in_url = $derived(
let person_options_loaded = $derived(Object.keys($slct.person_obj_kv ?? {}).length > 0);
// Whether the current session POC is signed in (auth'd) on this device.
// Also grants access by person_id so a POC signed in via one session link is automatically
// auth'd on all other sessions where their person record is the assigned POC.
let poc_is_authed = $derived(
events_auth_loc.current.auth__kv.session[$lq__event_session_obj?.event_session_id] === true
events_auth_loc.current.auth__kv.session[$lq__event_session_obj?.event_session_id] === true ||
(
!!events_auth_loc.current.auth__person.id &&
events_auth_loc.current.auth__person.id === $lq__event_session_obj?.poc_person_id
)
);
// QR Code Generation Logic