Browse Source

refactoring

devel
Dmitry Novikov 7 years ago
parent
commit
2a1331e00c
  1. 321
      abonapp/views.py
  2. 14
      devapp/templates/devapp/custom_dev_page/generic_switch.html
  3. 50
      devapp/urls.py
  4. 245
      devapp/views.py
  5. 12
      djing/lib/mixins.py

321
abonapp/views.py

@ -1,48 +1,48 @@
from typing import Dict, Optional
from datetime import datetime, date 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.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.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.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.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator 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.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 gw_app.models import NASModel
from tariff_app.models import Tariff
from gw_app.nas_managers import NasFailedResult, NasNetworkError 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 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 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' template_name = 'abonapp/peoples.html'
def get_queryset(self): def get_queryset(self):
@ -74,7 +74,8 @@ class PeoplesListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList):
context = super(PeoplesListView, self).get_context_data(**kwargs) 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['street_id'] = lib.safe_int(self.request.GET.get('street'))
context['group'] = group context['group'] = group
return context return context
@ -87,12 +88,14 @@ class GroupListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList):
def get_queryset(self): def get_queryset(self):
queryset = super(GroupListView, self).get_queryset() 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) accept_global_perms=False)
return queryset return queryset
class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixin_django, CreateView):
class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin,
PermissionRequiredMixin_django, CreateView):
permission_required = 'abonapp.add_abon' permission_required = 'abonapp.add_abon'
group = None group = None
abon = None abon = None
@ -135,7 +138,12 @@ class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixi
messages.success(self.request, _('create abon success msg')) messages.success(self.request, _('create abon success msg'))
self.abon = abon self.abon = abon
return super(AbonCreateView, self).form_valid(form) 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) messages.error(self.request, e)
except lib.MultipleException as errs: except lib.MultipleException as errs:
for err in errs.err_list: for err in errs.err_list:
@ -147,7 +155,7 @@ class AbonCreateView(LoginRequiredMixin, OnlyAdminsMixin, PermissionRequiredMixi
return super(AbonCreateView, self).form_invalid(form) return super(AbonCreateView, self).form_invalid(form)
class DelAbonDeleteView(AbonappPermissionMixin, DeleteView):
class DelAbonDeleteView(LoginAdminPermissionMixin, DeleteView):
permission_required = 'abonapp.delete_abon' permission_required = 'abonapp.delete_abon'
model = models.Abon model = models.Abon
slug_url_kwarg = 'uname' slug_url_kwarg = 'uname'
@ -166,13 +174,14 @@ class DelAbonDeleteView(AbonappPermissionMixin, DeleteView):
abon = self.get_object() abon = self.get_object()
gid = abon.group.id gid = abon.group.id
abon.delete() 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')) messages.success(request, _('delete abon success msg'))
return redirect('abonapp:people_list', gid=gid) return redirect('abonapp:people_list', gid=gid)
except NasNetworkError as e: except NasNetworkError as e:
@ -202,7 +211,8 @@ def abonamount(request, gid: int, uname):
comment = _('fill account through admin side') comment = _('fill account through admin side')
abon.add_ballance(request.user, amnt, comment=comment) abon.add_ballance(request.user, amnt, comment=comment)
abon.save(update_fields=('ballance',)) 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) return redirect('abonapp:abon_phistory', gid=gid, uname=uname)
else: else:
messages.error(request, _('I not know the account id')) 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' permission_required = 'group_app.view_group'
context_object_name = 'invoices' context_object_name = 'invoices'
template_name = 'abonapp/invoiceForPayment.html' template_name = 'abonapp/invoiceForPayment.html'
@ -229,7 +239,8 @@ class DebtsListView(AbonappPermissionMixin, OrderedFilteredList):
return self.abon.group return self.abon.group
def get_queryset(self): 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 self.abon = abon
return models.InvoiceForPayment.objects.filter(abon=abon) return models.InvoiceForPayment.objects.filter(abon=abon)
@ -240,7 +251,7 @@ class DebtsListView(AbonappPermissionMixin, OrderedFilteredList):
return context return context
class PayHistoryListView(AbonappPermissionMixin, OrderedFilteredList):
class PayHistoryListView(LoginAdminPermissionMixin, OrderedFilteredList):
permission_required = 'group_app.view_group' permission_required = 'group_app.view_group'
context_object_name = 'pay_history' context_object_name = 'pay_history'
template_name = 'abonapp/payHistory.html' template_name = 'abonapp/payHistory.html'
@ -251,9 +262,11 @@ class PayHistoryListView(AbonappPermissionMixin, OrderedFilteredList):
return models.Group.objects.filter(pk=self.kwargs.get('gid')).first() return models.Group.objects.filter(pk=self.kwargs.get('gid')).first()
def get_queryset(self): 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 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 return pay_history
def get_context_data(self, **kwargs): 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) abon = get_object_or_404(models.Abon, username=uname)
if abon.group != grp: 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) return redirect('abonapp:abon_services', abon.group.id, abon.username)
try: try:
periodic_pay = models.PeriodicPayForId.objects.filter(account=abon).first()
periodic_pay = models.PeriodicPayForId.objects.filter(
account=abon).first()
except models.PeriodicPayForId.DoesNotExist: except models.PeriodicPayForId.DoesNotExist:
periodic_pay = None 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' permission_required = 'abonapp.view_abon'
model = models.Abon model = models.Abon
form_class = forms.AbonForm form_class = forms.AbonForm
@ -301,7 +316,8 @@ class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try: try:
return super(AbonHomeUpdateView, self).dispatch(request, *args, **kwargs)
return super(AbonHomeUpdateView, self).dispatch(request, *args,
**kwargs)
except lib.LogicError as e: except lib.LogicError as e:
messages.error(request, e) messages.error(request, e)
except (NasFailedResult, NasNetworkError) as e: except (NasFailedResult, NasNetworkError) as e:
@ -348,7 +364,8 @@ class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView):
'password': passw 'password': passw
} }
except models.AbonRawPassword.DoesNotExist: 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': ''} return {'password': ''}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -357,7 +374,8 @@ class AbonHomeUpdateView(AbonappPermissionMixin, UpdateView):
context = { context = {
'group': self.group, 'group': self.group,
'device': device, '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) context.update(kwargs)
return super(AbonHomeUpdateView, self).get_context_data(**context) return super(AbonHomeUpdateView, self).get_context_data(**context)
@ -421,20 +439,23 @@ def pick_tariff(request, gid: int, uname):
if request.method == 'POST': if request.method == 'POST':
trf = Tariff.objects.get(pk=request.POST.get('tariff')) trf = Tariff.objects.get(pk=request.POST.get('tariff'))
deadline = request.POST.get('deadline') 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: if deadline == '' or deadline is None:
abon.pick_tariff(trf, request.user, comment=log_comment) abon.pick_tariff(trf, request.user, comment=log_comment)
else: else:
deadline = datetime.strptime(deadline, '%Y-%m-%d %H:%M:%S') 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() r = abon.nas_sync_self()
if r is None: if r is None:
messages.success(request, _('Tariff has been picked')) messages.success(request, _('Tariff has been picked'))
else: else:
messages.error(request, r) 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: except (lib.LogicError, NasFailedResult) as e:
messages.error(request, e) messages.error(request, e)
except NasNetworkError as e: except NasNetworkError as e:
@ -461,7 +482,8 @@ def pick_tariff(request, gid: int, uname):
@permission_required('abonapp.can_complete_service') @permission_required('abonapp.can_complete_service')
def unsubscribe_service(request, gid: int, uname, abon_tariff_id: int): def unsubscribe_service(request, gid: int, uname, abon_tariff_id: int):
try: 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() abon_tariff.delete()
messages.success(request, _('User has been detached from service')) messages.success(request, _('User has been detached from service'))
except NasFailedResult as e: 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) return redirect('abonapp:abon_services', gid=gid, uname=uname)
class LogListView(AbonappPermissionMixin, ListView):
class LogListView(LoginAdminPermissionMixin, ListView):
permission_required = 'abonapp.view_abonlog' permission_required = 'abonapp.view_abonlog'
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
http_method_names = ('get',) http_method_names = ('get',)
@ -483,7 +505,7 @@ class LogListView(AbonappPermissionMixin, ListView):
model = models.AbonLog model = models.AbonLog
class DebtorsListView(AbonappPermissionMixin, ListView):
class DebtorsListView(LoginAdminPermissionMixin, ListView):
permission_required = 'abonapp.view_invoiceforpayment' permission_required = 'abonapp.view_invoiceforpayment'
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
http_method_names = ('get',) http_method_names = ('get',)
@ -492,7 +514,7 @@ class DebtorsListView(AbonappPermissionMixin, ListView):
queryset = models.InvoiceForPayment.objects.filter(status=True) queryset = models.InvoiceForPayment.objects.filter(status=True)
class TaskLogListView(AbonappPermissionMixin, ListView):
class TaskLogListView(LoginAdminPermissionMixin, ListView):
permission_required = 'group_app.view_group' permission_required = 'group_app.view_group'
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
http_method_names = ('get',) http_method_names = ('get',)
@ -506,7 +528,8 @@ class TaskLogListView(AbonappPermissionMixin, ListView):
return get_object_or_404(models.Group, pk=self.kwargs.get('gid')) return get_object_or_404(models.Group, pk=self.kwargs.get('gid'))
def get_queryset(self): 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 self.abon = abon
return Task.objects.filter(abon=abon) return Task.objects.filter(abon=abon)
@ -517,14 +540,15 @@ class TaskLogListView(AbonappPermissionMixin, ListView):
return context return context
class PassportUpdateView(AbonappPermissionMixin, UpdateView):
class PassportUpdateView(LoginAdminPermissionMixin, UpdateView):
permission_required = 'abonapp.view_passportinfo' permission_required = 'abonapp.view_passportinfo'
form_class = forms.PassportForm form_class = forms.PassportForm
model = models.PassportInfo model = models.PassportInfo
template_name = 'abonapp/modal_passport_view.html' template_name = 'abonapp/modal_passport_view.html'
def get_object(self, queryset=None): 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: try:
passport_instance = models.PassportInfo.objects.get(abon=self.abon) passport_instance = models.PassportInfo.objects.get(abon=self.abon)
except models.PassportInfo.DoesNotExist: except models.PassportInfo.DoesNotExist:
@ -535,7 +559,8 @@ class PassportUpdateView(AbonappPermissionMixin, UpdateView):
pi = form.save(commit=False) pi = form.save(commit=False)
pi.abon = self.abon pi.abon = self.abon
pi.save() 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) return super(PassportUpdateView, self).form_valid(form)
def get_success_url(self): def get_success_url(self):
@ -556,7 +581,7 @@ class PassportUpdateView(AbonappPermissionMixin, UpdateView):
return super(PassportUpdateView, self).get_context_data(**context) return super(PassportUpdateView, self).get_context_data(**context)
class IpUpdateView(AbonappPermissionMixin, UpdateView):
class IpUpdateView(LoginAdminPermissionMixin, UpdateView):
permission_required = 'abonapp.change_abon' permission_required = 'abonapp.change_abon'
form_class = forms.AddIpForm form_class = forms.AddIpForm
model = models.Abon model = models.Abon
@ -600,7 +625,8 @@ def chgroup_tariff(request, gid):
messages.success(request, _('Successfully saved')) messages.success(request, _('Successfully saved'))
return redirect('abonapp:ch_group_tariff', gid) return redirect('abonapp:ch_group_tariff', gid)
tariffs = Tariff.objects.all() 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', { return render(request, 'abonapp/group_tariffs.html', {
'group': grp, 'group': grp,
'seleted_tariffs': seleted_tariffs_id, 'seleted_tariffs': seleted_tariffs_id,
@ -623,7 +649,8 @@ def dev(request, gid: int, uname):
else: else:
abon_dev = abon.device abon_dev = abon.device
except Device.DoesNotExist: 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: except models.Abon.DoesNotExist:
messages.error(request, _('Abon does not exist')) messages.error(request, _('Abon does not exist'))
return redirect('abonapp:people_list', gid=gid) return redirect('abonapp:people_list', gid=gid)
@ -697,7 +724,8 @@ def charts(request, gid: int, uname):
return render(request, 'abonapp/charts.html', { return render(request, 'abonapp/charts.html', {
'group': abon.group, 'group': abon.group,
'abon': abon, '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, 'high': high,
'wantdate': wandate 'wantdate': wandate
}) })
@ -710,7 +738,8 @@ def charts(request, gid: int, uname):
def abon_ping(request, gid: int, uname): def abon_ping(request, gid: int, uname):
ip = request.GET.get('cmd_param') ip = request.GET.get('cmd_param')
status = False status = False
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _('no ping')
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _(
'no ping')
abon = get_object_or_404(models.Abon, username=uname) abon = get_object_or_404(models.Abon, username=uname)
try: try:
if ip is None: if ip is None:
@ -719,17 +748,21 @@ def abon_ping(request, gid: int, uname):
if abon.nas is None: if abon.nas is None:
return { return {
'status': 1, 'status': 1,
'dat': '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _('gateway required')
'dat': '<span class="glyphicon glyphicon-exclamation-sign">'
'</span> %s' % _('gateway required')
} }
mngr = abon.nas.get_nas_manager() mngr = abon.nas.get_nas_manager()
ping_result = mngr.ping(ip) ping_result = mngr.ping(ip)
if ping_result is None: if ping_result is None:
if ping(ip, 10): if ping(ip, 10):
status = True status = True
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ping ok')
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _(
'ping ok')
else: else:
if type(ping_result) is tuple: 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]} ping_result = {'all': ping_result[0], 'return': ping_result[1]}
if loses_percent > 1.0: if loses_percent > 1.0:
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _( text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _(
@ -742,7 +775,8 @@ def abon_ping(request, gid: int, uname):
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _( text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _(
'no ping, %(all)d/%(return)d loses') % ping_result 'no ping, %(all)d/%(return)d loses') % ping_result
else: else:
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ping ok') + ' ' + str(ping_result)
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _(
'ping ok') + ' ' + str(ping_result)
status = True status = True
except (NasFailedResult, lib.LogicError) as e: except (NasFailedResult, lib.LogicError) as e:
@ -773,11 +807,18 @@ def set_auto_continue_service(request, gid: int, uname):
@login_required @login_required
@only_admins @only_admins
def vcards(r): 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', 'username', 'fio', 'group__title', 'telephone',
'street__name', 'house' '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 = HttpResponse(content_type='text/x-vcard')
response['Content-Disposition'] = 'attachment; filename="contacts.vcard"' response['Content-Disposition'] = 'attachment; filename="contacts.vcard"'
tmpl = ("BEGIN:VCARD\r\n" tmpl = ("BEGIN:VCARD\r\n"
@ -802,7 +843,8 @@ def vcards(r):
for add_tel in additional_tels.iterator(): for add_tel in additional_tels.iterator():
abon = add_tel.abon abon = add_tel.abon
yield tmpl % { 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, 'group_name': abon.group.title,
'abon_telephone': add_tel.telephone, 'abon_telephone': add_tel.telephone,
'street': abon.street.name if abon.street else '', 'street': abon.street.name if abon.street else '',
@ -818,13 +860,16 @@ class DialsListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList):
template_name = 'abonapp/dial_log.html' template_name = 'abonapp/dial_log.html'
def get_queryset(self): 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): if not self.request.user.has_perm('group_app.view_group', abon.group):
raise PermissionDenied raise PermissionDenied
self.abon = abon self.abon = abon
if abon.telephone is not None and abon.telephone != '': if abon.telephone is not None and abon.telephone != '':
tel = abon.telephone.replace('+', '') 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( logs = AsteriskCDR.objects.filter(
Q(src__contains=tel) | Q(dst__contains=tel) | Q(src__contains=tel) | Q(dst__contains=tel) |
Q(src__in=additional_tels) | Q(dst__in=additional_tels) Q(src__in=additional_tels) | Q(dst__in=additional_tels)
@ -840,9 +885,12 @@ class DialsListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList):
return context return context
def render_to_response(self, context, **response_kwargs): 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): def get(self, request, *args, **kwargs):
try: try:
@ -872,20 +920,25 @@ def save_user_dev_port(request, gid: int, uname):
port = DevPort.objects.get(pk=user_port) port = DevPort.objects.get(pk=user_port)
if abon.device is not None: if abon.device is not None:
try: 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: 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, _( messages.error(request, _(
"<a href='%(user_url)s'>%(user_name)s</a> already pinned to this port on this device") % { "<a href='%(user_url)s'>%(user_name)s</a> 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) return redirect('abonapp:abon_home', gid, uname)
except models.Abon.DoesNotExist: except models.Abon.DoesNotExist:
pass pass
except models.Abon.MultipleObjectsReturned: 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 abon.dev_port = port
if abon.is_dynamic_ip != is_dynamic_ip: if abon.is_dynamic_ip != is_dynamic_ip:
@ -929,7 +982,8 @@ def street_add(request, gid):
def street_edit(request, gid): def street_edit(request, gid):
try: try:
if request.method == 'POST': 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 = models.AbonStreet.objects.get(pk=sid)
street.name = sname street.name = sname
street.save() street.save()
@ -1015,7 +1069,8 @@ def tel_del(request, gid: int, uname):
tid = lib.safe_int(request.GET.get('tid')) tid = lib.safe_int(request.GET.get('tid'))
tel = models.AdditionalTelephone.objects.get(pk=tid) tel = models.AdditionalTelephone.objects.get(pk=tid)
tel.delete() tel.delete()
messages.success(request, _('Additional telephone successfully deleted'))
messages.success(request,
_('Additional telephone successfully deleted'))
except models.AdditionalTelephone.DoesNotExist: except models.AdditionalTelephone.DoesNotExist:
messages.error(request, _('Telephone not found')) messages.error(request, _('Telephone not found'))
return redirect('abonapp:abon_home', gid, uname) 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')) @permission_required('group_app.view_group', (Group, 'pk', 'gid'))
def phonebook(request, gid): def phonebook(request, gid):
res_format = request.GET.get('f') 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) telephones = tuple(t1) + tuple(t2)
if res_format == 'csv': if res_format == 'csv':
import csv import csv
@ -1055,19 +1119,24 @@ def abon_export(request, gid):
if frm.is_valid(): if frm.is_valid():
cleaned_data = frm.clean() cleaned_data = frm.clean()
fields = cleaned_data.get('fields') 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': if res_format == 'csv':
import csv import csv
response = HttpResponse(content_type='text/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) 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) writer.writerow(display_values)
for row in subscribers: for row in subscribers:
writer.writerow(row) writer.writerow(row)
return response return response
else: 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') return redirect('abonapp:group_list')
else: else:
messages.error(request, _('fix form errors')) messages.error(request, _('fix form errors'))
@ -1091,7 +1160,8 @@ def fin_report(request):
response['Content-Disposition'] = 'attachment; filename="report.csv"' response['Content-Disposition'] = 'attachment; filename="report.csv"'
writer = csv.writer(response, quoting=csv.QUOTE_NONNUMERIC) writer = csv.writer(response, quoting=csv.QUOTE_NONNUMERIC)
for row in q: 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 response
return render(request, 'abonapp/fin_report.html', { return render(request, 'abonapp/fin_report.html', {
'logs': q 'logs': q
@ -1109,9 +1179,11 @@ def add_edit_periodic_pay(request, gid: int, uname, periodic_pay_id=0):
else: else:
if not request.user.has_perm('abonapp.change_periodicpayforid'): if not request.user.has_perm('abonapp.change_periodicpayforid'):
raise PermissionDenied 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': 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(): if frm.is_valid():
abon = get_object_or_404(models.Abon, username=uname) abon = get_object_or_404(models.Abon, username=uname)
inst = frm.save(commit=False) 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('group_app.view_group', (Group, 'pk', 'gid'))
@permission_required('abonapp.delete_periodicpayforid') @permission_required('abonapp.delete_periodicpayforid')
def del_periodic_pay(request, gid: int, uname, periodic_pay_id): 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: if periodic_pay_instance.account.username != uname:
uname = periodic_pay_instance.account.username uname = periodic_pay_instance.account.username
periodic_pay_instance.delete() 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) return redirect('abonapp:abon_services', gid, uname)
class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView):
class EditSibscriberMarkers(LoginAdminPermissionMixin, UpdateView):
permission_required = 'abonapp.change_abon' permission_required = 'abonapp.change_abon'
http_method_names = ('get', 'post') http_method_names = ('get', 'post')
template_name = 'abonapp/modal_user_markers.html' template_name = 'abonapp/modal_user_markers.html'
@ -1154,7 +1227,8 @@ class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try: try:
return super(EditSibscriberMarkers, self).dispatch(request, *args, **kwargs)
return super(EditSibscriberMarkers, self).dispatch(request, *args,
**kwargs)
except ValidationError as e: except ValidationError as e:
messages.error(request, e) messages.error(request, e)
return self.render_to_response(self.get_context_data()) return self.render_to_response(self.get_context_data())
@ -1171,7 +1245,8 @@ class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView):
def form_valid(self, form): def form_valid(self, form):
v = super(EditSibscriberMarkers, self).form_valid(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 return v
@ -1202,7 +1277,11 @@ def attach_nas(request, gid):
abons = models.Abon.objects.filter(group__id=gid) abons = models.Abon.objects.filter(group__id=gid)
if abons.exists(): if abons.exists():
abons.update(nas=nas) 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') return redirect('abonapp:group_list')
else: else:
messages.warning(request, _('Users not found')) messages.warning(request, _('Users not found'))
@ -1220,16 +1299,17 @@ def attach_nas(request, gid):
@json_view @json_view
def abons(request): def abons(request):
ablist = ({ 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 = ({ 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 = { data = {
'subscribers': ablist, 'subscribers': ablist,
@ -1247,7 +1327,9 @@ def search_abon(request):
if not word: if not word:
return None return None
results = models.Abon.objects.filter(fio__icontains=word)[:8] 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): class DhcpLever(SecureApiView):
@ -1370,7 +1452,8 @@ class DublicatePay(SecureApiView):
if pays.count() > 0: if pays.count() > 0:
return self._bad_ret(-100) 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',)) abon.save(update_fields=('ballance',))
models.AllTimePayLog.objects.create( models.AllTimePayLog.objects.create(

14
devapp/templates/devapp/custom_dev_page/generic_switch.html

@ -125,11 +125,17 @@
</tbody> </tbody>
<tfoot> <tfoot>
<tr> <tr>
<td colspan="4" class="btn-group">
<td colspan="4">
{% if perms.devapp.add_port %} {% if perms.devapp.add_port %}
<a href="{% url 'devapp:add_ports' dev.group.pk dev.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add ports' %}
</a>
{% if ports %}
<a href="{% url 'devapp:add_ports' dev.group.pk dev.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add ports' %}
</a>
{% else %}
<a href="{% url 'devapp:add_port' dev.group.pk dev.pk %}" class="btn btn-sm btn-default btn-modal">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add ports' %}
</a>
{% endif %}
{% endif %} {% endif %}
</td> </td>
</tr> </tr>

50
devapp/urls.py

@ -5,34 +5,52 @@ app_name = 'devapp'
urlpatterns = [ urlpatterns = [
path('', views.GroupsListView.as_view(), name='group_list'), 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('fix_onu/', views.fix_onu, name='fix_onu'),
path('<int:group_id>/', views.DevicesListView.as_view(), name='devs'), path('<int:group_id>/', views.DevicesListView.as_view(), name='devs'),
path('<int:group_id>/add/', views.DeviceCreateView.as_view(), name='add'), path('<int:group_id>/add/', views.DeviceCreateView.as_view(), name='add'),
path('<int:group_id>/<int:device_id>/', views.devview, name='view'), path('<int:group_id>/<int:device_id>/', views.devview, name='view'),
path('<int:group_id>/<int:device_id>/del/', views.DeviceDeleteView.as_view(), name='del'),
path('<int:group_id>/<int:device_id>/add/', views.add_single_port, name='add_port'),
path('<int:group_id>/<int:device_id>/edit/', views.DeviceUpdate.as_view(), name='edit'),
path('<int:group_id>/<int:device_id>/edit_extra/', views.DeviceUpdateExtra.as_view(), name='extra_data_edit'),
path('<int:group_id>/<int:device_id>/ports/<int:port_id>/fix_port_conflict/', views.fix_port_conflict,
path('<int:group_id>/<int:device_id>/del/',
views.DeviceDeleteView.as_view(), name='del'),
path('<int:group_id>/<int:device_id>/add/', views.add_single_port,
name='add_port'),
path('<int:group_id>/<int:device_id>/edit/', views.DeviceUpdate.as_view(),
name='edit'),
path('<int:group_id>/<int:device_id>/edit_extra/',
views.DeviceUpdateExtra.as_view(), name='extra_data_edit'),
path(
'<int:group_id>/<int:device_id>/ports/<int:port_id>/fix_port_conflict/',
views.fix_port_conflict,
name='fix_port_conflict'), name='fix_port_conflict'),
path('<int:group_id>/<int:device_id>/ports/<int:port_id>/show_subscriber_on_port/',
path(
'<int:group_id>/<int:device_id>/ports/<int:port_id>/show_subscriber_on_port/',
views.ShowSubscriberOnPort.as_view(), name='show_subscriber_on_port'), views.ShowSubscriberOnPort.as_view(), name='show_subscriber_on_port'),
path('<int:group_id>/<int:device_id>/ports_add/', views.add_ports, name='add_ports'),
path('<int:group_id>/<int:device_id>/register_device/', views.register_device, name='dev_register'),
re_path('^(\d+)/(?P<device_id>\d+)/(?P<port_id>\d+)_(?P<status>[0-1]{1})$', views.toggle_port, name='port_toggle'),
path('<int:group_id>/<int:device_id>/<int:port_id>/del/', views.delete_single_port, name='del_port'),
path('<int:group_id>/<int:device_id>/<int:port_id>/edit/', views.edit_single_port, name='edit_port'),
path('fix_device_group/<int:device_id>/', views.fix_device_group, name='fix_device_group'),
path('<int:group_id>/<int:device_id>/ports_add/', views.add_ports,
name='add_ports'),
path('<int:group_id>/<int:device_id>/register_device/',
views.register_device, name='dev_register'),
re_path('^(\d+)/(?P<device_id>\d+)/(?P<port_id>\d+)_(?P<status>[0-1]{1})$',
views.toggle_port, name='port_toggle'),
path('<int:group_id>/<int:device_id>/<int:port_id>/del/',
views.delete_single_port, name='del_port'),
path('<int:group_id>/<int:device_id>/<int:port_id>/edit/',
views.edit_single_port, name='edit_port'),
path('fix_device_group/<int:device_id>/', views.fix_device_group,
name='fix_device_group'),
path('search_dev/', views.search_dev), path('search_dev/', views.search_dev),
# ZTE ports under fibers # ZTE ports under fibers
path('<int:group_id>/<int:device_id>/<int:fiber_id>/', views.zte_port_view_uncfg, name='zte_port_view_uncfg'),
path('<int:group_id>/<int:device_id>/<int:fiber_id>/',
views.zte_port_view_uncfg, name='zte_port_view_uncfg'),
# Monitoring api # Monitoring api
path('on_device_event/', views.OnDeviceMonitoringEvent.as_view()), path('on_device_event/', views.OnDeviceMonitoringEvent.as_view()),
# Nagios mon generate # 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')
] ]

245
devapp/views.py

@ -1,47 +1,50 @@
import re import re
from ipaddress import ip_address 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.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Q, Count from django.db.models import Q, Count
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.shortcuts import render, redirect, get_object_or_404, resolve_url 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.decorators import method_decorator
from django.utils.translation import gettext_lazy as _, gettext from django.utils.translation import gettext_lazy as _, gettext
from easysnmp import EasySNMPTimeoutError, EasySNMPError
from django.views.generic import DetailView, DeleteView, UpdateView, CreateView 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 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 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 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 .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' context_object_name = 'devices'
template_name = 'devapp/devices.html' template_name = 'devapp/devices.html'
permission_required = 'devapp.view_device'
def get_queryset(self): def get_queryset(self):
group_id = safe_int(self.kwargs.get('group_id')) group_id = safe_int(self.kwargs.get('group_id'))
queryset = Device.objects.filter(group__pk=group_id) \ queryset = Device.objects.filter(group__pk=group_id) \
.select_related('group') \ .select_related('group') \
.only('comment', 'mac_addr', 'devtype', 'group', 'pk', 'ip_address')
.only('comment', 'mac_addr', 'devtype', 'group', 'pk',
'ip_address')
return queryset return queryset
def get_context_data(self, **kwargs): 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) context['group'] = get_object_or_404(Group, pk=group_id)
return context return context
@method_decorator(login_decs)
@method_decorator(permission_required('devapp.view_device'))
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try: try:
response = super(DevicesListView, self).dispatch(request, *args, **kwargs)
response = super(DevicesListView, self).dispatch(request, *args,
**kwargs)
except (DeviceDBException, DeviceMonitoringException) as e: except (DeviceDBException, DeviceMonitoringException) as e:
messages.error(request, e) messages.error(request, e)
response = HttpResponse('Error') response = HttpResponse('Error')
return response 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' context_object_name = 'devices'
template_name = 'devapp/devices_null_group.html' 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 model = Device
pk_url_kwarg = 'device_id' pk_url_kwarg = 'device_id'
permission_required = 'devapp.delete_device'
def get_success_url(self): 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): def delete(self, request, *args, **kwargs):
res = super().delete(request, *args, **kwargs) res = super().delete(request, *args, **kwargs)
@ -93,9 +97,7 @@ class DeviceDeleteView(DeleteView):
return res 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' template_name = 'devapp/dev.html'
context_object_name = 'dev' context_object_name = 'dev'
model = Device model = Device
@ -103,6 +105,7 @@ class DeviceUpdate(UpdateView):
pk_url_kwarg = 'device_id' pk_url_kwarg = 'device_id'
device_group = None device_group = None
already_dev = None already_dev = None
permission_required = 'devapp.view_device'
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
if not request.user.has_perm('devapp.change_device'): if not request.user.has_perm('devapp.change_device'):
@ -120,13 +123,17 @@ class DeviceUpdate(UpdateView):
# check if that device is exist # check if that device is exist
device_id = self.kwargs.get(self.pk_url_kwarg) device_id = self.kwargs.get(self.pk_url_kwarg)
try: 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 self.already_dev = already_dev
if already_dev.group: 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: 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) return redirect('devapp:fix_device_group', already_dev.pk)
except Device.DoesNotExist: except Device.DoesNotExist:
pass pass
@ -148,7 +155,8 @@ class DeviceUpdate(UpdateView):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def form_invalid(self, form): 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) return super().form_invalid(form)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -159,37 +167,41 @@ class DeviceUpdate(UpdateView):
return context 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' template_name = 'devapp/add_dev.html'
context_object_name = 'dev' context_object_name = 'dev'
model = Device model = Device
form_class = DeviceForm form_class = DeviceForm
permission_required = 'devapp.add_device'
device_group = None device_group = None
already_dev = None already_dev = None
def form_valid(self, form): def form_valid(self, form):
# check if that device is exist # check if that device is exist
try: 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 self.already_dev = already_dev
if already_dev.group: 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: 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) return redirect('devapp:fix_device_group', already_dev.pk)
except Device.DoesNotExist: except Device.DoesNotExist:
pass pass
r = super().form_valid(form) r = super().form_valid(form)
# change device info in dhcpd.conf # change device info in dhcpd.conf
try: 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() self.object.update_dhcp()
messages.success(self.request, _('Device info has been saved')) messages.success(self.request, _('Device info has been saved'))
except PermissionError as e: except PermissionError as e:
@ -221,17 +233,17 @@ class DeviceCreateView(CreateView):
context['group'] = self.device_group context['group'] = self.device_group
context['already_dev'] = self.already_dev context['already_dev'] = self.already_dev
parent_device_id = self.request.GET.get('pdev') 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 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' template_name = 'devapp/modal_device_extra_edit.html'
model = Device model = Device
form_class = DeviceExtraDataForm form_class = DeviceExtraDataForm
pk_url_kwarg = 'device_id' pk_url_kwarg = 'device_id'
permission_required = 'devapp.change_device'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -240,12 +252,14 @@ class DeviceUpdateExtra(UpdateView):
def form_valid(self, form): def form_valid(self, form):
r = super().form_valid(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 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' template_name = 'devapp/manage_ports/modal_show_subscriber_on_port.html'
http_method_names = ('get',) http_method_names = ('get',)
@ -260,7 +274,9 @@ class ShowSubscriberOnPort(global_base_views.RedirectWhenErrorMixin, DetailView)
errmsg = gettext('More than one subscriber on device port') errmsg = gettext('More than one subscriber on device port')
# messages.error(self.request, errmsg) # messages.error(self.request, errmsg)
raise global_base_views.RedirectWhenError( 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), port_id=port_id),
errmsg errmsg
) )
@ -292,7 +308,8 @@ def add_ports(request, group_id: int, device_id: int):
res_ports = list() res_ports = list()
try: try:
if device.group is None: 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) return redirect('devapp:fix_device_group', device.pk)
if request.method == 'POST': if request.method == 'POST':
ports = zip( 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 = 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() manager = device.get_manager_object()
ports = manager.get_ports() ports = manager.get_ports()
@ -371,16 +389,18 @@ def edit_single_port(request, group_id: int, device_id: int, port_id: int):
frm.save() frm.save()
messages.success(request, _('Port successfully saved')) messages.success(request, _('Port successfully saved'))
else: 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) return redirect('devapp:view', group_id, device_id)
frm = PortForm(instance=port) 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: except Port.DoesNotExist:
messages.error(request, _('Port does not exist')) messages.error(request, _('Port does not exist'))
except (DeviceDBException, DuplicateEntry) as e: except (DeviceDBException, DuplicateEntry) as e:
@ -401,17 +421,19 @@ def add_single_port(request, group_id, device_id):
messages.success(request, _('Port successfully saved')) messages.success(request, _('Port successfully saved'))
return redirect('devapp:view', group_id, device_id) return redirect('devapp:view', group_id, device_id)
else: else:
messages.error(request, _('Form is invalid, check fields and try again'))
messages.error(request, _(
'Form is invalid, check fields and try again'))
else: else:
frm = PortForm(initial={ frm = PortForm(initial={
'num': request.GET.get('n'), 'num': request.GET.get('n'),
'descr': request.GET.get('t') '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: except Device.DoesNotExist:
messages.error(request, _('Device does not exist')) messages.error(request, _('Device does not exist'))
except (DeviceDBException, DuplicateEntry) as e: except (DeviceDBException, DuplicateEntry) as e:
@ -433,12 +455,13 @@ def devview(request, group_id: int, device_id: int):
template_name = 'generic_switch.html' template_name = 'generic_switch.html'
try: try:
if device.ip_address: if device.ip_address:
if not ping(device.ip_address):
if not ping(str(device.ip_address)):
messages.error(request, _('Dot was not pinged')) messages.error(request, _('Dot was not pinged'))
if device.man_passw: if device.man_passw:
manager = device.get_manager_object() manager = device.get_manager_object()
ports = tuple(manager.get_ports()) 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]) messages.error(request, ports[0])
ports = ports[1] ports = ports[1]
template_name = manager.get_template_name() template_name = manager.get_template_name()
@ -449,10 +472,12 @@ def devview(request, group_id: int, device_id: int):
'ports': ports, 'ports': ports,
'dev_accs': Abon.objects.filter(device=device), 'dev_accs': Abon.objects.filter(device=device),
'dev_manager': manager, '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: 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: except (DeviceDBException, DeviceImplementationError) as e:
messages.error(request, e) messages.error(request, e)
return render(request, 'devapp/custom_dev_page/' + template_name, { 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) zte_olt_device = get_object_or_404(Device, id=device_id)
manager = zte_olt_device.get_manager_object() manager = zte_olt_device.get_manager_object()
onu_list = manager.get_units_unregistered(fiber_id) 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 @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')) messages.error(request, _('wait for a reply from the SNMP Timeout'))
except EasySNMPError as e: except EasySNMPError as e:
messages.error(request, 'EasySNMPError: %s' % 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' context_object_name = 'groups'
template_name = 'devapp/group_list.html' template_name = 'devapp/group_list.html'
model = Group model = Group
def get_queryset(self): def get_queryset(self):
groups = super(GroupsListView, self).get_queryset() 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) accept_global_perms=False)
return groups return groups
@ -528,11 +556,13 @@ def search_dev(request):
qs |= Q(ip_address=str(ip)) qs |= Q(ip_address=str(ip))
except ValueError: except ValueError:
pass 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({ 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 return results
@ -549,9 +579,11 @@ def fix_device_group(request, device_id):
messages.success(request, _('Device fixed')) messages.success(request, _('Device fixed'))
return redirect('devapp:devs', ch_dev.group.pk) return redirect('devapp:devs', ch_dev.group.pk)
else: else:
messages.error(request, _('Please attach group for device'))
messages.error(request,
_('Please attach group for device'))
else: else:
messages.error(request, _('Form is invalid, check fields and try again'))
messages.error(request, _(
'Form is invalid, check fields and try again'))
else: else:
frm = DeviceForm(instance=device) frm = DeviceForm(instance=device)
except ValueError: except ValueError:
@ -577,7 +609,8 @@ def fix_onu(request):
manobj = parent.get_manager_object() manobj = parent.get_manager_object()
ports = manobj.get_list_keyval('.1.3.6.1.4.1.3320.101.10.1.1.3') ports = manobj.get_list_keyval('.1.3.6.1.4.1.3320.101.10.1.1.3')
text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' % \ text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' % \
(_('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: for srcmac, snmpnum in ports:
# convert bytes mac address to str presentation mac address # convert bytes mac address to str presentation mac address
real_mac = ':'.join('%x' % ord(i) for i in srcmac) real_mac = ':'.join('%x' % ord(i) for i in srcmac)
@ -585,7 +618,8 @@ def fix_onu(request):
onu.snmp_extra = str(snmpnum) onu.snmp_extra = str(snmpnum)
onu.save(update_fields=('snmp_extra',)) onu.save(update_fields=('snmp_extra',))
status = 0 status = 0
text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' % _('Fixed')
text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' % _(
'Fixed')
break break
else: else:
text += '\n%s' % _('Parent device not found') 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): if not re.match(MAC_ADDR_REGEX, dev_mac):
return {'text': 'mac address %s is not valid' % 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: if device_down is None:
return {'text': 'Devices with mac %s does not exist' % dev_mac} 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',)) device_down.save(update_fields=('status',))
if not device_down.is_noticeable: 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() names = list()
for recipient in recipients.iterator(): for recipient in recipients.iterator():
@ -688,7 +727,8 @@ def nagios_objects_conf(request):
except DeviceImplementationError: except DeviceImplementationError:
pass 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') \ .select_related('parent_dev') \
.only('ip_address', 'comment', 'parent_dev') .only('ip_address', 'comment', 'parent_dev')
confs = map(getconf, devices_queryset) confs = map(getconf, devices_queryset)
@ -710,7 +750,8 @@ class DevicesGetListView(global_base_views.SecureApiView):
devs = Device.objects.all() devs = Device.objects.all()
else: else:
devs = Device.objects.filter(devtype=device_type) 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: for r in res:
if isinstance(r['mac_addr'], EUI): if isinstance(r['mac_addr'], EUI):
r['mac_addr'] = int(r['mac_addr']) r['mac_addr'] = int(r['mac_addr'])
@ -726,6 +767,7 @@ def register_device(request, group_id: int, device_id: int):
'<span class="glyphicon glyphicon-%s"></span>' % icon, '<span class="glyphicon glyphicon-%s"></span>' % icon,
'<span class="hidden-xs">%s</span>' % msg '<span class="hidden-xs">%s</span>' % msg
)) ))
device = get_object_or_404(Device, pk=device_id) device = get_object_or_404(Device, pk=device_id)
status = 1 status = 1
try: try:
@ -734,7 +776,8 @@ def register_device(request, group_id: int, device_id: int):
except OnuZteRegisterError: except OnuZteRegisterError:
text = format_msg(gettext('Unregistered onu not found'), 'eye-close') text = format_msg(gettext('Unregistered onu not found'), 'eye-close')
except ZteOltLoginFailed: 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: except (ConnectionRefusedError, ZteOltConsoleError) as e:
text = format_msg(e, 'exclamation-sign') text = format_msg(e, 'exclamation-sign')
except DeviceImplementationError as e: except DeviceImplementationError as e:

12
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): class OnlyAdminsMixin(AccessMixin):
@ -7,3 +8,12 @@ class OnlyAdminsMixin(AccessMixin):
if not request.user.is_admin: if not request.user.is_admin:
return self.handle_no_permission() return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
class LoginAdminMixin(LoginRequiredMixin, OnlyAdminsMixin):
pass
class LoginAdminPermissionMixin(LoginRequiredMixin, OnlyAdminsMixin,
PermissionRequiredMixin):
return_403 = True
Loading…
Cancel
Save