Migrate initial site domain lookup to Aether API CRUD V3
- Implemented lookup_site_domain_v3 in ae_core__site.ts using Search API - Refactored root +layout.ts to use the new V3 lookup logic - Standardized top-level data initialization with V3 response metadata - Improved security by transitioning to standardized V3 API patterns
This commit is contained in:
@@ -77,6 +77,46 @@ export interface Site_Domain {
|
||||
*/
|
||||
|
||||
// Updated 2026-01-06
|
||||
// Updated 2026-01-06
|
||||
export async function lookup_site_domain_v3({
|
||||
api_cfg,
|
||||
fqdn,
|
||||
view = 'default',
|
||||
log_lvl = 0
|
||||
}: {
|
||||
api_cfg: any;
|
||||
fqdn: string;
|
||||
view?: string;
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** lookup_site_domain_v3() *** fqdn=${fqdn}`);
|
||||
}
|
||||
|
||||
const search_query = {
|
||||
and: [{ field: 'fqdn', op: 'eq', value: fqdn }]
|
||||
};
|
||||
|
||||
// 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({
|
||||
api_cfg,
|
||||
obj_type: 'site_domain',
|
||||
search_query,
|
||||
view, // This view should ideally join with site and account for the root lookup
|
||||
enabled: 'enabled',
|
||||
hidden: 'all',
|
||||
limit: 1,
|
||||
log_lvl
|
||||
});
|
||||
|
||||
if (result_li && result_li.length > 0) {
|
||||
return result_li[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function load_ae_obj_id__site({
|
||||
api_cfg,
|
||||
site_id,
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
// console.log(`ae_root +layout.ts: start`);
|
||||
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
// import { api } from '$lib/api';
|
||||
// import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/ae_stores';
|
||||
import { add_url_params, clean_headers } from '$lib/ae_core/core__api_helpers';
|
||||
import { lookup_site_domain_v3 } from '$lib/ae_core/ae_core__site';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
import {
|
||||
@@ -34,9 +31,9 @@ const ae_api_init: key_val = {
|
||||
ver: '2024-08-11_11',
|
||||
base_url: api_base_url,
|
||||
base_url_bak: api_base_url_bak,
|
||||
api_secret_key: api_secret_key, // 'YOUR_API_SECRET_KEY',
|
||||
api_secret_key_bak: api_secret_key, // 'YOUR_API_SECRET_KEY',
|
||||
api_crud_super_key: api_crud_super_key, // 'YOUR_SUPER_KEY' 'zp5PtX4zUsI'
|
||||
api_secret_key: api_secret_key,
|
||||
api_secret_key_bak: api_secret_key,
|
||||
api_crud_super_key: api_crud_super_key,
|
||||
headers: {},
|
||||
account_id: ae_account_id
|
||||
};
|
||||
@@ -49,8 +46,6 @@ ae_api_headers['x-aether-api-token'] = 'fake-temp-token';
|
||||
ae_api_headers['x-aether-api-expire-on'] = '';
|
||||
if (ae_account_id) {
|
||||
ae_api_headers['x-account-id'] = ae_account_id;
|
||||
} else {
|
||||
// ae_api_headers['x-account-id'] = ;
|
||||
}
|
||||
if (ae_no_account_id) {
|
||||
ae_api_headers['x-no-account-id'] = ae_no_account_id;
|
||||
@@ -58,21 +53,10 @@ if (ae_no_account_id) {
|
||||
|
||||
ae_api_init['headers'] = ae_api_headers;
|
||||
|
||||
const ae_loc_init: key_val = {};
|
||||
|
||||
// export const prerender = false;
|
||||
|
||||
// There is not an initial data store from SvelteKit for this, so we will just use the API to get the data.
|
||||
// properties: params, route, url
|
||||
// functions: fetch, setHeaders, parent, depends, untrack
|
||||
export async function load({ fetch, params, parent, route, url }) {
|
||||
// params, route, url
|
||||
const log_lvl: number = 0;
|
||||
// console.log(`Svelte root +layout.ts params:`, params);
|
||||
// console.log(`Svelte root +layout.ts route:`, route);
|
||||
// console.log(`Svelte root +layout.ts url:`, url);
|
||||
const log_lvl: number = 1;
|
||||
|
||||
let account_id: any; // Promise<any>;
|
||||
let account_id: any;
|
||||
|
||||
const ae_acct: key_val = {
|
||||
api: ae_api_init,
|
||||
@@ -87,209 +71,106 @@ export async function load({ fetch, params, parent, route, url }) {
|
||||
slct: {}
|
||||
};
|
||||
|
||||
// let ae_loc_tmp = get(ae_loc);
|
||||
// console.log(`ae_loc = `, ae_loc_tmp);
|
||||
|
||||
// let ae_api_tmp = get(ae_api);
|
||||
// console.log(`ae_api = `, ae_api_tmp);
|
||||
// Initialize API fetch with SvelteKit fetch
|
||||
ae_api_init['fetch'] = fetch;
|
||||
|
||||
const ae_loc_init: key_val = {};
|
||||
const ds_code_li: null | key_val = {};
|
||||
// if (ae_loc_tmp && ae_loc_tmp.ds) {
|
||||
// ds_code_li = ae_loc_tmp.ds;
|
||||
// }
|
||||
// console.log(`ae_ ds_code_li = `, ds_code_li);
|
||||
const ds_code: null | string = null;
|
||||
|
||||
const data_struct: key_val = {
|
||||
// ae_acct should only be updated and referenced by the corresponding account_id.
|
||||
account_id: null,
|
||||
ae_acct: {
|
||||
// '_XY7DXtc9MY': ae_acct,
|
||||
},
|
||||
|
||||
ae_acct: {},
|
||||
ae_loc: {},
|
||||
ae_api: ae_api_init,
|
||||
ae_ds: {},
|
||||
ae_hub: {}, // was ae_core
|
||||
ae_hub: {},
|
||||
ae_m_sponsorships: {},
|
||||
ae_m_events: {},
|
||||
ae_m_events_speakers: {},
|
||||
ae_slct: {},
|
||||
|
||||
iframe: false,
|
||||
|
||||
ae_root_layout_ts: true,
|
||||
|
||||
params: params,
|
||||
route: route,
|
||||
url: url,
|
||||
|
||||
// Not really used yet
|
||||
sections: [
|
||||
{ slug: 'new', title: 'New Test' },
|
||||
{ slug: 'manage', title: 'Manage Test' },
|
||||
{ slug: 'test', title: 'Test Test' }
|
||||
],
|
||||
|
||||
// Not really used yet
|
||||
submenu: {}
|
||||
};
|
||||
|
||||
// let parent_data = await parent();
|
||||
// console.log(`root +layout.ts parent_data:`, parent_data);
|
||||
|
||||
// First do a site_domain look up to check if it is valid and get the account_id.
|
||||
// ae_loc.url_host = data.url.host; // Use this to look up? sub.example.com:123
|
||||
// ae_loc.fqdn = url.host; // Use this to look up? sub.example.com:123
|
||||
// ae_loc.url_hostname = parent_data.url.hostname; // sub.example.com
|
||||
// ae_loc.url_origin = parent_data.url.origin; // Use this to look up? https://sub.example.com:123
|
||||
// ae_loc.site_domain = data.url.origin;
|
||||
// console.log(`ae_loc = `, ae_loc);
|
||||
|
||||
const fqdn = url.host;
|
||||
const api_endpoint = `/crud/site/domain/${fqdn}`;
|
||||
|
||||
const api_params: any = {
|
||||
use_alt_table: true,
|
||||
use_alt_base: true
|
||||
};
|
||||
|
||||
const api_url_str = add_url_params({
|
||||
base_url: ae_api_init['base_url'],
|
||||
endpoint: api_endpoint,
|
||||
params: api_params,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
let headers: any = {
|
||||
'x-no-account-id': 'Nothing to See Here'
|
||||
};
|
||||
|
||||
headers = clean_headers({
|
||||
headers: headers,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
|
||||
const fetchOptions: RequestInit = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
...ae_api_init['headers'],
|
||||
...headers
|
||||
}
|
||||
// signal: controller.signal
|
||||
};
|
||||
|
||||
const result = await fetch(api_url_str, fetchOptions)
|
||||
.then(async function (response) {
|
||||
if (response.ok) {
|
||||
const json_raw = await response.json();
|
||||
// console.log(`ALERT json_raw = `, json_raw);
|
||||
|
||||
let json_data: any = null;
|
||||
|
||||
if (json_raw.data) {
|
||||
json_data = json_raw.data;
|
||||
account_id = json_data.account_id_random;
|
||||
data_struct.account_id = json_data.account_id_random;
|
||||
ae_acct.account_id = json_data.account_id_random;
|
||||
|
||||
ae_api_init['account_id'] = json_data.account_id_random;
|
||||
ae_api_init['fetch'] = fetch;
|
||||
// ae_api_init['fetch'] = null;
|
||||
ae_api_init['headers']['x-account-id'] = json_data.account_id_random;
|
||||
ae_api_init['headers']['x-no-account-id'] = null;
|
||||
|
||||
ae_loc_init['account_id'] = json_data.account_id_random;
|
||||
ae_loc_init['account_code'] = json_data.account_code; // Useful for export file naming
|
||||
ae_loc_init['account_name'] = json_data.account_name; // Generally useful for display
|
||||
|
||||
ae_loc_init['site_id'] = json_data.site_id_random;
|
||||
ae_loc_init['site_domain_id'] = json_data.site_domain_id_random;
|
||||
ae_loc_init['site_enable'] = json_data.enable;
|
||||
ae_loc_init['site_header_image_path'] = json_data.header_image_path;
|
||||
ae_loc_init['site_style_href'] = json_data.style_href;
|
||||
ae_loc_init['site_google_tracking_id'] = json_data.google_tracking_id;
|
||||
ae_loc_init['site_access_code_kv'] = json_data.access_code_kv_json;
|
||||
ae_loc_init['site_cfg_json'] = json_data.cfg_json;
|
||||
ae_loc_init['site_access_key'] = json_data.access_key; // This is the general site access key
|
||||
ae_loc_init['site_domain_access_key'] = json_data.site_domain_access_key; // This is specific to a (sub)domain.
|
||||
|
||||
ae_loc_init['base_url'] = url.origin;
|
||||
ae_loc_init['hostname'] = url.hostname;
|
||||
|
||||
if (!ae_loc_init['site_access_key'] && !ae_loc_init['site_domain_access_key']) {
|
||||
ae_loc_init['key_checked'] = true; // Se to true to allow access without a key.
|
||||
ae_loc_init['allow_access'] = true; // No access key is required here.
|
||||
} else {
|
||||
const access_key = url.searchParams.get('key'); // Technically this is the site's auth key.
|
||||
|
||||
if (access_key) {
|
||||
if (log_lvl) {
|
||||
console.log(`root +layout.ts: access_key = ${access_key}`);
|
||||
}
|
||||
if (access_key == ae_loc_init['site_access_key']) {
|
||||
ae_loc_init['key_checked'] = ae_loc_init['site_access_key'];
|
||||
ae_loc_init['allow_access'] = ae_loc_init['site_access_key'];
|
||||
} else if (access_key == ae_loc_init['site_domain_access_key']) {
|
||||
ae_loc_init['key_checked'] = ae_loc_init['site_domain_access_key'];
|
||||
ae_loc_init['allow_access'] = ae_loc_init['site_domain_access_key'];
|
||||
} else {
|
||||
// The key changed and no longer matches the site or domain key.
|
||||
ae_loc_init['key_checked'] = true;
|
||||
ae_loc_init['allow_access'] = false;
|
||||
}
|
||||
} else {
|
||||
if (log_lvl > 1) {
|
||||
console.log(`root +layout.ts: No access key found in URL.`);
|
||||
}
|
||||
ae_loc_init['key_checked'] = true;
|
||||
// Do nothing to change the allow_access here
|
||||
// ae_loc_init['allow_access'] = false; // An access key is required at this point.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
'API GET Object *fetch* response was missing the JSON "data" part. This should not happen.'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return json_data; // || json_raw;
|
||||
} else if (response.status === 404) {
|
||||
console.log('API GET Object *fetch* response was a 404 not found.');
|
||||
return null;
|
||||
} else {
|
||||
console.log('API GET Object *fetch* request was not ok for some other reason.');
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(
|
||||
'API GET Object *fetch* request was aborted or failed in an unexpected way.',
|
||||
err
|
||||
);
|
||||
error(500, {
|
||||
message:
|
||||
'Site lookup aborted or failed! Check the network connection, domain name, and API.'
|
||||
});
|
||||
|
||||
const result = await lookup_site_domain_v3({
|
||||
api_cfg: ae_api_init,
|
||||
fqdn,
|
||||
view: 'base',
|
||||
log_lvl
|
||||
}).catch((err) => {
|
||||
console.log('Site lookup failed in root layout.', err);
|
||||
error(500, {
|
||||
message: 'Site lookup aborted or failed! Check network and API.'
|
||||
});
|
||||
if (log_lvl > 1) {
|
||||
console.log(`ALERT response = `, result);
|
||||
}
|
||||
});
|
||||
|
||||
if (result === null) {
|
||||
error(403, {
|
||||
message: 'The site lookup failed! Check that the domain name is configured and enabled.'
|
||||
});
|
||||
} else if (result === false) {
|
||||
error(500, {
|
||||
message: 'Site lookup failed or returned an unexpected response! Check the API.'
|
||||
});
|
||||
}
|
||||
|
||||
// log_lvl = 0;
|
||||
if (log_lvl > 1) {
|
||||
console.log(`root +layout.ts: Using account_id = `, account_id);
|
||||
console.log(`root +layout.ts: ae_loc_init = `, ae_loc_init);
|
||||
const json_data = result;
|
||||
account_id = json_data.account_id_random;
|
||||
data_struct.account_id = json_data.account_id_random;
|
||||
ae_acct.account_id = json_data.account_id_random;
|
||||
|
||||
ae_api_init['account_id'] = json_data.account_id_random;
|
||||
ae_api_init['headers']['x-account-id'] = json_data.account_id_random;
|
||||
ae_api_init['headers']['x-no-account-id'] = null;
|
||||
|
||||
ae_loc_init['account_id'] = json_data.account_id_random;
|
||||
ae_loc_init['account_code'] = json_data.account_code;
|
||||
ae_loc_init['account_name'] = json_data.account_name;
|
||||
|
||||
ae_loc_init['site_id'] = json_data.site_id_random;
|
||||
ae_loc_init['site_domain_id'] = json_data.site_domain_id_random;
|
||||
ae_loc_init['site_enable'] = json_data.enable;
|
||||
ae_loc_init['site_header_image_path'] = json_data.header_image_path;
|
||||
ae_loc_init['site_style_href'] = json_data.style_href;
|
||||
ae_loc_init['site_google_tracking_id'] = json_data.google_tracking_id;
|
||||
ae_loc_init['site_access_code_kv'] = json_data.access_code_kv_json;
|
||||
ae_loc_init['site_cfg_json'] = json_data.cfg_json;
|
||||
ae_loc_init['site_access_key'] = json_data.access_key;
|
||||
ae_loc_init['site_domain_access_key'] = json_data.site_domain_access_key;
|
||||
|
||||
ae_loc_init['base_url'] = url.origin;
|
||||
ae_loc_init['hostname'] = url.hostname;
|
||||
|
||||
if (!ae_loc_init['site_access_key'] && !ae_loc_init['site_domain_access_key']) {
|
||||
ae_loc_init['key_checked'] = true;
|
||||
ae_loc_init['allow_access'] = true;
|
||||
} else {
|
||||
const access_key = url.searchParams.get('key');
|
||||
|
||||
if (access_key) {
|
||||
if (log_lvl) {
|
||||
console.log(`root +layout.ts: access_key = ${access_key}`);
|
||||
}
|
||||
if (access_key == ae_loc_init['site_access_key']) {
|
||||
ae_loc_init['key_checked'] = ae_loc_init['site_access_key'];
|
||||
ae_loc_init['allow_access'] = ae_loc_init['site_access_key'];
|
||||
} else if (access_key == ae_loc_init['site_domain_access_key']) {
|
||||
ae_loc_init['key_checked'] = ae_loc_init['site_domain_access_key'];
|
||||
ae_loc_init['allow_access'] = ae_loc_init['site_domain_access_key'];
|
||||
} else {
|
||||
ae_loc_init['key_checked'] = true;
|
||||
ae_loc_init['allow_access'] = false;
|
||||
}
|
||||
} else {
|
||||
ae_loc_init['key_checked'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!account_id) {
|
||||
@@ -305,18 +186,12 @@ export async function load({ fetch, params, parent, route, url }) {
|
||||
account_id: account_id,
|
||||
site_domain_id: ae_loc_init.site_domain_id,
|
||||
site_id: ae_loc_init.site_id,
|
||||
|
||||
// For events_leads, events_badges, events_speakers
|
||||
event_id: ae_loc_init.site_cfg_json?.slct__event_id,
|
||||
event_badge_template_id: ae_loc_init.site_cfg_json?.slct__event_badge_template_id,
|
||||
|
||||
// For sponsorships
|
||||
sponsorship_cfg_id: ae_loc_init.site_cfg_json?.slct__sponsorship_cfg_id
|
||||
};
|
||||
// console.log(`ae_acct = `, ae_acct);
|
||||
|
||||
// WARNING: Using the Account ID is a precaution against shared data between other accounts (sites and sessions).
|
||||
data_struct[ae_loc_init.account_id] = ae_acct;
|
||||
|
||||
return data_struct;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user