Browse Source

rename nas_app to gw_app

devel
Dmitry Novikov 7 years ago
parent
commit
c9f5feb8c6
  1. 2
      Doc.txt
  2. 2
      abonapp/forms.py
  3. 4
      abonapp/locale/ru/LC_MESSAGES/django.po
  4. 4
      abonapp/migrations/0003_abon_nas.py
  5. 12
      abonapp/models.py
  6. 2
      abonapp/templates/abonapp/editAbon.html
  7. 8
      abonapp/views.py
  8. 2
      clientsideapp/views.py
  9. 2
      djing/settings.py
  10. 2
      djing/urls.py
  11. 6
      docs/dev.md
  12. 1
      gw_app/__init__.py
  13. 0
      gw_app/admin.py
  14. 5
      gw_app/apps.py
  15. 2
      gw_app/forms.py
  16. 109
      gw_app/locale/ru/LC_MESSAGES/django.po
  17. 0
      gw_app/migrations/0001_initial.py
  18. 0
      gw_app/migrations/__init__.py
  19. 4
      gw_app/models.py
  20. 9
      gw_app/nas_managers/__init__.py
  21. 10
      gw_app/nas_managers/core.py
  22. 4
      gw_app/nas_managers/mod_mikrotik.py
  23. 0
      gw_app/nas_managers/structs.py
  24. 4
      gw_app/templates/gw_app/nasmodel_add.html
  25. 2
      gw_app/templates/gw_app/nasmodel_confirm_delete.html
  26. 4
      gw_app/templates/gw_app/nasmodel_list.html
  27. 8
      gw_app/templates/gw_app/nasmodel_update.html
  28. 20
      gw_app/tests.py
  29. 4
      gw_app/urls.py
  30. 28
      gw_app/views.py
  31. 5
      nas_app/apps.py
  32. 0
      nas_app/migrations/__init__.py
  33. 9
      nas_app/nas_managers/__init__.py
  34. 6
      periodic.py
  35. 6
      templates/base.html

2
Doc.txt

@ -12,7 +12,7 @@
код из 2х букв, сочетание должно быть уникальным код из 2х букв, сочетание должно быть уникальным
и ваш класс для своей логики расчёта тарифа и ваш класс для своей логики расчёта тарифа
ВАЖНО! Для отработки своевременного выключения услуги, время на сервере биллинга и NAS должно быть настроено точно.
ВАЖНО! Для отработки своевременного выключения услуги, время на сервере биллинга и шлюза должно быть настроено точно.
Таблицу кеша статистики лучше сделать в памяти т.к. будет часто обновляться Таблицу кеша статистики лучше сделать в памяти т.к. будет часто обновляться
ALTER TABLE flowcache ENGINE=MEMORY; ALTER TABLE flowcache ENGINE=MEMORY;

2
abonapp/forms.py

@ -6,7 +6,7 @@ from string import digits, ascii_lowercase
from djing.lib import LogicError from djing.lib import LogicError
from ip_pool.models import NetworkModel from ip_pool.models import NetworkModel
from nas_app.models import NASModel
from gw_app.models import NASModel
from . import models from . import models
from django.conf import settings from django.conf import settings

4
abonapp/locale/ru/LC_MESSAGES/django.po

@ -204,8 +204,8 @@ msgstr "Покупка тарифного плана через админку"
#: models.py:238 models.py:255 models.py:272 views.py:684 views.py:1132 #: models.py:238 models.py:255 models.py:272 views.py:684 views.py:1132
#: views.py:1175 #: views.py:1175
msgid "NAS required"
msgstr "Необходимо выбрать NAS"
msgid "gateway required"
msgstr "Необходимо выбрать шлюз"
#: models.py:296 #: models.py:296
msgid "Pasport serial" msgid "Pasport serial"

4
abonapp/migrations/0003_abon_nas.py

@ -9,7 +9,7 @@ import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('nas_app', '0001_initial'),
('gw_app', '0001_initial'),
('abonapp', '0002_auto_20180808_1448'), ('abonapp', '0002_auto_20180808_1448'),
] ]
@ -17,6 +17,6 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='abon', model_name='abon',
name='nas', name='nas',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='nas_app.NASModel', verbose_name='Network access server'),
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='gw_app.NASModel', verbose_name='Network access server'),
), ),
] ]

12
abonapp/models.py

@ -12,7 +12,7 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _, gettext from django.utils.translation import ugettext_lazy as _, gettext
from accounts_app.models import UserProfile, MyUserManager, BaseAccount from accounts_app.models import UserProfile, MyUserManager, BaseAccount
from nas_app.nas_managers import SubnetQueue, NasFailedResult, NasNetworkError
from gw_app.nas_managers import SubnetQueue, NasFailedResult, NasNetworkError
from group_app.models import Group from group_app.models import Group
from djing.lib import LogicError from djing.lib import LogicError
from ip_pool.models import NetworkModel from ip_pool.models import NetworkModel
@ -96,7 +96,7 @@ class Abon(BaseAccount):
device = models.ForeignKey('devapp.Device', null=True, blank=True, on_delete=models.SET_NULL) device = models.ForeignKey('devapp.Device', null=True, blank=True, on_delete=models.SET_NULL)
dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL) dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL)
is_dynamic_ip = models.BooleanField(_('Is dynamic ip'), default=False) is_dynamic_ip = models.BooleanField(_('Is dynamic ip'), default=False)
nas = models.ForeignKey('nas_app.NASModel', null=True, blank=True, on_delete=models.SET_NULL,
nas = models.ForeignKey('gw_app.NASModel', null=True, blank=True, on_delete=models.SET_NULL,
verbose_name=_('Network access server'), default=None) verbose_name=_('Network access server'), default=None)
autoconnect_service = models.BooleanField(_('Automatically connect next service'), default=False) autoconnect_service = models.BooleanField(_('Automatically connect next service'), default=False)
@ -243,11 +243,11 @@ class Abon(BaseAccount):
def nas_sync_self(self) -> Optional[Exception]: def nas_sync_self(self) -> Optional[Exception]:
""" """
Synchronize user with gateway(NAS)
Synchronize user with gateway
:return: :return:
""" """
if self.nas is None: if self.nas is None:
raise LogicError(_('NAS required'))
raise LogicError(_('gateway required'))
try: try:
agent_abon = self.build_agent_struct() agent_abon = self.build_agent_struct()
if agent_abon is not None: if agent_abon is not None:
@ -265,7 +265,7 @@ class Abon(BaseAccount):
:return: :return:
""" """
if self.nas is None: if self.nas is None:
raise LogicError(_('NAS required'))
raise LogicError(_('gateway required'))
try: try:
agent_abon = self.build_agent_struct() agent_abon = self.build_agent_struct()
if agent_abon is not None: if agent_abon is not None:
@ -283,7 +283,7 @@ class Abon(BaseAccount):
:return: :return:
""" """
if self.nas is None: if self.nas is None:
raise LogicError(_('NAS required'))
raise LogicError(_('gateway required'))
try: try:
agent_abon = self.build_agent_struct() agent_abon = self.build_agent_struct()
if agent_abon is not None: if agent_abon is not None:

2
abonapp/templates/abonapp/editAbon.html

@ -54,7 +54,7 @@
}); });
</script> </script>
{% if perms.nas_app.change_nasmodel %}
{% if perms.gw_app.change_nasmodel %}
{% bootstrap_field form.nas form_group_class='form-group-sm' %} {% bootstrap_field form.nas form_group_class='form-group-sm' %}
{% endif %} {% endif %}
{% bootstrap_field form.description form_group_class='form-group-sm' %} {% bootstrap_field form.description form_group_class='form-group-sm' %}

8
abonapp/views.py

@ -16,9 +16,9 @@ from django.views.generic import ListView, UpdateView, CreateView, DeleteView
from django.conf import settings from django.conf import settings
from agent.commands.dhcp import dhcp_commit, dhcp_expiry, dhcp_release from agent.commands.dhcp import dhcp_commit, dhcp_expiry, dhcp_release
from nas_app.models import NASModel
from gw_app.models import NASModel
from tariff_app.models import Tariff from tariff_app.models import Tariff
from nas_app.nas_managers import NasFailedResult, NasNetworkError
from gw_app.nas_managers import NasFailedResult, NasNetworkError
from . import forms from . import forms
from . import models from . import models
from devapp.models import Device, Port as DevPort from devapp.models import Device, Port as DevPort
@ -719,7 +719,7 @@ 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' % _('NAS 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)
@ -1181,7 +1181,7 @@ class EditSibscriberMarkers(AbonappPermissionMixin, UpdateView):
def user_session_free(request, gid: int, uname): def user_session_free(request, gid: int, uname):
abon = get_object_or_404(models.Abon, username=uname) abon = get_object_or_404(models.Abon, username=uname)
if abon.nas is None: if abon.nas is None:
messages.error(request, _('NAS required'))
messages.error(request, _('gateway required'))
return redirect('abonapp:abon_home', gid, uname) return redirect('abonapp:abon_home', gid, uname)
if abon.ip_address: if abon.ip_address:
abon.free_ip_addr() abon.free_ip_addr()

2
clientsideapp/views.py

@ -9,7 +9,7 @@ from djing.lib.decorators import json_view
from tariff_app.models import Tariff from tariff_app.models import Tariff
from taskapp.models import Task from taskapp.models import Task
from djing.lib import LogicError from djing.lib import LogicError
from nas_app.nas_managers import NasFailedResult, NasNetworkError
from gw_app.nas_managers import NasFailedResult, NasNetworkError
@login_required @login_required

2
djing/settings.py

@ -43,7 +43,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'ip_pool', 'ip_pool',
'accounts_app', 'accounts_app',
'nas_app',
'gw_app',
'abonapp', 'abonapp',
'tariff_app', 'tariff_app',
'searchapp', 'searchapp',

2
djing/urls.py

@ -18,7 +18,7 @@ urlpatterns = [
path('dialing/', include('dialing_app.urls', namespace='dialapp')), path('dialing/', include('dialing_app.urls', namespace='dialapp')),
path('groups/', include('group_app.urls', namespace='group_app')), path('groups/', include('group_app.urls', namespace='group_app')),
path('ip_pool/', include('ip_pool.urls', namespace='ip_pool')), path('ip_pool/', include('ip_pool.urls', namespace='ip_pool')),
path('nas/', include('nas_app.urls', namespace='nas_app'))
path('gw/', include('gw_app.urls', namespace='gw_app'))
# Switch language # Switch language
#path(r'i18n/', include('django.conf.urls.i18n')), #path(r'i18n/', include('django.conf.urls.i18n')),

6
docs/dev.md

@ -150,7 +150,7 @@ def terminal_pay(request):
Сейчас биллинг работает с Mikrotik в роли устройства для доступа абонентов в интернет. Сейчас биллинг работает с Mikrotik в роли устройства для доступа абонентов в интернет.
Как можно реализовать такой-же для вашего роутера, например на GNU/Linux. Как можно реализовать такой-же для вашего роутера, например на GNU/Linux.
Создадим файл *nas_app/nas_managers/mod_linux.py* и реализуем потомка для интерфейса *BaseTransmitter*.
Создадим файл *gw_app/nas_managers/mod_linux.py* и реализуем потомка для интерфейса *BaseTransmitter*.
Методы вашего класса будут вызываться биллингом для взаимодействия с сервером доступа абонентов в интернет(NAS). Методы вашего класса будут вызываться биллингом для взаимодействия с сервером доступа абонентов в интернет(NAS).
```python ```python
@ -229,7 +229,7 @@ class LinuxTransmitter(BaseTransmitter):
""" """
``` ```
Для того чтоб биллинг знал о вашем классе надо указать его в *nas_app/nas_managers/\_\_init\_\_.py*.
Для того чтоб биллинг знал о вашем классе надо указать его в *gw_app/nas_managers/\_\_init\_\_.py*.
Замените Замените
>from .mod_mikrotik import MikrotikTransmitter >from .mod_mikrotik import MikrotikTransmitter
@ -249,7 +249,7 @@ from .structs import TariffStruct, AbonStruct
Transmitter = LinuxTransmitter Transmitter = LinuxTransmitter
``` ```
Для примера, как вы наверное уже догадались, можно посмотреть реализацию для Mikrotik в файле *nas_app/nas_managers/mod_mikrotik.py*
Для примера, как вы наверное уже догадались, можно посмотреть реализацию для Mikrotik в файле *gw_app/nas_managers/mod_mikrotik.py*
Чтобы выводить в биллинге различные сообщения об ошибках есть 2 типа исключений: *NasFailedResult* и *NasNetworkError*. Чтобы выводить в биллинге различные сообщения об ошибках есть 2 типа исключений: *NasFailedResult* и *NasNetworkError*.
NasNetworkError, как понятно из названия, вызывается при проблемах в сети. А NasFailedResult при ошибочных кодах возврата из модуля на сервере NAS. NasNetworkError, как понятно из названия, вызывается при проблемах в сети. А NasFailedResult при ошибочных кодах возврата из модуля на сервере NAS.

1
gw_app/__init__.py

@ -0,0 +1 @@
default_app_config = 'gw_app.apps.GatewaysAppConfig'

0
nas_app/admin.py → gw_app/admin.py

5
gw_app/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class GatewaysAppConfig(AppConfig):
name = 'gw_app'

2
nas_app/forms.py → gw_app/forms.py

@ -1,7 +1,7 @@
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from nas_app.models import NASModel
from gw_app.models import NASModel
from djing import IP_ADDR_REGEX from djing import IP_ADDR_REGEX

109
nas_app/locale/ru/LC_MESSAGES/django.po → gw_app/locale/ru/LC_MESSAGES/django.po

@ -1,18 +1,15 @@
# SOME DESCRIPTIVE TITLE. # SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# Dmitry Novikov nerosketch@gmail.com, 2018.
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-18 13:53+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"POT-Creation-Date: 2018-10-29 11:52+0300\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: ru\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -20,27 +17,35 @@ msgstr ""
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n" "%100>=11 && n%100<=14)? 2 : 3);\n"
#: forms.py:16 tests.py:119
#: forms.py:19
msgid "Can be only one default gateway" msgid "Can be only one default gateway"
msgstr "Может быть только один сервер доступа по умолчанию" msgstr "Может быть только один сервер доступа по умолчанию"
#: models.py:12 templates/nas_app/nasmodel_list.html:25
#: models.py:12 templates/gw_app/nasmodel_list.html:25
msgid "Title" msgid "Title"
msgstr "Название" msgstr "Название"
#: models.py:13 templates/nas_app/nasmodel_list.html:26
#: models.py:13 templates/gw_app/nasmodel_list.html:26
msgid "Ip address" msgid "Ip address"
msgstr "IP адрес" msgstr "IP адрес"
#: models.py:14 templates/nas_app/nasmodel_list.html:27
#: models.py:14 templates/gw_app/nasmodel_list.html:27
msgid "Port" msgid "Port"
msgstr "Порт" msgstr "Порт"
#: models.py:15 templates/gw_app/nasmodel_list.html:28
msgid "Auth login"
msgstr "Логин для входа"
#: models.py:16 templates/gw_app/nasmodel_list.html:29
msgid "Auth password"
msgstr "Пароль для входа"
#: models.py:17 #: models.py:17
msgid "Type" msgid "Type"
msgstr "Тип" msgstr "Тип"
#: models.py:18 templates/nas_app/nasmodel_list.html:31
#: models.py:18 templates/gw_app/nasmodel_list.html:31
msgid "Is default" msgid "Is default"
msgstr "По умолчанию" msgstr "По умолчанию"
@ -48,49 +53,45 @@ msgstr "По умолчанию"
msgid "One of nas types implementation is not found" msgid "One of nas types implementation is not found"
msgstr "Не найден тип реализации NAS" msgstr "Не найден тип реализации NAS"
#: models.py:49
#: models.py:48
msgid "Network access server. Gateway" msgid "Network access server. Gateway"
msgstr "Сервер доступа в интернет(NAS, Шлюз)" msgstr "Сервер доступа в интернет(NAS, Шлюз)"
#: models.py:50
#: models.py:49
msgid "Network access servers. Gateways" msgid "Network access servers. Gateways"
msgstr "Серверы доступа в интернет" msgstr "Серверы доступа в интернет"
#: models.py:63 tests.py:194
#: models.py:59
msgid "You cannot remove default server" msgid "You cannot remove default server"
msgstr "Вы не можете удалить шлюз по умолчанию" msgstr "Вы не можете удалить шлюз по умолчанию"
#: nas_managers/mod_mikrotik.py:166
#: nas_managers/mod_mikrotik.py:171
msgid "Mikrotik NAS" msgid "Mikrotik NAS"
msgstr "" msgstr ""
#: nas_managers/mod_mikrotik.py:491
msgid "You cannot disable last session"
msgstr "Вы не можете выключить последнюю сессию"
#: templates/nas_app/nasmodel_add.html:8 templates/nas_app/nasmodel_list.html:7
#: templates/nas_app/nasmodel_update.html:8
#: templates/gw_app/nasmodel_add.html:7 templates/gw_app/nasmodel_list.html:7
#: templates/gw_app/nasmodel_update.html:7
msgid "Network access servers" msgid "Network access servers"
msgstr "Серверы доступа в интернет(NAS)" msgstr "Серверы доступа в интернет(NAS)"
#: templates/nas_app/nasmodel_add.html:9 templates/nas_app/nasmodel_add.html:20
#: templates/gw_app/nasmodel_add.html:8 templates/gw_app/nasmodel_add.html:19
msgid "Add gateway" msgid "Add gateway"
msgstr "Добавить шлюз" msgstr "Добавить шлюз"
#: templates/nas_app/nasmodel_add.html:14
#: templates/gw_app/nasmodel_add.html:13
msgid "Add new gateway" msgid "Add new gateway"
msgstr "Добавить новый шлюз" msgstr "Добавить новый шлюз"
#: templates/nas_app/nasmodel_add.html:26
#: templates/nas_app/nasmodel_update.html:27
#: templates/gw_app/nasmodel_add.html:25
#: templates/gw_app/nasmodel_update.html:26
msgid "Save" msgid "Save"
msgstr "Сохранить" msgstr "Сохранить"
#: templates/nas_app/nasmodel_confirm_delete.html:9
#: templates/gw_app/nasmodel_confirm_delete.html:9
msgid "Remove NAS" msgid "Remove NAS"
msgstr "Удалить NAS" msgstr "Удалить NAS"
#: templates/nas_app/nasmodel_confirm_delete.html:14
#: templates/gw_app/nasmodel_confirm_delete.html:14
msgid "" msgid ""
"If you remove this server, then all users than has been attached to them " "If you remove this server, then all users than has been attached to them "
"will lost parent NAS server." "will lost parent NAS server."
@ -98,73 +99,61 @@ msgstr ""
"Если вы удалите этот сервер, тогда все пользователи которые его используют " "Если вы удалите этот сервер, тогда все пользователи которые его используют "
"потеряют интернет от этого сервера" "потеряют интернет от этого сервера"
#: templates/nas_app/nasmodel_list.html:12
#: templates/gw_app/nasmodel_list.html:12
msgid "Gateways" msgid "Gateways"
msgstr "Шлюзы" msgstr "Шлюзы"
#: templates/nas_app/nasmodel_list.html:28
msgid "Auth login"
msgstr "Логин для входа"
#: templates/nas_app/nasmodel_list.html:29
msgid "Auth password"
msgstr "Пароль для входа"
#: templates/nas_app/nasmodel_list.html:30
#: templates/gw_app/nasmodel_list.html:30
msgid "NAS type" msgid "NAS type"
msgstr "Тип NAS" msgstr "Тип NAS"
#: templates/nas_app/nasmodel_list.html:41
#: templates/gw_app/nasmodel_list.html:41
msgid "View" msgid "View"
msgstr "Посмотреть" msgstr "Посмотреть"
#: templates/nas_app/nasmodel_list.html:49
#: templates/gw_app/nasmodel_list.html:49
msgid "You don't have gateways" msgid "You don't have gateways"
msgstr "У вас нет шлюзов" msgstr "У вас нет шлюзов"
#: templates/nas_app/nasmodel_list.html:55
#: templates/gw_app/nasmodel_list.html:55
msgid "Add" msgid "Add"
msgstr "Добавить" msgstr "Добавить"
#: templates/nas_app/nasmodel_update.html:9
#: templates/gw_app/nasmodel_update.html:8
msgid "Edit gateway" msgid "Edit gateway"
msgstr "Редактировать шлюз" msgstr "Редактировать шлюз"
#: templates/nas_app/nasmodel_update.html:14
#: templates/gw_app/nasmodel_update.html:13
msgid "Change gateways" msgid "Change gateways"
msgstr "Изменить шлюзы" msgstr "Изменить шлюзы"
#: templates/nas_app/nasmodel_update.html:20
#: templates/gw_app/nasmodel_update.html:19
msgid "Change gateway" msgid "Change gateway"
msgstr "Изменить шлюз" msgstr "Изменить шлюз"
#: templates/nas_app/nasmodel_update.html:31
#: templates/nas_app/nasmodel_update.html:35
#: templates/gw_app/nasmodel_update.html:30
#: templates/gw_app/nasmodel_update.html:34
msgid "Delete" msgid "Delete"
msgstr "Удалить" msgstr "Удалить"
#: templates/nas_app/nasmodel_update.html:34
#: templates/gw_app/nasmodel_update.html:33
msgid "Permission denied" msgid "Permission denied"
msgstr "Не достаточно прав" msgstr "Не достаточно прав"
#: tests.py:72 views.py:33
#: views.py:44
msgid "New NAS has been created" msgid "New NAS has been created"
msgstr "Новый NAS добавлен" msgstr "Новый NAS добавлен"
#: tests.py:86
#, python-format
#: views.py:63
msgid "Server successfully removed"
msgstr "Информация о сервере успешно удалена"
#: views.py:81
msgid "Update successfully"
msgstr "Обновлено успешно"
msgid "Ensure this value is less than or equal to %(limit_value)s." msgid "Ensure this value is less than or equal to %(limit_value)s."
msgstr "Убедитесь что значение меньше или равно %(limit_value)s." msgstr "Убедитесь что значение меньше или равно %(limit_value)s."
#: tests.py:104 tests.py:131
#, python-format
msgid "%(model_name)s with this %(field_label)s already exists." msgid "%(model_name)s with this %(field_label)s already exists."
msgstr "%(model_name)s с таким %(field_label)s уже существует." msgstr "%(model_name)s с таким %(field_label)s уже существует."
#: tests.py:154 views.py:65
msgid "Update successfully"
msgstr "Обновлено успешно"
#: tests.py:182 views.py:47
msgid "Server successfully removed"
msgstr "Информация о сервере успешно удалена"

0
nas_app/migrations/0001_initial.py → gw_app/migrations/0001_initial.py

0
nas_app/__init__.py → gw_app/migrations/__init__.py

4
nas_app/models.py → gw_app/models.py

@ -5,7 +5,7 @@ from django.shortcuts import resolve_url
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from djing.lib import MyChoicesAdapter from djing.lib import MyChoicesAdapter
from nas_app.nas_managers import NAS_TYPES
from gw_app.nas_managers import NAS_TYPES
class NASModel(models.Model): class NASModel(models.Model):
@ -38,7 +38,7 @@ class NASModel(models.Model):
return o return o
def get_absolute_url(self): def get_absolute_url(self):
return resolve_url('nas_app:edit', self.pk)
return resolve_url('gw_app:edit', self.pk)
def __str__(self): def __str__(self):
return self.title return self.title

9
gw_app/nas_managers/__init__.py

@ -0,0 +1,9 @@
from gw_app.nas_managers.mod_mikrotik import MikrotikTransmitter
from gw_app.nas_managers.core import NasNetworkError, NasFailedResult
from gw_app.nas_managers.structs import SubnetQueue
# Указываем какие реализации шлюзов у нас есть, это будет использоваться в
# web интерфейсе
NAS_TYPES = (
('mktk', MikrotikTransmitter),
)

10
nas_app/nas_managers/core.py → gw_app/nas_managers/core.py

@ -1,20 +1,20 @@
from abc import ABC, abstractmethod, abstractproperty from abc import ABC, abstractmethod, abstractproperty
from typing import Iterator, Tuple, Optional from typing import Iterator, Tuple, Optional
from djing import ping from djing import ping
from nas_app.nas_managers.structs import SubnetQueue, VectorQueue
from gw_app.nas_managers.structs import SubnetQueue, VectorQueue
# Raised if NAS has returned failed result
# Raised if gw has returned failed result
class NasFailedResult(Exception): class NasFailedResult(Exception):
pass pass
# Raised when is no connection to the NAS
# Raised when is no connection to the gw
class NasNetworkError(Exception): class NasNetworkError(Exception):
pass pass
# Communicate with NAS
# Communicate with gw
class BaseTransmitter(ABC): class BaseTransmitter(ABC):
@abstractproperty @abstractproperty
def description(self): def description(self):
@ -34,7 +34,7 @@ class BaseTransmitter(ABC):
@abstractmethod @abstractmethod
def add_user_range(self, queue_list: VectorQueue): def add_user_range(self, queue_list: VectorQueue):
"""add subscribers list to NAS
"""add subscribers list to gateway
:param queue_list: Vector of instances of subscribers :param queue_list: Vector of instances of subscribers
""" """

4
nas_app/nas_managers/mod_mikrotik.py → gw_app/nas_managers/mod_mikrotik.py

@ -9,8 +9,8 @@ from typing import Iterable, Optional, Tuple, Generator, Dict, Iterator
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from djing.lib.decorators import LazyInitMetaclass from djing.lib.decorators import LazyInitMetaclass
from nas_app.nas_managers import core
from nas_app.nas_managers import structs as i_structs
from gw_app.nas_managers import core
from gw_app.nas_managers import structs as i_structs
DEBUG = getattr(settings, 'DEBUG', False) DEBUG = getattr(settings, 'DEBUG', False)

0
nas_app/nas_managers/structs.py → gw_app/nas_managers/structs.py

4
nas_app/templates/nas_app/nasmodel_add.html → gw_app/templates/gw_app/nasmodel_add.html

@ -4,7 +4,7 @@
{% block breadcrumb %} {% block breadcrumb %}
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li> <li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'nas_app:home' %}">{% trans 'Network access servers' %}</a></li>
<li><a href="{% url 'gw_app:home' %}">{% trans 'Network access servers' %}</a></li>
<li class="active">{% trans 'Add gateway' %}</li> <li class="active">{% trans 'Add gateway' %}</li>
</ol> </ol>
{% endblock %} {% endblock %}
@ -19,7 +19,7 @@
<h3 class="panel-title">{% trans 'Add gateway' %}</h3> <h3 class="panel-title">{% trans 'Add gateway' %}</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form action="{% url 'nas_app:add' %}" method="post">{% csrf_token %}
<form action="{% url 'gw_app:add' %}" method="post">{% csrf_token %}
{% bootstrap_form form %} {% bootstrap_form form %}
<button type="submit" class="btn btn-primary btn-sm"> <button type="submit" class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} <span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}

2
nas_app/templates/nas_app/nasmodel_confirm_delete.html → gw_app/templates/gw_app/nasmodel_confirm_delete.html

@ -2,7 +2,7 @@
{% load i18n %} {% load i18n %}
{% block modal_form_url %} {% block modal_form_url %}
{% url 'nas_app:del' object.pk %}
{% url 'gw_app:del' object.pk %}
{% endblock %} {% endblock %}
{% block modal_form_title %} {% block modal_form_title %}

4
nas_app/templates/nas_app/nasmodel_list.html → gw_app/templates/gw_app/nasmodel_list.html

@ -36,7 +36,7 @@
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
<div class="btn-group btn-group-sm"> <div class="btn-group btn-group-sm">
<a href="{% url 'nas_app:edit' nas.pk %}" class="btn btn-default">
<a href="{% url 'gw_app:edit' nas.pk %}" class="btn btn-default">
<span class="glyphicon glyphicon-eye-open"></span> <span class="glyphicon glyphicon-eye-open"></span>
<span class="hidden-md">{% trans 'View' %}</span> <span class="hidden-md">{% trans 'View' %}</span>
</a> </a>
@ -51,7 +51,7 @@
{% endfor %} {% endfor %}
<div class="col-sm-12"> <div class="col-sm-12">
<div class="btn-group btn-group-sm"> <div class="btn-group btn-group-sm">
<a href="{% url 'nas_app:add' %}" class="btn btn-default">
<a href="{% url 'gw_app:add' %}" class="btn btn-default">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %} <span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %}
</a> </a>
</div> </div>

8
nas_app/templates/nas_app/nasmodel_update.html → gw_app/templates/gw_app/nasmodel_update.html

@ -4,7 +4,7 @@
{% block breadcrumb %} {% block breadcrumb %}
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li> <li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'nas_app:home' %}">{% trans 'Network access servers' %}</a></li>
<li><a href="{% url 'gw_app:home' %}">{% trans 'Network access servers' %}</a></li>
<li class="active">{% trans 'Edit gateway' %}</li> <li class="active">{% trans 'Edit gateway' %}</li>
</ol> </ol>
{% endblock %} {% endblock %}
@ -19,14 +19,14 @@
<h3 class="panel-title">{% trans 'Change gateway' %}</h3> <h3 class="panel-title">{% trans 'Change gateway' %}</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form action="{% url 'nas_app:edit' object.pk %}" method="post">{% csrf_token %}
<form action="{% url 'gw_app:edit' object.pk %}" method="post">{% csrf_token %}
{% bootstrap_form form %} {% bootstrap_form form %}
<div class="btn-group"> <div class="btn-group">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} <span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button> </button>
{% if perms.nas_app.delete_nasmodel %}
<a href="{% url 'nas_app:del' object.pk %}" class="btn btn-danger btn-modal">
{% if perms.gw_app.delete_nasmodel %}
<a href="{% url 'gw_app:del' object.pk %}" class="btn btn-danger btn-modal">
<span class="glyphicon glyphicon-remove"></span> {% trans 'Delete' %} <span class="glyphicon glyphicon-remove"></span> {% trans 'Delete' %}
</a> </a>
{% else %} {% else %}

20
nas_app/tests.py → gw_app/tests.py

@ -6,8 +6,8 @@ from django.conf import settings
from django.shortcuts import resolve_url from django.shortcuts import resolve_url
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from group_app.models import Group from group_app.models import Group
from nas_app.models import NASModel
from nas_app.nas_managers import MikrotikTransmitter
from gw_app.models import NASModel
from gw_app.nas_managers import MikrotikTransmitter
class MyBaseTestCase(metaclass=ABCMeta): class MyBaseTestCase(metaclass=ABCMeta):
@ -55,7 +55,7 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
@override_settings(LANGUAGE_CODE='en', LANGUAGES=(('en', 'English'),)) @override_settings(LANGUAGE_CODE='en', LANGUAGES=(('en', 'English'),))
def test_create(self): def test_create(self):
url = resolve_url('nas_app:add')
url = resolve_url('gw_app:add')
self._client_get_check_login(url) self._client_get_check_login(url)
# test success create nas # test success create nas
@ -135,7 +135,7 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
@override_settings(LANGUAGE_CODE='en', LANGUAGES=(('en', 'English'),)) @override_settings(LANGUAGE_CODE='en', LANGUAGES=(('en', 'English'),))
def test_change(self): def test_change(self):
url = resolve_url('nas_app:edit', self.nas.pk)
url = resolve_url('gw_app:edit', self.nas.pk)
self._client_get_check_login(url) self._client_get_check_login(url)
# test get request # test get request
@ -150,7 +150,7 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
'auth_passw': '_v_c', 'auth_passw': '_v_c',
'nas_type': 'mktk' 'nas_type': 'mktk'
}) })
self.assertRedirects(r, resolve_url('nas_app:edit', self.nas.pk))
self.assertRedirects(r, resolve_url('gw_app:edit', self.nas.pk))
msg = r.cookies.get('messages') msg = r.cookies.get('messages')
self.assertIn('Update successfully', msg.output()) self.assertIn('Update successfully', msg.output())
NASModel.objects.get(title='New again nas2 changed', ip_address='192.168.8.12', NASModel.objects.get(title='New again nas2 changed', ip_address='192.168.8.12',
@ -158,7 +158,7 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
@override_settings(LANGUAGE_CODE='en', LANGUAGES=(('en', 'English'),)) @override_settings(LANGUAGE_CODE='en', LANGUAGES=(('en', 'English'),))
def test_delete(self): def test_delete(self):
url = resolve_url('nas_app:add')
url = resolve_url('gw_app:add')
self._client_get_check_login(url) self._client_get_check_login(url)
r = self.client.post(url, data={ r = self.client.post(url, data={
'title': 'Test success nas_2', 'title': 'Test success nas_2',
@ -171,7 +171,7 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
self.assertEqual(r.status_code, 302) self.assertEqual(r.status_code, 302)
o = NASModel.objects.get(title='Test success nas_2', ip_address='192.168.8.11', ip_port=1254, o = NASModel.objects.get(title='Test success nas_2', ip_address='192.168.8.11', ip_port=1254,
auth_login='_', auth_passw='_') auth_login='_', auth_passw='_')
url = resolve_url('nas_app:del', o.pk)
url = resolve_url('gw_app:del', o.pk)
# test get request # test get request
r = self.client.get(url) r = self.client.get(url)
@ -179,7 +179,7 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
# test deleting # test deleting
r = self.client.post(url) r = self.client.post(url)
self.assertRedirects(r, resolve_url('nas_app:home'))
self.assertRedirects(r, resolve_url('gw_app:home'))
msg = r.cookies.get('messages') msg = r.cookies.get('messages')
self.assertIn('Server successfully removed', msg.output()) self.assertIn('Server successfully removed', msg.output())
try: try:
@ -190,8 +190,8 @@ class NASModelTestCase(MyBaseTestCase, TestCase):
# try to remove default nas # try to remove default nas
nas_id = self.nas.pk nas_id = self.nas.pk
r = self.client.post(resolve_url('nas_app:del', nas_id))
self.assertRedirects(r, expected_url=resolve_url('nas_app:edit', nas_id))
r = self.client.post(resolve_url('gw_app:del', nas_id))
self.assertRedirects(r, expected_url=resolve_url('gw_app:edit', nas_id))
msg = r.cookies.get('messages') msg = r.cookies.get('messages')
self.assertIn('You cannot remove default server', msg.output()) self.assertIn('You cannot remove default server', msg.output())

4
nas_app/urls.py → gw_app/urls.py

@ -1,8 +1,8 @@
from django.urls import path from django.urls import path
from nas_app import views
from gw_app import views
app_name = 'nas_app'
app_name = 'gw_app'
urlpatterns = [ urlpatterns = [

28
nas_app/views.py → gw_app/views.py

@ -9,8 +9,8 @@ from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView, DeleteView, UpdateView from django.views.generic import ListView, CreateView, DeleteView, UpdateView
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 assign_perm from guardian.shortcuts import assign_perm
from nas_app.forms import NasForm
from nas_app.models import NASModel
from gw_app.forms import NasForm
from gw_app.models import NASModel
from djing.lib.decorators import only_admins from djing.lib.decorators import only_admins
@ -18,24 +18,24 @@ login_decs = login_required, only_admins
@method_decorator(login_decs, name='dispatch') @method_decorator(login_decs, name='dispatch')
@method_decorator(permission_required('nas_app.view_nasmodel'), name='dispatch')
@method_decorator(permission_required('gw_app.view_nasmodel'), name='dispatch')
class NasListView(ListView): class NasListView(ListView):
model = NASModel model = NASModel
@method_decorator(login_decs, name='dispatch') @method_decorator(login_decs, name='dispatch')
@method_decorator(permission_required('nas_app.add_nasmodel'), name='dispatch')
@method_decorator(permission_required('gw_app.add_nasmodel'), name='dispatch')
class NasCreateView(CreateView): class NasCreateView(CreateView):
model = NASModel model = NASModel
form_class = NasForm form_class = NasForm
template_name = 'nas_app/nasmodel_add.html'
success_url = reverse_lazy('nas_app:home')
template_name = 'gw_app/nasmodel_add.html'
success_url = reverse_lazy('gw_app:home')
def form_valid(self, form): def form_valid(self, form):
r = super(NasCreateView, self).form_valid(form) r = super(NasCreateView, self).form_valid(form)
assign_perm("nas_app.change_nasmodel", self.request.user, self.object)
assign_perm("nas_app.view_nasmodel", self.request.user, self.object)
assign_perm("nas_app.delete_nasmodel", self.request.user, self.object)
assign_perm("gw_app.change_nasmodel", self.request.user, self.object)
assign_perm("gw_app.view_nasmodel", self.request.user, self.object)
assign_perm("gw_app.delete_nasmodel", self.request.user, self.object)
self.request.user.log(self.request.META, 'cnas', '"%(title)s", %(ip)s, %(type)s' % { self.request.user.log(self.request.META, 'cnas', '"%(title)s", %(ip)s, %(type)s' % {
'title': self.object.title, 'title': self.object.title,
'ip': self.object.ip_address, 'ip': self.object.ip_address,
@ -46,10 +46,10 @@ class NasCreateView(CreateView):
@method_decorator(login_decs, name='dispatch') @method_decorator(login_decs, name='dispatch')
@method_decorator(permission_required('nas_app.delete_nasmodel'), name='dispatch')
@method_decorator(permission_required('gw_app.delete_nasmodel'), name='dispatch')
class NasDeleteView(DeleteView): class NasDeleteView(DeleteView):
model = NASModel model = NASModel
success_url = reverse_lazy('nas_app:home')
success_url = reverse_lazy('gw_app:home')
pk_url_kwarg = 'nas_id' pk_url_kwarg = 'nas_id'
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
@ -64,17 +64,17 @@ class NasDeleteView(DeleteView):
return r return r
except MessageFailure as e: except MessageFailure as e:
messages.error(request, e) messages.error(request, e)
failure_url = resolve_url('nas_app:edit', self.object.pk)
failure_url = resolve_url('gw_app:edit', self.object.pk)
return HttpResponseRedirect(failure_url) return HttpResponseRedirect(failure_url)
@method_decorator(login_decs, name='dispatch') @method_decorator(login_decs, name='dispatch')
@method_decorator(permission_required('nas_app.change_nasmodel'), name='dispatch')
@method_decorator(permission_required('gw_app.change_nasmodel'), name='dispatch')
class NasUpdateView(UpdateView): class NasUpdateView(UpdateView):
model = NASModel model = NASModel
form_class = NasForm form_class = NasForm
pk_url_kwarg = 'nas_id' pk_url_kwarg = 'nas_id'
template_name = 'nas_app/nasmodel_update.html'
template_name = 'gw_app/nasmodel_update.html'
def form_valid(self, form): def form_valid(self, form):
r = super(NasUpdateView, self).form_valid(form) r = super(NasUpdateView, self).form_valid(form)

5
nas_app/apps.py

@ -1,5 +0,0 @@
from django.apps import AppConfig
class NasAppConfig(AppConfig):
name = 'nas_app'

0
nas_app/migrations/__init__.py

9
nas_app/nas_managers/__init__.py

@ -1,9 +0,0 @@
from nas_app.nas_managers.mod_mikrotik import MikrotikTransmitter
from nas_app.nas_managers.core import NasNetworkError, NasFailedResult
from nas_app.nas_managers.structs import SubnetQueue
# Указываем какие реализации NAS у нас есть, это будет использоваться в
# web интерфейсе
NAS_TYPES = (
('mktk', MikrotikTransmitter),
)

6
periodic.py

@ -9,8 +9,8 @@ from django.utils import timezone
from django.db import transaction from django.db import transaction
from django.db.models import signals, Count from django.db.models import signals, Count
from abonapp.models import Abon, AbonTariff, abontariff_pre_delete, PeriodicPayForId, AbonLog from abonapp.models import Abon, AbonTariff, abontariff_pre_delete, PeriodicPayForId, AbonLog
from nas_app.nas_managers import NasNetworkError, NasFailedResult
from nas_app.models import NASModel
from gw_app.nas_managers import NasNetworkError, NasFailedResult
from gw_app.models import NASModel
from djing.lib import LogicError from djing.lib import LogicError
@ -99,7 +99,7 @@ def main():
for pay in ppays: for pay in ppays:
pay.payment_for_service(now=now) pay.payment_for_service(now=now)
# sync subscribers on NAS
# sync subscribers on GW
threads = tuple(NasSyncThread(nas) for nas in NASModel.objects. threads = tuple(NasSyncThread(nas) for nas in NASModel.objects.
annotate(usercount=Count('abon')). annotate(usercount=Count('abon')).
filter(usercount__gt=0)) filter(usercount__gt=0))

6
templates/base.html

@ -104,11 +104,11 @@
</a> </a>
</li> </li>
{% if perms.nas_app.view_nasmodel %}
{% url 'nas_app:home' as nashome %}
{% if perms.gw_app.view_nasmodel %}
{% url 'gw_app:home' as nashome %}
<li{% if nashome in request.path %} class="active"{% endif %}> <li{% if nashome in request.path %} class="active"{% endif %}>
<a href="{{ nashome }}"> <a href="{{ nashome }}">
<span class="glyphicon glyphicon-globe"></span> {% trans 'NAS' %}
<span class="glyphicon glyphicon-globe"></span> {% trans 'Gateways' %}
</a> </a>
</li> </li>
{% endif %} {% endif %}

Loading…
Cancel
Save