o
    gf*                     @   s\  d Z ddlmZmZ ddlmZ ddlmZ zddlZ	W n e
y;   zddl	Z	W n e
y8   ddlm	Z	 Y nw Y nw ddlmZ ddlmZ dd	lmZmZmZmZ dd
lmZ ddlmZmZmZ dZG dd deZG dd deZG dd deeZdd Z dd Z!	d!ddZ"G dd dej#Z$G dd deZ%G dd deeZ&ee&d Z'dS )"aY  
Odnoklassniki.ru OAuth2 and IFRAME application support
If you are using OAuth2 authentication,
    * Take a look to:
        http://dev.odnoklassniki.ru/wiki/display/ok/The+OAuth+2.0+Protocol
    * You need to register OAuth application here:
        http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188
elif you're building iframe application,
    * Take a look to:
        http://dev.odnoklassniki.ru/wiki/display/ok/
                Odnoklassniki.ru+Third+Party+Platform
    * You need to register your iframe application here:
        http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=5668937
    * You need to sign a public offer and do some bureaucracy if you want to be
      listed in application registry
Then setup your application according manual and use information from
registration mail to set settings values.
    )	urlencodeunquote)Request)md5N)
simplejson)forms)authenticate)OAuthBackend
BaseOAuth2BaseAuthSocialAuthBackend)
AuthFailed)logdsa_urlopenbackend_settingzhttp://api.odnoklassniki.ru/c                   @   s,   e Zd ZdZdZddgZdd Zdd Zd	S )
OdnoklassnikiBackendz$Odnoklassniki authentication backendodnoklassniki)refresh_tokenr   )
expires_inexpiresc                 C      |d S )z/Return user unique id provided by Odnoklassnikiuid selfdetailsresponser   r   k/var/www/html/humari/django-venv/lib/python3.10/site-packages/social_auth/backends/contrib/odnoklassniki.pyget_user_id1      z OdnoklassnikiBackend.get_user_idc                 C   ,   |d dt |d t |d t |d dS )z.Return user details from Odnoklassniki requestr    name
first_name	last_nameusernameemailfullnamer#   r$   r   r   r   r   r   r   get_user_details5   s   


z%OdnoklassnikiBackend.get_user_detailsN)__name__
__module____qualname____doc__r"   
EXTRA_DATAr   r+   r   r   r   r   r   +   s    r   c                   @   s   e Zd Zdd ZdS )OdnoklassnikiMixinc                 C   s.   t | | j}t | | j}t | | j}|||fS N)r   SETTINGS_KEY_NAMESETTINGS_SECRET_NAMESETTINGS_PUBLIC_NAME)r   
client_keyclient_secret
public_keyr   r   r   get_settingsA   s   
zOdnoklassnikiMixin.get_settingsN)r,   r-   r.   r9   r   r   r   r   r1   @   s    r1   c                   @   s8   e Zd ZdZeZdZdZdZdZ	dZ
dd Zd	d
 ZdS )OdnoklassnikiOAuth2zOdnoklassniki OAuth2 supportz+http://www.odnoklassniki.ru/oauth/authorizez*http://api.odnoklassniki.ru/oauth/token.doODNOKLASSNIKI_OAUTH2_CLIENT_KEY"ODNOKLASSNIKI_OAUTH2_CLIENT_SECRETODNOKLASSNIKI_OAUTH2_APP_KEYc                 C   s   t | dg S )N ODNOKLASSNIKI_OAUTH2_EXTRA_SCOPE)r   r   r   r   r   	get_scopeQ   s   zOdnoklassnikiOAuth2.get_scopec                 O   s(   |dd}|   \}}}t|t||dS )z,Return user data from Odnoklassniki REST APIzusers.getCurrentUser)access_tokenmethodoauth)r9   odnoklassniki_apiODNOKLASSNIKI_API_SERVER)r   rA   argskwargsdatar6   r7   r8   r   r   r   	user_dataT   s
   
zOdnoklassnikiOAuth2.user_dataN)r,   r-   r.   r/   r   AUTH_BACKENDAUTHORIZATION_URLACCESS_TOKEN_URLr3   r4   r5   r@   rI   r   r   r   r   r:   H   s    r:   c                 C   sD   t d| d | }tdd |  D }t d||  S )zCalculates signature of request data access_token value must be included
    Algorithm is described at
        http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=12878032,
    search for "little bit different way"
    z
{0:s}{1:s}rA   c                 S   s$   g | ]\}}|d krd ||qS )rA   {0:s}={1:s}format.0keyvaluer   r   r   
<listcomp>d   s
    
z+odnoklassniki_oauth_sig.<locals>.<listcomp>r!   )r   rO   	hexdigestsorteditemsjoin)rH   r7   suffix
check_listr   r   r   odnoklassniki_oauth_sig\   s   r[   c                 C   s,   t dd |  D }td||  S )a  Calculates signature as described at:
        http://dev.odnoklassniki.ru/wiki/display/ok/
            Authentication+and+Authorization
    If API method requires session context, request is signed with session
    secret key. Otherwise it is signed with application secret key
    c                 S   s   g | ]
\}}d  ||qS )rM   rN   rP   r   r   r   rT   q   s    z,odnoklassniki_iframe_sig.<locals>.<listcomp>r!   )rV   rW   r   rX   rU   )rH   client_secret_or_session_secret
param_listr   r   r   odnoklassniki_iframe_sigj   s   
r^   rC   c                 C   s   |  |dd |dkrt| || d< n#|dkr"t| | d | d< n|dkr.t| || d< n	d}t||t| }td	||}z
tt	|
 W S  tttttfyg   td
ddt|dd Y dS w )zt Calls Odnoklassniki REST API method
        http://dev.odnoklassniki.ru/wiki/display/ok/Odnoklassniki+Rest+API
    JSON)application_keyrO   rC   sigiframe_sessionsession_secret_keyiframe_nosessionz2Unknown request type {0}. How should it be signed?z{0}fb.do?{1}errorz'Could not load data from Odnoklassniki.T)rH   )exc_infoextraN)updater[   r^   r   rO   r   r   r   loadsr   read	TypeErrorKeyErrorIOError
ValueError
IndexErrorr   dict)rH   api_urlr8   r7   request_typemsgparamsrequestr   r   r   rD   w   s0   

rD   c                       s   e Zd Ze Ze Ze Ze Z	e Z
e Ze ZejddZejddZe Ze ZejddZ fddZdd Zdd Zd	d
 Z  ZS )OdnoklassnikiIframeFormF)requiredc                    s    || _ tt| j|i | d S r2   )authsuperrv   __init__)r   rx   rF   rG   	__class__r   r   rz      s   z OdnoklassnikiIframeForm.__init__c                 C   s2   t | jd}d| jd | jd |}t| S )NODNOKLASSNIKI_APP_SECRETz{0:d}{1:s}{2:s}logged_user_idsession_key)r   rx   rO   cleaned_datar   rU   )r   
secret_keyhash_sourcer   r   r   get_auth_sig   s   z$OdnoklassnikiIframeForm.get_auth_sigc                 C   s2   |   }| jd  }||krtd| jd S )Nauth_sigzWrong authorization key)r   r   lowerr   ValidationError)r   correct_keyrR   r   r   r   clean_auth_sig   s
   

z&OdnoklassnikiIframeForm.clean_auth_sigc                 C   s2   d}i }| j  D ]}||v r| j| ||< q	|S )N)r~   
api_serverr`   r   rc   
authorizedapiconnection)fieldskeysr   )r   r   r   	fieldnamer   r   r   get_response   s   z$OdnoklassnikiIframeForm.get_response)r,   r-   r.   r   IntegerFieldr~   	CharFieldr   r`   r   rc   r   r   refplacerefererr   ra   custom_argsrz   r   r   r   __classcell__r   r   r{   r   rv      s"    	rv   c                   @   s,   e Zd ZdZdZdd Zdd Zdd Zd	S )
OdnoklassnikiAppBackendz/Odnoklassniki iframe app authentication backendodnoklassnikiappc                 C   r   )z/Return unique user id provided by Odnoklassnikir   r   r   r   r   r   r      r   z#OdnoklassnikiAppBackend.get_user_idc                    s   t  fdd  D S )Nc                    s$   g | ]\}}| d  v r||fqS )extra_data_listr   rP   r   r   r   rT      s    z6OdnoklassnikiAppBackend.extra_data.<locals>.<listcomp>)rp   rW   )r   userr   r   r   r   r   r   
extra_data   s   z"OdnoklassnikiAppBackend.extra_datac                 C   r    )Nr   r!   r"   r#   r$   r%   r)   r*   r   r   r   r+      s   


z(OdnoklassnikiAppBackend.get_user_detailsN)r,   r-   r.   r/   r"   r   r   r+   r   r   r   r   r      s    r   c                   @   s4   e Zd ZdZdZdZdZeZdd Z	e
dd Zd	S )
OdnoklassnikiAppz-Odnoklassniki iframe app authentication classODNOKLASSNIKI_APP_KEYr}   ODNOKLASSNIKI_APP_PUBLIC_KEYc                 O   s   t | |jd}| std| }t| dd}d}|| }	dd|d d	|	d
}
|  \}}}t	|
|d ||d}t
|dkrsd|d v rs|d }t| dd}|D ]}|| ||< qV|	| |d< |d| d|| jjdi ntdt|i |S )N)rx   rH   z&Cannot authorize: malformed parameters&ODNOKLASSNIKI_APP_EXTRA_USER_DATA_LISTr   )r   r#   r$   r"   zusers.getInfoz{0}r~   ,)rB   uidsr   r   rd      r   r   &ODNOKLASSNIKI_APP_EXTRA_AUTH_DATA_LIST)r   r   r   rc   r   r   rx   r   Tz"Cannot get user details: API error)rv   GETis_validr   r   r   rO   rX   r9   rD   lenrh   rJ   r"   r   )r   ru   r   rF   rG   formr   extra_user_database_fieldsr   rH   r6   r7   r8   r   auth_data_fieldsfieldr   r   r   auth_complete   sF   
zOdnoklassnikiApp.auth_completec                 C   s   dS )zU
        Odnoklassniki API for iframe application does not require redirects
        Fr   r?   r   r   r   uses_redirect	  s   zOdnoklassnikiApp.uses_redirectN)r,   r-   r.   r/   r3   r4   r5   r   rJ   r   propertyr   r   r   r   r   r      s    (r   )r   r   )rC   )(r/   urllibr   r   urllib2r   hashlibr   jsonr   ImportErrordjango.utilsdjangor   django.contrib.authr   social_auth.backendsr	   r
   r   r   social_auth.exceptionsr   social_auth.utilsr   r   r   rE   r   objectr1   r:   r[   r^   rD   Formrv   r   r   BACKENDSr   r   r   r   <module>   sB    
29
