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:
@@ -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() ###
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
Reference in New Issue
Block a user