API & Client: registration controls
This commit is contained in:
@ -14,7 +14,8 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
data=json.dumps(dict(
|
||||
username='justatest',
|
||||
email='test@test.com',
|
||||
password='123456'
|
||||
password='12345678',
|
||||
password_conf='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
@ -26,14 +27,15 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
self.assertEqual(response.status_code, 201)
|
||||
|
||||
def test_user_registration_user_already_exists(self):
|
||||
add_user('test', 'test@test.com', 'test')
|
||||
add_user('test', 'test@test.com', '12345678')
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test',
|
||||
email='test@test.com',
|
||||
password='test'
|
||||
password='12345678',
|
||||
password_conf='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
@ -44,6 +46,101 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_user_registration_invalid_short_username(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='t',
|
||||
email='test@test.com',
|
||||
password='12345678',
|
||||
password_conf='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(
|
||||
data['message'] == "Errors: Username: 3 to 12 characters required.\n")
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_user_registration_invalid_long_username(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='testestestestestest',
|
||||
email='test@test.com',
|
||||
password='12345678',
|
||||
password_conf='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(
|
||||
data['message'] == "Errors: Username: 3 to 12 characters required.\n")
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_user_registration_invalid_email(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test',
|
||||
email='test@test',
|
||||
password='12345678',
|
||||
password_conf='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(
|
||||
data['message'] == "Errors: Valid email must be provided.\n")
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_user_registration_invalid_short_password(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test',
|
||||
email='test@test.com',
|
||||
password='1234567',
|
||||
password_conf='1234567'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(
|
||||
data['message'] == "Errors: Password: 8 characters required.\n")
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_user_registration_mismatched_password(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test',
|
||||
email='test@test.com',
|
||||
password='12345678',
|
||||
password_conf='87654321'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(
|
||||
data['message'] == "Errors: Password and password confirmation don\'t match.\n")
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_user_registration_invalid_json(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
@ -60,7 +157,10 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(email='test@test.com', password='test')),
|
||||
data=json.dumps(dict(
|
||||
email='test@test.com',
|
||||
password='12345678',
|
||||
password_conf='12345678')),
|
||||
content_type='application/json',
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
@ -73,7 +173,9 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test', password='test')),
|
||||
username='test',
|
||||
password='12345678',
|
||||
password_conf='12345678')),
|
||||
content_type='application/json',
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
@ -86,7 +188,24 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test', email='test@test.com')),
|
||||
username='test',
|
||||
email='test@test.com',
|
||||
password_conf='12345678')),
|
||||
content_type='application/json',
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('Invalid payload.', data['message'])
|
||||
self.assertIn('error', data['status'])
|
||||
|
||||
def test_user_registration_invalid_json_keys_no_password_conf(self):
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/register',
|
||||
data=json.dumps(dict(
|
||||
username='test',
|
||||
email='test@test.com',
|
||||
password='12345678')),
|
||||
content_type='application/json',
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
@ -96,12 +215,12 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
|
||||
def test_registered_user_login(self):
|
||||
with self.client:
|
||||
add_user('test', 'test@test.com', 'test')
|
||||
add_user('test', 'test@test.com', '12345678')
|
||||
response = self.client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(dict(
|
||||
email='test@test.com',
|
||||
password='test'
|
||||
password='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
@ -118,25 +237,42 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
'/api/auth/login',
|
||||
data=json.dumps(dict(
|
||||
email='test@test.com',
|
||||
password='test'
|
||||
password='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(data['message'] == 'User does not exist.')
|
||||
self.assertTrue(data['message'] == 'Invalid credentials.')
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_registered_user_login_invalid_password(self):
|
||||
add_user('test', 'test@test.com', '12345678')
|
||||
with self.client:
|
||||
response = self.client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(dict(
|
||||
email='test@test.com',
|
||||
password='123456789'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
data = json.loads(response.data.decode())
|
||||
self.assertTrue(data['status'] == 'error')
|
||||
self.assertTrue(data['message'] == 'Invalid credentials.')
|
||||
self.assertTrue(response.content_type == 'application/json')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_valid_logout(self):
|
||||
add_user('test', 'test@test.com', 'test')
|
||||
add_user('test', 'test@test.com', '12345678')
|
||||
with self.client:
|
||||
# user login
|
||||
resp_login = self.client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(dict(
|
||||
email='test@test.com',
|
||||
password='test'
|
||||
password='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
@ -155,13 +291,13 @@ class TestAuthBlueprint(BaseTestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_invalid_logout_expired_token(self):
|
||||
add_user('test', 'test@test.com', 'test')
|
||||
add_user('test', 'test@test.com', '12345678')
|
||||
with self.client:
|
||||
resp_login = self.client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(dict(
|
||||
email='test@test.com',
|
||||
password='test'
|
||||
password='12345678'
|
||||
)),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
@ -4,7 +4,7 @@ from sqlalchemy import exc, or_
|
||||
from mpwo_api import appLog, bcrypt, db
|
||||
|
||||
from .models import User
|
||||
from .utils import authenticate
|
||||
from .utils import authenticate, register_controls
|
||||
|
||||
auth_blueprint = Blueprint('auth', __name__)
|
||||
|
||||
@ -15,7 +15,8 @@ def register_user():
|
||||
post_data = request.get_json()
|
||||
if not post_data or post_data.get('username') is None \
|
||||
or post_data.get('email') is None \
|
||||
or post_data.get('password') is None:
|
||||
or post_data.get('password') is None \
|
||||
or post_data.get('password_conf') is None:
|
||||
response_object = {
|
||||
'status': 'error',
|
||||
'message': 'Invalid payload.'
|
||||
@ -24,6 +25,16 @@ def register_user():
|
||||
username = post_data.get('username')
|
||||
email = post_data.get('email')
|
||||
password = post_data.get('password')
|
||||
password_conf = post_data.get('password_conf')
|
||||
|
||||
ret = register_controls(username, email, password, password_conf)
|
||||
if ret != '':
|
||||
response_object = {
|
||||
'status': 'error',
|
||||
'message': 'Errors: ' + ret
|
||||
}
|
||||
return jsonify(response_object), 400
|
||||
|
||||
try:
|
||||
# check for existing user
|
||||
user = User.query.filter(
|
||||
@ -90,7 +101,7 @@ def login_user():
|
||||
else:
|
||||
response_object = {
|
||||
'status': 'error',
|
||||
'message': 'User does not exist.'
|
||||
'message': 'Invalid credentials.'
|
||||
}
|
||||
return jsonify(response_object), 404
|
||||
# handler errors
|
||||
|
@ -1,4 +1,5 @@
|
||||
from functools import wraps
|
||||
import re
|
||||
|
||||
from flask import request, jsonify
|
||||
|
||||
@ -33,3 +34,21 @@ def authenticate(f):
|
||||
def is_admin(user_id):
|
||||
user = User.query.filter_by(id=user_id).first()
|
||||
return user.admin
|
||||
|
||||
|
||||
def is_valid_email(email):
|
||||
mail_pattern = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"
|
||||
return re.match(mail_pattern, email) is not None
|
||||
|
||||
|
||||
def register_controls(username, email, password, password_conf):
|
||||
ret = ''
|
||||
if not 2 < len(username) < 13:
|
||||
ret += 'Username: 3 to 12 characters required.\n'
|
||||
if not is_valid_email(email):
|
||||
ret += 'Valid email must be provided.\n'
|
||||
if password != password_conf:
|
||||
ret += 'Password and password confirmation don\'t match.\n'
|
||||
if len(password) < 8:
|
||||
ret += 'Password: 8 characters required.\n'
|
||||
return ret
|
||||
|
@ -26,7 +26,7 @@ def seed_db():
|
||||
def test():
|
||||
"""Runs the tests without code coverage."""
|
||||
tests = unittest.TestLoader().discover(
|
||||
'mpwo_api/tests', pattern='test*.py')
|
||||
'mpwo_api/mpwo_api/tests', pattern='test*.py')
|
||||
result = unittest.TextTestRunner(verbosity=2).run(tests)
|
||||
if result.wasSuccessful():
|
||||
return 0
|
||||
|
Reference in New Issue
Block a user