Browse Source

Add per object permissions support

devel
Dmitry 9 years ago
parent
commit
de80ebba11
  1. 38
      abonapp/locale/ru/LC_MESSAGES/django.po
  2. 14
      abonapp/migrations/0001_squashed_0022_auto_20170816_1109.py
  3. 43
      abonapp/migrations/0003_auto_20170927_1838.py
  4. 73
      abonapp/models.py
  5. 58
      abonapp/templates/abonapp/complete_service.html
  6. 12
      abonapp/templates/abonapp/editAbon.html
  7. 2
      abonapp/templates/abonapp/group_list.html
  8. 16
      abonapp/templates/abonapp/payHistory.html
  9. 9
      abonapp/templates/abonapp/peoples.html
  10. 2
      abonapp/templates/abonapp/viewAbon.html
  11. 4
      abonapp/urls.py
  12. 1
      abonapp/urls_abon.py
  13. 216
      abonapp/views.py
  14. 30
      accounts_app/forms.py
  15. 70
      accounts_app/locale/ru/LC_MESSAGES/django.po
  16. 19
      accounts_app/migrations/0008_auto_20170927_1838.py
  17. 10
      accounts_app/models.py
  18. 30
      accounts_app/templates/accounts/ext.htm
  19. 50
      accounts_app/templates/accounts/group.html
  20. 58
      accounts_app/templates/accounts/group_list.html
  21. 34
      accounts_app/templates/accounts/perms/objects_of_type.html
  22. 36
      accounts_app/templates/accounts/perms/objects_types.html
  23. 71
      accounts_app/templates/accounts/perms/perms_edit.html
  24. 6
      accounts_app/templates/accounts/profile_chgroup.html
  25. 25
      accounts_app/templates/accounts/set_abon_groups_permission.html
  26. 7
      accounts_app/templates/accounts/settings/ext.htm
  27. 14
      accounts_app/templates/accounts/settings/permissions.html
  28. 14
      accounts_app/templates/accounts/settings/test.html
  29. 1
      accounts_app/templatetags/__init__.py
  30. 18
      accounts_app/templatetags/acc_tags.py
  31. 8
      accounts_app/urls.py
  32. 133
      accounts_app/views.py
  33. 5
      clientsideapp/templates/clientsideapp/ext.html
  34. 9
      devapp/locale/ru/LC_MESSAGES/django.po
  35. 23
      devapp/migrations/0003_auto_20170927_1838.py
  36. 11
      devapp/models.py
  37. 37
      devapp/templates/devapp/custom_dev_page/onu.html
  38. 12
      devapp/templates/devapp/devices_null_group.html
  39. 34
      devapp/views.py
  40. 8
      djing/settings_example.py
  41. 3
      mapapp/views.py
  42. 2
      requirements.txt
  43. 3
      tariff_app/views.py
  44. 3
      taskapp/views.py
  45. 2
      templates/all_base.html

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

@ -389,10 +389,6 @@ msgstr "Дом"
msgid "Is active"
msgstr "Активен"
#: abonapp/templates/abonapp/editAbon.html:106
msgid "Send account info to user"
msgstr "Отправить данные абоненту"
#: abonapp/templates/abonapp/editAbon.html:109
#: abonapp/templates/abonapp/editAbon.html:110
#, fuzzy
@ -473,7 +469,7 @@ msgstr "Принадлежность услуг к группам"
#: abonapp/templates/abonapp/invoiceForPayment.html:10
#: abonapp/templates/abonapp/payHistory.html:39
msgid "Debts"
msgstr "Долги"
msgstr "Квитанции (долги)"
#: abonapp/templates/abonapp/invoiceForPayment.html:15
msgid "Debtor"
@ -606,10 +602,6 @@ msgstr "Балланс"
msgid "Subscribers not found"
msgstr "Абоненты не найдены"
#: abonapp/templates/abonapp/peoples.html:130
msgid "Refresh subscribers on NAS"
msgstr "Обновить абонентов в NAS"
#: abonapp/templates/abonapp/peoples.html:133
msgid "Tariffs in groups"
msgstr "Тарифы в группах"
@ -736,10 +728,6 @@ msgstr "Адрес"
msgid "delete abon success msg"
msgstr "Абонент успешно удалён"
#: abonapp/views.py:180
msgid "I not know what to delete"
msgstr "Не понятно что удалять"
#: abonapp/views.py:184
#, python-format
msgid "NAS says: '%s'"
@ -993,3 +981,27 @@ msgstr "Номер телефона успешно удалён"
msgid "Telephone not found"
msgstr "Телефон не найден"
msgid "Can view subscriber group"
msgstr "Может просматривать группу абонентов"
msgid "Permission denied"
msgstr "Доступ запрещён"
msgid "Can view subscriber logs"
msgstr "Может видеть логи абонента"
msgid "Can view invoice for payment"
msgstr "Может видеть назначенные платежи"
msgid "Debt"
msgstr "Квитанция (долг)"
msgid "Passport Info"
msgstr "Паспортные данные"
msgid "Can ping"
msgstr "Может пинговать"
msgid "Can view additional telephones"
msgstr "Может видеть дополнительные телефоны"

14
abonapp/migrations/0001_squashed_0022_auto_20170816_1109.py

@ -231,11 +231,6 @@ class Migration(migrations.Migration):
name='tariffs',
field=models.ManyToManyField(blank=True, related_name='tariff_groups', to='tariff_app.Tariff'),
),
migrations.AddField(
model_name='abon',
name='opt82',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='abonapp.Opt82'),
),
migrations.CreateModel(
name='PassportInfo',
fields=[
@ -247,11 +242,6 @@ class Migration(migrations.Migration):
('abon', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.Abon')),
],
),
migrations.AlterField(
model_name='abon',
name='opt82',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.Opt82'),
),
migrations.CreateModel(
name='AbonDevice',
fields=[
@ -282,10 +272,6 @@ class Migration(migrations.Migration):
name='ip_address',
field=mydefs.MyGenericIPAddressField(blank=True, max_length=8, null=True, protocol='ipv4'),
),
migrations.RemoveField(
model_name='abon',
name='opt82',
),
migrations.AddField(
model_name='abon',
name='dev_port',

43
abonapp/migrations/0003_auto_20170927_1838.py

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-27 18:38
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0002_auto_20170905_1248'),
]
operations = [
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'), ('can_view_passport', 'Может просматривать паспортные данные'), ('can_add_ballance', 'Пополнение счёта'), ('can_ping', 'Может пинговать')), 'verbose_name': 'Абонент', 'verbose_name_plural': 'Абоненты'},
),
migrations.AlterModelOptions(
name='abongroup',
options={'permissions': (('can_view_abongroup', 'Может просматривать группу абонентов'),), 'verbose_name': 'Группа абонентов', 'verbose_name_plural': 'Группы абонентов'},
),
migrations.AlterModelOptions(
name='abonlog',
options={'permissions': (('can_view_abonlog', 'Может видеть логи абонента'),)},
),
migrations.AlterModelOptions(
name='additionaltelephone',
options={'ordering': ('owner_name',), 'permissions': (('can_view_additionaltelephones', 'Может видеть дополнительные телефоны'),), 'verbose_name': 'Дополнительный телефон', 'verbose_name_plural': 'Дополнительные телефоны'},
),
migrations.AlterModelOptions(
name='invoiceforpayment',
options={'ordering': ('date_create',), 'permissions': (('can_view_invoiceforpayment', 'Может видеть назначенные платежи'),), 'verbose_name': 'Квитанция (долг)', 'verbose_name_plural': 'Квитанции (долги)'},
),
migrations.AlterModelOptions(
name='passportinfo',
options={'verbose_name': 'Паспортные данные', 'verbose_name_plural': 'Паспортные данные'},
),
migrations.AlterModelTable(
name='passportinfo',
table='passport_info',
),
]

73
abonapp/models.py

@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.db.models.signals import post_save, post_delete, pre_delete, post_init
from django.dispatch import receiver
from django.utils import timezone
from django.db import models
from django.core import validators
from django.utils.translation import ugettext as _
from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError
from tariff_app.models import Tariff
from accounts_app.models import UserProfile
from accounts_app.models import UserProfile, MyUserManager
from mydefs import MyGenericIPAddressField, ip2int, LogicError, ip_addr_regex
from django.conf import settings
@ -23,7 +25,7 @@ class AbonGroup(models.Model):
class Meta:
db_table = 'abonent_groups'
permissions = (
('can_add_ballance', _('fill account')),
('can_view_abongroup', _('Can view subscriber group')),
)
verbose_name = _('Abon group')
verbose_name_plural = _('Abon groups')
@ -41,6 +43,9 @@ class AbonLog(models.Model):
class Meta:
db_table = 'abonent_log'
permissions = (
('can_view_abonlog', _('Can view subscriber logs')),
)
def __str__(self):
return self.comment
@ -133,6 +138,13 @@ class ExtraFieldsModel(models.Model):
db_table = 'abon_extra_fields'
class AbonManager(MyUserManager):
def get_queryset(self):
return super(MyUserManager, self).get_queryset().filter(is_admin=False)
class Abon(UserProfile):
current_tariff = models.ForeignKey(AbonTariff, null=True, blank=True, on_delete=models.SET_NULL)
group = models.ForeignKey(AbonGroup, models.SET_NULL, blank=True, null=True)
@ -150,11 +162,15 @@ class Abon(UserProfile):
def active_tariff(self):
return self.current_tariff
objects = AbonManager()
class Meta:
db_table = 'abonent'
permissions = (
('can_buy_tariff', _('Buy service perm')),
('can_view_passport', _('Can view passport'))
('can_view_passport', _('Can view passport')),
('can_add_ballance', _('fill account')),
('can_ping', _('Can ping'))
)
verbose_name = _('Abon')
verbose_name_plural = _('Abons')
@ -261,6 +277,11 @@ class PassportInfo(models.Model):
date_of_acceptance = models.DateField()
abon = models.OneToOneField(Abon, on_delete=models.SET_NULL, blank=True, null=True)
class Meta:
db_table = 'passport_info'
verbose_name = _('Passport Info')
verbose_name_plural = _('Passport Info')
def __str__(self):
return "%s %s" % (self.series, self.number)
@ -287,6 +308,11 @@ class InvoiceForPayment(models.Model):
class Meta:
ordering = ('date_create',)
db_table = 'abonent_inv_pay'
permissions = (
('can_view_invoiceforpayment', _('Can view invoice for payment')),
)
verbose_name = _('Debt')
verbose_name_plural = _('Debts')
# Log for pay system "AllTime"
@ -345,11 +371,16 @@ class AdditionalTelephone(models.Model):
class Meta:
db_table = 'additional_telephones'
ordering = ('owner_name',)
permissions = (
('can_view_additionaltelephones', _('Can view additional telephones')),
)
verbose_name = _('Additional telephone')
verbose_name_plural = _('Additional telephones')
def abon_post_save(sender, instance, **kwargs):
@receiver(post_save, sender=Abon)
def abon_post_save(sender, **kwargs):
instance, created = kwargs["instance"], kwargs["created"]
timeout = None
if hasattr(instance, 'is_dhcp') and instance.is_dhcp:
timeout = getattr(settings, 'DHCP_TIMEOUT', 14400)
@ -358,7 +389,7 @@ def abon_post_save(sender, instance, **kwargs):
return True
try:
tm = Transmitter()
if kwargs['created']:
if created:
# создаём абонента
tm.add_user(agent_abon, ip_timeout=timeout)
else:
@ -370,9 +401,11 @@ def abon_post_save(sender, instance, **kwargs):
return True
def abon_del_signal(sender, instance, **kwargs):
@receiver(post_delete, sender=Abon)
def abon_del_signal(sender, **kwargs):
abon = kwargs["instance"]
try:
ab = instance.build_agent_struct()
ab = abon.build_agent_struct()
if ab is None:
return True
# подключаемся к NAS'у
@ -383,17 +416,21 @@ def abon_del_signal(sender, instance, **kwargs):
return True
def abon_tariff_post_init(sender, instance, **kwargs):
if getattr(instance, 'time_start') is None:
instance.time_start = timezone.now()
calc_obj = instance.tariff.get_calc_type()(instance)
if getattr(instance, 'deadline') is None:
instance.deadline = calc_obj.calc_deadline()
@receiver(post_init, sender=AbonTariff)
def abon_tariff_post_init(sender, **kwargs):
abon_tariff = kwargs["instance"]
if getattr(abon_tariff, 'time_start') is None:
abon_tariff.time_start = timezone.now()
calc_obj = abon_tariff.tariff.get_calc_type()(abon_tariff)
if getattr(abon_tariff, 'deadline') is None:
abon_tariff.deadline = calc_obj.calc_deadline()
def abontariff_pre_delete(sender, instance, **kwargs):
@receiver(pre_delete, sender=AbonTariff)
def abontariff_pre_delete(sender, **kwargs):
abon_tariff = kwargs["instance"]
try:
abon = Abon.objects.get(current_tariff=instance)
abon = Abon.objects.get(current_tariff=abon_tariff)
ab = abon.build_agent_struct()
if ab is None:
return True
@ -404,9 +441,3 @@ def abontariff_pre_delete(sender, instance, **kwargs):
except (NasFailedResult, NasNetworkError, ConnectionResetError) as e:
print('NetErr:', e)
return True
models.signals.post_save.connect(abon_post_save, sender=Abon)
models.signals.post_delete.connect(abon_del_signal, sender=Abon)
models.signals.post_init.connect(abon_tariff_post_init, sender=AbonTariff)
models.signals.pre_delete.connect(abontariff_pre_delete, sender=AbonTariff)

58
abonapp/templates/abonapp/complete_service.html

@ -1,58 +0,0 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.id %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_home' abon_group.id abon.id %}">{{ abon.fio }}</a></li>
<li class="active">{% trans 'Finish service' %}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Finish service' %}</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'abonapp:compl_srv' abon_group.id abon.id abtar.id %}" method="post">{% csrf_token %}
<input name="finish_confirm" value="yes" type="hidden">
<p>
{% blocktrans %}Early completion of the current service will cause that user will be denied access to services Resources (Net closes)
To continue to use the resources necessary to connect the required service{% endblocktrans %}
</p>
<p>{% blocktrans %}Details: <br/>
You complete tariff{% endblocktrans %}
{% if perms.tariff_app.change_tariff %}
<a href="{% url 'tarifs:edit' abtar.tariff.id %}" target="_blank">{{ abtar.tariff.title }}</a>.<br/>
{% else %}
{{ abtar.tariff.title }}.<br/>
{% endif %}
{% now "d F Y, H: i: s" as today %}
{% blocktrans with time_start=abtar.time_start|date:'d F Y, H: i: s' amount=abtar.tariff.amount %}The service has been connected: {{ time_start }}<br/>
Today: {{ today }}<br/>
Time of use: {{ time_use }}<br/>
The total cost of the service: {{ amount }}<br/>
Total cost: {{ tcost }}<br/>
Cashback: {{ cashback }}{% endblocktrans %}
</p>
<div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
</div>
</form>
</div>
</div>
{% endblock %}

12
abonapp/templates/abonapp/editAbon.html

@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %}
{% load guardian_tags %}
{% block content %}
<div class="row">
@ -108,9 +109,6 @@
<button type="submit" class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-floppy-disk"></span> {% trans 'Save' %}
</button>
<!--<a href="#" class="btn btn-default btn-sm" onclick="showPrimary('<h3>Надо ещё придумать чем будем абонентам отправлять оповещения</h3> Ну кроме смс');">
<span class="glyphicon glyphicon-send"></span> {% trans 'Send account info to user' %}
</a>-->
{% if perms.taskapp.add_task %}
<a href="{% url 'taskapp:add' %}?uid={{ abon.username }}" class="btn btn-sm btn-success" title="{% trans 'Add new task' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add new task' %}
@ -119,7 +117,7 @@
</div>
</div>
{% if ip %}
{% if ip and perms.abonapp.can_ping %}
<div class="form-group-sm">
<div class="col-sm-offset-4 col-sm-8 btn-group btn-group-sm">
<a href="{% url 'abonapp:ping' %}" class="btn btn-sm btn-default btn-cmd" title="Ping" data-param="{{ ip }}">
@ -134,6 +132,7 @@
</div>
</div>
<div class="col-sm-6">
{% if perms.abonapp.change_abon %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Select the device' %}</h3>
@ -146,7 +145,7 @@
<label for="id_method" class="col-sm-2 control-label">{% trans 'Device' %}</label>
<div class="col-sm-10 btn-group btn-group-sm">
{% if device %}
<a href="{% url 'devapp:view' abon_group.pk device.pk %}" target="_blank" class="btn btn-sm btn-default" title="{% trans 'Mac Address' %} {{ device.mac_addr }}">
<a href="{% url 'devapp:view' abon_group.pk device.pk %}" target="_blank" class="btn btn-sm btn-default" title="{% trans 'Mac Address' %} {{ device.mac_addr }}">
<span class="glyphicon glyphicon-hdd"></span> {{ device.comment|truncatechars:11 }} {{ device.ip_address }}
</a>
<a href="{% url 'abonapp:clear_dev' abon_group.pk abon.pk %}" class="btn btn-sm btn-danger">
@ -199,6 +198,8 @@
</form>
</div>
</div>
{% endif %}
{% if perms.abonapp.add_extrafieldsmodel %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Extra fields' %}</h3>
@ -242,6 +243,7 @@
</form>
</div>
</div>
{% endif %}
</div>
</div>

2
abonapp/templates/abonapp/group_list.html

@ -38,7 +38,7 @@
<td class="btn-group">
{% if perms.abonapp.delete_abongroup %}
{% if gr.usercount == 0 %}
<a href="{% url 'abonapp:del_group' %}?t=a&id={{ gr.pk }}" class="btn btn-sm btn-danger">
<a href="{% url 'abonapp:del_group' %}?id={{ gr.pk }}" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove-circle"></span>
</a>
{% endif %}

16
abonapp/templates/abonapp/payHistory.html

@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %}
{% load guardian_tags %}
{% block content %}
<table class="table table-striped table-bordered">
@ -30,12 +31,17 @@
<tfoot>
<tr>
<td colspan="5" class="btn-group btn-group-sm">
{% if perms.abonapp.can_add_ballance %}
<a href="{% url 'abonapp:abon_amount' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% get_obj_perms request.user for abon as 'fill_perm' %}
{% if 'abonapp.can_add_ballance' in fill_perm %}
<a href="{% url 'abonapp:abon_amount' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% else %}
<a href="#" class="btn btn-default" title="{% trans 'Permission denied' %}" disabled>
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% endif %}
<a href="{% url 'abonapp:abon_debts' abon_group.pk abon.pk %}"class="btn btn-default">
<a href="{% url 'abonapp:abon_debts' abon_group.pk abon.pk %}" class="btn btn-default">
<span class="glyphicon glyphicon-gbp"></span> {% trans 'Debts' %}
</a>
</td>

9
abonapp/templates/abonapp/peoples.html

@ -104,7 +104,7 @@
<td>{{ human.ballance }}</td>
<td>
{% if can_del_trf %}
<a href="{% url 'abonapp:del_abon' %}?t=a&id={{ human.pk }}" class="btn btn-danger btn-sm">
<a href="{% url 'abonapp:del_abon' %}?id={{ human.pk }}" class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
@ -126,14 +126,11 @@
<tr>
<td colspan="11" class="btn-group">
{% if perms.abonapp.add_abon %}
<a href="{% url 'abonapp:add_abon' abon_group.pk %}" class="btn btn-sm btn-default" title="Добавить">
<a href="{% url 'abonapp:add_abon' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add abon' %}
</a>
{% endif %}
<a href="{% url 'abonapp:update_nas' abon_group.pk %}" class="btn btn-sm btn-default">
<span class="glyphicon glyphicon-refresh"></span> {% trans 'Refresh subscribers on NAS' %}
</a>
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}">
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-subscript"></span> {% trans 'Tariffs in groups' %}
</a>
</td>

2
abonapp/templates/abonapp/viewAbon.html

@ -61,6 +61,7 @@
</div>
</div>
{% if perms.abonapp.can_view_passport %}
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
@ -86,6 +87,7 @@
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}

4
abonapp/urls.py

@ -13,7 +13,7 @@ urlpatterns = [
url(r'^log$', views.log_page, name='log'),
url(r'^del$', views.delentity, name='del_abon'),
url(r'^del$', views.del_abon, name='del_abon'),
url(r'^pay$', views.terminal_pay, name='terminal_pay'),
@ -21,8 +21,6 @@ urlpatterns = [
url(r'^ping$', views.abon_ping, name='ping'),
url(r'^refresh_group_nas(?P<group_id>\d+)$', views.update_nas, name='update_nas'),
# Api's
url(r'^api/abons$', views.abons),
url(r'^api/abon_filter$', views.search_abon)

1
abonapp/urls_abon.py

@ -19,7 +19,6 @@ urlpatterns = [
url(r'^(?P<uid>\d+)/addinvoice$', views.add_invoice, name='add_invoice'),
url(r'^(?P<uid>\d+)/pick$', views.pick_tariff, name='pick_tariff'),
url(r'^(?P<uid>\d+)/passport_view$', views.passport_view, name='passport_view'),
url(r'^(?P<uid>\d+)/complete_service(?P<srvid>\d+)$', views.complete_service, name='compl_srv'),
url(r'^(?P<uid>\d+)/chart$', views.charts, name='charts'),
url(r'^(?P<uid>\d+)/dials$', views.dials, name='dials'),
url(r'^(?P<uid>\d+)/extra_field$', views.make_extra_field, name='extra_field'),

216
abonapp/views.py

@ -6,8 +6,7 @@ from django.db import IntegrityError, ProgrammingError
from django.db.models import Count, Q
from django.db.transaction import atomic
from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib.auth.decorators import login_required, permission_required
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
@ -23,17 +22,22 @@ from datetime import datetime, date
from taskapp.models import Task
from dialing_app.models import AsteriskCDR
from statistics.models import getModel, get_dates
from guardian.shortcuts import get_objects_for_user, assign_perm
from guardian.decorators import permission_required_or_403 as permission_required
@login_required
@mydefs.only_admins
def peoples(request, gid):
abon_group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', abon_group):
raise PermissionDenied
street_id = mydefs.safe_int(request.GET.get('street'))
peoples_list = models.Abon.objects.select_related('group', 'street')
if street_id > 0:
peoples_list = peoples_list.filter(group=gid, street=street_id)
peoples_list = peoples_list.filter(group=abon_group, street=street_id)
else:
peoples_list = peoples_list.filter(group=gid)
peoples_list = peoples_list.filter(group=abon_group)
# фильтр
dr, field = mydefs.order_helper(request)
@ -72,7 +76,10 @@ def addgroup(request):
if request.method == 'POST':
frm = forms.AbonGroupForm(request.POST)
if frm.is_valid():
frm.save()
grp = frm.save()
assign_perm('abonapp.can_view_abongroup', request.user, grp)
assign_perm('abonapp.delete_abongroup', request.user, grp)
assign_perm('abonapp.change_abongroup', request.user, grp)
messages.success(request, _('create group success msg'))
return redirect('abonapp:group_list')
else:
@ -91,6 +98,7 @@ def addgroup(request):
@mydefs.only_admins
def grouplist(request):
groups = models.AbonGroup.objects.annotate(usercount=Count('abon')).order_by('title')
groups = get_objects_for_user(request.user, 'abonapp.can_view_abongroup', klass=groups, accept_global_perms=False)
# фильтр
directory, field = mydefs.order_helper(request)
@ -107,11 +115,13 @@ def grouplist(request):
@login_required
@permission_required('abonapp.delete_abongroup')
def delgroup(request):
try:
agd = mydefs.safe_int(request.GET.get('id'))
get_object_or_404(models.AbonGroup, pk=agd).delete()
abon_group = models.AbonGroup.objects.get(pk=agd)
if not request.user.has_perm('abonapp.delete_abongroup', abon_group):
raise PermissionDenied
abon_group.delete()
messages.success(request, _('delete group success msg'))
return mydefs.res_success(request, 'abonapp:group_list')
except (NasFailedResult, NasNetworkError) as e:
@ -119,6 +129,8 @@ def delgroup(request):
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
except models.AbonGroup.DoesNotExist:
return mydefs.res_error(request, 'Group with id=%d does not exist' % agd)
return mydefs.res_error(request, 'abonapp:group_list')
@ -129,10 +141,17 @@ def addabon(request, gid):
group = None
try:
group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', group):
raise PermissionDenied
if request.method == 'POST':
frm = forms.AbonForm(request.POST, initial={'group': group})
if frm.is_valid():
abon = frm.save()
assign_perm("abonapp.change_abon", request.user, abon)
assign_perm("abonapp.delete_abon", request.user, abon)
assign_perm("abonapp.can_buy_tariff", request.user, abon)
assign_perm("abonapp.can_view_passport", request.user, abon)
assign_perm('abonapp.can_add_ballance', request.user, abon)
messages.success(request, _('create abon success msg'))
return redirect('abonapp:abon_home', group.id, abon.pk)
else:
@ -159,26 +178,18 @@ def addabon(request, gid):
@login_required
@mydefs.only_admins
def delentity(request):
typ = request.GET.get('t')
def del_abon(request):
uid = request.GET.get('id')
try:
if typ == 'a':
if not request.user.has_perm('abonapp.delete_abon'):
raise PermissionDenied
abon = get_object_or_404(models.Abon, pk=uid)
gid = abon.group.id
abon.delete()
messages.success(request, _('delete abon success msg'))
return mydefs.res_success(request, resolve_url('abonapp:people_list', gid=gid))
elif typ == 'g':
if not request.user.has_perm('abonapp.delete_abongroup'):
raise PermissionDenied
get_object_or_404(models.AbonGroup, pk=uid).delete()
messages.success(request, _('delete group success msg'))
return mydefs.res_success(request, 'abonapp:group_list')
else:
messages.warning(request, _('I not know what to delete'))
abon = get_object_or_404(models.Abon, pk=uid)
if not request.user.has_perm('abonapp.delete_abon') or not request.user.has_perm(
'abonapp.can_view_abongroup', abon.group):
raise PermissionDenied
gid = abon.group.id
abon.delete()
messages.success(request, _('delete abon success msg'))
return mydefs.res_success(request, resolve_url('abonapp:people_list', gid=gid))
except NasNetworkError as e:
messages.error(request, e)
except NasFailedResult as e:
@ -190,12 +201,13 @@ def delentity(request):
@login_required
@permission_required('abonapp.can_add_ballance')
@atomic
def abonamount(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
try:
if request.method == 'POST':
if not request.user.has_perm('abonapp.can_add_ballance', abon):
raise PermissionDenied
abonid = mydefs.safe_int(request.POST.get('abonid'))
if abonid == int(uid):
amnt = mydefs.safe_float(request.POST.get('amount'))
@ -218,6 +230,7 @@ def abonamount(request, gid, uid):
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def invoice_for_payment(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
invoices = models.InvoiceForPayment.objects.filter(abon=abon)
@ -231,6 +244,7 @@ def invoice_for_payment(request, gid, uid):
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def pay_history(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
pay_history = models.AbonLog.objects.filter(abon=abon).order_by('-id')
@ -246,6 +260,8 @@ def pay_history(request, gid, uid):
@mydefs.only_admins
def abon_services(request, gid, uid):
grp = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', grp):
raise PermissionDenied
abon = get_object_or_404(models.Abon, pk=uid)
return render(request, 'abonapp/service.html', {
@ -265,7 +281,7 @@ def abonhome(request, gid, uid):
passw = None
try:
if request.method == 'POST':
if not request.user.has_perm('abonapp.change_abon'):
if not request.user.has_perm('abonapp.change_abon', abon):
raise PermissionDenied
frm = forms.AbonForm(request.POST, instance=abon)
if frm.is_valid():
@ -303,6 +319,8 @@ def abonhome(request, gid, uid):
'dev_ports': DevPort.objects.filter(device=abon.device) if abon.device else None
})
else:
if not request.user.has_perm('abonapp.can_view_abongroup', abon_group):
raise PermissionDenied
return render(request, 'abonapp/viewAbon.html', {
'abon': abon,
'abon_group': abon_group,
@ -356,11 +374,12 @@ def add_invoice(request, gid, uid):
@login_required
@permission_required('abonapp.can_buy_tariff')
@atomic
def pick_tariff(request, gid, uid):
grp = get_object_or_404(models.AbonGroup, pk=gid)
abon = get_object_or_404(models.Abon, pk=uid)
if not request.user.has_perm('abonapp.can_buy_tariff', abon):
raise PermissionDenied
tariffs = grp.tariffs.all()
try:
if request.method == 'POST':
@ -395,70 +414,13 @@ def pick_tariff(request, gid, uid):
@login_required
@permission_required('abonapp.can_complete_service')
@atomic
def complete_service(request, gid, uid, srvid):
abtar = get_object_or_404(models.AbonTariff, pk=srvid)
abon = abtar.abon
# считаем не использованные ресурсы
calc_obj = abtar.tariff.get_calc_type()(abtar)
# получаем сколько использовано
res_amount = calc_obj.calc_amount()
cashback = abtar.tariff.amount - res_amount
if abtar.abon.group is None:
abon.group = get_object_or_404(models.AbonGroup, pk=gid)
abon.save(update_fields=['group'])
if int(abtar.abon.pk) != int(uid) or int(abtar.abon.group.pk) != int(gid):
# если что-то написали в урле вручную, то вернём на путь истинный
return redirect('abonapp:compl_srv', gid=abtar.abon.group.pk, uid=abtar.abon.pk, srvid=srvid)
time_use = None
try:
if request.method == 'POST':
# досрочно завершаем услугу
if request.POST.get('finish_confirm') == 'yes':
if cashback > 0.5:
# возвращаем деньги, которые абонент не использовал
abon.add_ballance(
request.user,
cashback,
_('Refunds for unused resources')
)
abon.save(update_fields=['ballance'])
# удаляем запись о текущей услуге.
abtar.delete()
messages.success(request, _('Service has been finished successfully'))
return redirect('abonapp:abon_services', gid, uid)
else:
raise mydefs.LogicError(_('Not confirmed'))
time_use = mydefs.RuTimedelta(timezone.now() - abtar.time_start)
except (mydefs.LogicError, NasFailedResult) as e:
messages.error(request, e)
except NasNetworkError as e:
messages.warning(request, e)
return redirect('abonapp:abon_home', gid, uid)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
return render(request, 'abonapp/complete_service.html', {
'abtar': abtar,
'abon': abon,
'time_use': time_use,
'abon_group': get_object_or_404(models.AbonGroup, pk=gid),
'tcost': round(res_amount, 4),
'cashback': round(cashback, 4)
})
@login_required
@permission_required('abonapp.delete_abontariff')
@mydefs.only_admins
def unsubscribe_service(request, gid, uid, abon_tariff_id):
try:
get_object_or_404(models.AbonTariff, pk=int(abon_tariff_id)).delete()
abon_tariff = get_object_or_404(models.AbonTariff, pk=int(abon_tariff_id))
if not request.user.has_perm('abonapp.delete_abontariff', abon_tariff):
raise PermissionDenied
abon_tariff.delete()
messages.success(request, _('User has been detached from service'))
except NasFailedResult as e:
messages.error(request, e)
@ -471,7 +433,7 @@ def unsubscribe_service(request, gid, uid, abon_tariff_id):
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abonlog')
def log_page(request):
logs = models.AbonLog.objects.all()
logs = mydefs.pag_mn(request, logs)
@ -481,42 +443,17 @@ def log_page(request):
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_invoiceforpayment')
def debtors(request):
# peoples_list = models.Abon.objects.filter(invoiceforpayment__status=True)
# peoples_list = mydefs.pag_mn(request, peoples_list)
invs = models.InvoiceForPayment.objects.filter(status=True)
invs = mydefs.pag_mn(request, invs)
return render(request, 'abonapp/debtors.html', {
# 'peoples': peoples_list
'invoices': invs
})
@login_required
@mydefs.only_admins
def update_nas(request, group_id):
users = models.Abon.objects.filter(group=group_id)
try:
tm = Transmitter()
for usr in users:
if not usr.ip_address:
continue
agent_abon = usr.build_agent_struct()
if agent_abon is not None:
tm.update_user(agent_abon)
except NasFailedResult as e:
messages.error(request, e)
except NasNetworkError as e:
messages.warning(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
return redirect('abonapp:people_list', gid=group_id)
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def task_log(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
tasks = Task.objects.filter(abon=abon)
@ -532,6 +469,8 @@ def task_log(request, gid, uid):
def passport_view(request, gid, uid):
try:
abon = models.Abon.objects.get(pk=uid)
if not request.user.has_perm('abonapp.can_view_passport', abon):
raise PermissionDenied
if request.method == 'POST':
try:
passport_instance = models.PassportInfo.objects.get(abon=abon)
@ -566,6 +505,8 @@ def passport_view(request, gid, uid):
@mydefs.only_admins
def chgroup_tariff(request, gid):
grp = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.change_abongroup', grp):
raise PermissionDenied
if request.method == 'POST':
tr = request.POST.getlist('tr')
grp.tariffs.clear()
@ -579,7 +520,7 @@ def chgroup_tariff(request, gid):
@login_required
@mydefs.only_admins
@permission_required('abonapp.change_abon')
def dev(request, gid, uid):
abon_dev = None
try:
@ -609,6 +550,8 @@ def dev(request, gid, uid):
def clear_dev(request, gid, uid):
try:
abon = models.Abon.objects.get(pk=uid)
if not request.user.has_perm('abonapp.change_abon', abon):
raise PermissionDenied
abon.device = None
abon.save(update_fields=['device'])
messages.success(request, _('Device has successfully unattached'))
@ -619,7 +562,7 @@ def clear_dev(request, gid, uid):
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def charts(request, gid, uid):
high = 100
@ -673,7 +616,7 @@ def charts(request, gid, uid):
@login_required
@permission_required('abonapp.add_extra_fields_model')
@permission_required('abonapp.add_extrafieldsmodel')
def make_extra_field(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
try:
@ -733,6 +676,7 @@ def extra_field_delete(request, gid, uid, fid):
@login_required
@permission_required('abonapp.can_ping')
def abon_ping(request):
ip = request.GET.get('cmd_param')
status = False
@ -753,7 +697,8 @@ def abon_ping(request):
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ok ping, %d/%d loses') % ping_result
status = True
else:
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _('no ping, %d/%d loses') % ping_result
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _(
'no ping, %d/%d loses') % ping_result
else:
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ping ok') + ' ' + str(ping_result)
status = True
@ -773,6 +718,8 @@ def abon_ping(request):
@mydefs.only_admins
def dials(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
if not request.user.has_perm('abonapp.can_view_abongroup', abon.group):
raise PermissionDenied
if hasattr(abon.group, 'pk') and abon.group.pk != int(gid):
return redirect('abonapp:dials', abon.group.pk, abon.pk)
if abon.telephone is not None and abon.telephone != '':
@ -804,6 +751,8 @@ def save_user_dev_port(request, gid, uid):
else:
port = DevPort.objects.get(pk=user_port)
abon = models.Abon.objects.get(pk=uid)
if not request.user.has_perm('abonapp.change_abon', abon):
raise PermissionDenied
abon.dev_port = port
if abon.is_dynamic_ip != is_dynamic_ip:
abon.is_dynamic_ip = is_dynamic_ip
@ -842,7 +791,8 @@ def street_add(request, gid):
def street_edit(request, gid):
try:
if request.method == 'POST':
streets_pairs = [(int(sid), sname) for sid, sname in zip(request.POST.getlist('sid'), request.POST.getlist('sname'))]
streets_pairs = [(int(sid), sname) for sid, sname in
zip(request.POST.getlist('sid'), request.POST.getlist('sname'))]
for sid, sname in streets_pairs:
street = models.AbonStreet.objects.get(pk=sid)
street.name = sname
@ -872,7 +822,7 @@ def street_del(request, gid, sid):
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_additionaltelephones')
def tels(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
telephones = abon.additional_telephones.all()
@ -923,17 +873,17 @@ def tel_del(request, gid, uid):
def abons(request):
ablist = [{
'id': abn.pk,
'tarif_id': abn.active_tariff().tariff.pk if abn.active_tariff() is not None else 0,
'ip': abn.ip_address.int_ip(),
'is_active': abn.is_active
} for abn in models.Abon.objects.all()]
'id': abn.pk,
'tarif_id': abn.active_tariff().tariff.pk if abn.active_tariff() is not None else 0,
'ip': abn.ip_address.int_ip(),
'is_active': abn.is_active
} for abn in models.Abon.objects.all()]
tarlist = [{
'id': trf.pk,
'speedIn': trf.speedIn,
'speedOut': trf.speedOut
} for trf in Tariff.objects.all()]
'id': trf.pk,
'speedIn': trf.speedIn,
'speedOut': trf.speedOut
} for trf in Tariff.objects.all()]
data = {
'subscribers': ablist,

30
accounts_app/forms.py

@ -1,12 +1,24 @@
# -*- coding: utf-8 -*-
from django import forms
from .models import UserProfile
from guardian.forms import UserObjectPermissionsForm
from guardian.shortcuts import assign_perm, remove_perm
class SetupPerms(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['user_permissions']
widgets = {
'user_permissions': forms.CheckboxSelectMultiple()
}
class MyUserObjectPermissionsForm(UserObjectPermissionsForm):
def save_obj_perms(self):
"""
Saves selected object permissions by creating new ones and removing
those which were not selected but already exists.
Should be called *after* form is validated.
"""
perms = set(self.cleaned_data[self.get_obj_perms_field_name()])
model_perms = set([c[0] for c in self.get_obj_perms_field_choices()])
init_perms = set(self.get_obj_perms_field_initial())
to_remove = (model_perms - perms) & init_perms
for perm in to_remove:
remove_perm(perm, self.user, self.obj)
for perm in perms - init_perms:
assign_perm(perm, self.user, self.obj)

70
accounts_app/locale/ru/LC_MESSAGES/django.po

@ -33,18 +33,6 @@ msgstr "Администраторы"
msgid "Groups"
msgstr "Группы"
#: accounts_app/templates/accounts/group.html:16
msgid "The current distribution of rights for groups"
msgstr "Действующее распределение прав для группы"
#: accounts_app/templates/accounts/group.html:22
msgid "Available rights"
msgstr "Доступные права"
#: accounts_app/templates/accounts/group.html:36
msgid "Rights for the group"
msgstr "Права группы"
#: accounts_app/templates/accounts/group.html:44
#: accounts_app/templates/accounts/profile_chgroup.html:20
#: accounts_app/templates/accounts/settings/ch_info.html:66
@ -58,22 +46,6 @@ msgstr "Сохранить"
msgid "Reset"
msgstr "Сбросить"
#: accounts_app/templates/accounts/group_list.html:11
msgid "Admin groups list"
msgstr "Список групп администраторов"
#: accounts_app/templates/accounts/group_list.html:20
msgid "Group"
msgstr "Группа"
#: accounts_app/templates/accounts/group_list.html:40
msgid "Groups does not found"
msgstr "Нет групп"
#: accounts_app/templates/accounts/group_list.html:47
msgid "Add group"
msgstr "Добавить группу"
#: accounts_app/templates/accounts/index.html:8
#: accounts_app/templates/accounts/settings/ch_info.html:37
msgid "Telephone"
@ -186,11 +158,47 @@ msgstr "Настройка прав"
msgid "Edit"
msgstr "Редактировать"
msgid "Set a task"
msgstr "Дать задачу"
msgid "Please select an image"
msgstr "Пожалуйста выберите изображение"
msgid "Avatar successfully changed"
msgstr "Аватар успешно изменён"
msgid "Access to groups"
msgstr "Доступ к группам"
msgid "The list of user groups to which the account has access"
msgstr "Список групп абонентов, к которым учётка имеет доступ"
msgid "The responsibility of the staff of the group of subscribers"
msgstr "Ответственность работника за группы абонентов"
msgid "Not set"
msgstr "Не найдено"
msgid "Change permission for that object"
msgstr "Изменение прав доступа для выбранного объекта"
msgid "Permissions has successfully updated"
msgstr "Права успешно обновлены"
msgid "Profile is superuser, permissions to change it makes no sense"
msgstr "Учётная запись является суперпользователем, разрешения менять нет смысла"
msgid "Staff account profile"
msgstr "Учётная запись работника"
msgid "Staff account profiles"
msgstr "Учётные записи работников"
msgid "Can view staff profile"
msgstr "Может просматривать учётку сотрудника"
msgid "Pick object for edit permissions"
msgstr "Выберите объект для редактирования прав доступа"
msgid "Pick the type of object"
msgstr "Выберите тип объекта"
msgid "Profile has been deleted"
msgstr "Учётная запись удалена"

19
accounts_app/migrations/0008_auto_20170927_1838.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-27 18:38
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0007_auto_20170816_1109'),
]
operations = [
migrations.AlterModelOptions(
name='userprofile',
options={'permissions': (('can_view_userprofile', 'Может просматривать учётку сотрудника'),), 'verbose_name': 'Учётная запись работника', 'verbose_name_plural': 'Учётные записи работников'},
),
]

10
accounts_app/models.py

@ -43,6 +43,9 @@ class MyUserManager(BaseUserManager):
user.save(using=self._db)
return user
def get_queryset(self):
return super(MyUserManager, self).get_queryset().filter(is_admin=True)
class UserProfile(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=127, unique=True)
@ -91,3 +94,10 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
def __str__(self):
return self.get_full_name()
class Meta:
permissions = (
('can_view_userprofile', _('Can view staff profile')),
)
verbose_name = _('Staff account profile')
verbose_name_plural = _('Staff account profiles')

30
accounts_app/templates/accounts/ext.htm

@ -22,11 +22,24 @@
{% endif %}
<div class="caption btn-group btn-group-sm">
{% if userprofile == request.user %}
<a href="{% url 'acc_app:setup_info' %}" class="btn btn-primary btn-sm" role="button">
<span class="glyphicon glyphicon-edit"></span> {% trans 'Edit' %}</a>
<a href="{% url 'acc_app:setup_info' %}" class="btn btn-primary btn-sm" role="button">
<span class="glyphicon glyphicon-edit"></span>
{% trans 'Edit' %}
</a>
{% endif %}
{% if request.user.is_superuser %}
{% if userprofile.is_superuser %}
<a href="{% url 'acc_app:setup_perms' userprofile.pk %}" class="btn btn-default btn-sm" title="{% trans 'Profile is superuser, permissions to change it makes no sense' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-lock"></span>
{% trans 'Permission options' %}
</a>
{% else %}
<a href="{% url 'acc_app:setup_perms' userprofile.pk %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-lock"></span>
{% trans 'Permission options' %}
</a>
{% endif %}
{% endif %}
<a href="#" class="btn btn-default btn-sm disabled" role="button">
<span class="glyphicon glyphicon-star-empty"></span> {% trans 'Set a task' %}</a>
</div>
</div>
</div>
@ -46,6 +59,15 @@
{% trans 'Groups' %}
</a>
</li>
{% if request.user.is_superuser %}
{% url 'acc_app:set_abon_groups_permission' uid as set_ag_perm %}
<li{% if set_ag_perm == request.path %} class="active"{% endif %}>
<a href="{{ set_ag_perm }}">
<span class="glyphicon glyphicon-lock"></span>
{% trans 'Access to groups' %}
</a>
</li>
{% endif %}
</ul>
<div class="tab-content">
<div class="tab-pane active">

50
accounts_app/templates/accounts/group.html

@ -1,50 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:groups_list' %}">{% trans 'Groups' %}</a></li>
<li class="active">{{ group.name }}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'The current distribution of rights for groups' %} <b>{{ group.name }}</b></h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'acc_app:group_link' group.id %}" method="post">{% csrf_token %}
<div class="choice_wrapper">
<label for="sel_left">{% trans 'Available rights' %}</label>
<select name="allrights" multiple id="sel_left">
{% for rgt in all_rights %}
<option value="{{ rgt.id }}">{{ rgt.content_type }} &lt;{{ rgt.name }}&gt;</option>
{% endfor %}
</select>
</div>
<ul class="select_choose">
<li><a href="javascript:chooser_select('sel_left','sel_right');" class="btn btn-blue"><i
class="black icon-arrow-right"></i></a></li>
<li><a href="javascript:chooser_select('sel_right','sel_left');" class="btn btn-blue"><i
class="black icon-arrow-left"></i></a></li>
</ul>
<div class="choice_wrapper">
<label for="sel_right">{% trans 'Rights for the group' %}</label>
<select name="group_rights" multiple id="sel_right">
{% for rgt in grp_rights %}
<option value="{{ rgt.id }}">{{ rgt.content_type }} &lt;{{ rgt.name }}&gt;</option>
{% endfor %}
</select>
</div>
<br/>
<input type="submit" value="{% trans 'Save' %}"> <input type="reset" value="{% trans 'Reset' %}">
</form>
</div>
</div>
{% endblock %}

58
accounts_app/templates/accounts/group_list.html

@ -1,58 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li class="active">{% trans 'Groups' %}</li>
</ol>
<h3>{% trans 'Admin groups list' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th width="50">#</th>
<th>{% trans 'Group' %}</th>
<th class="col-sm-1">&mdash;</th>
</tr>
</thead>
<tbody>
{% for grp in groups %}
<tr>
<td>{{ grp.id }}</td>
<td><a href="{% url 'acc_app:group_link' grp.id %}">{{ grp.name }}</a></td>
<td class="btn-group">
<a href="#" class="btn btn-sm btn-info">
<span class="glyphicon glyphicon-edit"></span>
</a>
<a href="#" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove"></span>
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="3"><a href="#">{% trans 'Groups does not found' %}</a></td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="3">
<a href="#" class="btn btn-primary btn-sm disabled" title="{% trans 'Add group' %}">
<span class="glyphicon glyphicon-plus"></span>
</a>
</td>
</tr>
</tfoot>
</table>
</div>
{% include 'toolbar_page.html' with pag=groups %}
{% endblock %}

34
accounts_app/templates/accounts/perms/objects_of_type.html

@ -0,0 +1,34 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:other_profile' userprofile.pk %}">{{ userprofile.username }}</a></li>
<li><a href="{% url 'acc_app:perms_klasses' userprofile.pk klass %}">{% trans 'Permission options' %}</a></li>
<li class="active">&lt;{{ klass }}&gt; {{ klass_name }}</li>
</ol>
<h3>{% trans 'Pick object for edit permissions' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>obj</th>
</tr>
</thead>
<tbody>
{% for obj in objects %}<tr><td>
<a href="{% url 'acc_app:perms_edit' userprofile.pk klass obj.pk %}">{{ obj }}</a>
</td></tr>{% endfor %}
</tbody>
</table>
</div>
{% include 'toolbar_page.html' with pag=objects %}
{% endblock %}

36
accounts_app/templates/accounts/perms/objects_types.html

@ -0,0 +1,36 @@
{% extends 'base.html' %}
{% load i18n %}
{% load acc_tags %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:other_profile' userprofile.pk %}">{{ userprofile.username }}</a></li>
<li class="active">{% trans 'Permission options' %}</li>
</ol>
<h3>{% trans 'Pick the type of object' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Group' %}</th>
</tr>
</thead>
<tbody>
{% for klass in klasses %}
<tr>
<td>
<a href="{% url 'acc_app:perms_klasses' userprofile.pk klass %}">&lt;{{ klass }}&gt; {% klass_name klass %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

71
accounts_app/templates/accounts/perms/perms_edit.html

@ -0,0 +1,71 @@
{% extends 'base.html' %}
{% load i18n %}
{% load guardian_tags %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:other_profile' userprofile.pk %}">{{ userprofile.username }}</a></li>
<li><a href="{% url 'acc_app:setup_perms' userprofile.pk %}">{% trans 'Permission options' %}</a></li>
<li><a href="{% url 'acc_app:perms_klasses' userprofile.pk klass %}">&lt;{{ klass }}&gt; {{ klass_name }}</a>
</li>
<li class="active">{{ obj }}</li>
</ol>
<h3>{% trans 'Pick object for edit permissions' %}</h3>
{% include 'message_block.html' %}
{% if userprofile.is_superuser %}
<div class="alert alert-info alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<span class="glyphicon glyphicon-info-sign"></span>
{% trans 'Profile is superuser, permissions to change it makes no sense' %}
</div>
{% endif %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Change permission for that object' %}</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'acc_app:perms_edit' userprofile.pk klass obj.pk %}" method="post">{% csrf_token %}
{% get_obj_perms userprofile for obj as 'obj_perms' %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}" class="col-sm-3 control-label">{{ field.label }}</label>
<div class="col-sm-9">
<select multiple="multiple" id="{{ field.id_for_label }}" name="{{ field.html_name }}"
class="form-control">
{% for perm_value, perm_name in field.field.choices %}
{% if perm_value in obj_perms %}
<option value="{{ perm_value }}" selected>{{ perm_name }}</option>
{% else %}
<option value="{{ perm_value }}">{{ perm_name }}</option>
{% endif %}
{% empty %}
<option value="0">{% trans 'Not set' %}</option>
{% endfor %}
</select>
</div>
</div>
{% endfor %}
<div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
<button type="reset" class="btn btn-sm btn-default">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %}
</button>
</div>
</form>
</div>
</div>
{% endblock %}

6
accounts_app/templates/accounts/profile_chgroup.html

@ -2,15 +2,15 @@
{% load i18n %}
{% block content %}
<legend>{% trans 'The responsibility of the administrator of the group of subscribers' %}</legend>
<legend>{% trans 'The responsibility of the staff of the group of subscribers' %}</legend>
<form action="{% url 'acc_app:profile_setup_group' userprofile.id %}" method="post" role="form">{% csrf_token %}
{% for ag in abongroups %}
<div class="checkbox">
<label>
{% if userprofile in ag.profiles.all %}
<input name="ag" type="checkbox" value="{{ ag.id }}" checked/>
<input name="ag" type="checkbox" value="{{ ag.pk }}" checked/>
{% else %}
<input name="ag" type="checkbox" value="{{ ag.id }}"/>
<input name="ag" type="checkbox" value="{{ ag.pk }}"/>
{% endif %}
{{ ag.title }}
</label>

25
accounts_app/templates/accounts/set_abon_groups_permission.html

@ -0,0 +1,25 @@
{% extends request.is_ajax|yesno:'nullcont.htm,accounts/ext.htm' %}
{% load i18n %}
{% block content %}
<legend>{% trans 'The list of user groups to which the account has access' %}</legend>
<form action="{% url 'acc_app:set_abon_groups_permission' userprofile.pk %}" method="post" role="form">{% csrf_token %}
{% for ag in abongroups %}
<div class="checkbox">
<label>
{% if ag.pk in picked_groups_ids %}
<input name="ag" type="checkbox" value="{{ ag.pk }}" checked/>
{% else %}
<input name="ag" type="checkbox" value="{{ ag.pk }}"/>
{% endif %}
{{ ag.title }}
</label>
</div>
{% endfor %}
<div class="btn-group">
<input type="submit" class="btn btn-primary" value="{% trans 'Save' %}">
<input type="reset" class="btn btn-default" value="{% trans 'Reset' %}">
</div>
</form>
{% endblock %}

7
accounts_app/templates/accounts/settings/ext.htm

@ -36,13 +36,6 @@
{% trans 'Change self onfo' %}
</a>
</li>
{% if user.is_superuser %}
<li>
<a href="#livetab_content" data-tab-remote="{% url 'acc_app:setup_perms' user.id %}">
{% trans 'Permission options' %}
</a>
</li>
{% endif %}
</ul>
<div class="tab-content">
<div class="tab-pane active">

14
accounts_app/templates/accounts/settings/permissions.html

@ -1,14 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,accounts/settings/ext.htm' %}
{% block content %}
<form role="form" action="{% url 'acc_app:setup_perms' uid %}" method="post">{% csrf_token %}
{% for perm, pname in form.user_permissions.field.choices %}
<div class="checkbox">
<label>
<input type="checkbox">
{{ pname }}
</label>
</div>
{% endfor %}
</form>
{% endblock %}

14
accounts_app/templates/accounts/settings/test.html

@ -0,0 +1,14 @@
<p>
<label for="id_permissions">Permissions:</label>
<select multiple="multiple" id="id_permissions" name="permissions">
<option value="add_abongroup">Can add abon group</option>
<option value="can_add_ballance">Пополнение счёта</option>
<option value="can_view_abongroup" selected="selected">Can view subscriber group</option>
<option value="change_abongroup">Can change abon group</option>
<option value="delete_abongroup">Can delete abon group</option>
</select>
</p>

1
accounts_app/templatetags/__init__.py

@ -0,0 +1 @@
__author__ = 'bashmak'

18
accounts_app/templatetags/acc_tags.py

@ -0,0 +1,18 @@
from django import template
from django.db.models import Model
from django.apps import apps
from six import string_types, class_types
register = template.Library()
@register.simple_tag
def klass_name(klass):
if type(klass) is class_types and issubclass(klass, Model):
kl = klass
elif isinstance(klass, string_types):
app_label, model_name = klass.split('.', 1)
kl = apps.get_model(app_label, model_name)
else:
return 'Type not detected'
return kl._meta.verbose_name

8
accounts_app/urls.py

@ -20,13 +20,11 @@ urlpatterns = [
url(r'^(?P<uid>\d+)$', views.profile_show, name='other_profile'),
url(r'^(?P<uid>\d+)/perms$', views.perms, name='setup_perms'),
url(r'^(?P<uid>\d+)/perms/(?P<klass_name>[a-z_]+\.[a-zA-Z_]+)$', views.perms_klasses, name='perms_klasses'),
url(r'^(?P<uid>\d+)/perms/(?P<klass_name>[a-z_]+\.[a-zA-Z_]+)/(?P<obj_id>\d+)$', views.perms_edit, name='perms_edit'),
url(r'^(?P<uid>\d+)/chgroup$', views.chgroup, name='profile_setup_group'),
url(r'^(?P<uid>\d+)/del$', views.delete_profile, name='delete_profile'),
# назначить задание
url(r'^(?P<uid>\d+)/appoint_task$', views.appoint_task, name='appoint_task'),
url(r'^group/$', views.groups, name='groups_list'),
url(r'^group/(?P<uid>\d+)$', views.group, name='group_link')
url(r'^(?P<uid>\d+)/user_group_access$', views.set_abon_groups_permission, name='set_abon_groups_permission')
]

133
accounts_app/views.py

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import NoReverseMatch
from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib.auth.models import Group, Permission
from django.contrib import messages
from django.utils.translation import ugettext as _
from abonapp.models import AbonGroup
@ -12,6 +11,8 @@ from abonapp.models import AbonGroup
from photo_app.models import Photo
from .models import UserProfile
import mydefs
from guardian.decorators import permission_required_or_403 as permission_required
from guardian.shortcuts import get_objects_for_user, assign_perm, remove_perm
@login_required
@ -62,6 +63,8 @@ def profile_show(request, uid=0):
return redirect('acc_app:other_profile', uid=request.user.id)
usr = get_object_or_404(UserProfile, id=uid)
if request.user != usr and not request.user.has_perm('accounts_app.can_view_userprofile', usr):
raise PermissionDenied
if request.method == 'POST':
usr.username = request.POST.get('username')
usr.fio = request.POST.get('fio')
@ -85,12 +88,14 @@ def chgroup(request, uid):
usr = request.user
else:
usr = get_object_or_404(UserProfile, id=uid)
if usr != request.user and not request.user.has_perm('accounts_app.change_userprofile', usr):
raise PermissionDenied
if request.method == 'POST':
ag = request.POST.getlist('ag')
usr.abon_groups.clear()
usr.abon_groups.add(*[int(d) for d in ag])
usr.save()
abongroups = AbonGroup.objects.all()
abongroups = AbonGroup.objects.only('pk', 'title')
return render(request, 'accounts/profile_chgroup.html', {
'uid': uid,
'userprofile': usr,
@ -155,7 +160,7 @@ def ch_info(request):
@login_required
@permission_required('acc_app.add_userprofile')
@permission_required('accounts_app.add_userprofile')
def create_profile(request):
if request.method == 'POST':
username = request.POST.get('username')
@ -194,18 +199,20 @@ def create_profile(request):
@login_required
@mydefs.only_admins
def delete_profile(request, uid):
prf = get_object_or_404(UserProfile, id=uid)
if uid != request.user.id:
if not request.user.has_perm('acc_app.delete_userprofile'):
if not request.user.has_perm('acc_app.delete_userprofile', prf):
raise PermissionDenied
prf = get_object_or_404(UserProfile, id=uid)
prf.delete()
messages.success(request, _('Profile has been deleted'))
return redirect('acc_app:accounts_list')
@login_required
@mydefs.only_admins
def acc_list(request):
users = UserProfile.objects.filter(is_admin=True)
users = UserProfile.objects.filter(is_admin=True).exclude(pk=request.user.pk)
users = get_objects_for_user(request.user, 'accounts_app.can_view_userprofile', users)
users = mydefs.pag_mn(request, users)
return render(request, 'accounts/acc_list.html', {
'users': users
@ -213,54 +220,88 @@ def acc_list(request):
@login_required
@mydefs.only_admins
def perms(request, uid):
profile = get_object_or_404(UserProfile, id=uid)
own_permissions = UserProfile.get_all_permissions(profile)
return render(request, 'accounts/settings/permissions.html', {
'uid': uid,
'own_permissions': own_permissions
if not request.user.is_superuser:
raise PermissionDenied
userprofile = get_object_or_404(UserProfile, id=uid)
klasses = (
'abonapp.AbonGroup', 'abonapp.Abon', 'accounts_app.UserProfile',
'abonapp.AbonTariff', 'abonapp.AbonStreet', 'devapp.Device',
'abonapp.PassportInfo', 'abonapp.AdditionalTelephone'
)
return render(request, 'accounts/perms/objects_types.html', {
'userprofile': userprofile,
'klasses': klasses
})
@login_required
@mydefs.only_admins
def groups(request):
grps = Group.objects.all()
grps = mydefs.pag_mn(request, grps)
return render(request, 'accounts/group_list.html', {
'groups': grps
def perms_klasses(request, uid, klass_name):
if not request.user.is_superuser:
raise PermissionDenied
from django.apps import apps
userprofile = get_object_or_404(UserProfile, pk=uid)
app_label, model_name = klass_name.split('.', 1)
klass = apps.get_model(app_label, model_name)
objects = klass.objects.all()
objects = mydefs.pag_mn(request, objects)
return render(request, 'accounts/perms/objects_of_type.html', {
'userprofile': userprofile,
'klass': klass_name,
'klass_name': klass._meta.verbose_name,
'objects': objects
})
@login_required
@mydefs.only_admins
def group(request, uid):
uid = mydefs.safe_int(uid)
grp = get_object_or_404(Group, id=uid)
if request.method == 'POST':
group_rights = filter(lambda x: x[0] == 'group_rights', request.POST.lists())[0][1]
grp.permissions.clear()
for grr in group_rights:
rid = mydefs.safe_int(grr)
grp.permissions.add(rid)
grp.save()
return redirect('acc_app:profile_group_link', id=uid)
grp_rights = grp.permissions.all()
all_rights = Permission.objects.exclude(group=grp)
return render(request, 'accounts/group.html', {
'group': grp,
'all_rights': all_rights,
'grp_rights': grp_rights
def perms_edit(request, uid, klass_name, obj_id):
if not request.user.is_superuser:
raise PermissionDenied
from django.apps import apps
from .forms import MyUserObjectPermissionsForm
userprofile = get_object_or_404(UserProfile, pk=uid)
app_label, model_name = klass_name.split('.', 1)
klass = apps.get_model(app_label, model_name)
obj = get_object_or_404(klass, pk=obj_id)
frm = MyUserObjectPermissionsForm(userprofile, obj, request.POST or None)
if request.method == 'POST' and frm.is_valid():
frm.save_obj_perms()
messages.success(request, _('Permissions has successfully updated'))
return render(request, 'accounts/perms/perms_edit.html', {
'userprofile': userprofile,
'obj': obj,
'form': frm,
'klass': klass_name,
'klass_name': klass._meta.verbose_name
})
@login_required
@mydefs.only_admins
def appoint_task(req, uid):
uid = mydefs.safe_int(uid)
url = resolve_url('taskapp:add')
return redirect("%s?rp=%d" % (url, uid))
def set_abon_groups_permission(request, uid):
# Only superuser can change object permissions
if not request.user.is_superuser:
raise PermissionDenied
userprofile = get_object_or_404(UserProfile, pk=uid)
picked_groups = get_objects_for_user(userprofile, 'abonapp.can_view_abongroup', accept_global_perms=False)
picked_groups = picked_groups.values_list('pk', flat=True)
if request.method == 'POST':
checked_groups = [int(ag) for ag in request.POST.getlist('ag', default=0)]
for abon_group in AbonGroup.objects.all():
if abon_group.pk in checked_groups and abon_group.pk not in picked_groups:
assign_perm('abonapp.can_view_abongroup', userprofile, obj=abon_group)
elif abon_group.pk not in checked_groups and abon_group.pk in picked_groups:
remove_perm('abonapp.can_view_abongroup', userprofile, obj=abon_group)
return redirect('acc_app:set_abon_groups_permission', uid)
abongroups = AbonGroup.objects.only('pk', 'title')
return render(request, 'accounts/set_abon_groups_permission.html', {
'uid': uid,
'userprofile': userprofile,
'abongroups': abongroups,
'picked_groups_ids': picked_groups
})

5
clientsideapp/templates/clientsideapp/ext.html

@ -93,7 +93,10 @@
<div id="footer">
<div class="container">
<p class="text-muted">&copy;DN</p>
<p class="text-muted">
Напишите разработчику <i>djing-developer@yandex.ru</i>.
П.С. Разработчик и ваш провайдер не одно и то же.
</p>
</div>
</div>

9
devapp/locale/ru/LC_MESSAGES/django.po

@ -300,3 +300,12 @@ msgstr "Посмотреть устройство"
msgid "Eltex switch"
msgstr "Элтекс свич"
msgid "Can view device"
msgstr "Может видеть устройство"
msgid "Device"
msgstr "Устройство"
msgid "Can toggle ports"
msgstr "Может переключать порты"

23
devapp/migrations/0003_auto_20170927_1838.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-27 18:38
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('devapp', '0002_device_user_group'),
]
operations = [
migrations.AlterModelOptions(
name='device',
options={'permissions': (('can_view_device', 'Can view device'),), 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'},
),
migrations.AlterModelOptions(
name='port',
options={'permissions': (('can_toggle_ports', 'Can toggle ports'),), 'verbose_name': 'Port', 'verbose_name_plural': 'Ports'},
),
]

11
devapp/models.py

@ -8,6 +8,7 @@ from . import dev_types
from mapapp.models import Dot
from subprocess import call
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
DEVICE_TYPES = (
@ -34,6 +35,11 @@ class Device(models.Model):
class Meta:
db_table = 'dev'
permissions = (
('can_view_device', _('Can view device')),
)
verbose_name = _('Device')
verbose_name_plural = _('Devices')
def get_abons(self):
pass
@ -69,6 +75,11 @@ class Port(models.Model):
class Meta:
db_table = 'dev_port'
unique_together = (('device', 'num'))
permissions = (
('can_toggle_ports', _('Can toggle ports')),
)
verbose_name = _('Port')
verbose_name_plural = _('Ports')
def dev_post_save_signal(sender, instance, **kwargs):

37
devapp/templates/devapp/custom_dev_page/onu.html

@ -14,25 +14,28 @@
</div>
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item">{% trans 'Ip address' %}: {{ dev.ip_address }}</li>
<li class="list-group-item">{% trans 'Mac' %}: {{ dev.mac_addr }}</li>
<li class="list-group-item">{% trans 'Description' %} {{ dev.comment }}</li>
<li class="list-group-item">{% trans 'Ip address' %}: {{ dev.ip_address }}</li>
<li class="list-group-item">{% trans 'Mac' %}: {{ dev.mac_addr }}</li>
<li class="list-group-item">{% trans 'Description' %} {{ dev.comment }}</li>
{% for da in dev_accs %}
<li class="list-group-item">{% trans 'Attached user' %}:
{% if da.group %}
<a href="{% url 'abonapp:abon_home' da.group.pk da.pk %}" target="_blank">{{ da.get_full_name }}</a>
{% else %}
{{ da.get_full_name }}
{% endif %}
</li>
<li class="list-group-item">{% trans 'Attached user' %}:
{% if da.group %}
<a href="{% url 'abonapp:abon_home' da.group.pk da.pk %}"
target="_blank">{{ da.get_full_name }}</a>
{% else %}
{{ da.get_full_name }}
{% endif %}
</li>
{% endfor %}
{% if dev.parent_dev %}
<li class="list-group-item">
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.user_group %}
{% trans 'Parent device' %}: <a href="{% url 'devapp:view' pdgrp.pk pdev.pk %}" title="{{ pdev.mac_addr|default:'' }}" target="_blank">{{ pdev.ip_address }} {{ pdev.comment }}</a>
{% endwith %}
</li>
{% endif %}
{% if dev.parent_dev %}
<li class="list-group-item">
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.user_group %}
{% trans 'Parent device' %}:<a href="{% url 'devapp:view' pdgrp.pk pdev.pk %}"
title="{{ pdev.mac_addr|default:'' }}"
target="_blank">{{ pdev.ip_address }} {{ pdev.comment }}</a>
{% endwith %}
</li>
{% endif %}
</ul>
</div>
</div>

12
devapp/templates/devapp/devices_null_group.html

@ -38,19 +38,20 @@
</thead>
<tbody>
{% with can_del_dev=perms.devapp.delete_device can_change_dev=perms.devapp.change_device %}
{% for dev in devices %}
<tr>
<td><a href="{% url 'devapp:view' dev.user_group.pk|default:0 dev.id %}">{{ dev.ip_address }}</a></td>
<td><a href="{% url 'devapp:view' dev.user_group.pk|default:0 dev.pk %}">{{ dev.ip_address }}</a></td>
<td>{{ dev.comment }}</td>
<td>{{ dev.get_devtype_display }}</td>
<td class="btn-group btn-group-sm">
{% if perms.devapp.delete_device %}
<a href="{% url 'devapp:del' dev.user_group.pk|default:0 dev.id %}" class="btn btn-danger btn-sm">
{% if can_del_dev %}
<a href="{% url 'devapp:del' dev.user_group.pk|default:0 dev.pk %}" class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
{% if perms.devapp.change_device %}
<a href="{% url 'devapp:edit' dev.user_group.pk|default:0 dev.id %}" class="btn btn-default btn-sm">
{% if can_change_dev %}
<a href="{% url 'devapp:edit' dev.user_group.pk|default:0 dev.pk %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-edit"></span>
</a>
{% endif %}
@ -61,6 +62,7 @@
<td colspan="4">{% trans 'Devices does not found' %}. <a href="{% url 'devapp:add' 0 %}">{% trans 'Create' %}</a></td>
</tr>
{% endfor %}
{% endwith %}
</tbody>
<tfoot>

34
devapp/views.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.gis.shortcuts import render_to_text
from django.core.exceptions import PermissionDenied
from django.db.models import Q
@ -15,13 +15,18 @@ from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_help
from .forms import DeviceForm, PortForm
from abonapp.models import AbonGroup, Abon
from django.conf import settings
from guardian.decorators import permission_required_or_403 as permission_required
from guardian.shortcuts import get_objects_for_user
@login_required
@only_admins
def devices(request, grp):
group = get_object_or_404(AbonGroup, pk=grp)
devs = Device.objects.filter(user_group=grp)
if not request.user.has_perm('abonapp.can_view_abongroup', group):
raise PermissionDenied
devs = Device.objects.filter(user_group=grp).only('comment', 'mac_addr', 'devtype', 'user_group', 'pk',
'ip_address')
# фильтр
dr, field = order_helper(request)
@ -41,7 +46,7 @@ def devices(request, grp):
@login_required
@only_admins
def devices_null_group(request):
devs = Device.objects.filter(user_group=None)
devs = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address')
# фильтр
dr, field = order_helper(request)
if field:
@ -71,10 +76,12 @@ def devdel(request, did):
@login_required
@only_admins
@permission_required('devapp.can_view_device')
def dev(request, grp, devid=0):
devinst = get_object_or_404(Device, id=devid) if devid != 0 else None
user_group = get_object_or_404(AbonGroup, pk=grp)
if not request.user.has_perm('abonapp.can_view_abongroup', user_group):
raise PermissionDenied
devinst = get_object_or_404(Device, id=devid) if devid != 0 else None
already_dev = None
if request.method == 'POST':
@ -294,7 +301,7 @@ def add_single_port(request, grp, did):
@login_required
@only_admins
@permission_required('devapp.can_view_device')
def devview(request, did):
ports = None
uptime = 0
@ -318,7 +325,7 @@ def devview(request, did):
except DeviceDBException as e:
messages.error(request, e)
return render(request, 'devapp/custom_dev_page/'+template_name, {
return render(request, 'devapp/custom_dev_page/' + template_name, {
'dev': dev,
'ports': ports,
'uptime': uptime,
@ -327,7 +334,7 @@ def devview(request, did):
@login_required
@only_admins
@permission_required('devapp.can_toggle_ports')
def toggle_port(request, did, portid, status=0):
portid = int(portid)
status = int(status)
@ -338,9 +345,9 @@ def toggle_port(request, did, portid, status=0):
manager = dev.get_manager_klass()(dev.ip_address, dev.man_passw)
ports = manager.get_ports()
if status:
ports[portid-1].enable()
ports[portid - 1].enable()
else:
ports[portid-1].disable()
ports[portid - 1].disable()
else:
messages.warning(request, _('Not Set snmp device password'))
else:
@ -353,7 +360,8 @@ def toggle_port(request, did, portid, status=0):
@login_required
@only_admins
def group_list(request):
groups = AbonGroup.objects.all()
groups = AbonGroup.objects.all().order_by('title')
groups = get_objects_for_user(request.user, 'abonapp.can_view_abongroup', klass=groups, accept_global_perms=False)
return render(request, 'devapp/group_list.html', {
'groups': groups
})
@ -365,6 +373,8 @@ def search_dev(request):
if word is None:
results = [{'id': 0, 'text': ''}]
else:
results = Device.objects.filter(Q(comment__icontains=word) | Q(ip_address=word))[:16]
results = Device.objects.filter(
Q(comment__icontains=word) | Q(ip_address=word)
).only('pk', 'ip_address', 'comment')[:16]
results = [{'id': dev.pk, 'text': "%s: %s" % (dev.ip_address, dev.comment)} for dev in results]
return HttpResponse(dumps(results, ensure_ascii=False))

8
djing/settings_example.py

@ -16,6 +16,11 @@ DEBUG = True
ALLOWED_HOSTS = ['*']
# required for django-guardian
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', # default
'guardian.backends.ObjectPermissionBackend'
)
# Application definition
@ -38,7 +43,8 @@ INSTALLED_APPS = [
'clientsideapp',
'chatbot',
'django_messages',
'dialing_app'
'dialing_app',
'guardian'
]
MIDDLEWARE_CLASSES = [

3
mapapp/views.py

@ -1,5 +1,5 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.gis.shortcuts import render_to_text
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
@ -9,6 +9,7 @@ from .models import Dot
from .forms import DotForm
from mydefs import pag_mn
from devapp.models import Device
from guardian.decorators import permission_required_or_403 as permission_required
@login_required

2
requirements.txt

@ -14,3 +14,5 @@ mysqlclient
easysnmp
rq
pid
django-guardian
jsonfield

3
tariff_app/views.py

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.gis.shortcuts import render_to_text
from django.utils.translation import ugettext as _
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from guardian.decorators import permission_required_or_403 as permission_required
from .models import Tariff
import mydefs

3
taskapp/views.py

@ -1,11 +1,12 @@
# coding=utf-8
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from abonapp.models import Abon
from django.utils.translation import ugettext as _
from datetime import date
from guardian.decorators import permission_required_or_403 as permission_required
from .handle import TaskException
from .models import Task

2
templates/all_base.html

@ -47,7 +47,7 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Другое <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="{% url 'acc_app:setup_info' %}">Настройки</a></li>
<li><a href="{% url 'acc_app:profile' %}">Настройки</a></li>
<li class="divider"></li>
<li class="dropdown-header">Действия аккаунта</li>
<li><a href="{% url 'acc_app:logout' %}">Выйти</a></li>

Loading…
Cancel
Save