U
    Enj                     @   s   d Z ddlZddlZddlmZmZ ddlmZ ddlZe  ee	dddZ
e	dZi Ze Ze Ze Zdd	d
ZdddZdd ZdS )a  
DB-backed secrets for the pipeline. Reads API keys/tokens from the `app_secret`
table (encrypted at rest) instead of the .env file, and reports auth/expiry
errors back onto the row so the admin panel can surface them.

Bootstrap: MYSQL_URI and SECRETS_ENC_KEY still come from .env (you can't store
the DB connection string inside the DB it connects to).

Migration-safe: if a key has no stored value yet (or the DB/decrypt fails),
get_secret() falls back to os.getenv(key) so nothing breaks mid-migration.
    N)create_enginetext)load_dotenv	MYSQL_URIT)pool_pre_pingZSECRETS_ENC_KEYc              
   C   s   |r0t " | tkr&t|  W  5 Q R  S W 5 Q R X d}zPt }|tdd| i }W 5 Q R X |r|d rtrt	|d t}W n6 t
k
r } ztd|  d|  W 5 d}~X Y nX |st| }t  |t| < W 5 Q R X |S )zReturn the secret value for `key` from the DB (decrypted), or fall back
    to the same-named .env variable if it isn't stored/decryptable yet.Nz9SELECT secret_value FROM app_secret WHERE secret_key = :kkr   z[SECRETS] DB read failed for : )_lock_cache_engineconnectexecuter   fetchone_ENC_KEYsecret_cryptodecrypt	Exceptionprintosgetenv)keyZ	use_cachevalueconnrowe r   M/var/www/api.dyntland.com/public_html/python_social_comments/secrets_store.py
get_secret    s(    
&
r   errorc              
   C   s   t 0 | tkrW 5 Q R  dS t|  t|  W 5 Q R X zbt *}|td|t	|dd | d W 5 Q R X t
d| d|  dt	|dd   W n6 tk
r } zt
d	|  d|  W 5 d}~X Y nX dS )
zRecord an auth/expiry failure against a key (shown in the admin panel).
    Fires at most once per key per process run to avoid hammering the DB.Nz
                UPDATE app_secret
                SET status = :s, last_error = :m, last_error_at = NOW()
                WHERE secret_key = :k
            i  )smr   z[SECRETS] Recorded z for r   x   z%[SECRETS] Could not record error for )r	   _reported_erroradd
_marked_okdiscardr   beginr   r   strr   r   )r   messagestatusr   r   r   r   r   report_secret_error<   s    


*r*   c              
   C   s   t . | tks| tkr$W 5 Q R  dS t|  W 5 Q R X z,t }|tdd| i W 5 Q R X W n6 tk
r } zt	d|  d|  W 5 d}~X Y nX dS )zAMark a key healthy after a successful call. Once per key per run.Nz
                UPDATE app_secret
                SET status = 'active', last_ok_at = NOW(),
                    last_error = NULL, last_error_at = NULL
                WHERE secret_key = :k
            r   z [SECRETS] Could not mark ok for r   )
r	   r$   r"   r#   r   r&   r   r   r   r   )r   r   r   r   r   r   mark_secret_okP   s    

r+   )T)r   )__doc__r   	threading
sqlalchemyr   r   dotenvr   r   r   r   r   r
   setr$   r"   Lockr	   r   r*   r+   r   r   r   r   <module>   s   


