U
    hnh™N  ã                   @   s  d Z ddlZddlmZ ddlmZ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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! 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l0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z? G dd„ de/ƒZ@G dd„ de1e-ƒZAG dd„ de/ƒZBG d d!„ d!e/ƒZCG d"d#„ d#e/ƒZDG d$d%„ d%e1e-ƒZEe@ F¡ ZGeA F¡ ZHeB F¡ ZIeC F¡ ZJeD F¡ ZKeE F¡ ZLed&d'„ ƒZMed(d)„ ƒZNed*d+„ ƒZOdS ),aÏ  
Adtlas Authentication Views

Enhanced authentication views for the Adtlas DAI Management System.
Includes login, registration, password reset, and profile management.

Features:
    - Enhanced login with remember me functionality
    - User registration with email verification
    - Password reset with secure tokens
    - Profile management
    - Activity logging and session management

Author: Adtlas Development Team
Version: 2.0.0
Last Updated: 2025-07-09
é    N)Ú	timedelta)ÚrenderÚredirectÚget_object_or_404)ÚloginÚlogout)Úlogin_required)Úmessages)ÚJsonResponseÚHttpResponse)Útimezone)ÚValidationError)Útransaction)Úrequire_http_methods)Úcsrf_protect)Únever_cache)Úvalidate_password)Ú	Paginator)ÚQ)Úsettings)Úreverse)Úmethod_decorator)ÚViewÚTemplateViewÚFormView)ÚLoginRequiredMixiné   )Ú	LoginFormÚUserRegistrationFormÚPasswordResetRequestFormÚPasswordResetConfirmFormÚProfileForm)ÚUserÚProfileÚUserSessionÚUserActivityÚPasswordResetTokenÚRoleÚUserRolec                       sP   e Zd ZdZdZeZ‡ fdd„Z‡ fdd„Zdd„ Z	‡ fd	d
„Z
dd„ Z‡  ZS )Ú	LoginViewzS
    Enhanced login view with remember me functionality and security features.
    zaccounts/login.htmlc                    s$   |j jrtdƒS tƒ j|f|ž|ŽS ©z<
        Redirect authenticated users to dashboard.
        úcore:dashboard©ÚuserZis_authenticatedr   ÚsuperÚdispatch©ÚselfÚrequestÚargsÚkwargs©Ú	__class__© ú src/apps/authentication/views.pyr/   ;   s    zLoginView.dispatchc                    s   t ƒ  ¡ }| j|d< |S )z:
        Pass request to form for authentication.
        r2   )r.   Úget_form_kwargsr2   ©r1   r4   r5   r7   r8   r9   C   s    

zLoginView.get_form_kwargsc                 C   s<  |  ¡ }t| j|ƒ |j d¡r0| jj d¡ n| jj d¡ t ¡ |_	t ¡ |_
|jddgd tjj|d|  ¡ | jj dd	¡|j dd
¡ddœd tjj|| jjj|  ¡ | jj dd	¡t ¡ t ¡ t|j d¡rÚdndd ddœd t | jd| ¡ › d¡ | jj d¡p$| jj d¡}|r4t|ƒS tdƒS )z*
        Handle successful login.
        Úremember_mei ' r   Ú
last_loginÚlast_activity)Zupdate_fieldsr   ÚHTTP_USER_AGENTÚ FZemail_password)r;   Zlogin_method©r-   ÚactionÚ
ip_addressÚ
user_agentÚdetailsé   r   )ZdaysT)rB   rC   r=   Z
expires_atÚ	is_active)r-   Úsession_keyÚdefaultszWelcome back, ú!Únextr+   )Zget_userÚ
auth_loginr2   Úcleaned_dataÚgetÚsessionZ
set_expiryr   Znowr<   r=   Úsaver%   ÚobjectsÚcreateÚget_client_ipÚMETAr$   Zupdate_or_createrG   r   r	   ÚsuccessZget_short_nameÚGETÚPOSTr   )r1   Úformr-   Znext_urlr7   r7   r8   Ú
form_validK   sF    

þû ûýþzLoginView.form_validc              	      sJ   |j  d¡}|r>tjjdd|  ¡ | jj dd¡|dddœd	 tƒ  	|¡S )
z.
        Handle failed login attempt.
        ÚemailNr   r>   r?   ZfailedzInvalid credentials)rY   ÚstatusÚerrorr@   )
rL   rM   r%   rP   rQ   rR   r2   rS   r.   Úform_invalid)r1   rW   rY   r5   r7   r8   r\   †   s    ýûzLoginView.form_invalidc                 C   s4   | j j d¡}|r"| d¡d }n| j j d¡}|S ©z(
        Get client IP address.
        ZHTTP_X_FORWARDED_FORú,r   ZREMOTE_ADDR©r2   rS   rM   Úsplit©r1   Zx_forwarded_forZipr7   r7   r8   rR   ›   s
    zLoginView.get_client_ip)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Útemplate_namer   Ú
form_classr/   r9   rX   r\   rR   Ú__classcell__r7   r7   r5   r8   r)   4   s   ;r)   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú
LogoutViewz4
    Enhanced logout view with session cleanup.
    c                 C   s
   |   |¡S )z(
        Handle logout request.
        )Úpost)r1   r2   r7   r7   r8   rM   ¬   s    zLogoutView.getc                 C   sŠ   |j }tjj|d|  ¡ |j dd¡ddid z(tjj||jj	dd}d	|_
| ¡  W n tjk
rl   Y nX t|ƒ t |d
¡ tdƒS )z,
        Handle logout and cleanup.
        r   r>   r?   Zlogout_methodZuser_initiatedr@   T)r-   rG   rF   Fz&You have been successfully logged out.úauthentication:login)r-   r%   rP   rQ   rR   rS   rM   r$   rN   rG   rF   rO   ÚDoesNotExistÚauth_logoutr	   rT   r   )r1   r2   r-   Zuser_sessionr7   r7   r8   rj   ²   s*    û	ýzLogoutView.postc                 C   s4   | j j d¡}|r"| d¡d }n| j j d¡}|S r]   r_   ra   r7   r7   r8   rR   Ó   s
    zLogoutView.get_client_ipN)rb   rc   rd   re   rM   rj   rR   r7   r7   r7   r8   ri   §   s   !ri   c                       s8   e Zd ZdZdZeZ‡ fdd„Zdd„ Zdd„ Z	‡  Z
S )	ÚRegisterViewz7
    User registration view with profile creation.
    zaccounts/register.htmlc                    s$   |j jrtdƒS tƒ j|f|ž|ŽS r*   r,   r0   r5   r7   r8   r/   æ   s    zRegisterView.dispatchc                 C   s°   t  ¡ Œ | ¡ }z(tjjddd}tjj||ddd W n tjk
rP   Y nX t	jj|ddt
|jƒt
|ƒ|  ¡ | jj dd	¡d
|jdœd W 5 Q R X t | jd¡ tdƒS )z1
        Handle successful registration.
        T)Z
is_defaultrF   Nz)Default role assigned during registration)r-   ÚroleZassigned_byZnotesrQ   r"   r>   r?   Z
email_form)Zregistration_methodZemail_verified©r-   rA   Úobject_typeÚ	object_idÚobject_reprrB   rC   rD   zMAccount created successfully! Please check your email to verify your account.rk   )r   ÚatomicrO   r'   rP   rM   r(   rQ   rl   r%   ÚstrÚidrR   r2   rS   Zis_verifiedr	   rT   r   )r1   rW   r-   Zdefault_roler7   r7   r8   rX   î   s:    
ü
þøþzRegisterView.form_validc                 C   s4   | j j d¡}|r"| d¡d }n| j j d¡}|S r]   r_   ra   r7   r7   r8   rR     s
    zRegisterView.get_client_ip)rb   rc   rd   re   rf   r   rg   r/   rX   rR   rh   r7   r7   r5   r8   rn   ß   s   +rn   c                   @   s(   e Zd ZdZdZeZdd„ Zdd„ ZdS )ÚPasswordResetRequestViewz&
    Password reset request view.
    z$accounts/password_reset_request.htmlc                 C   s^   |  ¡ }t | jd¡ |rVtjj|jddt|j	ƒt|ƒ|  
¡ | jj dd¡ddid td	ƒS )
z0
        Handle password reset request.
        z`If the email address exists in our system, you will receive password reset instructions shortly.Úadminr&   r>   r?   rA   Zpassword_reset_requestedrp   rk   )rO   r	   rT   r2   r%   rP   rQ   r-   ru   rv   rR   rS   rM   r   )r1   rW   Úreset_tokenr7   r7   r8   rX   ,  s"    þøz#PasswordResetRequestView.form_validc                 C   s4   | j j d¡}|r"| d¡d }n| j j d¡}|S r]   r_   ra   r7   r7   r8   rR   H  s
    z&PasswordResetRequestView.get_client_ipN)	rb   rc   rd   re   rf   r   rg   rX   rR   r7   r7   r7   r8   rw   %  s
   rw   c                       sD   e Zd ZdZdZeZ‡ fdd„Z‡ fdd„Zdd„ Z	d	d
„ Z
‡  ZS )ÚPasswordResetConfirmViewz+
    Password reset confirmation view.
    z$accounts/password_reset_confirm.htmlc                    sŽ   |  d¡| _zBtjj | jdd| _| j ¡ rBt |d¡ tdƒW S | jj	| _	W n* tj
k
rx   t |d¡ tdƒ Y S X tƒ j|f|ž|ŽS )z;
        Validate reset token before showing form.
        ÚtokenF)r{   Úis_usedz:Password reset link has expired. Please request a new one.z%authentication:password_reset_requestz6Invalid password reset link. Please request a new one.)rM   r{   r&   rP   ry   Z
is_expiredr	   r[   r   r-   rl   r.   r/   r0   r5   r7   r8   r/   [  s    þ

z!PasswordResetConfirmView.dispatchc                    s   t ƒ  ¡ }| j|d< |S )z$
        Pass user to form.
        r-   )r.   r9   r-   r:   r5   r7   r8   r9   s  s    

z(PasswordResetConfirmView.get_form_kwargsc                 C   s~   t  ¡ Z | ¡ }d| j_| j ¡  tjj|ddt|j	ƒt|ƒ|  
¡ | jj dd¡ddid W 5 Q R X t | jd	¡ td
ƒS )z3
        Handle successful password reset.
        TÚupdater"   r>   r?   rA   Zpassword_reset_completedrp   zBPassword reset successfully! Please log in with your new password.rk   )r   rt   rO   ry   r|   r%   rP   rQ   ru   rv   rR   r2   rS   rM   r	   rT   r   )r1   rW   r-   r7   r7   r8   rX   {  s&    

øþz#PasswordResetConfirmView.form_validc                 C   s4   | j j d¡}|r"| d¡d }n| j j d¡}|S r]   r_   ra   r7   r7   r8   rR   š  s
    z&PasswordResetConfirmView.get_client_ip)rb   rc   rd   re   rf   r    rg   r/   r9   rX   rR   rh   r7   r7   r5   r8   rz   T  s   rz   c                   @   s,   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	S )
ÚProfileViewz+
    User profile view and management.
    zaccounts/profile.htmlc           	      C   sŽ   t jj|jd\}}t||jd}tjj|jdd d¡}tjj|jd 	d¡dd… }t
jj|jdd 	d	¡}|||||d
œ}t|| j|ƒS )z'
        Display user profile.
        ©r-   ©Úinstancer-   T©r-   rF   ro   ú-created_atNé
   ú-last_activity©rW   ÚprofileÚ
user_rolesÚrecent_activitiesÚactive_sessions)r#   rP   Úget_or_creater-   r!   r(   ÚfilterÚselect_relatedr%   Úorder_byr$   r   rf   ©	r1   r2   r‡   ZcreatedrW   rˆ   r‰   rŠ   Úcontextr7   r7   r8   rM   ¬  s8    þýÿþþþýûzProfileView.getc           	      C   s  t jj|jd\}}t|j|j||jd}| ¡ r¢t 	¡ N | 
¡  tjj|jddt|jƒt|ƒ|  ¡ |j dd¡dt|jƒid W 5 Q R X t |d	¡ td
ƒS tjj|jdd d¡}tjj|jd d¡dd… }tjj|jdd d¡}|||||dœ}t|| j|ƒS )z(
        Handle profile update.
        r   r€   r}   r#   r>   r?   Zupdated_fieldsrp   zProfile updated successfully!zauthentication:profileTr‚   ro   rƒ   Nr„   r…   r†   )r#   rP   r‹   r-   r!   rV   ZFILESZis_validr   rt   rO   r%   rQ   ru   rv   rR   rS   rM   ÚlistZchanged_datar	   rT   r   r(   rŒ   r   rŽ   r$   r   rf   r   r7   r7   r8   rj   Ñ  sV    
øþýÿþþþýûzProfileView.postc                 C   s4   | j j d¡}|r"| d¡d }n| j j d¡}|S r]   r_   ra   r7   r7   r8   rR     s
    zProfileView.get_client_ipN)rb   rc   rd   re   rf   rM   rj   rR   r7   r7   r7   r8   r~   ¦  s
   %3r~   c                 C   sJ   | j  dd¡ ¡  ¡ }|s(tdddœƒS tjj|d ¡ }t| |dœƒS )z7
    Check if email is available for registration.
    rY   r?   FzEmail is required)Ú	availabler[   )rY   )r’   rY   )	rU   rM   ÚlowerÚstripr
   r"   rP   rŒ   Úexists)r2   rY   r•   r7   r7   r8   Úcheck_email_availability  s    þr–   c                 C   sº   | j dkrtddiddS zvtjj|| jdd}|j| jjkrNtdd	d
œƒW S d|_| 	¡  t
jj| jddt|jƒt|ƒddid tddiƒW S  tjk
r´   tddd
œƒ Y S X dS )z,
    Terminate a specific user session.
    rV   r[   zMethod not allowedi•  )rZ   T)rv   r-   rF   Fz Cannot terminate current session)rT   r[   rx   r$   rA   Zsession_terminated)r-   rA   rq   rr   rs   rD   rT   zSession not foundN)Úmethodr
   r$   rP   rM   r-   rG   rN   rF   rO   r%   rQ   ru   rv   rl   )r2   Z
session_idrN   r7   r7   r8   Úterminate_session.  s:    
ýþ
ú	þr˜   c           	   
   C   s¾   t jj| jd d¡}| j d¡}|r2|j|d}t| j dd¡ƒ}t| j dd¡ƒ}t||ƒ}| 	|¡}g }|D ],}| 
|j|j|j|j|j ¡ |jd	œ¡ qrt||j|j||jd
œdœƒS )z;
    API endpoint for user activities with pagination.
    r   rƒ   rA   )rA   Úpager   Úper_pager„   )rv   rA   rq   rs   Ú
created_atrD   )r™   Zpagesrš   Ztotal)Ú
activitiesZ
pagination)r%   rP   rŒ   r-   rŽ   rU   rM   Úintr   Zget_pageÚappendrv   rA   rq   rs   r›   Z	isoformatrD   r
   ZnumberZ	num_pagesÚcount)	r2   rœ   Zaction_filterr™   rš   Z	paginatorZpage_objZactivities_dataZactivityr7   r7   r8   Úuser_activities_api[  s<    ÿþ

ú
	üþr    )Pre   ZuuidZdatetimer   Zdjango.shortcutsr   r   r   Zdjango.contrib.authr   rK   r   rm   Zdjango.contrib.auth.decoratorsr   Zdjango.contribr	   Zdjango.httpr
   r   Zdjango.utilsr   Zdjango.core.exceptionsr   Z	django.dbr   Zdjango.views.decorators.httpr   Zdjango.views.decorators.csrfr   Zdjango.views.decorators.cacher   Z'django.contrib.auth.password_validationr   Zdjango.core.paginatorr   Zdjango.db.modelsr   Zdjango.confr   Zdjango.urlsr   Zdjango.utils.decoratorsr   Zdjango.views.genericr   r   r   Zdjango.contrib.auth.mixinsr   Zformsr   r   r   r    r!   Zapps.accounts.modelsr"   r#   r$   r%   r&   r'   r(   r)   ri   rn   rw   rz   r~   Zas_viewZ
login_viewZlogout_viewZregister_viewZpassword_reset_request_viewZpassword_reset_confirm_viewZprofile_viewr–   r˜   r    r7   r7   r7   r8   Ú<module>   sR   $s8F/Rk

,