U
    
ڲgH                     @   s  d 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Z	dZ
edd	d
dddddddddddddgZedddgZG dd dZdd Zdd  Zdjd"d#Zdkd$d%Zdld&d'Zdmd(d)Zdnd*d+Zdod,d-Zdpd/d0Zdqd1d2Zdrd3d4Zdsd5d6Zdtd7d8Zd9d: Zd;d< Zdud=d>Zd?d@ ZdvdAdBZ dCdD Z!G dEdF dFej"Z#G dGdH dHej"Z$G dIdJ dJej%Z&G dKdL dLej'Z(G dMdN dNej'Z)G dOdP dPej"Z*G dQdR dRej+Z,G dSdT dTej-Z.G dUdV dVej-Z/G dWdX dXej-Z0G dYdZ dZej'Z1G d[d\ d\ej-Z2G d]d^ d^ej'Z3G d_d` d`ej4Z5G dadb dbej4Z6e2e$e#e$e/e&e(e)e*e0e.e5e6dcZ7ddde Z8dfdg Z9dhdi Z:dS )wzFirebase auth utils.    N)parse)
exceptions)_utilsZFIREBASE_AUTH_EMULATOR_HOSTi  ZacrZamrZat_hashZaudZ	auth_timeZazpZcnfZc_hashexpZiatZissZjtiZnbfnoncesubZfirebaseZVERIFY_EMAILZEMAIL_SIGNINZPASSWORD_RESETc                   @   s4   e Zd ZdZdd Zdd Zdd Zedd	 Zd
S )PageIteratora(  An iterator that allows iterating over a sequence of items, one at a time.

    This implementation loads a page of items into memory, and iterates on them. When the whole
    page has been traversed, it loads another page. This class never keeps more than one page
    of entries in memory.
    c                 C   s   |st d|| _d | _d S )NzCurrent page must not be None.)
ValueError_current_page_iter)selfZcurrent_page r   >/tmp/pip-unpacked-wheel-p0r7i5ii/firebase_admin/_auth_utils.py__init__+   s    zPageIterator.__init__c                 C   sl   | j d krt| j| _ zt| j W S  tk
rf   | jjr`| j | _t| j| _ t| j  Y S  Y nX d S N)r   iteritemsnextStopIterationr
   Zhas_next_pageZget_next_pager   r   r   r   __next__2   s    
zPageIterator.__next__c                 C   s   | S r   r   r   r   r   r   __iter__A   s    zPageIterator.__iter__c                 C   s   t d S r   )NotImplementedErrorr   r   r   r   r   D   s    zPageIterator.itemsN)	__name__
__module____qualname____doc__r   r   r   propertyr   r   r   r   r   r   #   s   r   c                  C   s,   t td} | r(d| kr(tdt| | S )N z//z6Invalid {0}: "{1}". It must follow format "host:port".)osgetenvEMULATOR_HOST_ENV_VARr	   format)Zemulator_hostr   r   r   get_emulator_hostI   s     r#   c                   C   s
   t  dkS )Nr   )r#   r   r   r   r   is_emulatedR   s    r$   Fc                 C   s<   | d kr|sd S t | tr*| r*t| dkr8td| | S )N   zXInvalid uid: "{0}". The uid must be a non-empty string with no more than 128 characters.)
isinstancestrlenr	   r"   )uidrequiredr   r   r   validate_uidV   s    r+   c                 C   sd   | d kr|sd S t | tr| s,td| | d}t|dksR|d rR|d s`td| | S )Nz7Invalid email: "{0}". Email must be a non-empty string.@   r      z&Malformed email address string: "{0}".)r&   r'   r	   r"   splitr(   )emailr*   partsr   r   r   validate_email_   s    
r2   c                 C   sT   | dkr|sdS t | tr| s,td| | drBtd| sPtd| | S )a	  Validates the specified phone number.

    Phone number vlidation is very lax here. Backend will enforce E.164 spec compliance, and
    normalize accordingly. Here we check if the number starts with + sign, and contains at
    least one alphanumeric character.
    NzEInvalid phone number: "{0}". Phone number must be a non-empty string.+z[a-zA-Z0-9]zVInvalid phone number: "{0}". Phone number must be a valid, E.164 compliant identifier.)r&   r'   r	   r"   
startswithresearch)Zphoner*   r   r   r   validate_phonej   s    r7   c                 C   s2   | d kr|sd S t | tr&t| dk r.td| S )N   zNInvalid password string. Password must be a string at least 6 characters long.)r&   r'   r(   r	   )passwordr*   r   r   r   validate_password{   s    r:   c                 C   s0   | d kr|sd S t | tr| s,td|| S )Nz&{0} must be a non-empty byte sequence.)r&   bytesr	   r"   )valuelabelr*   r   r   r   validate_bytes   s
    r>   c                 C   s0   | d kr|sd S t | tr| s,td| | S )NzEInvalid display name: "{0}". Display name must be a non-empty string.r&   r'   r	   r"   )Zdisplay_namer*   r   r   r   validate_display_name   s    r@   Tc                 C   s0   | d kr|sd S t | tr| s,td| | S )NzCInvalid provider ID: "{0}". Provider ID must be a non-empty string.r?   )provider_idr*   r   r   r   validate_provider_id   s    rB   c                 C   s0   | d kr|sd S t | tr| s,td| | S )NzEInvalid provider UID: "{0}". Provider UID must be a non-empty string.r?   )Zprovider_uidr*   r   r   r   validate_provider_uid   s    rC   c                 C   sx   | dkr|sdS t | tr| s,td| z$t| }|jsLtd| | W S  tk
rr   td| Y nX dS )z*Parses and validates the given URL string.Nz?Invalid photo URL: "{0}". Photo URL must be a non-empty string.zMalformed photo URL: "{0}".)r&   r'   r	   r"   r   urlparsenetloc	Exception)Z	photo_urlr*   parsedr   r   r   validate_photo_url   s    
rH   c                 C   s   | dkr|sdS t | tr"tdzt| }W n" tk
rP   td| Y n2X || krhtd||dkr~td||S dS )zJValidates the given timestamp value. Timestamps must be positive integers.Nz%Boolean value specified as timestamp.z&Invalid type for timestamp value: {0}./{0} must be a numeric value and a whole number.r   z*{0} timestamp must be a positive interger.)r&   boolr	   int	TypeErrorr"   )	timestampr=   r*   Ztimestamp_intr   r   r   validate_timestamp   s    
rN   c                 C   s   | dkst | tr td| zt| }W n" tk
rN   td| Y n\X || krftd||dk	r||k rtd|||dk	r||krtd|||S dS )au  Validates that the given value represents an integer.

    There are several ways to represent an integer in Python (e.g. 2, 2L, 2.0). This method allows
    for all such representations except for booleans. Booleans also behave like integers, but
    always translate to 1 and 0. Passing a boolean to an API that expects integers is most likely
    a developer error.
    Nz$Invalid type for integer value: {0}.rI   z!{0} must not be smaller than {1}.z {0} must not be larger than {1}.)r&   rJ   r	   r"   rK   rL   )r<   r=   lowhighZval_intr   r   r   validate_int   s    rQ   c                 C   s   t | tstd|| | S )z+Validates that the given value is a string.Invalid type for {0}: {1}.r?   r<   r=   r   r   r   validate_string   s    
rT   c                 C   s   t | tstd|| | S )z,Validates that the given value is a boolean.rR   )r&   rJ   r	   r"   rS   r   r   r   validate_boolean   s    
rU   c                 C   s   | dkr|sdS t | }t|tkr2tdtzt|}W n tk
r\   tdY nX t|t	sptdt
t| }t|dkrdt|}td|t|dkrtd| |S )	zValidates the specified custom claims.

    Custom claims must be specified as a JSON string. The string must not exceed 1000
    characters, and the parsed JSON payload must not contain reserved JWT claims.
    Nz5Custom claims payload must not exceed {0} characters.z-Failed to parse custom claims string as JSON.z1Custom claims must be parseable as a JSON object.r.   , z/Claims "{0}" are reserved, and must not be set.z-Claim "{0}" is reserved, and must not be set.)r'   r(   MAX_CLAIMS_PAYLOAD_SIZEr	   r"   jsonloadsrF   r&   dictRESERVED_CLAIMSintersectionsetkeysjoinsortedpop)Zcustom_claimsr*   Z
claims_strrG   Zinvalid_claimsZjoinedr   r   r   validate_custom_claims   s0    
rb   c                 C   s"   | t krtd| dt | S )NzOInvalid action type provided action_type: {0}.             Valid values are {1}rV   )VALID_EMAIL_ACTION_TYPESr	   r"   r_   )Zaction_typer   r   r   validate_action_type  s     rd   c                 C   s,   | s|rt dg S | D ]}t|d q| S )Nz5Invalid provider IDs. Provider ids should be providedT)r	   rB   )Zprovider_idsr*   rA   r   r   r   validate_provider_ids  s    re   c                 C   sX   g }|   D ]B\}}t|trDt|}|D ]}|d|| q*q|| qt|S )z6Creates an update mask list from the given dictionary.z{0}.{1})r   r&   rZ   build_update_maskappendr"   r`   )paramsmaskkeyr<   Z
child_maskchildr   r   r   rf     s    
rf   c                   @   s   e Zd ZdZdZdd ZdS )UidAlreadyExistsErrorz.The user with the provided uid already exists.z-The user with the provided uid already existsc                 C   s   t j| ||| d S r   r   AlreadyExistsErrorr   r   messagecausehttp_responser   r   r   r   )  s    zUidAlreadyExistsError.__init__Nr   r   r   r   default_messager   r   r   r   r   rl   $  s   rl   c                   @   s   e Zd ZdZdZdd ZdS )EmailAlreadyExistsErrorz0The user with the provided email already exists.z/The user with the provided email already existsc                 C   s   t j| ||| d S r   rm   ro   r   r   r   r   2  s    z EmailAlreadyExistsError.__init__Nrs   r   r   r   r   ru   -  s   ru   c                   @   s   e Zd ZdZdZdd ZdS )InsufficientPermissionErrorzEThe credential used to initialize the SDK lacks required permissions.zThe credential used to initialize the SDK has insufficient permissions to perform the requested operation. See https://firebase.google.com/docs/admin/setup for details on how to initialize the Admin SDK with appropriate permissionsc                 C   s   t j| ||| d S r   )r   PermissionDeniedErrorr   ro   r   r   r   r   >  s    z$InsufficientPermissionError.__init__Nrs   r   r   r   r   rv   6  s   rv   c                   @   s   e Zd ZdZdZdd ZdS )InvalidDynamicLinkDomainErrorz<Dynamic link domain in ActionCodeSettings is not authorized.zEDynamic link domain specified in ActionCodeSettings is not authorizedc                 C   s   t j| ||| d S r   r   InvalidArgumentErrorr   ro   r   r   r   r   G  s    z&InvalidDynamicLinkDomainError.__init__Nrs   r   r   r   r   rx   B  s   rx   c                   @   s   e Zd ZdZdZdddZdS )InvalidIdTokenErrorz7The provided ID token is not a valid Firebase ID token.z The provided ID token is invalidNc                 C   s   t j| ||| d S r   ry   ro   r   r   r   r   P  s    zInvalidIdTokenError.__init__)NNrs   r   r   r   r   r{   K  s   r{   c                   @   s   e Zd ZdZdZdd ZdS )PhoneNumberAlreadyExistsErrorz7The user with the provided phone number already exists.z6The user with the provided phone number already existsc                 C   s   t j| ||| d S r   rm   ro   r   r   r   r   Y  s    z&PhoneNumberAlreadyExistsError.__init__Nrs   r   r   r   r   r|   T  s   r|   c                   @   s   e Zd ZdZdddZdS )UnexpectedResponseErrorzCBackend service responded with an unexpected or malformed response.Nc                 C   s   t j| ||| d S r   )r   UnknownErrorr   ro   r   r   r   r   `  s    z UnexpectedResponseError.__init__)NNr   r   r   r   r   r   r   r   r   r}   ]  s   r}   c                   @   s   e Zd ZdZdZdddZdS )UserNotFoundErrorz2No user record found for the specified identifier.z-No user record found for the given identifierNc                 C   s   t j| ||| d S r   r   NotFoundErrorr   ro   r   r   r   r   i  s    zUserNotFoundError.__init__)NNrs   r   r   r   r   r   d  s   r   c                   @   s   e Zd ZdZdZdddZdS )EmailNotFoundErrorz-No user record found for the specified email.z(No user record found for the given emailNc                 C   s   t j| ||| d S r   r   ro   r   r   r   r   r  s    zEmailNotFoundError.__init__)NNrs   r   r   r   r   r   m  s   r   c                   @   s   e Zd ZdZdZdddZdS )TenantNotFoundErrorz-No tenant found for the specified identifier.z(No tenant found for the given identifierNc                 C   s   t j| ||| d S r   r   ro   r   r   r   r   {  s    zTenantNotFoundError.__init__)NNrs   r   r   r   r   r   v  s   r   c                   @   s   e Zd ZdZdd ZdS )TenantIdMismatchErrorz4Missing or invalid tenant ID field in the given JWT.c                 C   s   t j| | d S r   ry   )r   rp   r   r   r   r     s    zTenantIdMismatchError.__init__Nr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdZdddZdS )ConfigurationNotFoundErrorz4No auth provider found for the specified identifier.z/No auth provider found for the given identifierNc                 C   s   t j| ||| d S r   r   ro   r   r   r   r     s    z#ConfigurationNotFoundError.__init__)NNrs   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdZdddZdS )UserDisabledErrorz8An operation failed due to a user record being disabled.zThe user record is disabledNc                 C   s   t j| ||| d S r   ry   ro   r   r   r   r     s    zUserDisabledError.__init__)NNrs   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdddZdS )TooManyAttemptsTryLaterErrorz*Rate limited because of too many attempts.Nc                 C   s   t j| ||| d S r   r   ResourceExhaustedErrorr   ro   r   r   r   r     s    z%TooManyAttemptsTryLaterError.__init__)NNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdddZdS )ResetPasswordExceedLimitErrorz,Reset password emails exceeded their limits.Nc                 C   s   t j| ||| d S r   r   ro   r   r   r   r     s    z&ResetPasswordExceedLimitError.__init__)NNr   r   r   r   r   r     s   r   )ZCONFIGURATION_NOT_FOUNDZDUPLICATE_EMAILZDUPLICATE_LOCAL_IDZEMAIL_EXISTSZEMAIL_NOT_FOUNDZINSUFFICIENT_PERMISSIONZINVALID_DYNAMIC_LINK_DOMAINZINVALID_ID_TOKENZPHONE_NUMBER_EXISTSZTENANT_NOT_FOUNDZUSER_NOT_FOUNDZTOO_MANY_ATTEMPTS_TRY_LATERZRESET_PASSWORD_EXCEED_LIMITc                 C   s~   | j dkrt| S t| j \}}|sFd| j j }tj| |dS t|}t	|||}|sntj| |dS ||| | j dS )zWConverts a requests error received from the Firebase Auth service into a FirebaseError.NzUnexpected error response: {0})rp   )rq   rr   )
responser   Zhandle_requests_error_parse_error_bodyr"   contentdecode_CODE_TO_EXC_TYPEget_build_error_message)errorcodecustom_messagemsgexc_typer   r   r   handle_auth_backend_error  s    


r   c                 C   s   i }z"|   }t|tr$|di }W n tk
r:   Y nX t|trP|dnd}d}|r|d}|dkr||d d  }|d| }||fS )zGParses the given error response to extract Auth error code and message.r   rp   N:r.   )rX   r&   rZ   r   r	   findstrip)r   Z
error_dictZparsed_bodyr   r   	separatorr   r   r   r     s    

r   c                 C   s8   |rt |dr|jnd}|r&d|nd}d|| |S )Nrt   z Error while calling Auth servicez {0}r   z{0} ({1}).{2})hasattrrt   r"   )r   r   r   rt   extr   r   r   r     s    r   )F)F)F)F)F)F)T)T)F)F)NN)F)F);r   rX   r   r5   urllibr   Zfirebase_adminr   r   r!   rW   r]   r[   rc   r   r#   r$   r+   r2   r7   r:   r>   r@   rB   rC   rH   rN   rQ   rT   rU   rb   rd   re   rf   rn   rl   ru   rw   rv   rz   rx   r{   r|   r~   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s                 &	
	




	
	
	




											