Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

768 be incorporate captcha #781

Merged
merged 46 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
acae4fb
add Contacts to settings.py
KuzykY Aug 28, 2024
c216695
add contacts to footer
KuzykY Aug 28, 2024
cbb1660
Configure celery beat and celery task for number of banners and logos…
AlexanderSychev2005 Aug 31, 2024
b65f666
Created task for sending an email and created a template with number …
AlexanderSychev2005 Sep 3, 2024
8902ba0
change email in settings.py
KuzykY Sep 6, 2024
2cc1862
resolve conflict
KuzykY Sep 6, 2024
312ea65
Reformat code with black
KuzykY Sep 6, 2024
e859288
Reformat code with black
KuzykY Sep 6, 2024
d9ac604
Reformat code with black
KuzykY Sep 6, 2024
5f2de62
Reformat code with black
KuzykY Sep 6, 2024
9dd2bd5
Add newline at end of file and fix formatting issues
KuzykY Sep 6, 2024
fbaa38f
Add newline at end of file and fix formatting issues
KuzykY Sep 6, 2024
f7eff2a
Add newline at end of file and fix formatting issues
KuzykY Sep 6, 2024
0f3dca2
run black
KuzykY Sep 6, 2024
9f5e166
Remove unnecessary print from celery task images
AlexanderSychev2005 Sep 9, 2024
95fe833
Added celery beat to docker compose dev
AlexanderSychev2005 Sep 10, 2024
cf7c6c5
Configured sending time for celery task as first day of each month
AlexanderSychev2005 Sep 10, 2024
1755588
Formatted
AlexanderSychev2005 Sep 10, 2024
7517076
Formatted black
AlexanderSychev2005 Sep 10, 2024
edf4548
Formatted black
AlexanderSychev2005 Sep 10, 2024
ffef24e
Merge branch 'refs/heads/develop' into 749-sending-email-to-admin-abo…
AlexanderSychev2005 Sep 10, 2024
24a7477
Added the functionality when email with info about logos and banners …
AlexanderSychev2005 Sep 10, 2024
0d85314
Changed the function for retrieving moderation email from db
AlexanderSychev2005 Sep 10, 2024
aae0f06
add css to contacts
KuzykY Sep 10, 2024
6600cf0
css App and MainPage
romanmyko Sep 11, 2024
cc5fb4e
css BasicPage global.css
romanmyko Sep 11, 2024
9dacbca
cookies img size
romanmyko Sep 11, 2024
57617db
Updated settings and env for recaptcha setup usage
superolegatron Sep 12, 2024
c9076ac
created function to verify recaptcha from server side
superolegatron Sep 12, 2024
a20012a
Updated signup and signin serializers to validate recaptcha
superolegatron Sep 12, 2024
e1c2425
Merge pull request #774 from ita-social-projects/749-sending-email-to…
AlexanderSychev2005 Sep 12, 2024
e41a065
Merge branch 'develop' into #730-Administrativ-panel-Possibility-to-e…
KuzykY Sep 12, 2024
dd5c3ec
Merge pull request #766 from ita-social-projects/#730-Administrativ-p…
KuzykY Sep 12, 2024
ca68698
Merge pull request #775 from ita-social-projects/#767FixCssBsicpagejs…
romanmyko Sep 12, 2024
5f60eb9
fixed bug
ohorodnykostap Sep 12, 2024
396a48f
Merge pull request #782 from ita-social-projects/FixOfBugsInTheWorkOf…
ohorodnykostap Sep 12, 2024
d61fdc2
small fix
superolegatron Sep 12, 2024
429fa54
Merge branch 'develop' into 768-be-incorporate-captcha
superolegatron Sep 12, 2024
1d98b64
fixed tests
superolegatron Sep 13, 2024
6cc4bd6
Merge branch '768-be-incorporate-captcha' of https://github.com/ita-s…
superolegatron Sep 13, 2024
aecad9f
minor fixes
superolegatron Sep 13, 2024
312bc82
recaptcha versioning
superolegatron Sep 15, 2024
aaf91d4
moved url for captcha verification to env
superolegatron Sep 15, 2024
9ce9e35
updated sample.env
superolegatron Sep 16, 2024
b618bdc
minor updates
superolegatron Sep 16, 2024
80ef38e
minor updates
superolegatron Sep 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/tests_be.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ env:
CORS_ORIGIN_WHITELIST: ''
ALLOWED_ENV_HOST: ''
REDIS_URL: ${{ vars.REDIS_URL }}
RECAPTCHA_V2_PRIVATE_KEY: ''


jobs:
Expand Down
2 changes: 2 additions & 0 deletions BackEnd/administration/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.urls import path

from administration.views import (
ContactsView,
ProfilesListView,
ProfileDetailView,
UsersListView,
Expand All @@ -22,4 +23,5 @@
name="automoderation_hours",
),
path("email/", ModerationEmailView.as_view(), name="moderation-email"),
path("contacts/", ContactsView.as_view(), name="contacts"),
]
12 changes: 12 additions & 0 deletions BackEnd/administration/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django.http import JsonResponse
from django.views import View
from drf_spectacular.utils import (
extend_schema,
OpenApiExample,
Expand All @@ -14,6 +16,7 @@
RetrieveUpdateAPIView,
)

from forum.settings import CONTACTS_INFO
from administration.serializers import (
AdminCompanyListSerializer,
AdminCompanyDetailSerializer,
Expand Down Expand Up @@ -136,3 +139,12 @@ class ModerationEmailView(RetrieveUpdateAPIView):

def get_object(self):
return ModerationEmail.objects.first()


class ContactsView(View):
"""
View for retrieving contact information.
"""

def get(self, request):
return JsonResponse(CONTACTS_INFO)
25 changes: 24 additions & 1 deletion BackEnd/authentication/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
validate_password_include_symbols,
)
from validation.validate_profile import validate_profile
from validation.validate_recaptcha import verify_recaptcha

User = get_user_model()

Expand All @@ -42,13 +43,23 @@ class UserRegistrationSerializer(UserCreatePasswordRetypeSerializer):
password = serializers.CharField(
style={"input_type": "password"}, write_only=True
)
captcha = serializers.CharField(
write_only=True, allow_blank=True, allow_null=True
)

class Meta(UserCreatePasswordRetypeSerializer.Meta):
model = User
fields = ("email", "password", "name", "surname", "company")
fields = ("email", "password", "name", "surname", "company", "captcha")

def validate(self, value):
custom_errors = defaultdict(list)
captcha_token = value.get("captcha")

if captcha_token and not verify_recaptcha(captcha_token):
custom_errors["captcha"].append(
"Invalid reCAPTCHA. Please try again."
)

self.fields.pop("re_password", None)
re_password = value.pop("re_password")
email = value.get("email").lower()
Expand Down Expand Up @@ -79,6 +90,7 @@ def validate(self, value):
return value

def create(self, validated_data):
validated_data.pop("captcha", None)
company_data = validated_data.pop("company")
user = User.objects.create(**validated_data)
user.set_password(validated_data["password"])
Expand All @@ -105,7 +117,18 @@ class Meta(UserSerializer.Meta):


class CustomTokenCreateSerializer(TokenCreateSerializer):
captcha = serializers.CharField(
write_only=True, allow_blank=True, allow_null=True
)

def validate(self, attrs):
captcha_token = attrs.get("captcha")

if captcha_token and not verify_recaptcha(captcha_token):
raise serializers.ValidationError(
"Invalid reCAPTCHA. Please try again."
)

try:
validate_profile(attrs.get("email"))
except ValidationError as error:
Expand Down
9 changes: 9 additions & 0 deletions BackEnd/authentication/tests/test_user_autologout.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import timedelta
from unittest.mock import patch

from rest_framework import status
from rest_framework.authtoken.models import Token
Expand All @@ -12,6 +13,12 @@

class UserLogoutAPITests(APITestCase):
def setUp(self):
patcher = patch(
"authentication.serializers.verify_recaptcha", return_value=True
)
self.mock_verify_recaptcha = patcher.start()
self.addCleanup(patcher.stop)

self.user = UserFactory(
email="test@test.com", name="Test", surname="Test"
)
Expand All @@ -29,6 +36,7 @@ def test_user_autologout_after_14_days(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
).data["auth_token"]
token = Token.objects.get(key=self.test_user_token)
Expand All @@ -53,6 +61,7 @@ def test_user_autologout_after_10_days(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
).data["auth_token"]
token = Token.objects.get(key=self.test_user_token)
Expand Down
18 changes: 18 additions & 0 deletions BackEnd/authentication/tests/test_user_login.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from unittest.mock import patch

from rest_framework import status
from rest_framework.test import APITestCase
from time import sleep
Expand All @@ -9,6 +11,12 @@

class UserLoginAPITests(APITestCase):
def setUp(self):
patcher = patch(
"authentication.serializers.verify_recaptcha", return_value=True
)
self.mock_verify_recaptcha = patcher.start()
self.addCleanup(patcher.stop)

self.user = UserFactory(email="test@test.com")

def test_login_successful(self):
Expand All @@ -20,6 +28,7 @@ def test_login_successful(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
Expand All @@ -35,6 +44,7 @@ def test_login_email_incorrect(self):
data={
"email": "tost@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
Expand All @@ -56,6 +66,7 @@ def test_login_password_incorrect(self):
data={
"email": "test@test.com",
"password": "Test5678",
"captcha": "dummy_captcha",
},
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
Expand All @@ -77,13 +88,15 @@ def test_login_after_allowed_number_attempts(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)
self.client.post(
path="/api/auth/token/login/",
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)

Expand All @@ -92,6 +105,7 @@ def test_login_after_allowed_number_attempts(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)
sleep(6)
Expand All @@ -110,6 +124,7 @@ def test_login_after_allowed_delay_time(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)

Expand All @@ -118,13 +133,15 @@ def test_login_after_allowed_delay_time(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)
self.client.post(
path="/api/auth/token/login/",
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)
sleep(6)
Expand All @@ -133,6 +150,7 @@ def test_login_after_allowed_delay_time(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
)

Expand Down
9 changes: 9 additions & 0 deletions BackEnd/authentication/tests/test_user_logout.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from unittest.mock import patch

from rest_framework import status
from rest_framework.test import APITestCase

Expand All @@ -8,6 +10,12 @@

class UserLogoutAPITests(APITestCase):
def setUp(self):
patcher = patch(
"authentication.serializers.verify_recaptcha", return_value=True
)
self.mock_verify_recaptcha = patcher.start()
self.addCleanup(patcher.stop)

self.user = UserFactory(email="test@test.com")

def test_logout_successful(self):
Expand All @@ -19,6 +27,7 @@ def test_logout_successful(self):
data={
"email": "test@test.com",
"password": "Test1234",
"captcha": "dummy_captcha",
},
).data["auth_token"]
self.client.credentials(
Expand Down
15 changes: 15 additions & 0 deletions BackEnd/authentication/tests/test_user_registration.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from unittest.mock import patch

from rest_framework import status
from rest_framework.test import APITestCase

Expand All @@ -8,6 +10,12 @@

class UserRegistrationAPITests(APITestCase):
def setUp(self):
patcher = patch(
"authentication.serializers.verify_recaptcha", return_value=True
)
self.mock_verify_recaptcha = patcher.start()
self.addCleanup(patcher.stop)

self.user = UserFactory(email="test@test.com")

def test_register_user_yurosoba_successful(self):
Expand All @@ -19,6 +27,7 @@ def test_register_user_yurosoba_successful(self):
"re_password": "Test1234",
"name": "Jane",
"surname": "Smith",
"captcha": "dummy_captcha",
"company": {
"name": "My Company",
"is_registered": True,
Expand Down Expand Up @@ -49,6 +58,7 @@ def test_register_user_fop_successful(self):
"re_password": "Test1234",
"name": "Jane",
"surname": "Smith",
"captcha": "dummy_captcha",
"company": {
"name": "My Company",
"is_registered": True,
Expand Down Expand Up @@ -79,6 +89,7 @@ def test_register_user_email_incorrect(self):
"re_password": "Test1234",
"name": "Jane",
"surname": "Smith",
"captcha": "dummy_captcha",
"company": {
"name": "My Company",
"is_registered": True,
Expand All @@ -103,6 +114,7 @@ def test_register_user_email_exists(self):
"re_password": "Test1234",
"name": "Test",
"surname": "Test",
"captcha": "dummy_captcha",
"company": {
"name": "Test Company",
"is_registered": True,
Expand All @@ -127,6 +139,7 @@ def test_register_user_password_incorrect(self):
"re_password": "tess",
"name": "Jane",
"surname": "Smith",
"captcha": "dummy_captcha",
"company": {
"name": "My Company",
"is_registered": True,
Expand Down Expand Up @@ -157,6 +170,7 @@ def test_register_user_who_represent_empty_fields(self):
"re_password": "Test1234",
"name": "Jane",
"surname": "Smith",
"captcha": "dummy_captcha",
"company": {
"name": "My Company",
"is_registered": False,
Expand All @@ -181,6 +195,7 @@ def test_register_user_who_represent_both_chosen(self):
"re_password": "Test1234",
"name": "Jane",
"surname": "Smith",
"captcha": "dummy_captcha",
"company": {
"name": "My Company",
"is_registered": True,
Expand Down
8 changes: 8 additions & 0 deletions BackEnd/forum/celery.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import os
from celery import Celery
from celery.schedules import crontab

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "forum.settings")
app = Celery("forum")

app.config_from_object("django.conf:settings", namespace="CELERY")

app.autodiscover_tasks()

app.conf.beat_schedule = {
"every": {
"task": "images.tasks.celery_send_email_images",
"schedule": crontab(day_of_month="1"),
}
}
12 changes: 11 additions & 1 deletion BackEnd/forum/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ def show_toolbar(request):
"SHOW_TOOLBAR_CALLBACK": show_toolbar,
}


LOGGING = {
"version": 1,
"disable_existing_loggers": False,
Expand Down Expand Up @@ -267,3 +266,14 @@ def show_toolbar(request):
},
},
}

# ReCaptcha V2 Invisible
RECAPTCHA_V2_PRIVATE_KEY = config("RECAPTCHA_V2_PRIVATE_KEY")
RECAPTCHA_URL = config("RECAPTCHA_URL")

CONTACTS_INFO = {
"email": "craft.forum0@gmail.com",
"phone": "+38 050 234 23 23",
"university": "Львівська Політехніка",
"address": "вул. Степана Бандери 12, Львів",
}
Loading
Loading