Merge pull request #5967 from FinnStutzenstein/loginErrorNonActive
Add login errors for inactive users
This commit is contained in:
commit
2e1690d2d0
@ -99,18 +99,21 @@ STATICFILES_DIRS = [os.path.join(MODULE_DIR, "static")] + [
|
|||||||
STATIC_ROOT = os.path.join(OPENSLIDES_USER_DATA_DIR, "collected-static")
|
STATIC_ROOT = os.path.join(OPENSLIDES_USER_DATA_DIR, "collected-static")
|
||||||
|
|
||||||
# Files
|
# Files
|
||||||
# https://docs.djangoproject.com/en/1.10/topics/files/
|
# https://docs.djangoproject.com/en/2.2/topics/files/
|
||||||
MEDIA_ROOT = os.path.join(OPENSLIDES_USER_DATA_DIR, "media", "")
|
MEDIA_ROOT = os.path.join(OPENSLIDES_USER_DATA_DIR, "media", "")
|
||||||
|
|
||||||
|
MEDIA_URL = "/media/"
|
||||||
|
|
||||||
# Sessions and user authentication
|
# Sessions and user authentication
|
||||||
# https://docs.djangoproject.com/en/1.10/topics/http/sessions/
|
# https://docs.djangoproject.com/en/2.2/topics/http/sessions/
|
||||||
# https://docs.djangoproject.com/en/1.10/topics/auth/
|
# https://docs.djangoproject.com/en/2.2/topics/auth/
|
||||||
|
|
||||||
AUTH_USER_MODEL = "users.User"
|
AUTH_USER_MODEL = "users.User"
|
||||||
|
|
||||||
AUTH_GROUP_MODEL = "users.Group"
|
AUTH_GROUP_MODEL = "users.Group"
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = ["openslides.utils.auth_backend.ModelBackend"]
|
||||||
|
|
||||||
SESSION_COOKIE_NAME = "OpenSlidesSessionID"
|
SESSION_COOKIE_NAME = "OpenSlidesSessionID"
|
||||||
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
||||||
@ -127,12 +130,5 @@ PASSWORD_HASHERS = [
|
|||||||
"django.contrib.auth.hashers.BCryptPasswordHasher",
|
"django.contrib.auth.hashers.BCryptPasswordHasher",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# Files
|
|
||||||
# https://docs.djangoproject.com/en/1.10/topics/files/
|
|
||||||
|
|
||||||
MEDIA_URL = "/media/"
|
|
||||||
|
|
||||||
|
|
||||||
# Enable updating the last_login field for users on every login.
|
# Enable updating the last_login field for users on every login.
|
||||||
ENABLE_LAST_LOGIN_FIELD = False
|
ENABLE_LAST_LOGIN_FIELD = False
|
||||||
|
@ -5,11 +5,11 @@ from typing import Iterable, List, Set, Union
|
|||||||
from asgiref.sync import async_to_sync
|
from asgiref.sync import async_to_sync
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import (
|
from django.contrib.auth import (
|
||||||
|
authenticate as auth_authenticate,
|
||||||
login as auth_login,
|
login as auth_login,
|
||||||
logout as auth_logout,
|
logout as auth_logout,
|
||||||
update_session_auth_hash,
|
update_session_auth_hash,
|
||||||
)
|
)
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.auth.password_validation import validate_password
|
from django.contrib.auth.password_validation import validate_password
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
@ -888,13 +888,19 @@ class UserLoginView(WhoAmIDataView):
|
|||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Cookies have to be enabled to use OpenSlides."}
|
{"detail": "Cookies have to be enabled to use OpenSlides."}
|
||||||
)
|
)
|
||||||
form = AuthenticationForm(self.request, data=self.request.data)
|
|
||||||
if not form.is_valid():
|
username = self.request.data.get("username")
|
||||||
|
password = self.request.data.get("password")
|
||||||
|
user = auth_authenticate(self.request, username=username, password=password)
|
||||||
|
if user is None:
|
||||||
raise ValidationError({"detail": "Username or password is not correct."})
|
raise ValidationError({"detail": "Username or password is not correct."})
|
||||||
self.user = form.get_user()
|
elif not user.is_active:
|
||||||
if self.user.auth_type != "default":
|
raise ValidationError({"detail": "You are not active."})
|
||||||
raise ValidationError({"detail": "Please login via your identity provider"})
|
elif user.auth_type != "default":
|
||||||
auth_login(self.request, self.user)
|
raise ValidationError(
|
||||||
|
{"detail": "Please login via your identity provider."}
|
||||||
|
)
|
||||||
|
auth_login(self.request, user)
|
||||||
return super().post(*args, **kwargs)
|
return super().post(*args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **context):
|
def get_context_data(self, **context):
|
||||||
|
14
server/openslides/utils/auth_backend.py
Normal file
14
server/openslides/utils/auth_backend.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.backends import ModelBackend as _ModelBackend
|
||||||
|
|
||||||
|
|
||||||
|
class ModelBackend(_ModelBackend):
|
||||||
|
def user_can_authenticate(self, user: Any) -> bool:
|
||||||
|
"""
|
||||||
|
Overwrite the default check for is_active.
|
||||||
|
This allows us to do the check it later to distinguish between a user
|
||||||
|
have not the right credentials and having the right credentials but
|
||||||
|
not being active.
|
||||||
|
"""
|
||||||
|
return True
|
@ -3,6 +3,7 @@ import json
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
from openslides.users.models import User
|
||||||
from tests.test_case import TestCase
|
from tests.test_case import TestCase
|
||||||
|
|
||||||
|
|
||||||
@ -101,6 +102,8 @@ class TestUserLoginView(TestCase):
|
|||||||
response = self.client.post(self.url)
|
response = self.client.post(self.url)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertEqual(response.status_code, 400)
|
||||||
|
content = json.loads(response.content.decode())
|
||||||
|
self.assertEqual(content.get("detail"), "Username or password is not correct.")
|
||||||
|
|
||||||
def test_post_correct_data(self):
|
def test_post_correct_data(self):
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
@ -121,3 +124,41 @@ class TestUserLoginView(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertEqual(response.status_code, 400)
|
||||||
|
content = json.loads(response.content.decode())
|
||||||
|
self.assertEqual(content.get("detail"), "Username or password is not correct.")
|
||||||
|
|
||||||
|
def test_user_inactive(self):
|
||||||
|
admin = User.objects.get()
|
||||||
|
admin.is_active = False
|
||||||
|
admin.save()
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
self.url, {"username": "admin", "password": "admin"}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
content = json.loads(response.content.decode())
|
||||||
|
self.assertEqual(content.get("detail"), "You are not active.")
|
||||||
|
|
||||||
|
def test_user_wrong_auth_type(self):
|
||||||
|
admin = User.objects.get()
|
||||||
|
admin.auth_type = "not default"
|
||||||
|
admin.save()
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
self.url, {"username": "admin", "password": "admin"}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
content = json.loads(response.content.decode())
|
||||||
|
self.assertEqual(
|
||||||
|
content.get("detail"), "Please login via your identity provider."
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_no_cookies(self):
|
||||||
|
response = self.client.post(
|
||||||
|
self.url, {"username": "admin", "password": "admin", "cookies": False}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
content = json.loads(response.content.decode())
|
||||||
|
self.assertEqual(
|
||||||
|
content.get("detail"), "Cookies have to be enabled to use OpenSlides."
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user