File: //home/arjun/projects/buyercall_forms/buyercall/buyercall/blueprints/activity/models.py
import logging as log
from enum import Enum
import datetime
from flask_login import current_user
from sqlalchemy import DateTime
from buyercall.extensions import db
from buyercall.lib.supervisor_manager import current_supervisor_user
from buyercall.lib.util_sqlalchemy import AwareDateTime, ResourceMixin
from buyercall.lib.util_datetime import tzware_datetime, timedelta_months
from buyercall.blueprints.user.models import User
from user_agents import parse
class ActivityType(str, Enum):
AUTHORIZATION = 'authorization',
PAGE = 'page',
MODAL= 'modal',
DATA = 'data',
CREDIT = 'credit'
class ActivityName(str, Enum):
LOGOUT = 'logout.success',
LOGIN_SUCCESS = 'login.success',
LOGIN_FAILED = 'login.failed',
TWOFACTAUTH_SUCCESS = 'login.twofactauth.success',
TWOFACTAUTH_FAILED = 'login.twofactauth.failed',
LOGIN_ACCEPTTERMS = 'login.acceptterms',
LOGIN_DECLINETERMS = 'login.declineterms',
PASSWORDRESET_SUCCESS = 'login.passwordreset.success'
PASSWORDRESET_FAILED =' login.passwordreset.failed'
VIEW = 'view',
EDIT = 'edit',
PDF = 'pdf',
DOWNLOAD = 'download'
class ActivityLogs(ResourceMixin, db.Model):
__tablename__ = 'activity_logs'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id',
name='activity_logs_user_id_fkey',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=False)
type = db.Column(db.String(64), nullable=False, server_default='')
name = db.Column(db.String(64), nullable=False, server_default='')
description = db.Column(db.String(64), nullable=False, server_default='')
ip_address = db.Column(db.String(64), nullable=False, server_default='')
device_browser = db.Column(db.String(64), nullable=False, server_default='')
device_os = db.Column(db.String(64), nullable=False, server_default='')
resource_address = db.Column(db.String(64), nullable=False, server_default='')
resource_id = db.Column(db.Integer, nullable=True)
partnership_id = db.Column(db.Integer, db.ForeignKey('partnerships.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=True)
partnership_account_id = db.Column(db.Integer, db.ForeignKey('partnership_accounts.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=True)
@classmethod
def add_log(cls, user_id, type_, name, request, resource_id=None, description=''):
"""
Create new user activity log entry
"""
if hasattr(current_supervisor_user, 'id'):
user_id = current_supervisor_user.id
p_id = None
pa_id = None
user = User.query.filter(User.id == user_id).first()
if user:
p_id = user.partnership_id
pa_id = user.partnership_account_id
try:
new_activity = ActivityLogs(
user_id=user_id,
type=type_,
name=name,
description=description,
ip_address=cls.get_ip_address_from_request(request),
device_browser=cls.get_device_browser_from_request(request),
device_os=cls.get_device_os_from_request(request),
resource_address=cls.get_resource_address_from_request(request),
resource_id=resource_id,
partnership_id=p_id,
partnership_account_id=pa_id
)
db.session.add(new_activity)
db.session.commit()
except Exception as e:
log.error('Error adding to activity log. Error: ' + str(e))
@classmethod
def get_ip_address_from_request(cls, request):
"""
Retrieves the user IP address
"""
try:
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
return request.environ['REMOTE_ADDR']
else:
return request.environ['HTTP_X_FORWARDED_FOR']
except Exception as e:
log.error('Error retrieving user IP address for activity log. Error: ' + str(e))
return ''
@classmethod
def get_device_browser_from_request(cls, request):
"""
Retrieves the user device browser details
"""
try:
if request:
user_agent = parse(request.user_agent.string)
return user_agent.browser.family + '|' + user_agent.browser.version_string
else:
return ''
except Exception as e:
log.error('Error retrieving user device browser for activity log. Error: ' + str(e))
return ''
@classmethod
def get_device_os_from_request(cls, request):
"""
Retrieves the user device os details
"""
try:
if request:
user_agent = parse(request.user_agent.string)
return user_agent.os.family
else:
return ''
except Exception as e:
log.error('Error retrieving user device os for activity log. Error: ' + str(e))
return ''
@classmethod
def get_resource_address_from_request(cls, request):
"""
Retrieves the requested url path
"""
try:
if request:
return request.path
else:
return ''
except Exception as e:
log.error('Error retrieving requested url path for activity log. Error: ' + str(e))
return ''
@classmethod
def delete_old_activity_logs(cls):
"""
Delete activity logs 6 months and older.
:return: int
"""
from buyercall.app import create_app
# Create a context for the database connection.
app = create_app()
db.app = app
with app.app_context():
delete_count = 0
expiration_days = 60
limit = timedelta_months(-6)
delete_count = ActivityLogs.query.filter(ActivityLogs.created_on <= limit).count()
ActivityLogs.query.filter(ActivityLogs.created_on <= limit).delete()
db.session.commit()
return delete_count
pass