334 lines
12 KiB
Python
334 lines
12 KiB
Python
import copy
|
|
import json
|
|
from datetime import datetime, timedelta
|
|
|
|
from animal_case import animalify
|
|
from grant.email.subscription_settings import get_default_email_subscriptions
|
|
from grant.user.models import User, user_schema, db
|
|
from mock import patch
|
|
|
|
from ..config import BaseUserConfig
|
|
from ..test_data import test_user
|
|
|
|
|
|
class TestUserAPI(BaseUserConfig):
|
|
@patch('grant.email.send.send_email')
|
|
def test_create_user(self, mock_send_email):
|
|
mock_send_email.return_value.ok = True
|
|
# Delete the user config user
|
|
db.session.delete(self.user)
|
|
db.session.commit()
|
|
|
|
response = self.app.post(
|
|
"/api/v1/users/",
|
|
data=json.dumps(test_user),
|
|
content_type='application/json'
|
|
)
|
|
self.assertStatus(response, 201)
|
|
|
|
# User
|
|
user_db = User.get_by_email(test_user["emailAddress"])
|
|
self.assertEqual(user_db.display_name, test_user["displayName"])
|
|
self.assertEqual(user_db.title, test_user["title"])
|
|
self.assertEqual(user_db.email_address, test_user["emailAddress"])
|
|
# should not be able to add social
|
|
self.assertFalse(user_db.social_medias)
|
|
|
|
def test_get_all_users(self):
|
|
users_get_resp = self.app.get(
|
|
"/api/v1/users/"
|
|
)
|
|
self.assert200(users_get_resp)
|
|
users_json = users_get_resp.json
|
|
self.assertEqual(users_json[0]["displayName"], self.user.display_name)
|
|
|
|
def test_get_single_user_by_id(self):
|
|
users_get_resp = self.app.get(
|
|
"/api/v1/users/{}".format(self.user.id)
|
|
)
|
|
|
|
users_json = users_get_resp.json
|
|
self.assertEqual(users_json["avatar"]["imageUrl"], self.user.avatar.image_url)
|
|
self.assertEqual(users_json["socialMedias"][0]["service"], 'GITHUB')
|
|
self.assertEqual(users_json["socialMedias"][0]["username"], 'groot')
|
|
self.assertEqual(users_json["socialMedias"][0]["url"], 'https://github.com/groot')
|
|
self.assertEqual(users_json["displayName"], self.user.display_name)
|
|
|
|
def test_user_auth_success(self):
|
|
user_auth_resp = self.app.post(
|
|
"/api/v1/users/auth",
|
|
data=json.dumps({
|
|
"email": self.user.email_address,
|
|
"password": self.user_password
|
|
}),
|
|
content_type="application/json"
|
|
)
|
|
self.assertEqual(user_auth_resp.json['emailAddress'], self.user.email_address)
|
|
self.assertEqual(user_auth_resp.json['displayName'], self.user.display_name)
|
|
|
|
def test_user_auth_required(self):
|
|
login_resp = self.app.post(
|
|
"/api/v1/users/auth",
|
|
data=json.dumps({
|
|
"email": self.user.email_address,
|
|
"password": self.user_password
|
|
}),
|
|
content_type="application/json"
|
|
)
|
|
# should have session cookie now
|
|
me_resp = self.app.get(
|
|
"/api/v1/users/me"
|
|
)
|
|
self.assert200(me_resp)
|
|
|
|
def test_me_get_includes_email_address(self):
|
|
self.login_default_user()
|
|
me_resp = self.app.get(
|
|
"/api/v1/users/me"
|
|
)
|
|
self.assert200(me_resp)
|
|
self.assertIsNotNone(me_resp.json['emailAddress'])
|
|
|
|
def test_user_auth_required_fail(self):
|
|
me_resp = self.app.get(
|
|
"/api/v1/users/me",
|
|
)
|
|
self.assert401(me_resp)
|
|
|
|
def test_user_auth_bad_password(self):
|
|
user_auth_resp = self.app.post(
|
|
"/api/v1/users/auth",
|
|
data=json.dumps({
|
|
"email": self.user.email_address,
|
|
"password": "badpassword"
|
|
}),
|
|
content_type="application/json"
|
|
)
|
|
self.assert403(user_auth_resp)
|
|
self.assertTrue(user_auth_resp.json['message'] is not None)
|
|
|
|
def test_user_auth_bad_email(self):
|
|
user_auth_resp = self.app.post(
|
|
"/api/v1/users/auth",
|
|
data=json.dumps({
|
|
"email": "bademail@bad.com",
|
|
"password": "somepassword"
|
|
}),
|
|
content_type="application/json"
|
|
)
|
|
self.assert400(user_auth_resp)
|
|
self.assertTrue(user_auth_resp.json['message'] is not None)
|
|
|
|
def test_create_user_duplicate_400(self):
|
|
# self.user is identical to test_user, should throw
|
|
response = self.app.post(
|
|
"/api/v1/users/",
|
|
data=json.dumps(test_user),
|
|
content_type='application/json'
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 409)
|
|
|
|
@patch('grant.user.views.remove_avatar')
|
|
def test_update_user_remove_social_and_avatar(self, mock_remove_avatar):
|
|
self.login_default_user()
|
|
updated_user = animalify(copy.deepcopy(user_schema.dump(self.user)))
|
|
updated_user["displayName"] = 'new display name'
|
|
updated_user["avatar"] = {}
|
|
updated_user["socialMedias"] = []
|
|
|
|
user_update_resp = self.app.put(
|
|
"/api/v1/users/{}".format(self.user.id),
|
|
data=json.dumps(updated_user),
|
|
content_type='application/json'
|
|
)
|
|
self.assert200(user_update_resp, user_update_resp.json)
|
|
|
|
user_json = user_update_resp.json
|
|
self.assertFalse(user_json["avatar"])
|
|
self.assertFalse(len(user_json["socialMedias"]))
|
|
self.assertEqual(user_json["displayName"], updated_user["displayName"])
|
|
self.assertEqual(user_json["title"], updated_user["title"])
|
|
mock_remove_avatar.assert_called_with(test_user["avatar"]["link"], 1)
|
|
|
|
def test_update_user_400_when_required_param_not_passed(self):
|
|
self.login_default_user()
|
|
updated_user = animalify(copy.deepcopy(user_schema.dump(self.user)))
|
|
updated_user["displayName"] = 'new display name'
|
|
del updated_user["avatar"]
|
|
user_update_resp = self.app.put(
|
|
"/api/v1/users/{}".format(self.user.id),
|
|
data=json.dumps(updated_user),
|
|
content_type='application/json'
|
|
)
|
|
self.assert400(user_update_resp)
|
|
|
|
@patch('grant.email.send.send_email')
|
|
def test_recover_user(self, mock_send_email):
|
|
mock_send_email.return_value.ok = True
|
|
|
|
# 1. request reset email
|
|
response = self.app.post(
|
|
"/api/v1/users/recover",
|
|
data=json.dumps({'email': self.user.email_address}),
|
|
content_type='application/json'
|
|
)
|
|
|
|
self.assertStatus(response, 200)
|
|
er = self.user.email_recovery
|
|
self.assertIsNotNone(er)
|
|
created_diff = datetime.now() - er.date_created
|
|
self.assertAlmostEqual(created_diff.seconds, 0)
|
|
code = er.code
|
|
|
|
# 2. reset password
|
|
new_password = 'n3wp455w3rd'
|
|
reset_resp = self.app.post(
|
|
"/api/v1/users/recover/{}".format(code),
|
|
data=json.dumps({'password': new_password}),
|
|
content_type='application/json'
|
|
)
|
|
self.assertStatus(reset_resp, 200)
|
|
|
|
# 3. check new password
|
|
login_resp = self.login_default_user(new_password)
|
|
self.assertStatus(login_resp, 200)
|
|
|
|
@patch('grant.email.send.send_email')
|
|
@patch('grant.email.models.datetime')
|
|
def test_recover_user_code_expired(self, mock_datetime, mock_send_email):
|
|
mock_send_email.return_value.ok = True
|
|
code_create_time = datetime(year=2020, month=1, day=1, hour=1)
|
|
mock_datetime.now.return_value = code_create_time
|
|
|
|
# 1. request reset email
|
|
response = self.app.post(
|
|
"/api/v1/users/recover",
|
|
data=json.dumps({'email': self.user.email_address}),
|
|
content_type='application/json'
|
|
)
|
|
self.assertStatus(response, 200)
|
|
er = self.user.email_recovery
|
|
self.assertEqual(er.date_created, code_create_time)
|
|
code = er.code
|
|
|
|
# expire (pass time)
|
|
mock_datetime.now.return_value = code_create_time + timedelta(minutes=61)
|
|
|
|
# 2. attempt reset password
|
|
reset_resp = self.app.post(
|
|
"/api/v1/users/recover/{}".format(code),
|
|
data=json.dumps({'password': 'n3wp455w3rd'}),
|
|
content_type='application/json'
|
|
)
|
|
self.assertStatus(reset_resp, 401)
|
|
self.assertIsNotNone(reset_resp.json['message'])
|
|
|
|
def test_recover_user_no_user(self):
|
|
response = self.app.post(
|
|
"/api/v1/users/recover",
|
|
data=json.dumps({'email': 'notinthe@system.com'}),
|
|
content_type='application/json'
|
|
)
|
|
|
|
self.assertStatus(response, 400)
|
|
self.assertIsNone(self.user.email_recovery)
|
|
|
|
def test_recover_user_no_code(self):
|
|
new_password = 'n3wp455w3rd'
|
|
reset_resp = self.app.post(
|
|
"/api/v1/users/recover/12345",
|
|
data=json.dumps({'password': 'n3wp455w3rd'}),
|
|
content_type='application/json'
|
|
)
|
|
self.assertStatus(reset_resp, 400)
|
|
self.assertIsNotNone(reset_resp.json['message'])
|
|
|
|
@patch('grant.user.views.verify_social')
|
|
def test_user_verify_social(self, mock_verify_social):
|
|
mock_verify_social.return_value = 'billy'
|
|
self.login_default_user()
|
|
|
|
verify_social_resp = self.app.post(
|
|
"/api/v1/users/social/GITHUB/verify",
|
|
data=json.dumps({"code": '12345'}),
|
|
content_type='application/json'
|
|
)
|
|
self.assert200(verify_social_resp)
|
|
self.assertEqual(verify_social_resp.json["username"], 'billy')
|
|
|
|
get_user_resp = self.app.get(
|
|
"/api/v1/users/{}".format(self.user.id)
|
|
)
|
|
|
|
users_json = get_user_resp.json
|
|
self.assertEqual(users_json["socialMedias"][0]["service"], 'GITHUB')
|
|
self.assertEqual(users_json["socialMedias"][0]["username"], 'billy')
|
|
self.assertEqual(users_json["socialMedias"][0]["url"], 'https://github.com/billy')
|
|
|
|
def test_user_verify_social_no_auth(self):
|
|
verify_social_resp = self.app.post(
|
|
"/api/v1/users/social/GITHUB/verify",
|
|
data=json.dumps({"code": '12345'}),
|
|
content_type='application/json'
|
|
)
|
|
self.assert401(verify_social_resp)
|
|
|
|
@patch('grant.user.views.get_social_login_url')
|
|
def test_user_social_authurl(self, mock_get_social_login_url):
|
|
expected_url = 'https://fake.login?token=12345'
|
|
mock_get_social_login_url.return_value = expected_url
|
|
self.login_default_user()
|
|
social_authurl_resp = self.app.get(
|
|
"/api/v1/users/social/SERVICE/authurl"
|
|
)
|
|
self.assert200(social_authurl_resp)
|
|
self.assertEqual(social_authurl_resp.json["url"], expected_url)
|
|
|
|
def test_get_user_settings_auth_required(self):
|
|
resp = self.app.get(
|
|
"/api/v1/users/{}/settings".format(self.user.id)
|
|
)
|
|
self.assert401(resp)
|
|
|
|
def test_get_user_settings(self):
|
|
self.login_default_user()
|
|
resp = self.app.get(
|
|
"/api/v1/users/{}/settings".format(self.user.id)
|
|
)
|
|
self.assert200(resp)
|
|
self.assertIsNotNone(resp.json['emailSubscriptions'])
|
|
|
|
def test_put_user_settings_auth_required(self):
|
|
resp = self.app.put(
|
|
"/api/v1/users/{}/settings".format(self.user.id),
|
|
data=json.dumps({'emailSubscriptions': {}}),
|
|
content_type='application/json'
|
|
)
|
|
self.assert401(resp)
|
|
|
|
def test_put_user_settings_email_subscriptions(self):
|
|
self.login_default_user()
|
|
subs = animalify(get_default_email_subscriptions())
|
|
subs['myCommentReply'] = False
|
|
resp = self.app.put(
|
|
"/api/v1/users/{}/settings".format(self.user.id),
|
|
data=json.dumps({'emailSubscriptions': subs}),
|
|
content_type='application/json'
|
|
)
|
|
self.assert200(resp)
|
|
self.assertIsNotNone(resp.json['emailSubscriptions'])
|
|
self.maxDiff = None
|
|
self.assertEquals(resp.json['emailSubscriptions'], subs)
|
|
|
|
def test_put_user_settings_email_subscriptions_bad_key(self):
|
|
self.login_default_user()
|
|
subs = animalify(get_default_email_subscriptions())
|
|
subs['badKey'] = False
|
|
resp = self.app.put(
|
|
"/api/v1/users/{}/settings".format(self.user.id),
|
|
data=json.dumps({'emailSubscriptions': subs}),
|
|
content_type='application/json'
|
|
)
|
|
self.assert400(resp)
|