feat(v3): robust search wildcards, smart status filtering, and fixed ID population

This commit is contained in:
Scott Idem
2026-01-06 15:54:31 -05:00
parent a42f32acf4
commit 45f6303219
19 changed files with 452 additions and 279 deletions

View File

@@ -2034,6 +2034,7 @@ def sql_and_in_dict_li_part(
# ### BEGIN ### API DB SQL Methods ### sql_enable_part() ###
# Updated 2022-01-17
# Updated 2026-01-06 to handle missing enable column gracefully.
@logger_reset
def sql_enable_part(table_name: str, enabled: str) -> bool|dict:
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
@@ -2043,19 +2044,25 @@ def sql_enable_part(table_name: str, enabled: str) -> bool|dict:
if enabled in ['enabled', 'disabled', 'all']:
log.info(f'Creating partial SQL string for "enabled" check. Enabled: {enabled}')
if enabled == 'all':
return '', None
# Check if column exists
try:
db.execute(text(f"SELECT enable FROM `{table_name}` LIMIT 0"))
except:
log.warning(f"Table/View '{table_name}' does not have an 'enable' column. Skipping filter.")
return '', None
if enabled == 'enabled':
# sql = f'AND `person`.enable = :enable'
sql = f'AND `{table_name}`.enable = true'
enable = True
elif enabled == 'disabled':
# sql = f'AND `person`.enable = :enable'
sql = f'AND `{table_name}`.enable = false'
enable = False
elif enabled == 'all':
sql = ''
enable = None
log.debug(sql)
return sql, enable
else:
return False
@@ -2064,6 +2071,7 @@ def sql_enable_part(table_name: str, enabled: str) -> bool|dict:
# ### BEGIN ### API DB SQL Methods ### sql_hidden_part() ###
# Updated 2022-01-17
# Updated 2026-01-06 to handle missing hide column gracefully.
@logger_reset
def sql_hidden_part(table_name: str, hidden: str) -> bool|dict:
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
@@ -2073,17 +2081,25 @@ def sql_hidden_part(table_name: str, hidden: str) -> bool|dict:
if hidden in ['hidden', 'not_hidden', 'all']:
log.info(f'Creating partial SQL string for "hidden" check. Hide: {hidden}')
if hidden == 'all':
return '', None
# Check if column exists
try:
db.execute(text(f"SELECT hide FROM `{table_name}` LIMIT 0"))
except:
log.warning(f"Table/View '{table_name}' does not have a 'hide' column. Skipping filter.")
return '', None
if hidden == 'hidden':
sql = f'AND `{table_name}`.hide = true'
hide = True
elif hidden == 'not_hidden':
sql = f'AND (`{table_name}`.hide = false OR `{table_name}`.hide IS NULL)'
hide = False
elif hidden == 'all':
sql = ''
hide = None
log.debug(sql)
return sql, hide
else:
return False
@@ -2258,4 +2274,4 @@ def sql_search_qry_part(
if sql_where:
return f"AND ({sql_where})", data
return "", {}
# ### END ### API DB SQL Methods ### sql_search_qry_part() ###
# ### END ### API DB SQL Methods ### sql_search_qry_part() ###

View File

@@ -38,6 +38,11 @@ class Account_Base(BaseModel):
short_name: Optional[str]
description: Optional[str]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
enable: Optional[bool]
enable_from: Optional[datetime.datetime] = None
enable_to: Optional[datetime.datetime] = None

View File

@@ -60,10 +60,13 @@ class Address_Base(BaseModel):
congressional_district: Optional[str]
#priority: Optional[int]
#sort: Optional[int]
#group: Optional[str]
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
@@ -98,6 +101,13 @@ class Address_Base(BaseModel):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('contact_id', always=True)
def contact_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
@@ -121,4 +131,4 @@ class Address_Base(BaseModel):
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
# ### END ### API Address Models ### Address_Base() ###
# ### END ### API Address Models ### Address_Base() ###

View File

@@ -72,10 +72,13 @@ class Contact_Base(BaseModel):
other_text: Optional[str]
other_json: Optional[Json]
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
@@ -114,6 +117,13 @@ class Contact_Base(BaseModel):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('address_id', always=True)
def address_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)

View File

@@ -220,6 +220,9 @@ class Event_Badge_Basic_Base(BaseModel):
**base_fields['event_badge_id_random'],
alias = 'event_badge_id_random',
)
id: Optional[int] = Field(
alias = 'event_badge_id'
)
event_badge_template_id_random: Optional[str]
# event_badge_template_id: Optional[int]
@@ -298,15 +301,15 @@ class Event_Badge_Basic_Base(BaseModel):
print_last_datetime: Optional[datetime.datetime] = None
print_count: Optional[int]
# hide: Optional[bool]
# priority: Optional[bool]
# sort: Optional[int]
# group: Optional[str]
# enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
enable: Optional[bool]
# notes: Optional[str]
# created_on: Optional[datetime.datetime] = None
# updated_on: Optional[datetime.datetime] = None
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
# Including other related objects
# order: Optional[Union[Order_Base, None]]
@@ -315,6 +318,13 @@ class Event_Badge_Basic_Base(BaseModel):
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True)
def event_badge_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='event_badge')
return None
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True

View File

@@ -42,6 +42,15 @@ class Membership_Group_Base(BaseModel):
expire_in_days: Optional[int]
enable: Optional[bool]
enable_from: Optional[datetime.datetime] = None
enable_to: Optional[datetime.datetime] = None
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
@@ -104,5 +113,6 @@ class Membership_Group_Base(BaseModel):
class Config:
underscore_attrs_are_private = True
fields = base_fields
allow_population_by_field_name = True
# Membership_Group_Base.update_forward_refs()

View File

@@ -55,6 +55,12 @@ class Membership_Person_Group_Base(BaseModel):
flag: Optional[bool]
flag_message: Optional[str]
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
@@ -117,5 +123,6 @@ class Membership_Person_Group_Base(BaseModel):
class Config:
underscore_attrs_are_private = True
fields = base_fields
allow_population_by_field_name = True
# Membership_Base.update_forward_refs()

View File

@@ -58,6 +58,7 @@ class Membership_Type_Base(BaseModel):
enable_from: Optional[datetime.datetime] = None
enable_to: Optional[datetime.datetime] = None
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int] = Field(0, ge=0, lt=100) # Essentially the membership level. Should there be a range limit?
group: Optional[str]
@@ -106,4 +107,9 @@ class Membership_Type_Base(BaseModel):
# return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
# return None
class Config:
underscore_attrs_are_private = True
fields = base_fields
allow_population_by_field_name = True
# Membership_Type_Base.update_forward_refs()

View File

@@ -34,6 +34,16 @@ class Order_Cfg_Base(BaseModel):
stripe_publishable_key: Optional[str] # Publish/Sharable
stripe_account_id: Optional[str] # Connected Stripe Account ID
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('account_id', always=True)
@@ -44,3 +54,8 @@ class Order_Cfg_Base(BaseModel):
if values['account_id_random']:
return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
return None
class Config:
underscore_attrs_are_private = True
fields = base_fields
allow_population_by_field_name = True

View File

@@ -49,6 +49,8 @@ class Organization_Base(BaseModel):
thumbnail_path: Optional[str]
thumbnail_bg_color: Optional[str]
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[int]
sort: Optional[int]
group: Optional[str]
@@ -89,8 +91,16 @@ class Organization_Base(BaseModel):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['account_id_random']:
return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('contact_id', always=True)

View File

@@ -138,4 +138,5 @@ class Post_Base(BaseModel):
class Config:
underscore_attrs_are_private = True
fields = base_fields
allow_population_by_field_name = True
# ### END ### API Post Models ### Post_Base() ###

View File

@@ -3,7 +3,7 @@ import datetime, pytz
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random
from app.db_sql import get_id_random, redis_lookup_id_random
from app.lib_general import log, logging
from app.models.common_field_schema import base_fields, default_num_bytes
@@ -38,6 +38,12 @@ class Site_Domain_Base(BaseModel):
cfg_json: Optional[Union[Json, None]] # In use 2024-03-04
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
@@ -53,9 +59,23 @@ class Site_Domain_Base(BaseModel):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
log.debug(values['id_random'])
return redis_lookup_id_random(record_id_random=values['id_random'], table_name='site_domain')
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='site_domain')
return None
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('site_id', always=True)
@@ -104,12 +124,18 @@ class Site_Domain_FQDN_ID_Base(BaseModel):
valid_for: Optional[int] # number of hours
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
# Including convenience data
# This is only for convenience. Probably going to keep unless it causes a problem.
# account_id: Optional[int]
account_id: Optional[int]
account_id_random: Optional[str]
account_code: Optional[str] # Useful for export file naming
account_name: Optional[str] # Generally useful for display
@@ -131,24 +157,19 @@ class Site_Domain_FQDN_ID_Base(BaseModel):
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
# @validator('id', always=True)
# def site_domain_id_lookup(cls, v, values, **kwargs):
# log.setLevel(logging.WARNING)
# log.debug(locals())
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
# if values['id_random']:
# log.debug(values['id_random'])
# return redis_lookup_id_random(record_id_random=values['id_random'], table_name='site_domain')
# return None
# @validator('account_id', always=True)
# def account_id_lookup(cls, v, values, **kwargs):
# log.setLevel(logging.WARNING)
# log.debug(locals())
# if values['account_id_random']:
# return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
# return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('site_id', always=True)
def site_id_lookup(cls, v, values, **kwargs):

View File

@@ -87,6 +87,11 @@ class Site_Base(BaseModel):
cfg_json: Optional[Union[Json, None]] # In use 2024-03-04
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
@@ -111,8 +116,16 @@ class Site_Base(BaseModel):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['account_id_random']:
return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
class Config:

View File

@@ -1,10 +1,9 @@
import datetime, pytz, secrets
# import datetime, hashlib, logging, os, pytz, redis, secrets
import datetime, hashlib, logging, os, pytz, redis, secrets
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random
from app.db_sql import get_id_random, redis_lookup_id_random
from app.lib_general import log, logging, secure_hash_string
from app.models.common_field_schema import base_fields, default_num_bytes
@@ -14,212 +13,6 @@ from app.models.organization_models import Organization_Base
# from app.models.user_role_models import User_Role_Base
# ### BEGIN ### API User Models ### User_New_Base() ###
class User_New_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
**base_fields['user_id_random'],
alias = 'user_id_random',
# default_factory = lambda:secrets.token_urlsafe(default_num_bytes),
)
id: Optional[int] = Field(
alias = 'user_id'
)
account_id_random: Optional[str]
account_id: Optional[int]
account_name: Optional[str]
contact_id_random: Optional[str]
contact_id: Optional[int]
organization_id_random: Optional[str]
organization_id: Optional[int]
person_id_random: Optional[str]
person_id: Optional[int]
username: str
name: str
email: str
email_verified: bool = False
new_password: str = Field(default_factory = lambda:secrets.token_urlsafe(default_num_bytes))
password: Optional[str] # If new_password is found then the validator below will create secure_hash_string() from the new password string.
allow_auth_key: bool = False
enable: bool = False
enable_from: Optional[datetime.datetime] = datetime.datetime.now(datetime.timezone.utc)
#enable_from: Optional[datetime.datetime] = datetime.datetime.now()
enable_to: Optional[datetime.datetime] = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365)
#enable_to: Optional[datetime.datetime] = datetime.datetime.now() + datetime.timedelta(days=365)
#super: Optional[bool] = False
#manager: Optional[bool] = False
administrator: bool = False
public: bool = False
verified: bool = False
group: Optional[str]
notes: Optional[str]
# Including JSON data
other_json: Optional[Json]
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
#@validator('user_id_random', always=True)
def user_id_random_copy(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
return values['id_random']
return None
@validator('id', always=True)
def user_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
log.debug(values['id_random'])
return redis_lookup_id_random(record_id_random=values['id_random'], table_name='user')
return None
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('contact_id', always=True)
def contact_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('contact_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='contact')
return None
@validator('organization_id', always=True)
def organization_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('organization_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='organization')
return None
@validator('person_id', always=True)
def person_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('person_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='person')
return None
@validator('password', always=True)
def hash_new_password(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values.get('new_password'):
return secure_hash_string(string=values['new_password'])
return None
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
# ### END ### API User Models ### User_New_Base() ###
# ### BEGIN ### API User Models ### User_Out_Base() ###
class User_Out_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
**base_fields['user_id_random'],
alias = 'user_id_random',
)
id: Optional[int] = Field(
alias = 'user_id'
)
account_id_random: Optional[str]
#account_id: Optional[int]
account_name: Optional[str]
contact_id_random: Optional[str]
#contact_id: Optional[int]
organization_id_random: Optional[str]
#organization_id: Optional[int]
person_id_random: Optional[str]
#person_id: Optional[int]
username: Optional[str]
name: Optional[str]
email: Optional[str]
email_verified: Optional[bool]
password: Optional[str]
allow_auth_key: Optional[int]
auth_key: Optional[str]
enable: Optional[bool]
enable_from: Optional[datetime.datetime]
enable_to: Optional[datetime.datetime]
super: Optional[bool]
manager: Optional[bool]
administrator: Optional[bool]
public: Optional[bool]
verified: Optional[bool]
status_id: Optional[int]
status_name: Optional[str]
password_set_on: Optional[datetime.datetime]
password_reset_token: Optional[str]
password_reset_expire_on: Optional[datetime.datetime]
logged_in_on: Optional[datetime.datetime]
last_activity_on: Optional[datetime.datetime]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime]
updated_on: Optional[datetime.datetime]
# Including other related objects
# from app.models.person_models import Person_Base # Causes circular import
# archive_list: Optional[list] # Archive_Base()
# contact: Optional[Contact_Base]
event_list: Optional[list] # Event_Base() # Priority complete
hosted_file_list: Optional[list] # Hosted_File_Base() # Priority l3
journal_list: Optional[list] # Journal_Base() # Priority l3
# membership_person: Optional[Membership_Person_Base] # Priority l2
# membership_person_list: Optional[list] # Membership_Base() ???
order_list: Optional[list] # Order_Base() # Priority l2
order_cart_list: Optional[list] # Order_Base() # Priority l2
organization: Optional[Union[Organization_Base, None]] # Organization_Base() # Priority l3
person: Optional[dict] # Person_Base() # Priority l2
# person: Optional[Union[Person_Base, None]]
post_list: Optional[list] # Post_Base() # Priority l1
user_role_list: Optional[list] = Field(
alias = 'role_list'
) # User_Role_Base()
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
# ### END ### API User Models ### User_Out_Base() ###
# ### BEGIN ### API User Models ### User_Base() ###
class User_Base(BaseModel):
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
@@ -271,12 +64,9 @@ class User_Base(BaseModel):
status_id: Optional[int]
status_name: Optional[str]
password_set_on: Optional[datetime.datetime] = None
password_reset_token: Optional[str] = None
password_reset_expire_on: Optional[datetime.datetime] = None
logged_in_on: Optional[datetime.datetime] = None
last_activity_on: Optional[datetime.datetime] = None
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
@@ -317,18 +107,23 @@ class User_Base(BaseModel):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
log.debug(values['id_random'])
return redis_lookup_id_random(record_id_random=values['id_random'], table_name='user')
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='user')
return None
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
if values['account_id_random']:
return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
# @validator('contact_id', always=True)
@@ -368,3 +163,243 @@ class User_Base(BaseModel):
allow_population_by_field_name = True
fields = base_fields
# ### END ### API User Models ### User_Base() ###
# ### BEGIN ### API User Models ### User_New_Base() ###
class User_New_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
**base_fields['user_id_random'],
alias = 'user_id_random',
# default_factory = lambda:secrets.token_urlsafe(default_num_bytes),
)
id: Optional[int] = Field(
alias = 'user_id'
)
account_id_random: Optional[str]
account_id: Optional[int]
account_name: Optional[str]
contact_id_random: Optional[str]
contact_id: Optional[int]
organization_id_random: Optional[str]
organization_id: Optional[int]
person_id_random: Optional[str]
person_id: Optional[int]
username: str
name: str
email: str
email_verified: bool = False
new_password: str = Field(default_factory = lambda:secrets.token_urlsafe(default_num_bytes))
password: Optional[str] # If new_password is found then the validator below will create secure_hash_string() from the new password string.
allow_auth_key: bool = False
enable: bool = False
enable_from: Optional[datetime.datetime] = datetime.datetime.now(datetime.timezone.utc)
#enable_from: Optional[datetime.datetime] = datetime.datetime.now()
enable_to: Optional[datetime.datetime] = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365)
#enable_to: Optional[datetime.datetime] = datetime.datetime.now() + datetime.timedelta(days=365)
#super: Optional[bool] = False
#manager: Optional[bool] = False
administrator: bool = False
public: bool = False
verified: bool = False
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
# Including JSON data
other_json: Optional[Json]
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
#@validator('user_id_random', always=True)
def user_id_random_copy(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
return values['id_random']
return None
@validator('id', always=True)
def user_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='user')
return None
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('contact_id', always=True)
def contact_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('contact_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='contact')
return None
@validator('organization_id', always=True)
def organization_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('organization_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='organization')
return None
@validator('person_id', always=True)
def person_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('person_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='person')
return None
@validator('password', always=True)
def hash_new_password(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values.get('new_password'):
return secure_hash_string(string=values['new_password'])
return None
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
# ### END ### API User Models ### User_New_Base() ###
# ### BEGIN ### API User Models ### User_Out_Base() ###
class User_Out_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
**base_fields['user_id_random'],
alias = 'user_id_random',
)
id: Optional[int] = Field(
alias = 'user_id'
)
account_id_random: Optional[str]
account_id: Optional[int]
account_name: Optional[str]
contact_id_random: Optional[str]
contact_id: Optional[int]
organization_id_random: Optional[str]
organization_id: Optional[int]
person_id_random: Optional[str]
person_id: Optional[int]
username: Optional[str]
name: Optional[str]
email: Optional[str]
email_verified: Optional[bool]
password: Optional[str]
allow_auth_key: Optional[int]
auth_key: Optional[str]
enable: Optional[bool]
enable_from: Optional[datetime.datetime]
enable_to: Optional[datetime.datetime]
super: Optional[bool]
manager: Optional[bool]
administrator: Optional[bool]
public: Optional[bool]
verified: Optional[bool]
status_id: Optional[int]
status_name: Optional[str]
password_set_on: Optional[datetime.datetime]
password_reset_token: Optional[str]
password_reset_expire_on: Optional[datetime.datetime]
logged_in_on: Optional[datetime.datetime]
last_activity_on: Optional[datetime.datetime]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str]
notes: Optional[str]
created_on: Optional[datetime.datetime]
updated_on: Optional[datetime.datetime]
# Including other related objects
# from app.models.person_models import Person_Base # Causes circular import
# archive_list: Optional[list] # Archive_Base()
# contact: Optional[Contact_Base]
event_list: Optional[list] # Event_Base() # Priority l1
hosted_file_list: Optional[list] # Hosted_File_Base() # Priority l2
journal_list: Optional[list] # Journal_Base() # Priority l3
# membership_person: Optional[Membership_Person_Base] # Priority l2
# membership_person_list: Optional[list] # Membership_Base() ???
order_list: Optional[list] # Order_Base() # Priority l2
order_cart_list: Optional[list] # Order_Base() # Priority l2
organization: Optional[Union[Organization_Base, None]] # Organization_Base() # Priority l3
person: Optional[dict] # Person_Base() # Priority l2
# person: Optional[Union[Person_Base, None]]
post_list: Optional[list] # Post_Base() # Priority l1
user_role_list: Optional[list] = Field(
alias = 'role_list'
) # User_Role_Base()
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
@validator('account_id_random', always=True)
def account_id_random_lookup(cls, v, values, **kwargs):
if isinstance(v, str) and len(v) >= 11: return v
elif account_id := values.get('account_id'):
return get_id_random(record_id=account_id, table_name='account')
return None
@validator('person_id', always=True)
def person_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('person_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='person')
return None
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
# ### END ### API User Models ### User_Out_Base() ###

View File

@@ -48,7 +48,7 @@ core_obj_li = {
# V3 Search Security:
'searchable_fields': [
'account_id_random', 'code', 'name', 'short_name', 'description',
'enable', 'created_on', 'updated_on'
'enable', 'hide', 'priority', 'sort', 'group', 'created_on', 'updated_on'
],
},
'account_cfg': {

View File

@@ -107,7 +107,8 @@ events_general_obj_li = {
# V3 Search Security:
'searchable_fields': [
'event_cfg_id_random', 'event_id_random', 'enable', 'conference',
'status', 'hide', 'priority', 'group', 'notes'
'status', 'hide', 'priority', 'sort', 'group', 'notes', 'created_on',
'updated_on'
],
},
}

View File

@@ -25,7 +25,8 @@ events_registration_obj_li = {
'title_names', 'given_name', 'middle_name', 'family_name', 'designations',
'professional_title', 'full_name', 'affiliations', 'email', 'phone',
'location', 'allow_tracking', 'print_count', 'print_first_datetime',
'print_last_datetime'
'print_last_datetime', 'enable', 'hide', 'priority', 'sort', 'group',
'notes', 'created_on', 'updated_on'
],
},
'event_badge_template': {
@@ -43,7 +44,8 @@ events_registration_obj_li = {
# V3 Search Security:
'searchable_fields': [
'event_badge_template_id_random', 'event_id_random', 'name',
'description', 'layout', 'notes'
'description', 'layout', 'notes', 'enable', 'hide', 'priority',
'sort', 'group', 'created_on', 'updated_on'
],
},
'event_person': {

View File

@@ -22,7 +22,7 @@ journal_obj_li = {
'searchable_fields': [
'journal_id_random', 'name', 'short_name', 'summary', 'outline',
'description', 'type_code', 'tags', 'billable', 'enable', 'hide',
'priority', 'group', 'created_on', 'updated_on'
'priority', 'sort', 'group', 'notes', 'created_on', 'updated_on'
],
},
'journal_entry': {
@@ -44,8 +44,8 @@ journal_obj_li = {
'searchable_fields': [
'journal_entry_id_random', 'journal_id_random', 'name', 'short_name',
'summary', 'content', 'type_code', 'topic_code', 'category_code',
'tags', 'location', 'billable', 'enable', 'hide', 'priority', 'group',
'created_on', 'updated_on'
'tags', 'location', 'billable', 'enable', 'hide', 'priority', 'sort',
'group', 'notes', 'created_on', 'updated_on'
],
},
}

View File

@@ -110,7 +110,8 @@ order_obj_li = {
# V3 Search Security:
'searchable_fields': [
'account_id_random', 'account_name', 'default_no_reply_email',
'confirm_email'
'confirm_email', 'enable', 'hide', 'priority', 'sort', 'group',
'notes', 'created_on', 'updated_on'
],
},
}