a
    AWe                     @   s  d dl m Z  d dlmZmZ d dlmZmZ d dlmZm	Z	m
Z
mZ d dlmZmZmZmZ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" edddZ#ede
j$dddddde
j$ddddeddZ%edde
j$dddiZ&ede
j$d d!d"d#e
j$d$dej'd%d&e
j$d'd!d(d#e
j$d)ddd#e
j$d*ded#e
j$d+ded#d,Z(ed-d.e
j$d/dd0iZ)e%e#j*e%j+< e&e#j*e&j+< e(e#j*e(j+< e)e#j*e)j+< e#,d1G d2d3 d3e	Z-e#,d4G d5d6 d6e	Z.e#,d7G d8d9 d9e	Z/e#,d:G d;d< d<e	Z0e#,d=G d>d? d?e	Z1e#,d@G dAdB dBe	Z2e#,dCG dDdE dEe	Z3e#,dFG dGdH dHe	Z4e#,dIG dJdK dKe	Z5dLS )M    )datetime)url_forrender_template)ValidationErrorEXCLUDE)	NamespaceResourcefieldsModel)create_access_tokencreate_refresh_tokenjwt_requiredget_jwt_identityget_jwtdecode_token)example_password)LoginSchema)EmailSchema)RegisterSchema)RefreshTokenSchema)AuthService)TokenService)MailServiceauthzUser Authentication)description
LoginInputz$Email Or Username for authenticationT      zadmin@pige.com)r   required
min_length
max_lengthexamplezPassword for authentication   )emailpassword
EmailInputr#   zThe user's email address)r   r   RegistrationInputz"User company name for registrationFzCompany Pige)r   r   r!   z"User Company type for registrationzAnonymous Company)r   r   enumr!   zUsername for registrationz
admin@pigezEmail for registrationzPassword for registrationz&Password Confirmation for registration)Zcompany_nameZcompany_typeusernamer#   r$   password_confirmRefreshTokenInputrefreshz.Refresh token for obtaining a new access token)r   r   z/loginc                   @   s,   e Zd Zejdddeedd ZdS )LoginResourcezUser login endpointNsecurityc              
   C   s  z"t j}t }z|j|td}W n4 tyV } zd|jidfW  Y d}~W S d}~0 0 t|d stddidfW S t	|d |d }|sdd	idfW S |j
sdd
idfW S |jrddidfW S |jdkr|  |  |  |j|j
|j|jd}d|jt|j|dt|jddddfW S  ty } z`t|drl|jdurldt|i|jfW  Y d}~S dt|ddfW  Y d}~S W Y d}~n
d}~0 0 dS )a  
        User Login Endpoint: Authenticate and obtain access & refresh tokens.

        This endpoint allows users to log in by providing their email and password. Upon successful
        authentication, it returns access and refresh tokens that can be used for authorized access
        to protected resources.

        :return: A JSON response containing access and refresh tokens if authentication is successful,
                or an error message if authentication fails.
        )unknownmsg  Nr#   z3Access denied: User with this email does not exist.  r$   z"Access denied: Incorrect password.z/Access denied: Account disabled, contact admin.i  z!Access denied: Account Forbidden.F)is_superuser	is_activeis_staffis_adminzLogin successful)identityadditional_claimsr7   )accessr+   )r0   Zuser_idtoken   code0An error occurred while processing your request.r0   error  )auth_namespacepayloadr   loadr   r   messagesr   get_user_by_emailauthenticater4   Z
is_blockedis_verifiedZupdate_last_loginZupdate_last_seensaver3   r5   r6   Z	public_idr   r#   r   	Exceptionhasattrr=   str)selfdataZlogin_schemavalidated_dataerruserr8   e rS   /app/app/resources/v1/auth.pypost`   sv    
	
	zLoginResource.post)__name__
__module____qualname__rB   docexpectr   rU   rS   rS   rS   rT   r,   ^   s   r,   z	/registerc                   @   s,   e Zd Zejdddeedd ZdS )RegisterResourcezUser registration endpointNr-   c           	   
   C   sd  zt j}t }z||}W n4 tyP } zd|jidfW  Y d}~W S d}~0 0 d|v r`|d= t|d durddidfW S t|}|du rddidfW S t	
|jd	}td
|dd}tjd|jtd|ddd ddidfW S  ty^ } z`t|dr,|jdur,dt|i|jfW  Y d}~S dt|ddfW  Y d}~S W Y d}~n
d}~0 0 dS )a  
        User Registration Endpoint: Create a new user account.

        This endpoint allows users to create a new account by providing their registration details,
        including username, first name, last name, email, and password. Upon successful registration,
        a user account is created, and they can use it to log in.

        :return: A JSON response indicating successful registration or an error message if registration fails.
        r0   r1   Nr)   r#   zBUser with this email already exists. Please use a different email.zUser registration failedrA   account_activationauth_verify_email_resourceTactivation_token	_external&Account Activation: Email Verificationactivation_email.htmlactivation_linksubject	recipientmessagehtmlzUser registered successfully   r=   r>   r?   )rB   rC   r   rD   r   rE   r   rF   Zcreate_userr   generate_tokenr#   r   r   
send_emailr   rJ   rK   r=   rL   )	rM   rN   Zregister_schemarO   rP   rQ   r_   rd   rR   rS   rS   rT   rU      s\    

zRegisterResource.post)rV   rW   rX   rB   rY   rZ   r&   rU   rS   rS   rS   rT   r[      s   r[   z/logoutc                   @   s0   e Zd Ze eeejdddd ZdS )LogoutResourcejwtr-   c              
   C   s  zt j}t }z||}W n4 tyR } zd|jidfW  Y d}~W S d}~0 0 tt j	}t
|d d}|durt  |krddidfW S t|t
|d d rdd	idfW S t|d d|t
|d d d
 tdd|t d d
 ddidfW S  ty } z`t|drN|jdurNdt|i|jfW  Y d}~S dt|ddfW  Y d}~S W Y d}~n
d}~0 0 dS )aT  
        User Logout Endpoint (POST): Revoke access and refresh tokens.

        This endpoint allows users to log out, revoking their access and refresh tokens.
        It checks the validity and expiration status of the refresh token before proceeding.

        :return: A response message indicating success or an error message.
        r0   r1   Nr+   expzRefresh token has expired.r2   jtiAccess denied: Bad Token.zUser Logoutr:   zUser logged out successfullyr<   r=   r>   r?   rA   )rB   rC   r   rD   r   rE   r   rF   r   idr   getr   utcnow	timestampr   is_blacklistedblacklist_tokenr   rJ   rK   r=   rL   )rM   rN   refresh_token_schemarO   rP   current_user_idrefresh_exprR   rS   rS   rT   rU     sN    "zLogoutResource.postN)	rV   rW   rX   r   rB   rZ   r*   rY   rU   rS   rS   rS   rT   rm     s   
rm   z/token/verifyc                   @   s@   e Zd Ze ejdddd Ze ejdddd ZdS )VerifyTokenResourcern   r-   c              
   C   s   zFt  }|du rddidfW S t|du r:ddidfW S ddidfW S  ty } z\t|dr|jdurdt|i|jfW  Y d}~S d	t|d
dfW  Y d}~S W Y d}~n
d}~0 0 dS aO  
        Token Verification Endpoint: Verify the validity of an access token.

        This endpoint allows users to verify the validity of their access token.
        It checks if the token is valid and if the user associated with the token exists.

        :return: A response message indicating success or an error message.
        Nr0   (Access denied: Invalid or expired token.r2   rq   zToken verified successfully.r<   r=   r>   r?   rA   r   r   rF   rJ   rK   r=   rL   rM   ry   rR   rS   rS   rT   rs   U  s6    zVerifyTokenResource.getc              
   C   s   zFt  }|du rddidfW S t|du r:ddidfW S ddidfW S  ty } z\t|dr|jdurdt|i|jfW  Y d}~S d	t|d
dfW  Y d}~S W Y d}~n
d}~0 0 dS r|   r~   r   rS   rS   rT   rU     s6    zVerifyTokenResource.postN)rV   rW   rX   r   rB   rY   rs   rU   rS   rS   rS   rT   r{   S  s   
*
r{   z/token/refreshc                   @   s&   e Zd Ze ejdddd ZdS )RefreshTokenResourcern   r-   c              
   C   s  zNt  }|du r ddidfW S tj}t }z||}W n4 tyn } zd|jidfW  Y d}~W S d}~0 0 t|d }|d}|durt	
  |krddidfW S ||d	krdd
idfW S t|}|du rddidfW S t||d rddidfW S t d }	|	r2tdd|jt d d t|d}
|
|d dddfW S  ty } z`t|dr|jdurdt|i|jfW  Y d}~S dt|ddfW  Y d}~S W Y d}~n
d}~0 0 dS )aP  
        Token Refresh Endpoint: Refresh an access token using a valid refresh token.

        This endpoint allows users to refresh their access token using a valid refresh token.
        It validates the refresh token and issues a new access token.

        :return: A response message indicating success or an error message.
        Nr0   r}   r2   r1   r+   ro   z)Access denied: Refresh token has expired.subz2Access denied: Invalid user for the refresh token.rq   rp   r:   zRefresh tokenr9   z#Access token refreshed successfully)r:   r+   r0   r<   r=   r>   r?   rA   )r   rB   rC   r   rD   r   rE   r   rs   r   rt   ru   r   rF   r   rv   r   rw   rr   r   rJ   rK   r=   rL   )rM   ry   rN   rx   rO   rP   Zrefresh_decoderz   rQ   Zprevious_access_jtir:   rR   rS   rS   rT   rU     sx    



zRefreshTokenResource.postN)rV   rW   rX   r   rB   rY   rU   rS   rS   rS   rT   r     s   
r   z#/activate/<string:activation_token>c                   @   s"   e Zd Zejddddd ZdS )VerifyEmailResourcez#Activate user account: verify emailNr-   c              
   C   s   zht |\}}|s$d|ddfW S t|d }|durN|jrNddidfW S d	|_|  dd
idfW S  ty } z\t|dr|jdurdt	|i|jfW  Y d}~S dt	|ddfW  Y d}~S W Y d}~n
d}~0 0 dS )a5  
        Email Verification Endpoint: Verify user's email address.

        This endpoint allows users to verify their email address by providing an activation token sent to their email.
        Upon successful verification, the user's email address is marked as verified, allowing them access to the application.

        :param activation_token: The activation token sent to the user's email address.
        :type activation_token: str

        :return: A JSON response indicating successful email verification or an error message if verification fails.
        zEmail verification failedr?   r1   r#   Nr0   zEmail is already verifiedr<   TzEmail verified successfullyr=   r>   rA   )
r   Zverify_tokenr   rF   rH   rI   rJ   rK   r=   rL   )rM   r_   statusrN   rQ   rR   rS   rS   rT   rs     s>    zVerifyEmailResource.get)rV   rW   rX   rB   rY   rs   rS   rS   rS   rT   r     s   r   z/resend-email-verifyc                   @   s,   e Zd Zeeejddddd ZdS )ResendVerificationEmailResourcez"Resend Verification Email endpointNr-   c           
   
   C   s`  zt j}t }z||}W n4 tyP } zd|jidfW  Y d}~W S d}~0 0 t|d }|du rvddidfW S |jrddidfW S t	
|jd	}td
|dd}tjd|jtd|ddd}|rddidfW S ddidfW S  tyZ }	 z`t|	dr(|	jdur(dt|	i|	jfW  Y d}	~	S dt|	ddfW  Y d}	~	S W Y d}	~	n
d}	~	0 0 dS )af  
        Resend Verification Email Endpoint: Resend a verification email to the user.

        This endpoint allows users to request the resending of a verification email.
        It checks if the user's email is already verified and sends a new verification email if not.

        :return: A response message indicating success or an error message.
        r0   r1   Nr#   $User with this email does not exist.i  zEmail is already verified.r<   r\   r]   Tr^   ra   rb   rc   re   $Failed to send password reset email.rA   z0Verification email has been resent successfully.r=   r>   r?   )rB   rC   r   rD   r   rE   r   rF   rH   r   rk   r#   r   r   rl   r   rJ   rK   r=   rL   )
rM   rN   email_schemarO   rP   rQ   r_   rd   send_mail_statusrR   rS   rS   rT   rU   E  sb    
z$ResendVerificationEmailResource.postrV   rW   rX   rB   rZ   r%   rY   rU   rS   rS   rS   rT   r   C  s   r   z/forgot-passwordc                   @   s6   e Zd Zeeejddddddddd	 Zd
S )ForgotPasswordResourcezForgot Password EndpointzCInitiate the password reset process by providing your email addressz8Password reset instructions have been sent to your emailzUser does not existz/An error occurred while processing your request)r<   r1   rA   )r   	responsesc           
   
   C   sL  zt j}t }z||}W n4 tyP } zd|jidfW  Y d}~W S d}~0 0 t|d }|du rvddidfW S t	|j
d}td|dd	}tjd
|j
td|ddd}|sddidfW S ddidfW S  tyF }	 z`t|	dr|	jdurdt|	i|	jfW  Y d}	~	S dt|	ddfW  Y d}	~	S W Y d}	~	n
d}	~	0 0 dS )a  
        Forgot Password Endpoint: Send a password reset email to the user.

        This endpoint allows users to request a password reset by providing their registered email address.

        :return: A response message indicating success or an error message.
        r0   r<   Nr#   r   Zpassword_resetZauth_reset_password_resourceT)password_reset_tokenr`   z#Password Reset: Reset Your Passwordzreset_password.html)password_reset_token_linkre   r   rA   z#Password reset email has been sent.r=   r>   r?   )rB   rC   r   rD   r   rE   r   rF   r   rk   r#   r   r   rl   r   rJ   rK   r=   rL   )
rM   rN   r   rO   rP   rQ   r   r   r   rR   rS   rS   rT   rU     sX    
zForgotPasswordResource.postNr   rS   rS   rS   rT   r     s   	r   z&/reset-password/<password_reset_token>c                   @   s   e Zd Zdd ZdS )ResetPasswordResourcec                 C   s   d S )NrS   )rM   r   rS   rS   rT   rU     s    zResetPasswordResource.postN)rV   rW   rX   rU   rS   rS   rS   rT   r     s   r   N)6r   flaskr   r   Zmarshmallowr   r   flask_restxr   r   r	   r
   flask_jwt_extendedr   r   r   r   r   r   Zapp.utils.password_generatorr   Zapp.schema.loginr   Zapp.schema.emailr   Zapp.schema.registerr   Zapp.schema.tokenr   app.services.authr   app.services.tokenr   Zapp.services.mailr   rB   Stringr   r%   Zallowed_company_typesr&   r*   modelsnamerouter,   r[   rm   r{   r   r   r   r   r   rS   rS   rS   rT   <module>   s    "aOBZ]6IL