Browse Source

Remove db_settings usage from misago.users

rafalp 6 years ago
parent
commit
6613de5836

+ 4 - 4
misago/users/api/auth.py

@@ -69,8 +69,8 @@ def get_criteria(request):
     """GET /auth/criteria/ will return password and username criteria for accounts"""
     """GET /auth/criteria/ will return password and username criteria for accounts"""
     criteria = {
     criteria = {
         'username': {
         'username': {
-            'min_length': settings.username_length_min,
-            'max_length': settings.username_length_max,
+            'min_length': request.settings.username_length_min,
+            'max_length': request.settings.username_length_max,
         },
         },
         'password': [],
         'password': [],
     }
     }
@@ -100,7 +100,7 @@ def send_activation(request):
 
 
         mail_subject = _("Activate %(user)s account on %(forum_name)s forums") % {
         mail_subject = _("Activate %(user)s account on %(forum_name)s forums") % {
             'user': requesting_user.username,
             'user': requesting_user.username,
-            'forum_name': settings.forum_name,
+            'forum_name': request.settings.forum_name,
         }
         }
 
 
         mail_user(
         mail_user(
@@ -139,7 +139,7 @@ def send_password_form(request):
 
 
         mail_subject = _("Change %(user)s password on %(forum_name)s forums") % {
         mail_subject = _("Change %(user)s password on %(forum_name)s forums") % {
             'user': requesting_user.username,
             'user': requesting_user.username,
-            'forum_name': settings.forum_name,
+            'forum_name': request.settings.forum_name,
         }
         }
 
 
         confirmation_token = make_password_change_token(requesting_user)
         confirmation_token = make_password_change_token(requesting_user)

+ 3 - 5
misago/users/api/captcha.py

@@ -3,15 +3,13 @@ from rest_framework.response import Response
 
 
 from django.http import Http404
 from django.http import Http404
 
 
-from misago.conf import settings
-
 
 
 @api_view()
 @api_view()
 def question(request):
 def question(request):
-    if settings.qa_question:
+    if request.settings.qa_question:
         return Response({
         return Response({
-            'question': settings.qa_question,
-            'help_text': settings.qa_help_text,
+            'question': request.settings.qa_question,
+            'help_text': request.settings.qa_help_text,
         })
         })
     else:
     else:
         raise Http404()
         raise Http404()

+ 22 - 12
misago/users/api/userendpoints/avatar.py

@@ -30,14 +30,14 @@ def avatar_endpoint(request, pk=None):
             status=status.HTTP_403_FORBIDDEN,
             status=status.HTTP_403_FORBIDDEN,
         )
         )
 
 
-    avatar_options = get_avatar_options(request.user)
+    avatar_options = get_avatar_options(request, request.user)
     if request.method == 'POST':
     if request.method == 'POST':
-        return avatar_post(avatar_options, request.user, request.data)
+        return avatar_post(request, avatar_options)
     else:
     else:
         return Response(avatar_options)
         return Response(avatar_options)
 
 
 
 
-def get_avatar_options(user):
+def get_avatar_options(request, user):
     options = {
     options = {
         'avatars': user.avatars,
         'avatars': user.avatars,
         'generated': True,
         'generated': True,
@@ -64,7 +64,7 @@ def get_avatar_options(user):
             })
             })
 
 
     # Can't have custom avatar?
     # Can't have custom avatar?
-    if not settings.allow_custom_avatars:
+    if not request.settings.allow_custom_avatars:
         return options
         return options
 
 
     # Allow Gravatar download
     # Allow Gravatar download
@@ -90,7 +90,7 @@ def get_avatar_options(user):
 
 
     # Allow upload conditions
     # Allow upload conditions
     options['upload'] = {
     options['upload'] = {
-        'limit': settings.avatar_upload_limit * 1024,
+        'limit': request.settings.avatar_upload_limit * 1024,
         'allowed_extensions': avatars.uploaded.ALLOWED_EXTENSIONS,
         'allowed_extensions': avatars.uploaded.ALLOWED_EXTENSIONS,
         'allowed_mime_types': avatars.uploaded.ALLOWED_MIME_TYPES,
         'allowed_mime_types': avatars.uploaded.ALLOWED_MIME_TYPES,
     }
     }
@@ -102,9 +102,14 @@ class AvatarError(Exception):
     pass
     pass
 
 
 
 
-def avatar_post(options, user, data):
+def avatar_post(request, options):
+    user = request.user
+    data = request.data
+
+    avatar_type = data.get('avatar', 'nope')
+
     try:
     try:
-        type_options = options[data.get('avatar', 'nope')]
+        type_options = options[avatar_type]
         if not type_options:
         if not type_options:
             return Response(
             return Response(
                 {
                 {
@@ -113,7 +118,7 @@ def avatar_post(options, user, data):
                 status=status.HTTP_400_BAD_REQUEST,
                 status=status.HTTP_400_BAD_REQUEST,
             )
             )
 
 
-        rpc_handler = AVATAR_TYPES[data.get('avatar', 'nope')]
+        avatar_strategy = AVATAR_TYPES[avatar_type]
     except KeyError:
     except KeyError:
         return Response(
         return Response(
             {
             {
@@ -123,7 +128,11 @@ def avatar_post(options, user, data):
         )
         )
 
 
     try:
     try:
-        response_dict = {'detail': rpc_handler(user, data)}
+        if avatar_type == "upload":
+            # avatar_upload strategy requires access to request.settings
+            response_dict = {'detail': avatar_upload(request, user, data)}
+        else:
+            response_dict = {'detail': avatar_strategy(user, data)}
     except AvatarError as e:
     except AvatarError as e:
         return Response(
         return Response(
             {
             {
@@ -134,7 +143,8 @@ def avatar_post(options, user, data):
 
 
     user.save()
     user.save()
 
 
-    response_dict.update(get_avatar_options(user))
+    updated_options = get_avatar_options(request, user)
+    response_dict.update(updated_options)
     return Response(response_dict)
     return Response(response_dict)
 
 
 
 
@@ -165,13 +175,13 @@ def avatar_gallery(user, data):
         raise AvatarError(_("Incorrect image."))
         raise AvatarError(_("Incorrect image."))
 
 
 
 
-def avatar_upload(user, data):
+def avatar_upload(request, user, data):
     new_avatar = data.get('image')
     new_avatar = data.get('image')
     if not new_avatar:
     if not new_avatar:
         raise AvatarError(_("No file was sent."))
         raise AvatarError(_("No file was sent."))
 
 
     try:
     try:
-        avatars.uploaded.handle_uploaded_file(user, new_avatar)
+        avatars.uploaded.handle_uploaded_file(request, user, new_avatar)
     except ValidationError as e:
     except ValidationError as e:
         raise AvatarError(e.args[0])
         raise AvatarError(e.args[0])
 
 

+ 4 - 2
misago/users/api/userendpoints/changeemail.py

@@ -16,10 +16,12 @@ def change_email_endpoint(request, pk=None):
     )
     )
 
 
     if serializer.is_valid():
     if serializer.is_valid():
-        token = store_new_credential(request, 'email', serializer.validated_data['new_email'])
+        token = store_new_credential(
+            request, 'email', serializer.validated_data['new_email']
+        )
 
 
         mail_subject = _("Confirm e-mail change on %(forum_name)s forums")
         mail_subject = _("Confirm e-mail change on %(forum_name)s forums")
-        mail_subject = mail_subject % {'forum_name': settings.forum_name}
+        mail_subject = mail_subject % {'forum_name': request.settings.forum_name}
 
 
         # swap address with new one so email is sent to new address
         # swap address with new one so email is sent to new address
         request.user.email = serializer.validated_data['new_email']
         request.user.email = serializer.validated_data['new_email']

+ 1 - 2
misago/users/api/userendpoints/changepassword.py

@@ -3,7 +3,6 @@ from rest_framework.response import Response
 
 
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
-from misago.conf import settings
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 from misago.users.credentialchange import store_new_credential
 from misago.users.credentialchange import store_new_credential
 from misago.users.serializers import ChangePasswordSerializer
 from misago.users.serializers import ChangePasswordSerializer
@@ -21,7 +20,7 @@ def change_password_endpoint(request, pk=None):
         )
         )
 
 
         mail_subject = _("Confirm password change on %(forum_name)s forums")
         mail_subject = _("Confirm password change on %(forum_name)s forums")
-        mail_subject = mail_subject % {'forum_name': settings.forum_name}
+        mail_subject = mail_subject % {'forum_name': request.settings.forum_name}
 
 
         mail_user(
         mail_user(
             request.user,
             request.user,

+ 18 - 15
misago/users/api/userendpoints/signature.py

@@ -4,7 +4,6 @@ from rest_framework.response import Response
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
-from misago.conf import settings
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 from misago.users.serializers import EditSignatureSerializer
 from misago.users.serializers import EditSignatureSerializer
 from misago.users.signatures import is_user_signature_valid, set_user_signature
 from misago.users.signatures import is_user_signature_valid, set_user_signature
@@ -22,19 +21,21 @@ def signature_endpoint(request):
         else:
         else:
             reason = None
             reason = None
 
 
-        return Response({
-            'detail': _("Your signature is locked. You can't change it."),
-            'reason': reason
-        },
-                        status=status.HTTP_403_FORBIDDEN)
+        return Response(
+            {
+                'detail': _("Your signature is locked. You can't change it."),
+                'reason': reason
+            },
+            status=status.HTTP_403_FORBIDDEN
+        )
 
 
     if request.method == 'POST':
     if request.method == 'POST':
         return edit_signature(request, user)
         return edit_signature(request, user)
 
 
-    return get_signature_options(user)
+    return get_signature_options(request.settings, user)
 
 
 
 
-def get_signature_options(user):
+def get_signature_options(settings, user):
     options = {
     options = {
         'signature': None,
         'signature': None,
         'limit': settings.signature_length_max,
         'limit': settings.signature_length_max,
@@ -53,14 +54,16 @@ def get_signature_options(user):
 
 
 
 
 def edit_signature(request, user):
 def edit_signature(request, user):
-    serializer = EditSignatureSerializer(user, data=request.data)
+    serializer = EditSignatureSerializer(
+        user, data=request.data, context={"settings": request.settings}
+    )
     if serializer.is_valid():
     if serializer.is_valid():
         signature = serializer.validated_data['signature']
         signature = serializer.validated_data['signature']
         set_user_signature(request, user, request.user_acl, signature)
         set_user_signature(request, user, request.user_acl, signature)
         user.save(update_fields=['signature', 'signature_parsed', 'signature_checksum'])
         user.save(update_fields=['signature', 'signature_parsed', 'signature_checksum'])
-        return get_signature_options(user)
-    else:
-        return Response({
-            'detail': serializer.errors['non_field_errors'][0]
-        },
-                        status=status.HTTP_400_BAD_REQUEST)
+        return get_signature_options(request.settings, user)
+
+    return Response(
+        {'detail': serializer.errors['non_field_errors'][0]},
+        status=status.HTTP_400_BAD_REQUEST
+    )

+ 22 - 23
misago/users/avatars/uploaded.py

@@ -9,12 +9,32 @@ from misago.conf import settings
 
 
 from . import store
 from . import store
 
 
-
 ALLOWED_EXTENSIONS = ('.gif', '.png', '.jpg', '.jpeg')
 ALLOWED_EXTENSIONS = ('.gif', '.png', '.jpg', '.jpeg')
 ALLOWED_MIME_TYPES = ('image/gif', 'image/jpeg', 'image/png', 'image/mpo')
 ALLOWED_MIME_TYPES = ('image/gif', 'image/jpeg', 'image/png', 'image/mpo')
 
 
 
 
-def validate_file_size(uploaded_file):
+def handle_uploaded_file(request, user, uploaded_file):
+    image = validate_uploaded_file(request.settings, uploaded_file)
+    store.store_temporary_avatar(user, image)
+
+
+def validate_uploaded_file(settings, uploaded_file):
+    try:
+        validate_file_size(settings, uploaded_file)
+        validate_extension(uploaded_file)
+        validate_mime(uploaded_file)
+        return validate_dimensions(uploaded_file)
+    except ValidationError as e:
+        try:
+            temporary_file_path = Path(uploaded_file.temporary_file_path())
+            if temporary_file_path.exists():
+                temporary_file_path.unlink()
+        except Exception:
+            pass
+        raise e
+
+
+def validate_file_size(settings, uploaded_file):
     upload_limit = settings.avatar_upload_limit * 1024
     upload_limit = settings.avatar_upload_limit * 1024
     if uploaded_file.size > upload_limit:
     if uploaded_file.size > upload_limit:
         raise ValidationError(_("Uploaded file is too big."))
         raise ValidationError(_("Uploaded file is too big."))
@@ -53,27 +73,6 @@ def validate_dimensions(uploaded_file):
     return image
     return image
 
 
 
 
-def validate_uploaded_file(uploaded_file):
-    try:
-        validate_file_size(uploaded_file)
-        validate_extension(uploaded_file)
-        validate_mime(uploaded_file)
-        return validate_dimensions(uploaded_file)
-    except ValidationError as e:
-        try:
-            temporary_file_path = Path(uploaded_file.temporary_file_path())
-            if temporary_file_path.exists():
-                temporary_file_path.unlink()
-        except Exception:
-            pass
-        raise e
-
-
-def handle_uploaded_file(user, uploaded_file):
-    image = validate_uploaded_file(uploaded_file)
-    store.store_temporary_avatar(user, image)
-
-
 def clean_crop(image, crop):
 def clean_crop(image, crop):
     message = _("Crop data is invalid. Please try again.")
     message = _("Crop data is invalid. Please try again.")
 
 

+ 10 - 10
misago/users/captcha.py

@@ -3,14 +3,12 @@ import requests
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
-from misago.conf import settings
-
 
 
 def recaptcha_test(request):
 def recaptcha_test(request):
     r = requests.post(
     r = requests.post(
         'https://www.google.com/recaptcha/api/siteverify',
         'https://www.google.com/recaptcha/api/siteverify',
         data={
         data={
-            'secret': settings.recaptcha_secret_key,
+            'secret': request.settings.recaptcha_secret_key,
             'response': request.data.get('captcha'),
             'response': request.data.get('captcha'),
             'remoteip': request.user_ip
             'remoteip': request.user_ip
         }
         }
@@ -25,15 +23,17 @@ def recaptcha_test(request):
 
 
 
 
 def qacaptcha_test(request):
 def qacaptcha_test(request):
-    answer = request.data.get('captcha', '').lower()
-    for predefined_answer in settings.qa_answers.lower().splitlines():
-        predefined_answer = predefined_answer.strip().lower()
-        if answer == predefined_answer:
-            break
-    else:
+    answer = request.data.get('captcha', '').lower().strip()
+    valid_answers = get_valid_qacaptcha_answers(request.settings)
+    if answer not in valid_answers:
         raise ValidationError(_("Entered answer is incorrect."))
         raise ValidationError(_("Entered answer is incorrect."))
 
 
 
 
+def get_valid_qacaptcha_answers(settings):
+    valid_answers = [i.strip() for i in settings.qa_answers.lower().splitlines()]
+    return filter(len, valid_answers)
+
+
 def nocaptcha_test(request):
 def nocaptcha_test(request):
     return  # no captcha means no validation
     return  # no captcha means no validation
 
 
@@ -46,4 +46,4 @@ CAPTCHA_TESTS = {
 
 
 
 
 def test_request(request):
 def test_request(request):
-    CAPTCHA_TESTS[settings.captcha_type](request)
+    CAPTCHA_TESTS[request.settings.captcha_type](request)

+ 4 - 3
misago/users/registration.py

@@ -1,6 +1,5 @@
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
-from misago.conf import settings
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
 from misago.legal.utils import save_user_agreement_acceptance
 from misago.legal.utils import save_user_agreement_acceptance
@@ -8,6 +7,8 @@ from misago.users.tokens import make_activation_token
 
 
 
 
 def send_welcome_email(request, user):
 def send_welcome_email(request, user):
+    settings = request.settings
+
     mail_subject = _("Welcome on %(forum_name)s forums!")
     mail_subject = _("Welcome on %(forum_name)s forums!")
     mail_subject = mail_subject % {'forum_name': settings.forum_name}
     mail_subject = mail_subject % {'forum_name': settings.forum_name}
 
 
@@ -16,7 +17,7 @@ def send_welcome_email(request, user):
             user,
             user,
             mail_subject,
             mail_subject,
             'misago/emails/register/complete',
             'misago/emails/register/complete',
-            context={"settings": request.settings},
+            context={"settings": settings},
         )
         )
         return
         return
 
 
@@ -33,7 +34,7 @@ def send_welcome_email(request, user):
             'activation_token': activation_token,
             'activation_token': activation_token,
             'activation_by_admin': activation_by_admin,
             'activation_by_admin': activation_by_admin,
             'activation_by_user': activation_by_user,
             'activation_by_user': activation_by_user,
-            'settings': request.settings,
+            'settings': settings,
         }
         }
     )
     )
 
 

+ 1 - 1
misago/users/serializers/options.py

@@ -4,7 +4,6 @@ from django.contrib.auth import get_user_model, logout
 from django.contrib.auth.password_validation import validate_password
 from django.contrib.auth.password_validation import validate_password
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
-from misago.conf import settings
 from misago.users.online.tracker import clear_tracking
 from misago.users.online.tracker import clear_tracking
 from misago.users.permissions import allow_delete_own_account
 from misago.users.permissions import allow_delete_own_account
 from misago.users.validators import validate_email, validate_username
 from misago.users.validators import validate_email, validate_username
@@ -48,6 +47,7 @@ class EditSignatureSerializer(serializers.ModelSerializer):
         fields = ['signature']
         fields = ['signature']
 
 
     def validate(self, data):
     def validate(self, data):
+        settings = self.context["settings"]
         if len(data.get('signature', '')) > settings.signature_length_max:
         if len(data.get('signature', '')) > settings.signature_length_max:
             raise serializers.ValidationError(_("Signature is too long."))
             raise serializers.ValidationError(_("Signature is too long."))
 
 

+ 12 - 10
misago/users/tests/test_avatars.py

@@ -1,4 +1,5 @@
 from pathlib import Path
 from pathlib import Path
+from unittest.mock import Mock
 
 
 from PIL import Image
 from PIL import Image
 
 
@@ -11,20 +12,19 @@ from misago.conf import settings
 from misago.users.avatars import dynamic, gallery, gravatar, set_default_avatar, store, uploaded
 from misago.users.avatars import dynamic, gallery, gravatar, set_default_avatar, store, uploaded
 from misago.users.models import Avatar, AvatarGallery
 from misago.users.models import Avatar, AvatarGallery
 
 
-
-UserModel = get_user_model()
+User = get_user_model()
 
 
 
 
 class AvatarsStoreTests(TestCase):
 class AvatarsStoreTests(TestCase):
     def test_store(self):
     def test_store(self):
         """store successfully stores and deletes avatar"""
         """store successfully stores and deletes avatar"""
-        user = UserModel.objects.create_user('Bob', 'bob@bob.com', 'pass123')
+        user = User.objects.create_user('Bob', 'bob@bob.com', 'pass123')
 
 
         test_image = Image.new("RGBA", (100, 100), 0)
         test_image = Image.new("RGBA", (100, 100), 0)
         store.store_new_avatar(user, test_image)
         store.store_new_avatar(user, test_image)
 
 
         # reload user
         # reload user
-        UserModel.objects.get(pk=user.pk)
+        User.objects.get(pk=user.pk)
 
 
         # assert that avatars were stored in media
         # assert that avatars were stored in media
         avatars_dict = {}
         avatars_dict = {}
@@ -85,7 +85,7 @@ class AvatarsStoreTests(TestCase):
 
 
 class AvatarSetterTests(TestCase):
 class AvatarSetterTests(TestCase):
     def setUp(self):
     def setUp(self):
-        self.user = UserModel.objects.create_user('Bob', 'kontakt@rpiton.com', 'pass123')
+        self.user = User.objects.create_user('Bob', 'kontakt@rpiton.com', 'pass123')
 
 
         self.user.avatars = None
         self.user.avatars = None
         self.user.save()
         self.user.save()
@@ -94,7 +94,7 @@ class AvatarSetterTests(TestCase):
         store.delete_avatar(self.user)
         store.delete_avatar(self.user)
 
 
     def get_current_user(self):
     def get_current_user(self):
-        return UserModel.objects.get(pk=self.user.pk)
+        return User.objects.get(pk=self.user.pk)
 
 
     def assertNoAvatarIsSet(self):
     def assertNoAvatarIsSet(self):
         user = self.get_current_user()
         user = self.get_current_user()
@@ -215,12 +215,14 @@ class UploadedAvatarTests(TestCase):
 
 
     def test_uploaded_image_size_validation(self):
     def test_uploaded_image_size_validation(self):
         """uploaded image size is validated"""
         """uploaded image size is validated"""
-        image = MockAvatarFile(size=settings.avatar_upload_limit * 2024)
+        settings = Mock(avatar_upload_limit=1)  # no. of MBs
+
+        image = MockAvatarFile(size=1025)
         with self.assertRaises(ValidationError):
         with self.assertRaises(ValidationError):
-            uploaded.validate_file_size(image)
+            uploaded.validate_file_size(settings, image)
 
 
-        image = MockAvatarFile(size=settings.avatar_upload_limit * 1000)
-        uploaded.validate_file_size(image)
+        image = MockAvatarFile(size=1024)
+        uploaded.validate_file_size(settings, image)
 
 
     def test_uploaded_image_extension_validation(self):
     def test_uploaded_image_extension_validation(self):
         """uploaded image extension is validated"""
         """uploaded image extension is validated"""

+ 10 - 11
misago/users/tests/test_captcha_api.py

@@ -1,31 +1,30 @@
 from django.test import TestCase
 from django.test import TestCase
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.conf import settings
+from misago.conf.test import override_dynamic_settings
+
+test_qa_question = "Do you like pies?"
+test_qa_help_text = 'Type in "yes".'
 
 
 
 
 class AuthenticateApiTests(TestCase):
 class AuthenticateApiTests(TestCase):
     def setUp(self):
     def setUp(self):
         self.api_link = reverse('misago:api:captcha-question')
         self.api_link = reverse('misago:api:captcha-question')
 
 
-    def tearDown(self):
-        settings.reset_settings()
-
+    @override_dynamic_settings(qa_question="")
     def test_api_no_qa_is_set(self):
     def test_api_no_qa_is_set(self):
         """qa api returns 404 if no QA question is set"""
         """qa api returns 404 if no QA question is set"""
-        settings.override_setting('qa_question', '')
-
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
+    @override_dynamic_settings(
+        qa_question=test_qa_question, qa_help_text=test_qa_help_text
+    )
     def test_api_get_question(self):
     def test_api_get_question(self):
         """qa api returns valid QA question"""
         """qa api returns valid QA question"""
-        settings.override_setting('qa_question', 'Do you like pies?')
-        settings.override_setting('qa_help_text', 'Type in "yes".')
-
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         response_json = response.json()
         response_json = response.json()
-        self.assertEqual(response_json['question'], 'Do you like pies?')
-        self.assertEqual(response_json['help_text'], 'Type in "yes".')
+        self.assertEqual(response_json['question'], test_qa_question)
+        self.assertEqual(response_json['help_text'], test_qa_help_text)

+ 38 - 21
misago/users/tests/test_social_pipeline.py

@@ -2,7 +2,7 @@ import json
 
 
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core import mail
 from django.core import mail
-from django.test import RequestFactory, override_settings
+from django.test import RequestFactory
 from social_core.backends.github import GithubOAuth2
 from social_core.backends.github import GithubOAuth2
 from social_django.utils import load_strategy
 from social_django.utils import load_strategy
 
 
@@ -10,6 +10,7 @@ from misago.acl import ACL_CACHE
 from misago.acl.useracl import get_user_acl
 from misago.acl.useracl import get_user_acl
 from misago.conf.dynamicsettings import DynamicSettings
 from misago.conf.dynamicsettings import DynamicSettings
 from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
 from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
+from misago.conf.test import override_dynamic_settings
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
 
 
@@ -41,6 +42,11 @@ def create_request(user_ip='0.0.0.0', data=None):
     return request
     return request
 
 
 
 
+def create_strategy():
+    request = create_request()
+    return load_strategy(request=request)
+
+
 class MockStrategy(object):
 class MockStrategy(object):
     def __init__(self, user_ip='0.0.0.0'):
     def __init__(self, user_ip='0.0.0.0'):
         self.cleaned_partial_token = None
         self.cleaned_partial_token = None
@@ -55,7 +61,8 @@ class PipelineTestCase(UserTestCase):
         self.user = self.get_authenticated_user()
         self.user = self.get_authenticated_user()
 
 
     def assertNewUserIsCorrect(
     def assertNewUserIsCorrect(
-            self, new_user, form_data=None, activation=None, email_verified=False):
+        self, new_user, form_data=None, activation=None, email_verified=False
+    ):
         self.assertFalse(new_user.has_usable_password())
         self.assertFalse(new_user.has_usable_password())
         self.assertIn('Welcome', mail.outbox[0].subject)
         self.assertIn('Welcome', mail.outbox[0].subject)
 
 
@@ -182,7 +189,7 @@ class CreateUser(PipelineTestCase):
         )
         )
         self.assertIsNone(result)
         self.assertIsNone(result)
 
 
-    @override_settings(account_activation='none')
+    @override_dynamic_settings(account_activation='none')
     def test_user_created_no_activation(self):
     def test_user_created_no_activation(self):
         """pipeline step creates active user for valid data and disabled activation"""
         """pipeline step creates active user for valid data and disabled activation"""
         result = create_user(
         result = create_user(
@@ -199,7 +206,7 @@ class CreateUser(PipelineTestCase):
         self.assertEqual(new_user.username, 'NewUser')
         self.assertEqual(new_user.username, 'NewUser')
         self.assertNewUserIsCorrect(new_user, email_verified=True, activation='none')
         self.assertNewUserIsCorrect(new_user, email_verified=True, activation='none')
 
 
-    @override_settings(account_activation='user')
+    @override_dynamic_settings(account_activation='user')
     def test_user_created_activation_by_user(self):
     def test_user_created_activation_by_user(self):
         """pipeline step creates active user for valid data and user activation"""
         """pipeline step creates active user for valid data and user activation"""
         result = create_user(
         result = create_user(
@@ -216,7 +223,7 @@ class CreateUser(PipelineTestCase):
         self.assertEqual(new_user.username, 'NewUser')
         self.assertEqual(new_user.username, 'NewUser')
         self.assertNewUserIsCorrect(new_user, email_verified=True, activation='user')
         self.assertNewUserIsCorrect(new_user, email_verified=True, activation='user')
 
 
-    @override_settings(account_activation='admin')
+    @override_dynamic_settings(account_activation='admin')
     def test_user_created_activation_by_admin(self):
     def test_user_created_activation_by_admin(self):
         """pipeline step creates in user for valid data and admin activation"""
         """pipeline step creates in user for valid data and admin activation"""
         result = create_user(
         result = create_user(
@@ -316,7 +323,7 @@ class CreateUserWithFormTests(PipelineTestCase):
             'username': ["This username is not available."],
             'username': ["This username is not available."],
         })
         })
 
 
-    @override_settings(account_activation='none')
+    @override_dynamic_settings(account_activation='none')
     def test_user_created_no_activation_verified_email(self):
     def test_user_created_no_activation_verified_email(self):
         """active user is created for verified email and activation disabled"""
         """active user is created for verified email and activation disabled"""
         form_data = {
         form_data = {
@@ -340,7 +347,7 @@ class CreateUserWithFormTests(PipelineTestCase):
 
 
         self.assertNewUserIsCorrect(new_user, form_data, activation='none', email_verified=True)
         self.assertNewUserIsCorrect(new_user, form_data, activation='none', email_verified=True)
 
 
-    @override_settings(account_activation='none')
+    @override_dynamic_settings(account_activation='none')
     def test_user_created_no_activation_nonverified_email(self):
     def test_user_created_no_activation_nonverified_email(self):
         """active user is created for non-verified email and activation disabled"""
         """active user is created for non-verified email and activation disabled"""
         form_data = {
         form_data = {
@@ -364,7 +371,7 @@ class CreateUserWithFormTests(PipelineTestCase):
 
 
         self.assertNewUserIsCorrect(new_user, form_data, activation='none', email_verified=False)
         self.assertNewUserIsCorrect(new_user, form_data, activation='none', email_verified=False)
 
 
-    @override_settings(account_activation='user')
+    @override_dynamic_settings(account_activation='user')
     def test_user_created_activation_by_user_verified_email(self):
     def test_user_created_activation_by_user_verified_email(self):
         """active user is created for verified email and activation by user"""
         """active user is created for verified email and activation by user"""
         form_data = {
         form_data = {
@@ -388,7 +395,7 @@ class CreateUserWithFormTests(PipelineTestCase):
 
 
         self.assertNewUserIsCorrect(new_user, form_data, activation='user', email_verified=True)
         self.assertNewUserIsCorrect(new_user, form_data, activation='user', email_verified=True)
 
 
-    @override_settings(account_activation='user')
+    @override_dynamic_settings(account_activation='user')
     def test_user_created_activation_by_user_nonverified_email(self):
     def test_user_created_activation_by_user_nonverified_email(self):
         """inactive user is created for non-verified email and activation by user"""
         """inactive user is created for non-verified email and activation by user"""
         form_data = {
         form_data = {
@@ -412,7 +419,7 @@ class CreateUserWithFormTests(PipelineTestCase):
 
 
         self.assertNewUserIsCorrect(new_user, form_data, activation='user', email_verified=False)
         self.assertNewUserIsCorrect(new_user, form_data, activation='user', email_verified=False)
 
 
-    @override_settings(account_activation='admin')
+    @override_dynamic_settings(account_activation='admin')
     def test_user_created_activation_by_admin_verified_email(self):
     def test_user_created_activation_by_admin_verified_email(self):
         """inactive user is created for verified email and activation by admin"""
         """inactive user is created for verified email and activation by admin"""
         form_data = {
         form_data = {
@@ -436,7 +443,7 @@ class CreateUserWithFormTests(PipelineTestCase):
 
 
         self.assertNewUserIsCorrect(new_user, form_data, activation='admin', email_verified=True)
         self.assertNewUserIsCorrect(new_user, form_data, activation='admin', email_verified=True)
 
 
-    @override_settings(account_activation='admin')
+    @override_dynamic_settings(account_activation='admin')
     def test_user_created_activation_by_admin_nonverified_email(self):
     def test_user_created_activation_by_admin_nonverified_email(self):
         """inactive user is created for non-verified email and activation by admin"""
         """inactive user is created for non-verified email and activation by admin"""
         form_data = {
         form_data = {
@@ -571,77 +578,87 @@ class CreateUserWithFormTests(PipelineTestCase):
 class GetUsernameTests(PipelineTestCase):
 class GetUsernameTests(PipelineTestCase):
     def test_skip_if_user_is_set(self):
     def test_skip_if_user_is_set(self):
         """pipeline step is skipped if user was passed"""
         """pipeline step is skipped if user was passed"""
-        result = get_username(None, {}, None, user=self.user)
+        strategy = create_strategy()
+        result = get_username(strategy, {}, None, user=self.user)
         self.assertIsNone(result)
         self.assertIsNone(result)
 
 
     def test_skip_if_no_names(self):
     def test_skip_if_no_names(self):
         """pipeline step is skipped if API returned no names"""
         """pipeline step is skipped if API returned no names"""
-        result = get_username(None, {}, None)
+        strategy = create_strategy()
+        result = get_username(strategy, {}, None)
         self.assertIsNone(result)
         self.assertIsNone(result)
 
 
     def test_resolve_to_username(self):
     def test_resolve_to_username(self):
         """pipeline step resolves username"""
         """pipeline step resolves username"""
-        result = get_username(None, {'username': 'BobBoberson'}, None)
+        strategy = create_strategy()
+        result = get_username(strategy, {'username': 'BobBoberson'}, None)
         self.assertEqual(result, {'clean_username': 'BobBoberson'})
         self.assertEqual(result, {'clean_username': 'BobBoberson'})
 
 
     def test_normalize_username(self):
     def test_normalize_username(self):
         """pipeline step normalizes username"""
         """pipeline step normalizes username"""
-        result = get_username(None, {'username': 'Błop Błoperson'}, None)
+        strategy = create_strategy()
+        result = get_username(strategy, {'username': 'Błop Błoperson'}, None)
         self.assertEqual(result, {'clean_username': 'BlopBloperson'})
         self.assertEqual(result, {'clean_username': 'BlopBloperson'})
 
 
     def test_resolve_to_first_name(self):
     def test_resolve_to_first_name(self):
         """pipeline attempts to use first name because username is taken"""
         """pipeline attempts to use first name because username is taken"""
+        strategy = create_strategy()
         details = {
         details = {
             'username': self.user.username,
             'username': self.user.username,
             'first_name': 'Błob',
             'first_name': 'Błob',
         }
         }
-        result = get_username(None, details, None)
+        result = get_username(strategy, details, None)
         self.assertEqual(result, {'clean_username': 'Blob'})
         self.assertEqual(result, {'clean_username': 'Blob'})
 
 
     def test_dont_resolve_to_last_name(self):
     def test_dont_resolve_to_last_name(self):
         """pipeline will not fallback to last name because username is taken"""
         """pipeline will not fallback to last name because username is taken"""
+        strategy = create_strategy()
         details = {
         details = {
             'username': self.user.username,
             'username': self.user.username,
             'last_name': 'Błob',
             'last_name': 'Błob',
         }
         }
-        result = get_username(None, details, None)
+        result = get_username(strategy, details, None)
         self.assertIsNone(result)
         self.assertIsNone(result)
 
 
     def test_resolve_to_first_last_name_first_char(self):
     def test_resolve_to_first_last_name_first_char(self):
         """pipeline will construct username from first name and first char of surname"""
         """pipeline will construct username from first name and first char of surname"""
+        strategy = create_strategy()
         details = {
         details = {
             'first_name': self.user.username,
             'first_name': self.user.username,
             'last_name': 'Błob',
             'last_name': 'Błob',
         }
         }
-        result = get_username(None, details, None)
+        result = get_username(strategy, details, None)
         self.assertEqual(result, {'clean_username': self.user.username + 'B'})
         self.assertEqual(result, {'clean_username': self.user.username + 'B'})
 
 
     def test_dont_resolve_to_banned_name(self):
     def test_dont_resolve_to_banned_name(self):
         """pipeline will not resolve to banned name"""
         """pipeline will not resolve to banned name"""
+        strategy = create_strategy()
         Ban.objects.create(banned_value='*Admin*', check_type=Ban.USERNAME)
         Ban.objects.create(banned_value='*Admin*', check_type=Ban.USERNAME)
         details = {
         details = {
             'username': 'Misago Admin',
             'username': 'Misago Admin',
             'first_name': 'Błob',
             'first_name': 'Błob',
         }
         }
-        result = get_username(None, details, None)
+        result = get_username(strategy, details, None)
         self.assertEqual(result, {'clean_username': 'Blob'})
         self.assertEqual(result, {'clean_username': 'Blob'})
 
 
     def test_resolve_full_name(self):
     def test_resolve_full_name(self):
         """pipeline will resolve to full name"""
         """pipeline will resolve to full name"""
+        strategy = create_strategy()
         Ban.objects.create(banned_value='*Admin*', check_type=Ban.USERNAME)
         Ban.objects.create(banned_value='*Admin*', check_type=Ban.USERNAME)
         details = {
         details = {
             'username': 'Misago Admin',
             'username': 'Misago Admin',
             'full_name': 'Błob Błopo',
             'full_name': 'Błob Błopo',
         }
         }
-        result = get_username(None, details, None)
+        result = get_username(strategy, details, None)
         self.assertEqual(result, {'clean_username': 'BlobBlopo'})
         self.assertEqual(result, {'clean_username': 'BlobBlopo'})
 
 
     def test_resolve_to_cut_name(self):
     def test_resolve_to_cut_name(self):
         """pipeline will resolve cut too long name on second pass"""
         """pipeline will resolve cut too long name on second pass"""
+        strategy = create_strategy()
         details = {
         details = {
             'username': 'Abrakadabrapokuskonstantynopolitańczykowianeczkatrzy',
             'username': 'Abrakadabrapokuskonstantynopolitańczykowianeczkatrzy',
         }
         }
-        result = get_username(None, details, None)
+        result = get_username(strategy, details, None)
         self.assertEqual(result, {'clean_username': 'Abrakadabrapok'})
         self.assertEqual(result, {'clean_username': 'Abrakadabrapok'})
 
 
 
 

+ 31 - 31
misago/users/tests/test_user_avatar_api.py

@@ -6,15 +6,15 @@ from django.contrib.auth import get_user_model
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.conf import settings
 from misago.conf import settings
+from misago.conf.test import override_dynamic_settings
 from misago.users.avatars import gallery, store
 from misago.users.avatars import gallery, store
 from misago.users.models import AvatarGallery
 from misago.users.models import AvatarGallery
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
 TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, 'avatar.png')
 TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, 'avatar.png')
 
 
-UserModel = get_user_model()
+User = get_user_model()
 
 
 
 
 class UserAvatarTests(AuthenticatedUserTestCase):
 class UserAvatarTests(AuthenticatedUserTestCase):
@@ -26,40 +26,40 @@ class UserAvatarTests(AuthenticatedUserTestCase):
         self.client.post(self.link, data={'avatar': 'generated'})
         self.client.post(self.link, data={'avatar': 'generated'})
 
 
     def get_current_user(self):
     def get_current_user(self):
-        return UserModel.objects.get(pk=self.user.pk)
+        return User.objects.get(pk=self.user.pk)
 
 
     def assertOldAvatarsAreDeleted(self, user):
     def assertOldAvatarsAreDeleted(self, user):
         self.assertEqual(
         self.assertEqual(
             user.avatar_set.count(), len(settings.MISAGO_AVATARS_SIZES)
             user.avatar_set.count(), len(settings.MISAGO_AVATARS_SIZES)
         )
         )
 
 
+    @override_dynamic_settings(allow_custom_avatars=False)
     def test_avatars_off(self):
     def test_avatars_off(self):
         """custom avatars are not allowed"""
         """custom avatars are not allowed"""
-        with self.settings(allow_custom_avatars=False):
-            response = self.client.get(self.link)
-            self.assertEqual(response.status_code, 200)
-
-            options = response.json()
-            self.assertTrue(options['generated'])
-            self.assertFalse(options['gravatar'])
-            self.assertFalse(options['crop_src'])
-            self.assertFalse(options['crop_tmp'])
-            self.assertFalse(options['upload'])
-            self.assertFalse(options['galleries'])
+        response = self.client.get(self.link)
+        self.assertEqual(response.status_code, 200)
 
 
+        options = response.json()
+        self.assertTrue(options['generated'])
+        self.assertFalse(options['gravatar'])
+        self.assertFalse(options['crop_src'])
+        self.assertFalse(options['crop_tmp'])
+        self.assertFalse(options['upload'])
+        self.assertFalse(options['galleries'])
+
+    @override_dynamic_settings(allow_custom_avatars=True)
     def test_avatars_on(self):
     def test_avatars_on(self):
-        """custom avatars are not allowed"""
-        with self.settings(allow_custom_avatars=True):
-            response = self.client.get(self.link)
-            self.assertEqual(response.status_code, 200)
+        """custom avatars are allowed"""
+        response = self.client.get(self.link)
+        self.assertEqual(response.status_code, 200)
 
 
-            options = response.json()
-            self.assertTrue(options['generated'])
-            self.assertTrue(options['gravatar'])
-            self.assertFalse(options['crop_src'])
-            self.assertFalse(options['crop_tmp'])
-            self.assertTrue(options['upload'])
-            self.assertFalse(options['galleries'])
+        options = response.json()
+        self.assertTrue(options['generated'])
+        self.assertTrue(options['gravatar'])
+        self.assertFalse(options['crop_src'])
+        self.assertFalse(options['crop_tmp'])
+        self.assertTrue(options['upload'])
+        self.assertFalse(options['galleries'])
 
 
     def test_gallery_exists(self):
     def test_gallery_exists(self):
         """api returns gallery"""
         """api returns gallery"""
@@ -95,7 +95,7 @@ class UserAvatarTests(AuthenticatedUserTestCase):
         })
         })
 
 
         self.login_user(
         self.login_user(
-            UserModel.objects.create_user("BobUser", "bob@bob.com", self.USER_PASSWORD)
+            User.objects.create_user("BobUser", "bob@bob.com", self.USER_PASSWORD)
         )
         )
 
 
         response = self.client.get(self.link)
         response = self.client.get(self.link)
@@ -347,7 +347,7 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.other_user = UserModel.objects.create_user("OtherUser", "other@user.com", "pass123")
+        self.other_user = User.objects.create_user("OtherUser", "other@user.com", "pass123")
 
 
         self.link = '/api/users/%s/moderate-avatar/' % self.other_user.pk
         self.link = '/api/users/%s/moderate-avatar/' % self.other_user.pk
 
 
@@ -386,7 +386,7 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        other_user = UserModel.objects.get(pk=self.other_user.pk)
+        other_user = User.objects.get(pk=self.other_user.pk)
 
 
         options = response.json()
         options = response.json()
         self.assertEqual(other_user.is_avatar_locked, True)
         self.assertEqual(other_user.is_avatar_locked, True)
@@ -411,7 +411,7 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        other_user = UserModel.objects.get(pk=self.other_user.pk)
+        other_user = User.objects.get(pk=self.other_user.pk)
         self.assertFalse(other_user.is_avatar_locked)
         self.assertFalse(other_user.is_avatar_locked)
         self.assertIsNone(other_user.avatar_lock_user_message)
         self.assertIsNone(other_user.avatar_lock_user_message)
         self.assertIsNone(other_user.avatar_lock_staff_message)
         self.assertIsNone(other_user.avatar_lock_staff_message)
@@ -435,7 +435,7 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        other_user = UserModel.objects.get(pk=self.other_user.pk)
+        other_user = User.objects.get(pk=self.other_user.pk)
         self.assertTrue(other_user.is_avatar_locked)
         self.assertTrue(other_user.is_avatar_locked)
         self.assertEqual(other_user.avatar_lock_user_message, '')
         self.assertEqual(other_user.avatar_lock_user_message, '')
         self.assertEqual(other_user.avatar_lock_staff_message, '')
         self.assertEqual(other_user.avatar_lock_staff_message, '')
@@ -457,7 +457,7 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        other_user = UserModel.objects.get(pk=self.other_user.pk)
+        other_user = User.objects.get(pk=self.other_user.pk)
         self.assertFalse(other_user.is_avatar_locked)
         self.assertFalse(other_user.is_avatar_locked)
         self.assertEqual(other_user.avatar_lock_user_message, '')
         self.assertEqual(other_user.avatar_lock_user_message, '')
         self.assertEqual(other_user.avatar_lock_staff_message, '')
         self.assertEqual(other_user.avatar_lock_staff_message, '')

+ 46 - 25
misago/users/tests/test_user_create_api.py

@@ -1,15 +1,13 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core import mail
 from django.core import mail
-from django.test import override_settings
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.conf import settings
+from misago.conf.test import override_dynamic_settings
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
 from misago.users.models import Ban, Online
 from misago.users.models import Ban, Online
 from misago.users.testutils import UserTestCase
 from misago.users.testutils import UserTestCase
 
 
-
-UserModel = get_user_model()
+User = get_user_model()
 
 
 
 
 class UserCreateTests(UserTestCase):
 class UserCreateTests(UserTestCase):
@@ -58,10 +56,9 @@ class UserCreateTests(UserTestCase):
             "detail": "This action is not available to signed in users."
             "detail": "This action is not available to signed in users."
         })
         })
 
 
+    @override_dynamic_settings(account_activation="closed")
     def test_registration_off_request(self):
     def test_registration_off_request(self):
         """registrations off request errors with code 403"""
         """registrations off request errors with code 403"""
-        settings.override_setting('account_activation', 'closed')
-
         response = self.client.post(self.api_link)
         response = self.client.post(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.json(), {
         self.assertEqual(response.json(), {
@@ -290,7 +287,11 @@ class UserCreateTests(UserTestCase):
             "password": ["The password is too similar to the username."],
             "password": ["The password is too similar to the username."],
         })
         })
 
 
-    @override_settings(captcha_type='qa', qa_question='Test', qa_answers='Lorem\nIpsum')
+    @override_dynamic_settings(
+        captcha_type='qa',
+        qa_question='Test',
+        qa_answers='Lorem\nIpsum'
+    )
     def test_registration_validates_captcha(self):
     def test_registration_validates_captcha(self):
         """api validates captcha"""
         """api validates captcha"""
         response = self.client.post(
         response = self.client.post(
@@ -323,6 +324,30 @@ class UserCreateTests(UserTestCase):
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
+    @override_dynamic_settings(
+        captcha_type='qa',
+        qa_question='',
+        qa_answers='Lorem\n\nIpsum'
+    )
+    def test_qacaptcha_handles_empty_answers(self):
+        """api validates captcha"""
+        response = self.client.post(
+            self.api_link,
+            data={
+                'username': 'totallyNew',
+                'email': 'loremipsum@dolor.met',
+                'password': 'LoremP4ssword',
+                'captcha': ''
+            },
+        )
+
+        self.assertEqual(response.status_code, 400)
+        self.assertEqual(
+            response.json(), {
+                'captcha': ['Entered answer is incorrect.'],
+            }
+        )
+
     def test_registration_check_agreement(self):
     def test_registration_check_agreement(self):
         """api checks agreement"""
         """api checks agreement"""
         agreement = Agreement.objects.create(
         agreement = Agreement.objects.create(
@@ -378,7 +403,7 @@ class UserCreateTests(UserTestCase):
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         
         
-        user = UserModel.objects.get(email='loremipsum@dolor.met')
+        user = User.objects.get(email='loremipsum@dolor.met')
         self.assertEqual(user.agreements, [agreement.id])
         self.assertEqual(user.agreements, [agreement.id])
         self.assertEqual(user.useragreement_set.count(), 1)
         self.assertEqual(user.useragreement_set.count(), 1)
 
 
@@ -402,7 +427,7 @@ class UserCreateTests(UserTestCase):
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         
         
-        user = UserModel.objects.get(email='loremipsum@dolor.met')
+        user = User.objects.get(email='loremipsum@dolor.met')
         self.assertEqual(user.agreements, [])
         self.assertEqual(user.agreements, [])
         self.assertEqual(user.useragreement_set.count(), 0)
         self.assertEqual(user.useragreement_set.count(), 0)
 
 
@@ -422,10 +447,9 @@ class UserCreateTests(UserTestCase):
             "password": ["This password is too short. It must contain at least 7 characters."],
             "password": ["This password is too short. It must contain at least 7 characters."],
         })
         })
 
 
+    @override_dynamic_settings(account_activation="none")
     def test_registration_creates_active_user(self):
     def test_registration_creates_active_user(self):
         """api creates active and signed in user on POST"""
         """api creates active and signed in user on POST"""
-        settings.override_setting('account_activation', 'none')
-
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
@@ -441,9 +465,9 @@ class UserCreateTests(UserTestCase):
             'email': 'bob@bob.com',
             'email': 'bob@bob.com',
         })
         })
 
 
-        UserModel.objects.get_by_username('Bob')
+        User.objects.get_by_username('Bob')
 
 
-        test_user = UserModel.objects.get_by_email('bob@bob.com')
+        test_user = User.objects.get_by_email('bob@bob.com')
         self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
         self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
 
 
         self.assertTrue(test_user.check_password('pass123'))
         self.assertTrue(test_user.check_password('pass123'))
@@ -456,10 +480,9 @@ class UserCreateTests(UserTestCase):
 
 
         self.assertEqual(test_user.audittrail_set.count(), 1)
         self.assertEqual(test_user.audittrail_set.count(), 1)
 
 
+    @override_dynamic_settings(account_activation="user")
     def test_registration_creates_inactive_user(self):
     def test_registration_creates_inactive_user(self):
         """api creates inactive user on POST"""
         """api creates inactive user on POST"""
-        settings.override_setting('account_activation', 'user')
-
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
@@ -478,15 +501,14 @@ class UserCreateTests(UserTestCase):
         auth_json = self.client.get(reverse('misago:api:auth')).json()
         auth_json = self.client.get(reverse('misago:api:auth')).json()
         self.assertFalse(auth_json['is_authenticated'])
         self.assertFalse(auth_json['is_authenticated'])
 
 
-        UserModel.objects.get_by_username('Bob')
-        UserModel.objects.get_by_email('bob@bob.com')
+        User.objects.get_by_username('Bob')
+        User.objects.get_by_email('bob@bob.com')
 
 
         self.assertIn('Welcome', mail.outbox[0].subject)
         self.assertIn('Welcome', mail.outbox[0].subject)
 
 
+    @override_dynamic_settings(account_activation="admin")
     def test_registration_creates_admin_activated_user(self):
     def test_registration_creates_admin_activated_user(self):
         """api creates admin activated user on POST"""
         """api creates admin activated user on POST"""
-        settings.override_setting('account_activation', 'admin')
-
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
@@ -505,15 +527,14 @@ class UserCreateTests(UserTestCase):
         auth_json = self.client.get(reverse('misago:api:auth')).json()
         auth_json = self.client.get(reverse('misago:api:auth')).json()
         self.assertFalse(auth_json['is_authenticated'])
         self.assertFalse(auth_json['is_authenticated'])
 
 
-        UserModel.objects.get_by_username('Bob')
-        UserModel.objects.get_by_email('bob@bob.com')
+        User.objects.get_by_username('Bob')
+        User.objects.get_by_email('bob@bob.com')
 
 
         self.assertIn('Welcome', mail.outbox[0].subject)
         self.assertIn('Welcome', mail.outbox[0].subject)
 
 
+    @override_dynamic_settings(account_activation="none")
     def test_registration_creates_user_with_whitespace_password(self):
     def test_registration_creates_user_with_whitespace_password(self):
         """api creates user with spaces around password"""
         """api creates user with spaces around password"""
-        settings.override_setting('account_activation', 'none')
-
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
@@ -529,9 +550,9 @@ class UserCreateTests(UserTestCase):
             'email': 'bob@bob.com',
             'email': 'bob@bob.com',
         })
         })
 
 
-        UserModel.objects.get_by_username('Bob')
+        User.objects.get_by_username('Bob')
 
 
-        test_user = UserModel.objects.get_by_email('bob@bob.com')
+        test_user = User.objects.get_by_email('bob@bob.com')
         self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
         self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
         self.assertTrue(test_user.check_password(' pass123 '))
         self.assertTrue(test_user.check_password(' pass123 '))