@@ -49,14 +49,6 @@ class ResetPasswordBody(InputSchema):
4949 email : str
5050
5151
52- def _get_request_context (request : web .Request ) -> dict [str , str ]:
53- return {
54- "request.remote" : f"{ request .remote } " ,
55- "request.method" : f"{ request .method } " ,
56- "request.path" : f"{ request .path } " ,
57- }
58-
59-
6052@routes .post (f"/{ API_VTAG } /auth/reset-password" , name = "initiate_reset_password" )
6153@global_rate_limit_route (number_of_requests = 10 , interval_seconds = HOUR )
6254async def initiate_reset_password (request : web .Request ):
@@ -80,27 +72,50 @@ async def initiate_reset_password(request: web.Request):
8072
8173 request_body = await parse_request_body_as (ResetPasswordBody , request )
8274
75+ _error_msg_prefix = "Password reset initiated"
76+
77+ def _get_error_context (
78+ user = None ,
79+ ) -> dict [str , str ]:
80+ ctx = {
81+ "user_email" : request_body .email ,
82+ "product_name" : product .name ,
83+ "request.remote" : f"{ request .remote } " ,
84+ "request.method" : f"{ request .method } " ,
85+ "request.path" : f"{ request .path } " ,
86+ }
87+
88+ if user :
89+ ctx .update (
90+ {
91+ "user_email" : request_body .email ,
92+ "user_id" : user ["id" ],
93+ "user_status" : user ["status" ],
94+ "user_role" : user ["role" ],
95+ }
96+ )
97+ return ctx
98+
8399 # NOTE: Always same response: never want to confirm or deny the existence of an account
84100 # with a given email or username.
85101 initiated_response = flash_response (
86102 MSG_EMAIL_SENT .format (email = request_body .email ), "INFO"
87103 )
104+
88105 # CHECK user exists
89106 user = await db .get_user ({"email" : request_body .email })
90107 if not user :
91108 _logger .warning (
92109 ** create_troubleshotting_log_kwargs (
93- "Password reset initiated for non-existent email. Ignoring request." ,
110+ "{_error_msg_prefix} for non-existent email. Ignoring request." ,
94111 error = Exception ("No user found with this email" ),
95- error_context = {
96- "user_email" : request_body .email ,
97- "product_name" : product .name ,
98- ** _get_request_context (request ),
99- },
112+ error_context = _get_error_context (),
100113 )
101114 )
102115 return initiated_response
103116
117+ assert user ["email" ] == request_body .email # nosec
118+
104119 # CHECK user state
105120 try :
106121 validate_user_status (user = dict (user ), support_email = product .support_email )
@@ -109,20 +124,14 @@ async def initiate_reset_password(request: web.Request):
109124 # do not want to forward but rather log due to the special rules in this entrypoint
110125 _logger .warning (
111126 ** create_troubleshotting_log_kwargs (
112- "Password reset initiated for invalid user. Ignoring request." ,
127+ f" { _error_msg_prefix } for invalid user. Ignoring request." ,
113128 error = err ,
114- error_context = {
115- "user_id" : user ["id" ],
116- "user" : user ,
117- "product_name" : product .name ,
118- ** _get_request_context (request ),
119- },
129+ error_context = _get_error_context (user ),
120130 )
121131 )
122132 return initiated_response
123133
124134 assert user ["status" ] == ACTIVE # nosec
125- assert user ["email" ] == request_body .email # nosec
126135 assert isinstance (user ["id" ], int ) # nosec
127136
128137 # CHECK access to product
@@ -131,14 +140,9 @@ async def initiate_reset_password(request: web.Request):
131140 ):
132141 _logger .warning (
133142 ** create_troubleshotting_log_kwargs (
134- "Password reset initiated for a user with NO access to this product. Ignoring request." ,
143+ f" { _error_msg_prefix } for a user with NO access to this product. Ignoring request." ,
135144 error = Exception ("User cannot access this product" ),
136- error_context = {
137- "user_id" : user ["id" ],
138- "user" : user ,
139- "product_name" : product .name ,
140- ** _get_request_context (request ),
141- },
145+ error_context = _get_error_context (user ),
142146 )
143147 )
144148 return initiated_response
@@ -169,11 +173,7 @@ async def initiate_reset_password(request: web.Request):
169173 ** create_troubleshotting_log_kwargs (
170174 "Unable to send email" ,
171175 error = err ,
172- error_context = {
173- "product_name" : product .name ,
174- "user_id" : user ["id" ],
175- ** _get_request_context (request ),
176- },
176+ error_context = _get_error_context (user ),
177177 )
178178 )
179179 raise web .HTTPServiceUnavailable (reason = MSG_CANT_SEND_MAIL ) from err
0 commit comments