o
    @h~0                     @   sn  d Z ddlZddlm  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mZ ddlmZ ddlmZ e
jdddd	 Ze
jddd
d Ze
jdddd Ze
jdddd Zdd Ze
jdddd Ze
jdddd Ze
jdddd Ze
jdddd Ze
jdddd Ze
jdddd Ze
jdddd Zd d! Ze
jddd"d# Z dS )$aH  
conftest.py

Purpose:
  Pytest configuration and fixtures for the automated testing system.
  Provides isolated test environments with in-memory databases, temporary
  directories, and pre-configured test users and clients.

Fixtures:
  - app: Flask application instance configured for testing
  - client: Flask test client for HTTP requests
  - db: In-memory SQLite database with test schema
  - temp_static: Temporary directory for image file testing
  - test_users: Pre-created test users with different permission levels
  - authenticated_clients: Pre-authenticated test clients
    N)Flask)
create_app)get_dbfunction)scopec            
      c   s   i } g d}|D ]
}t j|| |< q	t \}}t }t j|d}t j|dd |t jd< |t jd< dt jd< d	t jd
< dt jd< dt jd< dt jd< t	 }d|j
d< d|j
d< |  t  W d   n1 snw   Y  |V  |  ddlm} t|dr|j  t|d W d   n1 sw   Y  t | t | ddl}	|	j|dd |D ]}| | dur| | t j|< qt j|d qdS )z6Create and configure a Flask app instance for testing.)DATABASE_PATHUSER_PHOTOS_DIR_REAL
SECRET_KEYENABLE_HSTSzUser-photosT)exist_okr   r   z test-secret-key-for-testing-onlyr	   0r
   10000LOGIN_MAX_FAILS1LOGIN_WINDOW_SECONDSLOGIN_LOCK_SECONDSTESTINGFWTF_CSRF_ENABLEDNr   )g	_database)ignore_errors)osenvirongettempfilemkstempmkdtemppathjoinmakedirsr   configapp_contextinit_test_databaseflaskr   hasattrr   closedelattrunlinkshutilrmtreepop)
original_envenv_keyskeydb_fddb_pathtemp_statictemp_user_photosappr   r(    r3   /var/www/html/tests/conftest.pyr2      sN   















r2   c                 C   s   |   S )zCreate a Flask test client.)test_clientr2   r3   r3   r4   clientX   s   r7   c                 c   s8    |    t V  W d   dS 1 sw   Y  dS )z)Get database connection for the test app.N)r!   r   r6   r3   r3   r4   db^   s   

"r8   c                 C   s   t jdS )z$Get temporary static directory path.r   )r   r   r   r6   r3   r3   r4   r0   e   s   r0   c                  C   sx   t jd} t| }tj|_|d |d |d |d |d |d |d |  |	  d	S )
z6Initialize the test database with the required schema.r   z
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT UNIQUE NOT NULL,
            password_hash TEXT NOT NULL,
            is_admin BOOLEAN NOT NULL DEFAULT 0
        )
    a  
        CREATE TABLE IF NOT EXISTS cameras (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            camera_id INTEGER NOT NULL,
            camera_name TEXT NOT NULL,
            file_paths TEXT,
            added_to_map INTEGER DEFAULT 0,
            location TEXT,
            FOREIGN KEY (user_id) REFERENCES users (id)
        )
    a  
        CREATE TABLE IF NOT EXISTS markers (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            type TEXT NOT NULL,
            camera_id TEXT,
            latitude REAL NOT NULL,
            longitude REAL NOT NULL,
            added_to_map INTEGER DEFAULT 0,
            name TEXT,
            FOREIGN KEY (user_id) REFERENCES users (id)
        )
    a&  
        CREATE TABLE IF NOT EXISTS login_attempts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT NOT NULL,
            ip TEXT NOT NULL,
            fail_count INTEGER DEFAULT 0,
            last_failed_at INTEGER,
            locked_until INTEGER
        )
    z
        CREATE TABLE IF NOT EXISTS login_ip_attempts (
            ip TEXT PRIMARY KEY,
            fail_count INTEGER DEFAULT 0,
            last_failed_at INTEGER,
            locked_until INTEGER
        )
    aX  
        CREATE TABLE IF NOT EXISTS auth_log (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ts INTEGER NOT NULL,
            ip TEXT NOT NULL,
            user_id INTEGER,
            username TEXT,
            event TEXT NOT NULL,
            detail TEXT,
            FOREIGN KEY (user_id) REFERENCES users (id)
        )
    a  
        CREATE TABLE IF NOT EXISTS admin_audit (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ts INTEGER NOT NULL,
            ip TEXT NOT NULL,
            admin_user_id INTEGER NOT NULL,
            target_user_id INTEGER,
            action TEXT NOT NULL,
            detail TEXT,
            FOREIGN KEY (admin_user_id) REFERENCES users (id),
            FOREIGN KEY (target_user_id) REFERENCES users (id)
        )
    N)
r   r   r   sqlite3connectRowrow_factoryexecutecommitr%   )r/   r8   r3   r3   r4   r"   k   s   









r"   c                 C   s(  |    tjd}t|}tj|_i }t	d
dt d}|dd|df}|jdddd|d< t	d	
dt d}|dd
|df}|jd
d	dd|d< t	d
dt d}|dd|df}|jdddd|d< |  |  |W  d   S 1 sw   Y  dS )z3Create test users with different permission levels.r   testpass123zutf-8zFINSERT INTO users (username, password_hash, is_admin) VALUES (?, ?, ?)testuserF)idusernamepasswordis_adminregularadminpass123	testadminTadminlimitedpass123limiteduserlimitedN)r!   r   r   r   r9   r:   r;   r<   bcrypthashpwencodegensaltdecoder=   	lastrowidr>   r%   )r2   r/   r8   usersregular_password_hashcursoradmin_password_hashlimited_password_hashr3   r3   r4   
test_users   sN   




$rW   c                 C   (   |d }| j d|d |d dd | S )z5Create an authenticated test client for regular user.rE   /loginrB   rC   rB   rC   datapostr7   rW   userr3   r3   r4   authenticated_client_regular     
ra   c                 C   rX   )z3Create an authenticated test client for admin user.rH   rY   rB   rC   rZ   r[   r]   r_   r3   r3   r4   authenticated_client_admin  rb   rc   c                 C   rX   )z5Create an authenticated test client for limited user.rK   rY   rB   rC   rZ   r[   r]   r_   r3   r3   r4   authenticated_client_limited  rb   rd   c                   C   s.   dddddddddddddd	dd
S )z'Provide sample camera data for testing.123456789012zTest Camera 1)	camera_idcamera_name987654321098zTest Camera 212345zInvalid Camera12345678901a )validvalid_2invalid_short_idinvalid_non_numericinvalid_empty_namer3   r3   r3   r3   r4   sample_camera_data'  s    rq   c                   C   s   dddddddddS )	z&Provide sample image data for testing.z%PICT_20240101_120000_123456789012.jpgz
image/jpegs    JFIF  H H  )filenamecontent_typer\   z$IMG_20240101_130000_123456789012.pngz	image/pngs   PNG

   IHDR      )jpgpngr3   r3   r3   r3   r4   sample_image_dataB  s   rv   c                   C   s,   ddddddddd	d
dddddddS )z'Provide sample marker data for testing.camerare   g[?g͏F@g3@zTest Camera Marker)typerf   latitude	longitudenamefaunagDܜJF@gOY3@zWild Boar Sighting)rx   ry   rz   r{   	structureg-y<-?F@g>e3@zFeeding Station)camera_markerfauna_markerstructure_markerr3   r3   r3   r3   r4   sample_marker_dataS  s"   r   c                 C   sp   |   * tjd}t|}tj|_|d |d |	  |
  W d   dS 1 s1w   Y  dS )z,Helper function to clear rate limiting data.r   zDELETE FROM login_attemptszDELETE FROM login_ip_attemptsN)r!   r   r   r   r9   r:   r;   r<   r=   r>   r%   )r2   r/   r8   r3   r3   r4   clear_rate_limit_datam  s   




"r   c                 #   s(    t    fdd}|V  t   dS )z4Clear rate limiting data before and after each test.c                      s   t   d S )Nr   r3   r6   r3   r4   	clear_now  s   z$clear_rate_limits.<locals>.clear_nowNr   )r2   r   r3   r6   r4   clear_rate_limits{  s
   r   )!__doc__builtins@py_builtins_pytest.assertion.rewrite	assertionrewrite
@pytest_arr   r   r9   pytestrL   r#   r   app_modules.initializerr   app_modules.dbr   fixturer2   r7   r8   r0   r"   rW   ra   rc   rd   rq   rv   r   r   r   r3   r3   r3   r4   <module>   sF    "


;





e

5














