import http import os import socket import time import pytest from django.core.exceptions import ObjectDoesNotExist from django.urls import reverse from pytest_django.live_server_helper import LiveServer from perms.models import Perm from users.models import UserInfo DEFAULT_USER = 'admin' DEFAULT_PASSWORD = 'nimda' TEST_LANGS = sorted(('ru', 'en')) TEST_TIMEZONES = sorted(('UTC', 'Europe/Moscow', 'Europe/Paris', 'America/New_York')) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) CUR_DIR = os.path.abspath(os.getcwd()) TIMEOUT = 10 # time before timeout exception appears POLL_TIMEOUT = 0.3 # time execute next poll cycle, for example when waiting element from django.conf import settings LOGS_F = os.path.join(getattr(settings, 'LOG_PATH', ''), getattr(settings, 'USER_LOG_FILENAME', '')) @pytest.fixture(scope='session') def test_server() -> LiveServer: """ Custom fixture for creating live test server """ addr = socket.gethostbyname(socket.gethostname()) server = LiveServer(addr) try: yield server finally: server.stop() def find_message_in_log_file(file, message): """ Function for finding certain string in log file :param file: Log file descriptor :param message: message, that needs to be found :return: Assert True if message is found Assert False if message not found """ with open(file, encoding='utf-8') as f: if message in f.read(): return True, message else: return False, message @pytest.fixture def get_url(test_server): """ Get url from liveserver :param url: Url's name :param kwargs: Dictionary with arguments for reverse function :return: string with url """ def _get_url(url, kwargs=None): return test_server.url + reverse(url, kwargs=kwargs) return _get_url @pytest.fixture def add_user_with_permissions(django_user_model): """ Add user with selected permissions :param username: User name :param password: User password :param permissions: List with Perm's permissions, that will be add to created user :param is_superuser: If True - user will be superuser :return: created user with updated permissions cache """ def _login_user(username, password, permissions=[], is_superuser=False): user = django_user_model.objects.create_user(username=username, password=password) if is_superuser: user.is_superuser = True user.save() UserInfo(user=user).save() for cur in permissions: user.user_permissions.add(Perm.get_rights(cur)) return django_user_model.objects.get(pk=user.pk) return _login_user def wait_db_element(query_method, message='', timeout=TIMEOUT, poll=POLL_TIMEOUT): end_time = time.time() + timeout screen, stacktrace = None, None while True: try: e = query_method() if e: return e except ObjectDoesNotExist as exc: message = message or str(exc) screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(poll) if time.time() > end_time: break # TODO: Maybe add here screen and stacktrace from above raise RuntimeError(message) class PermApiBaseTest: """ Test class for checking API permissions @param get_url: URL to check @param test_server: testing server instance @param api_list: Fixture with API for testing in following format: [Permission_to_check, URL of api, arguments for API (optional)] e.x. with arguments [[Perm.can_export_events], 'api_change_event_export', dict(state='disable')] e.x. without arguments [[Perm.can_export_events], 'api_change_event_export'] """ def test_api_without_perms(self, get_url, test_server, api_list, add_user_with_permissions, client): username = 'user_with_no_perms' password = 'nimda' user = add_user_with_permissions(username=username, password=password) client.force_login(user) if len(api_list) == 2: response = client.get(get_url(api_list[1])) elif len(api_list) == 3: response = client.get(get_url(api_list[1], api_list[2])) else: assert False, f'Incorrect format of api_list instance: {api_list}' assert response.status_code == http.HTTPStatus.FORBIDDEN def test_api_with_perms(self, get_url, test_server, add_user_with_permissions, api_list, client): # username 'admin_1' used instead of DEFAULT_USER because in some cases login_user failing due to the # existence of user with that username # Fixed by @lvlukianenko in recent commits username = 'user_with_perms' password = 'nimda' user = add_user_with_permissions(username=username, password=password, permissions=api_list[0]) client.force_login(user) if len(api_list) == 2: response = client.get(get_url(api_list[1])) elif len(api_list) == 3: response = client.get(get_url(api_list[1], api_list[2])) else: assert False, f'Incorrect format of api_list instance: {api_list}' assert response.status_code == http.HTTPStatus.OK # TODO: Move to integration tests # class TestDeleteElasticsearchIndexes: # index_name = 'test-index' # # @pytest.fixture(autouse=True) # def setup_tests(self): # self.es = Elasticsearch([{'host': ELK_HOST, 'port': ELK_PORT}], http_auth=(ELK_LOGIN, ELK_PASS)) # for i in range(3): # self.es.indices.create(index=f'{self.index_name}-{i}', ignore=400) # yield # self.es.indices.delete(index=f'{self.index_name}-*', ignore=[400, 404]) # # def test_delete_all_index_by_template(self): # index_template = f'{self.index_name}-*' # index_count = len(self.es.indices.get_alias(index=index_template).keys()) # assert index_count == 3 # delete_elasticsearch_indexes_by_template(index_template) # assert len(self.es.indices.get_alias(index=index_template)) == 0 # # @pytest.mark.parametrize('exclude_indexes,expected', TEST_EXCLUDE_INDEXES) # def test_delete_index_by_template_witch_exclude_index(self, exclude_indexes: set, expected: int): # index_template = f'{self.index_name}-*' # delete_elasticsearch_indexes_by_template(index_template, es=self.es, exclude_indexes=exclude_indexes) # assert len(self.es.indices.get_alias(index=index_template, ignore=[400, 404])) == expected