ó
@j>Vc           @   sK  d  d l  m Z m Z d  d l m Z m Z d  d l m Z d  d l m Z d  d l	 m
 Z
 d  d l m Z m Z d  d l m 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 Z d  d	 l Z e j d
 d !d d d f k  rd GHe j d ƒ n  y d  d	 l Z e Z Wn e k
 r=e Z n Xy e Wn e k
 r_e  Z n Xd d l! m" Z" e j j# d k Z$ e
 e% ƒ Z& d e' f d „  ƒ  YZ( d e( f d „  ƒ  YZ) d e* f d „  ƒ  YZ+ d e* f d „  ƒ  YZ, d e' f d „  ƒ  YZ- d „  Z. d e+ f d „  ƒ  YZ/ d e+ f d  „  ƒ  YZ0 d! e* f d" „  ƒ  YZ1 d	 S(#   iÿÿÿÿ(   t	   b64encodet	   b64decode(   t   datetimet	   timedelta(   t   MIMEMultipart(   t   MIMEText(   t	   getLogger(   t   SMTPt   SMTP_SSL(   t   Thread(   t   timeNi    i   i   i   i   s   Python >= 2.7.8 is requiredi   (   t   JsonBackendt   AAAExceptionc           B   s   e  Z d  Z RS(   s.   Generic Authentication/Authorization Exception(   t   __name__t
   __module__t   __doc__(    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR   9   s   t   AuthExceptionc           B   s   e  Z d  Z RS(   s:   Authentication Exception: incorrect username/password pair(   R   R   R   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR   >   s   t   BaseCorkc        	   B   ss  e  Z d  Z d# d# d# e d# d# d d# d „ Z d# d# d „ Z d d d „ Z d# d# e d# d „ Z d „  Z	 d „  Z
 d	 „  Z d# d# d
 „ Z d „  Z d „  Z e d „  ƒ Z e d „  ƒ Z d „  Z d d d d d# d „ Z d „  Z d# d# d d d „ Z d „  Z d# d# e d d „ Z d „  Z d# d# d „ Z e d# d „ ƒ Z e d# d „ ƒ Z d „  Z d  d! „ Z d" „  Z RS($   s   Abstract classt	   localhostc	   	   
   C   sŽ   | r | } n  t  | | ƒ |  _ d |  _ | |  _ | p< d |  _ d |  _ | d k r t | d d d d d	 d
 d | ƒ|  _ n	 | |  _ d S(   s]  Auth/Authorization/Accounting class

        :param directory: configuration directory
        :type directory: str.
        :param users_fname: users filename (without .json), defaults to 'users'
        :type users_fname: str.
        :param roles_fname: roles filename (without .json), defaults to 'roles'
        :type roles_fname: str.
        i  i   s   beaker.sessiont   PBKDF2t   users_fnamet   userst   roles_fnamet   rolest   pending_reg_fnamet   registert
   initializeNi€Q (	   t   Mailert   mailert   password_reset_timeoutt   session_domaint   session_key_namet   preferred_hashing_algorithmt   NoneR   t   _store(	   t   selft	   directoryt   backendt   email_senderR   R   t   smtp_servert   smtp_urlR   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   __init__F   s    				c         C   sÓ   | |  j  j k r¹ |  j  j | d } t | d ƒ rG | j d ƒ } n  |  j | | | ƒ } | r¹ |  j | ƒ t t j ƒ  ƒ |  j  j | d <|  j  j	 ƒ  | r² |  j
 | ƒ n  t Sn  | rÏ |  j
 | ƒ n  t S(   s'  Check login credentials for an existing user.
        Optionally redirect the user to another page (typically /login)

        :param username: username
        :type username: str or unicode.
        :param password: cleartext password
        :type password: str.or unicode
        :param success_redirect: redirect authorized users (optional)
        :type success_redirect: str.
        :param fail_redirect: redirect unauthorized users (optional)
        :type fail_redirect: str.
        :returns: True for successful logins, else False
        t   hasht   encodet   asciit
   last_login(   R"   R   t   hasattrR+   t   _verify_passwordt   _setup_cookiet   strR   t   utcnowt
   save_userst	   _redirectt   Truet   False(   R#   t   usernamet   passwordt   success_redirectt   fail_redirectt   salted_hasht   authenticated(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   logine   s&    	s   /loginc         C   sb   y |  j  } | j ƒ  Wn7 t k
 rP } t j d t | ƒ ƒ |  j | ƒ n X|  j | ƒ d S(   sü   Log the user out, remove cookie

        :param success_redirect: redirect the user after logging out
        :type success_redirect: str.
        :param fail_redirect: redirect the user if it is not logged in
        :type fail_redirect: str.
        s   Exception %s while logging out.N(   t   _beaker_sessiont   deletet	   Exceptiont   logt   debugt   reprR4   (   R#   R9   R:   t   sessiont   e(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   logout   s    	c         C   sð  | d k	 r0 | |  j j k r0 t d ƒ ‚ q0 n  | rQ | d k rQ t d ƒ ‚ n  | d k	 r~ | |  j j k r~ t d ƒ ‚ n  y |  j } Wn9 t k
 rÆ | d k r¶ t d ƒ ‚ qÇ |  j | ƒ n X| j |  j j k rë t d ƒ ‚ n  | d k	 r8| |  j j	 k rd S| d k r(t d ƒ ‚ n  |  j | ƒ n  | r| |  j j k rTd S| d k rot d ƒ ‚ n  |  j | ƒ n  | d k	 rì|  j j |  j j } |  j j | } | | k rÁd S| d k rÜt d	 ƒ ‚ n  |  j | ƒ n  d S(
   sù  Ensure the user is logged in has the required role (or higher).
        Optionally redirect the user to another page (typically /login)
        If both `username` and `role` are specified, both conditions need to be
        satisfied.
        If none is specified, any authenticated user will be authorized.
        By default, any role with higher level than `role` will be authorized;
        set fixed_role=True to prevent this.

        :param username: username (optional)
        :type username: str.
        :param role: role
        :type role: str.
        :param fixed_role: require user role to match `role` strictly
        :type fixed_role: bool.
        :param redirect: redirect unauthorized users (optional)
        :type redirect: str.
        s   Nonexistent users3   A role must be specified if fixed_role has been sets   Role not founds   Unauthenticated users#   Role not found for the current userNs'   Unauthorized access: incorrect usernames#   Unauthorized access: incorrect roles   Unauthorized access: (
   R!   R"   R   R   R   t   current_userR   R4   t   roleR7   (   R#   R7   RH   t
   fixed_roleR:   t   cut   current_lvlt   threshold_lvl(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   require    sJ    c         C   s‘   |  j  j d k  r! t d ƒ ‚ n  | |  j j k rB t d ƒ ‚ n  y t | ƒ Wn t k
 ro t d ƒ ‚ n X| |  j j | <|  j j ƒ  d S(   sÎ   Create a new role.

        :param role: role name
        :type role: str.
        :param level: role level (0=lowest, 100=admin)
        :type level: int.
        :raises: AuthException on errors
        id   s&   The current user is not authorized to s   The role is already existings   The level must be numeric.N(	   RG   t   levelR   R"   R   R   t   intt
   ValueErrort
   save_roles(   R#   RH   RN   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   create_roleï   s    	c         C   sf   |  j  j d k  r! t d ƒ ‚ n  | |  j j k rB t d ƒ ‚ n  |  j j j | ƒ |  j j ƒ  d S(   sy   Deleta a role.

        :param role: role name
        :type role: str.
        :raises: AuthException on errors
        id   s&   The current user is not authorized to s   Nonexistent role.N(   RG   RN   R   R"   R   R   t   popRQ   (   R#   RH   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   delete_role  s    c         c   s6   x/ t  |  j j ƒ D] } | |  j j | f Vq Wd S(   sU   List roles.

        :returns: (role, role_level) generator (sorted by role)
        N(   t   sortedR"   R   (   R#   RH   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt
   list_roles  s    c         C   só   | s t  d ƒ ‚ |  j j d k  r3 t d ƒ ‚ n  | |  j j k rT t d ƒ ‚ n  | |  j j k ru t d ƒ ‚ n  t t	 j
 ƒ  ƒ } |  j | | ƒ } | j d ƒ } i | d 6| d 6| d	 6| d
 6| d 6| d 6|  j j | <|  j j ƒ  d S(   sé  Create a new user account.
        This method is available to users with level>=100

        :param username: username
        :type username: str.
        :param role: role
        :type role: str.
        :param password: cleartext password
        :type password: str.
        :param email_addr: email address (optional)
        :type email_addr: str.
        :param description: description (free form)
        :type description: str.
        :raises: AuthException on errors
        s   Username must be provided.id   s3   The current user is not authorized to create users.s   User is already existing.s   Nonexistent user role.R,   RH   R*   t
   email_addrt   desct   creation_dateR-   N(   t   AssertionErrorRG   RN   R   R"   R   R   R   R1   R   R2   t   _hasht   decodeR3   (   R#   R7   RH   R8   RW   t   descriptiont   tstampt   h(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   create_user  s$    c         C   sY   |  j  j d k  r! t d ƒ ‚ n  | |  j j k rB t d ƒ ‚ n  |  j | ƒ j ƒ  d S(   s¿   Delete a user account.
        This method is available to users with level>=100

        :param username: username
        :type username: str.
        :raises: Exceptions on errors
        id   s&   The current user is not authorized to s   Nonexistent user.N(   RG   RN   R   R"   R   R   t   userR?   (   R#   R7   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   delete_user@  s
    c         c   sN   xG t  |  j j ƒ D]3 } |  j j | } | | d | d | d f Vq Wd S(   s{   List users.

        :return: (username, role, email_addr, description) generator (sorted by
            username)
        RH   RW   RX   N(   RU   R"   R   (   R#   t   unt   d(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt
   list_usersN  s    c         C   s{   |  j  } | j d d ƒ } | d k r6 t d ƒ ‚ n  | d k	 rg | |  j j k rg t | |  d | ƒSt d | ƒ ‚ d S(   s€   Current autenticated user

        :returns: User() instance, if authenticated
        :raises: AuthException otherwise
        R7   s   Unauthenticated userRD   s   Unknown user: %sN(   R>   t   getR!   R   R"   R   t   User(   R#   RD   R7   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRG   X  s    	c         C   sO   y |  j  d } Wn t k
 r% t SX| |  j j k rK t d | ƒ ‚ n  t S(   s´   Check if the current user is anonymous.

        :returns: True if the user is anonymous, False otherwise
        :raises: AuthException if the session username is unknown
        R7   s   Unknown user: %s(   R>   t   KeyErrorR5   R"   R   R   R6   (   R#   R7   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   user_is_anonymousg  s    c         C   s/   | d k	 r+ | |  j j k r+ t | |  ƒ Sd S(   s[   Existing user

        :returns: User() instance if the user exist, None otherwise
        N(   R!   R"   R   Rg   (   R#   R7   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRa   x  s    Ra   i2   s   Signup confirmations   views/registration_email.tplc	         K   sp  | s t  d ƒ ‚ | s$ t  d ƒ ‚ | s6 t  d ƒ ‚ | |  j j k rW t d ƒ ‚ n  | |  j j k rx t d ƒ ‚ n  |  j j | | k r t d ƒ ‚ n  t j ƒ  j }
 t t	 j
 ƒ  ƒ } t j | d | d | d	 | d
 | d |
 |	 } |  j j | | | ƒ |  j | | ƒ } | j d ƒ } i | d 6| d	 6| d 6| d 6| d 6| d
 6|  j j |
 <|  j j ƒ  d S(   s]  Register a new user account. An email with a registration validation
        is sent to the user.
        WARNING: this method is available to unauthenticated users

        :param username: username
        :type username: str.
        :param password: cleartext password
        :type password: str.
        :param role: role (optional), defaults to 'user'
        :type role: str.
        :param max_level: maximum role level (optional), defaults to 50
        :type max_level: int.
        :param email_addr: email address
        :type email_addr: str.
        :param subject: email subject
        :type subject: str.
        :param email_template: email template filename
        :type email_template: str.
        :param description: description (free form)
        :type description: str.
        :raises: AssertError or AAAException on errors
        s   Username must be provided.s   A password must be provided.s"   An email address must be provided.s   User is already existing.s   Nonexistent roles   Unauthorized roleR7   RW   RH   RY   t   registration_codeR,   R*   RX   N(   RZ   R"   R   R   R   t   uuidt   uuid4t   hexR1   R   R2   t   bottlet   templateR   t
   send_emailR[   R\   t   pending_registrationst   save_pending_registrations(   R#   R7   R8   RW   RH   t	   max_levelt   subjectt   email_templateR]   t   kwargsRj   RY   t
   email_textR_   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR     s<    	c         C   sÏ   y |  j  j j | ƒ } Wn t k
 r8 t d ƒ ‚ n X| d } | |  j  j k rd t d ƒ ‚ n  i | d d 6| d d 6| d d 6| d d 6| d d 6t t j	 ƒ  ƒ d	 6|  j  j | <|  j  j
 ƒ  d
 S(   s¶   Validate pending account registration, create a new account if
        successful.

        :param registration_code: registration code
        :type registration_code: str.
        s   Invalid registration code.R7   s   User is already existing.RH   R*   RW   RX   RY   R-   N(   R"   Rq   RS   Rh   R   R   R   R1   R   R2   R3   (   R#   Rj   t   dataR7   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   validate_registrationÁ  s    
 s   Password reset confirmations   views/password_reset_emailc      	   K   sA  | sg | s t  d ƒ ‚ n  xÓ |  j j j ƒ  D]& \ } } | d | k r. | } Pq. q. Wt  d ƒ ‚ nŠ | |  j j k rˆ t  d ƒ ‚ n  | sÂ |  j j | j d d	 ƒ } | sñ t  d ƒ ‚ qñ n/ |  j j | d } | | k rñ t d ƒ ‚ n  |  j | | ƒ }	 t j	 | d | d | d |	 | }
 |  j
 j | | |
 ƒ d	 S(
   sœ  Email the user with a link to reset his/her password
        If only one parameter is passed, fetch the other from the users
        database. If both are passed they will be matched against the users
        database as a security check.

        :param username: username
        :type username: str.
        :param email_addr: email address
        :type email_addr: str.
        :param subject: email subject
        :type subject: str.
        :param email_template: email template filename
        :type email_template: str.
        :raises: AAAException on missing username or email_addr,
            AuthException on incorrect username/email_addr pair
        s6   At least `username` or `email_addr` must be specified.RW   s   Email address not found.s   Nonexistent user.s   Email address not available.s&   Username/email address pair not found.R7   t
   reset_codeN(   R   R"   R   t	   iteritemsRf   R!   R   t   _reset_codeRn   Ro   R   Rp   (   R#   R7   RW   Rt   Ru   Rv   t   kt   vt   stored_email_addrRz   Rw   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   send_password_reset_emailÜ  s4    	c         C   se  y t  | ƒ j ƒ  } | j d d ƒ \ } } } } t | ƒ } t | t d ƒ ƒ sZ t ‚ t | t d ƒ ƒ su t ‚ t | t d ƒ ƒ sœ | j d ƒ } n  Wn# t t	 f k
 rÂ t
 d ƒ ‚ n Xt ƒ  | |  j k rè t
 d ƒ ‚ n  t | t d ƒ ƒ st ‚ |  j | | | ƒ s't
 d ƒ ‚ n  |  j | ƒ } | d
 k rQt d ƒ ‚ n  | j d	 | ƒ d
 S(   sH  Validate reset_code and update the account password
        The username is extracted from the reset_code token

        :param reset_code: reset token
        :type reset_code: str.
        :param password: new password
        :type password: str.
        :raises: AuthException for invalid reset tokens, AAAException
        t   :i   u    t    s   utf-8s   Invalid reset code.s   Expired reset code.s   Nonexistent user.t   pwdN(   R   R\   t   splitRO   t
   isinstancet   typeRZ   R+   t	   TypeErrorRP   R   R
   R   R/   Ra   R!   R   t   update(   R#   Rz   R8   R7   RW   R^   R_   Ra   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   reset_password  s&    
c            s%   |  ‰  | | | | ‡  f d † } | S(   sh  
        Create a decorator to be used for authentication and authorization

        :param username: A resource can be protected for a specific user
        :param role: Minimum role level required for authorization
        :param fixed_role: Only this role gets authorized
        :param fail_redirect: The URL to redirect to if a login is required.
        c            s   ‡  ‡ ‡ ‡ ‡ f d †  } | S(   Nc            s=   d d  l  } | j ˆ  ƒ ‡ ‡ ‡  ‡ ‡ ‡ f d †  ƒ } | S(   Niÿÿÿÿc       	      s/   ˆ j  d ˆ d ˆ d ˆ d ˆ  ƒ ˆ |  | Ž  S(   NR7   RH   RI   R:   (   RM   (   t   at   ka(   R:   RI   t   funcRH   t   session_managerR7   (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   wrapperK  s    	(   t	   functoolst   wraps(   RŒ   R   RŽ   (   R:   RI   RH   R   R7   (   RŒ   s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt	   decoratorH  s    -(    (   R7   RH   RI   R:   R‘   (   R   (   R:   RI   RH   R7   s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   auth_requireF  s    
(    (   R#   R7   RH   RI   R:   R’   (    (   R   s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   make_auth_decorator:  s    
	c         C   s?   |  j  } | | d <|  j d k	 r1 |  j | _ n  |  j ƒ  d S(   s+   Setup cookie for a user that just logged inR7   N(   R>   R   R!   t   domaint   _save_session(   R#   R7   RD   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR0   X  s
    	
c         C   sp   | d k r |  j } n  | d k r: |  j | | d | ƒS| d k r\ |  j | | d | ƒSt d | ƒ ‚ d S(   sF   Hash username and password, generating salt value if required
        R   t   saltt   scrypts'   Unknown hashing algorithm requested: %sN(   R!   R    t   _hash_pbkdf2t   _hash_scryptt   RuntimeError(   R#   R7   Rƒ   R–   t   algo(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR[   a  s    c         C   s‹   t  s t d ƒ ‚ n  | d k r3 t j d ƒ } n  t | ƒ d k sQ t d ƒ ‚ d |  | f } t j | | ƒ } d | | } t	 | ƒ S(   s‚   Hash username and password, generating salt value if required
        Use scrypt.

        :returns: base-64 encoded str.
        s8   scrypt.hash required. Please install the scrypt library.i    s   Incorrect salt lengths   %s %st   sN(
   t   scrypt_availableR@   R!   t   ost   urandomt   lenRZ   R—   R*   R    (   R7   Rƒ   R–   t	   cleartextR_   t   hashed(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR™   o  s    c         C   sÝ   | d	 k r t j d ƒ } n  t | t ƒ s3 t ‚ t | ƒ d k sQ t d ƒ ‚ |  j d ƒ }  t |  t ƒ su t ‚ | j d ƒ } t | t ƒ s™ t ‚ |  d | } t j	 d | | d d d ƒ} d | | } t
 | ƒ S(
   s   Hash username and password, generating salt value if required
        Use PBKDF2 from Beaker

        :returns: base-64 encoded str.
        i    s   Incorrect salt lengths   utf-8t    t   sha1i
   t   dklent   pN(   R!   Rž   RŸ   R…   t   bytesRZ   R    R+   t   hashlibt   pbkdf2_hmacR    (   R7   Rƒ   R–   R¡   R_   R¢   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR˜   †  s    c         C   sÆ   t  | t d ƒ ƒ s t ‚ t | ƒ } | d } t  | t ƒ rO t | ƒ } n  | d d !} | d k r‡ |  j | | | ƒ } | | k S| d k r² |  j | | | ƒ } | | k St d | ƒ ‚ d S(	   sT   Verity username/password pair against a salted hash

        :returns: bool
        R‚   i    i   i!   R¦   Rœ   s%   Unknown hashing algorithm in hash: %rN(	   R…   R†   RZ   R   RO   t   chrR˜   R™   Rš   (   R#   R7   Rƒ   R;   t   decodedt	   hash_typeR–   R_   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR/      s    


i`   c         C   s™   |  j  j j ƒ  } t r' t | ƒ } n  xk | D]c \ } } t j | d d ƒ } t j ƒ  } t d | ƒ } | | | k r. |  j  j j	 | ƒ q. q. Wd S(   s~   Purge expired registration requests.

        :param exp_time: expiration time (hours)
        :type exp_time: float.
        RY   s   %Y-%m-%d %H:%M:%S.%ft   hoursN(
   R"   Rq   t   itemst   is_py3t   listR   t   strptimeR2   R   RS   (   R#   t   exp_timet   pendingt	   uuid_codeRx   t   creationt   nowt   maxdelta(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   _purge_expired_registrations·  s    	c         C   se   |  j  | | ƒ } d t ƒ  } | j d ƒ } d j | j d ƒ | j d ƒ | | f ƒ } t | ƒ S(   sÔ   generate a reset_code token

        :param username: username
        :type username: str.
        :param email_addr: email address
        :type email_addr: str.
        :returns: Base-64 encoded token
        s   %ds   utf-8R   (   R[   R
   R+   t   joinR    (   R#   R7   RW   R_   t   tRz   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR|   É  s    	N(    R   R   R   R!   R6   R)   R=   RF   RM   RR   RT   RV   R`   Rb   Re   t   propertyRG   Ri   Ra   R   Ry   R€   R‰   R“   R0   R[   t   staticmethodR™   R˜   R/   R¸   R|   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR   C   sN   		)	N			&		
		=	<	 				Rg   c           B   s/   e  Z d d  „ Z d d d d „ Z d „  Z RS(   c         C   sÎ   | |  _  | |  j  j j k s* t d ƒ ‚ | |  _ |  j  j j | } | d |  _ | d |  _ | d |  _ |  j  j j |  j |  _	 | d k	 rÊ y+ | d |  _ | d |  _ | d |  _ WqÊ qÊ Xn  d S(	   s‚  Represent an authenticated user, exposing useful attributes:
        username, role, level, description, email_addr, session_creation_time,
        session_accessed_time, session_id. The session-related attributes are
        available for the current user only.

        :param username: username
        :type username: str.
        :param cork_obj: instance of :class:`Cork`
        s   Unknown userRH   RX   RW   t   _creation_timet   _accessed_timet   _idN(   t   _corkR"   R   RZ   R7   RH   R]   RW   R   RN   R!   t   session_creation_timet   session_accessed_timet
   session_id(   R#   R7   t   cork_objRD   t	   user_data(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR)   Ü  s    
	!	c         C   sì   |  j  } | |  j j j k r- t d ƒ ‚ n  | d k	 rw | |  j j j k r] t d ƒ ‚ n  | |  j j j | d <n  | d k	 r² |  j j | | ƒ j ƒ  |  j j j | d <n  | d k	 rØ | |  j j j | d <n  |  j j j	 ƒ  d S(   s^  Update an user account data

        :param role: change user role, if specified
        :type role: str.
        :param pwd: change user password, if specified
        :type pwd: str.
        :param email_addr: change user email address, if specified
        :type email_addr: str.
        :raises: AAAException on nonexistent user or role.
        s   User does not exist.s   Nonexistent role.RH   R*   RW   N(
   R7   RÀ   R"   R   R   R!   R   R[   R\   R3   (   R#   RH   Rƒ   RW   R7   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRˆ   ÷  s    		&c         C   sQ   y |  j  j j j |  j ƒ Wn t k
 r< t d ƒ ‚ n X|  j  j j ƒ  d S(   sP   Delete user account

        :raises: AAAException on nonexistent user.
        s   Nonexistent user.N(   RÀ   R"   R   RS   R7   Rh   R   R3   (   R#   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR?     s
    N(   R   R   R!   R)   Rˆ   R?   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRg   Ú  s   t   Redirectc           B   s   e  Z RS(    (   R   R   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRÆ   !  s   c         C   s   t  |  ƒ ‚ d  S(   N(   RÆ   (   t   path(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   raise_redirect%  s    t   Corkc           B   s/   e  Z e d  „  ƒ Z e d „  ƒ Z d „  Z RS(   c         C   s   t  j |  ƒ d  S(   N(   Rn   t   redirect(   t   location(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR4   *  s    c         C   s   t  j j j |  j ƒ S(   s   Get session(   Rn   t   requestt   environRf   R   (   R#   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR>   .  s    c         C   s   |  j  j ƒ  d  S(   N(   R>   t   save(   R#   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR•   3  s    (   R   R   R¼   R4   R»   R>   R•   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRÉ   )  s   t	   FlaskCorkc           B   s/   e  Z e d  „  ƒ Z e d „  ƒ Z d „  Z RS(   c         C   s   t  |  ƒ d  S(   N(   RÈ   (   RË   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR4   8  s    c         C   s   d d l  } | j S(   s   Get sessioniÿÿÿÿN(   t   flaskRD   (   R#   RÐ   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR>   <  s    c         C   s   d  S(   N(    (   R#   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR•   B  s    (   R   R   R¼   R4   R»   R>   R•   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRÏ   7  s   R   c           B   sD   e  Z d  e d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   i   c         C   s:   | |  _  | |  _ | |  _ g  |  _ |  j | ƒ |  _ d S(   s²   Send emails asyncronously

        :param sender: Sender email address
        :type sender: str.
        :param smtp_server: SMTP server
        :type smtp_server: str.
        N(   t   sendert   join_timeoutt   use_threadst   _threadst   _parse_smtp_urlt   _conf(   R#   RÑ   R(   RÒ   RÓ   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR)   H  s
    				c         C   sº   t  j d | t  j ƒ } | s- t d ƒ ‚ n  | j ƒ  } | d d
 k rV d | d <n  | d d
 k rs d | d <n t | d ƒ | d <d | d k  o¢ d k  n s¶ t d	 ƒ ‚ n  | S(   s   Parse SMTP URLsB  
            (                                   # Optional protocol
                (?P<proto>smtp|starttls|ssl)    # Protocol name
                ://
            )?
            (                                   # Optional user:pass@
                (?P<user>[^:]*)                 # Match every char except ':'
                (: (?P<pass>.*) )? @            # Optional :pass
            )?
            (?P<fqdn>                           # Required FQDN on IP address
                ()|                             # Empty string
                (                               # FQDN
                    [a-zA-Z_\-]                 # First character cannot be a number
                    [a-zA-Z0-9_\-\.]{,254}
                )
                |(                              # IPv4
                    ([0-9]{1,3}\.){3}
                    [0-9]{1,3}
                 )
                |(                              # IPv6
                    \[                          # Square brackets
                        ([0-9a-f]{,4}:){1,8}
                        [0-9a-f]{,4}
                    \]
                )
            )
            (                                   # Optional :port
                :
                (?P<port>[0-9]{,5})             # Up to 5-digits port
            )?
            [/]?
            $
        s   SMTP URL seems incorrectt   protot   smtpt   porti   i    i   s   Incorrect SMTP portN(   t   ret   matcht   VERBOSERš   t	   groupdictR!   RO   (   R#   t   urlRÛ   Rd   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRÕ   V  s      c         C   s  |  j  d o |  j s% t d ƒ ‚ n  t d ƒ } | | d <|  j | d <| | d <t | t ƒ rs | j d ƒ } n  t | d ƒ } | j | ƒ | j	 ƒ  } t
 j d	 |  j  d ƒ |  j r÷ t d
 |  j d | | f ƒ } | j ƒ  |  j j | ƒ n |  j | | ƒ d S(   s'  Send an email

        :param email_addr: email address
        :type email_addr: str.
        :param subject: subject
        :type subject: str.
        :param email_text: email text
        :type email_text: str.
        :raises: AAAException if smtp_server and/or sender are not set
        t   fqdns   SMTP server or sender not sett   alternativet   Subjectt   Fromt   Tos   utf-8t   htmls   Sending email using %st   targett   argsN(   RÖ   RÑ   R   R   R…   R§   R+   R   t   attacht	   as_stringRA   RB   RÓ   R	   t   _sendt   startRÔ   t   append(   R#   RW   Rt   Rw   t   msgt   partt   thread(    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRp   ‹  s"    

	
c         C   si  |  j  d } | d k s) t d | ƒ ‚ y| d k re t j d ƒ t |  j  d |  j  d ƒ } n t |  j  d |  j  d ƒ } | d k r¼ t j d	 ƒ | j ƒ  | j ƒ  | j ƒ  n  |  j  d
 d k	 rý t j d ƒ | j	 |  j  d
 |  j  d ƒ n  t j d ƒ | j
 |  j | | ƒ | j ƒ  t j d ƒ Wn* t k
 rd} t j d | d t ƒn Xd S(   s    Deliver an email using SMTP

        :param email_addr: recipient
        :type email_addr: str.
        :param msg: email text
        :type msg: str.
        R×   RØ   t   starttlst   ssls   Incorrect protocol: %ss   Setting up SSLRß   RÙ   s   Sending EHLO and STARTTLSRa   s   Performing logint   passt   Sendings
   Email sents   Error sending email: %st   exc_infoN(   s   smtps   starttlss   ssl(   RÖ   RZ   RA   RB   R   R   t   ehloRï   R!   R=   t   sendmailRÑ   t   quitt   infoR@   t   errorR5   (   R#   RW   Rì   R×   RD   RE   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyRé   ­  s,     

!
c         C   s&   g  |  j  D] } | j |  j ƒ ^ q
 S(   sd   Flush email queue by waiting the completion of the existing threads

        :returns: None
        (   RÔ   R¹   RÒ   (   R#   Rº   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR¹   Ò  s    c         C   s&   y |  j  ƒ  Wn t k
 r! n Xd S(   s@   Class destructor: wait for threads to terminate within a timeoutN(   R¹   R‡   (   R#   (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   __del__Ù  s    (	   R   R   R5   R)   RÕ   Rp   Ré   R¹   Rù   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyR   F  s   	5	"	%	(2   t   base64R    R   R   R   t   email.mime.multipartR   t   email.mime.textR   t   loggingR   t   smtplibR   R   t	   threadingR	   R
   Rn   R¨   Rž   RÚ   t   sysRk   t   version_infot   exitR—   R5   R   t   ImportErrorR6   t
   basestringt	   NameErrorR1   t   backendsR   t   majorR¯   R   RA   R@   R   R   t   objectR   Rg   RÆ   RÈ   RÉ   RÏ   R   (    (    (    s:   /home/fede/newhome/projects/bottle-cork/tests/cork/cork.pyt   <module>   sN   


ÿ ÿ ™G	