Environment & Bootstrap Stability: Fix Ghost Account and Modernize PWA Manifest
- Resolved 'Ghost Account' warning by updating layout hydration to align with V3 ID Vision (account_id vs account_id_random). - Improved site lookup reliability using Agent API Key and structured EQ filters for exact FQDN matching (including ports). - Modernized PWA manifest with maskable icons (PNG/WebP), app shortcuts, and unique installation IDs. - Implemented automatic Electron 'Native' mode detection in root layout. - Fixed stale API URLs in Launcher native file download logic. - Added V3 migration documentation and JWT verification test scripts.
This commit is contained in:
@@ -131,9 +131,15 @@ export async function lookup_site_domain_v3({
|
||||
delete guest_api_cfg.account_id;
|
||||
|
||||
const search_query = {
|
||||
q: fqdn
|
||||
and: [{ field: 'fqdn', op: 'eq', value: fqdn }]
|
||||
};
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`BOOTSTRAP SEARCH: fqdn=${fqdn}`);
|
||||
console.log(`BOOTSTRAP HEADERS:`, guest_api_cfg.headers);
|
||||
console.log(`BOOTSTRAP QUERY:`, JSON.stringify(search_query));
|
||||
}
|
||||
|
||||
// We use search because we are looking up by a unique field (fqdn) rather than ID.
|
||||
// The backend should return a list, but since FQDN is unique, it will have 1 item.
|
||||
const result_li = await api.search_ae_obj_v3({
|
||||
@@ -147,6 +153,8 @@ export async function lookup_site_domain_v3({
|
||||
log_lvl
|
||||
});
|
||||
|
||||
if (log_lvl) console.log(`BOOTSTRAP RESULT:`, result_li);
|
||||
|
||||
if (result_li && result_li.length > 0) {
|
||||
const result = result_li[0];
|
||||
// Standardize and save to cache
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function load_ae_obj_id__event({
|
||||
inc_device_li = false,
|
||||
inc_location_li = false,
|
||||
inc_session_li = false,
|
||||
inc_template_li = false,
|
||||
inc_template_li = false,
|
||||
try_cache = true,
|
||||
log_lvl = 0
|
||||
}: {
|
||||
@@ -104,7 +104,7 @@ export async function load_ae_obj_id__event({
|
||||
*/
|
||||
async function _handle_nested_loads(event_obj: any, { api_cfg, inc_device_li, inc_location_li, inc_session_li, inc_template_li, log_lvl }: any) {
|
||||
const current_event_id = event_obj.event_id || event_obj.id;
|
||||
|
||||
|
||||
if (inc_device_li) {
|
||||
event_obj.event_device_obj_li = await load_ae_obj_li__event_device({
|
||||
api_cfg,
|
||||
@@ -171,7 +171,7 @@ export async function load_ae_obj_li__event({
|
||||
try_cache?: boolean;
|
||||
log_lvl?: number;
|
||||
}): Promise<ae_Event[]> {
|
||||
|
||||
|
||||
// Check if offline
|
||||
if (typeof navigator !== 'undefined' && !navigator.onLine) {
|
||||
if (log_lvl) console.log('Browser is offline. Skipping API and attempting cache load.');
|
||||
@@ -182,7 +182,7 @@ export async function load_ae_obj_li__event({
|
||||
}
|
||||
|
||||
let promise;
|
||||
|
||||
|
||||
if (qry_conference !== null) {
|
||||
// V3 Search now permits 'conference' field.
|
||||
const search_query: any = {
|
||||
@@ -193,7 +193,7 @@ export async function load_ae_obj_li__event({
|
||||
if (for_obj_id) {
|
||||
search_query.and.push({ field: 'account_id_random', op: 'eq', value: for_obj_id });
|
||||
}
|
||||
|
||||
|
||||
promise = api.search_ae_obj_v3({
|
||||
api_cfg,
|
||||
obj_type: 'event',
|
||||
@@ -443,7 +443,7 @@ export async function qry_ae_obj_li__event({
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
const search_query: any = { and: [] };
|
||||
|
||||
|
||||
if (qry_str) {
|
||||
// Use reserved 'q' property for global full-text search as per V3 Guide
|
||||
search_query.q = qry_str;
|
||||
@@ -498,11 +498,11 @@ export async function qry_ae_obj_li__event({
|
||||
if (qry_physical === true || qry_virtual === true) {
|
||||
const ev_physical = ev.physical === true || ev.physical === 1 || ev.physical === '1';
|
||||
const ev_virtual = ev.virtual === true || ev.virtual === 1 || ev.virtual === '1';
|
||||
|
||||
|
||||
let match = false;
|
||||
if (qry_physical === true && ev_physical) match = true;
|
||||
if (qry_virtual === true && ev_virtual) match = true;
|
||||
|
||||
|
||||
if (!match) return false;
|
||||
}
|
||||
|
||||
@@ -624,16 +624,16 @@ export async function qry_ae_obj_li__event_v2({
|
||||
}
|
||||
|
||||
// Location Filtering (Inclusive OR logic)
|
||||
// If either filter is explicitly true, we restrict results.
|
||||
// If either filter is explicitly true, we restrict results.
|
||||
// If both are false or null, we show everything.
|
||||
if (qry_physical === true || qry_virtual === true) {
|
||||
const ev_physical = ev.physical === true || ev.physical === 1 || ev.physical === '1';
|
||||
const ev_virtual = ev.virtual === true || ev.virtual === 1 || ev.virtual === '1';
|
||||
|
||||
|
||||
let match = false;
|
||||
if (qry_physical === true && ev_physical) match = true;
|
||||
if (qry_virtual === true && ev_virtual) match = true;
|
||||
|
||||
|
||||
if (!match) return false;
|
||||
}
|
||||
|
||||
@@ -855,7 +855,7 @@ export function sync_config__event_pres_mgmt({
|
||||
pres_mgmt_cfg_remote?.hide__presentation_code ?? false;
|
||||
pres_mgmt_cfg_local.hide__presentation_datetime =
|
||||
pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
|
||||
prev_mgmt_cfg_local.show_content__presentation_description =
|
||||
pres_mgmt_cfg_local.show_content__presentation_description =
|
||||
pres_mgmt_cfg_remote?.show_content__presentation_description ?? false;
|
||||
pres_mgmt_cfg_local.hide__presenter_code =
|
||||
pres_mgmt_cfg_remote?.hide__presenter_code ?? false;
|
||||
|
||||
@@ -489,7 +489,7 @@
|
||||
|
||||
// WARNING: This function returns a list. We only want the first one. There should be no more than 1 record returned.
|
||||
// WARNING: This function returns a list. We only want the first one. There should be no more than 1 record returned.
|
||||
// We use enabled: 'all' and hidden: 'all' to ensure we find the person record even if
|
||||
// We use enabled: 'all' and hidden: 'all' to ensure we find the person record even if
|
||||
// technical fields like 'hide' are NULL or the record is temporarily disabled.
|
||||
ae_promises['person'] = core_func
|
||||
.load_ae_obj_li__person({
|
||||
@@ -596,7 +596,7 @@
|
||||
|
||||
// WARNING: This function returns a list. We only want the first one. There should be no more than 1 record returned.
|
||||
// WARNING: This function returns a list. We only want the first one. There should be no more than 1 record returned.
|
||||
// We use enabled: 'all' and hidden: 'all' to ensure we find the person record even if
|
||||
// We use enabled: 'all' and hidden: 'all' to ensure we find the person record even if
|
||||
// technical fields like 'hide' are NULL or the record is temporarily disabled.
|
||||
ae_promises['person'] = core_func
|
||||
.load_ae_obj_li__person({
|
||||
@@ -833,7 +833,7 @@
|
||||
class="top-center bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md relative mx-auto w-full divide-y"
|
||||
>
|
||||
<div class="modal-box flex flex-col gap-2 items-center justify-center">
|
||||
<!-- If the user is a global Manger or Super then they can change the password for any user. Otherwise, they can only change their own password. Show email address field for a quick lookup to get the user.id. -->
|
||||
<!-- If the user is a global Manager or Super then they can change the password for any user. Otherwise, they can only change their own password. Show email address field for a quick lookup to get the user.id. -->
|
||||
<div class="flex flex-col flex-wrap gap-2">
|
||||
<span class="text-sm text-gray-500">
|
||||
Your Username: {$ae_loc?.user?.username ?? '-- not set --'}
|
||||
|
||||
Reference in New Issue
Block a user