mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2024-11-25 10:33:45 +03:00
make UserProfile fully optional; version 0.2.3
This commit is contained in:
parent
0a1d239374
commit
445c211ebe
|
@ -26,8 +26,6 @@ class UserProfile(models.Model):
|
|||
class Meta:
|
||||
app_label = 'rest_auth'
|
||||
|
||||
settings.REST_PROFILE_MODULE = UserProfile
|
||||
|
||||
|
||||
"""
|
||||
overwrite register to avoid sending email
|
||||
|
@ -46,15 +44,13 @@ class RegistrationView(BaseRegistrationView):
|
|||
request=request)
|
||||
|
||||
# create user profile
|
||||
user_profile_model = _resolve_model(
|
||||
getattr(settings, 'REST_PROFILE_MODULE', None))
|
||||
user_profile_model.objects.create(user=new_user)
|
||||
profile_model_path = getattr(settings, 'REST_PROFILE_MODULE', None)
|
||||
if profile_model_path:
|
||||
user_profile_model = _resolve_model(profile_model_path)
|
||||
user_profile_model.objects.create(user=new_user)
|
||||
|
||||
return new_user
|
||||
|
||||
settings.REST_REGISTRATION_BACKEND = 'rest_auth.runtests.RegistrationView'
|
||||
|
||||
|
||||
|
||||
def runtests():
|
||||
TestRunner = get_runner(settings)
|
||||
|
|
|
@ -5,7 +5,8 @@ from rest_framework import serializers
|
|||
from rest_framework.serializers import _resolve_model
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
profile_model_path = getattr(settings, 'REST_PROFILE_MODULE', None)
|
||||
|
||||
profile_model_path = lambda: getattr(settings, 'REST_PROFILE_MODULE', None)
|
||||
|
||||
class LoginSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=30)
|
||||
|
@ -74,49 +75,63 @@ class UserUpdateSerializer(DynamicFieldsModelSerializer):
|
|||
|
||||
|
||||
|
||||
if profile_model_path:
|
||||
class UserRegistrationProfileSerializer(serializers.ModelSerializer):
|
||||
def get_user_registration_profile_serializer():
|
||||
if profile_model_path():
|
||||
class UserRegistrationProfileSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer that includes all profile fields except for user fk / id.
|
||||
"""
|
||||
class Meta:
|
||||
"""
|
||||
Serializer that includes all profile fields except for user fk / id.
|
||||
"""
|
||||
class Meta:
|
||||
|
||||
model = _resolve_model(profile_model_path)
|
||||
fields = filter(lambda x: x != 'id' and x != 'user',
|
||||
map(lambda x: x.name, model._meta.fields))
|
||||
model = _resolve_model(profile_model_path())
|
||||
fields = filter(lambda x: x != 'id' and x != 'user',
|
||||
map(lambda x: x.name, model._meta.fields))
|
||||
else:
|
||||
class UserRegistrationProfileSerializer(serializers.Serializer):
|
||||
pass
|
||||
return UserRegistrationProfileSerializer
|
||||
|
||||
class UserProfileSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer for UserProfile model.
|
||||
"""
|
||||
def get_user_profile_serializer():
|
||||
if profile_model_path():
|
||||
class UserProfileSerializer(serializers.ModelSerializer):
|
||||
|
||||
user = UserDetailsSerializer()
|
||||
"""
|
||||
Serializer for UserProfile model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
# http://stackoverflow.com/questions/4881607/django-get-model-from-string
|
||||
model = _resolve_model(profile_model_path)
|
||||
user = UserDetailsSerializer()
|
||||
|
||||
class UserProfileUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
# http://stackoverflow.com/questions/4881607/django-get-model-from-string
|
||||
model = _resolve_model(profile_model_path())
|
||||
|
||||
"""
|
||||
Serializer for updating User and UserProfile model.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserProfileSerializer, self).__init__(*args, **kwargs)
|
||||
else:
|
||||
class UserProfileSerializer(serializers.Serializer):
|
||||
pass
|
||||
return UserProfileSerializer
|
||||
|
||||
user = UserUpdateSerializer()
|
||||
|
||||
class Meta:
|
||||
# http://stackoverflow.com/questions/4881607/django-get-model-from-string
|
||||
model = _resolve_model(profile_model_path)
|
||||
def get_user_profile_update_serializer():
|
||||
if profile_model_path():
|
||||
class UserProfileUpdateSerializer(serializers.ModelSerializer):
|
||||
|
||||
else:
|
||||
class UserRegistrationProfileSerializer(serializers.Serializer):
|
||||
pass
|
||||
class UserProfileSerializer(serializers.Serializer):
|
||||
pass
|
||||
class UserProfileUpdateSerializer(serializers.Serializer):
|
||||
pass
|
||||
"""
|
||||
Serializer for updating User and UserProfile model.
|
||||
"""
|
||||
|
||||
user = UserUpdateSerializer()
|
||||
|
||||
class Meta:
|
||||
# http://stackoverflow.com/questions/4881607/django-get-model-from-string
|
||||
model = _resolve_model(profile_model_path())
|
||||
else:
|
||||
class UserProfileUpdateSerializer(serializers.Serializer):
|
||||
pass
|
||||
return UserProfileUpdateSerializer
|
||||
|
||||
|
||||
class SetPasswordSerializer(serializers.Serializer):
|
||||
|
|
|
@ -112,19 +112,40 @@ class BaseAPITestCase(object):
|
|||
# T E S T H E R E
|
||||
# -----------------------
|
||||
|
||||
user_profile_model = _resolve_model(
|
||||
getattr(settings, 'REST_PROFILE_MODULE', None))
|
||||
|
||||
class LoginAPITestCase(TestCase, BaseAPITestCase):
|
||||
|
||||
class APITestCase1(TestCase, BaseAPITestCase):
|
||||
"""
|
||||
just run: python manage.py test rest_auth
|
||||
Case #1:
|
||||
- user profile: defined
|
||||
- custom registration: backend defined
|
||||
"""
|
||||
|
||||
USERNAME = 'person'
|
||||
PASS = 'person'
|
||||
EMAIL = "person1@world.com"
|
||||
NEW_PASS = 'new-test-pass'
|
||||
PROFILE_MODEL = 'rest_auth.UserProfile'
|
||||
REGISTRATION_VIEW = 'rest_auth.runtests.RegistrationView'
|
||||
|
||||
# data without user profile
|
||||
BASIC_REGISTRATION_DATA = {
|
||||
"username": USERNAME,
|
||||
"password": PASS,
|
||||
"email": EMAIL
|
||||
}
|
||||
|
||||
# data with user profile
|
||||
REGISTRATION_DATA = BASIC_REGISTRATION_DATA.copy()
|
||||
REGISTRATION_DATA['newsletter_subscribe'] = False
|
||||
|
||||
BASIC_USER_DATA = {
|
||||
'first_name': "John",
|
||||
'last_name': 'Smith',
|
||||
'email': EMAIL
|
||||
}
|
||||
USER_DATA = BASIC_USER_DATA.copy()
|
||||
USER_DATA['newsletter_subscribe'] = True
|
||||
|
||||
def setUp(self):
|
||||
self.init()
|
||||
|
@ -132,6 +153,17 @@ class LoginAPITestCase(TestCase, BaseAPITestCase):
|
|||
self.password_change_url = reverse('rest_password_change')
|
||||
self.register_url = reverse('rest_register')
|
||||
self.password_reset_url = reverse('rest_password_reset')
|
||||
self.user_url = reverse('rest_user_details')
|
||||
|
||||
setattr(settings, 'REST_PROFILE_MODULE', self.PROFILE_MODEL)
|
||||
self.user_profile_model = None
|
||||
if self.PROFILE_MODEL:
|
||||
self.user_profile_model = _resolve_model(self.PROFILE_MODEL)
|
||||
|
||||
if self.REGISTRATION_VIEW:
|
||||
setattr(settings, 'REST_REGISTRATION_BACKEND', self.REGISTRATION_VIEW)
|
||||
elif hasattr(settings, 'REST_REGISTRATION_BACKEND'):
|
||||
delattr(settings, 'REST_REGISTRATION_BACKEND')
|
||||
|
||||
def test_login(self):
|
||||
payload = {
|
||||
|
@ -202,59 +234,60 @@ class LoginAPITestCase(TestCase, BaseAPITestCase):
|
|||
# send empty payload
|
||||
self.post(self.password_change_url, data={}, status_code=400)
|
||||
|
||||
def test_registration_user_with_profile(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS,
|
||||
"email": "person@world.com",
|
||||
"newsletter_subscribe": "false"
|
||||
}
|
||||
def test_registration(self):
|
||||
user_count = User.objects.all().count()
|
||||
|
||||
# test empty payload
|
||||
self.post(self.register_url, data={}, status_code=400)
|
||||
|
||||
self.post(self.register_url, data=payload, status_code=201)
|
||||
|
||||
activation_key = RegistrationProfile.objects.latest('id').activation_key
|
||||
verify_url = reverse('verify_email',
|
||||
kwargs={'activation_key': activation_key})
|
||||
|
||||
# new user at this point shouldn't be active
|
||||
self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201)
|
||||
self.assertEqual(User.objects.all().count(), user_count+1)
|
||||
new_user = get_user_model().objects.latest('id')
|
||||
self.assertEqual(new_user.is_active, False)
|
||||
|
||||
# let's active new user and check is_active flag
|
||||
self.get(verify_url)
|
||||
if self.REGISTRATION_VIEW:
|
||||
activation_key = RegistrationProfile.objects.latest('id').activation_key
|
||||
verify_url = reverse('verify_email',
|
||||
kwargs={'activation_key': activation_key})
|
||||
|
||||
# new user at this point shouldn't be active
|
||||
self.assertEqual(new_user.is_active, False)
|
||||
|
||||
# let's active new user and check is_active flag
|
||||
self.get(verify_url)
|
||||
new_user = get_user_model().objects.latest('id')
|
||||
self.assertEqual(new_user.is_active, True)
|
||||
if self.user_profile_model:
|
||||
user_profile = self.user_profile_model.objects.get(user=new_user)
|
||||
self.assertIsNotNone(user_profile)
|
||||
else:
|
||||
self.assertEqual(new_user.is_active, True)
|
||||
|
||||
def test_registration_without_profile_data(self):
|
||||
user_count = User.objects.all().count()
|
||||
|
||||
self.post(self.register_url, data=self.BASIC_REGISTRATION_DATA,
|
||||
status_code=201)
|
||||
self.assertEqual(User.objects.all().count(), user_count+1)
|
||||
new_user = get_user_model().objects.latest('id')
|
||||
self.assertEqual(new_user.is_active, True)
|
||||
user_profile = user_profile_model.objects.get(user=new_user)
|
||||
self.assertIsNotNone(user_profile)
|
||||
|
||||
def test_registration_user_without_profile(self):
|
||||
if self.REGISTRATION_VIEW:
|
||||
activation_key = RegistrationProfile.objects.latest('id').activation_key
|
||||
verify_url = reverse('verify_email',
|
||||
kwargs={'activation_key': activation_key})
|
||||
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS,
|
||||
"email": self.EMAIL,
|
||||
}
|
||||
# new user at this point shouldn't be active
|
||||
self.assertEqual(new_user.is_active, False)
|
||||
|
||||
self.post(self.register_url, data=payload, status_code=201)
|
||||
# let's active new user and check is_active flag
|
||||
self.get(verify_url)
|
||||
new_user = get_user_model().objects.latest('id')
|
||||
self.assertEqual(new_user.is_active, True)
|
||||
if self.user_profile_model:
|
||||
user_profile = self.user_profile_model.objects.get(user=new_user)
|
||||
self.assertIsNotNone(user_profile)
|
||||
else:
|
||||
self.assertEqual(new_user.is_active, True)
|
||||
|
||||
activation_key = RegistrationProfile.objects.latest('id').activation_key
|
||||
verify_url = reverse('verify_email',
|
||||
kwargs={'activation_key': activation_key})
|
||||
|
||||
# new user at this point shouldn't be active
|
||||
new_user = get_user_model().objects.latest('id')
|
||||
self.assertEqual(new_user.is_active, False)
|
||||
|
||||
# let's active new user and check is_active flag
|
||||
self.get(verify_url)
|
||||
new_user = get_user_model().objects.latest('id')
|
||||
self.assertEqual(new_user.is_active, True)
|
||||
|
||||
user_profile = user_profile_model.objects.get(user=new_user)
|
||||
self.assertIsNotNone(user_profile)
|
||||
|
||||
def test_password_reset(self):
|
||||
user = User.objects.create_user(self.USERNAME, self.EMAIL, self.PASS)
|
||||
|
@ -280,6 +313,33 @@ class LoginAPITestCase(TestCase, BaseAPITestCase):
|
|||
}
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
|
||||
def test_user_details(self):
|
||||
user = User.objects.create_user(self.USERNAME, self.EMAIL, self.PASS)
|
||||
if self.user_profile_model:
|
||||
self.user_profile_model.objects.create(user=user)
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.token = self.response.json['key']
|
||||
self.get(self.user_url, status_code=200)
|
||||
|
||||
self.post(self.user_url, data=self.BASIC_USER_DATA, status_code=200)
|
||||
user = User.objects.get(pk=user.pk)
|
||||
|
||||
if self.user_profile_model:
|
||||
self.post(self.user_url, data=self.USER_DATA, status_code=200)
|
||||
user = User.objects.get(pk=user.pk)
|
||||
self.assertEqual(user.first_name, self.response.json['user']['first_name'])
|
||||
self.assertEqual(user.last_name, self.response.json['user']['last_name'])
|
||||
self.assertEqual(user.email, self.response.json['user']['email'])
|
||||
self.assertIn('newsletter_subscribe', self.response.json)
|
||||
else:
|
||||
self.assertEqual(user.first_name, self.response.json['first_name'])
|
||||
self.assertEqual(user.last_name, self.response.json['last_name'])
|
||||
self.assertEqual(user.email, self.response.json['email'])
|
||||
|
||||
|
||||
def generate_uid_and_token(self, user):
|
||||
result = {}
|
||||
|
@ -295,3 +355,30 @@ class LoginAPITestCase(TestCase, BaseAPITestCase):
|
|||
result['token'] = default_token_generator.make_token(user)
|
||||
return result
|
||||
|
||||
|
||||
class APITestCase2(APITestCase1):
|
||||
"""
|
||||
Case #2:
|
||||
- user profile: not defined
|
||||
- custom registration backend: not defined
|
||||
"""
|
||||
PROFILE_MODEL = None
|
||||
|
||||
|
||||
class APITestCase3(APITestCase1):
|
||||
"""
|
||||
Case #3:
|
||||
- user profile: defined
|
||||
- custom registration backend: not defined
|
||||
"""
|
||||
REGISTRATION_VIEW = None
|
||||
|
||||
|
||||
class APITestCase4(APITestCase1):
|
||||
"""
|
||||
Case #4:
|
||||
- user profile: not defined
|
||||
- custom registration backend: not defined
|
||||
"""
|
||||
PROFILE_MODEL = None
|
||||
REGISTRATION_VIEW = None
|
||||
|
|
|
@ -23,31 +23,31 @@ from registration.models import RegistrationProfile
|
|||
from registration import signals
|
||||
from registration.views import ActivationView
|
||||
|
||||
from .utils import construct_modules_and_import
|
||||
from .models import *
|
||||
from .serializers import TokenSerializer, UserDetailsSerializer, \
|
||||
LoginSerializer, UserRegistrationSerializer, \
|
||||
UserRegistrationProfileSerializer, \
|
||||
UserProfileUpdateSerializer, SetPasswordSerializer, \
|
||||
PasswordResetSerializer
|
||||
from rest_auth.utils import construct_modules_and_import
|
||||
from rest_auth.models import *
|
||||
from rest_auth.serializers import (TokenSerializer, UserDetailsSerializer,
|
||||
LoginSerializer, UserRegistrationSerializer,
|
||||
SetPasswordSerializer, PasswordResetSerializer, UserUpdateSerializer,
|
||||
get_user_registration_profile_serializer, get_user_profile_serializer,
|
||||
get_user_profile_update_serializer)
|
||||
|
||||
|
||||
# Get the UserProfile model from the setting value
|
||||
user_profile_path = getattr(settings, 'REST_PROFILE_MODULE', None)
|
||||
user_profile_model = None
|
||||
if user_profile_path:
|
||||
user_profile_model = _resolve_model(user_profile_path)
|
||||
def get_user_profile_model():
|
||||
# Get the UserProfile model from the setting value
|
||||
user_profile_path = getattr(settings, 'REST_PROFILE_MODULE', None)
|
||||
if user_profile_path:
|
||||
setattr(settings, 'AUTH_PROFILE_MODULE', user_profile_path)
|
||||
return _resolve_model(user_profile_path)
|
||||
|
||||
# Get the REST Registration Backend for django-registration
|
||||
registration_backend = getattr(settings, 'REST_REGISTRATION_BACKEND',
|
||||
'registration.backends.default.views.RegistrationView')
|
||||
|
||||
if not registration_backend:
|
||||
raise Exception('Please configure a registration backend')
|
||||
def get_registration_backend():
|
||||
# Get the REST Registration Backend for django-registration
|
||||
registration_backend = getattr(settings, 'REST_REGISTRATION_BACKEND',
|
||||
'registration.backends.simple.views.RegistrationView')
|
||||
|
||||
# Get the REST REGISTRATION BACKEND class from the setting value via above
|
||||
# method
|
||||
RESTRegistrationView = construct_modules_and_import(registration_backend)
|
||||
# Get the REST REGISTRATION BACKEND class from the setting value via above
|
||||
# method
|
||||
return construct_modules_and_import(registration_backend)
|
||||
|
||||
|
||||
class LoggedInRESTAPIView(APIView):
|
||||
|
@ -139,13 +139,15 @@ class Register(LoggedOutRESTAPIView, GenericAPIView):
|
|||
"""
|
||||
|
||||
serializer_class = UserRegistrationSerializer
|
||||
profile_serializer_class = UserRegistrationProfileSerializer
|
||||
|
||||
def get_profile_serializer_class(self):
|
||||
return get_user_registration_profile_serializer()
|
||||
|
||||
def post(self, request):
|
||||
# Create serializers with request.DATA
|
||||
serializer = self.serializer_class(data=request.DATA)
|
||||
profile_serializer = self.profile_serializer_class(
|
||||
data=request.DATA)
|
||||
profile_serializer_class = self.get_profile_serializer_class()
|
||||
profile_serializer = profile_serializer_class(data=request.DATA)
|
||||
|
||||
if serializer.is_valid() and profile_serializer.is_valid():
|
||||
# Change the password key to password1 so that RESTRegistrationView
|
||||
|
@ -158,6 +160,7 @@ class Register(LoggedOutRESTAPIView, GenericAPIView):
|
|||
data = serializer.data.copy()
|
||||
data.update(profile_serializer.data)
|
||||
|
||||
RESTRegistrationView = get_registration_backend()
|
||||
RESTRegistrationView().register(request, **data)
|
||||
|
||||
# Return the User object with Created HTTP status
|
||||
|
@ -182,28 +185,33 @@ class UserDetails(LoggedInRESTAPIView, GenericAPIView):
|
|||
Optional: email, first_name, last_name and UserProfile fields
|
||||
Returns the updated UserProfile and/or User object.
|
||||
"""
|
||||
def get_profile_serializer_class(self):
|
||||
return get_user_profile_serializer()
|
||||
|
||||
serializer_class = UserProfileUpdateSerializer
|
||||
def get_profile_update_serializer_class(self):
|
||||
return get_user_profile_update_serializer()
|
||||
|
||||
def get(self, request):
|
||||
# Create serializers with request.user and profile
|
||||
user_details = UserDetailsSerializer(request.user)
|
||||
try:
|
||||
serializer = self.serializer_class(request.user.get_profile())
|
||||
profile_data = serializer.data
|
||||
except ObjectDoesNotExist:
|
||||
|
||||
profile_data = {}
|
||||
user_profile_model = get_user_profile_model()
|
||||
if user_profile_model:
|
||||
profile_serializer_class = self.get_profile_serializer_class()
|
||||
serializer = profile_serializer_class(request.user.get_profile())
|
||||
else:
|
||||
serializer = UserDetailsSerializer(request.user)
|
||||
# Send the Return the User and its profile model with OK HTTP status
|
||||
return Response({
|
||||
'user': user_details.data,
|
||||
'profile': profile_data},
|
||||
status=status.HTTP_200_OK)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def post(self, request):
|
||||
# Get the User object updater via this Serializer
|
||||
serializer = self.serializer_class(
|
||||
request.user.get_profile(), data=request.DATA, partial=True)
|
||||
user_profile_model = get_user_profile_model()
|
||||
if user_profile_model:
|
||||
profile_serializer_class = self.get_profile_update_serializer_class()
|
||||
serializer = profile_serializer_class(request.user.get_profile(),
|
||||
data=request.DATA, partial=True)
|
||||
else:
|
||||
serializer = UserUpdateSerializer(request.user, data=request.DATA,
|
||||
partial=True)
|
||||
|
||||
if serializer.is_valid():
|
||||
# Save UserProfileUpdateSerializer
|
||||
|
|
Loading…
Reference in New Issue
Block a user