From a494a9ca6867d58e5448915b6635ac74b59f9fe2 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 2 Jul 2021 12:11:12 -0400 Subject: [PATCH] Added logging for client viewing --- app/main.py | 7 +- app/models/common_field_schema.py | 1 + app/models/log_client_viewing_models.py | 140 ++++++++++++++++++++++++ app/routers/api_crud.py | 3 +- app/routers/log_client_viewing.py | 68 ++++++++++++ 5 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 app/models/log_client_viewing_models.py create mode 100644 app/routers/log_client_viewing.py diff --git a/app/main.py b/app/main.py index a1b0c84..60c1163 100644 --- a/app/main.py +++ b/app/main.py @@ -18,7 +18,7 @@ from app.lib_general import log, logging from app.log import log # Import the routers here first: -from app.routers import api_crud, api, account, address, archive, archive_content, contact, event, event_exhibit, event_file, event_person, event_person_detail, event_presentation, event_presenter, event_registration, event_session, flask_cfg, hosted_file, journal, journal_entry, lookup, membership_group, membership_member, membership_type, order, order_cart, organization, page, person, post, post_comment, product, site, site_domain, user, user_person, websockets # , items, journals +from app.routers import api_crud, api, account, address, archive, archive_content, contact, event, event_exhibit, event_file, event_person, event_person_detail, event_presentation, event_presenter, event_registration, event_session, flask_cfg, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_group, membership_member, membership_type, order, order_cart, organization, page, person, post, post_comment, product, site, site_domain, user, user_person, websockets # , items, journals from app.db_sql import db @@ -154,6 +154,11 @@ app.include_router( prefix='/journal/entry', tags=['Journal Entry'], ) +app.include_router( + log_client_viewing.router, + prefix='/log/client_viewing', + tags=['Log Client Viewing'], +) app.include_router( lookup.router, prefix='/lu', diff --git a/app/models/common_field_schema.py b/app/models/common_field_schema.py index 43e3bae..9aa9380 100644 --- a/app/models/common_field_schema.py +++ b/app/models/common_field_schema.py @@ -48,6 +48,7 @@ base_fields['fundraising_cfg_id_random'] = xxx_id_random_field_schema base_fields['hosted_file_id_random'] = xxx_id_random_field_schema base_fields['journal_id_random'] = xxx_id_random_field_schema base_fields['journal_entry_id_random'] = xxx_id_random_field_schema +base_fields['log_client_viewing_id_random'] = xxx_id_random_field_schema # base_fields['membership_id_random'] = xxx_id_random_field_schema # renamed to membership_type base_fields['membership_cfg_id_random'] = xxx_id_random_field_schema base_fields['membership_group_id_random'] = xxx_id_random_field_schema diff --git a/app/models/log_client_viewing_models.py b/app/models/log_client_viewing_models.py new file mode 100644 index 0000000..0f49d90 --- /dev/null +++ b/app/models/log_client_viewing_models.py @@ -0,0 +1,140 @@ +from __future__ import annotations +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.lib_general import log, logging + +from app.models.common_field_schema import base_fields, default_num_bytes + + +class Log_Client_Viewing_Base(BaseModel): + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + id_random: Optional[str] = Field( + **base_fields['log_client_viewing_id_random'], + alias = 'log_client_viewing_id_random', + default_factory = lambda:secrets.token_urlsafe(default_num_bytes), + ) + id: Optional[int] = Field( + alias = 'log_client_viewing_id' + ) + account_id_random: Optional[str] + account_id: Optional[int] + + person_id_random: Optional[str] + person_id: Optional[int] + + user_id_random: Optional[str] + user_id: Optional[int] + + external_client_id: Optional[str] + + google_ga: Optional[str] + google_gid: Optional[str] + + name: Optional[str] + + given_name: Optional[str] + family_name: Optional[str] + middle_name: Optional[str] + prefix: Optional[str] + suffix: Optional[str] + full_name: Optional[str] + informal_name: Optional[str] + + source: Optional[str] + url_root: Optional[str] + url_full_path: Optional[str] + url_params: Optional[str] + + object_type: Optional[str] + object_id: Optional[str] + + # For now just using string instead of Json Pydantic data type + client_app_json: Optional[str] # When getting the dict version for SQL this should be a string. + + page_load_on: Optional[datetime.datetime] + authenticated_on: Optional[datetime.datetime] + + play_start_on: Optional[datetime.datetime] + play_start_on_first: Optional[datetime.datetime] + play_start_on_last: Optional[datetime.datetime] + play_start_count: Optional[int] + + play_pause_on: Optional[datetime.datetime] + play_pause_on_first: Optional[datetime.datetime] + play_pause_on_last: Optional[datetime.datetime] + play_pause_count: Optional[int] + + play_volume_on: Optional[datetime.datetime] + play_muted_on: Optional[datetime.datetime] + + play_seeked_on: Optional[datetime.datetime] + play_seeked_on_first: Optional[datetime.datetime] + play_seeked_on_last: Optional[datetime.datetime] + play_seeked_count: Optional[int] + + play_ended_on: Optional[datetime.datetime] + play_unload_on: Optional[datetime.datetime] + last_ping: Optional[datetime.datetime] + + # 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('log_client_viewing_id_random', always=True) + def log_client_viewing_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 log_client_viewing_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values.get('id_random', None): # 'id_random' in values and values['id_random']: + log.debug(values['id_random']) + return redis_lookup_id_random(record_id_random=values['id_random'], table_name='log_client_viewing') + 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('person_id', always=True) + def person_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values.get('person_id_random', None): + return redis_lookup_id_random(record_id_random=values['person_id_random'], table_name='person') + return None + + @validator('user_id', always=True) + def user_id_lookup(cls, v, values, **kwargs): + log.setLevel(logging.WARNING) + log.debug(locals()) + + if values['user_id_random']: + return redis_lookup_id_random(record_id_random=values['user_id_random'], table_name='user') + return None + + class Config: + underscore_attrs_are_private = True + allow_population_by_field_name = True + fields = base_fields diff --git a/app/routers/api_crud.py b/app/routers/api_crud.py index c4a9208..862a531 100644 --- a/app/routers/api_crud.py +++ b/app/routers/api_crud.py @@ -31,6 +31,7 @@ from app.models.event_track_models import * from app.models.hosted_file_models import * from app.models.journal_models import * from app.models.journal_entry_models import * +from app.models.log_client_viewing_models import Log_Client_Viewing_Base from app.models.membership_cfg_models import * from app.models.membership_group_models import * from app.models.membership_group_member_models import * @@ -85,7 +86,7 @@ obj_type_li['hosted_file'] = {'table_name': 'v_hosted_file', 'base_name': Hosted obj_type_li['journal'] = {'table_name': 'v_journal', 'base_name': Journal_Base} obj_type_li['journal_entry'] = {'table_name': 'v_journal_entry', 'base_name': Journal_Entry_Base} #obj_type_li['log'] = {'table_name': 'log', 'base_name': Log_Base} #'v_log' -#obj_type_li['log_client_viewing'] = {'table_name': 'log_client_viewing', 'base_name': Log_Client_Viewing_Base} +obj_type_li['log_client_viewing'] = {'table_name': 'log_client_viewing', 'base_name': Log_Client_Viewing_Base} obj_type_li['membership_cfg'] = {'table_name': 'v_membership_cfg', 'base_name': Membership_Cfg_Base} obj_type_li['membership_group'] = {'table_name': 'v_membership_group', 'base_name': Membership_Group_Base} obj_type_li['membership_group_member'] = {'table_name': 'v_membership_group_member', 'base_name': Membership_Group_Member_Base} diff --git a/app/routers/log_client_viewing.py b/app/routers/log_client_viewing.py new file mode 100644 index 0000000..1f82942 --- /dev/null +++ b/app/routers/log_client_viewing.py @@ -0,0 +1,68 @@ +import datetime, pytz, time +from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, status +from pydantic import BaseModel, EmailStr, Field +from typing import Dict, List, Optional, Set, Union + +from app.lib_general import log, logging +from app.config import settings +from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random + +from app.routers.api_crud import delete_obj_template, get_obj_template, get_obj_li_template, patch_obj_template, post_obj_template + +# from app.methods.log_client_viewing_methods import get_log_client_viewing_rec_list, load_log_client_viewing_obj + +from app.models.log_client_viewing_models import Log_Client_Viewing_Base +from app.models.response_models import Resp_Body_Base, mk_resp + + +router = APIRouter() + + +@router.post('', response_model=Resp_Body_Base) +async def post_log_client_viewing_obj( + obj: Log_Client_Viewing_Base, + x_account_id: str = Header(...), + return_obj: Optional[bool] = True, + by_alias: Optional[bool] = True, + exclude_unset: Optional[bool] = True, + ): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + obj_type = 'log_client_viewing' + obj_data_dict = obj.dict(by_alias=False, exclude_unset=True) + result = post_obj_template( + obj_type=obj_type, + data=obj_data_dict, + return_obj=True, + by_alias=True, + exclude_unset=True, + ) + return result + + +@router.patch('/{obj_id}', response_model=Resp_Body_Base) +async def patch_log_client_viewing_obj( + obj: Log_Client_Viewing_Base, + obj_id: str = Query(..., min_length=1, max_length=22), + x_account_id: Optional[str] = Header(..., ), + return_obj: Optional[bool] = True, + by_alias: Optional[bool] = True, + exclude_unset: Optional[bool] = True, + ): + log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(locals()) + + obj_type = 'log_client_viewing' + obj_data_dict = obj.dict(by_alias=False, exclude_unset=True) + obj_data_dict['id'] = redis_lookup_id_random(record_id_random=obj_id, table_name=obj_type) + obj_data_dict['id_random'] = obj_id + result = patch_obj_template( + obj_type=obj_type, + data=obj_data_dict, + obj_id=obj_id, + return_obj=True, + by_alias=True, + exclude_unset=True, + ) + return result