Commit a55a90018e1925b55dc0ed69b94e80ef99baeca9
Exists in
master
Merge branch 'master' of git.ucsd.edu:110swag/flashy-backend
Showing 3 changed files Inline Diff
flashcards/tests/test_api.py
View file @
a55a900
from django.core import mail | 1 | 1 | from django.core import mail | |
from flashcards.models import User, Section, Flashcard | 2 | 2 | from flashcards.models import User, Section, Flashcard | |
from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_201_CREATED, HTTP_200_OK, HTTP_401_UNAUTHORIZED | 3 | 3 | from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_201_CREATED, HTTP_200_OK, HTTP_401_UNAUTHORIZED | |
from rest_framework.test import APITestCase | 4 | 4 | from rest_framework.test import APITestCase | |
from re import search | 5 | 5 | from re import search | |
from django.utils.timezone import now | 6 | 6 | from django.utils.timezone import now | |
7 | 7 | |||
8 | 8 | |||
class LoginTests(APITestCase): | 9 | 9 | class LoginTests(APITestCase): | |
def setUp(self): | 10 | 10 | def setUp(self): | |
email = "test@flashy.cards" | 11 | 11 | email = "test@flashy.cards" | |
User.objects.create_user(email=email, password="1234") | 12 | 12 | User.objects.create_user(email=email, password="1234") | |
13 | 13 | |||
def test_login(self): | 14 | 14 | def test_login(self): | |
url = '/api/login' | 15 | 15 | url = '/api/login' | |
data = {'email': 'test@flashy.cards', 'password': '1234'} | 16 | 16 | data = {'email': 'test@flashy.cards', 'password': '1234'} | |
response = self.client.post(url, data, format='json') | 17 | 17 | response = self.client.post(url, data, format='json') | |
self.assertEqual(response.status_code, HTTP_200_OK) | 18 | 18 | self.assertEqual(response.status_code, HTTP_200_OK) | |
19 | 19 | |||
data = {'email': 'test@flashy.cards', 'password': '54321'} | 20 | 20 | data = {'email': 'test@flashy.cards', 'password': '54321'} | |
response = self.client.post(url, data, format='json') | 21 | 21 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'Invalid email or password', status_code=403) | 22 | 22 | self.assertContains(response, 'Invalid email or password', status_code=403) | |
23 | 23 | |||
data = {'email': 'none@flashy.cards', 'password': '54321'} | 24 | 24 | data = {'email': 'none@flashy.cards', 'password': '54321'} | |
response = self.client.post(url, data, format='json') | 25 | 25 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'Invalid email or password', status_code=403) | 26 | 26 | self.assertContains(response, 'Invalid email or password', status_code=403) | |
27 | 27 | |||
data = {'password': '54321'} | 28 | 28 | data = {'password': '54321'} | |
response = self.client.post(url, data, format='json') | 29 | 29 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'email', status_code=400) | 30 | 30 | self.assertContains(response, 'email', status_code=400) | |
31 | 31 | |||
data = {'email': 'none@flashy.cards'} | 32 | 32 | data = {'email': 'none@flashy.cards'} | |
response = self.client.post(url, data, format='json') | 33 | 33 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'password', status_code=400) | 34 | 34 | self.assertContains(response, 'password', status_code=400) | |
35 | 35 | |||
user = User.objects.get(email="test@flashy.cards") | 36 | 36 | user = User.objects.get(email="test@flashy.cards") | |
user.is_active = False | 37 | 37 | user.is_active = False | |
user.save() | 38 | 38 | user.save() | |
39 | 39 | |||
data = {'email': 'test@flashy.cards', 'password': '1234'} | 40 | 40 | data = {'email': 'test@flashy.cards', 'password': '1234'} | |
response = self.client.post(url, data, format='json') | 41 | 41 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'Account is disabled', status_code=403) | 42 | 42 | self.assertContains(response, 'Account is disabled', status_code=403) | |
43 | 43 | |||
def test_logout(self): | 44 | 44 | def test_logout(self): | |
url = '/api/login' | 45 | 45 | url = '/api/logout' | |
data = {'email': 'test@flashy.cards', 'password': '1234'} | 46 | 46 | self.client.login(email='test@flashy.cards', password='1234') | |
response = self.client.post(url, data, format='json') | 47 | 47 | response = self.client.post(url) | |
self.assertEqual(response.status_code, HTTP_200_OK) | 48 | 48 | self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) | |
49 | 49 | |||
p = self.client.post('/api/logout') | 50 | 50 | # since we're not logged in, we should get a 401 response | |
self.assertEqual(p.status_code, HTTP_204_NO_CONTENT) | 51 | |||
response = self.client.get('/api/users/me', format='json') | 52 | 51 | response = self.client.get('/api/users/me', format='json') | |
53 | ||||
# since we're not logged in, we shouldn't be able to see this | 54 | |||
self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) | 55 | 52 | self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) | |
56 | 53 | |||
57 | 54 | |||
class PasswordResetTest(APITestCase): | 58 | 55 | class PasswordResetTest(APITestCase): | |
def setUp(self): | 59 | 56 | def setUp(self): | |
# create a user to test things with | 60 | 57 | # create a user to test things with | |
email = "test@flashy.cards" | 61 | 58 | email = "test@flashy.cards" | |
User.objects.create_user(email=email, password="12345") | 62 | 59 | User.objects.create_user(email=email, password="12345") | |
63 | 60 | |||
def test_reset_password(self): | 64 | 61 | def test_reset_password(self): | |
# submit the request to reset the password | 65 | 62 | # submit the request to reset the password | |
url = '/api/reset_password' | 66 | 63 | url = '/api/reset_password' | |
post_data = {'email': 'test@flashy.cards'} | 67 | 64 | post_data = {'email': 'test@flashy.cards'} | |
self.client.post(url, post_data, format='json') | 68 | 65 | self.client.post(url, post_data, format='json') | |
self.assertEqual(len(mail.outbox), 1) | 69 | 66 | self.assertEqual(len(mail.outbox), 1) | |
self.assertIn('reset your password', mail.outbox[0].body) | 70 | 67 | self.assertIn('reset your password', mail.outbox[0].body) | |
71 | 68 | |||
# capture the reset token from the email | 72 | 69 | # capture the reset token from the email | |
capture = search('https://flashy.cards/app/reset_password/(\d+)/(.*)', | 73 | 70 | capture = search('https://flashy.cards/app/reset_password/(\d+)/(.*)', | |
mail.outbox[0].body) | 74 | 71 | mail.outbox[0].body) | |
patch_data = {'new_password': '54321'} | 75 | 72 | patch_data = {'new_password': '54321'} | |
patch_data['uid'] = capture.group(1) | 76 | 73 | patch_data['uid'] = capture.group(1) | |
reset_token = capture.group(2) | 77 | 74 | reset_token = capture.group(2) | |
78 | 75 | |||
# try to reset the password with the wrong reset token | 79 | 76 | # try to reset the password with the wrong reset token | |
patch_data['token'] = 'wrong_token' | 80 | 77 | patch_data['token'] = 'wrong_token' | |
response = self.client.patch(url, patch_data, format='json') | 81 | 78 | response = self.client.patch(url, patch_data, format='json') | |
self.assertContains(response, 'Could not verify reset token', status_code=400) | 82 | 79 | self.assertContains(response, 'Could not verify reset token', status_code=400) | |
83 | 80 | |||
# try to reset the password with the correct token | 84 | 81 | # try to reset the password with the correct token | |
patch_data['token'] = reset_token | 85 | 82 | patch_data['token'] = reset_token | |
response = self.client.patch(url, patch_data, format='json') | 86 | 83 | response = self.client.patch(url, patch_data, format='json') | |
self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) | 87 | 84 | self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) | |
user = User.objects.get(id=patch_data['uid']) | 88 | 85 | user = User.objects.get(id=patch_data['uid']) | |
assert user.check_password(patch_data['new_password']) | 89 | 86 | assert user.check_password(patch_data['new_password']) | |
90 | 87 | |||
91 | 88 | |||
class RegistrationTest(APITestCase): | 92 | 89 | class RegistrationTest(APITestCase): | |
def test_create_account(self): | 93 | 90 | def test_create_account(self): | |
url = '/api/users/me' | 94 | 91 | url = '/api/users/me' | |
95 | 92 | |||
# missing password | 96 | 93 | # missing password | |
data = {'email': 'none@none.com'} | 97 | 94 | data = {'email': 'none@none.com'} | |
response = self.client.post(url, data, format='json') | 98 | 95 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'password', status_code=400) | 99 | 96 | self.assertContains(response, 'password', status_code=400) | |
100 | 97 | |||
# missing email | 101 | 98 | # missing email | |
data = {'password': '1234'} | 102 | 99 | data = {'password': '1234'} | |
response = self.client.post(url, data, format='json') | 103 | 100 | response = self.client.post(url, data, format='json') | |
self.assertContains(response, 'email', status_code=400) | 104 | 101 | self.assertContains(response, 'email', status_code=400) | |
105 | 102 | |||
# create a user | 106 | 103 | # create a user | |
data = {'email': 'none@none.com', 'password': '1234'} | 107 | 104 | data = {'email': 'none@none.com', 'password': '1234'} | |
response = self.client.post(url, data, format='json') | 108 | 105 | response = self.client.post(url, data, format='json') | |
self.assertEqual(response.status_code, HTTP_201_CREATED) | 109 | 106 | self.assertEqual(response.status_code, HTTP_201_CREATED) | |
110 | 107 | |||
# user should not be confirmed | 111 | 108 | # user should not be confirmed | |
user = User.objects.get(email="none@none.com") | 112 | 109 | user = User.objects.get(email="none@none.com") | |
self.assertFalse(user.is_confirmed) | 113 | 110 | self.assertFalse(user.is_confirmed) | |
114 | 111 | |||
# check that the confirmation key was sent | 115 | 112 | # check that the confirmation key was sent | |
self.assertEqual(len(mail.outbox), 1) | 116 | 113 | self.assertEqual(len(mail.outbox), 1) | |
self.assertIn(user.confirmation_key, mail.outbox[0].body) | 117 | 114 | self.assertIn(user.confirmation_key, mail.outbox[0].body) | |
118 | 115 | |||
# log the user out | 119 | 116 | # log the user out | |
self.client.logout() | 120 | 117 | self.client.logout() | |
121 | 118 | |||
# log the user in with their registered credentials | 122 | 119 | # log the user in with their registered credentials | |
self.client.login(email='none@none.com', password='1234') | 123 | 120 | self.client.login(email='none@none.com', password='1234') | |
124 | 121 | |||
# try activating with an invalid key | 125 | 122 | # try activating with an invalid key | |
response = self.client.patch(url, {'confirmation_key': 'NOT A KEY'}) | 126 | 123 | response = self.client.patch(url, {'confirmation_key': 'NOT A KEY'}) | |
self.assertContains(response, 'confirmation_key is invalid', status_code=400) | 127 | 124 | self.assertContains(response, 'confirmation_key is invalid', status_code=400) | |
128 | 125 | |||
# try activating with the valid key | 129 | 126 | # try activating with the valid key | |
response = self.client.patch(url, {'confirmation_key': user.confirmation_key}) | 130 | 127 | response = self.client.patch(url, {'confirmation_key': user.confirmation_key}) | |
self.assertTrue(response.data['is_confirmed']) | 131 | 128 | self.assertTrue(response.data['is_confirmed']) | |
132 | 129 | |||
133 | 130 | |||
class ProfileViewTest(APITestCase): | 134 | 131 | class ProfileViewTest(APITestCase): | |
def setUp(self): | 135 | 132 | def setUp(self): | |
email = "profileviewtest@flashy.cards" | 136 | 133 | email = "profileviewtest@flashy.cards" | |
User.objects.create_user(email=email, password="1234") | 137 | 134 | User.objects.create_user(email=email, password="1234") | |
138 | 135 | |||
def test_get_me(self): | 139 | 136 | def test_get_me(self): | |
url = '/api/users/me' | 140 | 137 | url = '/api/users/me' | |
response = self.client.get(url, format='json') | 141 | 138 | response = self.client.get(url, format='json') | |
# since we're not logged in, we shouldn't be able to see this | 142 | 139 | # since we're not logged in, we shouldn't be able to see this | |
self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) | 143 | 140 | self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) | |
144 | 141 | |||
self.client.login(email='profileviewtest@flashy.cards', password='1234') | 145 | 142 | self.client.login(email='profileviewtest@flashy.cards', password='1234') | |
response = self.client.get(url, format='json') | 146 | 143 | response = self.client.get(url, format='json') | |
self.assertEqual(response.status_code, HTTP_200_OK) | 147 | 144 | self.assertEqual(response.status_code, HTTP_200_OK) | |
148 | 145 | |||
149 | 146 | |||
class PasswordChangeTest(APITestCase): | 150 | 147 | class PasswordChangeTest(APITestCase): | |
def setUp(self): | 151 | 148 | def setUp(self): | |
email = "none@none.com" | 152 | 149 | email = "none@none.com" | |
User.objects.create_user(email=email, password="1234") | 153 | 150 | User.objects.create_user(email=email, password="1234") | |
154 | 151 | |||
def test_change_password(self): | 155 | 152 | def test_change_password(self): | |
url = '/api/users/me' | 156 | 153 | url = '/api/users/me' | |
user = User.objects.get(email='none@none.com') | 157 | 154 | user = User.objects.get(email='none@none.com') | |
self.assertTrue(user.check_password('1234')) | 158 | 155 | self.assertTrue(user.check_password('1234')) | |
159 | 156 | |||
response = self.client.patch(url, {'new_password': '4321', 'old_password': '1234'}, format='json') | 160 | 157 | response = self.client.patch(url, {'new_password': '4321', 'old_password': '1234'}, format='json') | |
self.assertContains(response, 'You must be logged in to change your password', status_code=403) | 161 | 158 | self.assertContains(response, 'You must be logged in to change your password', status_code=403) | |
162 | 159 |
requirements.txt
View file @
a55a900
#beautifulsoup4 | 1 | 1 | #beautifulsoup4 | |
Django>=1.8 | 2 | 2 | Django>=1.8 | |
#django-websocket-redis==0.4.3 | 3 | 3 | #django-websocket-redis==0.4.3 | |
#gevent==1.0.1 | 4 | 4 | #gevent==1.0.1 | |
#greenlet==0.4.5 | 5 | 5 | #greenlet==0.4.5 | |
#redis==2.10.3 | 6 | 6 | #redis==2.10.3 | |
six==1.9.0 | 7 | 7 | six==1.9.0 | |
djangorestframework | 8 | 8 | djangorestframework | |
docutils | 9 | 9 | docutils | |
django-simple-email-confirmation | 10 | 10 | django-simple-email-confirmation | |
django-ses | 11 | 11 | django-ses | |
coverage | 12 | 12 | coverage | |
django-rest-swagger | 13 | 13 | django-rest-swagger | |
14 | newrelic |
scripts/run_production.sh
View file @
a55a900
#!/bin/bash -xe | 1 | 1 | #!/bin/bash -xe | |
source secrets.sh | 2 | 2 | source secrets.sh | |
source venv/bin/activate | 3 | 3 | source venv/bin/activate | |
/srv/flashy-backend/venv/bin/gunicorn --pid /run/flashy/gunicorn.pid -w 6 -n flashy -b 127.0.0.1:7002 flashy.wsgi | 4 | 4 | newrelic-admin run-program /srv/flashy-backend/venv/bin/gunicorn --pid /run/flashy/gunicorn.pid -w 6 -n flashy -b 127.0.0.1:7002 flashy.wsgi | |
5 | 5 |