Skip to content

Commit

Permalink
Closed #13 Authentication fixed and improved (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Virako authored Dec 29, 2018
1 parent e2b2ea7 commit a63424e
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 141 deletions.
67 changes: 33 additions & 34 deletions base/client.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import json

from django.conf import settings
from django.test import Client
from oauth2_provider.models import Application


class BaseClient(Client):
def __init__(self, base_url='/api', version='', *args, **kwargs):
def __init__(self, *args, **kwargs):
self.auth_token = ''
self.base_url = base_url
self.version = '/v{0}'.format(version)
self.access_token = ''
version = kwargs.get('version', settings.VERSION)
self.base_url = '/api/v{0}'.format(version)
super().__init__(*args, **kwargs)

def set_auth_token(self, response):
json_res = response.json()
token_type = json_res.get('token_type')
access_token = json_res.get('access_token')
self.auth_token = '%s %s' % (token_type, access_token)
self.access_token = json_res.get('access_token')
self.auth_token = '%s %s' % (token_type, self.access_token)

def authenticate(self, email, password):
app = Application.objects.get(name='local')
Expand All @@ -25,47 +27,44 @@ def authenticate(self, email, password):
'username': email,
'password': password
}
response = self.post('/social/token/', data)
response = self.post('/auth/token/', data)
if response.status_code == 200:
self.set_auth_token(response)
return response

def logout(self):
self.auth_token = ''
app = Application.objects.get(name='local')
data = {
'client_id': app.client_id,
'grant_type': 'password',
'token': self.access_token
}
response = self.post('/auth/revoke-token/', data)
if response.status_code == 204:
self.auth_token = ''
return response

def extra(self):
return {
'content_type': 'application/json',
'HTTP_AUTHORIZATION': self.auth_token
}

def get(self, url):
return super().get(self.base_url + self.version + url,
content_type='application/json',
HTTP_AUTHORIZATION=self.auth_token)
return super().get(self.base_url + url, **self.extra())

def post(self, url, data=None):
if data is None:
data = {}
return super().post(self.base_url + self.version + url,
json.dumps(data),
content_type='application/json',
HTTP_AUTHORIZATION=self.auth_token)
data = {} if data is None else json.dumps(data)
return super().post(self.base_url + url, data, **self.extra())

def put(self, url, data=None):
if data is None:
data = {}
return super().put(self.base_url + self.version + url,
json.dumps(data),
content_type='application/json',
HTTP_AUTHORIZATION=self.auth_token)
data = {} if data is None else json.dumps(data)
return super().put(self.base_url + url, data, **self.extra())

def patch(self, url, data=None):
if data is None:
data = {}
return super().patch(self.base_url + self.version + url,
json.dumps(data),
content_type='application/json',
HTTP_AUTHORIZATION=self.auth_token)
data = {} if data is None else json.dumps(data)
return super().patch(self.base_url + url, data, **self.extra())

def delete(self, url, data=None):
if data is None:
data = {}
return super().delete(self.base_url + self.version + url,
json.dumps(data),
content_type='application/json',
HTTP_AUTHORIZATION=self.auth_token)
data = {} if data is None else json.dumps(data)
return super().delete(self.base_url + url, data, **self.extra())
47 changes: 47 additions & 0 deletions base/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from django.core.management import call_command
from rest_framework.test import APITestCase

from .client import BaseClient
from character.factories import PlayerFactory
from character.models import Player


class BaseTestCase(APITestCase):

def setUp(self):
call_command('socialapps')
self.client = BaseClient()
self.player = PlayerFactory.create()

def tearDown(self):
self.client = None
Player.objects.all().delete()

def test_authenticate(self):
pwd = 'qweqweqwe'
response = self.client.authenticate(self.player.user.username, pwd)
self.assertEqual(response.status_code, 200)
self.assertNotEqual(self.client.auth_token, '')
self.assertEqual(
sorted(list(response.json().keys())),
sorted(['access_token', 'expires_in', 'refresh_token', 'scope',
'token_type']),
)

def test_logout_without_login(self):
response = self.client.logout()
self.assertEqual(response.status_code, 400)
self.assertEqual(
response.json(),
{
'error': 'invalid_request',
'error_description': 'Missing token parameter.'
}
)

def test_logout(self):
pwd = 'qweqweqwe'
self.client.authenticate(self.player.user.username, pwd)
response = self.client.logout()
self.assertEqual(response.status_code, 204)
self.assertEqual(self.client.auth_token, '')
4 changes: 1 addition & 3 deletions character/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
from django.contrib.auth.models import User


# User email will be unique and username not unique
# User email will be unique
User._meta.get_field('email')._unique = True
User._meta.get_field('username')._unique = False



class Character(models.Model):
Expand Down
2 changes: 0 additions & 2 deletions character/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ class Meta:
fields = ('username', 'email')


class NPCSerializer(CharacterSerializer):

class CharacterSerializer(serializers.ModelSerializer):
user = UserSerializer()

Expand Down
21 changes: 10 additions & 11 deletions character/tests.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
from django.conf import settings
from urllib.parse import urlencode
from django.contrib.auth.models import User
from django.core.management import call_command
from rest_framework.test import APITestCase
from urllib.parse import urlencode

from base.client import BaseClient
from .factories import NPCFactory
from .models import NPC
from .factories import NPCFactory, PlayerFactory
from .models import NPC, Player
from .serializers import NPCSerializer


class NPCTestCase(APITestCase):

def setUp(self):
self.user = User.objects.create_superuser(username='[email protected]',
password='qweqweqwe', email='[email protected]')
self.player = PlayerFactory.create()
call_command('socialapps')
self.client = BaseClient(version=settings.VERSION)
self.client = BaseClient()
self.npc = NPCFactory.create()
self.data = {
'user': {
Expand All @@ -27,10 +25,11 @@ def setUp(self):

def tearDown(self):
self.client = None
Player.objects.all().delete()
NPC.objects.all().delete()

def authenticate(self, username='[email protected]', pwd='qweqweqwe'):
response = self.client.authenticate(username, pwd)
self.assertEqual(response.status_code, 200)
def authenticate(self, pwd='qweqweqwe'):
self.client.authenticate(self.player.user.username, pwd)

# CREATE
def character_create(self, ctype, data, st):
Expand All @@ -54,7 +53,7 @@ def test_npc_create_bad_request(self):
def test_npc_create_exist(self):
self.authenticate()
data = {'user': {
'email': self.user.email,
'email': self.player.user.email,
'password': 'qweqweqwe'
}}
self.character_create('npc', data, 400)
Expand Down
1 change: 0 additions & 1 deletion contents/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
SubFactory
)


from .models import Content
from character.factories import NPCFactory, PlayerFactory
from things.factories import ItemFactory, KnowledgeFactory, RolFactory
Expand Down
36 changes: 15 additions & 21 deletions contents/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.gis.geos import Point
from django.core.management import call_command
Expand Down Expand Up @@ -27,11 +25,8 @@
class ContentTestCase(APITestCase):

def setUp(self):
User.objects.create_superuser(username='[email protected]',
password='qweqweqwe',
email='[email protected]')
call_command('socialapps')
self.client = BaseClient(version=settings.VERSION)
self.client = BaseClient()
self.player = PlayerFactory.create()
self.game = GameFactory.create()
self.owner = Owner(player=self.player, game=self.game)
Expand Down Expand Up @@ -82,23 +77,22 @@ def tearDown(self):
Knowledge.objects.all().delete()
Rol.objects.all().delete()

def authenticate(self, username='[email protected]', pwd='qweqweqwe'):
response = self.client.authenticate(username, pwd)
self.assertEqual(response.status_code, 200)
def authenticate(self, pwd='qweqweqwe'):
self.client.authenticate(self.player.user.username, pwd)

# LIST
def test_list_content_unauth(self):
response = self.client.get('/content/')
self.assertEqual(response.status_code, 401)

def test_list_content(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
response = self.client.get('/content/')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 5)

def test_list_content_filter_game(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
response = self.client.get('/content/?game_id={}'.format(self.game.pk))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 5)
Expand All @@ -109,7 +103,7 @@ def test_list_content_filter_game(self):

def test_list_content_filter_bad(self):
""" If you use bad query params, return none """
self.authenticate(username=self.player.user.username)
self.authenticate()
response = self.client.get('/content/?game_id=str')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 0)
Expand All @@ -127,7 +121,7 @@ def test_create_content_unauth(self):
self.assertEqual(response.status_code, 401)

def test_create_content_bad_request(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
self.data_mode1['content_type'] = 'bad'
response = self.client.post('/content/', self.data_mode1)
self.assertEqual(response.status_code, 400)
Expand All @@ -137,7 +131,7 @@ def test_create_content_bad_request(self):
self.assertEqual(response.status_code, 400)

def test_create_content(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
response = self.client.post('/content/', self.data_mode1)
self.assertEqual(response.status_code, 201)

Expand All @@ -149,13 +143,13 @@ def test_destroy_content_unauth(self):
response = self.client.delete('/content/{}/'.format(self.contentItem.pk))
self.assertEqual(response.status_code, 401)

self.owner.delete()
self.authenticate(username=self.player.user.username)
player = PlayerFactory.create()
self.client.authenticate(player.user.username, 'qweqweqwe')
response = self.client.delete('/content/{}/'.format(self.contentItem.pk))
self.assertEqual(response.status_code, 404)

def test_destroy_content(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
response = self.client.delete('/content/{}/'.format(self.contentItem.pk))
self.assertEqual(response.status_code, 204)

Expand All @@ -172,7 +166,7 @@ def test_update_content_unauth(self):
self.assertEqual(response.status_code, 401)

def test_update_content_bad_request(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
data = {
"portion": {
"longitude": 36.261421,
Expand All @@ -189,8 +183,8 @@ def test_update_content_bad_request(self):
self.assertEqual(response.status_code, 400)

def test_update_content(self):
self.authenticate(username=self.player.user.username)
data = ContentSerializer(self.contentNPC).data
self.authenticate()
data.update({
"position": {
"longitude": 36.261421,
Expand Down Expand Up @@ -218,7 +212,7 @@ def test_update_content(self):

# RETRIEVE
def test_get_content_unexist_pk(self):
self.authenticate(username=self.player.user.username)
self.authenticate()
response = self.client.get('/content/{}/'.format(0))
self.assertEqual(response.status_code, 404)

Expand All @@ -227,9 +221,9 @@ def test_get_content_unauth(self):
self.assertEqual(response.status_code, 401)

def test_get_content(self):
self.authenticate(username=self.player.user.username)
contents = [self.contentPlayer, self.contentNPC, self.contentItem,
self.contentKnowledge, self.contentRol]
self.authenticate()
for content in contents:
response = self.client.get('/content/{}/'.format(content.pk))
self.assertEqual(response.status_code, 200)
Expand Down
Loading

0 comments on commit a63424e

Please sign in to comment.