docs+site_domain: Add guidance for restoring access_key validation in site_domain lookup; stage recent user/auth changes and frontend guide updates

This commit is contained in:
Scott Idem
2026-03-25 19:33:53 -04:00
parent 6bde236633
commit 91434968f7
6 changed files with 529 additions and 6 deletions

View File

@@ -147,6 +147,8 @@ def get_site_domain_rec_list(
# ### BEGIN ### API Site Domain Methods ### lookup_site_domain_fqdn() ###
def lookup_site_domain_fqdn(
fqdn: str,
# TODO: Accept access_key as an argument for validation (str|None)
# access_key: Optional[str] = None,
enabled: str = 'enabled', # enabled, disabled, all
limit: int = 100,
offset: int = 0,
@@ -156,15 +158,22 @@ def lookup_site_domain_fqdn(
data = {}
data['fqdn'] = fqdn
# TODO: If access_key is provided, add it to the data dict for SQL parameterization
# if access_key is not None:
# data['access_key'] = access_key
sql_enabled, data['enable'] = sql_enable_part(table_name='site_domain', enabled=enabled) # Reasonably safe return str and bool
sql_limit = sql_limit_offset_part(limit=limit, offset=offset) # Reasonably safe return str
# TODO: Add access_key to WHERE clause if provided, e.g.:
# WHERE site_domain.fqdn = :fqdn AND (:access_key IS NULL OR site_domain.access_key = :access_key)
sql = f"""
SELECT `site_domain`.id AS 'site_domain_id', `site_domain`.id_random AS 'site_domain_id_random'
FROM `v_site_domain` AS site_domain
WHERE
site_domain.fqdn = :fqdn
-- TODO: Add access_key check here for stricter validation
-- AND (:access_key IS NULL OR site_domain.access_key = :access_key)
{sql_enabled}
ORDER BY `site_domain`.fqdn ASC, `site_domain`.access_key ASC, `site_domain`.required_referrer ASC, `site_domain`.created_on DESC, `site_domain`.updated_on DESC
{sql_limit};
@@ -176,4 +185,11 @@ def lookup_site_domain_fqdn(
site_domain_rec_li = []
return site_domain_rec_li
# ---
# To restore access_key validation:
# 1. Accept access_key as a parameter to this function (and any API endpoint calling it).
# 2. Add access_key to the SQL WHERE clause (see above) so only matching records are returned.
# 3. If access_key is required, return empty or error if not matched.
# 4. Update API docs and tests to reflect the new/required parameter.
# ### END ### API Site Domain Methods ### get_site_domain_rec_list() ###

View File

@@ -654,7 +654,7 @@ def email_user_auth_key_url(
else: return False
log.debug(account_cfg)
user_id_random = user_obj.id_random # NOTE: Not user_id_random because of alias
user_id_random = user_obj.id or user_obj.user_id # Vision ID: User_Out_Base uses 'id'/'user_id', not 'id_random'
from_email = account_cfg.default_no_reply_email
from_name = account_cfg.default_no_reply_name

View File

@@ -1,6 +1,6 @@
import datetime, hashlib, logging, os, pytz, redis, secrets
from typing import Dict, List, Optional, Set, Union
from typing import ClassVar, Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator
from app.db_sql import get_id_random, redis_lookup_id_random
@@ -169,6 +169,14 @@ class User_New_Base(BaseModel):
# Including JSON data
other_json: Optional[Json]
# Fields that are part of the model (for input) but must not be written to the DB table
fields_to_exclude_from_db: ClassVar[list] = [
'new_password', # Virtual input field — the validator hashes it into 'password'; DB has no new_password column
'id', 'user_id', # Vision ID strings — DB uses int 'id' (auto) and string 'id_random'
'account_id_random', 'contact_id_random', 'organization_id_random', 'person_id_random',
'account_name',
]
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@root_validator(pre=True)

View File

@@ -223,7 +223,8 @@ async def user_new_auth_key(
# NOTE: Should this be divided into username/password and user ID/auth key endpoints? Probably vote 2x
# Updated 2021-10-06
# NOTE: This is actively in use 2026-03-24 -Scott
# This is marked for deprecation and must be migrated to Aether API v3 standards!@router.get('/user/authenticate', response_model=Resp_Body_Base)
# This is marked for deprecation and must be migrated to Aether API v3 standards!
@router.get('/user/authenticate', response_model=Resp_Body_Base)
async def user_authenticate(
null_account_id: bool = False,
user_id: Optional[str] = Query(None, min_length=11, max_length=22),
@@ -417,14 +418,14 @@ async def user_verify_password(
account_id = commons.x_account_id
log.debug(user_obj)
log.debug(user_obj.id_random)
log.debug(user_obj.id)
log.debug(user_obj.current_password)
log.debug(user_obj.username)
if current_password := user_obj.current_password: pass
else: return mk_resp(data=False, status_code=400, status_message='The current password to verify is required.', response=commons.response) # Bad Request
if user_id_random := user_obj.id_random: # Use id_random instead of user_id_random when getting from User model.
if user_id_random := user_obj.id: # Vision ID: User_Base uses 'id' (not 'id_random') for the random string.
log.info(f'Using the user ID to look up the user. User ID: {user_id_random}')
# NOTE: Not doing a redis lookup since we have to look up the record again. Redis lookup may save or add an insignificant amount of time.
user_data = {}