2019-11-13 18:40:01 +01:00
|
|
|
import json
|
2022-03-23 18:29:49 +01:00
|
|
|
from typing import Optional
|
2019-11-13 18:40:01 +01:00
|
|
|
|
2022-03-23 18:29:49 +01:00
|
|
|
import pytest
|
2021-01-02 19:28:03 +01:00
|
|
|
from flask import Flask
|
|
|
|
|
2022-03-23 18:29:49 +01:00
|
|
|
from fittrackee.application.models import AppConfig
|
2021-01-20 16:47:00 +01:00
|
|
|
from fittrackee.users.models import User
|
|
|
|
|
2022-03-19 20:34:36 +01:00
|
|
|
from ..mixins import ApiTestCaseMixin
|
2022-04-02 17:16:10 +02:00
|
|
|
from ..utils import jsonify_dict
|
2019-11-13 18:40:01 +01:00
|
|
|
|
2021-02-20 23:20:20 +01:00
|
|
|
|
|
|
|
class TestGetConfig(ApiTestCaseMixin):
|
2022-03-19 22:02:06 +01:00
|
|
|
def test_it_gets_application_config_for_unauthenticated_user(
|
|
|
|
self, app: Flask
|
2021-01-02 19:28:03 +01:00
|
|
|
) -> None:
|
2022-04-02 17:16:10 +02:00
|
|
|
app_config = AppConfig.query.first()
|
2022-03-19 22:02:06 +01:00
|
|
|
client = app.test_client()
|
2020-05-10 15:55:56 +02:00
|
|
|
|
2022-03-19 22:02:06 +01:00
|
|
|
response = client.get('/api/config')
|
2020-05-10 15:55:56 +02:00
|
|
|
|
|
|
|
data = json.loads(response.data.decode())
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert 'success' in data['status']
|
2022-04-02 17:16:10 +02:00
|
|
|
assert data['data'] == jsonify_dict(app_config.serialize())
|
2020-05-10 15:55:56 +02:00
|
|
|
|
2022-03-19 22:02:06 +01:00
|
|
|
def test_it_gets_application_config(
|
|
|
|
self, app: Flask, user_1: User
|
|
|
|
) -> None:
|
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
|
|
|
app, user_1.email
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.get(
|
|
|
|
'/api/config',
|
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
|
|
|
)
|
|
|
|
|
|
|
|
data = json.loads(response.data.decode())
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert 'success' in data['status']
|
|
|
|
|
2020-05-10 15:55:56 +02:00
|
|
|
def test_it_returns_error_if_application_has_no_config(
|
2021-01-02 19:28:03 +01:00
|
|
|
self, app_no_config: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app_no_config, user_1_admin.email
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.get(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_500(response, 'error on getting configuration')
|
2020-05-10 15:55:56 +02:00
|
|
|
|
|
|
|
def test_it_returns_error_if_application_has_several_config(
|
2021-01-02 19:28:03 +01:00
|
|
|
self, app: Flask, app_config: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.get(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_500(response, 'error on getting configuration')
|
2020-05-10 15:55:56 +02:00
|
|
|
|
|
|
|
|
2021-02-20 23:20:20 +01:00
|
|
|
class TestUpdateConfig(ApiTestCaseMixin):
|
2021-01-02 19:28:03 +01:00
|
|
|
def test_it_updates_config_when_user_is_admin(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(dict(gpx_limit_import=100, max_users=10)),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
data = json.loads(response.data.decode())
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
assert 'success' in data['status']
|
|
|
|
assert data['data']['gpx_limit_import'] == 100
|
|
|
|
assert data['data']['is_registration_enabled'] is True
|
|
|
|
assert data['data']['max_single_file_size'] == 1048576
|
|
|
|
assert data['data']['max_zip_file_size'] == 10485760
|
|
|
|
assert data['data']['max_users'] == 10
|
|
|
|
|
2021-01-02 19:28:03 +01:00
|
|
|
def test_it_updates_all_config(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
2022-03-23 18:29:49 +01:00
|
|
|
admin_email = self.random_email()
|
2020-05-10 15:55:56 +02:00
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
2022-03-23 18:29:49 +01:00
|
|
|
admin_contact=admin_email,
|
2020-05-10 15:55:56 +02:00
|
|
|
gpx_limit_import=20,
|
|
|
|
max_single_file_size=10000,
|
|
|
|
max_zip_file_size=25000,
|
|
|
|
max_users=50,
|
|
|
|
)
|
|
|
|
),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
2022-03-23 18:29:49 +01:00
|
|
|
data = json.loads(response.data.decode())
|
2020-05-10 15:55:56 +02:00
|
|
|
assert 'success' in data['status']
|
2022-03-23 18:29:49 +01:00
|
|
|
assert data['data']['admin_contact'] == admin_email
|
2020-05-10 15:55:56 +02:00
|
|
|
assert data['data']['gpx_limit_import'] == 20
|
|
|
|
assert data['data']['is_registration_enabled'] is True
|
|
|
|
assert data['data']['max_single_file_size'] == 10000
|
|
|
|
assert data['data']['max_zip_file_size'] == 25000
|
|
|
|
assert data['data']['max_users'] == 50
|
|
|
|
|
2021-01-02 19:28:03 +01:00
|
|
|
def test_it_returns_403_when_user_is_not_an_admin(
|
|
|
|
self, app: Flask, user_1: User
|
|
|
|
) -> None:
|
2022-03-12 17:56:06 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
|
|
|
app, user_1.email
|
|
|
|
)
|
2020-05-10 15:55:56 +02:00
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(dict(gpx_limit_import=100, max_users=10)),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_403(response)
|
2020-05-10 15:55:56 +02:00
|
|
|
|
2021-01-02 19:28:03 +01:00
|
|
|
def test_it_returns_400_if_invalid_is_payload(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(dict()),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_400(response)
|
2020-05-10 15:55:56 +02:00
|
|
|
|
|
|
|
def test_it_returns_error_on_update_if_application_has_no_config(
|
2021-01-02 19:28:03 +01:00
|
|
|
self, app_no_config: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app_no_config, user_1_admin.email
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(dict(gpx_limit_import=100, max_users=10)),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2020-05-10 15:55:56 +02:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_500(response, 'error when updating configuration')
|
2021-02-20 14:14:26 +01:00
|
|
|
|
|
|
|
def test_it_raises_error_if_archive_max_size_is_below_files_max_size(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2021-02-20 14:14:26 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
|
|
|
gpx_limit_import=20,
|
|
|
|
max_single_file_size=10000,
|
|
|
|
max_zip_file_size=1000,
|
|
|
|
max_users=50,
|
|
|
|
)
|
|
|
|
),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2021-02-20 14:14:26 +01:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_400(
|
|
|
|
response,
|
|
|
|
(
|
|
|
|
'Max. size of zip archive must be equal or greater than max.'
|
|
|
|
' size of uploaded files'
|
|
|
|
),
|
|
|
|
)
|
2021-02-20 16:59:31 +01:00
|
|
|
|
|
|
|
def test_it_raises_error_if_archive_max_size_equals_0(
|
2021-02-20 21:37:31 +01:00
|
|
|
self, app_with_max_file_size_equals_0: Flask, user_1_admin: User
|
2021-02-20 16:59:31 +01:00
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app_with_max_file_size_equals_0, user_1_admin.email
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
|
|
|
max_zip_file_size=0,
|
|
|
|
)
|
|
|
|
),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_400(
|
|
|
|
response, 'Max. size of zip archive must be greater than 0'
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
def test_it_raises_error_if_files_max_size_equals_0(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
|
|
|
max_single_file_size=0,
|
|
|
|
)
|
|
|
|
),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_400(
|
|
|
|
response, 'Max. size of uploaded files must be greater than 0'
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
def test_it_raises_error_if_gpx_limit_import_equals_0(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
2021-02-20 23:20:20 +01:00
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
2022-03-12 17:56:06 +01:00
|
|
|
app, user_1_admin.email
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
|
|
|
gpx_limit_import=0,
|
|
|
|
)
|
|
|
|
),
|
2021-02-20 23:20:20 +01:00
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
|
|
|
|
2022-03-13 08:36:49 +01:00
|
|
|
self.assert_400(
|
|
|
|
response, 'Max. files in a zip archive must be greater than 0'
|
2021-02-20 16:59:31 +01:00
|
|
|
)
|
2022-03-23 18:29:49 +01:00
|
|
|
|
|
|
|
def test_it_raises_error_if_admin_contact_is_invalid(
|
|
|
|
self, app: Flask, user_1_admin: User
|
|
|
|
) -> None:
|
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
|
|
|
app, user_1_admin.email
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
|
|
|
admin_contact=self.random_string(),
|
|
|
|
)
|
|
|
|
),
|
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assert_400(
|
|
|
|
response, 'valid email must be provided for admin contact'
|
|
|
|
)
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'input_description,input_email', [('input string', ''), ('None', None)]
|
|
|
|
)
|
|
|
|
def test_it_empties_error_if_admin_contact_is_an_empty(
|
|
|
|
self,
|
|
|
|
app: Flask,
|
|
|
|
user_1_admin: User,
|
|
|
|
input_description: str,
|
|
|
|
input_email: Optional[str],
|
|
|
|
) -> None:
|
|
|
|
client, auth_token = self.get_test_client_and_auth_token(
|
|
|
|
app, user_1_admin.email
|
|
|
|
)
|
|
|
|
app_config = AppConfig.query.first()
|
|
|
|
app_config.admin_contact = self.random_email()
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
data=json.dumps(
|
|
|
|
dict(
|
|
|
|
admin_contact=input_email,
|
|
|
|
)
|
|
|
|
),
|
|
|
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
|
|
|
)
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
data = json.loads(response.data.decode())
|
|
|
|
assert 'success' in data['status']
|
|
|
|
assert data['data']['admin_contact'] is None
|
2022-06-15 19:16:14 +02:00
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'client_scope, can_access',
|
|
|
|
[
|
|
|
|
('application:write', True),
|
|
|
|
('profile:read', False),
|
|
|
|
('profile:write', False),
|
|
|
|
('users:read', False),
|
|
|
|
('users:write', False),
|
|
|
|
('workouts:read', False),
|
|
|
|
('workouts:write', False),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_expected_scopes_are_defined(
|
|
|
|
self,
|
|
|
|
app: Flask,
|
|
|
|
user_1_admin: User,
|
|
|
|
client_scope: str,
|
|
|
|
can_access: bool,
|
|
|
|
) -> None:
|
|
|
|
(
|
|
|
|
client,
|
|
|
|
oauth_client,
|
|
|
|
access_token,
|
|
|
|
_,
|
|
|
|
) = self.create_oauth_client_and_issue_token(
|
|
|
|
app, user_1_admin, scope=client_scope
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.patch(
|
|
|
|
'/api/config',
|
|
|
|
content_type='application/json',
|
|
|
|
headers=dict(Authorization=f'Bearer {access_token}'),
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assert_response_scope(response, can_access)
|