1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 06:51:10 +03:00

Added support for token authentication (with test).

This commit is contained in:
Chris Church 2013-04-10 00:41:51 -04:00
parent 09cca99c69
commit 9dbbf330e8
6 changed files with 62 additions and 2 deletions

View File

@ -14,8 +14,10 @@
# You should have received a copy of the GNU General Public License
# along with Ansible Commander. If not, see <http://www.gnu.org/licenses/>.
from django.db import models
from django.db import models, DatabaseError
from django.db.models import CASCADE, SET_NULL, PROTECT
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
@ -23,6 +25,7 @@ from django.utils.timezone import now
import exceptions
from jsonfield import JSONField
from djcelery.models import TaskMeta
from rest_framework.authtoken.models import Token
# TODO: jobs and events model TBD
# TODO: reporting model TBD
@ -814,3 +817,13 @@ class LaunchJobStatusEvent(models.Model):
# FIXME: Connect host based on event_data.
# TODO: reporting (MPD)
@receiver(post_save, sender=User)
def create_auth_token_for_user(sender, **kwargs):
instance = kwargs.get('instance', None)
if instance:
try:
Token.objects.get_or_create(user=instance)
except DatabaseError:
pass # Only fails when creating a new superuser from syncdb on a
# new database (before migrate has been called).

View File

@ -38,6 +38,7 @@ class BaseTestMixin(object):
django_user = DjangoUser.objects.create_superuser(username, "%s@example.com", password)
else:
django_user = DjangoUser.objects.create_user(username, "%s@example.com", password)
self.assertTrue(django_user.auth_token)
return django_user
def make_organizations(self, created_by, count=1):
@ -98,7 +99,10 @@ class BaseTestMixin(object):
assert data is not None
client = Client()
if auth:
client.login(username=auth[0], password=auth[1])
if isinstance(auth, (list, tuple)):
client.login(username=auth[0], password=auth[1])
elif isinstance(auth, basestring):
client = Client(HTTP_AUTHORIZATION='Token %s' % auth)
method = getattr(client,method)
response = None
if data is not None:

View File

@ -47,6 +47,33 @@ class UsersTest(BaseTest):
self.post(url, expect=201, data=new_user2, auth=self.get_normal_credentials())
self.post(url, expect=400, data=new_user2, auth=self.get_normal_credentials())
def test_auth_token_login(self):
auth_token_url = '/api/v1/authtoken/'
# Always returns a 405 for any GET request, regardless of credentials.
self.get(auth_token_url, expect=405, auth=None)
self.get(auth_token_url, expect=405, auth=self.get_invalid_credentials())
self.get(auth_token_url, expect=405, auth=self.get_normal_credentials())
# Posting without username/password fields or invalid username/password
# returns a 400 error.
data = {}
self.post(auth_token_url, data, expect=400)
data = dict(zip(('username', 'password'), self.get_invalid_credentials()))
self.post(auth_token_url, data, expect=400)
# A valid username/password should give us an auth token.
data = dict(zip(('username', 'password'), self.get_normal_credentials()))
result = self.post(auth_token_url, data, expect=200, auth=None)
self.assertTrue('token' in result)
self.assertEqual(result['token'], self.normal_django_user.auth_token.key)
auth_token = result['token']
# Verify we can access our own user information with the auth token.
data = self.get('/api/v1/me/', expect=200, auth=auth_token)
self.assertEquals(data['results'][0]['username'], 'normal')
self.assertEquals(data['count'], 1)
def test_ordinary_user_can_modify_some_fields_about_himself_but_not_all_and_passwords_work(self):
detail_url = '/api/v1/users/%s/' % self.other_django_user.pk

View File

@ -26,10 +26,18 @@ from rest_framework import generics
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework import status
from rest_framework.settings import api_settings
from rest_framework.authtoken.views import ObtainAuthToken
import exceptions
import datetime
from base_views import *
class AuthTokenView(ObtainAuthToken):
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
# FIXME: Show a better form for HTML view
# FIXME: How to make this view discoverable?
class OrganizationsList(BaseList):
model = Organization

View File

@ -43,6 +43,7 @@ REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
@ -138,6 +139,7 @@ INSTALLED_APPS = (
'django.contrib.staticfiles',
'south',
'rest_framework',
'rest_framework.authtoken',
'django_extensions',
'djcelery',
'kombu.transport.django',

View File

@ -18,6 +18,9 @@ from django.conf import settings
from django.conf.urls import *
import lib.main.views as views
# auth token
views_AuthTokenView = views.AuthTokenView.as_view()
# organizations service
views_OrganizationsList = views.OrganizationsList.as_view()
views_OrganizationsDetail = views.OrganizationsDetail.as_view()
@ -87,6 +90,9 @@ views_CredentialsDetail = views.CredentialsDetail.as_view()
urlpatterns = patterns('',
# obtain auth token
url(r'^api/v1/authtoken/$', views_AuthTokenView),
# organizations vice
url(r'^api/v1/organizations/$', views_OrganizationsList),
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/$', views_OrganizationsDetail),