fix(idaa): upgrade Novi UUID verification to server-side API call

Previously, IDAA iframe access relied on trusting URL params (uuid, email,
full_name) passed from Novi — any 36-char string granted authenticated access
with no actual verification.

The (idaa)/+layout.svelte now performs an async Novi API call on every UUID
load to verify the UUID exists, fetches name/email directly from Novi (cannot
be spoofed via URL), and sets $idaa_loc.novi_verified on success.
All-or-nothing: if novi_idaa_api_key is absent or the call fails, access denied.

- ae_idaa_stores.ts: add novi_verified boolean field to idaa_loc
- (idaa)/+layout.svelte: async UUID verification with spinner to prevent
  Access Denied flash; permission upgrade-only strategy preserved
- video_conferences/+page.svelte: skip duplicate Novi member details call if
  layout already verified ($idaa_loc.novi_verified check)
- iframe HTML files: remove browser-side Novi API fetch and email/full_name
  params; pass only uuid; add README/START/STOP/WARNING comments for client
  staff; fix iframe-before-script DOM ordering bug
- documentation: CLIENT__IDAA_and_customized_mods.md updated with full
  verification flow, site_cfg_json fields, permission table, access gate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-09 14:48:49 -04:00
parent 7df887fabd
commit eb0dcb17f8
8 changed files with 2538 additions and 513 deletions

View File

@@ -3,128 +3,122 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Novi Test Page</title>
<title>IDAA Novi Archives iframe Example Template Page</title>
</head>
<body>
<script>
let novi_customer_uid = '<%=Novi.User.CustomerUniqueId%>'; // NOTE: The Novi UUID for the current current user/customer
console.log(`Novi's Current User's ID: ${novi_customer_uid}`);
// var novi_current_user_role = '<%=Novi.User.xyz%>';
// console.log(`Novi's Current User's Role: ${novi_current_user_role}`);
<!-- README: This is an example template page for embedding the IDAA Archives iframe in the IDAA Novi site. Copy the code below to use it in your own page(s). -->
let novi_api_root_url = 'https://www.idaa.org/api';
let novi_api_key_for_idaa = 'CmNdWgdPmgluBWjiTd8xsUCk5mio8F1O9DYAh0pVDcg=';
<!-- START: Copy below this point -->
<!-- IMPORTANT: The <p> and <script> elements below are for using in an iframe in the IDAA Novi site. -->
<!-- IDAA OSIT iframe container element for Novi - Archives iframe -->
<p>
<iframe
width="100%"
height="750"
id="ae_idaa_archives_iframe"
src=""
style="min-height: 600px; max-height: 100%"
class="ae_idaa_iframe"
></iframe>
</p>
<!-- IDAA and Novi specific JavaScript to get current Novi user info and load Archives iframe -->
<script>
// NOTE: The Novi UUID for the current user — injected server-side by Novi.
// This is the only identity value passed to the iframe. Identity verification
// is handled securely by the OSIT server — do not add email or name here.
let novi_customer_uid = '<%=Novi.User.CustomerUniqueId%>';
console.log(`Novi's Current User's ID: ${novi_customer_uid}`);
let novi_current_user_obj = null;
let novi_current_user_email = null;
// WARNING: Do *not* use relative paths here. They must be direct to the site OSIT is hosting for IDAA.
let idaa_osit_ae_api_root_url = 'https://dev-idaa.oneskyit.com/idaa/archives'; // NOTE: DO NOT CHANGE THIS VALUE
// Example URLs: 'https://sk-idaa.oneskyit.com/idaa/archives' OR 'https://dev-idaa.oneskyit.com/idaa/archives'
let idaa_osit_site_key = '8VTOJ0X5hvT6JdiTJsGEzQ'; // 'restricted-access'
let idaa_ae_api_root_url = 'https://sk-idaa.oneskyit.com/idaa/archives';
let idaa_ae_params = new URLSearchParams(document.location.search);
let idaa_ae_slct_archive_id = idaa_ae_params.get('archive_id');
// WARNING: Do *not* change this value. It is required for access control to the IDAA AE API.
let idaa_osit_ae_site_key = 'restricted-access'; // DO NOT CHANGE THIS VALUE
let idaa_ae_iframe_height = null;
let idaa_ae_params = new URLSearchParams(document.location.search);
let idaa_ae_slct_archive_id = idaa_ae_params.get('archive_id');
var novi_api_headers = new Headers();
novi_api_headers.append('Authorization', `Basic ${novi_api_key_for_idaa}`);
let idaa_ae_iframe_height = null;
var requestOptions = {
method: 'GET',
headers: novi_api_headers,
redirect: 'follow'
};
let idaa_ae_iframe_element = document.getElementById('ae_idaa_archives_iframe');
let novi_api_get_customer_endpoint = `${novi_api_root_url}/customers/${novi_customer_uid}`;
// console.log(novi_api_get_customer_endpoint);
if (idaa_ae_slct_archive_id) {
idaa_ae_iframe_element.src = `${idaa_osit_ae_api_root_url}/${idaa_ae_slct_archive_id}?uuid=${novi_customer_uid}&iframe=true&key=${idaa_osit_ae_site_key}`;
} else {
idaa_ae_iframe_element.src = `${idaa_osit_ae_api_root_url}?uuid=${novi_customer_uid}&iframe=true&key=${idaa_osit_ae_site_key}`;
}
fetch(novi_api_get_customer_endpoint, requestOptions)
// .then(response => response.text())
.then((response) => response.json())
.then((result) => {
novi_current_user_obj = result;
// console.log(`Novi's Current User Obj (${novi_current_user_obj.Email}):`, novi_current_user_obj);
// NOTE: This listener handles messages sent from the IDAA iframe back to this parent page.
// It adjusts the iframe height dynamically, scrolls the page when navigation occurs inside
// the iframe, and keeps the browser URL in sync with navigation inside the iframe.
window.addEventListener('message', function (event) {
if (event.data) {
if (event.data.iframe_height) {
idaa_ae_iframe_height = event.data.iframe_height;
let idaa_ae_iframe_element = document.getElementById('ae_idaa_archives_iframe');
let idaa_ae_iframe_element =
document.getElementById('ae_idaa_archives_iframe');
idaa_ae_iframe_element.style.height = `${idaa_ae_iframe_height + 50}px`;
}
if (idaa_ae_slct_archive_id) {
// console.log(`Loading AE Archive ID: ${idaa_ae_slct_archive_id}`);
idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}/${idaa_ae_slct_archive_id}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&iframe=true&key=${idaa_osit_site_key}`;
} else {
idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&iframe=true&key=${idaa_osit_site_key}`;
if (event.data.scroll_to !== undefined) {
console.log(`Got scroll_to: ${event.data.scroll_to}`);
url.searchParams.delete('archive_id');
history.pushState({}, '', url);
}
// let iframe_src = document.getElementById('iframe_src');
// iframe_src.innerHTML = `iframe src = ${idaa_ae_iframe_element.src}`;
})
.catch((error) => console.log('error', error));
window.addEventListener('message', function (event) {
// console.log('Message received from the child:', event.data); // Message received from child
if (event.data) {
if (event.data.iframe_height) {
idaa_ae_iframe_height = event.data.iframe_height;
// console.log(`Got iframe height: ${idaa_ae_iframe_height}`);
let idaa_ae_iframe_element =
document.getElementById('ae_idaa_archives_iframe');
// idaa_ae_iframe_element.style.height = idaa_ae_iframe_height;
idaa_ae_iframe_element.style.height = `${idaa_ae_iframe_height + 50}px`;
}
const url = new URL(location);
// Check if archive_id is defined in the message
if (event.data.archive_id !== undefined) {
console.log(`Got AE Archives ID: ${event.data.archive_id}`);
idaa_ae_slct_archive_id = event.data.archive_id;
if (event.data.archive_id) {
url.searchParams.set('archive_id', event.data.archive_id);
} else {
url.searchParams.delete('archive_id');
}
history.pushState({}, '', url);
}
// Check if archive_content_id is defined in the message
if (event.data.archive_content_id !== undefined) {
console.log(`Got AE Archives Content ID: ${event.data.archive_content_id}`);
idaa_ae_slct_archive_content_id = event.data.archive_content_id;
if (event.data.archive_content_id) {
url.searchParams.set(
'archive_content_id',
event.data.archive_content_id
);
} else {
url.searchParams.delete('archive_content_id');
}
history.pushState({}, '', url);
}
let idaa_ae_iframe_element = document.getElementById('ae_idaa_archives_iframe');
if (idaa_ae_iframe_element) {
// NOTE: Scroll to the top of the iframe element, not the absolute page top.
// The iframe is embedded below Novi's own header and navigation, so
// scrolling to (0, 0) would show the Novi site header instead of the iframe.
let idaa_ae_iframe_top = window.pageYOffset + idaa_ae_iframe_element.getBoundingClientRect().top;
console.log(`Scrolling to iframe top: ${idaa_ae_iframe_top}px`);
window.scrollTo({
top: Math.max(0, idaa_ae_iframe_top - 20),
left: 0,
behavior: 'smooth'
});
} else {
console.log(`No data in message? ${event}`);
console.warn(`Element with ID "ae_idaa_archives_iframe" not found.`);
}
});
</script>
}
<!-- <div id="iframe_src">iframe src=</div> -->
const url = new URL(location);
// Check if archive_id is defined in the message
if (event.data.archive_id !== undefined) {
console.log(`Got AE Archives ID: ${event.data.archive_id}`);
idaa_ae_slct_archive_id = event.data.archive_id;
if (event.data.archive_id) {
url.searchParams.set('archive_id', event.data.archive_id);
} else {
url.searchParams.delete('archive_id');
}
history.pushState({}, '', url);
}
// Check if archive_content_id is defined in the message
if (event.data.archive_content_id !== undefined) {
console.log(`Got AE Archives Content ID: ${event.data.archive_content_id}`);
idaa_ae_slct_archive_content_id = event.data.archive_content_id;
if (event.data.archive_content_id) {
url.searchParams.set(
'archive_content_id',
event.data.archive_content_id
);
} else {
url.searchParams.delete('archive_content_id');
}
history.pushState({}, '', url);
}
} else {
console.log(`No data in message? ${event}`);
}
});
</script>
<!-- STOP: Do not copy below this point -->
<!-- IDAA Aether Apps for Novi - Archives iframe -->
<p>
<iframe
width="100%"
height="750"
id="ae_idaa_archives_iframe"
src=""
style="min-height: 600px; max-height: 100%"
class="ae_idaa_iframe"
></iframe>
</p>
</body>
</html>

View File

@@ -3,141 +3,118 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Novi Test Page</title>
<title>IDAA Novi Bulletin Board iframe Example Template Page</title>
</head>
<body>
<script>
let novi_customer_uid = '<%=Novi.User.CustomerUniqueId%>'; // NOTE: The Novi UUID for the current current user/customer
console.log(`Novi's Current User's ID: ${novi_customer_uid}`);
// var novi_current_user_role = '<%=Novi.User.xyz%>';
// console.log(`Novi's Current User's Role: ${novi_current_user_role}`);
<!-- README: This is an example template page for embedding the IDAA Bulletin Board iframe in the IDAA Novi site. Copy the code below to use it in your own page(s). -->
let novi_api_root_url = 'https://www.idaa.org/api';
let novi_api_key_for_idaa = 'CmNdWgdPmgluBWjiTd8xsUCk5mio8F1O9DYAh0pVDcg=';
<!-- START: Copy below this point -->
<!-- IMPORTANT: The <p> and <script> elements below are for using in an iframe in the IDAA Novi site. -->
<!-- IDAA OSIT iframe container element for Novi - Bulletin Board iframe -->
<p>
<iframe
width="100%"
height="750"
id="ae_idaa_bb_iframe"
src=""
style="min-height: 600px; max-height: 100%"
class="ae_idaa_iframe"
></iframe>
</p>
<!-- IDAA and Novi specific JavaScript to get current Novi user info and load Bulletin Board iframe -->
<script>
// NOTE: The Novi UUID for the current user — injected server-side by Novi.
// This is the only identity value passed to the iframe. Identity verification
// is handled securely by the OSIT server — do not add email or name here.
let novi_customer_uid = '<%=Novi.User.CustomerUniqueId%>';
console.log(`Novi's Current User's ID: ${novi_customer_uid}`);
let novi_current_user_obj = null;
let novi_current_user_email = null;
// WARNING: Do *not* use relative paths here. They must be direct to the site OSIT is hosting for IDAA.
let idaa_osit_ae_api_root_url = 'https://dev-idaa.oneskyit.com/idaa/bb'; // NOTE: DO NOT CHANGE THIS VALUE
// Example URLs: 'https://sk-idaa.oneskyit.com/idaa/bb' OR 'https://dev-idaa.oneskyit.com/idaa/bb'
let idaa_osit_site_key = '8VTOJ0X5hvT6JdiTJsGEzQ'; // 'restricted-access'
let idaa_ae_api_root_url = 'https://sk-idaa.oneskyit.com/idaa/bb';
let idaa_ae_params = new URLSearchParams(document.location.search);
let idaa_ae_slct_post_id = idaa_ae_params.get('post_id');
// WARNING: Do *not* change this value. It is required for access control to the IDAA AE API.
let idaa_osit_ae_site_key = 'restricted-access'; // DO NOT CHANGE THIS VALUE
let idaa_ae_iframe_height = null;
let idaa_ae_params = new URLSearchParams(document.location.search);
let idaa_ae_slct_post_id = idaa_ae_params.get('post_id');
var novi_api_headers = new Headers();
novi_api_headers.append('Authorization', `Basic ${novi_api_key_for_idaa}`);
let idaa_ae_iframe_height = null;
var requestOptions = {
method: 'GET',
headers: novi_api_headers,
redirect: 'follow'
};
let idaa_ae_iframe_element = document.getElementById('ae_idaa_bb_iframe');
let novi_api_get_customer_endpoint = `${novi_api_root_url}/customers/${novi_customer_uid}`;
// console.log(novi_api_get_customer_endpoint);
if (idaa_ae_slct_post_id) {
idaa_ae_iframe_element.src = `${idaa_osit_ae_api_root_url}/${idaa_ae_slct_post_id}?uuid=${novi_customer_uid}&iframe=true&key=${idaa_osit_ae_site_key}`;
} else {
idaa_ae_iframe_element.src = `${idaa_osit_ae_api_root_url}?uuid=${novi_customer_uid}&iframe=true&key=${idaa_osit_ae_site_key}`;
}
fetch(novi_api_get_customer_endpoint, requestOptions)
// .then(response => response.text())
.then((response) => response.json())
.then((result) => {
novi_current_user_obj = result;
// console.log(`Novi's Current User Obj (${novi_current_user_obj.Email}):`, novi_current_user_obj);
// NOTE: This listener handles messages sent from the IDAA iframe back to this parent page.
// It adjusts the iframe height dynamically, scrolls the page when navigation occurs inside
// the iframe, and keeps the browser URL in sync with navigation inside the iframe.
window.addEventListener('message', function (event) {
if (event.data) {
if (event.data.iframe_height) {
idaa_ae_iframe_height = event.data.iframe_height;
let idaa_ae_iframe_element = document.getElementById('ae_idaa_bb_iframe');
let idaa_ae_iframe_element = document.getElementById('ae_idaa_bb_iframe');
idaa_ae_iframe_element.style.height = `${idaa_ae_iframe_height + 50}px`;
}
if (idaa_ae_slct_post_id) {
// console.log(`Loading AE Post ID: ${idaa_ae_slct_post_id}`);
// idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&post_id=${idaa_ae_slct_post_id}&iframe=true&key=${idaa_osit_site_key}`;
if (event.data.scroll_to !== undefined) {
console.log(`Got scroll_to: ${event.data.scroll_to}`);
idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}/${idaa_ae_slct_post_id}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&iframe=true&key=${idaa_osit_site_key}`;
} else {
idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&iframe=true&key=${idaa_osit_site_key}`;
url.searchParams.delete('post_id');
history.pushState({}, '', url);
}
// let iframe_src = document.getElementById('iframe_src');
// iframe_src.innerHTML = `iframe src = ${idaa_ae_iframe_element.src}`;
})
.catch((error) => console.log('error', error));
window.addEventListener('message', function (event) {
// console.log('Message received from the child:', event.data); // Message received from child
if (event.data) {
if (event.data.iframe_height) {
idaa_ae_iframe_height = event.data.iframe_height;
// console.log(`Got iframe height: ${idaa_ae_iframe_height}`);
let idaa_ae_iframe_element = document.getElementById('ae_idaa_bb_iframe');
// idaa_ae_iframe_element.style.height = idaa_ae_iframe_height;
idaa_ae_iframe_element.style.height = `${idaa_ae_iframe_height + 50}px`;
}
if (event.data.scroll_to !== undefined) {
console.log(`Got scroll_to: ${event.data.scroll_to}`);
let idaa_ae_iframe_element = document.getElementById('ae_idaa_bb_iframe');
if (idaa_ae_iframe_element) {
console.log(`Scrolling to: ${event.data.scroll_to}`);
// window.scrollTo(0, 0); // This works for all current browsers
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
} else {
console.warn(`Element with ID "ae_idaa_bb_iframe" not found.`);
}
}
const url = new URL(location);
// Check if post_id is defined in the message
if (event.data.post_id !== undefined) {
console.log(`Got AE Post ID: ${event.data.post_id}`);
idaa_ae_slct_post_id = event.data.post_id;
if (event.data.post_id) {
url.searchParams.set('post_id', event.data.post_id);
} else {
url.searchParams.delete('post_id');
}
history.pushState({}, '', url);
}
// Check if post_comment_id is defined in the message
if (event.data.post_comment_id !== undefined) {
console.log(`Got AE Post Comment ID: ${event.data.post_comment_id}`);
idaa_ae_slct_post_comment_id = event.data.post_comment_id;
if (event.data.post_comment_id) {
url.searchParams.set('post_comment_id', event.data.post_comment_id);
} else {
url.searchParams.delete('post_comment_id');
}
history.pushState({}, '', url);
}
let idaa_ae_iframe_element = document.getElementById('ae_idaa_bb_iframe');
if (idaa_ae_iframe_element) {
// NOTE: Scroll to the top of the iframe element, not the absolute page top.
// The iframe is embedded below Novi's own header and navigation, so
// scrolling to (0, 0) would show the Novi site header instead of the iframe.
let idaa_ae_iframe_top = window.pageYOffset + idaa_ae_iframe_element.getBoundingClientRect().top;
console.log(`Scrolling to iframe top: ${idaa_ae_iframe_top}px`);
window.scrollTo({
top: Math.max(0, idaa_ae_iframe_top - 20),
left: 0,
behavior: 'smooth'
});
} else {
console.log(`No data in message? ${event}`);
console.warn(`Element with ID "ae_idaa_bb_iframe" not found.`);
}
});
</script>
}
const url = new URL(location);
// Check if post_id is defined in the message
if (event.data.post_id !== undefined) {
console.log(`Got AE Post ID: ${event.data.post_id}`);
idaa_ae_slct_post_id = event.data.post_id;
if (event.data.post_id) {
url.searchParams.set('post_id', event.data.post_id);
} else {
url.searchParams.delete('post_id');
}
history.pushState({}, '', url);
}
// Check if post_comment_id is defined in the message
if (event.data.post_comment_id !== undefined) {
console.log(`Got AE Post Comment ID: ${event.data.post_comment_id}`);
idaa_ae_slct_post_comment_id = event.data.post_comment_id;
if (event.data.post_comment_id) {
url.searchParams.set('post_comment_id', event.data.post_comment_id);
} else {
url.searchParams.delete('post_comment_id');
}
history.pushState({}, '', url);
}
} else {
console.log(`No data in message? ${event}`);
}
});
</script>
<!-- STOP: Do not copy below this point -->
<!-- IDAA Aether Apps for Novi - Bulletin Board (posts) iframe -->
<p>
<iframe
width="100%"
height="750"
id="ae_idaa_bb_iframe"
src=""
style="min-height: 600px; max-height: 100%"
class="ae_idaa_iframe"
></iframe>
</p>
</body>
</html>

View File

@@ -3,152 +3,111 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Novi Test Page</title>
<title>IDAA Novi Recovery Meetings iframe Example Template Page</title>
</head>
<body>
<script>
let novi_customer_uid = '<%=Novi.User.CustomerUniqueId%>'; // NOTE: The Novi UUID for the current current user/customer
console.log(`Novi's Current User's ID: ${novi_customer_uid}`);
// var novi_current_user_role = '<%=Novi.User.xyz%>';
// console.log(`Novi's Current User's Role: ${novi_current_user_role}`);
<!-- README: This is an example template page for embedding the IDAA Recovery Meetings iframe in the IDAA Novi site. Copy the code below to use it in your own page(s). -->
let novi_api_root_url = 'https://www.idaa.org/api';
let novi_api_key_for_idaa = 'CmNdWgdPmgluBWjiTd8xsUCk5mio8F1O9DYAh0pVDcg=';
<!-- START: Copy below this point -->
<!-- IMPORTANT: The <p> and <script> elements below are for using in an iframe in the IDAA Novi site. -->
<!-- IDAA OSIT iframe container element for Novi - Recovery Meetings iframe -->
<p>
<iframe
width="100%"
height="750"
id="ae_idaa_recovery_meetings_iframe"
src=""
style="min-height: 600px; height: min-content; max-height: 2048px"
class="ae_idaa_iframe"
></iframe>
</p>
<!-- IDAA and Novi specific JavaScript to get current Novi user info and load Recovery Meetings iframe -->
<script>
// NOTE: The Novi UUID for the current user — injected server-side by Novi.
// This is the only identity value passed to the iframe. Identity verification
// is handled securely by the OSIT server — do not add email or name here.
let novi_customer_uid = '<%=Novi.User.CustomerUniqueId%>';
console.log(`Novi's Current User's ID: ${novi_customer_uid}`);
let novi_current_user_obj = null;
let novi_current_user_email = null;
// WARNING: Do *not* use relative paths here. They must be direct to the site OSIT is hosting for IDAA.
let idaa_osit_ae_api_root_url = 'https://dev-idaa.oneskyit.com/idaa/recovery_meetings'; // NOTE: DO NOT CHANGE THIS VALUE
// Example URLs: 'https://sk-idaa.oneskyit.com/idaa/recovery_meetings' OR 'https://dev-idaa.oneskyit.com/idaa/recovery_meetings'
let idaa_osit_site_key = '8VTOJ0X5hvT6JdiTJsGEzQ'; // 'restricted-access'
let idaa_ae_api_root_url = 'https://sk-idaa.oneskyit.com/idaa/recovery_meetings';
let idaa_ae_params = new URLSearchParams(document.location.search);
let idaa_ae_slct_event_id = idaa_ae_params.get('event_id');
// WARNING: Do *not* change this value. It is required for access control to the IDAA AE API.
let idaa_osit_ae_site_key = 'restricted-access'; // DO NOT CHANGE THIS VALUE
let idaa_ae_iframe_height = null;
let idaa_ae_params = new URLSearchParams(document.location.search);
let idaa_ae_slct_event_id = idaa_ae_params.get('event_id');
var novi_api_headers = new Headers();
novi_api_headers.append('Authorization', `Basic ${novi_api_key_for_idaa}`);
let idaa_ae_iframe_height = null;
var requestOptions = {
method: 'GET',
headers: novi_api_headers,
redirect: 'follow'
};
let idaa_ae_iframe_element = document.getElementById('ae_idaa_recovery_meetings_iframe');
let novi_api_get_customer_endpoint = `${novi_api_root_url}/customers/${novi_customer_uid}`;
console.log(novi_api_get_customer_endpoint);
if (idaa_ae_slct_event_id) {
idaa_ae_iframe_element.src = `${idaa_osit_ae_api_root_url}/${idaa_ae_slct_event_id}?uuid=${novi_customer_uid}&iframe=true&key=${idaa_osit_ae_site_key}`;
} else {
idaa_ae_iframe_element.src = `${idaa_osit_ae_api_root_url}?uuid=${novi_customer_uid}&iframe=true&key=${idaa_osit_ae_site_key}`;
}
fetch(novi_api_get_customer_endpoint, requestOptions)
// .then(response => response.text())
.then((response) => response.json())
.then((result) => {
novi_current_user_obj = result;
// console.log(`Novi's Current User Obj (${novi_current_user_obj.Email}):`, novi_current_user_obj);
// NOTE: This listener handles messages sent from the IDAA iframe back to this parent page.
// It adjusts the iframe height dynamically, scrolls the page when navigation occurs inside
// the iframe, and keeps the browser URL in sync with navigation inside the iframe.
window.addEventListener('message', function (event) {
if (event.data) {
if (event.data.iframe_height) {
idaa_ae_iframe_height = event.data.iframe_height;
let idaa_ae_iframe_element = document.getElementById(
'ae_idaa_recovery_meetings_iframe'
);
let idaa_ae_iframe_element = document.getElementById(
'ae_idaa_recovery_meetings_iframe'
);
idaa_ae_iframe_element.style.height = `${idaa_ae_iframe_height + 50}px`;
}
if (idaa_ae_slct_event_id) {
// console.log(`Loading AE Archive ID: ${idaa_ae_slct_event_id}`);
// idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&event_id=${idaa_ae_slct_event_id}&iframe=true&key=${idaa_osit_site_key}`;
if (event.data.scroll_to !== undefined) {
console.log(`Got scroll_to: ${event.data.scroll_to}`);
idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}/${idaa_ae_slct_event_id}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&iframe=true&key=${idaa_osit_site_key}`;
} else {
idaa_ae_iframe_element.src = `${idaa_ae_api_root_url}?uuid=${novi_customer_uid}&email=${novi_current_user_obj.Email}&full_name=${novi_current_user_obj.Name}&iframe=true&key=${idaa_osit_site_key}`;
url.searchParams.delete('event_id');
history.pushState({}, '', url);
}
// let iframe_src = document.getElementById('iframe_src');
// iframe_src.innerHTML = `iframe src = ${idaa_ae_iframe_element.src}`;
})
.catch((error) => console.log('error', error));
window.addEventListener('message', function (event) {
// console.log('Message received from the child:', event.data); // Message received from child
if (event.data) {
if (event.data.iframe_height) {
// console.log(`Got iframe height: ${event.data.iframe_height}`);
idaa_ae_iframe_height = event.data.iframe_height;
let idaa_ae_iframe_element = document.getElementById(
'ae_idaa_recovery_meetings_iframe'
);
// idaa_ae_iframe_element.style.height = idaa_ae_iframe_height;
idaa_ae_iframe_element.style.height = `${idaa_ae_iframe_height + 50}px`;
}
if (event.data.scroll_to !== undefined) {
console.log(`Got scroll_to: ${event.data.scroll_to}`);
let idaa_ae_iframe_element = document.getElementById(
'ae_idaa_recovery_meetings_iframe'
);
if (idaa_ae_iframe_element) {
console.log(`Scrolling to: ${event.data.scroll_to}`);
// window.scrollTo(0, 0); // This works for all current browsers
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
// idaa_ae_iframe_element.scrollTo({x: 0, y: 0}); // Scroll to top
// document.body.scrollTo({x: 0, y: 0}); // Scroll to top
// document.body.scrollTo({
// top: 0,
// behavior: 'smooth'
// });
// document.body.scrollTop = 0;
// idaa_ae_iframe_element?.scrollTo(0, 0)
// idaa_ae_iframe_element.scrollTo({
// top: 0,
// behavior: 'smooth'
// });
// idaa_ae_iframe_element.scrollTo({
// top: event.data.scroll_to,
// behavior: 'smooth'
// });
} else {
console.warn(
`Element with ID "ae_idaa_recovery_meetings_iframe" not found.`
);
}
}
const url = new URL(location);
// Check if event_id is defined in the message
if (event.data.event_id !== undefined) {
console.log(`Got AE Events ID: ${event.data.event_id}`);
idaa_ae_slct_event_id = event.data.event_id;
if (event.data.event_id) {
url.searchParams.set('event_id', event.data.event_id);
} else {
url.searchParams.delete('event_id');
}
history.pushState({}, '', url);
}
let idaa_ae_iframe_element = document.getElementById(
'ae_idaa_recovery_meetings_iframe'
);
if (idaa_ae_iframe_element) {
// NOTE: Scroll to the top of the iframe element, not the absolute page top.
// The iframe is embedded below Novi's own header and navigation, so
// scrolling to (0, 0) would show the Novi site header instead of the iframe.
let idaa_ae_iframe_top = window.pageYOffset + idaa_ae_iframe_element.getBoundingClientRect().top;
console.log(`Scrolling to iframe top: ${idaa_ae_iframe_top}px`);
window.scrollTo({
top: Math.max(0, idaa_ae_iframe_top - 20),
left: 0,
behavior: 'smooth'
});
} else {
console.log(`No data in message? ${event}`);
console.warn(
`Element with ID "ae_idaa_recovery_meetings_iframe" not found.`
);
}
});
</script>
}
const url = new URL(location);
// Check if event_id is defined in the message
if (event.data.event_id !== undefined) {
console.log(`Got AE Events ID: ${event.data.event_id}`);
idaa_ae_slct_event_id = event.data.event_id;
if (event.data.event_id) {
url.searchParams.set('event_id', event.data.event_id);
} else {
url.searchParams.delete('event_id');
}
history.pushState({}, '', url);
}
} else {
console.log(`No data in message? ${event}`);
}
});
</script>
<!-- STOP: Do not copy below this point -->
<!-- IDAA Aether Apps for Novi - Recovery Meetings (events) iframe -->
<p>
<iframe
width="100%"
height="750"
id="ae_idaa_recovery_meetings_iframe"
src=""
style="min-height: 600px; height: min-content; max-height: 2048px"
class="ae_idaa_iframe"
></iframe>
</p>
</body>
</html>