Lots of work on user person security. Also some general clean up. Wrapping up for the day.
This commit is contained in:
@@ -18,6 +18,16 @@ import {
|
||||
// handle_db_save_ae_obj_li__person
|
||||
} from "$lib/ae_core/core__person";
|
||||
|
||||
import {
|
||||
auth_ae_obj__username_password,
|
||||
auth_ae_obj__user_id_user_auth_key,
|
||||
// handle_load_ae_obj_id__user,
|
||||
// handle_load_ae_obj_li__user,
|
||||
// handle_create_ae_obj__user,
|
||||
// handle_update_ae_obj__user,
|
||||
// handle_db_save_ae_obj_li__user
|
||||
} from "$lib/ae_core/core__user";
|
||||
|
||||
import {
|
||||
generate_qr_code,
|
||||
} from "$lib/ae_core/core__qr_code";
|
||||
@@ -430,6 +440,8 @@ let export_obj = {
|
||||
handle_load_ae_obj_li__person: handle_load_ae_obj_li__person,
|
||||
handle_create_ae_obj__person: handle_create_ae_obj__person,
|
||||
handle_update_ae_obj__person: handle_update_ae_obj__person,
|
||||
auth_ae_obj__username_password: auth_ae_obj__username_password,
|
||||
auth_ae_obj__user_id_user_auth_key: auth_ae_obj__user_id_user_auth_key,
|
||||
handle_update_ae_obj_id_crud: handle_update_ae_obj_id_crud,
|
||||
handle_download_export__obj_type: handle_download_export__obj_type,
|
||||
generate_qr_code: generate_qr_code
|
||||
|
||||
@@ -55,37 +55,46 @@ export async function handle_load_ae_obj_id__person(
|
||||
export async function handle_load_ae_obj_li__person(
|
||||
{
|
||||
api_cfg,
|
||||
account_id,
|
||||
for_obj_type = 'account',
|
||||
for_obj_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 99,
|
||||
offset = 0,
|
||||
order_by_li = {'start_datetime': 'DESC', 'name': 'ASC', 'updated_on': 'DESC', 'created_on': 'DESC'},
|
||||
params_json = null,
|
||||
params={},
|
||||
try_cache=true,
|
||||
log_lvl=0
|
||||
}: {
|
||||
api_cfg: any,
|
||||
account_id: string,
|
||||
for_obj_type: string,
|
||||
for_obj_id: string,
|
||||
enabled?: string,
|
||||
hidden?: string,
|
||||
limit?: number,
|
||||
offset?: number,
|
||||
order_by_li?: key_val,
|
||||
params_json?: null|key_val,
|
||||
params?: key_val,
|
||||
try_cache?: boolean,
|
||||
log_lvl?: number
|
||||
}
|
||||
) {
|
||||
console.log(`*** handle_load_ae_obj_li__person() *** account_id=${account_id}`);
|
||||
|
||||
let enabled: string = (params.qry__enabled ?? 'enabled'); // all, disabled, enabled
|
||||
let hidden: string = (params.qry__hidden ?? 'not_hidden'); // all, hidden, not_hidden
|
||||
let limit: number = (params.qry__limit ?? 99); // 99
|
||||
let offset: number = (params.qry__offset ?? 0); // 0
|
||||
|
||||
|
||||
let params_json: key_val = {};
|
||||
console.log(`*** handle_load_ae_obj_li__person() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id} enabled=${enabled} hidden=${hidden} limit=${limit} offset=${offset}`);
|
||||
|
||||
// console.log('params_json:', params_json);
|
||||
|
||||
ae_promises.load__person_obj_li = await api.get_ae_obj_li_for_obj_id_crud({
|
||||
ae_promises.load__person_obj_li = await api.get_ae_obj_li_for_obj_id_crud_v2({
|
||||
api_cfg: api_cfg,
|
||||
obj_type: 'person',
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: account_id,
|
||||
use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value
|
||||
for_obj_id: for_obj_id,
|
||||
use_alt_tbl: false,
|
||||
use_alt_mdl: false,
|
||||
use_alt_exp: false,
|
||||
// use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config.
|
||||
// use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value
|
||||
enabled: enabled,
|
||||
hidden: hidden,
|
||||
order_by_li: {'given_name': 'ASC', 'family_name': 'ASC', 'updated_on': 'DESC', 'created_on': 'DESC'},
|
||||
|
||||
136
src/lib/ae_core/core__user.ts
Normal file
136
src/lib/ae_core/core__user.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import type { key_val } from '$lib/ae_stores';
|
||||
import { api } from '$lib/api';
|
||||
|
||||
import { db_core } from "$lib/ae_core/db_core";
|
||||
|
||||
let ae_promises: key_val = {};
|
||||
|
||||
|
||||
// Updated 2025-04-04
|
||||
export async function auth_ae_obj__username_password(
|
||||
{
|
||||
api_cfg,
|
||||
account_id,
|
||||
null_account_id = false,
|
||||
username,
|
||||
password,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 1
|
||||
}: {
|
||||
api_cfg: any,
|
||||
account_id: string,
|
||||
null_account_id?: boolean,
|
||||
username: string,
|
||||
password: string,
|
||||
params?: key_val,
|
||||
try_cache?: boolean,
|
||||
log_lvl?: number
|
||||
}
|
||||
) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** auth_ae_obj__username_password() *** account_id=${account_id} username=${username} password=${password}`);
|
||||
}
|
||||
|
||||
let endpoint = '/user/authenticate';
|
||||
|
||||
if (null_account_id) {
|
||||
params['null_account_id'] = true;
|
||||
}
|
||||
params['username'] = username; // Required
|
||||
params['password'] = password; // Required
|
||||
if (log_lvl > 1) {
|
||||
console.log(`auth_ae_obj__username_password() - params:`, params);
|
||||
}
|
||||
|
||||
ae_promises.auth__username_password = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
// data: {},
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (user_obj_get_result) {
|
||||
if (user_obj_get_result) {
|
||||
// if (try_cache) {
|
||||
// // This is expecting a list
|
||||
// db_save_ae_obj_li__user({
|
||||
// obj_type: 'user',
|
||||
// obj_li: [user_obj_get_result],
|
||||
// log_lvl: log_lvl
|
||||
// });
|
||||
// }
|
||||
return user_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.auth__username_password:', ae_promises.auth__username_password);
|
||||
}
|
||||
return ae_promises.auth__username_password;
|
||||
}
|
||||
|
||||
|
||||
// Updated 2025-04-04
|
||||
export async function auth_ae_obj__user_id_user_auth_key(
|
||||
{
|
||||
api_cfg,
|
||||
account_id,
|
||||
user_id,
|
||||
user_auth_key,
|
||||
params = {},
|
||||
try_cache = true,
|
||||
log_lvl = 1
|
||||
}: {
|
||||
api_cfg: any,
|
||||
account_id: string,
|
||||
user_id: string,
|
||||
user_auth_key: string,
|
||||
params?: key_val,
|
||||
try_cache?: boolean,
|
||||
log_lvl?: number
|
||||
}
|
||||
) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** auth_ae_obj__user_id_user_auth_key() *** account_id=${account_id} user_id=${user_id}`);
|
||||
}
|
||||
|
||||
let endpoint = '/user/authenticate';
|
||||
|
||||
params['user_id'] = user_id; // Required
|
||||
params['auth_key'] = user_auth_key; // Required
|
||||
if (log_lvl > 1) {
|
||||
console.log(`auth_ae_obj__user_id_user_auth_key() - params:`, params);
|
||||
}
|
||||
|
||||
ae_promises.auth__user_id_user_key = await api.get_object({
|
||||
api_cfg: api_cfg,
|
||||
endpoint: endpoint,
|
||||
params: params,
|
||||
log_lvl: log_lvl
|
||||
})
|
||||
.then(async function (user_obj_get_result) {
|
||||
if (user_obj_get_result) {
|
||||
return user_obj_get_result;
|
||||
} else {
|
||||
console.log('No results returned.');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log('No results returned or failed.', error);
|
||||
});
|
||||
|
||||
if (log_lvl) {
|
||||
console.log('ae_promises.auth__user_id_user_key:', ae_promises.auth__user_id_user_key);
|
||||
}
|
||||
return ae_promises.auth__user_id_user_key;
|
||||
}
|
||||
@@ -299,6 +299,7 @@ export class MySubClassedDexie extends Dexie {
|
||||
id, journal_id,
|
||||
code,
|
||||
account_id,
|
||||
person_id,
|
||||
conference, type,
|
||||
name,
|
||||
start_datetime, end_datetime,
|
||||
|
||||
@@ -102,6 +102,37 @@ export let ae_app_local_data_struct: key_val = {
|
||||
|
||||
'user_email': null, // Currently used with Sponsorships only?
|
||||
|
||||
// Added 2025-04-04
|
||||
person_id: null, // The current person_id of the logged-in user (if any)
|
||||
person: {
|
||||
id: null, // The current person_id of the logged-in user
|
||||
// profile_id: null, // The current person_profile_id of the logged-in user
|
||||
// pronouns: null,
|
||||
// informal_name: null,
|
||||
// given_name: null,
|
||||
// family_name: null,
|
||||
// professional_title: null,
|
||||
full_name: null, // convenience
|
||||
// affiliations: null,
|
||||
primary_email: null, // The primary email of the logged-in person/user
|
||||
user_id: null, // The user ID of the logged-in user
|
||||
},
|
||||
|
||||
// Added 2025-04-04
|
||||
user_id: null, // The current user_id of the logged-in user (if any)
|
||||
user: {
|
||||
id: null, // The current user_id of the logged-in user
|
||||
username: null,
|
||||
name: null,
|
||||
email: null, // The email of the logged-in user
|
||||
allow_auth_key: null, // For sign in without password
|
||||
super: false, // Is the user a super user
|
||||
manager: false, // Is the user a global manager (can manage accounts and users)
|
||||
administrator: false, // Is the user an account administrator
|
||||
public: false, // Is the user a public user (can view public content)
|
||||
person_id: null, // The person ID of the logged-in user
|
||||
},
|
||||
|
||||
'qry__enabled': 'enabled', // all, disabled, enabled
|
||||
'qry__hidden': 'not_hidden', // all, hidden, not_hidden
|
||||
'qry__limit': 20,
|
||||
@@ -118,6 +149,7 @@ export let ae_app_local_data_struct: key_val = {
|
||||
show_element__access_type: true,
|
||||
show_element__cfg: true,
|
||||
show_element__cfg_detail: false,
|
||||
show_element__sign_in_out: true, // Show the sign-in/out button in the UI
|
||||
show_opt__debug: true,
|
||||
show_opt__permissions: true,
|
||||
show_opt__reset: true,
|
||||
|
||||
@@ -166,34 +166,6 @@ function handle_clear_access() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// function dispatch_access_type_changed() {
|
||||
// if (log_lvl) {
|
||||
// console.log('*** dispatch_access_type_changed() ***');
|
||||
|
||||
// console.log(ae_util);
|
||||
// console.log($ae_loc);
|
||||
// }
|
||||
|
||||
// dispatch('access_type_changed', {
|
||||
// access_type: $ae_loc.access_type
|
||||
// });
|
||||
// }
|
||||
|
||||
// function dispatch_edit_mode_changed() {
|
||||
// if (log_lvl) {
|
||||
// console.log('*** dispatch_edit_mode_changed() ***');
|
||||
|
||||
// console.log(ae_util);
|
||||
// console.log($ae_loc);
|
||||
// }
|
||||
|
||||
// window.localStorage.setItem('edit_mode', $ae_loc.edit_mode);
|
||||
|
||||
// dispatch('edit_mode_changed', {
|
||||
// edit_mode: $ae_loc.edit_mode
|
||||
// });
|
||||
// }
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@@ -288,8 +288,8 @@ function handle_clear_storage(item: null|string) {
|
||||
/* position: relative; */
|
||||
/* position: static; */
|
||||
/* position: sticky; */
|
||||
/* top: 1em; */
|
||||
bottom: 1.5rem;
|
||||
top: 4.5em;
|
||||
/* bottom: 9.5rem; */
|
||||
left: 0rem;
|
||||
|
||||
padding: .5rem;
|
||||
|
||||
516
src/lib/element_sign_in_out.svelte
Normal file
516
src/lib/element_sign_in_out.svelte
Normal file
@@ -0,0 +1,516 @@
|
||||
<script lang="ts">
|
||||
|
||||
// *** Import Svelte specific
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
// *** Import other supporting libraries
|
||||
import {
|
||||
LogIn, LogOut, LockKeyhole,
|
||||
User
|
||||
} from '@lucide/svelte';
|
||||
|
||||
// *** Import Aether specific variables and functions
|
||||
import type { key_val } from '$lib/ae_stores';
|
||||
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/ae_stores';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { core_func } from '$lib/ae_core/ae_core_functions';
|
||||
|
||||
// *** Setup Svelte properties
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
data?: any;
|
||||
hidden: null|boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
log_lvl = 0,
|
||||
data = null,
|
||||
hidden = true,
|
||||
}: Props = $props();
|
||||
|
||||
|
||||
let url_user_id = data.url.searchParams.get('user_id');
|
||||
let url_user_key = data.url.searchParams.get('user_key'); // Reminder that "key" is the site's auth key.
|
||||
|
||||
let ae_promises: key_val = {};
|
||||
|
||||
|
||||
// let user_id: string|null = null;
|
||||
// let user_obj: key_val = {};
|
||||
|
||||
// let person_id: string|null = null;
|
||||
// let person_obj: key_val = {};
|
||||
|
||||
let trigger: null|boolean = $state(null); // Use $state to ensure reactivity
|
||||
let user_id = $state(null); // Use $state to ensure reactivity
|
||||
let user_obj: key_val = $state({}); // Use $state to ensure reactivity
|
||||
let person_id = $state(null); // Use $state to ensure reactivity
|
||||
let person_obj: key_val = $state({}); // Use $state to ensure reactivity
|
||||
|
||||
$effect(() => {
|
||||
if (user_id && person_id && trigger) {
|
||||
// alert(`Ready to sign in person! \n\nuser_id: ${user_id}\nperson_id: ${person_id}\n\nThis is a test alert to confirm the values are set.`);
|
||||
trigger = false;
|
||||
sign_in();
|
||||
}
|
||||
});
|
||||
|
||||
function sign_in() {
|
||||
$ae_loc.person_id = person_id; // Set the person_id in the ae_loc store
|
||||
$ae_loc.person = person_obj; // Store the full person object for reference
|
||||
$ae_loc.user_id = user_id; // Set the user_id in the ae_loc store
|
||||
$ae_loc.user = user_obj; // Store the full user object for reference
|
||||
|
||||
if (user_obj.super) {
|
||||
$ae_loc.access_type = 'super';
|
||||
} else if (user_obj.manager) {
|
||||
$ae_loc.access_type = 'manager';
|
||||
} else if (user_obj.administrator) {
|
||||
$ae_loc.access_type = 'administrator';
|
||||
} else if (user_obj.verified) {
|
||||
// They are "trusted" because the user has been verified. External staff usually start with this level.
|
||||
$ae_loc.access_type = 'trusted';
|
||||
} else if (user_obj.public) {
|
||||
$ae_loc.access_type = 'public';
|
||||
} else {
|
||||
$ae_loc.access_type = 'authenticated';
|
||||
}
|
||||
|
||||
let access_checks_results = ae_util.process_permission_checks($ae_loc.access_type);
|
||||
// WARNING: I think this is causing a loop in Svelte or something.
|
||||
// Last ten effects were:
|
||||
// Uncaught Svelte error: effect_update_depth_exceeded
|
||||
// Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops
|
||||
// https://svelte.dev/e/effect_update_depth_exceeded
|
||||
$ae_loc = {
|
||||
...$ae_loc,
|
||||
...access_checks_results
|
||||
};
|
||||
// $ae_loc = {...access_checks_results};
|
||||
}
|
||||
|
||||
function sign_out() {
|
||||
// Clear the session information
|
||||
$ae_loc.person_id = null;
|
||||
$ae_loc.person = {};
|
||||
$ae_loc.user_id = null;
|
||||
$ae_loc.user = {};
|
||||
|
||||
user_id = null; // Clear the user_id
|
||||
user_obj = {}; // Clear the user object
|
||||
person_id = null; // Clear the person_id
|
||||
person_obj = {}; // Clear the person object
|
||||
|
||||
$ae_loc.access_type = ''; // Clear the access type
|
||||
let access_checks_results = ae_util.process_permission_checks('');
|
||||
$ae_loc = {...$ae_loc, ...access_checks_results};
|
||||
|
||||
console.log('Signed out successfully.');
|
||||
}
|
||||
|
||||
|
||||
if (browser) {
|
||||
if (url_user_id) {
|
||||
// Pre-fill the auth__entered_user_id if passed in via the URL.
|
||||
$ae_sess.auth__entered_user_id = url_user_id;
|
||||
}
|
||||
if (url_user_key) {
|
||||
// Pre-fill the auth__entered_key if passed in via the URL.
|
||||
$ae_sess.auth__entered_user_key = url_user_key;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<!-- It is important to keep in mind that a Person can only fully sign in if they have a linked User record. -->
|
||||
<!-- *:hover:inline -->
|
||||
<section
|
||||
id="AE-Sign-In-Out"
|
||||
class="
|
||||
ae_sign_in_out
|
||||
hidden-print
|
||||
bg-surface-100 text-surface-800
|
||||
transition-all duration-300 delay-150 hover:delay-1000 hover:ease-out hover:transition-all
|
||||
flex flex-col flex-wrap items-start gap-1
|
||||
"
|
||||
class:hidden={hidden}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm variant-outline-surface hover:variant-filled-surface"
|
||||
title="Sign In"
|
||||
onclick={() => {
|
||||
$ae_sess.show__sign_in_out__fields = !$ae_sess.show__sign_in_out__fields; // Toggle the visibility of the sign-in form
|
||||
}}
|
||||
>
|
||||
{#if $ae_loc?.person_id && $ae_loc?.user_id}
|
||||
|
||||
{#if $ae_sess.show__sign_in_out__fields}
|
||||
Hide Sign-In Options
|
||||
{:else}
|
||||
<User class="mx-1 inline-block text-gray-500" />
|
||||
{$ae_loc?.person.full_name ?? '-- not set --'}
|
||||
{/if}
|
||||
{:else}
|
||||
|
||||
{#if $ae_sess.show__sign_in_out__fields}
|
||||
Hide Sign-In Options
|
||||
{:else}
|
||||
<LockKeyhole size="1.25em" class="mx-1 inline-block text-gray-500" />
|
||||
<!-- <User class="mx-1 inline-block text-gray-500" /> -->
|
||||
Sign-In?
|
||||
{/if}
|
||||
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<header
|
||||
class:hidden={!$ae_sess.show__sign_in_out__fields}
|
||||
class="ae_header"
|
||||
>
|
||||
<h2 class="text-sm">
|
||||
{#if $ae_loc?.person_id && $ae_loc?.user_id}
|
||||
<!-- <button
|
||||
type="button"
|
||||
class="btn btn-sm variant-outline-surface hover:variant-filled-surface"
|
||||
title="Show/Hide Sign-In/Out Options"
|
||||
onclick={() => {
|
||||
$ae_sess.show__sign_in_out__fields = !$ae_sess.show__sign_in_out__fields; // Toggle the visibility of the sign-in form
|
||||
}}
|
||||
> -->
|
||||
{$ae_loc?.person.full_name ?? '-- not set --'}
|
||||
<!-- <span class="text-sm text-gray-500">
|
||||
{$ae_loc?.user.username ?? '-- not set --'}
|
||||
</span> -->
|
||||
<!-- {#if log_lvl > 1}
|
||||
<span class="text-xs text-gray-500">({$ae_loc.person_id} / {$ae_loc.user_id})</span>
|
||||
{/if} -->
|
||||
<!-- </button> -->
|
||||
{:else}
|
||||
<!-- <LogIn class="mx-1" /> -->
|
||||
Sign In
|
||||
|
||||
{/if}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<span
|
||||
class:hidden={!$ae_sess.show__sign_in_out__fields}
|
||||
class="transition-all"
|
||||
>
|
||||
{#if !$ae_loc?.person_id && !$ae_loc?.user_id}
|
||||
<!-- We need to get the person's linked User ID and auth_key or User username and password to sign in. -->
|
||||
|
||||
<form
|
||||
class="ae_sign_in_form flex flex-col items-start gap-1"
|
||||
onsubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// WARNING: Logging in as a global user does not work yet. The API needs to be updated. Currently it returns multiple user records from the v_user view if there is more than one person record linked to the user ID.
|
||||
|
||||
if ($ae_sess.auth__entered_user_id && $ae_sess.auth__entered_user_key) {
|
||||
|
||||
// Try to use the user ID and user auth key passed in the URL params for authentication
|
||||
alert('Attempting to authenticate with User ID and Auth Key.');
|
||||
|
||||
ae_promises['user'] = await core_func.auth_ae_obj__user_id_user_auth_key({
|
||||
api_cfg: $ae_api,
|
||||
account_id: $ae_loc.account_id,
|
||||
// null_account_id: false, // Set to true to allow to authenticate as global user (Super or Manager)
|
||||
user_id: $ae_sess.auth__entered_user_id,
|
||||
user_auth_key: $ae_sess.auth__entered_user_key,
|
||||
log_lvl: 2,
|
||||
}).then((user_response) => {
|
||||
// console.log(`HERE:`, user_response);
|
||||
if (user_response.user_id_random) {
|
||||
console.log(`Successfully authenticated in with User ID and User Auth Key: ${user_response.username}`, user_response);
|
||||
user_obj = user_response; // Store the user object for later use
|
||||
user_id = user_obj.user_id_random; // Use the user_id_random for further API calls
|
||||
// person_id = user_obj.person_id_random;
|
||||
} else {
|
||||
alert('Failed to authenticate: ' + user_response.error);
|
||||
}
|
||||
}).then((response) => {
|
||||
if (!user_id) {
|
||||
// If we didn't get a user_id, return early
|
||||
console.error('No user_id obtained from auth_ae_obj__username_password');
|
||||
return;
|
||||
}
|
||||
|
||||
// Next we need to get the person's information. This is odd because we need to look it up based on the account_id and user_id. There should only be one account person record per user. 99% of the time the user's account ID will be the same as the person's account ID. The exception is for AE Global users (Super or Manager) who can have multiple accounts but only one person record per account.
|
||||
|
||||
let params = {
|
||||
user_id_random: user_id, // The user_id_random from the above authentication
|
||||
}
|
||||
|
||||
let params_json: key_val = {};
|
||||
|
||||
params_json['and_qry'] = {};
|
||||
|
||||
if (user_id) {
|
||||
params_json['and_qry']['user_id_random'] = user_id;
|
||||
}
|
||||
|
||||
// WARNING: This function returns a list. We only want the first one. There should be no more than 1 record returned.
|
||||
ae_promises['person'] = core_func.handle_load_ae_obj_li__person({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: 1,
|
||||
}).then((person_response) => {
|
||||
if (person_response[0].person_id_random) {
|
||||
console.log(`Successfully loaded person for user_id_random (${user_id}):`, person_response[0]);
|
||||
person_obj = person_response[0];
|
||||
person_id = person_obj.person_id_random;
|
||||
|
||||
trigger = true; // Set trigger to true to indicate we can now sign in
|
||||
} else {
|
||||
alert('Failed to load person information: ' + person_response.error);
|
||||
}
|
||||
}).then(() => {
|
||||
// Once all promises are resolved, we can check if we have both user_id and person_id
|
||||
if (user_id && person_id) {
|
||||
// Set the session information
|
||||
// $ae_loc.person_id = person_id; // Set the person_id in the ae_loc store
|
||||
// $ae_loc.person = person_obj; // Store the full person object for reference
|
||||
// $ae_loc.user_id = user_id; // Set the user_id in the ae_loc store
|
||||
// $ae_loc.user = user_obj; // Store the full user object for reference
|
||||
|
||||
console.log(`Successfully authenticated and loaded user and person records:
|
||||
user_id: ${user_id},
|
||||
person_id: ${person_id}
|
||||
`);
|
||||
// window.location.reload(); // Reload to get the new session
|
||||
} else {
|
||||
console.error('Failed to authenticate and load data: missing user_id or person_id');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
// console.log('DONE???', ae_promises);
|
||||
|
||||
} else if ($ae_sess.auth__entered_username && $ae_sess.auth__entered_password) {
|
||||
|
||||
// Try to use the username/password for authentication
|
||||
// alert('Attempting to authenticate with Username and Password.');
|
||||
ae_promises['user'] = await core_func.auth_ae_obj__username_password({
|
||||
api_cfg: $ae_api,
|
||||
account_id: $ae_loc.account_id,
|
||||
// null_account_id: false, // Set to true to allow to authenticate as global user (Super or Manager)
|
||||
username: $ae_sess.auth__entered_username,
|
||||
password: $ae_sess.auth__entered_password,
|
||||
log_lvl: 1,
|
||||
}).then((user_response) => {
|
||||
if (user_response.user_id_random) {
|
||||
console.log(`Successfully authenticated in with Username (${user_response.username}) and Password:`, user_response);
|
||||
user_obj = user_response; // Store the user object for later use
|
||||
user_id = user_obj.user_id_random; // Use the user_id_random for further API calls
|
||||
// person_id = user_obj.person_id_random;
|
||||
} else {
|
||||
alert('Failed to authenticate: ' + user_response.error);
|
||||
}
|
||||
}).then((response) => {
|
||||
if (!user_id) {
|
||||
// If we didn't get a user_id, return early
|
||||
console.error('No user_id obtained from auth_ae_obj__username_password');
|
||||
return;
|
||||
}
|
||||
|
||||
// Next we need to get the person's information. This is odd because we need to look it up based on the account_id and user_id. There should only be one account person record per user. 99% of the time the user's account ID will be the same as the person's account ID. The exception is for AE Global users (Super or Manager) who can have multiple accounts but only one person record per account.
|
||||
|
||||
let params = {
|
||||
user_id_random: user_id, // The user_id_random from the above authentication
|
||||
}
|
||||
|
||||
let params_json: key_val = {};
|
||||
|
||||
params_json['and_qry'] = {};
|
||||
|
||||
if (user_id) {
|
||||
params_json['and_qry']['user_id_random'] = user_id;
|
||||
}
|
||||
|
||||
// WARNING: This function returns a list. We only want the first one. There should be no more than 1 record returned.
|
||||
ae_promises['person'] = core_func.handle_load_ae_obj_li__person({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_type: 'account',
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
params_json: params_json,
|
||||
params: params,
|
||||
log_lvl: 1,
|
||||
}).then((person_response) => {
|
||||
if (person_response[0].person_id_random) {
|
||||
console.log(`Successfully loaded person for user_id_random (${user_id}):`, person_response[0]);
|
||||
person_obj = person_response[0];
|
||||
person_id = person_obj.person_id_random;
|
||||
|
||||
trigger = true; // Set trigger to true to indicate we can now sign in
|
||||
} else {
|
||||
alert('Failed to load person information: ' + person_response.error);
|
||||
}
|
||||
}).then(() => {
|
||||
// Once all promises are resolved, we can check if we have both user_id and person_id
|
||||
if (user_id && person_id) {
|
||||
// Set the session information
|
||||
// $ae_loc.person_id = person_id; // Set the person_id in the ae_loc store
|
||||
// $ae_loc.person = person_obj; // Store the full person object for reference
|
||||
// $ae_loc.user_id = user_id; // Set the user_id in the ae_loc store
|
||||
// $ae_loc.user = user_obj; // Store the full user object for reference
|
||||
|
||||
console.log(`Successfully authenticated and loaded user and person records:
|
||||
user_id: ${user_id},
|
||||
person_id: ${person_id}
|
||||
`);
|
||||
// window.location.reload(); // Reload to get the new session
|
||||
} else {
|
||||
console.error('Failed to authenticate and load data: missing user_id or person_id');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// console.log('DONE???', ae_promises);
|
||||
|
||||
} else {
|
||||
alert('Please enter either a User ID and Auth Key or Username and Password.');
|
||||
return false; // Prevent form submission if no credentials are provided
|
||||
}
|
||||
|
||||
}}
|
||||
>
|
||||
{#if $ae_sess.auth__entered_user_id}
|
||||
|
||||
<input
|
||||
type="text"
|
||||
class="input max-w-36"
|
||||
placeholder="User ID"
|
||||
value={$ae_sess.auth__entered_user_id ?? ''}
|
||||
oninput={(e) => $ae_sess.auth__entered_user_id = e.target.value}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input max-w-36"
|
||||
placeholder="Auth Key"
|
||||
value={$ae_sess.auth__entered_user_key ?? ''}
|
||||
oninput={(e) => $ae_sess.auth__entered_user_key = e.target.value}
|
||||
>
|
||||
|
||||
{:else}
|
||||
|
||||
<input
|
||||
type="text"
|
||||
class="input max-w-48"
|
||||
placeholder="Username"
|
||||
value={$ae_sess.auth__entered_username ?? ''}
|
||||
oninput={(e) => $ae_sess.auth__entered_username = e.target.value}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input max-w-48"
|
||||
placeholder="Password"
|
||||
value={$ae_sess.auth__entered_password ?? ''}
|
||||
oninput={(e) => $ae_sess.auth__entered_password = e.target.value}
|
||||
>
|
||||
|
||||
{/if}
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-sm variant-filled-success"
|
||||
title="Sign In"
|
||||
>
|
||||
<LogIn class="mx-1" />
|
||||
Sign In
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{:else}
|
||||
|
||||
<div class="flex flex-col items-start gap-1">
|
||||
<span class="text-sm text-gray-500">
|
||||
{$ae_loc?.user.username ?? '-- not set --'}
|
||||
</span>
|
||||
<!-- Display sign out option if the user is signed in -->
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm variant-filled-warning"
|
||||
title="Sign Out"
|
||||
onclick={async () => {
|
||||
if (confirm('Are you sure you want to sign out?')) {
|
||||
sign_out();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LogOut class="mx-1" />
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/if}
|
||||
|
||||
</span>
|
||||
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
/* BEGIN: AE's Svelte Quick Access Type component */
|
||||
#AE-Sign-In-Out {
|
||||
/* position: absolute; */
|
||||
position: fixed;
|
||||
/* position: relative; */
|
||||
/* position: static; */
|
||||
/* position: sticky; */
|
||||
/* top: 1em; */
|
||||
bottom: 1.5rem;
|
||||
left: 0rem;
|
||||
|
||||
padding: .5rem;
|
||||
|
||||
/* lightyellow */
|
||||
/* background-color: hsla(60,100%,90%,.30); */
|
||||
/* background-color: rgba(var(--color-surface-500) / .5); */
|
||||
|
||||
border-top: solid thin hsla(0,0%,0%,.25);
|
||||
border-right: solid thin hsla(0,0%,0%,.25);
|
||||
border-bottom: solid thin hsla(0,0%,0%,.25);
|
||||
border-top-right-radius: .5em;
|
||||
border-bottom-right-radius: .5em;
|
||||
|
||||
opacity: .15;
|
||||
// opacity: .85;
|
||||
/* opacity: 1; */
|
||||
|
||||
font-size: .75rem;
|
||||
|
||||
z-index: 5;
|
||||
|
||||
/* NOTE: transition when no longer hovering */
|
||||
transition-property: opacity, background-color;
|
||||
transition-delay: 1.25s;
|
||||
transition-duration: .75s;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
#AE-Sign-In-Out:hover {
|
||||
/* lightyellow */
|
||||
/* background-color: hsla(60,100%,90%,.95); */
|
||||
/* background-color: rgba(var(--color-surface-500) / 1); */
|
||||
|
||||
// Doing this to give it more space. Especially for password managers
|
||||
// top: 65%;
|
||||
|
||||
border-top: solid thin hsla(0,0%,0%,.95);
|
||||
border-right: solid thin hsla(0,0%,0%,.95);
|
||||
border-bottom: solid thin hsla(0,0%,0%,.95);
|
||||
|
||||
opacity: 1;
|
||||
|
||||
/* NOTE: transition when hover starts */
|
||||
transition-property: opacity, background-color;
|
||||
transition-delay: .5s;
|
||||
transition-duration: .25s;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user