55
66import redis
77from flask import (
8- abort , Flask , render_template , request , jsonify , make_response
8+ abort , Flask , render_template , request , jsonify , make_response , Response , Request
99)
1010from redis .exceptions import ConnectionError
1111from urllib .parse import quote_plus , unquote_plus , urljoin , urlsplit
1212# _ is required to get the Jinja templates translated
13- from flask_babel import Babel , _ # noqa: F401
13+ from flask_babel import Babel , _ # type: ignore # noqa: F401
1414
1515_no_ssl_env = os .environ .get ('NO_SSL' , 'False' ).lower ()
1616NO_SSL : bool = _no_ssl_env in ('true' , '1' , 't' , 'y' , 'yes' )
@@ -40,12 +40,15 @@ def get_locale() -> typing.Optional[str]:
4040babel = Babel (app , locale_selector = get_locale )
4141
4242# Initialize Redis
43+ redis_client : redis .StrictRedis
4344if os .environ .get ('MOCK_REDIS' ):
4445 from fakeredis import FakeStrictRedis
4546
46- redis_client = FakeStrictRedis (version = (6 , 2 ), protocol = 2 )
47+ redis_client = FakeStrictRedis (version = (6 , 2 ), protocol = 2 ) # type: ignore
4748elif os .environ .get ('REDIS_URL' ):
48- redis_client = redis .StrictRedis .from_url (os .environ .get ('REDIS_URL' ))
49+ redis_url = os .environ .get ('REDIS_URL' )
50+ assert redis_url is not None
51+ redis_client = redis .StrictRedis .from_url (redis_url )
4952else :
5053 redis_host = os .environ .get ('REDIS_HOST' , 'localhost' )
5154 redis_port = int (os .environ .get ('REDIS_PORT' , 6379 ))
@@ -64,7 +67,7 @@ def get_locale() -> typing.Optional[str]:
6467MAX_TTL : int = DEFAULT_API_TTL
6568
6669
67- def _request_has_trusted_host (req : request ) -> bool :
70+ def _request_has_trusted_host (req : Request ) -> bool :
6871 # When HOST_OVERRIDE is not configured the base URL is derived from the
6972 # request's Host header, which a client can spoof. Only loopback hosts are
7073 # trusted for that fallback (local/dev use); production should set
@@ -94,12 +97,12 @@ def inner(*args: typing.Any, **kwargs: typing.Any) -> typing.Any:
9497
9598
9699def as_validation_problem (
97- request : request ,
100+ req : Request ,
98101 problem_type : str ,
99102 problem_title : str ,
100103 invalid_params : typing .List [typing .Dict [str , str ]]
101- ) -> make_response :
102- base_url = set_base_url (request )
104+ ) -> Response :
105+ base_url = set_base_url (req )
103106
104107 problem = {
105108 "type" : f"{ base_url } { problem_type } " ,
@@ -110,12 +113,12 @@ def as_validation_problem(
110113
111114
112115def as_not_found_problem (
113- request : request ,
116+ req : Request ,
114117 problem_type : str ,
115118 problem_title : str ,
116119 invalid_params : typing .List [typing .Dict [str , str ]]
117- ) -> make_response :
118- base_url = set_base_url (request )
120+ ) -> Response :
121+ base_url = set_base_url (req )
119122
120123 problem = {
121124 "type" : f"{ base_url } { problem_type } " ,
@@ -128,7 +131,7 @@ def as_not_found_problem(
128131def as_problem_response (
129132 problem : typing .Dict [str , typing .Any ],
130133 status_code : typing .Optional [int ] = None
131- ) -> make_response :
134+ ) -> Response :
132135 if not isinstance (status_code , int ) or not status_code :
133136 status_code = 400
134137
@@ -190,7 +193,7 @@ def clean_input() -> typing.Tuple[int, str]:
190193 return TIME_CONVERSION [time_period ], password
191194
192195
193- def set_base_url (req : request ) -> str :
196+ def set_base_url (req : Request ) -> str :
194197 scheme = 'http' if NO_SSL else 'https'
195198 if HOST_OVERRIDE :
196199 base_url = f'{ scheme } ://{ HOST_OVERRIDE } /'
@@ -206,12 +209,12 @@ def set_base_url(req: request) -> str:
206209
207210
208211@app .route ('/' , methods = ['GET' ])
209- def index ():
212+ def index () -> str :
210213 return render_template ('set_password.html' )
211214
212215
213216@app .route ('/' , methods = ['POST' ])
214- def handle_password ():
217+ def handle_password () -> typing . Union [ Response , str , typing . Tuple [ str , int ]] :
215218 password = request .form .get ('password' )
216219 ttl = request .form .get ('ttl' )
217220 if password and ttl and not empty (password ) and not empty (ttl ):
@@ -234,7 +237,7 @@ def handle_password():
234237
235238
236239@app .route ('/api/set_password/' , methods = ['POST' ])
237- def api_handle_password ():
240+ def api_handle_password () -> Response :
238241 password = request .json .get ('password' )
239242 ttl = int (request .json .get ('ttl' , DEFAULT_API_TTL ))
240243 if password and isinstance (ttl , int ) and ttl <= MAX_TTL :
@@ -247,7 +250,7 @@ def api_handle_password():
247250
248251
249252@app .route ('/api/v2/passwords' , methods = ['POST' ])
250- def api_v2_set_password ():
253+ def api_v2_set_password () -> Response :
251254 password = request .json .get ('password' )
252255 ttl = int (request .json .get ('ttl' , DEFAULT_API_TTL ))
253256
@@ -294,7 +297,7 @@ def api_v2_set_password():
294297
295298
296299@app .route ('/api/v2/passwords/<token>' , methods = ['HEAD' ])
297- def api_v2_check_password (token : str ):
300+ def api_v2_check_password (token : str ) -> typing . Tuple [ str , int ] :
298301 token = unquote_plus (token )
299302 if not password_exists (token ):
300303 # Return NotFound, to indicate that password does not exist
@@ -305,7 +308,7 @@ def api_v2_check_password(token: str):
305308
306309
307310@app .route ('/api/v2/passwords/<token>' , methods = ['GET' ])
308- def api_v2_retrieve_password (token : str ):
311+ def api_v2_retrieve_password (token : str ) -> Response :
309312 token = unquote_plus (token )
310313 password = get_password (token )
311314 if not password :
@@ -322,7 +325,7 @@ def api_v2_retrieve_password(token: str):
322325
323326
324327@app .route ('/<password_key>' , methods = ['GET' ])
325- def preview_password (password_key : str ):
328+ def preview_password (password_key : str ) -> typing . Union [ str , typing . Tuple [ str , int ]] :
326329 password_key = unquote_plus (password_key )
327330 if not password_exists (password_key ):
328331 return render_template ('expired.html' ), 404
@@ -331,7 +334,7 @@ def preview_password(password_key: str):
331334
332335
333336@app .route ('/<password_key>' , methods = ['POST' ])
334- def show_password (password_key : str ):
337+ def show_password (password_key : str ) -> typing . Union [ str , typing . Tuple [ str , int ]] :
335338 password_key = unquote_plus (password_key )
336339 password = get_password (password_key )
337340 if not password :
@@ -342,12 +345,12 @@ def show_password(password_key: str):
342345
343346@app .route ('/_/_/health' , methods = ['GET' ])
344347@check_redis_alive
345- def health_check ():
348+ def health_check () -> typing . Dict [ typing . Any , typing . Any ] :
346349 return {}
347350
348351
349352@check_redis_alive
350- def main ():
353+ def main () -> None :
351354 app .run (host = os .environ .get ('SNAPPASS_BIND_ADDRESS' , '0.0.0.0' ),
352355 port = int (os .environ .get ('SNAPPASS_PORT' , 5000 )))
353356
0 commit comments