o
    ãË·eA  ã                   @   s„   d 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„ Z	G dd	„ d	eƒZ
G d
d„ de
ƒZG dd„ de
ƒZG dd„ de
ƒZdS )a.  
This module contains C{L{OpenIDStore}} implementations that use
various SQL databases to back them.

Example of how to initialize a store database::

python -c 'from openid.store import sqlstore; import pysqlite2.dbapi2;'
  'sqlstore.SQLiteStore(pysqlite2.dbapi2.connect("cstore.db")).createTables()'
é    N)ÚAssociation)ÚOpenIDStore)Únoncec                    sT   ‡ fdd„}t ˆ dƒrz
ˆ jdd … |_W n	 ty   Y nw t ˆ dƒr(ˆ j|_|S )Nc                    s   | j ˆ | g|¢R i |¤ŽS ©N)Ú_callInTransaction)ÚselfÚargsÚkwargs©Úfunc© úL/var/www/ideatree/venv/lib/python3.10/site-packages/openid/store/sqlstore.pyÚwrapped   s   z_inTxn.<locals>.wrappedÚ__name__é   Ú__doc__)Úhasattrr   Ú	TypeErrorr   )r   r   r   r
   r   Ú_inTxn   s   
ÿ
r   c                   @   sÄ   e Zd ZdZdZdZd!dd„Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZeeƒZdd„ ZeeƒZd"dd„ZeeƒZdd„ ZeeƒZdd„ ZeeƒZdd„ ZeeƒZdd „ ZeeƒZdS )#ÚSQLStoreaŒ  
    This is the parent class for the SQL stores, which contains the
    logic common to all of the SQL stores.

    The table names used are determined by the class variables
    C{L{associations_table}} and
    C{L{nonces_table}}.  To change the name of the tables used, pass
    new table names into the constructor.

    To create the tables with the proper schema, see the
    C{L{createTables}} method.

    This class shouldn't be used directly.  Use one of its subclasses
    instead, as those contain the code necessary to use a specific
    database.

    All methods other than C{L{__init__}} and C{L{createTables}}
    should be considered implementation details.


    @cvar associations_table: This is the default name of the table to
        keep associations in

    @cvar nonces_table: This is the default name of the table to keep
        nonces in.


    @sort: __init__, createTables
    Úoid_associationsÚ
oid_noncesNc                 C   st   || _ d| _i | _|p| j|p| jdœ| _d| _t| j dƒr(t| j dƒr(| j | _t| jdƒr4t| jdƒs8t	dƒ‚dS )a¸  
        This creates a new SQLStore instance.  It requires an
        established database connection be given to it, and it allows
        overriding the default table names.


        @param conn: This must be an established connection to a
            database of the correct type for the SQLStore subclass
            you're using.

        @type conn: A python database API compatible connection
            object.


        @param associations_table: This is an optional parameter to
            specify the name of the table used for storing
            associations.  The default value is specified in
            C{L{SQLStore.associations_table}}.

        @type associations_table: C{str}


        @param nonces_table: This is an optional parameter to specify
            the name of the table used for storing nonces.  The
            default value is specified in C{L{SQLStore.nonces_table}}.

        @type nonces_table: C{str}
        N)ÚassociationsÚnoncesi`T  ÚIntegrityErrorÚOperationalErrorzDError using database connection module (Maybe it can't be imported?))
ÚconnÚcurÚ_statement_cacheÚassociations_tableÚnonces_tableÚ_table_namesÚmax_nonce_ager   Ú
exceptionsÚRuntimeError)r   r   r   r    r   r   r   Ú__init__D   s    þ
ÿ
ÿþzSQLStore.__init__c                 C   ó   |S )zSConvert a blob as returned by the SQL engine into a str object.

        str -> strr   ©r   Úblobr   r   r   Ú
blobDecodev   s   zSQLStore.blobDecodec                 C   r&   )z]Convert a str object into the necessary object for storing
        in the database as a blob.r   ©r   Úsr   r   r   Ú
blobEncode|   s   zSQLStore.blobEncodec                 C   sB   z| j | W S  ty    t| |ƒ}|| j; }|| j |< | Y S w r   )r   ÚKeyErrorÚgetattrr!   )r   Úsql_nameÚsqlr   r   r   Ú_getSQL   s   


üzSQLStore._getSQLc                 G   s2   |   |¡}dd„ }tt||ƒƒ}| j ||¡ d S )Nc                 S   s   t | tƒr	t| ƒS | S r   )Ú
isinstanceÚstr)Úargr   r   r   Úunicode_to_str‘   s   
z)SQLStore._execSQL.<locals>.unicode_to_str)r1   ÚlistÚmapr   Úexecute)r   r/   r   r0   r5   Ústr_argsr   r   r   Ú_execSQLŠ   s   
zSQLStore._execSQLc                    sL   |d d… dkr|dd … d ‰‡ ‡fdd„}t ˆ ||ƒ |S td|f ƒ‚)Né   Údb_Ú_sqlc                     s   ˆ j ˆg| ¢R Ž S r   )r:   )r   ©r   r/   r   r   r   ¡   s   z"SQLStore.__getattr__.<locals>.funczAttribute %r not found)ÚsetattrÚAttributeError)r   Úattrr   r   r>   r   Ú__getattr__š   s   zSQLStore.__getattr__c                 O   sr   | j  ¡  z#| j  ¡ | _z||i |¤Ž}W | j ¡  d| _n	| j ¡  d| _w W n	   | j  ¡  ‚ | j  ¡  |S )z­Execute the given function inside of a transaction, with an
        open cursor. If no exception is raised, the transaction is
        comitted, otherwise it is rolled back.N)r   ÚrollbackÚcursorr   ÚcloseÚcommit)r   r   r   r	   Úretr   r   r   r   ©   s   


ÿ

zSQLStore._callInTransactionc                 C   s   |   ¡  |  ¡  dS )z¡
        This method creates the database tables necessary for this
        store to work.  It should not be called if the tables already
        exist.
        N)Údb_create_nonceÚdb_create_assoc©r   r   r   r   Útxn_createTables¿   s   zSQLStore.txn_createTablesc                 C   s,   |}|   ||j|  |j¡|j|j|j¡ dS )zQSet the association for the server URL.

        Association -> NoneType
        N)Údb_set_assocÚhandler,   ÚsecretÚissuedÚlifetimeÚ
assoc_type)r   Ú
server_urlÚassociationÚar   r   r   Útxn_storeAssociationÊ   s
   
þzSQLStore.txn_storeAssociationc                 C   s°   |dur|   ||¡ n|  |¡ | j ¡ }t|ƒdkrdS g }|D ](}t|ƒ}|  |d ¡|d< t|Ž }|jdkrA|  	||j
¡ q!| |j|f¡ q!|rV| ¡  |d d S dS )zŠGet the most recent association that has been set for this
        server URL and handle.

        str -> NoneType or Association
        Nr   é   éÿÿÿÿ)Údb_get_assocÚdb_get_assocsr   ÚfetchallÚlenr6   r)   r   Ú	expiresInÚtxn_removeAssociationrM   ÚappendrO   Úsort)r   rR   rM   Úrowsr   ÚvaluesÚassocr   r   r   Útxn_getAssociationÖ   s$   


zSQLStore.txn_getAssociationc                 C   s   |   ||¡ | jjdkS )zšRemove the association for the given server URL and handle,
        returning whether the association existed at all.

        (str, str) -> bool
        r   )Údb_remove_assocr   Úrowcount)r   rR   rM   r   r   r   r]   ÷   s   zSQLStore.txn_removeAssociationc                 C   sH   t |t ¡  ƒtjkrdS z
|  |||¡ W dS  | jjy#   Y dS w )zmReturn whether this nonce is present, and if it is, then
        remove it from the set.

        str -> boolFT)ÚabsÚtimer   ÚSKEWÚdb_add_noncer#   r   )r   rR   Ú	timestampÚsaltr   r   r   Útxn_useNonce  s   ûþzSQLStore.txn_useNoncec                 C   s    |   tt ¡ ƒtj ¡ | jjS r   )Údb_clean_nonceÚintrg   r   rh   r   re   rJ   r   r   r   Útxn_cleanupNonces  s   zSQLStore.txn_cleanupNoncesc                 C   s   |   tt ¡ ƒ¡ | jjS r   )Údb_clean_assocrn   rg   r   re   rJ   r   r   r   Útxn_cleanupAssociations  s   z SQLStore.txn_cleanupAssociations)NNr   )r   Ú
__module__Ú__qualname__r   r   r    r%   r)   r,   r1   r:   rB   r   rK   r   ÚcreateTablesrU   ÚstoreAssociationrc   ÚgetAssociationr]   ÚremoveAssociationrl   ÚuseNoncero   ÚcleanupNoncesrq   ÚcleanupAssociationsr   r   r   r   r   "   s2    
2		

	r   c                       sP   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdd„ Z‡ fdd„Z‡  ZS )ÚSQLiteStorez÷
    This is an SQLite-based specialization of C{L{SQLStore}}.

    To create an instance, see C{L{SQLStore.__init__}}.  To create the
    tables it will use, see C{L{SQLStore.createTables}}.

    All other methods are implementation details.
    z¤
    CREATE TABLE %(nonces)s (
        server_url VARCHAR,
        timestamp INTEGER,
        salt CHAR(40),
        UNIQUE(server_url, timestamp, salt)
    );
    a  
    CREATE TABLE %(associations)s
    (
        server_url VARCHAR(2047),
        handle VARCHAR(255),
        secret BLOB(128),
        issued INTEGER,
        lifetime INTEGER,
        assoc_type VARCHAR(64),
        PRIMARY KEY (server_url, handle)
    );
    z}INSERT OR REPLACE INTO %(associations)s (server_url, handle, secret, issued, lifetime, assoc_type) VALUES (?, ?, ?, ?, ?, ?);z_SELECT handle, secret, issued, lifetime, assoc_type FROM %(associations)s WHERE server_url = ?;znSELECT handle, secret, issued, lifetime, assoc_type FROM %(associations)s WHERE server_url = ? AND handle = ?;zDSELECT server_url FROM %(associations)s WHERE issued + lifetime < ?;zADELETE FROM %(associations)s WHERE server_url = ? AND handle = ?;z9DELETE FROM %(associations)s WHERE issued + lifetime < ?;z(INSERT INTO %(nonces)s VALUES (?, ?, ?);z+DELETE FROM %(nonces)s WHERE timestamp < ?;c                 C   s   t |ƒS r   )Ú
memoryviewr*   r   r   r   r,   X  ó   zSQLiteStore.blobEncodec              
      sV   zt t| ƒj|i |¤ŽW S  | jjy* } zt dt|ƒ¡r%W Y d }~dS ‚ d }~ww )Nz^columns .* are not unique$F)Úsuperr{   rx   r#   r   ÚreÚmatchr3   )r   r   r	   Úwhy©Ú	__class__r   r   rx   [  s   €üzSQLiteStore.useNonce)r   rr   rs   r   Úcreate_nonce_sqlÚcreate_assoc_sqlÚset_assoc_sqlÚget_assocs_sqlÚget_assoc_sqlÚget_expired_sqlÚremove_assoc_sqlÚclean_assoc_sqlÚadd_nonce_sqlÚclean_nonce_sqlr,   rx   Ú__classcell__r   r   r‚   r   r{   "  s    		ÿr{   c                   @   s\   e Zd ZdZzddlZW n ey   dZY nw dZdZdZ	dZ
dZd	Zd
ZdZdZdZdS )Ú
MySQLStorea&  
    This is a MySQL-based specialization of C{L{SQLStore}}.

    Uses InnoDB tables for transaction support.

    To create an instance, see C{L{SQLStore.__init__}}.  To create the
    tables it will use, see C{L{SQLStore.createTables}}.

    All other methods are implementation details.
    r   NzÙ
    CREATE TABLE %(nonces)s (
        server_url BLOB NOT NULL,
        timestamp INTEGER NOT NULL,
        salt CHAR(40) NOT NULL,
        PRIMARY KEY (server_url(255), timestamp, salt)
    )
    ENGINE=InnoDB;
    aG  
    CREATE TABLE %(associations)s
    (
        server_url BLOB NOT NULL,
        handle VARCHAR(255) NOT NULL,
        secret BLOB NOT NULL,
        issued INTEGER NOT NULL,
        lifetime INTEGER NOT NULL,
        assoc_type VARCHAR(64) NOT NULL,
        PRIMARY KEY (server_url(255), handle)
    )
    ENGINE=InnoDB;
    zDREPLACE INTO %(associations)s VALUES (%%s, %%s, %%s, %%s, %%s, %%s);úaSELECT handle, secret, issued, lifetime, assoc_type FROM %(associations)s WHERE server_url = %%s;úFSELECT server_url FROM %(associations)s WHERE issued + lifetime < %%s;úrSELECT handle, secret, issued, lifetime, assoc_type FROM %(associations)s WHERE server_url = %%s AND handle = %%s;úEDELETE FROM %(associations)s WHERE server_url = %%s AND handle = %%s;ú;DELETE FROM %(associations)s WHERE issued + lifetime < %%s;ú.INSERT INTO %(nonces)s VALUES (%%s, %%s, %%s);ú-DELETE FROM %(nonces)s WHERE timestamp < %%s;)r   rr   rs   r   ÚMySQLdbr#   ÚImportErrorr„   r…   r†   r‡   r‰   rˆ   rŠ   r‹   rŒ   r   r   r   r   r   r   h  s$    ÿ
ÿr   c                   @   sŒ   e Zd ZdZzddlZW n ey   ddlmZ e ¡  Y nw dZ	dZ
dZdd„ Zd	Zd
ZdZdZdZdZdZdZdZdd„ Zdd„ ZdS )ÚPostgreSQLStorezú
    This is a PostgreSQL-based specialization of C{L{SQLStore}}.

    To create an instance, see C{L{SQLStore.__init__}}.  To create the
    tables it will use, see C{L{SQLStore.createTables}}.

    All other methods are implementation details.
    r   N)ÚcompatzË
    CREATE TABLE %(nonces)s (
        server_url VARCHAR(2047) NOT NULL,
        timestamp INTEGER NOT NULL,
        salt CHAR(40) NOT NULL,
        PRIMARY KEY (server_url, timestamp, salt)
    );
    a…  
    CREATE TABLE %(associations)s
    (
        server_url VARCHAR(2047) NOT NULL,
        handle VARCHAR(255) NOT NULL,
        secret BYTEA NOT NULL,
        issued INTEGER NOT NULL,
        lifetime INTEGER NOT NULL,
        assoc_type VARCHAR(64) NOT NULL,
        PRIMARY KEY (server_url, handle),
        CONSTRAINT secret_length_constraint CHECK (LENGTH(secret) <= 128)
    );
    c           	      C   sF   |   ||¡}| j ¡ }t|ƒr|  ||||||¡S |  ||||||¡S )z¥
        Set an association.  This is implemented as a method because
        REPLACE INTO is not supported by PostgreSQL (and is not
        standard SQL).
        )rX   r   rZ   r[   Údb_update_assocÚdb_new_assoc)	r   rR   rM   rN   rO   rP   rQ   Úresultr`   r   r   r   rL   Î  s   
ÿÿzPostgreSQLStore.db_set_assoczCINSERT INTO %(associations)s VALUES (%%s, %%s, %%s, %%s, %%s, %%s);zUPDATE %(associations)s SET secret = %%s, issued = %%s, lifetime = %%s, assoc_type = %%s WHERE server_url = %%s AND handle = %%s;r   r‘   r’   r“   r”   r•   r–   c                 C   s   ddl m} ||ƒS )Nr   )ÚBinary)Úpsycopg2rž   )r   r(   rž   r   r   r   r,   ø  s   zPostgreSQLStore.blobEncodec                 C   s   |  ¡ S r   )Útobytesr'   r   r   r   r)   ý  r}   zPostgreSQLStore.blobDecode)r   rr   rs   r   rŸ   r˜   Úpsycopg2cffirš   Úregisterr#   r„   r…   rL   Únew_assoc_sqlÚupdate_assoc_sqlr‡   r‰   rˆ   rŠ   r‹   rŒ   r   r,   r)   r   r   r   r   r™   ¥  s0    	þ	ÿr™   )r   r   rg   Úopenid.associationr   Úopenid.store.interfacer   Úopenid.storer   r   r   r{   r   r™   r   r   r   r   Ú<module>   s    	  F=