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:
parent
09cca99c69
commit
9dbbf330e8
@ -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).
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user