Merge branch 'feature/pylint' into feature/documentation

# Conflicts:
#	main/extra_func.py
This commit is contained in:
Степаненко Ольга 2021-05-06 12:44:12 +03:00
commit 9c54fcca11
7 changed files with 65 additions and 58 deletions

View File

@ -1,19 +1,19 @@
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
class EmailAuthBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = User.objects.get(email=username)
user = get_user_model().objects.get(email=username)
if user.check_password(password):
return user
return None
except User.DoesNotExist:
except get_user_model().DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return get_user_model().objects.get(pk=user_id)
except get_user_model().DoesNotExist:
return None

View File

@ -24,7 +24,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.getenv('ACTRL_SECRET_KEY', 'empty')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = bool(int(os.getenv('ACTRL_DEBUG', 1)))
DEBUG = bool(int(os.getenv('ACTRL_DEBUG', '1')))
ALLOWED_HOSTS = [
'127.0.0.1',
@ -60,8 +60,8 @@ ROOT_URLCONF = 'access_controller.urls'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.getenv('ACTRL_EMAIL_HOST', 'smtp.gmail.com')
EMAIL_PORT = int(os.getenv('ACTRL_EMAIL_PORT', 587))
EMAIL_USE_TLS = bool(int(os.getenv('ACTRL_EMAIL_TLS', 1)))
EMAIL_PORT = int(os.getenv('ACTRL_EMAIL_PORT', '587'))
EMAIL_USE_TLS = bool(int(os.getenv('ACTRL_EMAIL_TLS', '1')))
EMAIL_HOST_USER = os.getenv('ACTRL_EMAIL_HOST_USER', 'group02django@gmail.com')
EMAIL_HOST_PASSWORD = os.getenv('ACTRL_EMAIL_HOST_PASSWORD', 'djangogroup02')
DEFAULT_FROM_EMAIL = os.getenv('ACTRL_FROM_EMAIL', EMAIL_HOST_USER)
@ -154,8 +154,8 @@ AUTHENTICATION_BACKENDS = [
ZENDESK_ROLES = {
'engineer': int(os.getenv('ENG_CROLE_ID', 0)),
'light_agent': int(os.getenv('LA_CROLE_ID', 0)),
'engineer': int(os.getenv('ENG_CROLE_ID', '0')),
'light_agent': int(os.getenv('LA_CROLE_ID', '0')),
}
ZENDESK_GROUPS = {
@ -165,7 +165,7 @@ ZENDESK_GROUPS = {
SOLVED_TICKETS_EMAIL = os.getenv('ST_EMAIL')
ZENDESK_MAX_AGENTS = int(os.getenv('LICENSE_NO', 0))
ZENDESK_MAX_AGENTS = int(os.getenv('LICENSE_NO', '0'))
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
@ -175,7 +175,7 @@ REST_FRAMEWORK = {
]
}
ONE_DAY = int(os.getenv('SHIFTH', 0)) # Количество часов в 1 рабочем дне
ONE_DAY = int(os.getenv('SHIFTH', '0')) # Количество часов в 1 рабочем дне
ACTRL_ZENDESK_SUBDOMAIN = os.getenv('ACTRL_ZENDESK_SUBDOMAIN') or os.getenv('ZD_DOMAIN')
ACTRL_API_EMAIL = os.getenv('ACTRL_API_EMAIL') or os.getenv('ACCESS_CONTROLLER_API_EMAIL')

View File

@ -5,7 +5,7 @@ import logging
from datetime import timedelta, datetime, date
from typing import Optional, Union
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
@ -21,12 +21,13 @@ from main.models import UserProfile, RoleChangeLogs, UnassignedTicket, Unassigne
from main.zendesk_admin import zenpy
def update_role(user_profile: UserProfile, role: int) -> None:
def update_role(user_profile: UserProfile, role: int, who_changes: get_user_model()) -> None:
"""
Функция меняет роль пользователя.
:param user_profile: Профиль пользователя
:param role: Новая роль
:param who_changes: Пользователь, меняющий роль
:return: Пользователь с обновленной ролью
"""
zendesk = zenpy
@ -34,21 +35,21 @@ def update_role(user_profile: UserProfile, role: int) -> None:
user.custom_role_id = role
user_profile.custom_role_id = role
user_profile.save()
log(user_profile)
log(user_profile, who_changes.userprofile)
zendesk.admin.users.update(user)
def make_engineer(user_profile: UserProfile) -> None:
def make_engineer(user_profile: UserProfile, who_changes: get_user_model()) -> None:
"""
Функция устанавливает пользователю роль инженера.
:param user_profile: Профиль пользователя
:return: Вызов функции **update_role** с параметрами: профиль пользователя, роль "engineer"
"""
update_role(user_profile, ROLES['engineer'])
update_role(user_profile, ROLES['engineer'], who_changes)
def make_light_agent(user_profile: UserProfile) -> None:
def make_light_agent(user_profile: UserProfile, who_changes: get_user_model()) -> None:
"""
Функция устанавливает пользователю роль легкого агента.
@ -68,13 +69,14 @@ def make_light_agent(user_profile: UserProfile) -> None:
else:
ticket.assignee = None
ticket.group_id = zenpy.buffer_group_id
if tickets.count:
zenpy.admin.tickets.update(tickets.values)
attempts, success = 5, False
while not success and attempts != 0:
try:
update_role(user_profile, ROLES['light_agent'])
update_role(user_profile, ROLES['light_agent'], who_changes)
success = True
except APIException as e:
attempts -= 1
@ -101,7 +103,7 @@ def get_tickets_list(email) -> list:
return zenpy.admin.search(assignee=email, type='ticket')
def update_profile(user_profile: UserProfile):
def update_profile(user_profile: UserProfile) -> None:
"""
Функция обновляет профиль пользователя в соответствии с текущим в Zendesk.
@ -173,7 +175,7 @@ def update_user_in_model(profile: UserProfile, zendesk_user: ZenpyUser) -> None:
def count_users(users: list) -> tuple:
"""
Функция подсчета количества сотрудников с ролями engineer и light_agent
Функция подсчета количества сотрудников с ролями engineer и light_agent.
"""
engineers, light_agents = 0, 0
for user in users:
@ -184,14 +186,14 @@ def count_users(users: list) -> tuple:
return engineers, light_agents
def update_users_in_model() -> list:
def update_users_in_model():
"""
Обновляет пользователей в модели UserProfile по списку пользователей в организации
"""
users = get_users_list()
for user in users:
try:
profile = User.objects.get(email=user.email).userprofile
profile = get_user_model().objects.get(email=user.email).userprofile
update_user_in_model(profile, user)
except ObjectDoesNotExist:
pass
@ -290,8 +292,7 @@ class StatisticData:
stat = self._use_display(stat)
stat = self._use_interval(stat)
return stat
else:
return None
return None
def is_valid_statistic(self) -> bool:
"""
@ -333,8 +334,7 @@ class StatisticData:
"""
if self.is_valid_data():
return self.data
else:
return None
return None
def is_valid_data(self) -> bool:
"""
@ -407,9 +407,9 @@ class StatisticData:
try:
self.data = RoleChangeLogs.objects.filter(
change_time__range=[self.start_date, self.end_date + timedelta(days=1)],
user=User.objects.get(email=self.email),
user=get_user_model().objects.get(email=self.email),
).order_by('change_time')
except User.DoesNotExist:
except get_user_model().DoesNotExist:
self.errors += ['Пользователь не найден']
def _init_statistic(self) -> None:
@ -434,9 +434,11 @@ class StatisticData:
if self.data[log_index].new_role == ROLES['engineer']:
self.engineer_logic(log_index)
def engineer_logic(self, log_index: int) -> None:
def engineer_logic(self, log_index):
"""
Функция обрабатывает основную часть работы инженера
Функция обрабатывает основную часть работы инженера.
:param log_index: Индекс текущего лога
"""
current_log, next_log = self.data[log_index], self.data[log_index + 1]
if current_log.change_time.date() != next_log.change_time.date():
@ -450,7 +452,9 @@ class StatisticData:
def post_engineer_logic(self, last_log: RoleChangeLogs) -> None:
"""
Функция обрабатывает случай, когда нам изветсно что инженер работал и после диапазона
Функция обрабатывает случай, когда нам известно что инженер работал и после диапазона.
:param last_log: Последний лог
"""
self.fill_daterange(last_log.change_time.date() + timedelta(days=1), self.end_date + timedelta(days=1))
if last_log.change_time.date() == timezone.now().date():
@ -463,11 +467,13 @@ class StatisticData:
if self.end_date == timezone.now().date():
self.statistic[self.end_date] = get_timedelta(None, timezone.now().time()).total_seconds()
def prev_engineer_logic(self, first_log):
def prev_engineer_logic(self, first_log: RoleChangeLogs) -> None:
"""
Функция обрабатывает случай, когда нам изветсно что инженер начал работу до диапазона
Функция обрабатывает случай, когда нам извеcтно, что инженер начал работу до диапазона.
:param first_log: Первый лог
"""
self.fill_daterange(max(User.objects.get(email=self.email).date_joined.date(), self.start_date),
self.fill_daterange(max(get_user_model().objects.get(email=self.email).date_joined.date(), self.start_date),
first_log.change_time.date())
self.statistic[first_log.change_time.date()] += get_timedelta(first_log).total_seconds()
@ -556,12 +562,12 @@ class CsvFormatter(logging.Formatter):
return msg
def log(user, admin=None):
def log(user: get_user_model(), admin: int = 0) -> None:
"""
Осуществляет запись логов в базу данных и csv файл
:param admin:
:param user:
:return:
Функция осуществляет запись логов в базу данных и csv файл.
:param admin: Админ, который меняет роль
:param user: Пользователь, которому изменена роль
"""
users = [user, admin]
logger = logging.getLogger('MY_LOGGER')

View File

@ -4,7 +4,7 @@
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils import timezone
@ -25,7 +25,7 @@ class UserProfile(models.Model):
('has_control_access', 'Can view admin page'),
)
user = models.OneToOneField(to=User, on_delete=models.CASCADE, help_text='Пользователь')
user = models.OneToOneField(to=get_user_model(), on_delete=models.CASCADE, help_text='Пользователь')
role = models.CharField(default='None', max_length=100, help_text='Глобальное имя роли пользователя')
custom_role_id = models.IntegerField(default=0, help_text='Код роли пользователя')
image = models.URLField(null=True, blank=True, help_text='Аватарка')
@ -47,7 +47,7 @@ class UserProfile(models.Model):
return 'UNDEFINED'
@receiver(post_save, sender=User)
@receiver(post_save, sender=get_user_model())
def create_user_profile(instance, created, **kwargs) -> None:
"""
Функция создания профиля пользователя (Userprofile) при регистрации пользователя.
@ -61,7 +61,7 @@ def create_user_profile(instance, created, **kwargs) -> None:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
@receiver(post_save, sender=get_user_model())
def save_user_profile(instance, **kwargs) -> None:
"""
Функция записи БД профиля пользователя.
@ -77,12 +77,12 @@ class RoleChangeLogs(models.Model):
"""
Модель для логгирования изменений ролей пользователя
"""
user = models.ForeignKey(to=User, on_delete=models.CASCADE,
user = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE,
help_text='Пользователь, которому присвоили другую роль')
old_role = models.IntegerField(default=0, help_text='Старая роль')
new_role = models.IntegerField(default=0, help_text='Присвоенная роль')
change_time = models.DateTimeField(default=timezone.now, help_text='Дата и время изменения роли')
changed_by = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='changed_by',
changed_by = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name='changed_by',
help_text='Кем была изменена роль')
@ -110,7 +110,7 @@ class UnassignedTicket(models.Model):
Модель не распределенного тикета.
"""
assignee = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='tickets',
assignee = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name='tickets',
help_text='Пользователь, с которого снят тикет')
ticket_id = models.IntegerField(help_text='Номер тикета, для которого сняли ответственного')
status = models.IntegerField(choices=UnassignedTicketStatus.choices, default=UnassignedTicketStatus.UNASSIGNED,

View File

@ -1,7 +1,7 @@
"""
Сериализаторы.
"""
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from rest_framework import serializers
from main.models import UserProfile
from access_controller.settings import ZENDESK_ROLES
@ -17,7 +17,7 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
:type email: :class:`list`
"""
class Meta:
model = User
model = get_user_model()
fields = ['email']

View File

@ -1,6 +1,6 @@
from urllib.parse import urlparse
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.core import mail
from django.test import TestCase, Client
from django.urls import reverse
@ -71,13 +71,13 @@ class RegistrationTestCase(TestCase):
def test_registration_user_creating(self):
with self.settings(EMAIL_BACKEND=self.email_backend):
self.client.post(reverse('registration'), data={'email': self.any_zendesk_user_email})
user = User.objects.get(email=self.any_zendesk_user_email)
user = get_user_model().objects.get(email=self.any_zendesk_user_email)
zendesk_user = zenpy.get_user(self.any_zendesk_user_email)
self.assertEqual(user.userprofile.name, zendesk_user.name)
def test_permissions_applying(self):
with self.settings(EMAIL_BACKEND=self.email_backend):
self.client.post(reverse('registration'), data={'email': self.zendesk_admin_email})
user = User.objects.get(email=self.zendesk_admin_email)
user = get_user_model().objects.get(email=self.zendesk_admin_email)
self.assertEqual(user.userprofile.role, 'admin')
self.assertTrue(user.has_perm('main.has_control_access'))

View File

@ -9,7 +9,8 @@ from typing import Dict, Any, Optional
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.auth.models import User, Permission
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.views import LoginView
@ -83,7 +84,7 @@ class CustomRegistrationView(RegistrationView):
}
redirect_url = 'done'
def register(self, form: CustomRegistrationForm) -> Optional[User]:
def register(self, form: CustomRegistrationForm) -> Optional[get_user_model()]:
"""
Функция регистрации пользователя.
1. Ввод email пользователя, указанный на Zendesk
@ -108,10 +109,10 @@ class CustomRegistrationView(RegistrationView):
'html_email_template_name': None,
'extra_email_context': None,
}
user = User.objects.create_user(
user = get_user_model().objects.create_user(
username=form.data['email'],
email=form.data['email'],
password=User.objects.make_random_password(length=50)
password=get_user_model().objects.make_random_password(length=50)
)
try:
update_profile(user.userprofile)
@ -128,7 +129,7 @@ class CustomRegistrationView(RegistrationView):
return None
@staticmethod
def set_permission(user: User) -> None:
def set_permission(user: get_user_model()) -> None:
"""
Функция дает разрешение на просмотр страница администратора, если пользователь имеет роль admin.
@ -142,7 +143,7 @@ class CustomRegistrationView(RegistrationView):
)
user.user_permissions.add(permission)
def get_success_url(self, user: User = None) -> Dict:
def get_success_url(self, user: get_user_model() = None) -> Dict:
"""
Функция возвращает url-адрес страницы, куда нужно перейти после успешной/не успешной регистрации.
Используется самой django-registration.