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

Migrate to the dj-rest-auth==5.0.2 and django-allauth==0.57.2 #7635

Merged
merged 24 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8b0053c
Migrate to dj-rest-auth==5.0.2
Marishka17 Mar 18, 2024
6e8c790
Merge branch 'develop' into mk/update_module_versions
Marishka17 Mar 19, 2024
6f6d25e
Migrate to django-allauth>=0.56.0,<0.58.0
Marishka17 Mar 19, 2024
9077959
Update settings
Marishka17 Mar 20, 2024
054c42a
Allow dj-rest-auth compatible releases
Marishka17 Mar 20, 2024
6b52dc7
Fix missing RegisterSerializerEx fields in server schema
Marishka17 Mar 20, 2024
a35d8b1
Reimplement RegisterView::perform_create method to fix missing user a…
Marishka17 Mar 20, 2024
96dee57
Merge branch 'develop' into mk/update_module_versions
Marishka17 Mar 21, 2024
9f62ff6
Merge branch 'develop' into mk/update_module_versions
Marishka17 Mar 21, 2024
0ef24ff
Merge branch 'develop' into mk/update_module_versions
Marishka17 Mar 25, 2024
eb86ad0
Resolve conflicts
Marishka17 Mar 26, 2024
89dc0aa
Apply comments
Marishka17 Mar 26, 2024
8dceb43
Update cvat/requirements/base.in
Marishka17 Mar 26, 2024
8d13899
Add a link to the issue from the upstream repo
Marishka17 Mar 26, 2024
8feb940
Merge branch 'mk/update_module_versions' of github.com:opencv/cvat in…
Marishka17 Mar 26, 2024
16d25d2
Merge branch 'develop' into mk/update_module_versions
Marishka17 Mar 26, 2024
7bb737f
Update server schema
Marishka17 Mar 26, 2024
4c4f6b5
Merge branch 'develop' into mk/update_module_versions
Marishka17 Apr 2, 2024
e7b7d7b
Limit supported dj-rest--auth & alluth versions
Marishka17 Apr 3, 2024
cfcb9d0
Add changelog fragment
Marishka17 Apr 3, 2024
9816500
Run CI
Marishka17 Apr 3, 2024
e4b2d9f
Merge branch 'develop' into mk/update_module_versions
Marishka17 Apr 3, 2024
47e2eb3
fix autogenerated dash to underscore
Marishka17 Apr 4, 2024
5a7a292
Merge branch 'develop' into mk/update_module_versions
Marishka17 Apr 4, 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
42 changes: 35 additions & 7 deletions cvat/apps/iam/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework.exceptions import ValidationError
from rest_framework import serializers
from allauth.account import app_settings
from allauth.account import app_settings as allauth_settings
from allauth.account.utils import filter_users_by_email
from allauth.account.adapter import get_adapter
from allauth.utils import email_address_exists
from allauth.account.utils import setup_user_email
from allauth.account.models import EmailAddress

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User

from drf_spectacular.utils import extend_schema_field
from typing import Optional, Union, Dict

from cvat.apps.iam.forms import ResetPasswordFormEx
from cvat.apps.iam.utils import get_dummy_user
Expand All @@ -23,6 +28,20 @@
class RegisterSerializerEx(RegisterSerializer):
first_name = serializers.CharField(required=False)
last_name = serializers.CharField(required=False)
email_verification_required = serializers.SerializerMethodField()
key = serializers.SerializerMethodField()

@extend_schema_field(serializers.BooleanField)
def get_email_verification_required(self, obj: Union[Dict, User]) -> bool:
return allauth_settings.EMAIL_VERIFICATION == allauth_settings.EmailVerificationMethod.MANDATORY

@extend_schema_field(serializers.CharField(allow_null=True))
def get_key(self, obj: Union[Dict, User]) -> Optional[str]:
SpecLad marked this conversation as resolved.
Show resolved Hide resolved
key = None
if isinstance(obj, User) and allauth_settings.EMAIL_VERIFICATION != \
allauth_settings.EmailVerificationMethod.MANDATORY:
key = obj.auth_token.key
return key

def get_cleaned_data(self):
data = super().get_cleaned_data()
Expand All @@ -34,8 +53,17 @@ def get_cleaned_data(self):
return data

def validate_email(self, email):
def email_address_exists(email) -> bool:
if EmailAddress.objects.filter(email__iexact=email).exists():
return True

if (email_field := allauth_settings.USER_MODEL_EMAIL_FIELD):
users = get_user_model().objects
return users.filter(**{email_field + "__iexact": email}).exists()
return False

email = get_adapter().clean_email(email)
if app_settings.UNIQUE_EMAIL:
if allauth_settings.UNIQUE_EMAIL:
if email and email_address_exists(email):
user = get_dummy_user(email)
if not user:
Expand Down Expand Up @@ -88,10 +116,10 @@ class LoginSerializerEx(LoginSerializer):
def get_auth_user_using_allauth(self, username, email, password):

def is_email_authentication():
return settings.ACCOUNT_AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.EMAIL
return settings.ACCOUNT_AUTHENTICATION_METHOD == allauth_settings.AuthenticationMethod.EMAIL

def is_username_authentication():
return settings.ACCOUNT_AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME
return settings.ACCOUNT_AUTHENTICATION_METHOD == allauth_settings.AuthenticationMethod.USERNAME

# check that the server settings match the request
if is_username_authentication() and not username and email:
Expand All @@ -107,11 +135,11 @@ def is_username_authentication():
'Please check your server configuration ACCOUNT_AUTHENTICATION_METHOD.')

# Authentication through email
if settings.ACCOUNT_AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.EMAIL:
if settings.ACCOUNT_AUTHENTICATION_METHOD == allauth_settings.AuthenticationMethod.EMAIL:
return self._validate_email(email, password)

# Authentication through username
if settings.ACCOUNT_AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME:
if settings.ACCOUNT_AUTHENTICATION_METHOD == allauth_settings.AuthenticationMethod.USERNAME:
return self._validate_username(username, password)

# Authentication through either username or email
Expand Down
41 changes: 33 additions & 8 deletions cvat/apps/iam/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
from django.http import HttpResponse
from django.views.decorators.http import etag as django_etag
from rest_framework.response import Response
from dj_rest_auth.app_settings import api_settings as dj_rest_auth_settings
from dj_rest_auth.registration.views import RegisterView
from dj_rest_auth.utils import jwt_encode
from dj_rest_auth.views import LoginView
from allauth.account import app_settings as allauth_settings
from allauth.account.views import ConfirmEmailView
from allauth.account.utils import has_verified_email, send_email_confirmation
from allauth.account.utils import complete_signup, has_verified_email, send_email_confirmation

from furl import furl

Expand Down Expand Up @@ -97,14 +99,37 @@ def post(self, request, *args, **kwargs):

class RegisterViewEx(RegisterView):
def get_response_data(self, user):
data = self.get_serializer(user).data
data['email_verification_required'] = True
data['key'] = None
serializer = self.get_serializer(user)
return serializer.data

# NOTE: we should reimplement this method to fix the following issue:
# In the previous used version of dj-rest-auth 2.2.7, if the REST_SESSION_LOGIN setting was not defined in the settings file,
# the default value specified in the documentation (https://dj-rest-auth.readthedocs.io/en/2.2.7/configuration.html)
# was not applied for some unknown reason, and an authentication token was added to a user.
# With the dj-rest-auth version 5.0.2, there have been changes to how settings are handled,
# and now the default value is properly taken into account.
# However, even with the updated code, it still does not handle the scenario
# of handling two authentication flows simultaneously during registration process.
# Since there is no mention in the dj-rest-auth documentation that session authentication
# cannot be used alongside token authentication (https://dj-rest-auth.readthedocs.io/en/latest/configuration.html),
# and given the login implementation (https://github.com/iMerica/dj-rest-auth/blob/c6b6530eb0bfa5b10fd7b9e955a39301156e49d2/dj_rest_auth/views.py#L69-L75),
# this situation appears to be a bug.
SpecLad marked this conversation as resolved.
Show resolved Hide resolved
# Link to the issue: https://github.com/iMerica/dj-rest-auth/issues/604
def perform_create(self, serializer):
user = serializer.save(self.request)
if allauth_settings.EMAIL_VERIFICATION != \
allauth_settings.EmailVerificationMethod.MANDATORY:
data['email_verification_required'] = False
data['key'] = user.auth_token.key
return data
allauth_settings.EmailVerificationMethod.MANDATORY:
if dj_rest_auth_settings.USE_JWT:
self.access_token, self.refresh_token = jwt_encode(user)
elif self.token_model:
dj_rest_auth_settings.TOKEN_CREATOR(self.token_model, user, serializer)

complete_signup(
self.request._request, user,
allauth_settings.EMAIL_VERIFICATION,
None,
)
return user

def _etag(etag_func):
"""
Expand Down
8 changes: 3 additions & 5 deletions cvat/requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ clickhouse-connect==0.6.8
coreapi==2.3.3
datumaro @ git+https://github.com/cvat-ai/datumaro.git@8a14a99fe17f19d98595a2a4a74ab459051cc23b
dj-pagination==2.5.0
dj-rest-auth[with_social]==2.2.7

# dj-rest-auth[with_social] includes django-allauth but with version range: >=0.40.0,<0.53.0
# This does not suit us in the case when one of the previous allauth version was installed.
# Despite direct indication allauth in requirements we should keep 'with_social' for dj-rest-auth
# to avoid possible further versions conflicts (we use registration functionality)
# https://dj-rest-auth.readthedocs.io/en/latest/installation.html#registration-optional
django-allauth>=0.52.0
Marishka17 marked this conversation as resolved.
Show resolved Hide resolved
dj-rest-auth[with_social]>=5.0.2,<6
# The same django-allauth version range as dj-rest-auth requirements
SpecLad marked this conversation as resolved.
Show resolved Hide resolved
django-allauth>=0.56.0,<0.58.0

django-auth-ldap==2.2.0
django-compressor==4.3.1
Expand Down
41 changes: 20 additions & 21 deletions cvat/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# SHA1:92683dac1b858a87e89ba736358e779ac8be666d
# SHA1:6ea58f466019839a02f9fb2b6cebd287a8d3eee9
#
# This file is autogenerated by pip-compile-multi
# To update, run:
#
# pip-compile-multi
#
-r ../../utils/dataset_manifest/requirements.txt
asgiref==3.7.2
asgiref==3.8.1
# via django
async-timeout==4.0.3
# via redis
Expand Down Expand Up @@ -66,10 +66,8 @@ deprecated==1.2.14
# via limits
dj-pagination==2.5.0
# via -r cvat/requirements/base.in
dj-rest-auth[with-social]==2.2.7
# via
# -r cvat/requirements/base.in
# dj-rest-auth
dj-rest-auth[with-social]==5.0.2
# via -r cvat/requirements/base.in
django==4.2.11
# via
# -r cvat/requirements/base.in
Expand All @@ -85,7 +83,7 @@ django==4.2.11
# django-sendfile2
# djangorestframework
# drf-spectacular
django-allauth==0.52.0
django-allauth==0.57.2
# via
# -r cvat/requirements/base.in
# dj-rest-auth
Expand Down Expand Up @@ -118,17 +116,17 @@ easyprocess==1.1
# via pyunpack
entrypoint2==1.1
# via pyunpack
fonttools==4.49.0
fonttools==4.50.0
# via matplotlib
freezegun==1.4.0
# via rq-scheduler
furl==2.1.0
# via -r cvat/requirements/base.in
google-api-core==2.17.1
google-api-core==2.18.0
# via
# google-cloud-core
# google-cloud-storage
google-auth==2.28.1
google-auth==2.29.0
# via
# google-api-core
# google-cloud-core
Expand All @@ -141,15 +139,15 @@ google-crc32c==1.5.0
# via google-resumable-media
google-resumable-media==2.7.0
# via google-cloud-storage
googleapis-common-protos==1.62.0
googleapis-common-protos==1.63.0
# via google-api-core
h5py==3.10.0
# via datumaro
idna==3.6
# via requests
importlib-metadata==7.0.1
importlib-metadata==7.1.0
# via clickhouse-connect
importlib-resources==6.1.2
importlib-resources==6.4.0
# via limits
inflection==0.5.1
# via drf-spectacular
Expand All @@ -167,7 +165,7 @@ jsonschema==4.17.3
# via drf-spectacular
kiwisolver==1.4.5
# via matplotlib
limits==3.9.0
limits==3.10.1
# via python-logstash-async
lxml==5.1.0
# via datumaro
Expand All @@ -191,7 +189,7 @@ orderedmultidict==1.0.1
# via furl
orjson==3.9.15
# via datumaro
packaging==23.2
packaging==24.0
# via
# limits
# matplotlib
Expand All @@ -203,10 +201,13 @@ patool==1.12
# via -r cvat/requirements/base.in
pdf2image==1.14.0
# via -r cvat/requirements/base.in
proto-plus==1.23.0
# via google-api-core
protobuf==4.25.3
# via
# google-api-core
# googleapis-common-protos
# proto-plus
# tensorboardx
psutil==5.9.4
# via -r cvat/requirements/base.in
Expand All @@ -226,12 +227,10 @@ pycocotools==2.0.7
pycparser==2.21
# via cffi
pyjwt[crypto]==2.8.0
# via
# django-allauth
# pyjwt
# via django-allauth
pylogbeat==2.0.1
# via python-logstash-async
pyparsing==3.1.1
pyparsing==3.1.2
# via matplotlib
pyrsistent==0.20.0
# via jsonschema
Expand Down Expand Up @@ -280,7 +279,7 @@ requests==2.31.0
# msrest
# python-logstash-async
# requests-oauthlib
requests-oauthlib==1.3.1
requests-oauthlib==2.0.0
# via
# django-allauth
# msrest
Expand Down Expand Up @@ -337,7 +336,7 @@ urllib3==1.26.18
# requests
wrapt==1.16.0
# via deprecated
zipp==3.17.0
zipp==3.18.1
# via importlib-metadata
zstandard==0.22.0
# via clickhouse-connect
6 changes: 3 additions & 3 deletions cvat/requirements/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
-r base.txt
astroid==2.11.7
# via pylint
autopep8==2.0.4
autopep8==2.1.0
# via django-silk
black==24.2.0
black==24.3.0
# via -r cvat/requirements/development.in
dill==0.3.8
# via pylint
Expand Down Expand Up @@ -62,5 +62,5 @@ tornado==6.4
# via snakeviz

# The following packages are considered to be unsafe in a requirements file:
setuptools==69.1.1
setuptools==69.2.0
# via astroid
4 changes: 1 addition & 3 deletions cvat/requirements/production.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ python-dotenv==1.0.1
sniffio==1.3.1
# via anyio
uvicorn[standard]==0.22.0
# via
# -r cvat/requirements/production.in
# uvicorn
# via -r cvat/requirements/production.in
uvloop==0.19.0
# via uvicorn
watchfiles==0.21.0
Expand Down
7 changes: 7 additions & 0 deletions cvat/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9245,6 +9245,13 @@ components:
type: string
last_name:
type: string
email_verification_required:
type: boolean
readOnly: true
key:
type: string
nullable: true
readOnly: true
required:
- username
RegisterSerializerExRequest:
Expand Down
9 changes: 3 additions & 6 deletions cvat/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,11 @@ def generate_secret_key():
}


REST_AUTH_REGISTER_SERIALIZERS = {
REST_AUTH = {
'REGISTER_SERIALIZER': 'cvat.apps.iam.serializers.RegisterSerializerEx',
}

REST_AUTH_SERIALIZERS = {
'LOGIN_SERIALIZER': 'cvat.apps.iam.serializers.LoginSerializerEx',
'PASSWORD_RESET_SERIALIZER': 'cvat.apps.iam.serializers.PasswordResetSerializerEx',
'OLD_PASSWORD_FIELD_ENABLED': True,
}

if to_bool(os.getenv('CVAT_ANALYTICS', False)):
Expand All @@ -198,6 +196,7 @@ def generate_secret_key():
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'dj_pagination.middleware.PaginationMiddleware',
'cvat.apps.iam.middleware.ContextMiddleware',
'allauth.account.middleware.AccountMiddleware',
]

UI_URL = ''
Expand Down Expand Up @@ -263,8 +262,6 @@ def generate_secret_key():
ACCOUNT_EMAIL_VERIFICATION_SENT_REDIRECT_URL = '/auth/email-verification-sent'
INCORRECT_EMAIL_CONFIRMATION_URL = '/auth/incorrect-email-confirmation'

OLD_PASSWORD_FIELD_ENABLED = True

# Django-RQ
# https://github.com/rq/django-rq

Expand Down
Loading