o
    ?hLI                     @   sN  d Z ddlZddlm  mZ ddlZddlZddl	m
Z
 ejjdd Zejjdd Zejjdd	 Zejjd
d Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjd d! Zejjd"d# Zejjd$d% ZdS )&a  
test_auth.py

Purpose:
  Comprehensive test suite for authentication functionality including login,
  logout, rate limiting, session management, and CSRF protection.

Test Categories:
  - Successful login with valid credentials
  - Failed login with invalid credentials  
  - Logout functionality and session clearing
  - Rate limiting enforcement per user and IP
  - Session management and security
    Nget_dbc                 C   s  |   }|d }|jd|d |d dd}|j}d}||k}|sUtd|fd	||fd
t v s6t|r;t|nd
t|t|d }	dd|	i }
t	t
|
d } }}|j}|j}d}||}|sdd
t v sut|rzt|nd
t|t|t|t|d }t	t
|d } } }}|d}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}dS )z=Test successful login with valid credentials via POST /login.regular/loginusernamepasswordr   r   data.  ==z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sresponsepy0py2py5assert %(py7)spy7N/selecthassert %(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.location
}.endswith
}(%(py6)s)
}r   r   py4py6py8   )test_clientpoststatus_code
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationlocationendswithget)app
test_usersclear_rate_limitsclientuserr   @py_assert1@py_assert4@py_assert3@py_format6@py_format8@py_assert5@py_assert7@py_format9 r8   +/var/www/html/tests/functional/test_auth.py'test_successful_login_valid_credentials   s   

r:   c                 C   s  |   }|jddddd}|j}d}||k}|sMtd|fd||fd	t v s.t|r3t|nd	t|t|d
 }dd|i }	t	t
|	d } }}|j}|j}d}
||
}|sdd	t v smt|rrt|nd	t|t|t|
t|d }t	t
|d } } }
}|d}|j}d}||k}|std|fd||fd	t v st|rt|nd	t|t|d
 }dd|i }	t	t
|	d } }}g }d}|j}||v }|}|sd}|j}||v }|}|s}td|fd||ft|d	t v st|rt|nd	t|d }	dd|	i }|| |shtd|fd||ft|d	t v sOt|rTt|nd	t|d }dd|i }|| t|di  }dd|i }t	t
|d } } } } } } }}dS ) z(Test failed login with invalid username.r   nonexistentuseranypasswordr   r	   r   r   r   r   r   r   r   N/r   r   r      Pogre   korisniinz,%(py3)s in %(py7)s
{%(py7)s = %(py5)s.data
}py3r   r   %(py9)spy9z0%(py12)s in %(py16)s
{%(py16)s = %(py14)s.data
}py12py14py16%(py18)spy18   assert %(py21)spy21r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r
   append_format_boolop)r+   r,   r-   r.   r   r0   r1   r2   r3   r4   r5   r6   r7   @py_assert2@py_assert6@py_assert0@py_assert11@py_assert15@py_assert13@py_format10@py_format17@py_format19@py_format20@py_format22r8   r8   r9   "test_failed_login_invalid_username,   s   

` r_   c                 C   s,  |   }|d }|jd|d ddd}|j}d}||k}|sStd|fd	||fd
t v s4t|r9t|nd
t|t|d }	dd|	i }
t	t
|
d } }}|j}|j}d}||}|sdd
t v sst|rxt|nd
t|t|t|t|d }t	t
|d } } }}|d}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}g }d}|j}||v }|}|sd}|j}||v }|}|std|fd||ft|d
t v st|r$t|nd
t|d }
dd|
i }|| |sotd|fd||ft|d
t v sVt|r[t|nd
t|d }dd|i }|| t|di  }dd |i }t	t
|d } } } } } } }}dS )!z(Test failed login with invalid password.limitedr   r   wrongpasswordr   r	   r   r   r   r   r   r   r   Nr=   r   r   r   r>   r?   r@   rB   rC   rE   rF   rG   rH   rL   rM   rN   rO   rP   rQ   )r+   r,   r-   r.   r/   r   r0   r1   r2   r3   r4   r5   r6   r7   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r8   r8   r9   "test_failed_login_invalid_passwordA   s   

b rb   c                 C   s0  |   }|jddddd}|j}d}||k}|sMtd|fd||fdt v s.t|r3t|ndt|t|d	 }d
d|i }t	t
|d } }}|j}|j}d}	||	}
|
sddt v smt|rrt|ndt|t|t|	t|
d }t	t
|d } } }	}
dS )z)Test failed login with empty credentials.r    r   r	   r   r   r   r   r   r   r   Nr=   r   r   )r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   )r+   r-   r.   r   r0   r1   r2   r3   r4   r5   r6   r7   r8   r8   r9   #test_failed_login_empty_credentialsW   s   
rd   c                 C   sL  |  |   }|d }|jd|d |d dd}|j}d}||k}|sXtd|fd	||fd
t v s9t|r>t|nd
t|t|d }	dd|	i }
t	t
|
d } }}|d}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}| }|dd}W d   n1 sw   Y  |jdd|id}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}|j}|j}d}||}|sOdd
t v s.t|r3t|nd
t|t|t|t|d }t	t
|d } } }}|d}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}dS )z@Test logout functionality via POST /logout and session clearing.adminr   r   r   r   r	   r   r   r   r   r   r   r   Nr   r   
csrf_tokenrc   /logoutr=   r   r   )r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r*   session_transactionr(   r)   )r+   r,   r-   r.   r/   r   r0   r1   r2   r3   r4   sessrf   r5   r6   r7   r8   r8   r9   test_logout_functionalityg   s$   



rj   c                 C   sR  |   }|d }|jd|d |d dd}|j}d}||k}|sUtd|fd	||fd
t v s6t|r;t|nd
t|t|d }	dd|	i }
t	t
|
d } }}|d}|j}ddg}||v }|std|fd||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}dS )z3Test that GET /logout is not supported (only POST).r   r   r   r   r   r	   r   r   r   r   r   r   r   Nrg   i  i  r@   )z3%(py2)s
{%(py2)s = %(py0)s.status_code
} in %(py5)s)r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r*   )r+   r,   r-   r.   r/   r   r0   r1   r2   r3   r4   r8   r8   r9   %test_logout_get_request_not_supported   s   

rk   c                 C   s  |  |   }ddl}ddlm} |  3 | }|dd| d}ddl	}dt
|	  }|d||df}	|  W d   n1 sKw   Y  |jd	|dd
d}
|
j}d}||k}|std|fd||fdt v szt|
rt|
ndt|t|d }dd|i }tt|d } }}tdD ]L}|d}
|
j}d}||k}|std|fd||fdt v st|
rt|
ndt|t|d }dd|i }tt|d } }}qdS )z7Test that session persists across requests after login.r   Nr   testpassutf-8sessionuser_FINSERT INTO users (username, password_hash, is_admin) VALUES (?, ?, ?)Fr   r   r	   r   r   r   r   r   r   r      r   r   )r   bcryptapp_modules.dbr   app_contexthashpwencodegensaltdecodetimeintexecutecommitr   r   r    r!   r"   r#   r$   r%   r&   r'   ranger*   )r+   r-   r.   rq   r   dbtest_password_hashrx   unique_usernamecursorr   r0   r1   r2   r3   r4   ir8   r8   r9   test_session_management   s0   



r   c                 C   s   |   }ddg}|D ]L}||}|j}d}||k}|sPtd|fd||fdt v s1t|r6t|ndt|t|d }	dd	|	i }
t	t
|
d
 } }}q
d
S )z5Test that protected endpoints require authentication.r   /dodaj-kamerur   r   r   r   r   r   r   N)r   r*   r   r    r!   r"   r#   r$   r%   r&   r'   )r+   r-   r.   protected_endpointsendpointr   r0   r1   r2   r3   r4   r8   r8   r9   /test_protected_endpoints_require_authentication   s   
r   c                 C   s$  |   }|d }|jd|d |d dd}|j}d}||k}|sUtd|fd	||fd
t v s6t|r;t|nd
t|t|d }	dd|	i }
t	t
|
d } }}|jdi d}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}| }|dd}W d   n1 sw   Y  |jdd|id}|j}d}||k}|s
td|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}dS )z(Test CSRF protection on logout endpoint.r   r   r   r   r   r	   r   r   r   r   r   r   r   Nrg     rf   rc   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   rh   r*   r+   r,   r-   r.   r/   r   r0   r1   r2   r3   r4   ri   rf   r8   r8   r9   test_csrf_protection_on_logout   s   

r   c                 C   s  |   }|d}|j}d}||k}|sHtd|fd||fdt v s)t|r.t|ndt|t|d }dd|i }t	t
|d	 } }}| }	|	d
}
d	}|
|u}|std|fd|
|fd
t v sut|
rzt|
nd
t|d }dd|i }t	t
|d	 }}t|
}d}||k}|std|fd||fdt v sttrttndd
t v st|
rt|
nd
t|t|d }dd|i }t	t
|d	 } }}W d	   d	S 1 sw   Y  d	S )z:Test that CSRF tokens are properly generated and injected.r=   r   r   r   r   r   r   r   Nrf   is notz%(py0)s is not %(py3)sr   rD   assert %(py5)sr      )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenr   py1rD   r   assert %(py8)sr   )r   r*   r   r    r!   r"   r#   r$   r%   r&   r'   rh   r   )r+   r-   r.   r   r0   r1   r2   r3   r4   ri   rf   rT   @py_format4r5   @py_format7r7   r8   r8   r9   test_csrf_token_generation   s   


x"r   c                 C   s  |   }|d }|jd|d |d dd}|j}d}||k}|sUtd|fd	||fd
t v s6t|r;t|nd
t|t|d }	dd|	i }
t	t
|
d } }}| }|dd}W d   n1 spw   Y  |jddddd}|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }	dd|	i }
t	t
|
d } }}dS )z9Test CSRF protection on various state-changing endpoints.re   r   r   r   r   r	   r   r   r   r   r   r   r   Nrf   rc   z/admin/add_usertestuser123testpass123r   r   r   r8   r8   r9   /test_csrf_protection_on_state_changing_requests  s   


r   c                 C   s  |   }|d }|   t }|d |  W d   n1 s#w   Y  |jd|d |d dd}|j}d	}||k}	|	sutd
|	fd||fdt	
 v sVt|r[t|ndt|t|d }
dd|
i }tt|d } }	}|   t }|dd|d f }t|}d}||k}|std
|fd||fdt	
 v sttrttnddt	
 v st|rt|ndt|t|d }dd|i }tt|d } }}|d }|d }|d }	||	k}|std
|fd||	ft|t|	d }dd|i }tt|d } }}	|d }d}	||	u}|sStd|fd ||	ft|t|	d }dd|i }tt|d } }}	|d! }d}	||	k}|std
|fd||	ft|t|	d }dd|i }tt|d } }}	W d   n	1 sw   Y  |   }|jd|d d"dd}|j}d	}||k}	|	std
|	fd||fdt	
 v st|rt|ndt|t|d }
dd|
i }tt|d } }	}|   t }|dd#|d f }t|}d}||k}|satd
|fd||fdt	
 v s/ttr4ttnddt	
 v sBt|rGt|ndt|t|d }dd|i }tt|d } }}|d }|d }|d }	||	k}|std
|fd||	ft|t|	d }dd|i }tt|d } }}	|d! }d#}	||	k}|std
|fd||	ft|t|	d }dd|i }tt|d } }}	W d   dS 1 sw   Y  dS )$z4Test that authentication events are properly logged.r`   zDELETE FROM auth_logNr   r   r   r   r	   r   r   r   r   r   r   r   z7SELECT * FROM auth_log WHERE event = ? AND username = ?login_successrN   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   logsr   r   r   r   )z%(py1)s == %(py4)sr   r   assert %(py6)sr   user_idr   )z%(py1)s is not %(py4)seventra   login_failure)r   rs   r   rz   r{   r   r   r    r!   r"   r#   r$   r%   r&   r'   fetchallr   )r+   r,   r-   r.   r/   r}   r   r0   r1   r2   r3   r4   r   rT   r5   r   r7   logrV   @py_format5client_2r8   r8   r9   !test_authentication_event_logging#  sV   




pln


pn$r   c                 C   s  |   }|d }|d}|j}d}||k}|sLtd|fd||fdt v s-t|r2t|ndt|t|d }	dd	|	i }
t	t
|
d
 } }}| }|dd}W d
   n1 sgw   Y  |jd|d |d dd}|j}d}||k}|std|fd||fdt v st|rt|ndt|t|d }	dd	|	i }
t	t
|
d
 } }}| J}|d}d
}||u}|std|fd||fdt v st|rt|ndt|d }dd|i }	t	t
|	d
 }}W d
   n	1 sw   Y  |d}|j}d}||k}|s]td|fd||fdt v s>t|rCt|ndt|t|d }	dd	|	i }
t	t
|
d
 } }}| N}|dd}d}||k}|std|fd||fdt v st|rt|ndt|d }dd|i }	t	t
|	d
 }}W d
   d
S 1 sw   Y  d
S )zFTest that session is regenerated on login to prevent session fixation.r   r=   r   r   r   r   r   r   r   Nrf   rc   r   r   r   r   r	   r   r   r   r   logged_in_user_idr   r   r   r   !=)z%(py0)s != %(py3)scsrf_token_after_login)r   r*   r   r    r!   r"   r#   r$   r%   r&   r'   rh   r   )r+   r,   r-   r.   r/   r   r0   r1   r2   r3   r4   ri   initial_csrf_tokenr   rT   r   r   r8   r8   r9   "test_session_regeneration_on_loginU  s,   




|

$r   c                 C   sx  |d }|   }|   }|jd|d |d dd}|j}d}||k}	|	sYtd|	fd	||fd
t v s:t|r?t|nd
t|t|d }
dd|
i }t	t
|d } }	}|jd|d |d dd}|j}d}||k}	|	std|	fd	||fdt v st|rt|ndt|t|d }
dd|
i }t	t
|d } }	}|d}|j}d}||k}	|	std|	fd	||fd
t v st|rt|nd
t|t|d }
dd|
i }t	t
|d } }	}|d}|j}d}||k}	|	sCtd|	fd	||fdt v s$t|r)t|ndt|t|d }
dd|
i }t	t
|d } }	}| }|dd}W d   n	1 s_w   Y  |jdd|id |d}|j}d}||k}	|	std|	fd	||fdt v st|rt|ndt|t|d }
dd|
i }t	t
|d } }	}dS )z@Test handling of multiple concurrent sessions for the same user.re   r   r   r   r   r	   r   r   r   	response1r   r   r   N	response2r   r   rf   rc   rg   )r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r*   rh   )r+   r,   r-   r/   client1client2r   r0   r1   r2   r3   r4   r   ri   csrf_token1r8   r8   r9   !test_multiple_concurrent_sessionsz  s.   





r   c              	   C   s*  |   }|d }|jd|d |d dd}|j}d}||k}|sUtd|fd	||fd
t v s6t|r;t|nd
t|t|d }	dd|	i }
t	t
|
d } }}ddg}|D ]}||}g }|j}d}||k}|}|s|j}|j}d}||}| }|}|std|fd||fd
t v st|rt|nd
t|t|d }
dd|
i }|| |sdd
t v st|rt|nd
t|t|t|t|d }|| t|di  }dd|i }t	t
|d } } } } } } } } }}qadS )zBTest that authenticated session persists across multiple requests.r`   r   r   r   r   r	   r   r   r   r   r   r   r   Nr   r   r=   r   )z3%(py4)s
{%(py4)s = %(py2)s.status_code
} != %(py7)s)r   r   r   rE   rF   zmnot %(py19)s
{%(py19)s = %(py15)s
{%(py15)s = %(py13)s
{%(py13)s = %(py11)s.location
}.endswith
}(%(py17)s)
})py11py13py15py17py19rN   zassert %(py23)spy23)r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r*   r(   r)   rR   rS   )r+   r,   r-   r.   r/   r   r0   r1   r2   r3   r4   protected_urlsurlrU   r5   rV   @py_assert12@py_assert14@py_assert16@py_assert18@py_assert20rZ   @py_format21r^   @py_format24r8   r8   r9   (test_session_persistence_across_requests  s   

X r   c                 C   s
  |   }ddl}ddlm} |  3 | }|dd| d}ddl	}dt
|	  }|d||df}	|  W d   n1 sHw   Y  td	D ]Q}
|jd
|ddd}|j}d}||k}|std|fd||fdt v s}t|rt|ndt|t|d }dd|i }tt|d } }}qQ|  T | }|d|f }|r|d }d	}||k}|std|fd||ft|t|d }dd|i }tt|d } }}W d   dS W d   dS 1 sw   Y  dS )z6Test comprehensive rate limiting enforcement per user.r   Nr   rl   rm   ratelimituser_ro   F   r   ra   r   r	   r   r   r   r   r   r   r   z8SELECT fail_count FROM login_attempts WHERE username = ?
fail_count>=)z%(py1)s >= %(py4)sr   r   r   )r   rq   rr   r   rs   rt   ru   rv   rw   rx   ry   rz   r{   r|   r   r   r    r!   r"   r#   r$   r%   r&   r'   fetchone)r+   r-   r.   rq   r   r}   r~   rx   r   r   r   r   r0   r1   r2   r3   r4   attemptsrV   rT   r   r   r8   r8   r9   )test_rate_limiting_per_user_comprehensive  sB   



l"r   c                  C   s@  |   }ddl}ddlm} ddl}|  @ | }|dd| 	d}g }t
dD ]}	dt|  d|	 }
|d	|
|d
f}||
 q.|  W d   n1 sYw   Y  g }|D ](}t
dD ]}|jd|ddd}||j |jdkr nqh|d dkr nqbg }d}||v }|}|sd}||v }|}|std|fd||ft|dt v st|rt|ndd }dd|i }|| |std|fd||ft|dt v st|rt|ndd }dd|i }|| t|di  }dd|i }tt|d } } } } }}|  o | }|d }t|}d}||k}|std |fd!||fd"t v sUttrZttnd"d#t v sht|rmt|nd#t|t|d$ }d%d&|i }tt|d } }}W d   dS 1 sw   Y  dS )'z.Test rate limiting enforcement per IP address.r   Nr   rl   rm   rp   ipuser__ro   Fr   ra   r   r	   i  r   r@   )z%(py3)s in %(py5)s	responses)rD   r   z%(py7)sr   )z%(py10)s in %(py12)s)py10rI   z%(py14)srJ   rN   zassert %(py17)sr   zSELECT * FROM login_ip_attemptsr   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr   ip_attemptsr   r   r   )r   rq   rr   r   rx   rs   rt   ru   rv   rw   r|   ry   rz   rR   r{   r   r   r    r!   r%   r"   r#   r$   rS   r&   r'   r   r   ) r+   r-   r.   rq   r   rx   r}   r~   usersr   r   r   r   r   jr   r0   rT   r1   rV   @py_assert9rW   r3   r4   @py_format13@py_format15@py_format16@py_format18r   r5   r   r7   r8   r8   r9   test_rate_limiting_per_ip  sL   



0 
$r   )__doc__builtinsr"   _pytest.assertion.rewrite	assertionrewriter    pytestrx   rr   r   markauthr:   r_   rb   rd   rj   rk   r   r   r   r   r   r   r   r   r   r   r   r8   r8   r8   r9   <module>   sL    "




%

%




1
$
(

,