Remove JWT related code
This commit is contained in:
parent
f1f9f935cf
commit
88de997603
2
.env.dev
2
.env.dev
|
@ -3,7 +3,7 @@ DJANGO_SETTINGS_MODULE=config.settings.local
|
||||||
DJANGO_SECRET_KEY=dev
|
DJANGO_SECRET_KEY=dev
|
||||||
C_FORCE_ROOT=true
|
C_FORCE_ROOT=true
|
||||||
FUNKWHALE_HOSTNAME=localhost
|
FUNKWHALE_HOSTNAME=localhost
|
||||||
FUNKWHALE_PROTOCOL=http
|
FUNKWHALE_PROTOCOL=https
|
||||||
PYTHONDONTWRITEBYTECODE=true
|
PYTHONDONTWRITEBYTECODE=true
|
||||||
VUE_PORT=8080
|
VUE_PORT=8080
|
||||||
MUSIC_DIRECTORY_PATH=/music
|
MUSIC_DIRECTORY_PATH=/music
|
||||||
|
|
|
@ -10,7 +10,6 @@ from funkwhale_api.music import views
|
||||||
from funkwhale_api.playlists import views as playlists_views
|
from funkwhale_api.playlists import views as playlists_views
|
||||||
from funkwhale_api.subsonic.views import SubsonicViewSet
|
from funkwhale_api.subsonic.views import SubsonicViewSet
|
||||||
from funkwhale_api.tags import views as tags_views
|
from funkwhale_api.tags import views as tags_views
|
||||||
from funkwhale_api.users import jwt_views
|
|
||||||
|
|
||||||
router = common_routers.OptionalSlashRouter()
|
router = common_routers.OptionalSlashRouter()
|
||||||
router.register(r"activity", activity_views.ActivityViewSet, "activity")
|
router.register(r"activity", activity_views.ActivityViewSet, "activity")
|
||||||
|
@ -84,8 +83,6 @@ v1_patterns += [
|
||||||
r"^oauth/",
|
r"^oauth/",
|
||||||
include(("funkwhale_api.users.oauth.urls", "oauth"), namespace="oauth"),
|
include(("funkwhale_api.users.oauth.urls", "oauth"), namespace="oauth"),
|
||||||
),
|
),
|
||||||
url(r"^token/?$", jwt_views.obtain_jwt_token, name="token"),
|
|
||||||
url(r"^token/refresh/?$", jwt_views.refresh_jwt_token, name="token_refresh"),
|
|
||||||
url(r"^rate-limit/?$", common_views.RateLimitView.as_view(), name="rate-limit"),
|
url(r"^rate-limit/?$", common_views.RateLimitView.as_view(), name="rate-limit"),
|
||||||
url(
|
url(
|
||||||
r"^text-preview/?$", common_views.TextPreviewView.as_view(), name="text-preview"
|
r"^text-preview/?$", common_views.TextPreviewView.as_view(), name="text-preview"
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import datetime
|
|
||||||
import logging.config
|
import logging.config
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -812,13 +811,6 @@ def get_user_secret_key(user):
|
||||||
return settings.SECRET_KEY + str(user.secret_key)
|
return settings.SECRET_KEY + str(user.secret_key)
|
||||||
|
|
||||||
|
|
||||||
JWT_AUTH = {
|
|
||||||
"JWT_ALLOW_REFRESH": True,
|
|
||||||
"JWT_EXPIRATION_DELTA": datetime.timedelta(days=7),
|
|
||||||
"JWT_REFRESH_EXPIRATION_DELTA": datetime.timedelta(days=30),
|
|
||||||
"JWT_AUTH_HEADER_PREFIX": "JWT",
|
|
||||||
"JWT_GET_USER_SECRET_KEY": get_user_secret_key,
|
|
||||||
}
|
|
||||||
OLD_PASSWORD_FIELD_ENABLED = True
|
OLD_PASSWORD_FIELD_ENABLED = True
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
|
@ -857,9 +849,6 @@ REST_FRAMEWORK = {
|
||||||
"DEFAULT_AUTHENTICATION_CLASSES": (
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||||
"funkwhale_api.common.authentication.OAuth2Authentication",
|
"funkwhale_api.common.authentication.OAuth2Authentication",
|
||||||
"funkwhale_api.common.authentication.ApplicationTokenAuthentication",
|
"funkwhale_api.common.authentication.ApplicationTokenAuthentication",
|
||||||
"funkwhale_api.common.authentication.JSONWebTokenAuthenticationQS",
|
|
||||||
"funkwhale_api.common.authentication.BearerTokenHeaderAuth",
|
|
||||||
"funkwhale_api.common.authentication.JSONWebTokenAuthentication",
|
|
||||||
"rest_framework.authentication.BasicAuthentication",
|
"rest_framework.authentication.BasicAuthentication",
|
||||||
"rest_framework.authentication.SessionAuthentication",
|
"rest_framework.authentication.SessionAuthentication",
|
||||||
),
|
),
|
||||||
|
@ -998,14 +987,6 @@ THROTTLING_RATES = {
|
||||||
"rate": THROTTLING_USER_RATES.get("login", "30/hour"),
|
"rate": THROTTLING_USER_RATES.get("login", "30/hour"),
|
||||||
"description": "Login",
|
"description": "Login",
|
||||||
},
|
},
|
||||||
"jwt-login": {
|
|
||||||
"rate": THROTTLING_USER_RATES.get("jwt-login", "30/hour"),
|
|
||||||
"description": "JWT token creation",
|
|
||||||
},
|
|
||||||
"jwt-refresh": {
|
|
||||||
"rate": THROTTLING_USER_RATES.get("jwt-refresh", "30/hour"),
|
|
||||||
"description": "JWT token refresh",
|
|
||||||
},
|
|
||||||
"signup": {
|
"signup": {
|
||||||
"rate": THROTTLING_USER_RATES.get("signup", "10/day"),
|
"rate": THROTTLING_USER_RATES.get("signup", "10/day"),
|
||||||
"description": "Account creation",
|
"description": "Account creation",
|
||||||
|
@ -1052,7 +1033,6 @@ REST_AUTH_SERIALIZERS = {
|
||||||
"PASSWORD_RESET_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetSerializer" # noqa
|
"PASSWORD_RESET_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetSerializer" # noqa
|
||||||
}
|
}
|
||||||
REST_SESSION_LOGIN = False
|
REST_SESSION_LOGIN = False
|
||||||
REST_USE_JWT = True
|
|
||||||
|
|
||||||
ATOMIC_REQUESTS = False
|
ATOMIC_REQUESTS = False
|
||||||
USE_X_FORWARDED_HOST = True
|
USE_X_FORWARDED_HOST = True
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.encoding import smart_text
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
@ -9,8 +8,6 @@ from oauth2_provider.contrib.rest_framework.authentication import (
|
||||||
OAuth2Authentication as BaseOAuth2Authentication,
|
OAuth2Authentication as BaseOAuth2Authentication,
|
||||||
)
|
)
|
||||||
from rest_framework import exceptions
|
from rest_framework import exceptions
|
||||||
from rest_framework_jwt import authentication
|
|
||||||
from rest_framework_jwt.settings import api_settings
|
|
||||||
|
|
||||||
from funkwhale_api.users import models as users_models
|
from funkwhale_api.users import models as users_models
|
||||||
|
|
||||||
|
@ -76,116 +73,3 @@ class ApplicationTokenAuthentication(object):
|
||||||
|
|
||||||
request.scopes = application.scope.split()
|
request.scopes = application.scope.split()
|
||||||
return user, None
|
return user, None
|
||||||
|
|
||||||
|
|
||||||
class BaseJsonWebTokenAuth(object):
|
|
||||||
def authenticate(self, request):
|
|
||||||
try:
|
|
||||||
return super().authenticate(request)
|
|
||||||
except UnverifiedEmail as e:
|
|
||||||
msg = _("You need to verify your email address.")
|
|
||||||
resend_confirmation_email(request, e.user)
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
|
|
||||||
def authenticate_credentials(self, payload):
|
|
||||||
"""
|
|
||||||
We have to implement this method by hand to ensure we can check that the
|
|
||||||
User has a verified email, if required
|
|
||||||
"""
|
|
||||||
User = authentication.get_user_model()
|
|
||||||
username = authentication.jwt_get_username_from_payload(payload)
|
|
||||||
|
|
||||||
if not username:
|
|
||||||
msg = _("Invalid payload.")
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
|
|
||||||
try:
|
|
||||||
user = User.objects.get_by_natural_key(username)
|
|
||||||
except User.DoesNotExist:
|
|
||||||
msg = _("Invalid signature.")
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
|
|
||||||
if not user.is_active:
|
|
||||||
msg = _("User account is disabled.")
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
|
|
||||||
if should_verify_email(user):
|
|
||||||
raise UnverifiedEmail(user)
|
|
||||||
|
|
||||||
return user
|
|
||||||
|
|
||||||
|
|
||||||
class JSONWebTokenAuthenticationQS(
|
|
||||||
BaseJsonWebTokenAuth, authentication.BaseJSONWebTokenAuthentication
|
|
||||||
):
|
|
||||||
|
|
||||||
www_authenticate_realm = "api"
|
|
||||||
|
|
||||||
def get_jwt_value(self, request):
|
|
||||||
token = request.query_params.get("jwt")
|
|
||||||
if "jwt" in request.query_params and not token:
|
|
||||||
msg = _("Invalid Authorization header. No credentials provided.")
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
return token
|
|
||||||
|
|
||||||
def authenticate_header(self, request):
|
|
||||||
return '{0} realm="{1}"'.format(
|
|
||||||
api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BearerTokenHeaderAuth(
|
|
||||||
BaseJsonWebTokenAuth, authentication.BaseJSONWebTokenAuthentication
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
For backward compatibility purpose, we used Authorization: JWT <token>
|
|
||||||
but Authorization: Bearer <token> is probably better.
|
|
||||||
"""
|
|
||||||
|
|
||||||
www_authenticate_realm = "api"
|
|
||||||
|
|
||||||
def get_jwt_value(self, request):
|
|
||||||
auth = authentication.get_authorization_header(request).split()
|
|
||||||
auth_header_prefix = "bearer"
|
|
||||||
|
|
||||||
if not auth:
|
|
||||||
if api_settings.JWT_AUTH_COOKIE:
|
|
||||||
return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if smart_text(auth[0].lower()) != auth_header_prefix:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if len(auth) == 1:
|
|
||||||
msg = _("Invalid Authorization header. No credentials provided.")
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
elif len(auth) > 2:
|
|
||||||
msg = _(
|
|
||||||
"Invalid Authorization header. Credentials string "
|
|
||||||
"should not contain spaces."
|
|
||||||
)
|
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
|
||||||
|
|
||||||
return auth[1]
|
|
||||||
|
|
||||||
def authenticate_header(self, request):
|
|
||||||
return '{0} realm="{1}"'.format("Bearer", self.www_authenticate_realm)
|
|
||||||
|
|
||||||
def authenticate(self, request):
|
|
||||||
auth = super().authenticate(request)
|
|
||||||
if auth:
|
|
||||||
if not auth[0].actor:
|
|
||||||
auth[0].create_actor()
|
|
||||||
return auth
|
|
||||||
|
|
||||||
|
|
||||||
class JSONWebTokenAuthentication(
|
|
||||||
BaseJsonWebTokenAuth, authentication.JSONWebTokenAuthentication
|
|
||||||
):
|
|
||||||
def authenticate(self, request):
|
|
||||||
auth = super().authenticate(request)
|
|
||||||
|
|
||||||
if auth:
|
|
||||||
if not auth[0].actor:
|
|
||||||
auth[0].create_actor()
|
|
||||||
return auth
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
from rest_framework_jwt import views as jwt_views
|
|
||||||
|
|
||||||
from . import serializers
|
|
||||||
|
|
||||||
|
|
||||||
class ObtainJSONWebToken(jwt_views.ObtainJSONWebToken):
|
|
||||||
throttling_scopes = {"*": {"anonymous": "jwt-login", "authenticated": "jwt-login"}}
|
|
||||||
serializer_class = serializers.JSONWebTokenSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class RefreshJSONWebToken(jwt_views.RefreshJSONWebToken):
|
|
||||||
throttling_scopes = {
|
|
||||||
"*": {"anonymous": "jwt-refresh", "authenticated": "jwt-refresh"}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
obtain_jwt_token = ObtainJSONWebToken.as_view()
|
|
||||||
refresh_jwt_token = RefreshJSONWebToken.as_view()
|
|
|
@ -10,10 +10,8 @@ from allauth.account import models as allauth_models
|
||||||
from rest_auth.serializers import PasswordResetSerializer as PRS
|
from rest_auth.serializers import PasswordResetSerializer as PRS
|
||||||
from rest_auth.registration.serializers import RegisterSerializer as RS, get_adapter
|
from rest_auth.registration.serializers import RegisterSerializer as RS, get_adapter
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework_jwt import serializers as jwt_serializers
|
|
||||||
|
|
||||||
from funkwhale_api.activity import serializers as activity_serializers
|
from funkwhale_api.activity import serializers as activity_serializers
|
||||||
from funkwhale_api.common import authentication
|
|
||||||
from funkwhale_api.common import models as common_models
|
from funkwhale_api.common import models as common_models
|
||||||
from funkwhale_api.common import preferences
|
from funkwhale_api.common import preferences
|
||||||
from funkwhale_api.common import serializers as common_serializers
|
from funkwhale_api.common import serializers as common_serializers
|
||||||
|
@ -42,15 +40,6 @@ username_validators = [ASCIIUsernameValidator()]
|
||||||
NOOP = object()
|
NOOP = object()
|
||||||
|
|
||||||
|
|
||||||
class JSONWebTokenSerializer(jwt_serializers.JSONWebTokenSerializer):
|
|
||||||
def validate(self, data):
|
|
||||||
try:
|
|
||||||
return super().validate(data)
|
|
||||||
except authentication.UnverifiedEmail as e:
|
|
||||||
authentication.send_email_confirmation(self.context["request"], e.user)
|
|
||||||
raise serializers.ValidationError("Please verify your email address.")
|
|
||||||
|
|
||||||
|
|
||||||
class RegisterSerializer(RS):
|
class RegisterSerializer(RS):
|
||||||
invitation = serializers.CharField(
|
invitation = serializers.CharField(
|
||||||
required=False, allow_null=True, allow_blank=True
|
required=False, allow_null=True, allow_blank=True
|
||||||
|
|
|
@ -25,7 +25,6 @@ celery~=4.4.0
|
||||||
django-cors-headers~=3.4.0
|
django-cors-headers~=3.4.0
|
||||||
musicbrainzngs~=0.7.1
|
musicbrainzngs~=0.7.1
|
||||||
djangorestframework~=3.11.0
|
djangorestframework~=3.11.0
|
||||||
djangorestframework-jwt~=1.11.0
|
|
||||||
arrow~=0.15.5
|
arrow~=0.15.5
|
||||||
persisting-theory~=0.2.0
|
persisting-theory~=0.2.0
|
||||||
django-versatileimagefield~=2.0.0
|
django-versatileimagefield~=2.0.0
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from rest_framework import exceptions
|
|
||||||
from rest_framework_jwt.settings import api_settings as jwt_settings
|
|
||||||
|
|
||||||
from funkwhale_api.common import authentication
|
from funkwhale_api.common import authentication
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,35 +30,6 @@ def test_should_verify_email(
|
||||||
assert authentication.should_verify_email(user) is expected
|
assert authentication.should_verify_email(user) is expected
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"setting_value, verified_email, expected",
|
|
||||||
[
|
|
||||||
("mandatory", False, True),
|
|
||||||
("optional", False, False),
|
|
||||||
("mandatory", True, False),
|
|
||||||
("optional", True, False),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_json_webtoken_auth_verify_email_validity(
|
|
||||||
setting_value, verified_email, expected, factories, settings, mocker, api_request
|
|
||||||
):
|
|
||||||
settings.ACCOUNT_EMAIL_VERIFICATION = setting_value
|
|
||||||
user = factories["users.User"](verified_email=verified_email)
|
|
||||||
should_verify = mocker.spy(authentication, "should_verify_email")
|
|
||||||
payload = jwt_settings.JWT_PAYLOAD_HANDLER(user)
|
|
||||||
token = jwt_settings.JWT_ENCODE_HANDLER(payload)
|
|
||||||
request = api_request.get("/", HTTP_AUTHORIZATION="JWT {}".format(token))
|
|
||||||
|
|
||||||
auth = authentication.JSONWebTokenAuthentication()
|
|
||||||
if expected is False:
|
|
||||||
assert auth.authenticate(request)[0] == user
|
|
||||||
else:
|
|
||||||
with pytest.raises(exceptions.AuthenticationFailed, match=r".*verify.*"):
|
|
||||||
auth.authenticate(request)
|
|
||||||
|
|
||||||
should_verify.assert_called_once_with(user)
|
|
||||||
|
|
||||||
|
|
||||||
def test_app_token_authentication(factories, api_request):
|
def test_app_token_authentication(factories, api_request):
|
||||||
user = factories["users.User"]()
|
user = factories["users.User"]()
|
||||||
app = factories["users.Application"](user=user, scope="read write")
|
app = factories["users.Application"](user=user, scope="read write")
|
||||||
|
|
|
@ -22,8 +22,6 @@ from django import urls
|
||||||
"/api/v1/manage/accounts",
|
"/api/v1/manage/accounts",
|
||||||
"/api/v1/oauth/apps",
|
"/api/v1/oauth/apps",
|
||||||
"/api/v1/moderation/content-filters",
|
"/api/v1/moderation/content-filters",
|
||||||
"/api/v1/token",
|
|
||||||
"/api/v1/token/refresh",
|
|
||||||
"/api/v1/instance/settings",
|
"/api/v1/instance/settings",
|
||||||
"/api/v1/instance/nodeinfo/2.0",
|
"/api/v1/instance/nodeinfo/2.0",
|
||||||
],
|
],
|
||||||
|
|
|
@ -5,20 +5,6 @@ jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
||||||
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
||||||
|
|
||||||
|
|
||||||
def test_can_authenticate_using_jwt_token_param_in_url(factories, preferences, client):
|
|
||||||
user = factories["users.User"]()
|
|
||||||
preferences["common__api_authentication_required"] = True
|
|
||||||
url = reverse("api:v1:tracks-list")
|
|
||||||
response = client.get(url)
|
|
||||||
|
|
||||||
assert response.status_code == 401
|
|
||||||
|
|
||||||
payload = jwt_payload_handler(user)
|
|
||||||
token = jwt_encode_handler(payload)
|
|
||||||
response = client.get(url, data={"jwt": token})
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_can_authenticate_using_oauth_token_param_in_url(
|
def test_can_authenticate_using_oauth_token_param_in_url(
|
||||||
factories, preferences, client, mocker
|
factories, preferences, client, mocker
|
||||||
):
|
):
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
import pytest
|
|
||||||
from jwt.exceptions import DecodeError
|
|
||||||
from rest_framework_jwt.settings import api_settings
|
|
||||||
|
|
||||||
|
|
||||||
def test_can_invalidate_token_when_changing_user_secret_key(factories):
|
|
||||||
user = factories["users.User"]()
|
|
||||||
u1 = user.secret_key
|
|
||||||
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
|
||||||
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
|
||||||
payload = jwt_payload_handler(user)
|
|
||||||
payload = jwt_encode_handler(payload)
|
|
||||||
|
|
||||||
# this should work
|
|
||||||
api_settings.JWT_DECODE_HANDLER(payload)
|
|
||||||
|
|
||||||
# now we update the secret key
|
|
||||||
user.update_secret_key()
|
|
||||||
user.save()
|
|
||||||
assert user.secret_key != u1
|
|
||||||
|
|
||||||
# token should be invalid
|
|
||||||
with pytest.raises(DecodeError):
|
|
||||||
api_settings.JWT_DECODE_HANDLER(payload)
|
|
||||||
|
|
||||||
|
|
||||||
def test_can_invalidate_token_when_changing_settings_secret_key(factories, settings):
|
|
||||||
settings.SECRET_KEY = "test1"
|
|
||||||
user = factories["users.User"]()
|
|
||||||
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
|
||||||
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
|
||||||
payload = jwt_payload_handler(user)
|
|
||||||
payload = jwt_encode_handler(payload)
|
|
||||||
|
|
||||||
# this should work
|
|
||||||
api_settings.JWT_DECODE_HANDLER(payload)
|
|
||||||
|
|
||||||
# now we update the secret key
|
|
||||||
settings.SECRET_KEY = "test2"
|
|
||||||
|
|
||||||
# token should be invalid
|
|
||||||
with pytest.raises(DecodeError):
|
|
||||||
api_settings.JWT_DECODE_HANDLER(payload)
|
|
|
@ -134,42 +134,6 @@ def test_can_fetch_data_from_api(api_client, factories):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_can_get_token_via_api(api_client, factories):
|
|
||||||
user = factories["users.User"]()
|
|
||||||
url = reverse("api:v1:token")
|
|
||||||
payload = {"username": user.username, "password": "test"}
|
|
||||||
|
|
||||||
response = api_client.post(url, payload)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert "token" in response.data
|
|
||||||
|
|
||||||
|
|
||||||
def test_can_get_token_via_api_inactive(api_client, factories):
|
|
||||||
user = factories["users.User"](is_active=False)
|
|
||||||
url = reverse("api:v1:token")
|
|
||||||
payload = {"username": user.username, "password": "test"}
|
|
||||||
|
|
||||||
response = api_client.post(url, payload)
|
|
||||||
assert response.status_code == 400
|
|
||||||
|
|
||||||
|
|
||||||
def test_can_refresh_token_via_api(api_client, factories, mocker):
|
|
||||||
# first, we get a token
|
|
||||||
user = factories["users.User"]()
|
|
||||||
url = reverse("api:v1:token")
|
|
||||||
payload = {"username": user.username, "password": "test"}
|
|
||||||
|
|
||||||
response = api_client.post(url, payload)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
token = response.data["token"]
|
|
||||||
url = reverse("api:v1:token_refresh")
|
|
||||||
response = api_client.post(url, {"token": token})
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert "token" in response.data
|
|
||||||
|
|
||||||
|
|
||||||
def test_changing_password_updates_secret_key(logged_in_api_client):
|
def test_changing_password_updates_secret_key(logged_in_api_client):
|
||||||
user = logged_in_api_client.user
|
user = logged_in_api_client.user
|
||||||
password = user.password
|
password = user.password
|
||||||
|
@ -488,40 +452,6 @@ def test_signup_with_approval_enabled_validation_error(
|
||||||
assert response.status_code == 400
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
def test_user_login_jwt(factories, api_client):
|
|
||||||
user = factories["users.User"]()
|
|
||||||
data = {
|
|
||||||
"username": user.username,
|
|
||||||
"password": "test",
|
|
||||||
}
|
|
||||||
url = reverse("api:v1:token")
|
|
||||||
response = api_client.post(url, data)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"setting_value, verified_email, expected_status_code",
|
|
||||||
[
|
|
||||||
("mandatory", False, 400),
|
|
||||||
("mandatory", True, 200),
|
|
||||||
("optional", False, 200),
|
|
||||||
("optional", True, 200),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_user_login_jwt_honor_email_verification(
|
|
||||||
setting_value, verified_email, expected_status_code, settings, factories, api_client
|
|
||||||
):
|
|
||||||
settings.ACCOUNT_EMAIL_VERIFICATION = setting_value
|
|
||||||
user = factories["users.User"](verified_email=verified_email)
|
|
||||||
data = {
|
|
||||||
"username": user.username,
|
|
||||||
"password": "test",
|
|
||||||
}
|
|
||||||
url = reverse("api:v1:token")
|
|
||||||
response = api_client.post(url, data)
|
|
||||||
assert response.status_code == expected_status_code
|
|
||||||
|
|
||||||
|
|
||||||
def test_login_via_api(api_client, factories):
|
def test_login_via_api(api_client, factories):
|
||||||
user = factories["users.User"]()
|
user = factories["users.User"]()
|
||||||
url = reverse("api:v1:users:login")
|
url = reverse("api:v1:users:login")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Remove deprecated JWT Authentication (#1108) (1108)
|
Loading…
Reference in New Issue