o
    㓝h^                     @   s  d dl mZmZ d dlmZ d dl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 d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dl 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(Z(d dl)Z)d dl*m+Z+ d dl,Z,d dl-Z-d dl.Z.d dl/m0Z0 d dl1m2Z2 d dl1m3Z3 d dl4m5Z5 e.6e7Z8ede7Z9ee9Z:d dl4m5Z5mZ G dd deZ;e:<e;d G dd deZ=e:<e=d  G d!d" d"eZ>e:<e>d# G d$d% d%eZ?e:<e?d& G d'd( d(eZ@e:<e@d) G d*d+ d+eZAe:<eAd, d d-lBmCZC G d.d/ d/eZDG d0d1 d1eZEe:<eEd2 G d3d4 d4eZFe:<eFd5 dS )6    )ObjectIderrors)	Blueprint)ResourceApireqparse)User)Image)UserReferral)	QuizShare)SECRET)send_sms)
send_email)generate_password_hashN)datetime)ValidationError)check_password_hash)generate_token)jwt_required)requestcurrent_app)secure_filename)Slider)urlparse)Exam)StudyMaterial)NotUniqueErrorauth)r   r   c                   @   s   e Zd Ze Zejdedd ejdedd ejdedd ejdedd ejdedd ejded	d
d ejdedd ejdedd dd ZdddZ	dd Z
dS )Register	mobile_noFtyperequirednameemailpasswordconfirm_passwordregister_typeTSelect user typer!   r"   helprefer_byshared_quiz_idc                 C   s   d}t t||S )Nz0^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)boolrematch)selfr$   Zemail_regex r1   ID:\Internship2\StudyBuddy\EduRuby_flask\flask_backend-main\routes\auth.pyvalidate_email   s   zRegister.validate_email   
   c                 C   sJ   t |D ]}dtjtjtj |d}tj|d	 s |  S qt
d)N )kreferral_codez'Failed to generate unique referral code)rangejoinrandomchoicesstringascii_uppercasedigitsr   objectsfirst	Exception)r0   lengthZmax_attempts_coder1   r1   r2   generate_referral_code   s   zRegister.generate_referral_codec              
   C   sD  t d | j }|d s|d sddddfS |d rL|d r%|d	 s,dd
ddfS |d |d	 kr;ddddfS tj|d d rLddddfS |d r| |d s^ddddfS |d siddddfS |d rq|d	 sxdd
ddfS |d |d	 krddddfS tj|d d rddddfS d }d}|d rtj|d d }|sddddfS |jdkrddddfS |d dkrdnd}t	t
dd}|d |d |d rt|d nd |  dt d |d!}|dr|d |d"< t|d |}|d# sdd$dd%fS |dr5|d |d< d|d&< t|d ||d }|d# s5dd'dd%fS d|v rD|d d u rD|d= t d(|  ztd:i | }W nn tyy }	 zt d)|	  dd*ddfW  Y d }	~	S d }	~	w ty }	 zt d+|	  dd,t	|	 ddfW  Y d }	~	S d }	~	w ty }	 zt d-|	  dd.t	|	 dd%fW  Y d }	~	S d }	~	ww |drt|||t d d/  |d0rtj|d0 d1 }
|
sdd2ddfS t|
j|
|t d d3  |drd4nd5| }t d6 d7|t	|jd8d9fS );Nu#   📩 Reached Register POST endpointr   r$   F"Mobile number or email is requiredstatusmessage  r%   r&   z#Enter password and confirm password*Password and Confirm Password do not match)phoneMobile number already existszEnter a valid emailr#   z
Enter namer$   Email already existsr   r+   r8   Invalid referral code  z/Referral user is not active. Kindly verify OTP.i  r'   Learner(   2   '  韆 %Y-%m-%d %H:%M:%S)r#   	user_typer%   r9   rJ   created_date	login_otprN   rJ   z'Failed to send OTP due to server error.  is_email_verifiedzFailed to send OTP via email.u"   🔥 Final user_data before save: u   ❌ Duplicate entry: zDuplicate user foundu   ❌ Validation error: zValidation failed: u   ❌ Unexpected error: zUnexpected error: )user_idreferred_by_user_idpointsr[   r,   idInvalid quiz idshared_by_user_idquiz_idr_   r[   z1OTP sent successfully, verify your mobile number.z,OTP sent to your email address. Your OTP is u    ✅ User registration successfulT)rJ   rK   Zlast_id   r1   )loggerdebugparser
parse_argsr   rA   rB   r3   rJ   strr<   randintr   rG   r   nowstrftimegetr   r   saver   errorr   rC   r
   r	   r   r_   inforc   )r0   datareferrerra   otp	user_dataZsms_responseemail_responseusereimagerK   r1   r1   r2   post   s   





$$
zRegister.postN)r4   r5   )__name__
__module____qualname__r   RequestParserrk   add_argumentrm   r3   rG   r}   r1   r1   r1   r2   r      s    
r   z	/registerc                   @   R   e Zd Ze Zejdeddd ejdeddd ejdeddd d	d
 ZdS )	VerifyOTPuseridTEnter user idr)   rw   z	Enter OTPr!   zEnter type (otp/email/forget)c                 C   s  | j  }tj|d d }|sddddfS |d dkr+|jd	kr*dd
ddfS n|d dkr;|jr;ddddfS |j|d krIddddfS |d dkrX|jd	d d}n!|d dkrh|jd	d	d d}n|d dkrqd}n|jd	d d}tj|d d 	 }d||ddfS )Nr   rb   FzUser id not exists.rI     r!   rw      zUser already verified.i  r$   zEmail already verified.zInvalid OTP.rS   )set__statuszOTP verified successfully)Zset__is_email_verifiedr   zEmail verified successfullyZforgetz5Otp verified successfully. Continue to reset passwordTrJ   rK   rz      )
rk   rl   r   rA   rB   rJ   r^   r\   updateto_json)r0   ru   rz   msgupdated_userr1   r1   r2   r}   T  s<   

zVerifyOTP.postN	r~   r   r   r   r   rk   r   rm   r}   r1   r1   r1   r2   r   N      r   z
/verifyotpc                   @   r   )ResetPasswordr   Tr   r)   r%   Enter passwordr&   zEnter confirm passwordc                 C   s   | j  }|d  }|d  }|s|sddddfS |s%ddddfS |s.ddddfS ||kr9dd	ddfS tj|d
 d }|sLddddfS t|}|j|d ddddfS )Nr%   r&   Fz-Password and Confirm Password cannot be emptyrI   rL   zPassword cannot be emptyz Confirm Password cannot be emptyrM   r   rb   zInvalid user id.r   )Zset__passwordTzPassword reset successfullyr   )rk   rl   stripr   rA   rB   r   r   )r0   ru   r%   r&   rz   Zhashed_passwordr1   r1   r2   r}     sR   
zResetPassword.postNr   r1   r1   r1   r2   r     r   r   z/reset-passwordc                   @   s^   e Zd Ze Zejdedd ejdedd ejdeddd ejd	edd d
d ZdS )Loginr   Fr    r$   r%   Tr   r)   r,   c                 C   s  | j  }|d}|d}|d}|d}|s$|s$ddddfS |r-d	}|}d
}nd}|}d}tjd%i ||i }	|	sHd|ddfS |	jsRddddfS t|	j|s_ddddfS |	jdkr|r|	j	suddt
|	jdddfS ddt
|	jdddfS ddt
|	jdddfS |	jdkrddddfS |	  }
|
dd  |
dd  t
|
d |
d< d|
v r|
d r|
d d|
d< t
|	j|	j|	jpdd}t|}g }|	jrtj|	jd}|D ]4}|  }|dd  |dd  t
|d |d< d|v r|d r|d d|d< || q|r;tj|d }|s.ddddfS t|j||	t d   d!d"||
|d#}|d$fS )&Nr   r$   r%   r,   FrH   rI   rL   rN   zMobile number not exists.zEmail not exists.r   z%Password is not set for this account.rS   zPassword is incorrect.r   zVerify your email to login.)rJ   rK   r_   r!   Account is deactivated.zVerify your mobile no to loginrw   Account is deleted.r\   _idr[   rY   rT   rc   r$   Zroler+   rb   rd   )rf   rg   r_   Z
created_atTLogin successfully.rJ   rK   tokenrz   	referralsr   r1   )rk   rl   rq   r   rA   rB   r%   r   rJ   r^   rm   rc   
is_deletedto_mongoto_dictpoprp   r$   rZ   r   r9   appendr	   r   r_   r   utcnowrr   )r0   ru   r   r$   r%   r,   Zlookup_fieldZlookup_valueZmissing_msgrz   	user_dicttoken_payloadr   r   referred_usersref_userref_user_datar|   responser1   r1   r2   r}     s   






z
Login.postNr   r1   r1   r1   r2   r     s    r   z/loginc                   @      e Zd Zedd ZdS )Profilec                 C   sH  t tdd }|sddddfS tj|d }|s ddddfS |  }t|d	 |d
< |d	d  |dd  |dd  d|v rQ|d rQ|d 	d|d< g }|
drtj|d d}|D ]8}|  }t|d	 |d
< |d	d  |dd  |dd  d|v r|d r|d 	d|d< || qbdd||ddfS )Nr_   FPass user idrI   rS   rb   Invalid user idr   r   rc   r%   r\   r[   rY   r9   r   Tz(Profile information fetched successfully)rJ   rK   rz   r   r   )getattrr   r   rA   rB   r   r   rm   r   rp   rq   r   )r0   r_   rz   rx   r   Zreferral_usersr   Zref_datar1   r1   r2   rq     sP   
zProfile.getN)r~   r   r   r   rq   r1   r1   r1   r2   r         r   z/profilec                   @   s.   e Zd Ze Zejdeddd dd ZdS )ForgotPasswordr$   TzEnter emailr)   c                 C   s   | j  }|d}tj|d }|sddddfS ttdd}|j	|d	 t
||d
d}|d s;ddddfS dd| dt|jddfS )Nr$   rP   Fz$Email does not exists in our record.rI   r   rW   rX   )Zset__login_otpzForget Password)Zto_emailrw   rZ   rJ   zFailed to send OTP email.r]   TzEnter code z sent to your registered email)rJ   rK   r_   r   )rk   rl   rq   r   rA   rB   rm   r<   rn   r   r   rc   )r0   ru   r$   rz   Z
new_randomry   r1   r1   r2   r}     s8   


zForgotPassword.postNr   r1   r1   r1   r2   r     s    r   z/forget-password)auth_requiredc                   @   r   )UpdateProfilec              
   C   sR  t tdd }|sddddfS tj|d }|s ddddfS i }tjd	}|rI| rI| }tj||jd
 }|rEddddfS ||d	< tjd}|rp| rp| }tj||jd }|rlddddfS ||d< tjd}|r| r| |d< tj	d}	|	rig d}
|	j
 |
vrddddfS |	dtj |	 }|	d |dkrddddfS t|	j}tj|d }|j dtd  | }tjtjdddd}tj|dd  tj||}z|	| W n ty } zdd!t| dd"fW  Y d }~S d }~ww tjd# d$| }||d< |j}|rit |}tj!|j}tjtjdddd|}tj"|rizt#| W n tyh } zt$d%|  W Y d }~nd }~ww |ssdd&ddfS |j%d.i | tj|d & ' }t|d' |d(< |(d'd  |(d)d  |(d*d  dd+|d,d-fS )/Nr_   Fr   rI   rS   rb   r   r   r$   )r$   id__nerQ   rL   r   )rN   r   rO   rN   r#   profile_image)z
image/jpegz	image/jpgz	image/pngz*Only JPG, JPEG, and PNG images are allowedr   i   z(Profile image size should not exceed 1MBrE   r4   staticimagesZuploadsprofileT)exist_okzFailed to save profile image: r]   /z/static/images/uploads/profile/u#   ⚠️ Could not delete old image: zNo fields provided for updater   rc   r%   r\   zProfile updated successfullyr   r   r1   ))r   r   r   rA   rB   formrq   r   rc   filesmimetypelowerseekosSEEK_ENDtellr   filenamepathsplitexturandomhexr;   r   	root_pathmakedirsrr   rC   rm   host_urlrstripr   r   basenameexistsunlinkprintr   r   r   r   )r0   r_   rz   Zupdate_datar$   Zexisting_email_userr   Zexisting_mobile_userr#   r   Zallowed_typessizer   extnew_nameZ
upload_dirnew_pathr{   Z
public_urlZold_urlparsedZold_filenameold_pathr   r1   r1   r2   r}     s   

zUpdateProfile.postN)r~   r   r   r   r}   r1   r1   r1   r2   r     r   r   c                   @   s&   e Zd Zdd Zd	ddZdd ZdS )
GoogleLoginc                 C   s  t jdd}|d}|d}|d}|d}|s#ddd	d
fS |s,ddd	d
fS | |}|dr?d|d d	dfS |d}|dd d|dd  }|s^ddd	dfS tj|d }	|	s|  }
||||
ddd}|rtj|d }|r||d< |dkrdnd}i }|dkr|j	| |d< n|dkr|j
| |d< |j| |d< |jd |d< |jd0i | td0i | }t|j|j|d   ndd!d	dfS td0i | }|}	n|	jdkrdd"d	dfS |	jdkrdd#d	dfS |	  }|d$d  |d%d  t|d& |d&< t|	j|	j|	jp!dd'}t|}g }|	jrZtj|	jd(}|D ]"}|  }|d$d  |d%d  t|d& |d&< || q7|rtj|d) }|sodd*d	dfS t|j||	t  !d+d,  dd-|||d.d/fS )1NT)forcer   r'   r+   r,   FzClerk token not providedrI   rL   r(   rs   rS   r$   	firstNamer6    lastNamez%Clerk token does not contain an emailrP   r   )r#   r$   rZ   r9   r^   rJ   r8   rT   rU   rV   referral_points_learnerZTeacherreferral_points_teachertotal_referral_pointstotal_referrals)r_   r`   ra   rR   r   r   r%   r\   r   r   r   rb   rd   rY   re   r   r   r   r1   )"r   get_jsonrq   verifyClerkTokenr   r   rA   rB   rG   r   r   r   r   r   rr   r
   rc   r   rJ   r   r   r   rm   r$   rZ   r   r9   r   r	   r   r_   r   ro   rp   )r0   ru   Zclerk_tokenr'   r+   r,   rx   r$   r#   rz   r9   Zuser_data_dictrv   ra   Zreferrer_update_dataZnew_userr   r   r   r   r   r   r   r|   r1   r1   r2   r}   \  s   






"	


zGoogleLogin.postr4   c                 C   s4   t    dt  }t|   d| S )z3PHP logic uses md5(uniqid). Replicate that exactly.-N)r<   timehashlibmd5encode	hexdigestupper)r0   rD   rawr1   r1   r2   rG     s   z"GoogleLogin.generate_referral_codec                 C   s0   t j|tdgd}|d |d |d |d dS )NZHS256)Z
algorithmssubr$   r   r   )rc   r$   r   r   )jwtdecoder   )r0   r   payloadr1   r1   r2   r     s   zGoogleLogin.verifyClerkTokenN)r4   )r~   r   r   r}   rG   r   r1   r1   r1   r2   r   Z  s
     
-r   z/google-loginc                   @   s   e Zd Zdd ZdS )GetSliderInfoc              
   C   s   z;t jddd}g }|D ]}||j|j|j|j|jr"|j	 nd d q|g kr4d|ddfW S d|ddfW S  t
yV } zdt|d	d
fW  Y d }~S d }~ww )Nr   )rJ   slide_position)rc   r|   r   rJ   r[   F)rJ   ru   r   TrI   r]   )r   rA   order_byr   rc   r|   r   rJ   r[   	isoformatrC   rm   )r0   ZslidersresultZsliderr{   r1   r1   r2   rq   ,  s<   
zGetSliderInfo.getN)r~   r   r   rq   r1   r1   r1   r2   r   +  s    r   z/getsliderinfo)Gbsonr   r   flaskr   Zflask_restfulr   r   r   Zmodels.userr   Zmodels.imager	   Zmodels.user_referralr
   Zmodels.quiz_sharer   testr   Zutils.sms_servicer   Zutils.email_servicer   Zwerkzeug.securityr   r<   r>   r.   r   mongoenginer   r   r   Zutils.jwt_servicer   r   r   r   Zwerkzeug.utilsr   r   r   Zmodels.sliderr   r   requestsloggingurllib.parser   Zmodels.examr   r   mongoengine.errorsr   	getLoggerr~   ri   auth_bpZauth_apir   Zadd_resourcer   r   r   r   r   Zutils.auth_middlewarer   r   r   r   r1   r1   r1   r2   <module>   sx    

  	,3   .4's P!