Private
Public Access
1
0

Merge branch 'release/v23.6.13'

This commit is contained in:
2025-10-30 16:09:27 +01:00
5 changed files with 47 additions and 10 deletions

View File

@@ -1066,7 +1066,8 @@ class RegistrationFormSex(RegistrationFormUniqueEmail):
month=4,
day=15))
url = HoneypotField(label="URL")
hp_field = HoneypotField(label="URL")
timestamp = forms.CharField(widget=forms.HiddenInput(), required=False)
def clean_birthdate(self):
dob = self.cleaned_data['birthdate']
@@ -1087,6 +1088,22 @@ class RegistrationFormSex(RegistrationFormUniqueEmail):
adaptiveclass = forms.ChoiceField(label='Adaptive Classification',
choices=adaptivecategories, initial='None', required=False)
captcha = ReCaptchaField(widget=ReCaptchaV3(
attrs={
'required_score': 0.85,
}))
def clean(self):
cleaned_data = super().clean()
timestamp = cleaned_data.get('timestamp')
if timestamp:
submission_time = timezone.now()
form_render_time = timezone.datetime.fromtimestamp(float(timestamp), tz=timezone.get_current_timezone())
if (submission_time - form_render_time).seconds < 3:
raise forms.ValidationError("Form submitted too quickly. Are you a bot?")
return cleaned_data
class PowerIntervalUpdateForm(forms.Form):
selectorchoices = (

View File

@@ -31,6 +31,8 @@
<table width=100%>
{{ form.as_table }}
</table>
<!-- Manually add the timestamp field -->
<input type="hidden" name="timestamp" value="{{ timestamp }}">
<p>
<a href="/rowers/legal/">Terms of Service</a>
</p>

View File

@@ -5,7 +5,8 @@ from __future__ import unicode_literals
#from __future__ import print_function
from .statements import *
from django_recaptcha.client import RecaptchaResponse
from django_recaptcha.fields import ReCaptchaField
nu = datetime.datetime.now()
#@pytest.mark.django_db
@@ -22,7 +23,11 @@ class NewUserRegistrationTest(TestCase):
pass
@patch('rowers.dataprep.workout_summary_to_df',side_effect=mock_workout_summaries)
def test_newuser(self,mock_workout_summaries):
@patch("django_recaptcha.fields.client.submit")
def test_newuser(self,mock_submit, mock_workout_summaries):
mock_response = RecaptchaResponse(is_valid=True, extra_data={'score': 0.95})
mock_submit.return_value = mock_response
form_data = {
'first_name':'Jan',
'last_name':'Roeiert',
@@ -30,16 +35,21 @@ class NewUserRegistrationTest(TestCase):
'username':'janderoeiert',
'password1':'Aapindewei2',
'password2':'Aapindewei2',
'url': '',
'hp_field': '',
'tos':True,
'weightcategory':'hwt',
'adaptiveclass': 'None',
'sex':'male',
'captcha': 'PASSED',
'g-recaptcha-response': 'PASSED',
'next':'/rowers/list-workouts',
'birthdate':datetime.datetime(year=1970,month=4,day=2)
}
form = RegistrationFormSex(form_data)
if not form.is_valid():
print(form.errors)
self.assertTrue(form.is_valid())
response = self.c.post('/rowers/register/', form_data, follow=True)
@@ -118,7 +128,7 @@ class NewUserRegistrationTest(TestCase):
'password1':'aapindewei2',
'password2':'aapindewei2',
'tos':True,
'url': '',
'hp_field': '',
'weightcategory':'hwt',
'adaptiveclass': 'None',
'sex':'male',
@@ -126,11 +136,15 @@ class NewUserRegistrationTest(TestCase):
'birthdate':datetime.datetime(year=1970,month=4,day=2)
}
form = RegistrationFormSex(form_data)
self.assertFalse(form.is_valid())
@patch('rowers.dataprep.workout_summary_to_df',side_effect=mock_workout_summaries)
def test_newuser_honeypot(self,mock_workout_summaries):
@patch("django_recaptcha.fields.client.submit")
def test_newuser_honeypot(self,mock_submit, mock_workout_summaries):
mock_response = RecaptchaResponse(is_valid=True, extra_data={'score': 0.95})
mock_submit.return_value = mock_response
form_data = {
'first_name':'Jan',
'last_name':'Roeiert',
@@ -138,7 +152,7 @@ class NewUserRegistrationTest(TestCase):
'username':'janderoeiert',
'password1':'Aapindewei2',
'password2':'Aapindewei2',
'url': 'http://example.com',
'hp_field': 'http://example.com',
'tos':True,
'weightcategory':'hwt',
'adaptiveclass': 'None',

Binary file not shown.

View File

@@ -5,6 +5,7 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.auth.backends import ModelBackend
from rowers.views.statements import *
from django.core.mail import EmailMessage
from django_ratelimit.decorators import ratelimit
from rowers import credits
@@ -888,6 +889,7 @@ def useractivate(request, uidb64, token): # pragma: no cover
# User registration
@ratelimit(key='ip', rate='5/h', method='POST')
def rower_register_view(request):
nextpage = request.GET.get('next', '/rowers/list-workouts/')
@@ -896,7 +898,7 @@ def rower_register_view(request):
if request.method == 'POST':
# Check if honeypot was triggered (optional logging)
honeypot_value = request.POST.get('url', '')
honeypot_value = request.POST.get('hp_field', '')
if honeypot_value:
# bot user, do not register
messages.error(request, "Registration failed. Please try again.")
@@ -985,13 +987,15 @@ def rower_register_view(request):
return render(request,
"registration_form.html",
{'form': form,
'next': nextpage, })
'next': nextpage,
'timestamp': timezone.now().timestamp(),})
else:
form = RegistrationFormSex()
return render(request,
"registration_form.html",
{'form': form,
'next': nextpage, })
'next': nextpage,
'timestamp': timezone.now().timestamp(),})
# User registration