From 2a1331e00c6131597454504671a6910c4044a378 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Fri, 2 Nov 2018 17:26:20 +0300 Subject: [PATCH] refactoring --- abonapp/views.py | 321 +++++++++++------- .../custom_dev_page/generic_switch.html | 14 +- devapp/urls.py | 50 ++- devapp/views.py | 245 +++++++------ djing/lib/mixins.py | 12 +- 5 files changed, 401 insertions(+), 241 deletions(-) diff --git a/abonapp/views.py b/abonapp/views.py index f9ee1c1..8b4975d 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -1,48 +1,48 @@ -from typing import Dict, Optional from datetime import datetime, date +from typing import Dict, Optional + +from agent.commands.dhcp import dhcp_commit, dhcp_expiry, dhcp_release +from devapp.models import Device, Port as DevPort +from dialing_app.models import AsteriskCDR +from django.conf import settings +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import LoginRequiredMixin, \ + PermissionRequiredMixin as PermissionRequiredMixin_django from django.core.exceptions import PermissionDenied, ValidationError -from django.db import IntegrityError, ProgrammingError, transaction, OperationalError, DatabaseError +from django.db import IntegrityError, ProgrammingError, transaction, \ + OperationalError, DatabaseError from django.db.models import Count, Q +from django.http import HttpResponse, HttpResponseBadRequest, \ + HttpResponseRedirect from django.shortcuts import render, redirect, get_object_or_404, resolve_url -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin as PermissionRequiredMixin_django -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect -from django.contrib import messages from django.urls import reverse_lazy from django.utils import timezone -from django.utils.translation import gettext_lazy as _ from django.utils.decorators import method_decorator +from django.utils.translation import gettext_lazy as _ from django.views.generic import ListView, UpdateView, CreateView, DeleteView -from django.conf import settings - -from agent.commands.dhcp import dhcp_commit, dhcp_expiry, dhcp_release +from djing import lib +from djing import ping +from djing.global_base_views import OrderedFilteredList, SecureApiView +from djing.lib.decorators import json_view, only_admins +from djing.lib.mixins import OnlyAdminsMixin, LoginAdminPermissionMixin +from group_app.models import Group +from guardian.decorators import \ + permission_required_or_403 as permission_required +from guardian.shortcuts import get_objects_for_user, assign_perm from gw_app.models import NASModel -from tariff_app.models import Tariff from gw_app.nas_managers import NasFailedResult, NasNetworkError -from . import forms -from . import models -from devapp.models import Device, Port as DevPort -from taskapp.models import Task -from dialing_app.models import AsteriskCDR -from statistics.models import getModel -from group_app.models import Group from ip_pool.models import NetworkModel -from guardian.shortcuts import get_objects_for_user, assign_perm -from guardian.decorators import permission_required_or_403 as permission_required -from guardian.mixins import PermissionRequiredMixin -from djing import ping -from djing import lib -from djing.lib.decorators import json_view, only_admins -from djing.lib.mixins import OnlyAdminsMixin -from djing.global_base_views import OrderedFilteredList, SecureApiView +from statistics.models import getModel +from tariff_app.models import Tariff +from taskapp.models import Task from xmlview.decorators import xml_view +from . import forms +from . import models -class AbonappPermissionMixin(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixin): - return_403 = True - - -class PeoplesListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList): +class PeoplesListView(LoginRequiredMixin, OnlyAdminsMixin, + OrderedFilteredList): template_name = 'abonapp/peoples.html' def get_queryset(self): @@ -74,7 +74,8 @@ class PeoplesListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList): context = super(PeoplesListView, self).get_context_data(**kwargs) - context['streets'] = models.AbonStreet.objects.filter(group=gid).only('name') + context['streets'] = models.AbonStreet.objects.filter(group=gid).only( + 'name') context['street_id'] = lib.safe_int(self.request.GET.get('street')) context['group'] = group return context @@ -87,12 +88,14 @@ class GroupListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList): def get_queryset(self): queryset = super(GroupListView, self).get_queryset() - queryset = get_objects_for_user(self.request.user, 'group_app.view_group', klass=queryset, + queryset = get_objects_for_user(self.request.user, + 'group_app.view_group', klass=queryset, accept_global_perms=False) return queryset -class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixin_django, CreateView): +class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, + PermissionRequiredMixin_django, CreateView): permission_required = 'abonapp.add_abon' group = None abon = None @@ -135,7 +138,12 @@ class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixi messages.success(self.request, _('create abon success msg')) self.abon = abon return super(AbonCreateView, self).form_valid(form) - except (IntegrityError, NasFailedResult, NasNetworkError, lib.LogicError) as e: + except ( + IntegrityError, + NasFailedResult, + NasNetworkError, + lib.LogicError + ) as e: messages.error(self.request, e) except lib.MultipleException as errs: for err in errs.err_list: @@ -147,7 +155,7 @@ class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixi return super(AbonCreateView, self).form_invalid(form) -class DelAbonDeleteView(AbonappPermissionMixin, DeleteView): +class DelAbonDeleteView(LoginAdminPermissionMixin, DeleteView): permission_required = 'abonapp.delete_abon' model = models.Abon slug_url_kwarg = 'uname' @@ -166,13 +174,14 @@ class DelAbonDeleteView(AbonappPermissionMixin, DeleteView): abon = self.get_object() gid = abon.group.id abon.delete() - request.user.log(request.META, 'dusr', ('%(uname)s, "%(fio)s", %(group)s %(street)s %(house)s' % { - 'uname': abon.username, - 'fio': abon.fio or '-', - 'group': abon.group.title if abon.group else '', - 'street': abon.street.name if abon.street else '', - 'house': abon.house or '' - }).strip()) + request.user.log(request.META, 'dusr', ( + '%(uname)s, "%(fio)s", %(group)s %(street)s %(house)s' % { + 'uname': abon.username, + 'fio': abon.fio or '-', + 'group': abon.group.title if abon.group else '', + 'street': abon.street.name if abon.street else '', + 'house': abon.house or '' + }).strip()) messages.success(request, _('delete abon success msg')) return redirect('abonapp:people_list', gid=gid) except NasNetworkError as e: @@ -202,7 +211,8 @@ def abonamount(request, gid: int, uname): comment = _('fill account through admin side') abon.add_ballance(request.user, amnt, comment=comment) abon.save(update_fields=('ballance',)) - messages.success(request, _('Account filled successfully on %.2f') % amnt) + messages.success( + request, _('Account filled successfully on %.2f') % amnt) return redirect('abonapp:abon_phistory', gid=gid, uname=uname) else: messages.error(request, _('I not know the account id')) @@ -220,7 +230,7 @@ def abonamount(request, gid: int, uname): }) -class DebtsListView(AbonappPermissionMixin, OrderedFilteredList): +class DebtsListView(LoginAdminPermissionMixin, OrderedFilteredList): permission_required = 'group_app.view_group' context_object_name = 'invoices' template_name = 'abonapp/invoiceForPayment.html' @@ -229,7 +239,8 @@ class DebtsListView(AbonappPermissionMixin, OrderedFilteredList): return self.abon.group def get_queryset(self): - abon = get_object_or_404(models.Abon, username=self.kwargs.get('uname')) + abon = get_object_or_404(models.Abon, + username=self.kwargs.get('uname')) self.abon = abon return models.InvoiceForPayment.objects.filter(abon=abon) @@ -240,7 +251,7 @@ class DebtsListView(AbonappPermissionMixin, OrderedFilteredList): return context -class PayHistoryListView(AbonappPermissionMixin, OrderedFilteredList): +class PayHistoryListView(LoginAdminPermissionMixin, OrderedFilteredList): permission_required = 'group_app.view_group' context_object_name = 'pay_history' template_name = 'abonapp/payHistory.html' @@ -251,9 +262,11 @@ class PayHistoryListView(AbonappPermissionMixin, OrderedFilteredList): return models.Group.objects.filter(pk=self.kwargs.get('gid')).first() def get_queryset(self): - abon = get_object_or_404(models.Abon, username=self.kwargs.get('uname')) + abon = get_object_or_404(models.Abon, + username=self.kwargs.get('uname')) self.abon = abon - pay_history = models.AbonLog.objects.filter(abon=abon).order_by('-date') + pay_history = models.AbonLog.objects.filter(abon=abon).order_by( + '-date') return pay_history def get_context_data(self, **kwargs): @@ -272,11 +285,13 @@ def abon_services(request, gid: int, uname): abon = get_object_or_404(models.Abon, username=uname) if abon.group != grp: - messages.warning(request, _("User group id is not matches with group in url")) + messages.warning(request, + _("User group id is not matches with group in url")) return redirect('abonapp:abon_services', abon.group.id, abon.username) try: - periodic_pay = models.PeriodicPayForId.objects.filter(account=abon).first() + periodic_pay = models.PeriodicPayForId.objects.filter( + account=abon).first() except models.PeriodicPayForId.DoesNotExist: periodic_pay = None @@ -289,7 +304,7 @@ def abon_services(request, gid: int, uname): }) -class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView): +class AbonHomeUpdateView(LoginAdminPermissionMixin, UpdateView): permission_required = 'abonapp.view_abon' model = models.Abon form_class = forms.AbonForm @@ -301,7 +316,8 @@ class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView): def dispatch(self, request, *args, **kwargs): try: - return super(AbonHomeUpdateView, self).dispatch(request, *args, **kwargs) + return super(AbonHomeUpdateView, self).dispatch(request, *args, + **kwargs) except lib.LogicError as e: messages.error(request, e) except (NasFailedResult, NasNetworkError) as e: @@ -348,7 +364,8 @@ class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView): 'password': passw } except models.AbonRawPassword.DoesNotExist: - messages.warning(self.request, _('User has not have password, and cannot login')) + messages.warning(self.request, + _('User has not have password, and cannot login')) return {'password': ''} def get_context_data(self, **kwargs): @@ -357,7 +374,8 @@ class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView): context = { 'group': self.group, 'device': device, - 'dev_ports': DevPort.objects.filter(device=device) if device else None + 'dev_ports': DevPort.objects.filter( + device=device) if device else None } context.update(kwargs) return super(AbonHomeUpdateView, self).get_context_data(**context) @@ -421,20 +439,23 @@ def pick_tariff(request, gid: int, uname): if request.method == 'POST': trf = Tariff.objects.get(pk=request.POST.get('tariff')) deadline = request.POST.get('deadline') - log_comment = _("Service '%(service_name)s' has connected via admin") % { - 'service_name': trf.title - } + log_comment = _( + "Service '%(service_name)s' has connected via admin") % { + 'service_name': trf.title + } if deadline == '' or deadline is None: abon.pick_tariff(trf, request.user, comment=log_comment) else: deadline = datetime.strptime(deadline, '%Y-%m-%d %H:%M:%S') - abon.pick_tariff(trf, request.user, deadline=deadline, comment=log_comment) + abon.pick_tariff(trf, request.user, deadline=deadline, + comment=log_comment) r = abon.nas_sync_self() if r is None: messages.success(request, _('Tariff has been picked')) else: messages.error(request, r) - return redirect('abonapp:abon_services', gid=gid, uname=abon.username) + return redirect('abonapp:abon_services', gid=gid, + uname=abon.username) except (lib.LogicError, NasFailedResult) as e: messages.error(request, e) except NasNetworkError as e: @@ -461,7 +482,8 @@ def pick_tariff(request, gid: int, uname): @permission_required('abonapp.can_complete_service') def unsubscribe_service(request, gid: int, uname, abon_tariff_id: int): try: - abon_tariff = get_object_or_404(models.AbonTariff, pk=int(abon_tariff_id)) + abon_tariff = get_object_or_404(models.AbonTariff, + pk=int(abon_tariff_id)) abon_tariff.delete() messages.success(request, _('User has been detached from service')) except NasFailedResult as e: @@ -474,7 +496,7 @@ def unsubscribe_service(request, gid: int, uname, abon_tariff_id: int): return redirect('abonapp:abon_services', gid=gid, uname=uname) -class LogListView(AbonappPermissionMixin, ListView): +class LogListView(LoginAdminPermissionMixin, ListView): permission_required = 'abonapp.view_abonlog' paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) http_method_names = ('get',) @@ -483,7 +505,7 @@ class LogListView(AbonappPermissionMixin, ListView): model = models.AbonLog -class DebtorsListView(AbonappPermissionMixin, ListView): +class DebtorsListView(LoginAdminPermissionMixin, ListView): permission_required = 'abonapp.view_invoiceforpayment' paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) http_method_names = ('get',) @@ -492,7 +514,7 @@ class DebtorsListView(AbonappPermissionMixin, ListView): queryset = models.InvoiceForPayment.objects.filter(status=True) -class TaskLogListView(AbonappPermissionMixin, ListView): +class TaskLogListView(LoginAdminPermissionMixin, ListView): permission_required = 'group_app.view_group' paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) http_method_names = ('get',) @@ -506,7 +528,8 @@ class TaskLogListView(AbonappPermissionMixin, ListView): return get_object_or_404(models.Group, pk=self.kwargs.get('gid')) def get_queryset(self): - abon = get_object_or_404(models.Abon, username=self.kwargs.get('uname')) + abon = get_object_or_404(models.Abon, + username=self.kwargs.get('uname')) self.abon = abon return Task.objects.filter(abon=abon) @@ -517,14 +540,15 @@ class TaskLogListView(AbonappPermissionMixin, ListView): return context -class PassportUpdateView(AbonappPermissionMixin, UpdateView): +class PassportUpdateView(LoginAdminPermissionMixin, UpdateView): permission_required = 'abonapp.view_passportinfo' form_class = forms.PassportForm model = models.PassportInfo template_name = 'abonapp/modal_passport_view.html' def get_object(self, queryset=None): - self.abon = get_object_or_404(models.Abon, username=self.kwargs.get('uname')) + self.abon = get_object_or_404(models.Abon, + username=self.kwargs.get('uname')) try: passport_instance = models.PassportInfo.objects.get(abon=self.abon) except models.PassportInfo.DoesNotExist: @@ -535,7 +559,8 @@ class PassportUpdateView(AbonappPermissionMixin, UpdateView): pi = form.save(commit=False) pi.abon = self.abon pi.save() - messages.success(self.request, _('Passport information has been saved')) + messages.success(self.request, + _('Passport information has been saved')) return super(PassportUpdateView, self).form_valid(form) def get_success_url(self): @@ -556,7 +581,7 @@ class PassportUpdateView(AbonappPermissionMixin, UpdateView): return super(PassportUpdateView, self).get_context_data(**context) -class IpUpdateView(AbonappPermissionMixin, UpdateView): +class IpUpdateView(LoginAdminPermissionMixin, UpdateView): permission_required = 'abonapp.change_abon' form_class = forms.AddIpForm model = models.Abon @@ -600,7 +625,8 @@ def chgroup_tariff(request, gid): messages.success(request, _('Successfully saved')) return redirect('abonapp:ch_group_tariff', gid) tariffs = Tariff.objects.all() - seleted_tariffs_id = tuple(pk[0] for pk in grp.tariff_set.only('pk').values_list('pk')) + seleted_tariffs_id = tuple( + pk[0] for pk in grp.tariff_set.only('pk').values_list('pk')) return render(request, 'abonapp/group_tariffs.html', { 'group': grp, 'seleted_tariffs': seleted_tariffs_id, @@ -623,7 +649,8 @@ def dev(request, gid: int, uname): else: abon_dev = abon.device except Device.DoesNotExist: - messages.warning(request, _('Device your selected already does not exist')) + messages.warning(request, + _('Device your selected already does not exist')) except models.Abon.DoesNotExist: messages.error(request, _('Abon does not exist')) return redirect('abonapp:people_list', gid=gid) @@ -697,7 +724,8 @@ def charts(request, gid: int, uname): return render(request, 'abonapp/charts.html', { 'group': abon.group, 'abon': abon, - 'charts_data': ',\n'.join(charts_data) if charts_data is not None else None, + 'charts_data': ',\n'.join( + charts_data) if charts_data is not None else None, 'high': high, 'wantdate': wandate }) @@ -710,7 +738,8 @@ def charts(request, gid: int, uname): def abon_ping(request, gid: int, uname): ip = request.GET.get('cmd_param') status = False - text = ' %s' % _('no ping') + text = ' %s' % _( + 'no ping') abon = get_object_or_404(models.Abon, username=uname) try: if ip is None: @@ -719,17 +748,21 @@ def abon_ping(request, gid: int, uname): if abon.nas is None: return { 'status': 1, - 'dat': ' %s' % _('gateway required') + 'dat': '' + ' %s' % _('gateway required') } mngr = abon.nas.get_nas_manager() ping_result = mngr.ping(ip) if ping_result is None: if ping(ip, 10): status = True - text = ' %s' % _('ping ok') + text = ' %s' % _( + 'ping ok') else: if type(ping_result) is tuple: - loses_percent = (ping_result[0] / ping_result[1] if ping_result[1] != 0 else 1) + loses_percent = ( + ping_result[0] / ping_result[1] if ping_result[ + 1] != 0 else 1) ping_result = {'all': ping_result[0], 'return': ping_result[1]} if loses_percent > 1.0: text = ' %s' % _( @@ -742,7 +775,8 @@ def abon_ping(request, gid: int, uname): text = ' %s' % _( 'no ping, %(all)d/%(return)d loses') % ping_result else: - text = ' %s' % _('ping ok') + ' ' + str(ping_result) + text = ' %s' % _( + 'ping ok') + ' ' + str(ping_result) status = True except (NasFailedResult, lib.LogicError) as e: @@ -773,11 +807,18 @@ def set_auto_continue_service(request, gid: int, uname): @login_required @only_admins def vcards(r): - users = models.Abon.objects.exclude(group=None).select_related('group', 'street').only( + users = models.Abon.objects.exclude(group=None).select_related( + 'group', + 'street' + ).only( 'username', 'fio', 'group__title', 'telephone', 'street__name', 'house' ) - additional_tels = models.AdditionalTelephone.objects.select_related('abon', 'abon__group', 'abon__street') + additional_tels = models.AdditionalTelephone.objects.select_related( + 'abon', + 'abon__group', + 'abon__street' + ) response = HttpResponse(content_type='text/x-vcard') response['Content-Disposition'] = 'attachment; filename="contacts.vcard"' tmpl = ("BEGIN:VCARD\r\n" @@ -802,7 +843,8 @@ def vcards(r): for add_tel in additional_tels.iterator(): abon = add_tel.abon yield tmpl % { - 'uname': "%s (%s)" % (add_tel.owner_name, abon.get_full_name()), + 'uname': "%s (%s)" % ( + add_tel.owner_name, abon.get_full_name()), 'group_name': abon.group.title, 'abon_telephone': add_tel.telephone, 'street': abon.street.name if abon.street else '', @@ -818,13 +860,16 @@ class DialsListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList): template_name = 'abonapp/dial_log.html' def get_queryset(self): - abon = get_object_or_404(models.Abon, username=self.kwargs.get('uname')) + abon = get_object_or_404(models.Abon, + username=self.kwargs.get('uname')) if not self.request.user.has_perm('group_app.view_group', abon.group): raise PermissionDenied self.abon = abon if abon.telephone is not None and abon.telephone != '': tel = abon.telephone.replace('+', '') - additional_tels = tuple(t.telephone for t in models.AdditionalTelephone.objects.filter(abon=abon).iterator()) + additional_tels = tuple(t.telephone for t in + models.AdditionalTelephone.objects.filter( + abon=abon).iterator()) logs = AsteriskCDR.objects.filter( Q(src__contains=tel) | Q(dst__contains=tel) | Q(src__in=additional_tels) | Q(dst__in=additional_tels) @@ -840,9 +885,12 @@ class DialsListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList): return context def render_to_response(self, context, **response_kwargs): - if hasattr(self.abon.group, 'pk') and self.abon.group.pk != int(self.kwargs.get('gid')): - return redirect('abonapp:dials', self.abon.group.pk, self.abon.username) - return super(DialsListView, self).render_to_response(context, **response_kwargs) + if hasattr(self.abon.group, 'pk') and self.abon.group.pk != int( + self.kwargs.get('gid')): + return redirect('abonapp:dials', self.abon.group.pk, + self.abon.username) + return super(DialsListView, self).render_to_response(context, + **response_kwargs) def get(self, request, *args, **kwargs): try: @@ -872,20 +920,25 @@ def save_user_dev_port(request, gid: int, uname): port = DevPort.objects.get(pk=user_port) if abon.device is not None: try: - other_abon = models.Abon.objects.get(device=abon.device, dev_port=port) + other_abon = models.Abon.objects.get(device=abon.device, + dev_port=port) if other_abon != abon: - user_url = resolve_url('abonapp:abon_home', other_abon.group.id, other_abon.username) + user_url = resolve_url('abonapp:abon_home', + other_abon.group.id, + other_abon.username) messages.error(request, _( "%(user_name)s already pinned to this port on this device") % { - 'user_url': user_url, - 'user_name': other_abon.get_full_name() - }) + 'user_url': user_url, + 'user_name': other_abon.get_full_name() + }) return redirect('abonapp:abon_home', gid, uname) except models.Abon.DoesNotExist: pass except models.Abon.MultipleObjectsReturned: - messages.error(request, _('Multiple users on the same device port')) - return redirect('devapp:view', abon.device.group.pk, abon.device.pk) + messages.error(request, + _('Multiple users on the same device port')) + return redirect('devapp:view', abon.device.group.pk, + abon.device.pk) abon.dev_port = port if abon.is_dynamic_ip != is_dynamic_ip: @@ -929,7 +982,8 @@ def street_add(request, gid): def street_edit(request, gid): try: if request.method == 'POST': - for sid, sname in zip(request.POST.getlist('sid'), request.POST.getlist('sname')): + for sid, sname in zip(request.POST.getlist('sid'), + request.POST.getlist('sname')): street = models.AbonStreet.objects.get(pk=sid) street.name = sname street.save() @@ -1015,7 +1069,8 @@ def tel_del(request, gid: int, uname): tid = lib.safe_int(request.GET.get('tid')) tel = models.AdditionalTelephone.objects.get(pk=tid) tel.delete() - messages.success(request, _('Additional telephone successfully deleted')) + messages.success(request, + _('Additional telephone successfully deleted')) except models.AdditionalTelephone.DoesNotExist: messages.error(request, _('Telephone not found')) return redirect('abonapp:abon_home', gid, uname) @@ -1026,9 +1081,18 @@ def tel_del(request, gid: int, uname): @permission_required('group_app.view_group', (Group, 'pk', 'gid')) def phonebook(request, gid): res_format = request.GET.get('f') - t1 = models.Abon.objects.filter(group__id=int(gid)).only('telephone', 'fio').values_list('telephone', 'fio') - t2 = models.AdditionalTelephone.objects.filter(abon__group__id=gid).only('telephone', 'owner_name').values_list( - 'telephone', 'owner_name') + t1 = models.Abon.objects.filter( + group__id=int(gid) + ).only('telephone', 'fio').values_list( + 'telephone', 'fio' + ) + t2 = models.AdditionalTelephone.objects.filter( + abon__group__id=gid + ).only( + 'telephone', 'owner_name' + ).values_list( + 'telephone', 'owner_name' + ) telephones = tuple(t1) + tuple(t2) if res_format == 'csv': import csv @@ -1055,19 +1119,24 @@ def abon_export(request, gid): if frm.is_valid(): cleaned_data = frm.clean() fields = cleaned_data.get('fields') - subscribers = models.Abon.objects.filter(group__id=gid).only(*fields).values_list(*fields) + subscribers = models.Abon.objects.filter(group__id=gid).only( + *fields).values_list(*fields) if res_format == 'csv': import csv response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename="users.csv"' + response[ + 'Content-Disposition'] = 'attachment; filename="users.csv"' writer = csv.writer(response, quoting=csv.QUOTE_NONNUMERIC) - display_values = (f[1] for f in frm.fields['fields'].choices if f[0] in fields) + display_values = (f[1] for f in frm.fields['fields'].choices if + f[0] in fields) writer.writerow(display_values) for row in subscribers: writer.writerow(row) return response else: - messages.info(request, _('Unexpected format %(export_format)s') % {'export_format': res_format}) + messages.info(request, + _('Unexpected format %(export_format)s') % { + 'export_format': res_format}) return redirect('abonapp:group_list') else: messages.error(request, _('fix form errors')) @@ -1091,7 +1160,8 @@ def fin_report(request): response['Content-Disposition'] = 'attachment; filename="report.csv"' writer = csv.writer(response, quoting=csv.QUOTE_NONNUMERIC) for row in q: - writer.writerow((row['summ'], row['pay_date'].strftime('%Y-%m-%d'))) + writer.writerow( + (row['summ'], row['pay_date'].strftime('%Y-%m-%d'))) return response return render(request, 'abonapp/fin_report.html', { 'logs': q @@ -1109,9 +1179,11 @@ def add_edit_periodic_pay(request, gid: int, uname, periodic_pay_id=0): else: if not request.user.has_perm('abonapp.change_periodicpayforid'): raise PermissionDenied - periodic_pay_instance = get_object_or_404(models.PeriodicPayForId, pk=periodic_pay_id) + periodic_pay_instance = get_object_or_404(models.PeriodicPayForId, + pk=periodic_pay_id) if request.method == 'POST': - frm = forms.PeriodicPayForIdForm(request.POST, instance=periodic_pay_instance) + frm = forms.PeriodicPayForIdForm(request.POST, + instance=periodic_pay_instance) if frm.is_valid(): abon = get_object_or_404(models.Abon, username=uname) inst = frm.save(commit=False) @@ -1135,7 +1207,8 @@ def add_edit_periodic_pay(request, gid: int, uname, periodic_pay_id=0): @permission_required('group_app.view_group', (Group, 'pk', 'gid')) @permission_required('abonapp.delete_periodicpayforid') def del_periodic_pay(request, gid: int, uname, periodic_pay_id): - periodic_pay_instance = get_object_or_404(models.PeriodicPayForId, pk=periodic_pay_id) + periodic_pay_instance = get_object_or_404(models.PeriodicPayForId, + pk=periodic_pay_id) if periodic_pay_instance.account.username != uname: uname = periodic_pay_instance.account.username periodic_pay_instance.delete() @@ -1143,7 +1216,7 @@ def del_periodic_pay(request, gid: int, uname, periodic_pay_id): return redirect('abonapp:abon_services', gid, uname) -class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView): +class EditSibscriberMarkers(LoginAdminPermissionMixin, UpdateView): permission_required = 'abonapp.change_abon' http_method_names = ('get', 'post') template_name = 'abonapp/modal_user_markers.html' @@ -1154,7 +1227,8 @@ class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView): def dispatch(self, request, *args, **kwargs): try: - return super(EditSibscriberMarkers, self).dispatch(request, *args, **kwargs) + return super(EditSibscriberMarkers, self).dispatch(request, *args, + **kwargs) except ValidationError as e: messages.error(request, e) return self.render_to_response(self.get_context_data()) @@ -1171,7 +1245,8 @@ class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView): def form_valid(self, form): v = super(EditSibscriberMarkers, self).form_valid(form) - messages.success(self.request, _('User flags has changed successfully')) + messages.success(self.request, + _('User flags has changed successfully')) return v @@ -1202,7 +1277,11 @@ def attach_nas(request, gid): abons = models.Abon.objects.filter(group__id=gid) if abons.exists(): abons.update(nas=nas) - messages.success(request, _('Network access server for users in this group, has been updated')) + messages.success( + request, + _('Network access server for users in this ' + 'group, has been updated') + ) return redirect('abonapp:group_list') else: messages.warning(request, _('Users not found')) @@ -1220,16 +1299,17 @@ def attach_nas(request, gid): @json_view def abons(request): ablist = ({ - 'id': abn.pk, - 'tarif_id': abn.active_tariff().tariff.pk if abn.active_tariff() is not None else 0, - 'ip': abn.ip_address - } for abn in models.Abon.objects.iterator()) + 'id': abn.pk, + 'tarif_id': abn.active_tariff().tariff.pk + if abn.active_tariff() is not None else 0, + 'ip': abn.ip_address + } for abn in models.Abon.objects.iterator()) tarlist = ({ - 'id': trf.pk, - 'speedIn': trf.speedIn, - 'speedOut': trf.speedOut - } for trf in Tariff.objects.all()) + 'id': trf.pk, + 'speedIn': trf.speedIn, + 'speedOut': trf.speedOut + } for trf in Tariff.objects.all()) data = { 'subscribers': ablist, @@ -1247,7 +1327,9 @@ def search_abon(request): if not word: return None results = models.Abon.objects.filter(fio__icontains=word)[:8] - return list({'id': usr.pk, 'text': "%s: %s" % (usr.username, usr.fio)} for usr in results) + return list( + {'id': usr.pk, 'text': "%s: %s" % (usr.username, usr.fio)} for usr in + results) class DhcpLever(SecureApiView): @@ -1370,7 +1452,8 @@ class DublicatePay(SecureApiView): if pays.count() > 0: return self._bad_ret(-100) - abon.add_ballance(None, pay_amount, comment='KonikaForward %.2f' % pay_amount) + abon.add_ballance(None, pay_amount, + comment='KonikaForward %.2f' % pay_amount) abon.save(update_fields=('ballance',)) models.AllTimePayLog.objects.create( diff --git a/devapp/templates/devapp/custom_dev_page/generic_switch.html b/devapp/templates/devapp/custom_dev_page/generic_switch.html index 8355a1f..8f9a633 100644 --- a/devapp/templates/devapp/custom_dev_page/generic_switch.html +++ b/devapp/templates/devapp/custom_dev_page/generic_switch.html @@ -125,11 +125,17 @@ - + {% if perms.devapp.add_port %} - - {% trans 'Add ports' %} - + {% if ports %} + + {% trans 'Add ports' %} + + {% else %} + + {% trans 'Add ports' %} + + {% endif %} {% endif %} diff --git a/devapp/urls.py b/devapp/urls.py index f0f4b27..4d3a84c 100644 --- a/devapp/urls.py +++ b/devapp/urls.py @@ -5,34 +5,52 @@ app_name = 'devapp' urlpatterns = [ path('', views.GroupsListView.as_view(), name='group_list'), - path('devices_without_groups/', views.DevicesWithoutGroupsListView.as_view(), name='devices_null_group'), + path('devices_without_groups/', + views.DevicesWithoutGroupsListView.as_view(), + name='devices_null_group'), path('fix_onu/', views.fix_onu, name='fix_onu'), path('/', views.DevicesListView.as_view(), name='devs'), path('/add/', views.DeviceCreateView.as_view(), name='add'), path('//', views.devview, name='view'), - path('//del/', views.DeviceDeleteView.as_view(), name='del'), - path('//add/', views.add_single_port, name='add_port'), - path('//edit/', views.DeviceUpdate.as_view(), name='edit'), - path('//edit_extra/', views.DeviceUpdateExtra.as_view(), name='extra_data_edit'), - path('//ports//fix_port_conflict/', views.fix_port_conflict, + path('//del/', + views.DeviceDeleteView.as_view(), name='del'), + path('//add/', views.add_single_port, + name='add_port'), + path('//edit/', views.DeviceUpdate.as_view(), + name='edit'), + path('//edit_extra/', + views.DeviceUpdateExtra.as_view(), name='extra_data_edit'), + path( + '//ports//fix_port_conflict/', + views.fix_port_conflict, name='fix_port_conflict'), - path('//ports//show_subscriber_on_port/', + path( + '//ports//show_subscriber_on_port/', views.ShowSubscriberOnPort.as_view(), name='show_subscriber_on_port'), - path('//ports_add/', views.add_ports, name='add_ports'), - path('//register_device/', views.register_device, name='dev_register'), - re_path('^(\d+)/(?P\d+)/(?P\d+)_(?P[0-1]{1})$', views.toggle_port, name='port_toggle'), - path('///del/', views.delete_single_port, name='del_port'), - path('///edit/', views.edit_single_port, name='edit_port'), - path('fix_device_group//', views.fix_device_group, name='fix_device_group'), + path('//ports_add/', views.add_ports, + name='add_ports'), + path('//register_device/', + views.register_device, name='dev_register'), + re_path('^(\d+)/(?P\d+)/(?P\d+)_(?P[0-1]{1})$', + views.toggle_port, name='port_toggle'), + path('///del/', + views.delete_single_port, name='del_port'), + path('///edit/', + views.edit_single_port, name='edit_port'), + path('fix_device_group//', views.fix_device_group, + name='fix_device_group'), path('search_dev/', views.search_dev), # ZTE ports under fibers - path('///', views.zte_port_view_uncfg, name='zte_port_view_uncfg'), + path('///', + views.zte_port_view_uncfg, name='zte_port_view_uncfg'), # Monitoring api path('on_device_event/', views.OnDeviceMonitoringEvent.as_view()), # Nagios mon generate - path('nagios/hosts/', views.nagios_objects_conf, name='nagios_objects_conf'), - path('api/getall/', views.DevicesGetListView.as_view(), name='nagios_get_all_hosts') + path('nagios/hosts/', views.nagios_objects_conf, + name='nagios_objects_conf'), + path('api/getall/', views.DevicesGetListView.as_view(), + name='nagios_get_all_hosts') ] diff --git a/devapp/views.py b/devapp/views.py index 314efab..eda2d00 100644 --- a/devapp/views.py +++ b/devapp/views.py @@ -1,47 +1,50 @@ import re from ipaddress import ip_address + +from abonapp.models import Abon +from accounts_app.models import UserProfile +from chatbot.models import ChatException +from chatbot.send_func import send_notify +from devapp.base_intr import DeviceImplementationError +from django.conf import settings +from django.contrib import messages from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied from django.db import IntegrityError from django.db.models import Q, Count from django.http import HttpResponse, Http404 from django.shortcuts import render, redirect, get_object_or_404, resolve_url -from django.contrib import messages from django.utils.decorators import method_decorator from django.utils.translation import gettext_lazy as _, gettext -from easysnmp import EasySNMPTimeoutError, EasySNMPError from django.views.generic import DetailView, DeleteView, UpdateView, CreateView - -from devapp.base_intr import DeviceImplementationError -from djing.lib.decorators import only_admins, hash_auth_view +from djing import global_base_views, MAC_ADDR_REGEX, ping, get_object_or_None from djing.lib import safe_int, ProcessLocked, DuplicateEntry -from abonapp.models import Abon -from djing.lib.tln import ZteOltConsoleError, OnuZteRegisterError, ZteOltLoginFailed +from djing.lib.decorators import json_view +from djing.lib.decorators import only_admins, hash_auth_view +from djing.lib.mixins import LoginAdminPermissionMixin, LoginAdminMixin +from djing.lib.tln import ZteOltConsoleError, OnuZteRegisterError, \ + ZteOltLoginFailed +from easysnmp import EasySNMPTimeoutError, EasySNMPError from group_app.models import Group -from accounts_app.models import UserProfile -from django.conf import settings -from guardian.decorators import permission_required_or_403 as permission_required +from guardian.decorators import \ + permission_required_or_403 as permission_required from guardian.shortcuts import get_objects_for_user -from chatbot.send_func import send_notify -from chatbot.models import ChatException -from djing.lib.decorators import json_view -from djing import global_base_views, MAC_ADDR_REGEX, ping, get_object_or_None -from .models import Device, Port, DeviceDBException, DeviceMonitoringException from .forms import DeviceForm, PortForm, DeviceExtraDataForm +from .models import Device, Port, DeviceDBException, DeviceMonitoringException -login_decs = login_required, only_admins - - -class DevicesListView(global_base_views.OrderedFilteredList): +class DevicesListView(LoginAdminPermissionMixin, + global_base_views.OrderedFilteredList): context_object_name = 'devices' template_name = 'devapp/devices.html' + permission_required = 'devapp.view_device' def get_queryset(self): group_id = safe_int(self.kwargs.get('group_id')) queryset = Device.objects.filter(group__pk=group_id) \ .select_related('group') \ - .only('comment', 'mac_addr', 'devtype', 'group', 'pk', 'ip_address') + .only('comment', 'mac_addr', 'devtype', 'group', 'pk', + 'ip_address') return queryset def get_context_data(self, **kwargs): @@ -50,33 +53,34 @@ class DevicesListView(global_base_views.OrderedFilteredList): context['group'] = get_object_or_404(Group, pk=group_id) return context - @method_decorator(login_decs) - @method_decorator(permission_required('devapp.view_device')) def dispatch(self, request, *args, **kwargs): try: - response = super(DevicesListView, self).dispatch(request, *args, **kwargs) + response = super(DevicesListView, self).dispatch(request, *args, + **kwargs) except (DeviceDBException, DeviceMonitoringException) as e: messages.error(request, e) response = HttpResponse('Error') return response -@method_decorator(login_decs, name='dispatch') -@method_decorator(permission_required('devapp.view_device'), name='dispatch') -class DevicesWithoutGroupsListView(global_base_views.OrderedFilteredList): +class DevicesWithoutGroupsListView(LoginAdminPermissionMixin, + global_base_views.OrderedFilteredList): context_object_name = 'devices' template_name = 'devapp/devices_null_group.html' - queryset = Device.objects.filter(group=None).only('comment', 'devtype', 'pk', 'ip_address') + queryset = Device.objects.filter(group=None).only('comment', 'devtype', + 'pk', 'ip_address') + permission_required = 'devapp.view_device' -@method_decorator(login_decs, name='dispatch') -@method_decorator(permission_required('devapp.delete_device'), name='dispatch') -class DeviceDeleteView(DeleteView): +class DeviceDeleteView(LoginAdminPermissionMixin, DeleteView): model = Device pk_url_kwarg = 'device_id' + permission_required = 'devapp.delete_device' def get_success_url(self): - return resolve_url('devapp:devs', group_id=self.object.group.pk if self.object.group else 0) + return resolve_url('devapp:devs', + group_id=self.object.group.pk + if self.object.group else 0) def delete(self, request, *args, **kwargs): res = super().delete(request, *args, **kwargs) @@ -93,9 +97,7 @@ class DeviceDeleteView(DeleteView): return res -@method_decorator(login_decs, name='dispatch') -@method_decorator(permission_required('devapp.view_device'), name='dispatch') -class DeviceUpdate(UpdateView): +class DeviceUpdate(LoginAdminPermissionMixin, UpdateView): template_name = 'devapp/dev.html' context_object_name = 'dev' model = Device @@ -103,6 +105,7 @@ class DeviceUpdate(UpdateView): pk_url_kwarg = 'device_id' device_group = None already_dev = None + permission_required = 'devapp.view_device' def post(self, request, *args, **kwargs): if not request.user.has_perm('devapp.change_device'): @@ -120,13 +123,17 @@ class DeviceUpdate(UpdateView): # check if that device is exist device_id = self.kwargs.get(self.pk_url_kwarg) try: - already_dev = self.model.objects.exclude(pk=device_id).get(mac_addr=self.request.POST.get('mac_addr')) + already_dev = self.model.objects.exclude(pk=device_id).get( + mac_addr=self.request.POST.get('mac_addr')) self.already_dev = already_dev if already_dev.group: - messages.warning(self.request, _('You have redirected to existing device')) - return redirect('devapp:view', already_dev.group.pk, already_dev.pk) + messages.warning(self.request, + _('You have redirected to existing device')) + return redirect('devapp:view', already_dev.group.pk, + already_dev.pk) else: - messages.warning(self.request, _('Please attach group for device')) + messages.warning(self.request, + _('Please attach group for device')) return redirect('devapp:fix_device_group', already_dev.pk) except Device.DoesNotExist: pass @@ -148,7 +155,8 @@ class DeviceUpdate(UpdateView): return super().dispatch(request, *args, **kwargs) def form_invalid(self, form): - messages.error(self.request, _('Form is invalid, check fields and try again')) + messages.error(self.request, + _('Form is invalid, check fields and try again')) return super().form_invalid(form) def get_context_data(self, **kwargs): @@ -159,37 +167,41 @@ class DeviceUpdate(UpdateView): return context -@method_decorator(login_decs, name='dispatch') -@method_decorator(permission_required('devapp.add_device'), name='dispatch') -class DeviceCreateView(CreateView): +class DeviceCreateView(LoginAdminPermissionMixin, CreateView): template_name = 'devapp/add_dev.html' context_object_name = 'dev' model = Device form_class = DeviceForm + permission_required = 'devapp.add_device' device_group = None already_dev = None def form_valid(self, form): # check if that device is exist try: - already_dev = self.model.objects.get(mac_addr=self.request.POST.get('mac_addr')) + already_dev = self.model.objects.get( + mac_addr=self.request.POST.get('mac_addr')) self.already_dev = already_dev if already_dev.group: - messages.warning(self.request, _('You have redirected to existing device')) - return redirect('devapp:view', already_dev.group.pk, already_dev.pk) + messages.warning(self.request, + _('You have redirected to existing device')) + return redirect('devapp:view', already_dev.group.pk, + already_dev.pk) else: - messages.warning(self.request, _('Please attach group for device')) + messages.warning(self.request, + _('Please attach group for device')) return redirect('devapp:fix_device_group', already_dev.pk) except Device.DoesNotExist: pass r = super().form_valid(form) # change device info in dhcpd.conf try: - self.request.user.log(self.request.META, 'cdev', 'ip %s, mac: %s, "%s"' % ( - self.object.ip_address, - self.object.mac_addr, - self.object.comment - )) + self.request.user.log(self.request.META, 'cdev', + 'ip %s, mac: %s, "%s"' % ( + self.object.ip_address, + self.object.mac_addr, + self.object.comment + )) self.object.update_dhcp() messages.success(self.request, _('Device info has been saved')) except PermissionError as e: @@ -221,17 +233,17 @@ class DeviceCreateView(CreateView): context['group'] = self.device_group context['already_dev'] = self.already_dev parent_device_id = self.request.GET.get('pdev') - context['selected_parent_dev'] = get_object_or_None(Device, pk=parent_device_id) + context['selected_parent_dev'] = get_object_or_None( + Device, pk=parent_device_id) return context -@method_decorator(login_decs, name='dispatch') -@method_decorator(permission_required('devapp.change_device'), name='dispatch') -class DeviceUpdateExtra(UpdateView): +class DeviceUpdateExtra(LoginAdminPermissionMixin, UpdateView): template_name = 'devapp/modal_device_extra_edit.html' model = Device form_class = DeviceExtraDataForm pk_url_kwarg = 'device_id' + permission_required = 'devapp.change_device' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -240,12 +252,14 @@ class DeviceUpdateExtra(UpdateView): def form_valid(self, form): r = super().form_valid(form) - messages.success(self.request, _('Device extra data has successfully updated')) + messages.success(self.request, _('Device extra data has ' + 'successfully updated')) return r -@method_decorator(login_decs, name='dispatch') -class ShowSubscriberOnPort(global_base_views.RedirectWhenErrorMixin, DetailView): +class ShowSubscriberOnPort(LoginAdminMixin, + global_base_views.RedirectWhenErrorMixin, + DetailView): template_name = 'devapp/manage_ports/modal_show_subscriber_on_port.html' http_method_names = ('get',) @@ -260,7 +274,9 @@ class ShowSubscriberOnPort(global_base_views.RedirectWhenErrorMixin, DetailView) errmsg = gettext('More than one subscriber on device port') # messages.error(self.request, errmsg) raise global_base_views.RedirectWhenError( - resolve_url('devapp:fix_port_conflict', group_id=self.kwargs.get('group_id'), device_id=dev_id, + resolve_url('devapp:fix_port_conflict', + group_id=self.kwargs.get('group_id'), + device_id=dev_id, port_id=port_id), errmsg ) @@ -292,7 +308,8 @@ def add_ports(request, group_id: int, device_id: int): res_ports = list() try: if device.group is None: - messages.error(request, _('Device does not have a group, please fix that')) + messages.error(request, + _('Device does not have a group, please fix that')) return redirect('devapp:fix_device_group', device.pk) if request.method == 'POST': ports = zip( @@ -314,7 +331,8 @@ def add_ports(request, group_id: int, device_id: int): ) db_ports = Port.objects.filter(device=device) - db_ports = tuple(TempPort(p.num, p.descr, None, True, p.pk) for p in db_ports) + db_ports = tuple( + TempPort(p.num, p.descr, None, True, p.pk) for p in db_ports) manager = device.get_manager_object() ports = manager.get_ports() @@ -371,16 +389,18 @@ def edit_single_port(request, group_id: int, device_id: int, port_id: int): frm.save() messages.success(request, _('Port successfully saved')) else: - messages.error(request, _('Form is invalid, check fields and try again')) + messages.error(request, _( + 'Form is invalid, check fields and try again')) return redirect('devapp:view', group_id, device_id) frm = PortForm(instance=port) - return render(request, 'devapp/manage_ports/modal_add_edit_port.html', { - 'port_id': port_id, - 'did': device_id, - 'gid': group_id, - 'form': frm - }) + return render(request, 'devapp/manage_ports/modal_add_edit_port.html', + { + 'port_id': port_id, + 'did': device_id, + 'gid': group_id, + 'form': frm + }) except Port.DoesNotExist: messages.error(request, _('Port does not exist')) except (DeviceDBException, DuplicateEntry) as e: @@ -401,17 +421,19 @@ def add_single_port(request, group_id, device_id): messages.success(request, _('Port successfully saved')) return redirect('devapp:view', group_id, device_id) else: - messages.error(request, _('Form is invalid, check fields and try again')) + messages.error(request, _( + 'Form is invalid, check fields and try again')) else: frm = PortForm(initial={ 'num': request.GET.get('n'), 'descr': request.GET.get('t') }) - return render(request, 'devapp/manage_ports/modal_add_edit_port.html', { - 'did': device_id, - 'gid': group_id, - 'form': frm - }) + return render(request, 'devapp/manage_ports/modal_add_edit_port.html', + { + 'did': device_id, + 'gid': group_id, + 'form': frm + }) except Device.DoesNotExist: messages.error(request, _('Device does not exist')) except (DeviceDBException, DuplicateEntry) as e: @@ -433,12 +455,13 @@ def devview(request, group_id: int, device_id: int): template_name = 'generic_switch.html' try: if device.ip_address: - if not ping(device.ip_address): + if not ping(str(device.ip_address)): messages.error(request, _('Dot was not pinged')) if device.man_passw: manager = device.get_manager_object() ports = tuple(manager.get_ports()) - if ports is not None and len(ports) > 0 and isinstance(ports[0], Exception): + if ports is not None and len(ports) > 0 and isinstance(ports[0], + Exception): messages.error(request, ports[0]) ports = ports[1] template_name = manager.get_template_name() @@ -449,10 +472,12 @@ def devview(request, group_id: int, device_id: int): 'ports': ports, 'dev_accs': Abon.objects.filter(device=device), 'dev_manager': manager, - 'ports_db': Port.objects.filter(device=device).annotate(num_abons=Count('abon')), + 'ports_db': Port.objects.filter(device=device).annotate( + num_abons=Count('abon')), }) except EasySNMPError as e: - messages.error(request, "%s: %s" % (gettext('SNMP error on device'), e)) + messages.error(request, + "%s: %s" % (gettext('SNMP error on device'), e)) except (DeviceDBException, DeviceImplementationError) as e: messages.error(request, e) return render(request, 'devapp/custom_dev_page/' + template_name, { @@ -467,11 +492,12 @@ def zte_port_view_uncfg(request, group_id: str, device_id: str, fiber_id: str): zte_olt_device = get_object_or_404(Device, id=device_id) manager = zte_olt_device.get_manager_object() onu_list = manager.get_units_unregistered(fiber_id) - return render(request, 'devapp/custom_dev_page/olt_ztec320_units_uncfg.html', { - 'onu_list': onu_list, - 'dev': zte_olt_device, - 'grp': group_id - }) + return render(request, + 'devapp/custom_dev_page/olt_ztec320_units_uncfg.html', { + 'onu_list': onu_list, + 'dev': zte_olt_device, + 'grp': group_id + }) @login_required @@ -498,18 +524,20 @@ def toggle_port(request, device_id: str, port_id: str, status=0): messages.error(request, _('wait for a reply from the SNMP Timeout')) except EasySNMPError as e: messages.error(request, 'EasySNMPError: %s' % e) - return redirect('devapp:view', device.group.pk if device.group is not None else 0, device_id) + return redirect('devapp:view', + device.group.pk if device.group is not None else 0, + device_id) -@method_decorator(login_decs, name='dispatch') -class GroupsListView(global_base_views.OrderedFilteredList): +class GroupsListView(LoginAdminMixin, global_base_views.OrderedFilteredList): context_object_name = 'groups' template_name = 'devapp/group_list.html' model = Group def get_queryset(self): groups = super(GroupsListView, self).get_queryset() - groups = get_objects_for_user(self.request.user, 'group_app.view_group', klass=groups, + groups = get_objects_for_user(self.request.user, + 'group_app.view_group', klass=groups, accept_global_perms=False) return groups @@ -528,11 +556,13 @@ def search_dev(request): qs |= Q(ip_address=str(ip)) except ValueError: pass - results = Device.objects.filter(qs).only('pk', 'ip_address', 'comment')[:16] + results = Device.objects.filter(qs).only('pk', 'ip_address', + 'comment')[:16] results = tuple({ - 'id': device.pk, - 'text': "%s: %s" % (device.ip_address or '', device.comment) - } for device in results) + 'id': device.pk, + 'text': "%s: %s" % ( + device.ip_address or '', device.comment) + } for device in results) return results @@ -549,9 +579,11 @@ def fix_device_group(request, device_id): messages.success(request, _('Device fixed')) return redirect('devapp:devs', ch_dev.group.pk) else: - messages.error(request, _('Please attach group for device')) + messages.error(request, + _('Please attach group for device')) else: - messages.error(request, _('Form is invalid, check fields and try again')) + messages.error(request, _( + 'Form is invalid, check fields and try again')) else: frm = DeviceForm(instance=device) except ValueError: @@ -577,7 +609,8 @@ def fix_onu(request): manobj = parent.get_manager_object() ports = manobj.get_list_keyval('.1.3.6.1.4.1.3320.101.10.1.1.3') text = ' ' % \ - (_('Device with mac address %(mac)s does not exist') % {'mac': mac}) + (_('Device with mac address %(mac)s does not exist') % { + 'mac': mac}) for srcmac, snmpnum in ports: # convert bytes mac address to str presentation mac address real_mac = ':'.join('%x' % ord(i) for i in srcmac) @@ -585,7 +618,8 @@ def fix_onu(request): onu.snmp_extra = str(snmpnum) onu.save(update_fields=('snmp_extra',)) status = 0 - text = ' ' % _('Fixed') + text = ' ' % _( + 'Fixed') break else: text += '\n%s' % _('Parent device not found') @@ -630,7 +664,8 @@ class OnDeviceMonitoringEvent(global_base_views.SecureApiView): if not re.match(MAC_ADDR_REGEX, dev_mac): return {'text': 'mac address %s is not valid' % dev_mac} - device_down = Device.objects.filter(mac_addr=dev_mac).defer('extra_data').first() + device_down = Device.objects.filter(mac_addr=dev_mac).defer( + 'extra_data').first() if device_down is None: return {'text': 'Devices with mac %s does not exist' % dev_mac} @@ -650,9 +685,13 @@ class OnDeviceMonitoringEvent(global_base_views.SecureApiView): device_down.save(update_fields=('status',)) if not device_down.is_noticeable: - return {'text': 'Notification for %s is unnecessary' % device_down.ip_address or device_down.comment} + return { + 'text': 'Notification for %s is unnecessary' % + device_down.ip_address or device_down.comment + } - recipients = UserProfile.objects.get_profiles_by_group(device_down.group.pk) + recipients = UserProfile.objects.get_profiles_by_group( + device_down.group.pk) names = list() for recipient in recipients.iterator(): @@ -688,7 +727,8 @@ def nagios_objects_conf(request): except DeviceImplementationError: pass - devices_queryset = Device.objects.exclude(Q(mac_addr=None) | Q(ip_address='127.0.0.1')) \ + devices_queryset = Device.objects.exclude( + Q(mac_addr=None) | Q(ip_address='127.0.0.1')) \ .select_related('parent_dev') \ .only('ip_address', 'comment', 'parent_dev') confs = map(getconf, devices_queryset) @@ -710,7 +750,8 @@ class DevicesGetListView(global_base_views.SecureApiView): devs = Device.objects.all() else: devs = Device.objects.filter(devtype=device_type) - res = devs.defer('man_passw', 'group', 'parent_dev', 'extra_data').values() + res = devs.defer('man_passw', 'group', 'parent_dev', + 'extra_data').values() for r in res: if isinstance(r['mac_addr'], EUI): r['mac_addr'] = int(r['mac_addr']) @@ -726,6 +767,7 @@ def register_device(request, group_id: int, device_id: int): '' % icon, '' % msg )) + device = get_object_or_404(Device, pk=device_id) status = 1 try: @@ -734,7 +776,8 @@ def register_device(request, group_id: int, device_id: int): except OnuZteRegisterError: text = format_msg(gettext('Unregistered onu not found'), 'eye-close') except ZteOltLoginFailed: - text = format_msg(gettext('Wrong login or password for telnet access'), 'lock') + text = format_msg(gettext('Wrong login or password for telnet access'), + 'lock') except (ConnectionRefusedError, ZteOltConsoleError) as e: text = format_msg(e, 'exclamation-sign') except DeviceImplementationError as e: diff --git a/djing/lib/mixins.py b/djing/lib/mixins.py index f3e1363..c4326bf 100644 --- a/djing/lib/mixins.py +++ b/djing/lib/mixins.py @@ -1,4 +1,5 @@ -from django.contrib.auth.mixins import AccessMixin +from django.contrib.auth.mixins import AccessMixin, LoginRequiredMixin +from guardian.mixins import PermissionRequiredMixin class OnlyAdminsMixin(AccessMixin): @@ -7,3 +8,12 @@ class OnlyAdminsMixin(AccessMixin): if not request.user.is_admin: return self.handle_no_permission() return super().dispatch(request, *args, **kwargs) + + +class LoginAdminMixin(LoginRequiredMixin, OnlyAdminsMixin): + pass + + +class LoginAdminPermissionMixin(LoginRequiredMixin, OnlyAdminsMixin, + PermissionRequiredMixin): + return_403 = True