Skip to content

Commit c9bd58f

Browse files
Merge pull request #57 from RandomProgramm3r/develop
feat: Refactor core logic and enhance security This commit introduces a major refactoring of core application logic to improve modularity, performance, and security. Key changes include: - **Centralized Core Utilities:** - A new `core` application has been updated to house shared utilities. - `CustomLimitOffsetPagination` is now centralized in `core.pagination`. - A generic `bump_token_version` utility in `core.utils.auth` now handles token versioning for both User and Company models and includes cache invalidation. - **Performance and Security Enhancements:** - Implemented a caching layer for the authentication process. Authenticated user and company instances are now cached to reduce database queries. - Strengthened password security by setting Argon2 as the default password hasher. - **Code Simplification:** - Removed custom email validators in favor of relying on database integrity constraints (`try...except IntegrityError`), making the validation logic more robust and reducing boilerplate code. - **Other changes:** - Remove unused imports from tests
2 parents 4923c78 + ebcff8d commit c9bd58f

File tree

19 files changed

+150
-161
lines changed

19 files changed

+150
-161
lines changed

promo_code/business/serializers.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
import business.constants
1414
import business.models
15-
import business.utils.auth
1615
import business.utils.tokens
1716
import business.validators
17+
import core.utils.auth
1818

1919

2020
class CompanySignUpSerializer(rest_framework.serializers.ModelSerializer):
@@ -36,12 +36,6 @@ class CompanySignUpSerializer(rest_framework.serializers.ModelSerializer):
3636
required=True,
3737
min_length=business.constants.COMPANY_EMAIL_MIN_LENGTH,
3838
max_length=business.constants.COMPANY_EMAIL_MAX_LENGTH,
39-
validators=[
40-
business.validators.UniqueEmailValidator(
41-
'This email address is already registered.',
42-
'email_conflict',
43-
),
44-
],
4539
)
4640

4741
class Meta:
@@ -50,11 +44,20 @@ class Meta:
5044

5145
@django.db.transaction.atomic
5246
def create(self, validated_data):
53-
company = business.models.Company.objects.create_company(
54-
**validated_data,
55-
)
47+
try:
48+
company = business.models.Company.objects.create_company(
49+
**validated_data,
50+
)
51+
except django.db.IntegrityError:
52+
exc = rest_framework.exceptions.APIException(
53+
detail={
54+
'email': 'This email address is already registered.',
55+
},
56+
)
57+
exc.status_code = 409
58+
raise exc
5659

57-
return business.utils.auth.bump_company_token_version(company)
60+
return core.utils.auth.bump_token_version(company)
5861

5962

6063
class CompanySignInSerializer(rest_framework.serializers.Serializer):

promo_code/business/tests/auth/base.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import django.urls
22
import rest_framework
3-
import rest_framework.status
43
import rest_framework.test
54

65
import business.models

promo_code/business/tests/auth/test_authentication.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import rest_framework.status
2-
import rest_framework.test
32

43
import business.models
54
import business.tests.auth.base

promo_code/business/tests/auth/test_registration.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import rest_framework.status
2-
import rest_framework.test
32

43
import business.models
54
import business.tests.auth.base

promo_code/business/tests/auth/test_tokens.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import rest_framework.status
2-
import rest_framework.test
32
import rest_framework_simplejwt.tokens
43

54
import business.models

promo_code/business/tests/auth/test_validation.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import parameterized
22
import rest_framework.status
3-
import rest_framework.test
43

54
import business.models
65
import business.tests.auth.base

promo_code/business/utils/auth.py

Lines changed: 0 additions & 13 deletions
This file was deleted.

promo_code/business/validators.py

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,6 @@
11
import rest_framework.exceptions
22

33
import business.constants
4-
import business.models
5-
6-
7-
class UniqueEmailValidator:
8-
def __init__(self, default_detail=None, default_code=None):
9-
self.status_code = 409
10-
self.default_detail = (
11-
default_detail or 'This email address is already registered.'
12-
)
13-
self.default_code = default_code or 'email_conflict'
14-
15-
def __call__(self, value):
16-
if business.models.Company.objects.filter(email=value).exists():
17-
exc = rest_framework.exceptions.APIException(
18-
detail={
19-
'status': 'error',
20-
'message': self.default_detail,
21-
'code': self.default_code,
22-
},
23-
)
24-
exc.status_code = self.status_code
25-
raise exc
264

275

286
class PromoValidator:

promo_code/business/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
import rest_framework_simplejwt.views
1111

1212
import business.models
13-
import business.pagination
1413
import business.permissions
1514
import business.serializers
16-
import business.utils.auth
1715
import business.utils.tokens
16+
import core.pagination
17+
import core.utils.auth
1818
import user.models
1919

2020

@@ -49,7 +49,7 @@ def post(self, request, *args, **kwargs):
4949
serializer.is_valid(raise_exception=True)
5050

5151
company = serializer.validated_data['company']
52-
company = business.utils.auth.bump_company_token_version(company)
52+
company = core.utils.auth.bump_token_version(company)
5353

5454
return rest_framework.response.Response(
5555
business.utils.tokens.generate_company_tokens(company),
@@ -75,7 +75,7 @@ class CompanyPromoListCreateView(rest_framework.generics.ListCreateAPIView):
7575
business.permissions.IsCompanyUser,
7676
]
7777
# Pagination is only needed for GET (listing)
78-
pagination_class = business.pagination.CustomLimitOffsetPagination
78+
pagination_class = core.pagination.CustomLimitOffsetPagination
7979

8080
_validated_query_params = {}
8181

File renamed without changes.

0 commit comments

Comments
 (0)