55
66import requests
77
8- from odoo .exceptions import AccessError
8+ from odoo .exceptions import AccessError , UserError , ValidationError
99
1010from odoo .addons .fastapi .tests .common import FastAPITransactionCase
1111
@@ -26,6 +26,22 @@ def setUpClass(cls):
2626 cls .endpoint .captcha_secret_key = "test_secret"
2727 cls .default_fastapi_app = cls .endpoint ._get_app ()
2828
29+ def test_no_secret_key (self ):
30+ self .endpoint .captcha_secret_key = False
31+ with self ._create_test_client () as test_client :
32+ with self .assertRaisesRegex (
33+ UserError ,
34+ "No secret key found for this endpoint" ,
35+ ):
36+ test_client .get ("/demo/" , headers = {"X-Captcha-Token" : "valid" })
37+
38+ def test_invalid_regex (self ):
39+ with self .assertRaisesRegex (
40+ ValidationError ,
41+ r"Invalid regex for captcha routes: /route/\( " ,
42+ ):
43+ self .endpoint .captcha_routes_regex = r"/route/("
44+
2945 def test_missing_header (self ):
3046 with self ._create_test_client () as test_client :
3147 with self .assertRaisesRegex (
@@ -95,6 +111,7 @@ def test_valid_header_recaptcha(self):
95111
96112 def test_invalid_header_hcaptcha (self ):
97113 self .endpoint .captcha_type = "hcaptcha"
114+ self .endpoint .captcha_minimum_score = 0.8
98115 with patch (
99116 "odoo.addons.fastapi_captcha.models.fastapi_endpoint.requests.post" ,
100117 return_value = requests .Response (),
@@ -120,6 +137,7 @@ def test_invalid_header_hcaptcha(self):
120137
121138 def test_valid_header_hcaptcha (self ):
122139 self .endpoint .captcha_type = "hcaptcha"
140+ self .endpoint .captcha_minimum_score = 0.8
123141 with patch (
124142 "odoo.addons.fastapi_captcha.models.fastapi_endpoint.requests.post" ,
125143 return_value = requests .Response (),
@@ -149,6 +167,132 @@ def test_valid_header_hcaptcha(self):
149167 },
150168 )
151169
170+ def test_valid_header_low_score_hcaptcha (self ):
171+ self .endpoint .captcha_type = "hcaptcha"
172+ self .endpoint .captcha_minimum_score = 0.8
173+ with patch (
174+ "odoo.addons.fastapi_captcha.models.fastapi_endpoint.requests.post" ,
175+ return_value = requests .Response (),
176+ ) as mock_post :
177+ mock_post .return_value .status_code = 200
178+ mock_post .return_value .json = lambda : {
179+ "success" : True ,
180+ "score" : 0.6 ,
181+ "score_reason" : "low-confidence" ,
182+ }
183+ with self ._create_test_client () as test_client :
184+ with self .assertRaisesRegex (
185+ AccessError ,
186+ r"Hcaptcha validation failed: score 0.6 < 0.8 \(low-confidence\)" ,
187+ ):
188+ test_client .get ("/demo/" , headers = {"X-Captcha-Token" : "valid" })
189+
190+ def test_invalid_header_altcha (self ):
191+ self .endpoint .captcha_type = "altcha"
192+ with patch (
193+ "odoo.addons.fastapi_captcha.models.fastapi_endpoint.requests.post" ,
194+ return_value = requests .Response (),
195+ ) as mock_post :
196+ mock_post .return_value .status_code = 200
197+ mock_post .return_value .json = lambda : {
198+ "verified" : False ,
199+ "error" : "invalid-input-response" ,
200+ }
201+ with self ._create_test_client () as test_client :
202+ with self .assertRaisesRegex (
203+ AccessError ,
204+ r"Altcha \(https://eu.altcha.org/api/v1/challenge/verify\) "
205+ "validation failed: invalid-input-response" ,
206+ ):
207+ test_client .get ("/demo/" , headers = {"X-Captcha-Token" : "invalid" })
208+
209+ self .assertGreaterEqual (mock_post .call_count , 1 )
210+ self .assertEqual (
211+ mock_post .call_args .args [0 ],
212+ "https://eu.altcha.org/api/v1/challenge/verify" ,
213+ )
214+
215+ with self .assertRaisesRegex (
216+ AccessError ,
217+ r"Altcha \(https://eu.altcha.org/api/v1/challenge/verify\) "
218+ "validation failed: invalid-input-response" ,
219+ ):
220+ test_client .get (
221+ "/demo/who_ami" , headers = {"X-Captcha-Token" : "invalid" }
222+ )
223+
224+ def test_valid_header_altcha (self ):
225+ self .endpoint .captcha_type = "altcha"
226+ with patch (
227+ "odoo.addons.fastapi_captcha.models.fastapi_endpoint.requests.post" ,
228+ return_value = requests .Response (),
229+ ) as mock_post :
230+ mock_post .return_value .status_code = 200
231+ mock_post .return_value .json = lambda : {
232+ "verified" : True ,
233+ }
234+ with self ._create_test_client () as test_client :
235+ response = test_client .get (
236+ "/demo/" , headers = {"X-Captcha-Token" : "valid" }
237+ )
238+ self .assertEqual (response .status_code , status .HTTP_200_OK )
239+ self .assertEqual (response .json (), {"Hello" : "World" })
240+
241+ self .assertGreaterEqual (mock_post .call_count , 1 )
242+ self .assertEqual (
243+ mock_post .call_args .args [0 ],
244+ "https://eu.altcha.org/api/v1/challenge/verify" ,
245+ )
246+ response = test_client .get (
247+ "/demo/who_ami" , headers = {"X-Captcha-Token" : "valid" }
248+ )
249+ self .assertEqual (response .status_code , status .HTTP_200_OK )
250+ partner = self .default_fastapi_authenticated_partner
251+ self .assertDictEqual (
252+ response .json (),
253+ {
254+ "name" : partner .name ,
255+ "display_name" : partner .display_name ,
256+ },
257+ )
258+
259+ def test_valid_header_custom_url_altcha (self ):
260+ self .endpoint .captcha_type = "altcha"
261+ self .endpoint .captcha_custom_verify_url = "https://custom.exemple.org/verify"
262+
263+ with patch (
264+ "odoo.addons.fastapi_captcha.models.fastapi_endpoint.requests.post" ,
265+ return_value = requests .Response (),
266+ ) as mock_post :
267+ mock_post .return_value .status_code = 200
268+ mock_post .return_value .json = lambda : {
269+ "verified" : True ,
270+ }
271+ with self ._create_test_client () as test_client :
272+ response = test_client .get (
273+ "/demo/" , headers = {"X-Captcha-Token" : "valid" }
274+ )
275+ self .assertEqual (response .status_code , status .HTTP_200_OK )
276+ self .assertEqual (response .json (), {"Hello" : "World" })
277+
278+ self .assertGreaterEqual (mock_post .call_count , 1 )
279+ self .assertEqual (
280+ mock_post .call_args .args [0 ],
281+ "https://custom.exemple.org/verify" ,
282+ )
283+ response = test_client .get (
284+ "/demo/who_ami" , headers = {"X-Captcha-Token" : "valid" }
285+ )
286+ self .assertEqual (response .status_code , status .HTTP_200_OK )
287+ partner = self .default_fastapi_authenticated_partner
288+ self .assertDictEqual (
289+ response .json (),
290+ {
291+ "name" : partner .name ,
292+ "display_name" : partner .display_name ,
293+ },
294+ )
295+
152296 def test_routes_matching_1 (self ):
153297 self .endpoint .captcha_routes_regex = "/demo/wh.*,/demo/ca.?"
154298 # Refresh app
0 commit comments