From e19cbdb85a4a31c7efb94de8850fe0d026a8a227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BE=D0=BA=D1=83=D1=80=D0=BE=D0=B2=20=D0=98=D0=B4?= =?UTF-8?q?=D0=B0=D1=80?= Date: Tue, 11 May 2021 05:56:39 +0000 Subject: [PATCH 1/4] Add reset password tests --- main/tests.py | 176 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 145 insertions(+), 31 deletions(-) diff --git a/main/tests.py b/main/tests.py index 99d58cc..5f71955 100644 --- a/main/tests.py +++ b/main/tests.py @@ -1,8 +1,10 @@ +import random from unittest.mock import patch -from urllib.parse import urlparse from django.contrib.auth.models import User from django.core import mail +from django.http import HttpResponseRedirect +from django.template.loader import render_to_string from django.test import TestCase, Client from django.urls import reverse, reverse_lazy from django.utils import translation @@ -35,39 +37,20 @@ class RegistrationTestCase(TestCase): resp = self.client.post(reverse('registration'), data={'email': '123@test.ru'}) self.assertContains(resp, 'Этот адрес электронной почты уже используется', count=1, status_code=200) - def test_registration_email_sending(self): - # TODO: Найти способ лучше проверять сообщения - email_template = [ - '', - 'Вы получили это письмо, потому что вы (или кто-то другой) запросили восстановление пароля ' - 'от учётной записи на сайте testserver, которая связана с этим адресом электронной почты.', - '', - 'Пожалуйста, перейдите на эту страницу и введите новый пароль:', - '', - 'url', - '', - f'Ваше имя пользователя (на случай, если вы его забыли): {self.any_zendesk_user_email}', - '', - 'Спасибо, что используете наш сайт!', - '', - 'Команда сайта testserver', - '', - '', - '', - ] - with self.settings(EMAIL_BACKEND=self.email_backend) and translation.override('ru'): - self.client.post(reverse('registration'), data={'email': self.any_zendesk_user_email}) - + def test_registration_send_email(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + response: HttpResponseRedirect = \ + self.client.post(reverse('registration'), data={'email': self.any_zendesk_user_email}) + self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].to, [self.zendesk_admin_email]) - self.assertEqual(mail.outbox[0].from_email, sets.DEFAULT_FROM_EMAIL) - message = mail.outbox[0].body.split('\n') - for i in range(len(message)): - if email_template[i] != 'url': - self.assertEqual(message[i], email_template[i]) - else: - self.assertTrue(urlparse(message[i]).scheme) + # context that the email template was rendered with + email_context = response.context[0].dicts[1] + correct_subject = render_to_string('registration/password_reset_subject.txt', email_context, response.request) + self.assertEqual(mail.outbox[0].subject, correct_subject.strip()) + correct_body = render_to_string('registration/password_reset_email.html', email_context, response.request) + self.assertEqual(mail.outbox[0].body, correct_body) def test_registration_user_creating(self): with self.settings(EMAIL_BACKEND=self.email_backend): @@ -148,3 +131,134 @@ class MakeEngineerTestCase(TestCase): self.assertEqual(len(call_list), 2) for obj in mock_objects: self.assertEqual(obj[0][0].custom_role_id, sets.ZENDESK_ROLES['engineer']) + + +class PasswordResetTestCase(TestCase): + fixtures = ['fixtures/test_make_engineer.json'] + + def setUp(self): + self.user = '123@test.ru' + self.email_backend = 'django.core.mail.backends.locmem.EmailBackend' + self.client = Client() + self.client.force_login(User.objects.get(email=self.user)) + + def test_redirect(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + resp = self.client.post(reverse_lazy('password_reset'), data={'email': self.user}) + self.assertRedirects(resp, reverse('password_reset_done')) + self.assertEqual(resp.status_code, 302) + + def test_send_email(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + response: HttpResponseRedirect = \ + self.client.post(reverse_lazy('password_reset'), data={'email': self.user}) + self.assertEqual(response.status_code, 302) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].to, [self.user]) + + # context that the email template was rendered with + email_context = response.context[0].dicts[1] + correct_subject = render_to_string('registration/password_reset_subject.txt', email_context, response.request) + self.assertEqual(mail.outbox[0].subject, correct_subject.strip()) + correct_body = render_to_string('registration/password_reset_email.html', email_context, response.request) + self.assertEqual(mail.outbox[0].body, correct_body) + + def test_email_invalid(self): + with self.settings(EMAIL_BACKEND=self.email_backend) and translation.override('ru'): + resp = self.client.post(reverse_lazy('password_reset'), data={'email': 1}) + self.assertContains(resp, 'Введите правильный адрес электронной почты.', count=1, status_code=200) + + def test_user_does_not_exist(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + resp = self.client.post(reverse_lazy('password_reset'), data={'email': self.user + str(random.random())}) + self.assertRedirects(resp, reverse('password_reset_done')) + self.assertEqual(resp.status_code, 302) + self.assertEqual(len(mail.outbox), 0) + + +class PasswordChangeTestCase(TestCase): + fixtures = ['fixtures/test_make_engineer.json'] + + def setUp(self): + self.user = '123@test.ru' + self.client = Client() + self.client.force_login(User.objects.get(email=self.user)) + self.set_password() + + def set_password(self): + user: User = User.objects.get(email=self.user) + user.set_password('ImpossiblyHardPassword') + user.save() + self.client.force_login(User.objects.get(email=self.user)) + + def test_change_successful(self): + self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': 'EasyPassword', + 'new_password2': 'EasyPassword', + } + ) + user = User.objects.get(email=self.user) + self.assertTrue(user.check_password('EasyPassword')) + + def test_invalid_old_password(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'EasyPassword', + 'new_password1': 'EasyPassword', + 'new_password2': 'EasyPassword', + } + ) + self.assertContains(resp, 'Ваш старый пароль введен неправильно', count=1, status_code=200) + + def test_different_new_passwords(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': 'EasyPassword', + 'new_password2': 'EasyPassword1', + } + ) + self.assertContains(resp, 'Введенные пароли не совпадают', count=1, status_code=200) + + def test_invalid_new_password1(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': 'short', + 'new_password2': 'short', + } + ) + self.assertContains(resp, 'Введённый пароль слишком короткий', count=1, status_code=200) + + def test_invalid_new_password2(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': '123123123123123123132123123', + 'new_password2': '123123123123123123132123123', + } + ) + self.assertContains(resp, 'Введённый пароль состоит только из цифр', count=1, status_code=200) + + def test_invalid_new_password3(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': self.user, + 'new_password2': self.user, + } + ) + self.assertContains(resp, 'Введённый пароль слишком похож на имя пользователя', count=1, status_code=200) From 76cd782ff44616bcdcb2a42e0456588a08f42a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BE=D0=BA=D1=83=D1=80=D0=BE=D0=B2=20=D0=98=D0=B4?= =?UTF-8?q?=D0=B0=D1=80?= Date: Thu, 13 May 2021 04:49:02 +0000 Subject: [PATCH 2/4] Add get tickets tests --- main/extra_func.py | 2 +- main/forms.py | 20 ++++++++ main/templates/pages/work.html | 9 ++-- main/tests.py | 94 +++++++++++++++++++++++++++++++++- main/views.py | 43 ++++++++-------- main/zendesk_admin.py | 15 +++++- 6 files changed, 151 insertions(+), 32 deletions(-) diff --git a/main/extra_func.py b/main/extra_func.py index e6a2a97..90ec414 100644 --- a/main/extra_func.py +++ b/main/extra_func.py @@ -6,8 +6,8 @@ from django.core.exceptions import ObjectDoesNotExist from django.shortcuts import redirect from django.utils import timezone from zenpy import Zenpy -from zenpy.lib.exception import APIException from zenpy.lib.api_objects import User as ZenpyUser, Ticket as ZenpyTicket +from zenpy.lib.exception import APIException from zenpy.lib.generator import SearchResultGenerator from access_controller.settings import ZENDESK_ROLES as ROLES, ACTRL_ZENDESK_SUBDOMAIN diff --git a/main/forms.py b/main/forms.py index 81b2e8a..8ca6f13 100644 --- a/main/forms.py +++ b/main/forms.py @@ -140,3 +140,23 @@ class StatisticForm(forms.Form): } ), ) + + +class WorkGetTicketsForm(forms.Form): + """ + Форма получения количества тикетов для страницы work и work_get_tickets. + + :param count_tickets: Поле для ввода количества тикетов + :type count_tickets: :class:`django.forms.fields.IntegerField` + """ + count_tickets = forms.IntegerField( + min_value=0, + max_value=100, + required=True, + widget=forms.NumberInput( + attrs={ + 'class': 'form-control mb-3', + 'value': 1 + } + ), + ) diff --git a/main/templates/pages/work.html b/main/templates/pages/work.html index cb07b6d..bd46341 100644 --- a/main/templates/pages/work.html +++ b/main/templates/pages/work.html @@ -66,10 +66,11 @@ Сдать права инженера
-
- - -
+
+ {% csrf_token %} + {{ get_tickets_form.count_tickets }} + +
{% for message in messages %} diff --git a/main/tests.py b/main/tests.py index 5f71955..59df965 100644 --- a/main/tests.py +++ b/main/tests.py @@ -1,5 +1,5 @@ import random -from unittest.mock import patch +from unittest.mock import patch, Mock from django.contrib.auth.models import User from django.core import mail @@ -43,7 +43,7 @@ class RegistrationTestCase(TestCase): self.client.post(reverse('registration'), data={'email': self.any_zendesk_user_email}) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].to, [self.zendesk_admin_email]) + self.assertEqual(mail.outbox[0].to, [self.any_zendesk_user_email]) # context that the email template was rendered with email_context = response.context[0].dicts[1] @@ -262,3 +262,93 @@ class PasswordChangeTestCase(TestCase): } ) self.assertContains(resp, 'Введённый пароль слишком похож на имя пользователя', count=1, status_code=200) + + +class GetTicketsTestCase(TestCase): + """ + Класс тестов для проверки функции получения тикетов. + """ + fixtures = ['fixtures/test_make_engineer.json'] + + def setUp(self): + """ + Предустановленные значения для проведения тестов. + """ + self.light_agent = '123@test.ru' + self.engineer = 'customer@example.com' + self.client = Client() + self.client.force_login(User.objects.get(email=self.engineer)) + self.light_agent_client = Client() + self.light_agent_client.force_login(User.objects.get(email=self.light_agent)) + + @patch('main.views.zenpy.get_user') + @patch('main.extra_func.zenpy') + def test_redirect(self, ZenpyMock, GetUserMock): + """ + Функция проверки переадресации пользователя на рабочую страницу. + """ + GetUserMock.return_value = Mock() + user = User.objects.get(email=self.engineer) + resp = self.client.post(reverse('work_get_tickets')) + self.assertRedirects(resp, reverse('work', args=[user.id])) + self.assertEqual(resp.status_code, 302) + + @patch('main.views.zenpy') + @patch('main.views.get_tickets_list_for_group') + def test_take_one_ticket(self, TicketsMock, ZenpyViewsMock): + """ + Функция проверки назначения одного тикета на engineer. + """ + TicketsMock.return_value = [Mock()] + ZenpyViewsMock.get_user.return_value = Mock(role='agent', custom_role_id=sets.ZENDESK_ROLES['engineer']) + self.client.post(reverse('work_get_tickets'), data={'count_tickets': 1}) + tickets = ZenpyViewsMock.update_tickets.call_args + self.assertEqual(tickets[0][0][0].assignee, ZenpyViewsMock.get_user.return_value) + + @patch('main.views.get_tickets_list_for_group') + @patch('main.views.zenpy') + def test_take_many_tickets(self, ZenpyMock, TicketsMock): + """ + Функция проверки назначения нескольких тикетов на engineer. + """ + TicketsMock.return_value = [Mock()] * 3 + ZenpyMock.get_user.return_value = Mock(role='agent', custom_role_id=sets.ZENDESK_ROLES['engineer']) + self.client.post(reverse('work_get_tickets'), data={'count_tickets': 3}) + tickets = ZenpyMock.update_tickets.call_args + for ticket in tickets[0][0]: + self.assertEqual(ticket.assignee, ZenpyMock.get_user.return_value) + + @patch('main.views.zenpy.get_user') + @patch('main.views.zenpy') + def test_light_agent_take_ticket(self, ZenpyMock, GetUserMock): + """ + Функция проверки попытки назначения тикета на light_agent. + """ + GetUserMock.return_value = Mock(role='agent', custom_role_id=sets.ZENDESK_ROLES['light_agent']) + self.light_agent_client.post(reverse('work_get_tickets'), data={'count_tickets': 3}) + tickets = ZenpyMock.update_tickets.call_args + self.assertIsNone(tickets) + + @patch('main.views.zenpy') + @patch('main.views.get_tickets_list_for_group') + def test_take_zero_tickets(self, TicketsMock, ZenpyMock): + """ + Функция проверки попытки назначения нуля тикета на engineer. + """ + TicketsMock.return_value = [Mock()] * 3 + ZenpyMock.get_user.return_value = Mock(role='agent', custom_role_id=sets.ZENDESK_ROLES['engineer']) + self.client.post(reverse('work_get_tickets'), data={'count_tickets': 0}) + tickets = ZenpyMock.update_tickets.call_args[0][0] + self.assertListEqual(tickets, []) + + @patch('main.views.get_tickets_list_for_group') + @patch('main.views.zenpy') + def test_take_invalid_count_tickets(self, ZenpyMock, TicketsMock, ): + """ + Функция проверки попытки назначения нуля тикетов на engineer. + """ + TicketsMock.return_value = [Mock()] * 3 + ZenpyMock.get_user.return_value = Mock(role='agent', custom_role_id=sets.ZENDESK_ROLES['engineer']) + self.client.post(reverse('work_get_tickets'), data={'count_tickets': 'asd'}) + tickets = ZenpyMock.update_tickets.call_args + self.assertIsNone(tickets) diff --git a/main/views.py b/main/views.py index 22978c2..4602bcf 100644 --- a/main/views.py +++ b/main/views.py @@ -1,19 +1,18 @@ from smtplib import SMTPException -from typing import Dict, Any from django.contrib import messages from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.contrib.auth.models import User, Permission from django.contrib.auth.tokens import default_token_generator -from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.views import LoginView from django.contrib.contenttypes.models import ContentType from django.contrib.messages.views import SuccessMessageMixin from django.core.handlers.wsgi import WSGIRequest from django.http import HttpResponseRedirect, HttpResponse from django.shortcuts import render, redirect -from django.urls import reverse_lazy, reverse +from django.urls import reverse_lazy from django.views.generic import FormView from django_registration.views import RegistrationView # Django REST @@ -23,13 +22,13 @@ from rest_framework.response import Response from access_controller.settings import DEFAULT_FROM_EMAIL, ZENDESK_ROLES, ZENDESK_MAX_AGENTS, ZENDESK_GROUPS from main.extra_func import check_user_exist, update_profile, get_user_organization, \ make_engineer, make_light_agent, get_users_list, update_users_in_model, count_users, \ - log, set_session_params_for_work_page, get_tickets_list_for_group -from .statistic_data import StatisticData -from main.zendesk_admin import zenpy -from main.requester import TicketListRequester -from main.forms import AdminPageUsers, CustomRegistrationForm, CustomAuthenticationForm, StatisticForm + set_session_params_for_work_page, get_tickets_list_for_group +from main.forms import AdminPageUsers, CustomRegistrationForm, CustomAuthenticationForm, StatisticForm, \ + WorkGetTicketsForm from main.serializers import ProfileSerializer, ZendeskUserSerializer +from main.zendesk_admin import zenpy from .models import UserProfile +from .statistic_data import StatisticData class CustomRegistrationView(RegistrationView): @@ -178,6 +177,7 @@ def work_page(request: WSGIRequest, id: int) -> HttpResponse: 'messages': messages.get_messages(request), 'licences_remaining': max(0, ZENDESK_MAX_AGENTS - len(engineers)), 'pagename': 'Управление правами', + 'get_tickets_form': WorkGetTicketsForm() } return render(request, 'pages/work.html', context) return redirect("login") @@ -211,21 +211,18 @@ def work_become_engineer(request: WSGIRequest) -> HttpResponseRedirect: @login_required() def work_get_tickets(request): zenpy_user = zenpy.get_user(request.user.email) - if zenpy_user.role == 'admin' or zenpy_user.custom_role_id == ZENDESK_ROLES['engineer']: - tickets = get_tickets_list_for_group(ZENDESK_GROUPS['buffer']) - assigned_tickets = [] - count = 0 - for i in range(len(tickets)): - if i == int(request.GET.get('count_tickets')): - if assigned_tickets: - zenpy.admin.tickets.update(assigned_tickets) - return set_session_params_for_work_page(request, count) - tickets[i].assignee = zenpy_user - assigned_tickets.append(tickets[i]) - count += 1 - if assigned_tickets: - zenpy.admin.tickets.update(assigned_tickets) - return set_session_params_for_work_page(request, count) + + if request.method == 'POST': + if zenpy_user.role == 'admin' or zenpy_user.custom_role_id == ZENDESK_ROLES['engineer']: + form = WorkGetTicketsForm(request.POST) + if form.is_valid(): + tickets = get_tickets_list_for_group(ZENDESK_GROUPS['buffer']) + assigned_tickets = [] + for i in range(min(form.cleaned_data['count_tickets'], len(tickets))): + tickets[i].assignee = zenpy_user + assigned_tickets.append(tickets[i]) + zenpy.update_tickets(assigned_tickets) + return set_session_params_for_work_page(request, len(assigned_tickets)) return set_session_params_for_work_page(request, is_confirm=False) diff --git a/main/zendesk_admin.py b/main/zendesk_admin.py index 2a689ce..627d900 100644 --- a/main/zendesk_admin.py +++ b/main/zendesk_admin.py @@ -1,7 +1,9 @@ -from typing import Optional, Dict +from typing import Optional, Dict, List + from zenpy import Zenpy -from zenpy.lib.api_objects import User as ZenpyUser, Group as ZenpyGroup +from zenpy.lib.api_objects import User as ZenpyUser, Group as ZenpyGroup, Ticket as ZenpyTicket from zenpy.lib.exception import APIException + from access_controller.settings import ACTRL_ZENDESK_SUBDOMAIN, ACTRL_API_EMAIL, ACTRL_API_TOKEN, ACTRL_API_PASSWORD, \ ZENDESK_GROUPS, SOLVED_TICKETS_EMAIL @@ -28,6 +30,15 @@ class ZendeskAdmin: """ self.admin.users.update(user) + def update_tickets(self, tickets: List[ZenpyTicket]): + """ + Функция сохраняет изменение тикетов в Zendesk. + + :param tickets: Тикеты с изменёнными данными + """ + if tickets: + self.admin.tickets.update(tickets) + def check_user(self, email: str) -> bool: """ Функция осуществляет проверку существования пользователя в Zendesk по email. From 74f8b1ce1fbad9c334e2a276b2d69b816869dcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BE=D0=BA=D1=83=D1=80=D0=BE=D0=B2=20=D0=98=D0=B4?= =?UTF-8?q?=D0=B0=D1=80?= Date: Thu, 13 May 2021 04:57:51 +0000 Subject: [PATCH 3/4] Add profile tests --- fixtures/profile.json | 59 ++++++++++++++++++++++++++++++++++++++++++ main/tests.py | 60 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 fixtures/profile.json diff --git a/fixtures/profile.json b/fixtures/profile.json new file mode 100644 index 0000000..8ce02db --- /dev/null +++ b/fixtures/profile.json @@ -0,0 +1,59 @@ +[ + { + "model": "auth.user", + "pk": 1, + "fields": { + "password": "pbkdf2_sha256$216000$gHBBCr1jBELf$ZkEDW3IEd8Wij7u8vkv+0Eze32CS01bcaYWhcD9OIC4=", + "last_login": null, + "is_superuser": true, + "username": "idar.sokurov.05@mail.ru", + "first_name": "", + "last_name": "", + "email": "idar.sokurov.05@mail.ru", + "is_staff": true, + "is_active": true, + "date_joined": "2021-03-10T16:38:56.303Z", + "groups": [], + "user_permissions": [ + 33 + ] + } + }, + { + "model": "main.userprofile", + "pk": 1, + "fields": { + "name": "ZendeskAdmin", + "user": 1, + "role": "admin" + } + }, + { + "model": "auth.user", + "pk": 2, + "fields": { + "password": "pbkdf2_sha256$216000$5qLJgrm2Quq9$KDBNNymVZXkUx0HKBPFst2m83kLe0egPBnkW7KnkORU=", + "last_login": null, + "is_superuser": false, + "username": "krav-88@mail.ru", + "first_name": "", + "last_name": "", + "email": "krav-88@mail.ru", + "is_staff": false, + "is_active": true, + "date_joined": "2021-03-10T16:38:56.303Z", + "groups": [], + "user_permissions": [] + } + }, + { + "model": "main.userprofile", + "pk": 2, + "fields": { + "name": "UserForAccessTest", + "user": 2, + "role": "agent", + "custom_role_id": "360005209000" + } + } +] diff --git a/main/tests.py b/main/tests.py index 59df965..b086488 100644 --- a/main/tests.py +++ b/main/tests.py @@ -352,3 +352,63 @@ class GetTicketsTestCase(TestCase): self.client.post(reverse('work_get_tickets'), data={'count_tickets': 'asd'}) tickets = ZenpyMock.update_tickets.call_args self.assertIsNone(tickets) + + +class ProfileTestCase(TestCase): + """ + Класс тестов для проверки синхронизации профиля пользователя. + """ + fixtures = ['fixtures/profile.json'] + + def setUp(self): + """ + Предустановленные значения для проведения тестов. + """ + self.zendesk_agent_email = 'krav-88@mail.ru' + self.zendesk_admin_email = 'idar.sokurov.05@mail.ru' + self.client = Client() + self.client.force_login(User.objects.get(email=self.zendesk_agent_email)) + self.admin_client = Client() + self.admin_client.force_login(User.objects.get(email=self.zendesk_admin_email)) + + def test_correct_username(self): + """ + Функция проверки синхронизации имени пользователя. + """ + resp = self.client.get(reverse('profile')) + self.assertEqual(resp.context['profile'].name, zenpy.get_user(self.zendesk_agent_email).name) + + def test_correct_email(self): + """ + Функция проверки синхронизации почты пользователя. + """ + resp = self.client.get(reverse('profile')) + self.assertEqual(resp.context['profile'].user.email, zenpy.get_user(self.zendesk_agent_email).email) + + def test_correct_role(self): + """ + Функция проверки синхронизации роли пользователя. + """ + resp = self.client.get(reverse('profile')) + self.assertEqual(resp.context['profile'].role, zenpy.get_user(self.zendesk_agent_email).role) + resp = self.admin_client.get(reverse('profile')) + self.assertEqual(resp.context['profile'].role, zenpy.get_user(self.zendesk_admin_email).role) + + def test_correct_custom_role_id(self): + """ + Функция проверки синхронизации рабочей роли пользователя. + """ + resp = self.client.get(reverse('profile')) + user = zenpy.get_user(self.zendesk_agent_email) + self.assertEqual(resp.context['profile'].custom_role_id, user.custom_role_id if user.custom_role_id else 0) + resp = self.admin_client.get(reverse('profile')) + user = zenpy.get_user(self.zendesk_admin_email) + self.assertEqual(resp.context['profile'].custom_role_id, user.custom_role_id if user.custom_role_id else 0) + + def test_correct_image(self): + """ + Функция проверки синхронизации изображения пользователя. + """ + resp = self.client.get(reverse('profile')) + user = zenpy.get_user(self.zendesk_agent_email) + self.assertEqual(resp.context['profile'].image, user.photo['content_url'] if user.photo else None) From 86995e01b3a32d97adcc1860f2e62b5e46f25ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B0=D1=82=D0=B8=D1=89=D0=B5=D0=B2=20=D0=AE=D1=80?= =?UTF-8?q?=D0=B8=D0=B9?= Date: Thu, 13 May 2021 17:04:56 +0000 Subject: [PATCH 4/4] Add `python-dotenv` --- README.md | 8 ++++---- access_controller/settings.py | 4 ++++ requirements/common.txt | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eb66f37..8489e7d 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,9 @@ cp .env.example .env sudo apt install make pip install --upgrade pip pip install -r requirements/dev.txt -(set -a && source .env && ./manage.py migrate) -(set -a && source .env && ./manage.py loaddata data.json) -(set -a && source .env && ./manage.py runserver) +./manage.py migrate +./manage.py loaddata data.json +./manage.py runserver ``` ## Перед запуском для тестирования: @@ -65,7 +65,7 @@ pip install -r requirements/dev.txt - Перейти в папку приложения - Активировать виртуальное окружение - Выполнить команду `pip install -r requirements/dev.txt` -- В виртуальное окружение добавить следующие переменные: +- В файл `.env` добавить следующие переменные: ``` diff --git a/access_controller/settings.py b/access_controller/settings.py index a74ad7f..7361a60 100644 --- a/access_controller/settings.py +++ b/access_controller/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/ """ import os from pathlib import Path +from dotenv import load_dotenv # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -18,6 +19,9 @@ BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ +# Load environment variables from .env +load_dotenv() + # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.getenv('ACTRL_SECRET_KEY', 'empty') diff --git a/requirements/common.txt b/requirements/common.txt index 6b3e7fa..0bbb21b 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -14,3 +14,6 @@ sphinx-rtd-theme==0.5.1 sphinx-autodoc-typehints==1.11.1 pyenchant==3.2.0 sphinxcontrib-spelling==7.1.0 + +# Misc +python-dotenv==0.17.1