U
    ;hDi                     @   s  d Z ddlZddlZddlmZmZ ddlmZmZmZm	Z	m
Z
 ddlmZmZmZ ddlmZmZ ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z"m#Z#m$Z$ ddl%m&Z&m'Z'm(Z( e Z)e*e+Z,e Z-e Z.e Z/eedd Z0eedd Z1eedd Z2eedd Z3eedd Z4eedd Z5ee-dd Z6ee.dd  Z7d!d" Z8d#d$ Z9d%d& Z:d'd( Z;ee/d)d* Z<d+d, Z=d-d. Z>dS )/a  
Adtlas Activities Signals

This module contains Django signal handlers for the activities app,
providing automatic activity logging, model change tracking, and
event-driven functionality.

Features:
    - Automatic activity logging for model changes
    - User authentication activity tracking
    - System event monitoring
    - Custom signal handlers
    - Activity cleanup and maintenance
    - Real-time notifications

Author: Adtlas Development Team
Version: 1.0.0
Last Updated: 2025-01-27
    N)datetime	timedelta)	post_savepost_deletepre_save
pre_deletem2m_changed)user_logged_inuser_logged_outuser_login_failed)request_startedrequest_finished)receiverSignal)get_user_model)ContentType)timezone)settings)cache)transaction   )ActivityActivityCategoryActivitySummary)get_client_ipget_user_agentshould_log_activityc                 K   s   zt jjddddddd\}}tj|dd	|j d
||dt|ddt|ddt 	 dd t
d|j t d td|j  W n> tk
r } z td|j dt|  W 5 d}~X Y nX dS )aU  
    Log user login activity.
    
    This signal handler automatically creates an activity record
    when a user successfully logs in to the system.
    
    Args:
        sender: The sender of the signal
        request: Django request object
        user: User instance that logged in
        **kwargs: Additional keyword arguments
    authAuthenticationUser authentication activities#007bfffas fa-sign-in-altnamedescriptioncoloriconcodedefaultsloginUser z logged in successfullyTlogin_methodstandardremember_meF)r,   r.   login_timestamp)useractionr$   categoryrequestis_successfulmetadatauser_last_login_  zLogin activity logged for user z&Failed to log login activity for user : N)r   objectsget_or_creater   log_activityemailgetattrr   now	isoformatr   setidloggerinfo	Exceptionerrorstr)senderr3   r0   kwargsauth_category_e rL   2/var/www/html/Focus/src/apps/activities/signals.pylog_user_login9   s2    



rN   c                 K   s   z|sW dS t jjdd }|s(W dS td|j }d}|rVt | 	 d }t
j|dd|j d||d	|t|d
d|t  dd td|j  td|j  W n6 tk
r } ztdt|  W 5 d}~X Y nX dS )aY  
    Log user logout activity.
    
    This signal handler automatically creates an activity record
    when a user logs out of the system.
    
    Args:
        sender: The sender of the signal
        request: Django request object
        user: User instance that logged out (may be None)
        **kwargs: Additional keyword arguments
    Nr   )r(   r6   i  logoutr+   z logged outTlogout_methodr-   )rP   Zsession_duration_msZlogout_timestamp)r0   r1   r$   r2   r3   r4   duration_msr5   z Logout activity logged for user zFailed to log logout activity: )r   r9   filterfirstr   getrA   r   r>   total_secondsr   r;   r<   r=   r?   deleterB   rC   rD   rE   rF   )rG   r3   r0   rH   rI   
last_loginZsession_durationrK   rL   rL   rM   log_user_logoutk   s:    


rX   c                 K   s   zt jjddddddd\}}|dd	}tjd
dd| ||dd|dt  dd t	|}d| }t
|dd }	t
||	d td| d|  W n6 tk
r }
 ztdt|
  W 5 d
}
~
X Y nX d
S )aD  
    Log failed login attempts.
    
    This signal handler automatically creates an activity record
    when a login attempt fails.
    
    Args:
        sender: The sender of the signal
        credentials: Login credentials used
        request: Django request object
        **kwargs: Additional keyword arguments
    r   r   r   r    r!   r"   r'   usernameUnknownNlogin_failedz#Failed login attempt for username: FzInvalid credentials providedZinvalid_credentials)Zattempted_usernameZfailure_reasonZattempt_timestamp)r0   r1   r$   r2   r3   r4   error_messager5   Zfailed_login_attempts_r   r   r7   z"Failed login attempt for username z	 from IP z%Failed to log failed login activity: )r   r9   r:   rT   r   r;   r   r>   r?   r   r   r@   rB   warningrD   rE   rF   )rG   credentialsr3   rH   rI   rJ   rY   
ip_address	cache_keyZattemptsrK   rL   rL   rM   log_failed_login   s<    


ra   c                 K   s   |r| t krdS t| sdS zt|dd}|s4W dS | jj}t|}t j|dd| jj dt| |t	j
| |jd| jjt|t|dd td	| jj d|j  W n@ tk
r } z"td
| jj dt|  W 5 d}~X Y nX dS )aq  
    Log model creation activities.
    
    This signal handler automatically creates activity records
    when new model instances are created.
    
    Args:
        sender: Model class that sent the signal
        instance: Model instance that was saved
        created: Boolean indicating if instance was created
        **kwargs: Additional keyword arguments
    N_current_usercreatezCreated r8   T)modelobject_reprZcreated_fieldsr0   r1   r$   r2   content_type	object_idr4   r5   zCreation activity logged for z$Failed to log creation activity for r   r   r=   _meta	app_labelget_or_create_category_for_appr;   verbose_namerF   r   r9   get_for_modelpklabelget_model_fieldsrB   debugrD   rE   )rG   instancecreatedrH   r0   rk   r2   rK   rL   rL   rM   log_model_creation   s4    
 ru   c           	      K   s  |s| t krdS t| sdS zt|dd}|s4W dS t|di }|sJW dS | jj}t|}t j|dd| jj dt| |t	j
| |jd| jjt||t|dd	 td
| jj d|j  W nB tk
r } z"td| jj dt|  W 5 d}~X Y nX dS )ak  
    Log model update activities.
    
    This signal handler automatically creates activity records
    when model instances are updated.
    
    Args:
        sender: Model class that sent the signal
        instance: Model instance that was saved
        created: Boolean indicating if instance was created
        **kwargs: Additional keyword arguments
    Nrb   Z_changed_fieldsupdatezUpdated r8   T)rd   re   changed_fieldsZfield_countrf   zUpdate activity logged for z"Failed to log update activity for )r   r   r=   rj   rk   rl   r;   rm   rF   r   r9   rn   ro   rp   lenrB   rr   rD   rE   )	rG   rs   rt   rH   r0   rw   rk   r2   rK   rL   rL   rM   log_model_update  s<    
 ry   c                 K   s   | t krdS t| sdS zt|dd}|s0W dS | jj}t|}t j|dd| jj dt| |t	j
| |jd| jjt|t|dd td	| jj d|j  W n@ tk
r } z"td
| jj dt|  W 5 d}~X Y nX dS )a3  
    Log model deletion activities.
    
    This signal handler automatically creates activity records
    when model instances are deleted.
    
    Args:
        sender: Model class that sent the signal
        instance: Model instance that was deleted
        **kwargs: Additional keyword arguments
    Nrb   rV   zDeleted r8   T)rd   re   Zdeleted_fieldsrf   zDeletion activity logged for z$Failed to log deletion activity for ri   )rG   rs   rH   r0   rk   r2   rK   rL   rL   rM   log_model_deletionX  s4    
 rz   c              
   K   s   zt tdrLtjsLddlm} ||j |jr6|j	nd|j
rD|jnd n*t|j |jrb|j	nd|j
rp|jnd ttddrt| td|j  W n6 tk
r } ztdt|  W 5 d}~X Y nX dS )	a\  
    Handle activity logged signal.
    
    This signal handler performs additional processing when
    an activity is logged, such as updating summaries and
    triggering notifications.
    
    Args:
        sender: The sender of the signal
        activity: Activity instance that was logged
        **kwargs: Additional keyword arguments
    CELERY_TASK_ALWAYS_EAGERr   )update_activity_summaryNZACTIVITIES_REALTIME_ENABLEDFz,Activity logged signal handled for activity z)Failed to handle activity logged signal: )hasattrr   r{   tasksr|   delay
created_atdater0   user_idr2   category_idupdate_activity_summary_syncr=   send_realtime_notificationrB   rr   rA   rD   rE   rF   )rG   activityrH   r|   rK   rL   rL   rM   handle_activity_logged  s$    r   c              
   K   s   zt  }|D ]6}|j |jr$|jnd|jr2|jndf}|| qtt	drpt	j
spddlm} |t| n|D ]\}}}	t|||	 qttdt| d W n6 tk
r }
 ztdt|
  W 5 d}
~
X Y nX dS )a<  
    Handle bulk activity logged signal.
    
    This signal handler performs batch processing when
    multiple activities are logged at once.
    
    Args:
        sender: The sender of the signal
        activities: List of Activity instances that were logged
        **kwargs: Additional keyword arguments
    Nr{   r   )update_activity_summaries_bulkz(Bulk activity logged signal handled for z activitiesz.Failed to handle bulk activity logged signal: )r@   r   r   r0   r   r2   r   addr}   r   r{   r~   r   r   listr   rB   rC   rx   rD   rE   rF   )rG   
activitiesrH   Zsummary_keysr   Zsummary_keyr   r   r   r   rK   rL   rL   rM   handle_bulk_activity_logged  s     r   c              	   C   s   ddddddddd	dd
ddddddddddddddd}| | |   d|  dddd}tjj|d |d\}}|S )z
    Get or create an activity category for a Django app.
    
    Args:
        app_label: Django app label
    
    Returns:
        ActivityCategory: Category instance for the app
    zUser ManagementZuser_managementr    zfas fa-users)r#   r(   r%   r&   Campaign ManagementZcampaign_management#28a745fas fa-bullhornzChannel ManagementZchannel_management#ffc107z	fas fa-tvAnalytics & Reporting	analyticsz#17a2b8fas fa-chart-barzVAST Ad ServingZvast_serving#6f42c1zfas fa-play-circle)accounts	campaignschannelsr   vastz ManagementZ_managementz#6c757dz
fas fa-cogr(   r'   )rT   titler   r9   r:   )rk   Zcategory_mappingcategory_datar2   rt   rL   rL   rM   rl     sJ    !
rl   c              	   C   s   i }| j jD ]|}zXt| |j}t|dr2| }n*t|dr\t|ttt	t
tdfs\t|}|||j< W q tk
r   d||j< Y qX q|S )z
    Get model fields and their values for logging.
    
    Args:
        instance: Model instance
    
    Returns:
        dict: Dictionary of field names and values
    r?   __str__Nz<unable to serialize>)rj   fieldsr=   r#   r}   r?   
isinstancerF   intfloatbooltyperD   )rs   r   fieldvaluerL   rL   rM   rq     s    


"rq   c              
   C   s  zt   tjj| ||d\}}tjj| d}|r@|j|d}|rP|j|d}| |_|jdd |_	|jdd |_
|jddjd	dd
}|rt|t| |_|d  |_|  W 5 Q R X W n8 tk
r
 } ztdt|  W 5 d}~X Y nX dS )z
    Update activity summary synchronously.
    
    Args:
        date: Date for the summary
        user_id: User ID (optional)
        category_id: Category ID (optional)
    )r   r   r   )Zcreated_at__date)r   )r   T)r4   F)Zduration_ms__isnullrQ   )flatr_   z#Failed to update activity summary: N)r   atomicr   r9   r:   r   rR   counttotal_activitiessuccessful_activitiesfailed_activitiesvalues_listsumrx   avg_duration_msvaluesdistinct
unique_ipssaverD   rB   rE   rF   )r   r   r   summaryrt   r   Z	durationsrK   rL   rL   rM   r   :  s:    	


 r   c              
   C   s   zjd}t |g }|dt| j| jr.| jjnd|  | j| j	
 | jd |dd }t ||d W n6 tk
r } ztdt|  W 5 d}~X Y nX dS )	zf
    Send real-time notification for activity.
    
    Args:
        activity: Activity instance
    Zlatest_activitiesr   System)rA   r0   r1   r$   	timestampr4   N2   r7   z'Failed to send real-time notification: )r   rT   insertrF   rA   r0   r<   get_action_displayr$   r   r?   r4   r@   rD   rB   rE   )r   r`   latestrK   rL   rL   rM   r   m  s    
r   c              
   K   s   t d| d z4tjddd| dtdd|t  d	d
 W n6 tk
r| } zt 	dt
|  W 5 d}~X Y nX dS )z
    Handle activity cleanup completion.
    
    Args:
        sender: The sender of the signal
        deleted_count: Number of activities deleted
        **kwargs: Additional keyword arguments
    zActivity cleanup completed: z activities deletedNZsystem_cleanupzAutomatic cleanup completed: z old activities removedr   T)deleted_countZcleanup_timestamp)r0   r1   r$   r2   r4   r5   z Failed to log cleanup activity: )rB   rC   r   r;   rl   r   r>   r?   rD   rE   rF   )rG   r   rH   rK   rL   rL   rM   handle_cleanup_completed  s    



r   c                 K   s   zddl m} ddddddd	d
dddddddd
dddddddd
dddddddd
dddd d!dd"d
d#d$d%d&d'ddd
g}|D ]0}|jj|d( |d)\}}|rtd*|j  qW n0 tk
r } ztd+|  W 5 d,}~X Y nX d,S )-a+  
    Create default activity categories if they don't exist.
    
    This method creates the basic activity categories needed for
    proper activity classification and filtering.
    
    Categories created:
        - Authentication (login, logout, password changes)
        - Content Management (create, update, delete content)
        - Campaign Management (campaign operations)
        - System Administration (user management, settings)
        - Analytics (report generation, data export)
        - Security (failed logins, permission changes)
    r   )r   r   r   z@User authentication activities (login, logout, password changes)r    r!   TZ   )r#   r(   r$   r%   r&   	is_systemretention_dayszContent Managementcontentz7Content creation, modification, and deletion activitiesr   zfas fa-file-altim  r   campaignz:Campaign creation, modification, and management activitiesr   r   i  zSystem Administrationadminz<Administrative activities (user management, system settings)z#dc3545zfas fa-cogsiG  r   r   z@Analytics viewing, report generation, and data export activitiesr   r      zSecurity Eventssecurityz;Security-related events (failed logins, permission changes)z#fd7e14zfas fa-shield-altr(   r'   z#Created default activity category: z7Warning: Could not create default activity categories: N)modelsr   r9   r:   printr#   rD   )rG   rH   r   Zdefault_categoriesr   r2   rt   rK   rL   rL   rM   "create_default_activity_categories  sx    




:
r   c              
   K   s   zfddl m}m} ddl}|jjdddddd\}}|jj|dd|g |i d	d
d td W n0 tk
r } ztd|  W 5 d}~X Y nX dS )az  
    Set up periodic cleanup tasks for old activity records.
    
    This method configures Celery periodic tasks to automatically
    clean up old activity records based on retention policies.
    
    Tasks configured:
        - Daily cleanup of expired activity records
        - Weekly aggregation of activity statistics
        - Monthly archival of old activity data
    r   )PeriodicTaskCrontabScheduleN   *)minutehourday_of_weekday_of_monthmonth_of_yearZactivities_daily_cleanupz0apps.activities.tasks.cleanup_expired_activitiesT)argsrH   enabled)crontabr#   taskr)   z,Activities periodic cleanup tasks configuredz+Warning: Could not setup periodic cleanup: )	Zdjango_celery_beat.modelsr   r   jsonr9   r:   dumpsr   rD   )rG   rH   r   r   r   schedulert   rK   rL   rL   rM   setup_periodic_cleanup  s,    
r   )?__doc__r   loggingr   r   Zdjango.db.models.signalsr   r   r   r   r   Zdjango.contrib.auth.signalsr	   r
   r   Zdjango.core.signalsr   r   django.dispatchr   r   django.contrib.authr   "django.contrib.contenttypes.modelsr   django.utilsr   django.confr   django.core.cacher   	django.dbr   r   r   r   r   utilsr   r   r   User	getLogger__name__rB   Zactivity_loggedZbulk_activity_loggedZactivity_cleanup_completedrN   rX   ra   ru   ry   rz   r   r   rl   rq   r   r   r   r   r   rL   rL   rL   rM   <module>   sX   

1
:
9
7
?
7
(
(:3"
[