
    3fi'                        U d dl Z d dlZd dlZd dlmZmZmZmZmZ d dl	m
Z
mZ d dlmZmZ d dlmZmZ d dl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 m!Z! ddl"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)  ejT                  e+      Z,dZ-e.e/d<   dZ0e.e/d<   dZ1dZ2e3e/d<   i ddgddgddgddgddgddgd d!dgd"d#dgd$d%gd&d'gd(d)gd*d+gd,d-gd.d/gd0d1gd2d3gd4d5gd6gd7gd8gd9gdgd:gd;gd<gd=Z4e5e.e6e.   f   e/d><   eeef   Z7 G d? d@e      Z8 G dA dB      Z9 G dC dDe9      Z: G dE dFe9      Z; G dG dH      Z<	 	 dOdIe.dJe.dKee.   dLee9   dMe=f
dNZ>y)P    N)CallableDictListOptionalUnion)parse_qsurlparse)ConfidentialClientApplicationPublicClientApplication)ResponseSession)HTTPAdapter)ConnectionError	HTTPError
ProxyErrorRequestExceptionSSLErrorTimeout)Retry)get_localzone)ZoneInfoZoneInfoNotFoundError   )ME_RESOURCEBaseTokenBackendFileSystemTokenBackendget_windows_tzto_camel_caseto_pascal_caseto_snake_casev1.0GRAPH_API_VERSION<https://login.microsoftonline.com/common/oauth2/nativeclientOAUTH_REDIRECT_URL)i    i  i  i  g      ?RETRIES_BACKOFF_FACTORbasicz	User.Readmailboxz	Mail.Readmailbox_sharedzMail.Read.Sharedmailbox_settingszMailboxSettings.ReadWritemessage_sendz	Mail.Sendmessage_send_sharedzMail.Send.Sharedmessage_allzMail.ReadWritemessage_all_sharedzMail.ReadWrite.Sharedaddress_bookzContacts.Readaddress_book_sharedzContacts.Read.Sharedaddress_book_allzContacts.ReadWriteaddress_book_all_sharedzContacts.ReadWrite.SharedcalendarzCalendars.Readcalendar_sharedzCalendars.Read.Sharedcalendar_allzCalendars.ReadWritecalendar_shared_allzCalendars.ReadWrite.ShareduserszUser.ReadBasic.AllzFiles.Read.AllzFiles.ReadWrite.AllzSites.Read.AllzSites.ReadWrite.Allz
Tasks.ReadzTasks.ReadWritezPresence.Read)onedriveonedrive_all
sharepointsharepoint_allsettings_alltasks	tasks_allpresenceDEFAULT_SCOPESc                       e Zd Zy)TokenExpiredErrorN)__name__
__module____qualname__     M/var/www/auto_recruiter/arenv/lib/python3.12/site-packages/O365/connection.pyrB   rB   Q   s    rG   rB   c                      e Zd ZU dZdZeed<   dZeed<   i Ze	ee
e   f   ed<   dddddddd	ee   d
ee   dee   dee   dee   deee   ee   f   fdZedefd       Zej$                  deeef   ddfd       Zdeeef   ddfdZdedee   fdZdedefdZededefd       Zdeee
eef      de
fdZdedefdZy)ProtocolzBase class for all protocolsnot_defined_protocol_url _oauth_scope_prefix_oauth_scopesN)protocol_urlapi_versiondefault_resourcecasing_functionprotocol_scope_prefixtimezonerP   rQ   rR   rS   rT   rU   c                6   ||t        d      |xs | j                  | _        |xs d| _        || _        | | d| _        |xs t        | _        |dnd| _        |xs t        | _
        i | _        d| _        d| _        |r|| _        yt               | _        y)a  Create a new protocol object

        :param protocol_url: the base url used to communicate with the
         server
        :param api_version: the api version
        :param default_resource: the default resource to use when there is
         nothing explicitly specified during the requests
        :param casing_function: the casing transform function to be
         used on api keywords (camelcase / pascalcase)
        :param protocol_scope_prefix: prefix url for scopes
        :param timezone: preferred timezone, if not provided will default
         to the system timezone or fallback to UTC
        :raises ValueError: if protocol_url or api_version are not supplied
        Nz6Must provide valid protocol_url and api_version valuesrM   /TFr%   )
ValueErrorrL   rP   rT   rQ   service_urlr   rR   use_default_casingr   rS   keyword_data_storemax_top_value	_timezonerU   r   )selfrP   rQ   rR   rS   rT   rU   kwargss           rH   __init__zProtocol.__init__]   s    2 ;#6UVV!-!C1C1C*?*E2" +#/.Q ?%5%D0?0GU)8)IM )+ #& .2$DM '4oDMrG   returnc                     | j                   S N)r]   r^   s    rH   rU   zProtocol.timezone   s    ~~rG   c                 &    | j                  |       y rc   )_update_timezone)r^   rU   s     rH   rU   zProtocol.timezone   s    h'rG   c                    t        |t              r	 t        |      }nt        |t              st        d      t        j                  d| d       || _        y# t        $ r }t        j                  d| d       |d}~ww xY w)zaSets the timezone. This is not done in the setter as you can't call super from a overriden setterz	Timezone z could not be found.NzLThe timezone parameter must be either a string or a valid ZoneInfo instance.zTimezone set to: .)	
isinstancestrr   r   logerrorrX   debugr]   )r^   rU   es      rH   rf   zProtocol._update_timezone   s    h$#H-
 h1 b  			%hZq12! ) 		IhZ/CDEs   A 	B#A>>Bkeywordc                 :    | j                   j                  |d      S )zReturns the data set to the key in the internal data-key dict

        :param keyword: key to get value for
        :return: value of the keyword
        N)r[   get)r^   ro   s     rH   get_service_keywordzProtocol.get_service_keyword   s     &&**7D99rG   keyc                 @    | j                   r|S | j                  |      S )ah  Returns a key converted with this protocol casing method

        Converts case to send/read from the cloud

        When using Microsoft Graph API, the keywords of the API use
        lowerCamelCase Casing

        Default case in this API is lowerCamelCase

        :param  key: a dictionary key to convert
        :return: key after case conversion
        )rZ   rS   )r^   rs   s     rH   convert_casezProtocol.convert_case   s"     --sL43G3G3LLrG   c                     t        |       S )zConverts key to snake_case

        :param key: key to convert into snake_case
        :return: key after case conversion
        )r    )rs   s    rH   to_api_casezProtocol.to_api_case   s     S!!rG   user_provided_scopesc                 h   || j                   D cg c]  }| }}nt        |t              r|g}t        |t        t        f      st        d      t               }|D ]D  }| j                   j                  ||g      D ]"  }|j                  | j                  |             $ F t        |      S c c}w )a?  Returns a list of scopes needed for each of the
        scope_helpers provided, by adding the prefix to them if required

        :param user_provided_scopes: a list of scopes or scope helpers
        :return: scopes with url prefix added
        :raises ValueError: if unexpected datatype of scopes are passed
        z;'user_provided_scopes' must be a list or a tuple of strings)
rO   ri   rj   listtuplerX   setrq   addprefix_scope)r^   rx   app_partscopesscopes        rH   get_scopes_forzProtocol.get_scopes_for   s      '=A=O=O#PH#P #P,c2$8#9 .u>M  , 	5H++//8*E 5

4,,U345	5 F| $Qs   	B/r   c                 t    | j                   r+|j                  | j                         s| j                    | S |S )z-Inserts the protocol scope prefix if required)rT   
startswith)r^   r   s     rH   r~   zProtocol.prefix_scope   s:    %%##D$>$>?445eW==rG   )rC   rD   rE   __doc__rL   rj   __annotations__rN   rO   dictrz   r   r   r   r   r`   propertyrU   setterrf   rr   ru   staticmethodrw   r{   r   r~   rF   rG   rH   rJ   rJ   U   s   & 'M3&!!*,M4T#Y',
 '+%)*..2/3=A;6 sm;6 c]	;6
 #3-;6 "(+;6  (};6 x'99:;6z (   __(sH}!5 ($ ( ("sH})= "$ "":3 :8C= :M M M " " " "$,U4e3C-D$E	8# # rG   rJ   c                        e Zd ZdZdZdZeZd
dede	e   f fdZ
ej                  j                  deeef   ddf fd	       Z xZS )MSGraphProtocolzvA Microsoft Graph Protocol Implementation
    https://docs.microsoft.com/en-us/outlook/rest/compare-graph-outlook
    zhttps://graph.microsoft.com/NrQ   rR   c           	      2   t        |   d| j                  ||t        | j                  d| d| j
                  d<   d| j
                  d<   d| j
                  d<   d| j
                  d	<   d
t        | j                         d| j
                  d<   d| _        y)ah  Create a new Microsoft Graph protocol object

        _protocol_url = 'https://graph.microsoft.com/'

        _oauth_scope_prefix = 'https://graph.microsoft.com/'

        :param str api_version: api version to use
        :param str default_resource: the default resource to use when there is
         nothing explicitly specified during the requests
        rP   rQ   rR   rS   rT   microsoft.graph.messagemessage_typemicrosoft.graph.eventMessageevent_message_type#microsoft.graph.fileAttachmentfile_attachment_type#microsoft.graph.itemAttachmentitem_attachment_typeoutlook.timezone=""prefer_timezone_header  NrF   )	superr`   rL   r   rN   r[   r   r]   r\   )r^   rQ   rR   r_   	__class__s       rH   r`   zMSGraphProtocol.__init__   s     	 	
++#-)"&":":	
 	
 3L/8V 45- 	 67 . 	 67 !!? @B 	 89 !rG   rU   ra   c                 p    t         |   |       dt        | j                         d| j                  d<   y Nr   r   r   r   rf   r   r]   r[   r^   rU   r   s     rH   rU   zMSGraphProtocol.timezone"  7     * !? @B 	 89rG   )r!   N)rC   rD   rE   r   rL   rN   r@   rO   rj   r   r`   rJ   rU   r   r   r   __classcell__r   s   @rH   r   r      si     3M8"M !C  !HSM  !D 
sH}!5 
$ 
 
rG   r   c                        e Zd ZdZdZdZeZdZ	 	 dde	de
e	   de
e	   f fdZej                  j                  dee	ef   d	df fd
       Z xZS )MSBusinessCentral365ProtocolzA Microsoft Business Central Protocol Implementation
    https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v1.0/
    z)https://api.businesscentral.dynamics.com/NrQ   rR   environmentc           	         |rd}d|z   }nd}d}| j                    d| | d| _         t        |   d| j                   ||t        | j                  d| d| j
                  d	<   d
| j
                  d<   d| j
                  d<   d| j
                  d<   dt        | j                         d| j
                  d<   d| _        y)a  Create a new Microsoft Graph protocol object

        _protocol_url = 'https://api.businesscentral.dynamics.com/'

        _oauth_scope_prefix = 'https://api.businesscentral.dynamics.com/'

        :param str api_version: api version to use
        :param str default_resource: the default resource to use when there is
         nothing explicitly specified during the requests
        z2.0rW   z1.0rM   vz/api/r   r   r   r   r   r   r   r   r   r   r   r   r   NrF   )	rL   r   r`   r   _protocol_scope_prefixr[   r   rU   r\   )r^   rQ   rR   r   r_   _version_environmentr   s          rH   r`   z%MSBusinessCentral365Protocol.__init__4  s     H,LHL $ 2 231XJ|nER 	
++#-)"&"="=	
 	
 3L/8V 45- 	 67 . 	 67 !!> ?qA 	 89 !rG   rU   ra   c                 p    t         |   |       dt        | j                         d| j                  d<   y r   r   r   s     rH   rU   z%MSBusinessCentral365Protocol.timezoneb  r   rG   )r!   NN)rC   rD   rE   r   rL   rN   r@   rO   r   rj   r   r`   rJ   rU   r   r   r   r   r   s   @rH   r   r   *  s     @ME"MH KO)-,!,!:B3-,!!#,!\ 
sH}!5 
$ 
 
rG   r   c            '       4   e Zd ZdZg dZdddddddddd	d
dddddddddedee   dee   dee   dee   de	dede	dedee
   dededee   dee   dee   deej                     de	dede	f&dZed efd!       Zdd"d#ee   d dfd$Zed ee   fd%       Zej&                  dee   d dfd&       Zdedededede	d dfd'Zed efd(       Z	 dId)ee   d*ee   d eeef   fd+Zdddd,d-ee   d.ee   d)eee      d/e	d e	f
d0Zd e	fd1ZdJd2e	d efd3Zd efd4ZdId5ee   d dfd6Zd e	fd7Zd e	fd8Z dKd9Z!	 dJd:ed;ed<ed=e	d e"f
d>Z#d;ed<ed e"fd?Z$d;ed<ed e"fd@Z%dId;edAee   d e"fdBZ&dId;edCee   d e"fdDZ'dId;edCee   d e"fdEZ(dId;edCee   d e"fdFZ)d;ed e"fdGZ*dKdHZ+y)L
ConnectionzCHandles all communication (requests) between the app and the server)rq   postputpatchdeleteNi  F   T   commonauthorization)proxy_server
proxy_portproxy_usernameproxy_passwordproxy_http_onlyrequests_delayraise_http_errorsrequest_retriestoken_backend	tenant_idauth_flow_typeusernamepasswordtimeoutjson_encoder
verify_ssldefault_headersstore_token_after_refreshcredentialsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   c                   |dv rAt        |t              r|f}t        |t              rt        |      dk7  s|d   s>t	        d      t        |t              rt        |      dk7  s
|d   s|d   st	        d      || _        |dv r|dk(  rt	        d	      || _        || _        |xs
 t               | _	        || _
        |
xs t        di |}
t        |
t              st	        d
      |
| _        d| _        || _        d| _        || _        i | _        | j'                  |||||       |xs d| _        d| _        || _        |	| _        || _        || _        || _        d| _        d| _        d| | _        d| _        y)aD  Creates an API connection object

        :param tuple credentials: a tuple of (client_id, client_secret)
         Generate client_id and client_secret in https://entra.microsoft.com/
        :param str proxy_server: the proxy server
        :param int proxy_port: the proxy port, defaults to 8080
        :param str proxy_username: the proxy username
        :param str proxy_password: the proxy password
        :param int requests_delay: number of milliseconds to wait between api
         calls.
         The Api will respond with 429 Too many requests if more than
         17 requests are made per second. Defaults to 200 milliseconds
         just in case more than 1 connection is making requests
         across multiple processes.
        :param bool raise_http_errors: If True Http 4xx and 5xx status codes
         will raise as exceptions
        :param int request_retries: number of retries done when the server
         responds with 5xx error codes.
        :param BaseTokenBackend token_backend: the token backend used to get
         and store tokens
        :param str tenant_id: use this specific tenant id, defaults to common
        :param dict default_headers: allow to force headers in api call
         (ex: default_headers={"Prefer": 'IdType="ImmutableId"'}) to get constant id for objects.
        :param str auth_flow_type: the auth method flow style used: Options:

            - 'authorization': 2-step web style grant flow using an authentication url
            - 'public': 2-step web style grant flow using an authentication url for public apps where
                client secret cannot be secured
            - 'credentials': also called client credentials grant flow using only the client id and secret.
                The secret can be certificate based authentication
            - 'password': using the username and password. Not recommended

        :param str username: The username the credentials will be taken from in the token backend.
            If None, the username will be the first one found in the token backend.
            The user's email address to provide in case of auth_flow_type == 'password'
        :param str password: The user's password to provide in case of auth_flow_type == 'password'
        :param float or tuple timeout: How long to wait for the server to send
            data before giving up, as a float, or a tuple (connect timeout, read timeout)
        :param JSONEncoder json_encoder: The JSONEncoder to use during the JSON serialization on the request.
        :param bool verify_ssl: set the verify flag on the requests library
        :param bool store_token_after_refresh: if after a token refresh the token backend should call save_token
        :param dict kwargs: any extra params passed to Connection
        :raises ValueError: if credentials is not tuple of (client_id, client_secret)

        publicr   r   r   z>Provide client id only for public or password flow credentials   zProvide valid auth credentials)r   r   r   zQWhen using the "credentials" or "password" auth_flow, the "tenant_id" must be setzE"token_backend" must be an instance of a subclass of BaseTokenBackendNz"https://login.microsoftonline.com/r#   rF   )ri   rj   r{   lenrX   _auth_flow_typeauthr   r   r   r   r   r   r   sessionr   	_usernamer   proxy	set_proxyr   _previous_request_atr   r   r   r   r   naive_session_msal_client_msal_authorityoauth_redirect_url)r^   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r_   s                        rH   r`   zConnection.__init__o  s   L  
 
 +s+*n{E2{#q(#A T 
 {E2{#q(#A{1~ !ABB  	 88Y(=Rc 
 '	' &5%>/H&%I)?)I&)I-)9:W  0=*. (0(,'/ 
*nno	

 $2#6Q59!'8$3# *8D  	
  	 'I$T K 	rG   ra   c                     | j                   S rc   )r   rd   s    rH   r   zConnection.auth_flow_type  s    ###rG   home_account_idr   c                n    | j                   j                  |      }|r|j                  d      | _        yy)z
        If token data is present, this will try to set the username. If home_account_id is not provided this will try
        to set the username from the first account found on the token_backend.
        r   r   N)r   get_accountrq   r   )r^   r   account_infos      rH    _set_username_from_token_backendz+Connection._set_username_from_token_backend  s7     ))55o5V(,,Z8DM rG   c                 R    | j                   s| j                          | j                   S )z
        Returns the username in use
        If username is not set this will try to set the username to the first account found
        from the token_backend.
        )r   r   rd   s    rH   r   zConnection.username   s!     ~~113~~rG   c                 ^   | j                   |k(  ry t        j                  d| j                    d|        || _         | j                  e| j                  j                  |      }|| j                  |d          y d| j                  j                  v r| j                  j                  d= y y y )NzCurrent username changed from z to r   secretaccess_tokenAuthorization)r   rk   rm   r   r   get_access_tokenupdate_session_auth_headerheaders)r^   r   r   s      rH   r   zConnection.username+  s    >>X%		24>>2B$xjQR! <<#-->>>QL'//\(=S/T #dll&:&::,,_= ; $rG   c                     |rB|r?|r|r| d| d| d| }n| d| }|du rd| d| d| _         yd| d| d| _         yyy)aR  Sets a proxy on the Session

        :param str proxy_server: the proxy server
        :param int proxy_port: the proxy port, defaults to 8080
        :param str proxy_username: the proxy username
        :param str proxy_password: the proxy password
        :param bool proxy_http_only: if the proxy should only be used for http
        :@Fhttp://https://)httphttpsN)r   )r^   r   r   r   r   r   	proxy_uris          rH   r   zConnection.set_proxy<  s      J.%&a'7qa
|T   ,nAj\:	%'%i[1'	{3
 &i[1&yk2
 '<rG   c           	         | j                   | j                  dv rQt        | j                  d   | j                  | j
                  | j                  | j                  | j                        }nx| j                  dv r_t        | j                  d   | j                  d   | j                  | j
                  | j                  | j                  | j                        }nt        d      || _         | j                   S )z>Returns the msal client or creates it if it's not already doner   r   )	client_id	authoritytoken_cacheproxiesverifyr   )r   r   r   )r   client_credentialr   r   r   r   r   zC"auth_flow_type" must be "authorization", "public" or "credentials")r   r   r   r   r   r   r   r   r   r
   rX   )r^   clients     rH   msal_clientzConnection.msal_client_  s     $""&<<0"iil"22 $ 2 2 JJ?? LL $$(HH6"iil&*iil"22 $ 2 2 JJ?? LL !Y  !'D   rG   requested_scopesredirect_uric                     |xs | j                   }| j                  dvrt        d      |st        d      | j                  j                  ||      }|j                  d      |fS )a  Initializes the oauth authorization flow, getting the
        authorization url that the user must approve.

        :param list[str] requested_scopes: list of scopes to request access for
        :param str redirect_uri: redirect url configured in registered app
        :param kwargs: allow to pass unused params in conjunction with Connection
        :return: authorization url and the flow dict
        r   r   zIThis method is only valid for auth flow type "authorization" and "public"zMust provide at least one scope)r   r   auth_uri)r   r   RuntimeErrorrX   r   initiate_auth_code_flowrq   )r^   r   r   r_   flows        rH   get_authorization_urlz Connection.get_authorization_url}  sz     $>t'>'>&AA[   >??77#, 8 
 xx
#T))rG   )r  r   store_tokenauthorization_urlr  r  c                   | j                   dv r||st        d| j                          t        |      }t        |j                        j                         D ci c]  \  }}||d    }	}}| j                  j                  ||	      }
n| j                   dk(  r*|t        d      | j                  j                  |      }
nZ| j                   dk(  r@|st        d	      | j                  j                  | j                  | j                  |
      }
nt        d      d|
vr:t        j                  d|
j                  d       d|
j                  d              y|
j                  d      }|r?|j                  d      }|j                  d      }|r|r| d| }| j                  |       | j                   | j#                  |
d          |r| j$                  j'                          yc c}}w )a  Authenticates for the specified url and gets the oauth token data. Saves the
        token in the backend if store_token is True. This will replace any other tokens stored
        for the same username and scopes requested.
        If the token data is successfully requested, then this method will try to set the username if
        not previously set.

        :param str or None authorization_url: url given by the authorization flow or None if it's client credentials
        :param dict flow: dict object holding the data used in get_authorization_url
        :param list[str] requested_scopes: list of scopes to request access for
        :param bool store_token: True to store the token in the token backend,
         so you don't have to keep opening the auth link and
         authenticating every time
        :param kwargs: allow to pass unused params in conjunction with Connection
        :return: Success/Failure
        :rtype: bool
        r   z.Authorization url not provided for oauth flow r   )auth_responser   zvAuth flow type "credentials" needs the default scope for a resource. For example: https://graph.microsoft.com/.default)r   r   z>Auth flow type "password" requires scopes and none where given)r   r   r   zO"auth_flow_type" must be "authorization", "password", "public" or "credentials"r   z#Unable to fetch auth token. Error: rl   z | Description: error_descriptionFid_token_claimsoidtidrh   r   r   T)r   rX   r	   r   queryitemsr   acquire_token_by_auth_code_flowacquire_token_for_client"acquire_token_by_username_passwordr   r   rk   rl   rq   r   r   r   r   
save_token)r^   r  r  r   r  r_   parsedkr   query_params_dictresultr
  r  r  r   s                  rH   request_tokenzConnection.request_token  s   4 "==$ DTEXEXDYZ  /0F5=fll5K5Q5Q5S TTQAaD T T%%EE$5 F F   M1' I 
 %%>>FV>WF  J.# T  %%HHGW I F a  'II5fjj6I5JJZ[a[e[efy[zZ{|  %jj):;O%))%0%))%03),QsenO99(7 : 
 ||'//VN=S/T))+i !Us   G,c                     | j                   j                         r?| j                  2| j                   j                         }|r|j	                  d      | _        yy)zSLoads the token from the backend and tries to set the self.username if it's not setr   TF)r   
load_tokenr   r   rq   r   )r^   r   s     rH   load_token_from_backendz"Connection.load_token_from_backend  sM    ((*~~%#11==?$0$4$4Z$@DMrG   r  c                 *   |r&| j                   j                  s| j                          | j                   j                  | j                        }t               }|#|j                  j                  dd|d    i       | j                  |_	        | j                  |_        | j                  rgt        | j                  | j                  | j                  t        t        d      }t!        |      }|j#                  d|       |j#                  d	|       |S )
a:  Create a requests Session object with the oauth token attached to it

        :param bool load_token: load the token from the token backend and load the access token into the session auth
        :return: A ready to use requests session with authentication header attached
        :rtype: requests.Session
        r   r   Bearer r   T)totalreadconnectbackoff_factorstatus_forcelistrespect_retry_after_headermax_retriesr   r   )r   has_datar  r   r   r   r   updater   r   r   r   r   r   r&   RETRIES_STATUS_LISTr   mount)r^   r  tokenr   retryadapters         rH   get_sessionzConnection.get_session  s     d0099((*""33T]]3K)OO""OwuX>O5P#QR****)),,5!4+/E "e4GMM)W-MM*g.rG   c                 B   t               }| j                  |_        | j                  |_        | j
                  rft        | j
                  | j
                  | j
                  t        t              }t        |      }|j                  d|       |j                  d|       |S )z#Creates and returns a naive session)r  r  r  r   r!  r#  r   r   )r   r   r   r   r   r   r   r&   r'  r   r(  )r^   r   r*  r+  s       rH   get_naive_sessionzConnection.get_naive_session  s    	 $

#**)),,5!4E "e4G	73
G4rG   r   c                    |H| j                   j                  | j                        xs i }|j                  d      }|t	        d      t
        j                  d       | j                  j                  j                  dd| i       y)zJ Will update the internal request session auth header with an access tokenNr   r   zhTried to update the session auth header but no access token was provided nor found in the token backend.z-New access token set into session auth headerr   r  )
r   r   r   rq   r  rk   rm   r   r   r&  )r^   r   access_token_dicts      rH   r   z%Connection.update_session_auth_header1  s     $ 2 2 C C !D ! !  -00:L#" $X Y Y		AB##~67	
rG   c                    d}| j                   j                  | j                        s| j                  dk(  r~t        j                  d       | j                   j                  | | j                        }t        j                  d|        |du r| j                         S |du r| j                          yyt        j                  d       y)	z8Internal method to check try to update the refresh tokenFr   r   z7Asking the token backend if we should refresh the token)conr   zToken Backend answered TzYou can not refresh an access token that has no 'refresh_token' available.Include 'offline_access' permission to get a 'refresh_token'.)
r   token_is_long_livedr   r   rk   rm   should_refresh_tokenrefresh_tokenr   rl   )r^   token_refreshed	should_rts      rH   _try_refresh_tokenzConnection._try_refresh_tokenB  s      22DMM2J""m3 IIOP**??DSWS`S`?aIII/	{;<D ))++e# //1 IIP rG   c                 R   t         j                  d       | j                  | j                  d      | _        | j                  j                  | j                  d      }| j                  j                  || j                  j                  | j                        d         }|t        d      d	|v rt        d
|d	          d|v r^t         j                  d| j                          | j                  |d          | j                  r| j                  j                          yy)a  
        Refresh the OAuth authorization token.
        This will be called automatically when the access token
        expires, however, you can manually call this method to
        request a new refresh token.

        :return bool: Success / Failure
        zRefreshing access tokenTr  )r   remove_reservedr   r   )r   accountz$There is no refresh token to refreshrl   z Refresh token operation failed: r   z8New oauth token fetched by refresh method for username: r   F)rk   rm   r   r,  r   get_token_scopesr   r   acquire_token_silent_with_errorget_accountsr  r   r   r  )r^   r   r  s      rH   r5  zConnection.refresh_token`  s%    			+,<<++t+<DL ##44]]D 5 

 !!AA$$114==1I!L B 
 >EFF!A&/ARSTTv%IIJ4==/Z ++9O+P--""--/rG   c                 H   | j                   r}t        t        j                         | j                   z
  d      dz  }|| j                  k  r@| j                  |z
  }t        j                  d| d       t        j                  |dz         t        j                         | _         y)z?Checks if a delay is needed between requests and sleeps if Truer   i  zSleeping for z millisecondsN)r   roundtimer   rk   rm   sleep)r^   dif	sleep_fors      rH   _check_delayzConnection._check_delay  s    $$diikD$=$==qADH  T((( //#5			M)MBC

9t+,$(IIK!rG   session_objurlmethod	ignore40xc           	      v   |j                         }|| j                  vrt        d| j                         d|vri | j                  |d<   nS| j                  j	                         D ]6  \  }}||d   vr	||d   |<   |dk(  s||d   v s$|d   |    d| |d   |<   8 |dk(  r|j                  dd       nx|dv rt|j                  d      |d   j                  d
      d|d   d
<   d|v rC|d   >|d   j                  d
      dk(  r't        j                  |d   | j                        |d<   | j                  | j                  |d<   | j                          	 t        j                  d|j                          d|        t        j                  d|        t        j                  d|j                           |j                   ||fi |}|j#                          t        j                  d|j$                   d|j&                          |S # t(        t*        t,        t.        f$ r=}	t        j                  d| d| j0                  rd| j0                   nd        |	d	}	~	wt2        $ r}	|	j4                  j$                  dv rW|du rS| j6                  j9                  | j:                        r-t        j                  d| j:                          t=        d      	 |	j4                  j                         }
|
j                  di       j                  dd      }|
j                  di       j                  di       j                  d d      }n# t        $ r d}d}Y nw xY wt?        |	j4                  j$                  d!z        }|d"k(  rt        jA                  d#|	 d$| d%|        nt        j                  d&|	        | jB                  r.|r*t3        |	jD                  d'    d$| |	j4                  (      d	|	|	j4                  cY d	}	~	S d	}	~	wtF        $ r}	t        j                  d)|	        |	d	}	~	ww xY w)*a  Internal handling of requests. Handles Exceptions.

        :param session_obj: a requests Session instance.
        :param str url: url to send request to
        :param str method: type of request (get/put/post/patch/delete)
        :param bool ignore40x: indicates whether to ignore 40x errors when it would
          indicate that there the token has expired. This is set to 'True' for the
          first call to the api, and 'False' for the call that is initiated after a
          tpken refresh.
        :param kwargs: extra params to send to the request api
        :return: Response of the request
        :rtype: requests.Response
        zMethod must be one of: r   Preferz, rq   allow_redirectsT)r   r   r   NzContent-typezapplication/jsondata)clsr   zRequesting (z) URL: zRequest parameters: zSession default headers: zReceived response (z) from URL zConnection Error calling: rh   zUsing proxy rM   )i  i  r   z%Oauth Token is expired for username: zOauth Token is expiredrl   message
innerErrorcoded      zClient Error: z | Error Message: z | Error Code: zServer Error: r   )responsezRequest Exception: )$lower_allowed_methodsrX   r   r  
setdefaultrq   jsondumpsr   r   rF  rk   rm   upperr   requestraise_for_statusstatus_coderH  r   r   r   r   r   r   rU  r   token_is_expiredr   rB   intrl   r   argsr   )r^   rG  rH  rI  rJ  r_   rs   valuerU  rn   rl   error_message
error_coder^  s                 rH   _internal_requestzConnection._internal_request  s;   * ...6t7L7L6MNOOF" 84#7#7 8F9"2288: R
UfY//-2F9%c*H_y0A)A06y0A#0F/Gr%-QF9%c*	R U?/6//

9%19%)).9A4Fy!.1& 6N.9%)).9=OO!%6N(9(9"v <<# $F9?	IIV\\^$4GC5ABII,VH56II1+2E2E1FGH*{**63A&AH%%'II%h&:&:%;;x||nU OXw? 	II,SERVR\R\\$**3Nbd2ef G )	"zz%%3	T8I%%666N II Edmm_UV+,DEE 

) %		'2 6 : :9b IIIgr*..|R@DDVRP     "
  ajj44s:;Ka 		$QC'9-XbWcd
 		N1#./%% #66!9+%7G!"   
 Gzz! 	II+A3/0G	s^   B7H P8-8I%%P82A/P"A.MPM!P M!!B&PP8P8P33P8c                     | j                   | j                         | _          | j                  | j                   ||fddi|S )as  Makes a request to url using an without oauth authorization
        session, but through a normal session

        :param str url: url to send request to
        :param str method: type of request (get/put/post/patch/delete)
        :param kwargs: extra params to send to the request api
        :return: Response of the request
        :rtype: requests.Response
        rJ  F)r   r.  re  )r^   rH  rI  r_   s       rH   naive_requestzConnection.naive_request  sS     %!%!7!7!9D%t%%V
7<
@F
 	
rG   c                    | j                   | j                  d      | _         n=| j                   j                  j                  d      t	        d| j
                         	  | j                  | j                   ||fddi|S # t        $ r=}| j                         r& | j                  | j                   ||fddi|cY d}~S |d}~ww xY w)a  Makes a request to url using an oauth session.
        Raises RuntimeError if the session does not have an Authorization header

        :param str url: url to send request to
        :param str method: type of request (get/put/post/patch/delete)
        :param kwargs: extra params to send to the request api
        :return: Response of the request
        :rtype: requests.Response
        NTr:  r   z9No auth token found. Authentication Flow needed for user rJ  F)	r   r,  r   rq   r  r   re  rB   r8  )r^   rH  rI  r_   rn   s        rH   oauth_requestzConnection.oauth_request  s     <<++t+<DL||##''8@"OPTP]P]_ 	)4))c659=C  ! 		 &&(-t--LL#v9>BH  		s$   # B 	C
0C=C
CC
paramsc                 .     | j                   |dfd|i|S )a;  Shorthand for self.oauth_request(url, 'get')

        :param str url: url to send get oauth request to
        :param dict params: request parameter to get the service data
        :param kwargs: extra params to send to request api
        :return: Response of the request
        :rtype: requests.Response
        rq   rj  ri  )r^   rH  rj  r_   s       rH   rq   zConnection.getF  s#     "t!!#uFVFvFFrG   rN  c                 .     | j                   |dfd|i|S )a1  Shorthand for self.oauth_request(url, 'post')

        :param str url: url to send post oauth request to
        :param dict data: post data to update the service
        :param kwargs: extra params to send to request api
        :return: Response of the request
        :rtype: requests.Response
        r   rN  rl  r^   rH  rN  r_   s       rH   r   zConnection.postQ  s#     "t!!#vCDCFCCrG   c                 .     | j                   |dfd|i|S )a.  Shorthand for self.oauth_request(url, 'put')

        :param str url: url to send put oauth request to
        :param dict data: put data to update the service
        :param kwargs: extra params to send to request api
        :return: Response of the request
        :rtype: requests.Response
        r   rN  rl  rn  s       rH   r   zConnection.put\  s#     "t!!#uB4B6BBrG   c                 .     | j                   |dfd|i|S )a4  Shorthand for self.oauth_request(url, 'patch')

        :param str url: url to send patch oauth request to
        :param dict data: patch data to update the service
        :param kwargs: extra params to send to request api
        :return: Response of the request
        :rtype: requests.Response
        r   rN  rl  rn  s       rH   r   zConnection.patchg  s#     "t!!#wDTDVDDrG   c                 *     | j                   |dfi |S )zShorthand for self.request(url, 'delete')

        :param str url: url to send delete oauth request to
        :param kwargs: extra params to send to request api
        :return: Response of the request
        :rtype: requests.Response
        r   rl  )r^   rH  r_   s      rH   r   zConnection.deleter  s     "t!!#x:6::rG   c                     t        | d      r&| j                  | j                  j                          t        | d      r(| j                  | j                  j                          yyy)a&  
        Clear the session by closing it
        This should be called manually by the user "del account.con"
        There is no guarantee that this method will be called by the garbage collection
        But this is not an issue because this connections will be automatically closed.
        r   Nr   )hasattrr   closer   rd   s    rH   __del__zConnection.__del__|  sW     4#(@LL 4)d.@.@.L$$& /M)rG   rc   )F)ra   N),rC   rD   rE   r   rW  r{   r   rj   r`  boolr   rY  JSONEncoderr   r`   r   r   r   r   r   r   MsalClientApplicationr   r   r  r  r  r   r,  r.  r   r8  r5  rF  r   re  rg  ri  rq   r   r   r   r   ru  rF   rG   rH   r   r   j  s*   M@ '+$((,(, %!"& 48!-"&"&!%37 $*.+_
_
 sm	_

 SM_
 !_
 !_
 _
 _
  _
 _
   01_
 _
 _
 3-_
  3-!_
" ##_
$ t//0%_
& '_
( )_
* $(+_
D $ $ $ 37	9"*3-	9		9 (3-   __># >4 > > !! ! 	!
 ! ! 
!F !2 ! !< JN* $S	*9A#*	sDy	*@  $04 U#C=U tn	U
 #49-U U 
Un !d !w !F7 (
x} 
PT 
"D <&t &P
0"  vv v 	v
 v 
vp
 
c 
 
$& &c & &P	Gs 	GHTN 	G 	G	D 	D8D> 	Dx 	D	Cs 	C(4. 	Ch 	C	E 	EHTN 	E 	E;# ;H ;
'rG   r   r   client_secretr   protocolra   c                 J   | |f}|xs
 t               }t        |fi |} |j                  d	d|j                  |      i|\  }}t	        d       t	        |       t        d      }	|	r1 |j                  |	fd|i|}
|
rt	        d       |
S t	        d       |
S t	        d       y)
aK  A helper method to perform the OAuth2 authentication flow.
    Authenticate and get the oauth token

    :param str client_id: the client_id
    :param str client_secret: the client_secret
    :param list[str] scopes: a list of protocol user scopes to be converted
     by the protocol or raw scopes
    :param Protocol protocol: the protocol to be used.
     Defaults to MSGraphProtocol
    :param kwargs: other configuration to be passed to the Connection instance,
     connection.get_authorization_url or connection.request_token
    :return: Success or Failure
    :rtype: bool
    r   z(Visit the following url to give consent:z"Paste the authenticated url here:
r  zRAuthentication Flow Completed. Oauth Access Token Stored. You can now use the API.z%Something go wrong. Please try again.zAuthentication Flow aborted.FrF   )r   r   r  r   printinputr  )r   ry  r   rz  r_   r   r2  consent_urlr  	token_urlr  s              rH   oauth_authentication_flowr    s    , m,K,?,H
[
+F
+C111 !008<BK 

45	+;<I"""9B4B6B+  9:,-rG   )NN)?rY  loggingrB  typingr   r   r   r   r   urllib.parser   r	   msalr
   r   requestsr   r   requests.adaptersr   requests.exceptionsr   r   r   r   r   r   $requests.packages.urllib3.util.retryr   tzlocalr   zoneinfor   r   utilsr   r   r   r   r   r   r    	getLoggerrC   rk   r"   rj   r   r$   r'  r&   floatr@   r   rz   rx  rB   rJ   r   r   r   rv  r  rF   rG   rH   <module>r     sx      8 8 + G & )  7 ! 4   g! 3 X C X  !$  #(k]( }( )*	(
 45( [M( ./( $k2( 24FG( _%( 23( -.(  ;<( !"( /0(  *+!(" 89#($ "#%(& ""*+#$,-01^#$ !5(S$s)^$ : 57TTU 		 	_ _D0
h 0
f=
8 =
@\' \'D #'	222 I2 x 	2 
2rG   