§
    Þ¶»jâH  ã                  óê   — d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	m
Z
 ddlmZmZmZmZmZmZmZ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 dd	lm Z   G d
„ d¦  «        Z! G d„ d¦  «        Z"dS )z©
High-Level Authentication & Account Management Service for FreeExile.
Coordinates Registration, Email Activation, Anti-Bot Captcha, Pluggable OAuth, and Token Refresh.
é    )ÚannotationsN)ÚDictÚOptionalÚTuple)	ÚAccountÚAccountRegistrationResultÚAccountStatusÚAuthTokenPairÚEmailVerificationResultÚLoginResultÚOAuthLoginResultÚOAuthProviderTypeÚRefreshTokenResult)ÚPasswordHasherÚTokenService)ÚCaptchaEngineÚCaptchaChallengeÚCaptchaTypeÚRateLimiter)ÚEmailVerificationService)ÚOAuthServicec                  ój   — e Zd ZdZdd„Zej        dfdd„Zdd„Zd d„Z	d!d„Z
d"d„Zd#d„Zd$d„Zd%d„ZdS )&ÚAccountRepositoryz>Thread-safe in-memory account data store with indexed lookups.ÚreturnÚNonec                ó>   — i | _         i | _        i | _        i | _        d S ©N)Ú_accounts_by_idÚ_accounts_by_emailÚ_accounts_by_usernameÚ_refresh_tokens)Úselfs    ú1C:\Projects\FreeExile\server\auth\auth_service.pyÚ__init__zAccountRepository.__init__!   s(   € Ø35ˆÔØ68ˆÔØ9;ˆÔ"Ø/1ˆÔÐÐó    NÚemailÚstrÚpassword_hashÚusernameÚstatusr	   ÚrolesúOptional[list[str]]r   c                ó`  — dt          j        ¦   «         j        d d…         › �}t          ||                     ¦   «                              ¦   «         |                     ¦   «         |||�|ndg¬¦  «        }|| j        |<   || j        |j        <   || j	        |j
                             ¦   «         <   |S )NÚacc_é   Úplayer)Ú
account_idr&   r)   r(   r*   r+   )ÚuuidÚuuid4Úhexr   ÚstripÚlowerr   r   r&   r    r)   )r"   r&   r(   r)   r*   r+   r1   Úaccounts           r#   Úcreate_accountz AccountRepository.create_account'   s±   € ð 4�DœJ™LœLÔ,¨S¨b¨SÔ1Ð3Ð3ˆ
ÝØ!Ø—+’+‘-”-×%Ò%Ñ'Ô'Ø—^’^Ñ%Ô%Ø'ØØ Ð,�%�%°8°*ð
ñ 
ô 
ˆð ,3ˆÔ˜ZÑ(Ø18ˆÔ ¤Ñ.Ø?FˆÔ" 7Ô#3×#9Ò#9Ñ#;Ô#;Ñ<Øˆr%   r1   úOptional[Account]c                ó6   — | j                              |¦  «        S r   )r   Úget)r"   r1   s     r#   Ú	get_by_idzAccountRepository.get_by_id=   s   € ØÔ#×'Ò'¨
Ñ3Ô3Ð3r%   c                ó~   — | j                              |                     ¦   «                              ¦   «         ¦  «        S r   )r   r;   r5   r6   )r"   r&   s     r#   Úget_by_emailzAccountRepository.get_by_email@   s-   € ØÔ&×*Ò*¨5¯;ª;©=¬=×+>Ò+>Ñ+@Ô+@ÑAÔAÐAr%   c                ó~   — | j                              |                     ¦   «                              ¦   «         ¦  «        S r   )r    r;   r5   r6   )r"   r)   s     r#   Úget_by_usernamez!AccountRepository.get_by_usernameC   s/   € ØÔ)×-Ò-¨h¯nªnÑ.>Ô.>×.DÒ.DÑ.FÔ.FÑGÔGÐGr%   Úproviderr   Úprovider_user_idc                ó”   — | j                              ¦   «         D ]-}|j                             |¦  «        }|r|j        |k    r|c S Œ.d S r   )r   ÚvaluesÚoauth_identitiesr;   rB   )r"   rA   rB   r7   Úidentitys        r#   Úget_by_oauthzAccountRepository.get_by_oauthF   s[   € ØÔ+×2Ò2Ñ4Ô4ð 	ð 	ˆGØÔ/×3Ò3°HÑ=Ô=ˆHØð ˜HÔ5Ð9IÒIÐIØ���øØˆtr%   Úrefresh_tokenc                ó   — || j         |<   d S r   )r!   ©r"   rH   r1   s      r#   Ústore_refresh_tokenz%AccountRepository.store_refresh_tokenM   s   € Ø.8ˆÔ˜]Ñ+Ð+Ð+r%   c                óh   — | j                              |¦  «        }|r|                      |¦  «        S d S r   )r!   r;   r<   rJ   s      r#   Úget_account_by_refresh_tokenz.AccountRepository.get_account_by_refresh_tokenP   s7   € ØÔ)×-Ò-¨mÑ<Ô<ˆ
Øð 	.Ø—>’> *Ñ-Ô-Ð-Øˆtr%   c                ó<   — | j                              |d ¦  «         d S r   )r!   Úpop)r"   rH   s     r#   Úrevoke_refresh_tokenz&AccountRepository.revoke_refresh_tokenV   s!   € ØÔ× Ò  °Ñ5Ô5Ð5Ð5Ð5r%   )r   r   )r&   r'   r(   r'   r)   r'   r*   r	   r+   r,   r   r   )r1   r'   r   r9   )r&   r'   r   r9   )r)   r'   r   r9   )rA   r   rB   r'   r   r9   )rH   r'   r1   r'   r   r   )rH   r'   r   r9   )rH   r'   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r$   r	   ÚPENDING_ACTIVATIONr8   r<   r>   r@   rG   rK   rM   rP   © r%   r#   r   r      sæ   € € € € € ØHÐHð2ð 2ð 2ð 2ð !.Ô @Ø%)ðð ð ð ð ð,4ð 4ð 4ð 4ðBð Bð Bð BðHð Hð Hð Hðð ð ð ð9ð 9ð 9ð 9ðð ð ð ð6ð 6ð 6ð 6ð 6ð 6r%   r   c                  óž   — e Zd ZdZ ej        d¦  «        Z	 	 	 	 dAdBd„Zej	        fdCd!„Z
dDd(„ZdEd+„Z	 	 	 	 dFdGd2„ZdHd5„ZdId;„ZdJd>„ZdKdLd@„ZdS )MÚAuthServicez0Core Authentication & Account Lifecycle Service.z0^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$Né   ç      Œ@Ú
repositoryr   Úhasherr   Útoken_servicer   Úcaptcha_enginer   Úemail_servicer   Úoauth_servicer   Úsecurity_engineúOptional[Any]Úcharacter_serviceÚmax_login_attemptsÚintÚlockout_duration_secondsÚfloatr   r   c                ó¾   — || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        t          dd¬¦  «        | _        d S )Né
   g      N@)Úmax_requestsÚwindow_seconds)r[   r\   r]   r^   r_   r`   ra   rc   rd   rf   r   Úip_rate_limiter)r"   r[   r\   r]   r^   r_   r`   ra   rc   rd   rf   s              r#   r$   zAuthService.__init___   sm   € ð %ˆŒØˆŒØ*ˆÔØ,ˆÔØ*ˆÔØ*ˆÔØ.ˆÔØ!2ˆÔØ"4ˆÔØ(@ˆÔ%Ý*¸È4ÐPÑPÔPˆÔÐÐr%   Ú	client_ipr'   Úpreferred_typer   r   c                óŠ   — |t           j        k    r| j                             d¬¦  «        S | j                             ¦   «         S )z)Issue dynamic anti-bot Captcha challenge.é   )Ú
difficulty)r   ÚPOWr^   Úgenerate_pow_challengeÚgenerate_math_challenge)r"   rm   rn   s      r#   Úrequest_captchazAuthService.request_captchax   s>   € à�[œ_Ò,Ð,ØÔ&×=Ò=ÈÐ=ÑKÔKÐKØÔ"×:Ò:Ñ<Ô<Ð<r%   r&   Úpasswordr)   Ú
captcha_idÚcaptcha_solutionr   c                ót  — | j                              |¦  «        st          dd¬¦  «        S |                     ¦   «                              ¦   «         }| j                             |¦  «        st          dd¬¦  «        S t          |¦  «        dk     rt          dd¬¦  «        S d\  }}	|                     d¦  «        rô| j	         
                    |› d	|                     ¦   «         › d	t          t          j        ¦   «         d
z  ¦  «        dz   › �¦  «        }
| j	                             ||| j	         
                    |› d	|                     ¦   «         › d	t          t          j        ¦   «         d
z  ¦  «        dz   › �¦  «        t          t          j        ¦   «         d
z  ¦  «        dz   ¬¦  «        \  }}	nœ|                     d¦  «        r‡| j	                             ||d| j	         
                    |› dt          t          j        ¦   «         d
z  ¦  «        dz   › �¦  «        t          t          j        ¦   «         d
z  ¦  «        dz   ¬¦  «        \  }}	|s|dk    rt          dd¬¦  «        S | j                             |¦  «        �t          dd¬¦  «        S |r|                     ¦   «         n|                     d¦  «        d         }| j                             |¦  «        �|› dt'          j        d¦  «        › �}| j                             |¦  «        }| j                             |||t0          j        ¬¦  «        }	 | j                             ||j        ¬¦  «         n?# t:          $ r2}t          ddt=          |¦  «        › �|j        d¬¦  «        cY d}~S d}~ww xY wt          dd|j        d| j        j        ¬¦  «        S ) zTQuick registration with bot-spam protection and automatic email activation dispatch.FzDToo many registration requests from your IP. Please try again later.©ÚsuccessÚmessagezInvalid email address format.é   z,Password must be at least 8 characters long.)FzMissing captchaÚcap_ú:iè  i ¿ )Úchallenge_idÚuser_answerÚ	signatureÚ
expires_atÚpow_rp   z:2:)ÚseedÚnoncerq   r‚   rƒ   Úinvalid_answerz"Invalid anti-bot Captcha solution.NzEmail is already registered.ú@r   Ú_i'  )r&   r(   r)   r*   )r&   r1   Tz,Account created, but email dispatch failed: )r{   r|   r1   Úrequires_verificationzIRegistration successful. Please check your email for the activation code.)r{   r|   r1   rŠ   Úcode_expires_in_seconds) rl   Ú
is_allowedr   r5   r6   ÚEMAIL_REGEXÚmatchÚlenÚ
startswithr^   Ú_signre   ÚtimeÚverify_math_challengeÚverify_pow_challenger[   r>   Úsplitr@   ÚsecretsÚ	randbelowr\   Úhash_passwordr8   r	   rU   r_   Úsend_activation_emailr1   Ú	Exceptionr'   Úcode_ttl_seconds)r"   r&   rv   r)   rw   rx   rm   Ú
norm_emailÚis_valid_captchaÚcaptcha_msgÚexpected_sigÚchosen_usernameÚpwd_hashr7   Úes                  r#   Úquick_registerzAuthService.quick_register~   sB  € ð Ô#×.Ò.¨yÑ9Ô9ð 	Ý,ØØ^ðñ ô ð ð —[’[‘]”]×(Ò(Ñ*Ô*ˆ
ØÔ×%Ò% jÑ1Ô1ð 	eÝ,°UÐDcÐdÑdÔdÐdõ ˆx‰=Œ=˜1ÒÐÝ,°UÐDrÐsÑsÔsÐsð
 )AÑ%Ð˜+Ø× Ò  Ñ(Ô(ð 	ð  Ô.×4Ò4¸
ð  6Að  6AÐEU×E[ÒE[ÑE]ÔE]ð  6Að  6AÕ`cÕdhÔdmÑdoÔdoÐptÑdtÑ`uÔ`uÐx~Ñ`~ð  6Að  6Añ  Bô  BˆLà,0Ô,?×,UÒ,UØ'Ø,ØÔ-×3Ò3°zÐ4Ð4ÐDT×DZÒDZÑD\ÔD\Ð4Ð4Õ_bÕcgÔclÑcnÔcnÐosÑcsÑ_tÔ_tÐw}Ñ_}Ð4Ð4ñ  Aô  AÝ�tœy™{œ{¨TÑ1Ñ2Ô2°VÑ;ð	 -Vñ -ô -Ñ)Ð˜k˜kð ×"Ò" 6Ñ*Ô*ð 	Ø,0Ô,?×,TÒ,TØØ&ØØÔ-×3Ò3°zÐ4fÐ4fÅcÍ$Ì)É+Ì+ÐVZÑJZÑF[ÔF[Ð^dÑFdÐ4fÐ4fÑgÔgÝ�tœy™{œ{¨TÑ1Ñ2Ô2°VÑ;ð -Uñ -ô -Ñ)Ð˜kð  ð 	jÐ$4Ð8HÒ$HÐ$HÝ,°UÐDhÐiÑiÔiÐið Œ?×'Ò'¨
Ñ3Ô3Ð?Ý,°UÐDbÐcÑcÔcÐcð /7ÐT˜(Ÿ.š.Ñ*Ô*Ð*¸J×<LÒ<LÈSÑ<QÔ<QÐRSÔ<TˆØŒ?×*Ò*¨?Ñ;Ô;ÐGØ!0ÐMÐMµ7Ô3DÀUÑ3KÔ3KÐMÐMˆOð ”;×,Ò,¨XÑ6Ô6ˆð ”/×0Ò0ØØ"Ø$Ý Ô3ð	 1ñ 
ô 
ˆð	ØÔ×4Ò4¸:ÐRYÔRdÐ4ÑeÔeÐeÐeøÝð 	ð 	ð 	Ý,ØØOÅsÈ1ÁvÄvÐOÐOØ"Ô-Ø&*ð	ñ ô ð ð ð ð ð ð øøøøð	øøøõ )ØØ_ØÔ)Ø"&Ø$(Ô$6Ô$Gð
ñ 
ô 
ð 	
s   Ì6!M Í
NÍ"'NÎ	NÎNÚverification_coder   c                óÊ  — |                      ¦   «                              ¦   «         }| j                             |¦  «        }|st	          dd¬¦  «        S |j        t          j        k    rt	          dd¬¦  «        S | j         	                    ||¦  «        \  }}|st	          d|¬¦  «        S t          j        |_        t          | j        d¦  «        r| j                             |¦  «         | j                             |j        |j        |j        ¬¦  «        }| j                             |j        |j        ¦  «         t	          dd|j        |j        |j        |j        ¬	¦  «        S )
zRActivate account using 6-digit OTP or link token and issue initial session tokens.FzAccount not found.rz   zAccount is already activated.Úupdate_account©r1   r+   r&   Tz5Account activated successfully. Welcome to FreeExile!)r{   r|   r1   Úaccess_tokenrH   Úexpires_in_seconds)r5   r6   r[   r>   r   r*   r	   ÚACTIVEr_   Úverify_codeÚhasattrr¦   r]   Úgenerate_token_pairr1   r+   r&   rK   rH   r¨   r©   )r"   r&   r¤   rœ   r7   Úis_validÚmsgÚ
token_pairs           r#   Úverify_emailzAuthService.verify_emailß   se  € à—[’[‘]”]×(Ò(Ñ*Ô*ˆ
Ø”/×.Ò.¨zÑ:Ô:ˆØð 	XÝ*°5ÐBVÐWÑWÔWÐWàŒ>�]Ô1Ò1Ð1Ý*°5ÐBaÐbÑbÔbÐbàÔ*×6Ò6°zÐCTÑUÔU‰ˆ�#Øð 	GÝ*°5À#ÐFÑFÔFÐFõ 'Ô-ˆŒÝ�4”?Ð$4Ñ5Ô5ð 	4ØŒO×*Ò*¨7Ñ3Ô3Ð3ð Ô'×;Ò;ØÔ)Ø”-Ø”-ð <ñ 
ô 
ˆ
ð
 	Œ×+Ò+¨JÔ,DÀgÔFXÑYÔYÐYå&ØØKØÔ)Ø#Ô0Ø$Ô2Ø)Ô<ð
ñ 
ô 
ð 	
r%   FúOptional[str]Úremember_meÚboolÚdevice_fingerprintr   c           
     ó   — |                      ¦   «                              ¦   «         }| j                             |¦  «        }	|	st	          dd¬¦  «        S |	                     ¦   «         rPt          |	j        pt          j        ¦   «         t          j        ¦   «         z
  ¦  «        }
t	          dd|
› d�¬¦  «        S | j	         
                    ||	j        ¦  «        s³| j        r9|r7| j                             |	j        |¦  «        \  }}|rt	          dd¬¦  «        S nQ|	xj        dz  c_        |	j        | j        k    r1t          j        ¦   «         | j        z   |	_        t	          dd¬¦  «        S t	          dd| j        |	j        z
  › d	�¬¦  «        S |	j        t&          j        k    rt	          dd
|	j        |	j        ¬¦  «        S |	j        t&          j        t&          j        fv r7t	          dd|	j        j                             ¦   «         › d�|	j        ¬¦  «        S | j        r#|r!| j                             |	j        |¦  «         nUd|	_        d|	_        t          j        ¦   «         |	_        t5          | j        d¦  «        r| j                             |	¦  «         | j                             |	j        |	j        |	j        ¬¦  «        }| j                              |j!        |	j        ¦  «         d}|r9| j        r2|r0| j         "                    |	j        |d¬¦  «        }|j#        r|j$        }t	          dd|j%        |j!        |	j        |	j&        |	j        |¬¦  «        S )z^Authenticate user credentials with brute-force lockout protection and optional remember token.FzInvalid email or password.rz   zGAccount temporarily locked due to repeated failed logins. Try again in z	 seconds.z>Too many failed login attempts. Account locked for 15 minutes.é   zInvalid email or password. (z attempts left)z>Account is pending activation. Please verify your email first.)r{   r|   r1   r*   zAccount is ú.)r{   r|   r*   r   Nr¦   r§   é   )r1   ÚdeviceÚ
valid_daysTzLogin successful.©r{   r|   r¨   rH   r1   r)   r*   Úremember_token)'r5   r6   r[   r>   r   Ú	is_lockedre   Úlockout_untilr’   r\   Úverify_passwordr(   ra   Úrecord_login_failurer1   Úfailed_login_attemptsrd   rf   r*   r	   rU   ÚBANNEDÚ	SUSPENDEDÚnameÚrecord_login_successÚlast_login_atr¬   r¦   r]   r­   r+   r&   rK   rH   Úissue_remember_tokenr{   Ú	raw_tokenr¨   r)   )r"   r&   rv   rm   rw   rx   r³   rµ   rœ   r7   Úremaining_lockoutÚdelayr¾   r°   Úremember_tokÚrem_ress                   r#   ÚloginzAuthService.login  s½  € ð —[’[‘]”]×(Ò(Ñ*Ô*ˆ
Ø”/×.Ò.¨zÑ:Ô:ˆØð 	TÝ uÐ6RÐSÑSÔSÐSð ×ÒÑÔð 	Ý # WÔ%:Ð%I½d¼i¹k¼kÍTÌYÉ[Ì[Ñ$XÑ YÔ YÐÝØØ~ÐbsÐ~Ð~Ð~ðñ ô ð ð Œ{×*Ò*¨8°WÔ5JÑKÔKð 	ØÔ#ð Ð(:ð Ø#'Ô#7×#LÒ#LÈWÔM_ÐasÑ#tÔ#tÑ ��yØð Ý&Ø %Ø `ðñ ô ð ðð Ð-Ô-°Ñ2Ð-Ô-ØÔ0°DÔ4KÒKÐKÝ,0¬I©K¬K¸$Ô:WÑ,W�GÔ)Ý&Ø %Ø `ðñ ô ð õ ØØ°tÔ7NÐQXÔQnÑ7nÐÐÐðñ ô ð ð Œ>�]Ô=Ò=Ð=ÝØØXØ"Ô-Ø”~ð	ñ ô ð ð Œ>�mÔ2µMÔ4KÐLÐLÐLÝØØD g¤nÔ&9×&?Ò&?Ñ&AÔ&AÐDÐDÐDØ”~ðñ ô ð ð Ôð 	8Ð$6ð 	8ØÔ ×5Ò5°gÔ6HÐJ\Ñ]Ô]Ð]Ð]à,-ˆGÔ)Ø$(ˆGÔ!Ý$(¤I¡K¤KˆGÔ!Ý�t”Ð(8Ñ9Ô9ð 8Ø”×.Ò.¨wÑ7Ô7Ð7ð Ô'×;Ò;ØÔ)Ø”-Ø”-ð <ñ 
ô 
ˆ
ð
 	Œ×+Ò+¨JÔ,DÀgÔFXÑYÔYÐYð ˆØð 	1˜4Ô/ð 	1Ð4Fð 	1ØÔ*×?Ò?Ø"Ô-Ø)Øð @ñ ô ˆGð
 Œð 1Ø&Ô0�åØØ'Ø#Ô0Ø$Ô2ØÔ)ØÔ%Ø”>Ø'ð	
ñ 	
ô 	
ð 		
r%   r½   ÚAnyc           
     óB  — | j         st          dd¬¦  «        S | j                              ||¬¦  «        }|j        r|j        st          d|j        ¬¦  «        S | j                             |j        ¦  «        }|r|j        t          j
        k    rt          dd¬¦  «        S | j                             |j        |j        |j        ¬¦  «        }| j                             |j        |j        ¦  «         t          dd|j        |j        |j        |j        |j        |¬	¦  «        S )
z81-Click login using bank-grade remember-me device token.Fz Security engine not initialized.rz   )rÉ   Úcurrent_devicezAccount inactive or not found.r§   Tz&Remember-me authentication successful.r¼   )ra   r   Úauthenticate_remember_tokenr{   r1   r|   r[   r<   r*   r	   rª   r]   r­   r+   r&   rK   rH   r¨   r)   )r"   r½   rµ   rÍ   r7   r°   s         r#   Úlogin_with_remember_tokenz%AuthService.login_with_remember_tokeni  sE  € ð Ô#ð 	ZÝ uÐ6XÐYÑYÔYÐYàÔ&×BÒBØ$Ø-ð Cñ 
ô 
ˆð Œð 	G gÔ&8ð 	GÝ u°g´oÐFÑFÔFÐFà”/×+Ò+¨GÔ,>Ñ?Ô?ˆØð 	X˜'œ.­MÔ,@Ò@Ð@Ý uÐ6VÐWÑWÔWÐWð Ô'×;Ò;ØÔ)Ø”-Ø”-ð <ñ 
ô 
ˆ
ð
 	Œ×+Ò+¨JÔ,DÀgÔFXÑYÔYÐYåØØ<Ø#Ô0Ø$Ô2ØÔ)ØÔ%Ø”>Ø)ð	
ñ 	
ô 	
ð 		
r%   rA   r   Úauth_code_or_tokenÚredirect_urir   c                ó>   — | j                              ||||¬¦  «        S )z:Authenticate via OAuth provider (Google, Apple, Facebook).)Úprovider_typerÔ   rÕ   rm   )r`   Úauthenticate_oauth)r"   rA   rÔ   rÕ   rm   s        r#   Úoauth_loginzAuthService.oauth_login�  s0   € ð Ô!×4Ò4Ø"Ø1Ø%Øð	 5ñ 
ô 
ð 	
r%   rH   r   c                ó¢  — | j                              |¦  «        }|r|j        t          j        k    rt          dd¬¦  «        S | j                              |¦  «         | j                             |j	        |j
        |j        ¬¦  «        }| j                              |j        |j	        ¦  «         t          dd|j        |j        |j        ¬¦  «        S )z0Rotate refresh token and issue new access token.Fz!Invalid or expired refresh token.rz   r§   TzToken refreshed successfully.)r{   r|   r¨   rH   r©   )r[   rM   r*   r	   rª   r   rP   r]   r­   r1   r+   r&   rK   rH   r¨   r©   )r"   rH   r7   Únew_token_pairs       r#   rH   zAuthService.refresh_tokenŸ  sâ   € à”/×>Ò>¸}ÑMÔMˆØð 	˜'œ.­MÔ,@Ò@Ð@Ý%ØØ;ðñ ô ð ð 	Œ×,Ò,¨]Ñ;Ô;Ð;ð Ô+×?Ò?ØÔ)Ø”-Ø”-ð @ñ 
ô 
ˆð
 	Œ×+Ò+¨NÔ,HÈ'ÔJ\Ñ]Ô]Ð]å!ØØ3Ø'Ô4Ø(Ô6Ø-Ô@ð
ñ 
ô 
ð 	
r%   r¨   c                ór   — | j                              |¦  «         |r| j                             |¦  «         dS )zRevoke active tokens.T)r]   Úrevoke_tokenr[   rP   )r"   r¨   rH   s      r#   ÚlogoutzAuthService.logout»  s=   € àÔ×'Ò'¨Ñ5Ô5Ð5Øð 	@ØŒO×0Ò0°Ñ?Ô?Ð?Øˆtr%   )NNrY   rZ   )r[   r   r\   r   r]   r   r^   r   r_   r   r`   r   ra   rb   rc   rb   rd   re   rf   rg   r   r   )rm   r'   rn   r   r   r   )r&   r'   rv   r'   r)   r'   rw   r'   rx   r'   rm   r'   r   r   )r&   r'   r¤   r'   r   r   )NNFN)r&   r'   rv   r'   rm   r'   rw   r²   rx   r²   r³   r´   rµ   rb   r   r   )r½   r'   rµ   rÏ   r   r   )
rA   r   rÔ   r'   rÕ   r'   rm   r'   r   r   )rH   r'   r   r   r   )r¨   r'   rH   r²   r   r´   )rQ   rR   rS   rT   ÚreÚcompiler�   r$   r   ÚMATHru   r£   r±   rÎ   rÓ   rÙ   rH   rÞ   rV   r%   r#   rX   rX   Z   s,  € € € € € Ø:Ð:à�"”*ÐPÑQÔQ€Kð *.Ø+/Ø"#Ø*/ðQð Qð Qð Qð Qð2 MXÔL\ð =ð =ð =ð =ð =ð_
ð _
ð _
ð _
ðB"
ð "
ð "
ð "
ðR %)Ø*.Ø!Ø,0ðd
ð d
ð d
ð d
ð d
ðL%
ð %
ð %
ð %
ðN
ð 
ð 
ð 
ð
ð 
ð 
ð 
ð8ð ð ð ð ð ð r%   rX   )#rT   Ú
__future__r   rß   r–   r’   r2   Útypingr   r   r   Úserver.auth.modelsr   r   r	   r
   r   r   r   r   r   Úserver.auth.cryptor   r   Úserver.auth.captchar   r   r   r   Úserver.auth.email_verificationr   Úserver.auth.oauthr   r   rX   rV   r%   r#   ú<module>ré      sš  ððð ð
 #Ð "Ð "Ð "Ð "Ð "Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ð (ð
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ð <Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø YÐ YÐ YÐ YÐ YÐ YÐ YÐ YÐ YÐ YÐ YÐ YØ CÐ CÐ CÐ CÐ CÐ CØ *Ð *Ð *Ð *Ð *Ð *ð96ð 96ð 96ð 96ð 96ñ 96ô 96ð 96ðxfð fð fð fð fñ fô fð fð fð fr%   