mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2024-11-10 19:26:35 +03:00
Created AUTHORS, MANIFEST.in, and setup.py.
+ Revised README.md. + AutoPEP8 rest_auth python files.
This commit is contained in:
parent
e1c577d4fd
commit
93a3de57ff
4
MANIFEST.in
Normal file
4
MANIFEST.in
Normal file
|
@ -0,0 +1,4 @@
|
|||
include AUTHORS
|
||||
include LICENSE
|
||||
include MANIFEST.in
|
||||
include README.md
|
115
README.md
115
README.md
|
@ -1,2 +1,115 @@
|
|||
django-rest-auth
|
||||
================
|
||||
=====
|
||||
|
||||
Since the introduction of django-rest-framework, Django apps have been able to serve up app-level REST API endpoints. As a result, we saw a lot of instances where developers implemented their own REST registration API endpoints here and there, snippets, and so on. We aim to solve this demand by providing django-rest-auth, a set of REST API endpoints to handle User Registration and Authentication tasks. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for User Management. Of course, we'll add more API endpoints as we see the demand.
|
||||
|
||||
Features
|
||||
--------
|
||||
1. User Registration with activation
|
||||
2. Login/Logout
|
||||
3. Retrieve/Update the Django User & user-defined UserProfile model
|
||||
4. Password change
|
||||
5. Password reset via e-mail
|
||||
|
||||
Installation
|
||||
-----------
|
||||
|
||||
1. This project needs the following packages
|
||||
|
||||
> django-registration>=1.0
|
||||
>
|
||||
> djangorestframework>=2.3.13
|
||||
>
|
||||
> django-rest-swagger>=0.1.14
|
||||
|
||||
2. Install this package.
|
||||
|
||||
3. Add rest_auth app to INSTALLED\_APPS in your django settings.py
|
||||
|
||||
> INSTALLED\_APPS = (
|
||||
>
|
||||
> ...,
|
||||
>
|
||||
> 'rest_auth',
|
||||
> )
|
||||
|
||||
4. This project depends on django-rest-framework library, therefore the following REST_FRAMEWORK settings needs to be entered in your Django settings.py::
|
||||
|
||||
> REST_FRAMEWORK = {
|
||||
>
|
||||
> 'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
> 'rest_framework.authentication.SessionAuthentication',
|
||||
> ),
|
||||
>
|
||||
> 'DEFAULT_PERMISSION_CLASSES': (
|
||||
> 'rest_framework.permissions.IsAuthenticated'
|
||||
> )
|
||||
> }
|
||||
|
||||
5. Lastly, this project accepts the following Django setting values. You can set the UserProfile model and/or create your own REST registration backend for django-registration.
|
||||
|
||||
> REST\_REGISTRATION\_BACKEND = 'rest\_auth.backends.rest\_registration.RESTRegistrationView'
|
||||
>
|
||||
> REST\_PROFILE\_MODULE = 'accounts.UserProfile'
|
||||
|
||||
6. You're good to go now!
|
||||
|
||||
API endpoints without Authentication
|
||||
------------------------------------
|
||||
|
||||
1. /rest\_accounts/register/ - POST
|
||||
|
||||
Parameters
|
||||
|
||||
username, password, email, first\_name, last\_name
|
||||
|
||||
2. /rest\_accounts/password/reset/ - POST
|
||||
|
||||
Parameters
|
||||
|
||||
email
|
||||
|
||||
3. /rest\_accounts/password/reset/confirm/{uidb64}/{token}/ - POST
|
||||
|
||||
Django URL Keywords
|
||||
|
||||
uidb64, token
|
||||
|
||||
Parameters
|
||||
|
||||
new\_password1, new\_password2
|
||||
|
||||
4. /rest\_accounts/login/ - POST
|
||||
|
||||
Parameters
|
||||
|
||||
username, password
|
||||
|
||||
5. /rest\_accounts/verify-email/{activation\_key}/ - GET
|
||||
|
||||
Django URL Keywords
|
||||
|
||||
activation_key
|
||||
|
||||
API endpoints with Authentication
|
||||
------------------------------------
|
||||
|
||||
1. /rest\_accounts/logout/ - GET
|
||||
|
||||
2. /rest\_accounts/user/ - GET & POST
|
||||
|
||||
GET Parameters
|
||||
|
||||
POST Parameters
|
||||
|
||||
user as dictionary with id, email, first\_name, last\_name
|
||||
|
||||
Ex) "user": {"id": 1, "first\_name": "Person", "last\_name": "2"}
|
||||
|
||||
user-defined UserProfile model fields
|
||||
|
||||
3. /rest\_accounts/password/change/ - POST
|
||||
|
||||
Parameters
|
||||
|
||||
new\_password1, new\_password2
|
||||
|
|
|
@ -12,6 +12,7 @@ class LoginSerializer(serializers.Serializer):
|
|||
|
||||
|
||||
class TokenSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer for Token model.
|
||||
"""
|
||||
|
@ -22,6 +23,7 @@ class TokenSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class UserRegistrationSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer for Django User model and most of its fields.
|
||||
"""
|
||||
|
@ -32,6 +34,7 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class UserRegistrationProfileSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer that includes all profile fields except for user fk / id.
|
||||
"""
|
||||
|
@ -42,6 +45,7 @@ class UserRegistrationProfileSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class UserDetailsSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
User model w/o password
|
||||
"""
|
||||
|
@ -51,6 +55,7 @@ class UserDetailsSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class UserProfileSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer for UserProfile model.
|
||||
"""
|
||||
|
@ -63,6 +68,7 @@ class UserProfileSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
ModelSerializer that allows fields argument to control fields
|
||||
"""
|
||||
|
@ -81,6 +87,7 @@ class DynamicFieldsModelSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class UserUpdateSerializer(DynamicFieldsModelSerializer):
|
||||
|
||||
"""
|
||||
User model w/o username and password
|
||||
"""
|
||||
|
@ -90,6 +97,7 @@ class UserUpdateSerializer(DynamicFieldsModelSerializer):
|
|||
|
||||
|
||||
class UserProfileUpdateSerializer(serializers.ModelSerializer):
|
||||
|
||||
"""
|
||||
Serializer for updating User and UserProfile model.
|
||||
"""
|
||||
|
@ -102,6 +110,7 @@ class UserProfileUpdateSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class SetPasswordSerializer(serializers.Serializer):
|
||||
|
||||
"""
|
||||
Serializer for changing Django User password.
|
||||
"""
|
||||
|
@ -111,6 +120,7 @@ class SetPasswordSerializer(serializers.Serializer):
|
|||
|
||||
|
||||
class PasswordResetSerializer(serializers.Serializer):
|
||||
|
||||
"""
|
||||
Serializer for requesting a password reset e-mail.
|
||||
"""
|
||||
|
|
|
@ -11,13 +11,16 @@ from registration.models import RegistrationProfile
|
|||
|
||||
|
||||
# Get the UserProfile model from the setting value
|
||||
user_profile_model = _resolve_model(getattr(settings, 'REST_PROFILE_MODULE', None))
|
||||
user_profile_model = _resolve_model(
|
||||
getattr(settings, 'REST_PROFILE_MODULE', None))
|
||||
|
||||
# Get the REST Registration Backend for django-registration
|
||||
registration_backend = getattr(settings, 'REST_REGISTRATION_BACKEND', 'rest_auth.backends.rest_registration.RESTRegistrationView')
|
||||
registration_backend = getattr(settings, 'REST_REGISTRATION_BACKEND',
|
||||
'rest_auth.backends.rest_registration.RESTRegistrationView')
|
||||
|
||||
|
||||
class RegistrationAndActivationTestCase(TestCase):
|
||||
|
||||
"""
|
||||
Unit Test for registering and activating a new user
|
||||
|
||||
|
@ -30,7 +33,8 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
|
||||
def test_successful_registration(self):
|
||||
print 'Registering a new user'
|
||||
payload = {"username": "person", "password": "person", "email": "person@world.com", "newsletter_subscribe": "false"}
|
||||
payload = {"username": "person", "password": "person",
|
||||
"email": "person@world.com", "newsletter_subscribe": "false"}
|
||||
|
||||
print 'The request will attempt to register:'
|
||||
print 'Django User object'
|
||||
|
@ -39,7 +43,8 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
print 'newsletter_subscribe: false'
|
||||
print 'Sending a POST request to register API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 201):
|
||||
print r.content
|
||||
|
@ -47,10 +52,12 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
print 'Activating a new user'
|
||||
|
||||
# Get the latest activation key from RegistrationProfile model
|
||||
activation_key = RegistrationProfile.objects.latest('id').activation_key
|
||||
activation_key = RegistrationProfile.objects.latest(
|
||||
'id').activation_key
|
||||
|
||||
# Set the url and GET the request to verify and activate a new user
|
||||
url = "http://localhost:8000/rest_auth/verify-email/" + activation_key + "/"
|
||||
url = "http://localhost:8000/rest_auth/verify-email/" + \
|
||||
activation_key + "/"
|
||||
r = requests.get(url)
|
||||
|
||||
print "Sending a GET request to activate the user from verify-email API"
|
||||
|
@ -69,7 +76,8 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
|
||||
def test_successful_registration_without_userprofile_model(self):
|
||||
print 'Registering a new user'
|
||||
payload = {"username": "person1", "password": "person1", "email": "person1@world.com"}
|
||||
payload = {"username": "person1", "password":
|
||||
"person1", "email": "person1@world.com"}
|
||||
|
||||
print 'The request will attempt to register:'
|
||||
print 'Django User object'
|
||||
|
@ -77,7 +85,8 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
print 'No Django UserProfile object'
|
||||
print 'Sending a POST request to register API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 201):
|
||||
print r.content
|
||||
|
@ -85,10 +94,12 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
print 'Activating a new user'
|
||||
|
||||
# Get the latest activation key from RegistrationProfile model
|
||||
activation_key = RegistrationProfile.objects.latest('id').activation_key
|
||||
activation_key = RegistrationProfile.objects.latest(
|
||||
'id').activation_key
|
||||
|
||||
# Set the url and GET the request to verify and activate a new user
|
||||
url = "http://localhost:8000/rest_auth/verify-email/" + activation_key + "/"
|
||||
url = "http://localhost:8000/rest_auth/verify-email/" + \
|
||||
activation_key + "/"
|
||||
r = requests.get(url)
|
||||
|
||||
print "Sending a GET request to activate the user from verify-email API"
|
||||
|
@ -112,13 +123,15 @@ class RegistrationAndActivationTestCase(TestCase):
|
|||
print 'The request will attempt to register with no data provided.'
|
||||
print 'Sending a POST request to register API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 400):
|
||||
print r.content
|
||||
|
||||
|
||||
class LoginTestCase(TestCase):
|
||||
|
||||
"""
|
||||
Unit Test for logging in
|
||||
|
||||
|
@ -137,7 +150,8 @@ class LoginTestCase(TestCase):
|
|||
print 'Username: %s\nPassword: %s' % ('person', 'person')
|
||||
print 'Sending a POST request to login API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 200):
|
||||
print r.content
|
||||
|
@ -152,7 +166,8 @@ class LoginTestCase(TestCase):
|
|||
print 'Username: %s\nPassword: %s' % ('person', 'person32')
|
||||
print 'Sending a POST request to login API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 401):
|
||||
print r.content
|
||||
|
@ -164,13 +179,15 @@ class LoginTestCase(TestCase):
|
|||
print 'The request will attempt to login with no data provided.'
|
||||
print 'Sending a POST request to login API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 400):
|
||||
print r.content
|
||||
|
||||
|
||||
class PasswordChangeCase(TestCase):
|
||||
|
||||
"""
|
||||
Unit Test for changing the password while logged in
|
||||
|
||||
|
@ -188,7 +205,8 @@ class PasswordChangeCase(TestCase):
|
|||
|
||||
print 'Sending a POST request to login API'
|
||||
|
||||
r = requests.post(login_url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(login_url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 200):
|
||||
print r.content
|
||||
|
@ -198,18 +216,22 @@ class PasswordChangeCase(TestCase):
|
|||
self.token = r.json()['key']
|
||||
self.headers['authorization'] = "Token " + r.json()['key']
|
||||
|
||||
payload = {"new_password1": "new_person", "new_password2": "new_person"}
|
||||
payload = {"new_password1": "new_person",
|
||||
"new_password2": "new_person"}
|
||||
print 'Sending a POST request to password change API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 200):
|
||||
print r.content
|
||||
|
||||
payload = {"new_password1": "person", "new_password2": "person"}
|
||||
payload = {"new_password1": "person",
|
||||
"new_password2": "person"}
|
||||
print 'Sending a POST request to password change API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(
|
||||
self.url, data=json.dumps(payload), headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 200):
|
||||
print r.content
|
||||
|
@ -221,7 +243,8 @@ class PasswordChangeCase(TestCase):
|
|||
|
||||
print 'Sending a POST request to login API'
|
||||
|
||||
r = requests.post(login_url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(login_url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 200):
|
||||
print r.content
|
||||
|
@ -231,10 +254,12 @@ class PasswordChangeCase(TestCase):
|
|||
self.token = r.json()['key']
|
||||
self.headers['authorization'] = "Token " + r.json()['key']
|
||||
|
||||
payload = {"new_password1": "new_person", "new_password2": "wrong_person"}
|
||||
payload = {"new_password1": "new_person",
|
||||
"new_password2": "wrong_person"}
|
||||
print 'Sending a POST request to password change API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 400):
|
||||
print r.content
|
||||
|
@ -246,7 +271,8 @@ class PasswordChangeCase(TestCase):
|
|||
|
||||
print 'Sending a POST request to login API'
|
||||
|
||||
r = requests.post(login_url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(login_url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 200):
|
||||
print r.content
|
||||
|
@ -261,7 +287,8 @@ class PasswordChangeCase(TestCase):
|
|||
print 'The request will attempt to login with no data provided.'
|
||||
print 'Sending a POST request to password change API'
|
||||
|
||||
r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
|
||||
r = requests.post(self.url, data=json.dumps(payload),
|
||||
headers=self.headers)
|
||||
|
||||
if self.assertEqual(r.status_code, 400):
|
||||
print r.content
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.contrib.auth.models import User
|
|||
|
||||
|
||||
class APIClient(Client):
|
||||
|
||||
def patch(self, path, data='', content_type=MULTIPART_CONTENT, follow=False, **extra):
|
||||
return self.generic('PATCH', path, data, content_type, **extra)
|
||||
|
||||
|
@ -19,6 +20,7 @@ class APIClient(Client):
|
|||
|
||||
|
||||
class CustomJSONEncoder(json.JSONEncoder):
|
||||
|
||||
"""
|
||||
Convert datetime/date objects into isoformat
|
||||
"""
|
||||
|
@ -31,13 +33,15 @@ class CustomJSONEncoder(json.JSONEncoder):
|
|||
|
||||
|
||||
class BaseAPITestCase(object):
|
||||
|
||||
"""
|
||||
base for API tests:
|
||||
* easy request calls, f.e.: self.post(url, data), self.get(url)
|
||||
* easy status check, f.e.: self.post(url, data, status_code=200)
|
||||
"""
|
||||
|
||||
img = os.path.join(settings.STATICFILES_DIRS[0][1], 'images/no_profile_photo.png')
|
||||
img = os.path.join(
|
||||
settings.STATICFILES_DIRS[0][1], 'images/no_profile_photo.png')
|
||||
|
||||
def send_request(self, request_method, *args, **kwargs):
|
||||
request_func = getattr(self.client, request_method)
|
||||
|
@ -55,10 +59,12 @@ class BaseAPITestCase(object):
|
|||
kwargs['HTTP_AUTHORIZATION'] = 'Token %s' % self.token
|
||||
|
||||
if hasattr(self, 'company_token'):
|
||||
kwargs['HTTP_AUTHORIZATION'] = 'Company-Token %s' % self.company_token
|
||||
kwargs[
|
||||
'HTTP_AUTHORIZATION'] = 'Company-Token %s' % self.company_token
|
||||
|
||||
self.response = request_func(*args, **kwargs)
|
||||
is_json = bool(filter(lambda x: 'json' in x, self.response._headers['content-type']))
|
||||
is_json = bool(
|
||||
filter(lambda x: 'json' in x, self.response._headers['content-type']))
|
||||
if is_json and self.response.content:
|
||||
self.response.json = json.loads(self.response.content)
|
||||
else:
|
||||
|
@ -95,7 +101,8 @@ class BaseAPITestCase(object):
|
|||
content_type = kwargs.pop('content_type')
|
||||
response = self.send_request('get', *args, **kwargs)
|
||||
if content_type:
|
||||
self.assertEqual(bool(filter(lambda x: content_type in x, response._headers['content-type'])), True)
|
||||
self.assertEqual(
|
||||
bool(filter(lambda x: content_type in x, response._headers['content-type'])), True)
|
||||
return response
|
||||
|
||||
def init(self):
|
||||
|
@ -103,12 +110,11 @@ class BaseAPITestCase(object):
|
|||
self.client = APIClient()
|
||||
|
||||
|
||||
|
||||
# -----------------------
|
||||
# T E S T H E R E
|
||||
# -----------------------
|
||||
|
||||
class LoginAPITestCase(TestCase, BaseAPITestCase):
|
||||
|
||||
"""
|
||||
just run: python manage.py test rest_auth
|
||||
"""
|
||||
|
@ -137,7 +143,6 @@ class LoginAPITestCase(TestCase, BaseAPITestCase):
|
|||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.assertEqual('key' in self.response.json.keys(), True)
|
||||
|
||||
|
||||
self.token = self.response.json['key']
|
||||
# TODO:
|
||||
# now all urls that required token should be available
|
||||
|
@ -145,4 +150,5 @@ class LoginAPITestCase(TestCase, BaseAPITestCase):
|
|||
|
||||
|
||||
# TODO:
|
||||
# another case to test - make user inactive and test if login is impossible
|
||||
# another case to test - make user inactive and test if login is
|
||||
# impossible
|
||||
|
|
|
@ -7,17 +7,22 @@ from .views import Login, Logout, Register, UserDetails, \
|
|||
|
||||
urlpatterns = patterns('rest_auth.views',
|
||||
# URLs that do not require a session or valid token
|
||||
url(r'^register/$', Register.as_view(), name='rest_register'),
|
||||
url(r'^password/reset/$', PasswordReset.as_view(), name='rest_password_reset'),
|
||||
url(r'^register/$', Register.as_view(),
|
||||
name='rest_register'),
|
||||
url(r'^password/reset/$', PasswordReset.as_view(),
|
||||
name='rest_password_reset'),
|
||||
url(r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
|
||||
PasswordResetConfirm.as_view(), name='rest_password_reset_confirm'),
|
||||
PasswordResetConfirm.as_view(
|
||||
), name='rest_password_reset_confirm'),
|
||||
url(r'^login/$', Login.as_view(), name='rest_login'),
|
||||
url(r'^verify-email/(?P<activation_key>\w+)/$',
|
||||
VerifyEmail.as_view(), name='verify_email'),
|
||||
|
||||
# URLs that require a user to be logged in with a valid session / token.
|
||||
# URLs that require a user to be logged in with a valid
|
||||
# session / token.
|
||||
url(r'^logout/$', Logout.as_view(), name='rest_logout'),
|
||||
url(r'^user/$', UserDetails.as_view(), name='rest_user_details'),
|
||||
url(r'^user/$', UserDetails.as_view(),
|
||||
name='rest_user_details'),
|
||||
url(r'^password/change/$', PasswordChange.as_view(),
|
||||
name='rest_password_change'),
|
||||
)
|
||||
|
@ -25,5 +30,6 @@ urlpatterns = patterns('rest_auth.views',
|
|||
if settings.DEBUG:
|
||||
urlpatterns += patterns('',
|
||||
# Swagger Docs
|
||||
url(r'^docs/', include('rest_framework_swagger.urls')),
|
||||
url(r'^docs/',
|
||||
include('rest_framework_swagger.urls')),
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ from django.utils.crypto import get_random_string
|
|||
|
||||
HASH_CHARACTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
|
||||
|
||||
def generate_new_hash_with_length(length):
|
||||
"""
|
||||
Generates a random string with the alphanumerical character set and given length.
|
||||
|
|
|
@ -230,7 +230,8 @@ class PasswordReset(LoggedOutRESTAPIView, GenericAPIView):
|
|||
reset_form.save(**opts)
|
||||
|
||||
# Return the success message with OK HTTP status
|
||||
return Response({"success": "Password reset e-mail has been sent."},
|
||||
return Response(
|
||||
{"success": "Password reset e-mail has been sent."},
|
||||
status=status.HTTP_200_OK)
|
||||
|
||||
else:
|
||||
|
@ -241,7 +242,9 @@ class PasswordReset(LoggedOutRESTAPIView, GenericAPIView):
|
|||
return Response(serializer.errors,
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class PasswordResetConfirm(LoggedOutRESTAPIView, GenericAPIView):
|
||||
|
||||
"""
|
||||
Password reset e-mail link is confirmed, therefore this resets the user's password.
|
||||
|
||||
|
@ -276,10 +279,13 @@ class PasswordResetConfirm(LoggedOutRESTAPIView, GenericAPIView):
|
|||
form.save()
|
||||
|
||||
# Return the success message with OK HTTP status
|
||||
return Response({"success": "Password has been reset with the new password."},
|
||||
return Response(
|
||||
{"success":
|
||||
"Password has been reset with the new password."},
|
||||
status=status.HTTP_200_OK)
|
||||
else:
|
||||
return Response({"error": "Invalid password reset token."},
|
||||
return Response(
|
||||
{"error": "Invalid password reset token."},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
return Response(form._errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
@ -293,6 +299,7 @@ class PasswordResetConfirm(LoggedOutRESTAPIView, GenericAPIView):
|
|||
|
||||
|
||||
class VerifyEmail(LoggedOutRESTAPIView, GenericAPIView):
|
||||
|
||||
"""
|
||||
Verifies the email of the user through their activation_key.
|
||||
|
||||
|
|
46
setup.py
Normal file
46
setup.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
try:
|
||||
from setuptools import setup, find_packages
|
||||
except ImportError:
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
import os
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
f = open(os.path.join(here, 'README.md'))
|
||||
long_description = f.read().strip()
|
||||
f.close()
|
||||
|
||||
|
||||
setup(
|
||||
name='django-rest-auth',
|
||||
version='0.1',
|
||||
author='Sumit Chachra',
|
||||
author_email='chachra@tivix.com',
|
||||
url='http://github.com/Tivix/django-rest-auth',
|
||||
description='Create a set of REST API endpoints for Authentication and Registration',
|
||||
packages=find_packages(),
|
||||
long_description=long_description,
|
||||
keywords='django rest auth registration rest-framework django-registration api',
|
||||
zip_safe=False,
|
||||
install_requires=[
|
||||
'Django>=1.5.0',
|
||||
'django-registration>=1.0',
|
||||
'djangorestframework>=2.3.13',
|
||||
'django-rest-swagger>=0.1.14',
|
||||
],
|
||||
test_suite='rest_auth.tests',
|
||||
include_package_data=True,
|
||||
# cmdclass={},
|
||||
classifiers=[
|
||||
'Framework :: Django',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: System Administrators',
|
||||
'Operating System :: OS Independent',
|
||||
'Topic :: Software Development'
|
||||
],
|
||||
)
|
Loading…
Reference in New Issue
Block a user