U
    
ڲgKB                  
   @   s  d Z ddl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mZ dZ	dZ
ed	Zd
dddddddddg
ZejZejZd$ddZd%ddZd&ddZd'ddZd(ddZde
dfddZdd ZG dd dZG dd dZG dd
 d
ZG d d! d!Zd"d# ZdS ))zFirebase tenant management module.

This module contains functions for creating and configuring authentication tenants within a
Google Cloud Identity Platform (GCIP) instance.
    N)auth)_auth_utils)_http_client)_utilsZ_tenant_mgtd   z^[a-zA-Z][a-zA-Z0-9-]{3,19}$ListTenantsPageTenantTenantIdMismatchErrorTenantNotFoundErrorauth_for_tenantcreate_tenantdelete_tenant
get_tenantlist_tenantsupdate_tenantc                 C   s   t |}|| S )a+  Gets an Auth Client instance scoped to the given tenant ID.

    Args:
        tenant_id: A tenant ID string.
        app: An App instance (optional).

    Returns:
        auth.Client: An ``auth.Client`` object.

    Raises:
        ValueError: If the tenant ID is None, empty or not a string.
    )_get_tenant_mgt_servicer   	tenant_idapptenant_mgt_service r   =/tmp/pip-unpacked-wheel-p0r7i5ii/firebase_admin/tenant_mgt.pyr   9   s    c                 C   s   t |}|| S )a  Gets the tenant corresponding to the given ``tenant_id``.

    Args:
        tenant_id: A tenant ID string.
        app: An App instance (optional).

    Returns:
        Tenant: A tenant object.

    Raises:
        ValueError: If the tenant ID is None, empty or not a string.
        TenantNotFoundError: If no tenant exists by the given ID.
        FirebaseError: If an error occurs while retrieving the tenant.
    )r   r   r   r   r   r   r   J   s    c                 C   s   t |}|j| ||dS )a  Creates a new tenant from the given options.

    Args:
        display_name: Display name string for the new tenant. Must begin with a letter and contain
            only letters, digits and hyphens. Length must be between 4 and 20.
        allow_password_sign_up: A boolean indicating whether to enable or disable the email sign-in
            provider (optional).
        enable_email_link_sign_in: A boolean indicating whether to enable or disable email link
            sign-in (optional). Disabling this makes the password required for email sign-in.
        app: An App instance (optional).

    Returns:
        Tenant: A tenant object.

    Raises:
        ValueError: If any of the given arguments are invalid.
        FirebaseError: If an error occurs while creating the tenant.
    display_nameallow_password_sign_upenable_email_link_sign_in)r   r   )r   r   r   r   r   r   r   r   r   ]   s     c                 C   s   t |}|j| |||dS )a   Updates an existing tenant with the given options.

    Args:
        tenant_id: ID of the tenant to update.
        display_name: Updated display name string for the tenant (optional).
        allow_password_sign_up: A boolean indicating whether to enable or disable the email sign-in
            provider.
        enable_email_link_sign_in: A boolean indicating whether to enable or disable email link
            sign-in. Disabling this makes the password required for email sign-in.
        app: An App instance (optional).

    Returns:
        Tenant: The updated tenant object.

    Raises:
        ValueError: If any of the given arguments are invalid.
        TenantNotFoundError: If no tenant exists by the given ID.
        FirebaseError: If an error occurs while creating the tenant.
    r   )r   r   )r   r   r   r   r   r   r   r   r   r   w   s      c                 C   s   t |}||  dS )aw  Deletes the tenant corresponding to the given ``tenant_id``.

    Args:
        tenant_id: A tenant ID string.
        app: An App instance (optional).

    Raises:
        ValueError: If the tenant ID is None, empty or not a string.
        TenantNotFoundError: If no tenant exists by the given ID.
        FirebaseError: If an error occurs while retrieving the tenant.
    N)r   r   r   r   r   r   r      s    c                    s    t |  fdd}t|| |S )a  Retrieves a page of tenants from a Firebase project.

    The ``page_token`` argument governs the starting point of the page. The ``max_results``
    argument governs the maximum number of tenants that may be included in the returned page.
    This function never returns None. If there are no user accounts in the Firebase project, this
    returns an empty page.

    Args:
        page_token: A non-empty page token string, which indicates the starting point of the page
            (optional). Defaults to ``None``, which will retrieve the first page of users.
        max_results: A positive integer indicating the maximum number of users to include in the
            returned page (optional). Defaults to 100, which is also the maximum number allowed.
        app: An App instance (optional).

    Returns:
        ListTenantsPage: A page of tenants.

    Raises:
        ValueError: If ``max_results`` or ``page_token`` are invalid.
        FirebaseError: If an error occurs while retrieving the user accounts.
    c                    s     | |S N)r   )
page_tokenmax_resultsr   r   r   download   s    zlist_tenants.<locals>.download)r   r   )r   r   r   r    r   r   r   r      s    c                 C   s   t | ttS r   )r   Zget_app_service_TENANT_MGT_ATTRIBUTE_TenantManagementService)r   r   r   r   r      s    r   c                   @   sH   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	dS )r   a  Represents a tenant in a multi-tenant application.

    Multi-tenancy support requires Google Cloud Identity Platform (GCIP). To learn more about
    GCIP including pricing and features, see https://cloud.google.com/identity-platform.

    Before multi-tenancy can be used in a Google Cloud Identity Platform project, tenants must be
    enabled in that project via the Cloud Console UI. A Tenant instance provides information
    such as the display name, tenant identifier and email authentication configuration.
    c                 C   s2   t |tstd|d|kr(td|| _d S )Nz0Invalid data argument in Tenant constructor: {0}namez&Tenant response missing required keys.)
isinstancedict
ValueErrorformat_data)selfdatar   r   r   __init__   s
    
zTenant.__init__c                 C   s   | j d }|dd S )Nr#   /)r(   split)r)   r#   r   r   r   r      s    
zTenant.tenant_idc                 C   s   | j dS )NdisplayNamer(   getr)   r   r   r   r      s    zTenant.display_namec                 C   s   | j ddS )NallowPasswordSignupFr0   r2   r   r   r   r      s    zTenant.allow_password_sign_upc                 C   s   | j ddS )NenableEmailLinkSigninFr0   r2   r   r   r   r      s    z Tenant.enable_email_link_sign_inN)
__name__
__module____qualname____doc__r+   propertyr   r   r   r   r   r   r   r   r      s   



c                   @   sV   e Zd ZdZdZdd Zdd Zdd Zdd
dZdddZ	dd Z
d	efddZd	S )r"   z#Firebase tenant management service.z)https://identitytoolkit.googleapis.com/v2c                 C   sV   |j  }dtj}d| j|j}|| _tj	||d|id| _
i | _t | _d S )NzPython/Admin/{0}z{0}/projects/{1}zX-Client-Version)
credentialbase_urlheaders)r:   get_credentialr'   firebase_admin__version__TENANT_MGT_URLZ
project_idr   r   ZJsonHttpClientclienttenant_clients	threadingRLocklock)r)   r   r:   Zversion_headerr;   r   r   r   r+      s    
  z!_TenantManagementService.__init__c              
   C   sx   t |tr|std|| jL || jkrD| j| W  5 Q R  S tj| j|d}|| j|< |W  5 Q R  S Q R X dS )z;Gets an Auth Client instance scoped to the given tenant ID.=Invalid tenant ID: {0}. Tenant ID must be a non-empty string.)r   N)	r$   strr&   r'   rE   rB   r   ZClientr   )r)   r   rA   r   r   r   r      s    

z(_TenantManagementService.auth_for_tenantc              
   C   sr   t |tr|std|z| jdd|}W n0 tjjk
rd } zt	
|W 5 d}~X Y n
X t|S dS )z9Gets the tenant corresponding to the given ``tenant_id``.rF   r1   /tenants/{0}N)r$   rG   r&   r'   rA   bodyrequests
exceptionsRequestExceptionr   handle_auth_backend_errorr   )r)   r   rI   errorr   r   r   r     s    z#_TenantManagementService.get_tenantNc              
   C   s   dt |i}|dk	r$t|d|d< |dk	r<t|d|d< z| jjdd|d}W n0 tjjk
r } zt|W 5 d}~X Y n
X t	|S dS )z/Creates a new tenant from the given parameters.r/   Nr3   r4   post/tenants)json)
_validate_display_namer   validate_booleanrA   rI   rJ   rK   rL   rM   r   )r)   r   r   r   payloadrI   rN   r   r   r   r     s       z&_TenantManagementService.create_tenantc              
   C   s   t |tr|stdi }|dk	r.t||d< |dk	rFt|d|d< |dk	r^t|d|d< |sjtdd|}dt|}d	|}z| j	j
d
|||d}	W n0 tjjk
r }
 zt|
W 5 d}
~
X Y n
X t|	S dS )z7Updates the specified tenant with the given parameters.z%Tenant ID must be a non-empty string.Nr/   r3   r4   z4At least one parameter must be specified for update.rH   ,zupdateMask={0}patch)rQ   params)r$   rG   r&   rR   r   rS   r'   joinZbuild_update_maskrA   rI   rJ   rK   rL   rM   r   )r)   r   r   r   r   rT   urlZupdate_maskrW   rI   rN   r   r   r   r   %  s2      

z&_TenantManagementService.update_tenantc              
   C   sj   t |tr|std|z| jdd| W n0 tjjk
rd } zt	
|W 5 d}~X Y nX dS )z<Deletes the tenant corresponding to the given ``tenant_id``.rF   deleterH   N)r$   rG   r&   r'   rA   requestrJ   rK   rL   r   rM   )r)   r   rN   r   r   r   r   C  s    z&_TenantManagementService.delete_tenantc              
   C   s   |dk	rt |tr|stdt |ts0td|dk s@|tkrNtdtd|i}|rb||d< z| jjdd	|d
W S  tj	j
k
r } zt|W 5 d}~X Y nX dS )zRetrieves a batch of tenants.Nz&Page token must be a non-empty string.zMax results must be an integer.   zAMax results must be a positive integer less than or equal to {0}.ZpageSizeZ	pageTokenr1   rP   )rW   )r$   rG   r&   int_MAX_LIST_TENANTS_RESULTSr'   rA   rI   rJ   rK   rL   r   rM   )r)   r   r   rT   rN   r   r   r   r   N  s$    
z%_TenantManagementService.list_tenants)NN)NNN)r5   r6   r7   r8   r@   r+   r   r   r   r   r   r^   r   r   r   r   r   r"      s   
   
    
r"   c                   @   sL   e Zd ZdZdd Zedd Zedd Zedd	 Zd
d Z	dd Z
dS )r   aH  Represents a page of tenants fetched from a Firebase project.

    Provides methods for traversing tenants included in this page, as well as retrieving
    subsequent pages of tenants. The iterator returned by ``iterate_all()`` can be used to iterate
    through all tenants in the Firebase project starting from this page.
    c                 C   s   || _ || _|||| _d S r   )	_download_max_results_current)r)   r    r   r   r   r   r   r+   k  s    zListTenantsPage.__init__c                 C   s   dd | j dg D S )zBA list of ``ExportedUserRecord`` instances available in this page.c                 S   s   g | ]}t |qS r   )r   ).0r*   r   r   r   
<listcomp>s  s     z+ListTenantsPage.tenants.<locals>.<listcomp>tenantsra   r1   r2   r   r   r   rd   p  s    zListTenantsPage.tenantsc                 C   s   | j ddS )zKPage token string for the next page (empty string indicates no more pages).ZnextPageToken re   r2   r   r   r   next_page_tokenu  s    zListTenantsPage.next_page_tokenc                 C   s
   t | jS )z6A boolean indicating whether more pages are available.)boolrg   r2   r   r   r   has_next_pagez  s    zListTenantsPage.has_next_pagec                 C   s   | j rt| j| j| jS dS )zRetrieves the next page of tenants, if available.

        Returns:
            ListTenantsPage: Next page of tenants, or None if this is the last page.
        N)ri   r   r_   rg   r`   r2   r   r   r   get_next_page  s    zListTenantsPage.get_next_pagec                 C   s   t | S )aG  Retrieves an iterator for tenants.

        Returned iterator will iterate through all the tenants in the Firebase project
        starting from this page. The iterator will never buffer more than one page of tenants
        in memory at a time.

        Returns:
            iterator: An iterator of Tenant instances.
        )_TenantIteratorr2   r   r   r   iterate_all  s    
zListTenantsPage.iterate_allN)r5   r6   r7   r8   r+   r9   rd   rg   ri   rj   rl   r   r   r   r   r   c  s   



c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )rk   a  An iterator that allows iterating over tenants.

    This implementation loads a page of tenants 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.r   )r&   _current_page_index)r)   Zcurrent_pager   r   r   r+     s    z_TenantIterator.__init__c                 C   sf   | j t| jjkr,| jjr,| j | _d| _ | j t| jjk r^| jj| j  }|  j d7  _ |S td S )Nr   r\   )rn   lenrm   rd   ri   rj   StopIteration)r)   resultr   r   r   next  s    z_TenantIterator.nextc                 C   s   |   S r   )rr   r2   r   r   r   __next__  s    z_TenantIterator.__next__c                 C   s   | S r   r   r2   r   r   r   __iter__  s    z_TenantIterator.__iter__N)r5   r6   r7   r8   r+   rr   rs   rt   r   r   r   r   rk     s
   rk   c                 C   s(   t | tstdt| s$td| S )NzInvalid type for displayNamezjdisplayName must start with a letter and only consist of letters, digits and hyphens with 4-20 characters.)r$   rG   r&   _DISPLAY_NAME_PATTERNsearch)r   r   r   r   rR     s    

rR   )N)N)NNN)NNNN)N)r8   rerC   rJ   r>   r   r   r   r   r!   r^   compileru   __all__r	   r
   r   r   r   r   r   r   r   r   r"   r   rk   rR   r   r   r   r   <module>   sV   


     
      

%{3 