Browse Source

Merge branch 'devel' of https://github.com/nerosketch/djing into devel

devel
www-data 8 years ago
parent
commit
8c24905ed4
  1. 2
      chatbot/models.py
  2. 23
      devapp/views.py
  3. 26
      djing/global_base_views.py
  4. 307
      migrate_to_0.2.py
  5. 15
      static/js/my.js
  6. 23
      systemd_units/webdav_backup.py

2
chatbot/models.py

@ -57,7 +57,7 @@ class MessageQueue(models.Model):
('r', 'Read') ('r', 'Read')
) )
status = models.CharField(_('Status of message'), max_length=1, choices=STATUSES, default='n') status = models.CharField(_('Status of message'), max_length=1, choices=STATUSES, default='n')
# tag каждое приложение ставит своим чтоб делить сообщения между этими приложениями
# tag: each application puts its own to separate messages between these applications
tag = models.CharField(_('App tag'), max_length=6, default='none') tag = models.CharField(_('App tag'), max_length=6, default='none')
objects = MessageQueueManager() objects = MessageQueueManager()

23
devapp/views.py

@ -22,12 +22,11 @@ from guardian.shortcuts import get_objects_for_user
from chatbot.telebot import send_notify from chatbot.telebot import send_notify
from chatbot.models import ChatException from chatbot.models import ChatException
from jsonview.decorators import json_view from jsonview.decorators import json_view
from djing.global_base_views import HashAuthView, AllowedSubnetMixin, OrderingMixin
from djing import global_base_views
from .models import Device, Port, DeviceDBException, DeviceMonitoringException from .models import Device, Port, DeviceDBException, DeviceMonitoringException
from .forms import DeviceForm, PortForm from .forms import DeviceForm, PortForm
from mydefs import safe_int from mydefs import safe_int
PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@ -37,7 +36,7 @@ class BaseDeviceListView(ListView):
@method_decorator([login_required, only_admins], name='dispatch') @method_decorator([login_required, only_admins], name='dispatch')
class DevicesListView(BaseDeviceListView, OrderingMixin):
class DevicesListView(BaseDeviceListView, global_base_views.OrderingMixin):
context_object_name = 'devices' context_object_name = 'devices'
template_name = 'devapp/devices.html' template_name = 'devapp/devices.html'
@ -64,7 +63,7 @@ class DevicesListView(BaseDeviceListView, OrderingMixin):
@method_decorator([login_required, only_admins], name='dispatch') @method_decorator([login_required, only_admins], name='dispatch')
class DevicesWithoutGroupsListView(BaseDeviceListView, OrderingMixin):
class DevicesWithoutGroupsListView(BaseDeviceListView, global_base_views.OrderingMixin):
context_object_name = 'devices' context_object_name = 'devices'
template_name = 'devapp/devices_null_group.html' template_name = 'devapp/devices_null_group.html'
queryset = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address') queryset = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address')
@ -181,7 +180,7 @@ def manage_ports(request, device_id):
@method_decorator([login_required, only_admins], name='dispatch') @method_decorator([login_required, only_admins], name='dispatch')
class ShowSubscriberOnPort(DetailView):
class ShowSubscriberOnPort(global_base_views.RedirectWhenErrorMixin, DetailView):
template_name = 'devapp/manage_ports/modal_show_subscriber_on_port.html' template_name = 'devapp/manage_ports/modal_show_subscriber_on_port.html'
http_method_names = ['get'] http_method_names = ['get']
@ -192,6 +191,14 @@ class ShowSubscriberOnPort(DetailView):
obj = Abon.objects.get(device_id=dev_id, dev_port_id=port_id) obj = Abon.objects.get(device_id=dev_id, dev_port_id=port_id)
except Abon.DoesNotExist: except Abon.DoesNotExist:
raise Http404(gettext('Subscribers on port does not exist')) raise Http404(gettext('Subscribers on port does not exist'))
except Abon.MultipleObjectsReturned:
errmsg = gettext('More than one subscriber on device port')
# messages.error(self.request, errmsg)
raise global_base_views.RedirectWhenError(
resolve_url('devapp:fix_port_conflict', group_id=self.kwargs.get('group_id'), device_id=dev_id,
port_id=port_id),
errmsg
)
return obj return obj
@ -468,8 +475,8 @@ def fix_onu(request):
if parent is not None: if parent is not None:
manobj = parent.get_manager_object() manobj = parent.get_manager_object()
ports = manobj.get_list_keyval('.1.3.6.1.4.1.3320.101.10.1.1.3') ports = manobj.get_list_keyval('.1.3.6.1.4.1.3320.101.10.1.1.3')
text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' %\
(_('Device with mac address %(mac)s does not exist') % {'mac': mac})
text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' % \
(_('Device with mac address %(mac)s does not exist') % {'mac': mac})
for srcmac, snmpnum in ports: for srcmac, snmpnum in ports:
real_mac = ':'.join(['%x' % ord(i) for i in srcmac]) real_mac = ':'.join(['%x' % ord(i) for i in srcmac])
if mac == real_mac: if mac == real_mac:
@ -502,7 +509,7 @@ def fix_port_conflict(request, group_id, device_id, port_id):
}) })
class OnDevDown(AllowedSubnetMixin, HashAuthView):
class OnDevDown(global_base_views.AllowedSubnetMixin, global_base_views.HashAuthView):
# #
# Api view for monitoring devices # Api view for monitoring devices
# #

26
djing/global_base_views.py

@ -1,6 +1,7 @@
from hashlib import sha256 from hashlib import sha256
from json import dumps
from django.views.generic.base import View from django.views.generic.base import View
from django.http.response import HttpResponseForbidden, Http404, HttpResponseRedirect
from django.http.response import HttpResponseForbidden, Http404, HttpResponseRedirect, HttpResponse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.conf import settings from django.conf import settings
from django.views.generic import ListView from django.views.generic import ListView
@ -102,7 +103,22 @@ class OrderingMixin(object):
return "%s%s" % (dfx, order_by) return "%s%s" % (dfx, order_by)
class BaseListWithFiltering(ListView):
class RedirectWhenErrorMixin(object):
def get(self, request, *args, **kwargs):
try:
return super(RedirectWhenErrorMixin, self).get(request, *args, **kwargs)
except RedirectWhenError as e:
if request.is_ajax():
return HttpResponse(dumps({
'url': e.url,
'text': e.message or ''
}))
else:
return HttpResponseRedirect(e.url)
class BaseListWithFiltering(RedirectWhenErrorMixin, ListView):
""" """
When queryset contains filter and pagination than data may be missing, When queryset contains filter and pagination than data may be missing,
and original code is raising 404 error. We want to redirect without pagination. and original code is raising 404 error. We want to redirect without pagination.
@ -135,9 +151,3 @@ class BaseListWithFiltering(ListView):
'page_number': page_number, 'page_number': page_number,
'message': str(e) 'message': str(e)
}) })
def get(self, request, *args, **kwargs):
try:
return super(BaseListWithFiltering, self).get(request, *args, **kwargs)
except RedirectWhenError as e:
return HttpResponseRedirect(e.url)

307
migrate_to_0.2.py

@ -0,0 +1,307 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import shutil
from json import dump
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings")
from django.db.models import fields as django_fields
def get_fixture_from_unchanget_model(model_name: str, model_class):
"""
Создаёт фикстуру если модели между версиями не изменились
:param model_name: str 'app_label.model_name'
:param model_class: Model модель для которой надо сделать фикстуру
:return: список словарей
"""
print(model_name)
def get_fields(obj):
fields = dict()
for field in obj._meta.get_fields():
if isinstance(field, (django_fields.reverse_related.ManyToOneRel, django_fields.reverse_related.ManyToManyRel)):
continue
field_val = getattr(obj, field.name)
if field_val is None:
continue
if isinstance(field, django_fields.related.ManyToManyField):
fields[field.name] = [f.pk for f in field_val.all()]
elif isinstance(field, (django_fields.related.ForeignKey, django.contrib.contenttypes.fields.GenericForeignKey)):
fields[field.name] = field_val.pk
elif isinstance(field, django_fields.FloatField):
fields[field.name] = float(field_val)
elif isinstance(field, django_fields.DateTimeField):
fields[field.name] = str(field_val)
elif isinstance(field, django_fields.AutoField):
continue
else:
fields[field.name] = field_val
return fields
res = [{
'model': model_name,
'pk': obj.pk,
'fields': get_fields(obj)
} for obj in model_class.objects.all()]
return res
def dump_groups():
from abonapp import models
print('group_app.group')
res = [{
'model': 'group_app.group',
'pk': abon_group.pk,
'fields': {
'title': abon_group.title
}
} for abon_group in models.AbonGroup.objects.all()]
return res
def dump_abonapp():
from abonapp import models
# res += get_fixture_from_unchanget_model('abonapp.abonlog', models.AbonLog)
res = get_fixture_from_unchanget_model('abonapp.abontariff', models.AbonTariff)
res += get_fixture_from_unchanget_model('abonapp.abonstreet', models.AbonStreet)
res += get_fixture_from_unchanget_model('abonapp.extrafieldsmodel', models.ExtraFieldsModel)
print('abonapp.abon')
res += [{
'model': 'abonapp.abon',
'pk': abon.pk,
'fields': {
'current_tariff': abon.current_tariff.pk if abon.current_tariff else None,
'group': abon.group.pk if abon.group else None,
'ballance': abon.ballance,
'ip_address': abon.ip_address,
'description': abon.description,
'street': abon.street.pk if abon.street else None,
'house': abon.house,
'extra_fields': [a.pk for a in abon.extra_fields.all()],
'device': abon.device.pk if abon.device else None,
'dev_port': abon.dev_port if abon.dev_port else None,
'is_dynamic_ip': abon.is_dynamic_ip,
'markers': abon.markers
}
} for abon in models.Abon.objects.filter(is_admin=False)]
res += get_fixture_from_unchanget_model('abonapp.passportinfo', models.PassportInfo)
res += get_fixture_from_unchanget_model('abonapp.invoiceforpayment', models.InvoiceForPayment)
res += get_fixture_from_unchanget_model('abonapp.alltimepaylog', models.AllTimePayLog)
res += get_fixture_from_unchanget_model('abonapp.abonrawpassword', models.AbonRawPassword)
res += get_fixture_from_unchanget_model('abonapp.additionaltelephone', models.AdditionalTelephone)
res += get_fixture_from_unchanget_model('abonapp.periodicpayforid', models.PeriodicPayForId)
return res
def dump_tariffs():
from tariff_app import models
res = get_fixture_from_unchanget_model('tariff_app.tariff', models.Tariff)
res += get_fixture_from_unchanget_model('tariff_app.periodicpay', models.PeriodicPay)
return res
def dump_devs():
from devapp import models
print('devapp.device')
res = [{
'model': 'devapp.device',
'pk': dv.pk,
'fields': {
'ip_address': dv.ip_address,
'mac_addr': dv.mac_addr,
'devtype': dv.devtype,
'man_passw': dv.man_passw,
'group': dv.user_group.pk if dv.user_group else None,
'parent_dev': dv.parent_dev.pk if dv.parent_dev else None
}
} for dv in models.Device.objects.all()]
res += get_fixture_from_unchanget_model('devapp.port', models.Port)
return res
def dump_accounts():
from accounts_app import models
from abonapp.models import AbonGroup
def get_responsibility_groups(account):
responsibility_groups = AbonGroup.objects.filter(profiles__in=[account])
ids = [ag.pk for ag in responsibility_groups]
return ids
print('accounts_app.baseaccount')
res = [{
'model': 'accounts_app.baseaccount',
'pk': up.pk,
'fields': {
'username': up.username,
'fio': up.fio,
'birth_day': up.birth_day,
'is_active': up.is_active,
'is_admin': up.is_admin,
'telephone': up.telephone,
'password': up.password,
'last_login': up.last_login
}
} for up in models.UserProfile.objects.all()]
print('accounts_app.userprofile')
res += [{
'model': 'accounts_app.userprofile',
'pk': up.pk,
'fields': {
'avatar': up.avatar.pk if up.avatar else None,
'email': up.email,
'responsibility_groups': get_responsibility_groups(up)
}
} for up in models.UserProfile.objects.filter(is_admin=True)]
return res
def dump_photos():
from photo_app.models import Photo
print('photo_app.photo')
res = [{
'model': 'photo_app.photo',
'pk': p.pk,
'fields': {
'image': "%s" % p.image,
'wdth': p.wdth,
'heigt': p.heigt
}
} for p in Photo.objects.all()]
return res
def dump_chatbot():
from chatbot import models
res = get_fixture_from_unchanget_model('chatbot.telegrambot', models.TelegramBot)
res += get_fixture_from_unchanget_model('chatbot.messagehistory', models.MessageHistory)
res += get_fixture_from_unchanget_model('chatbot.messagequeue', models.MessageQueue)
return res
def dump_map():
from mapapp import models
res = get_fixture_from_unchanget_model('mapapp.dot', models.Dot)
return res
def dump_task_app():
from taskapp import models
res = get_fixture_from_unchanget_model('taskapp.changelog', models.ChangeLog)
res += get_fixture_from_unchanget_model('taskapp.task', models.Task)
res += get_fixture_from_unchanget_model('taskapp.ExtraComment', models.ExtraComment)
return res
def dump_auth():
from django.contrib.auth import models
res = get_fixture_from_unchanget_model('auth.group', models.Group)
res += get_fixture_from_unchanget_model('auth.permission', models.Permission)
return res
def dump_guardian():
from guardian import models
res = get_fixture_from_unchanget_model('guardian.groupobjectpermission', models.GroupObjectPermission)
res += get_fixture_from_unchanget_model('guardian.userobjectpermission', models.UserObjectPermission)
return res
def make_migration():
from datetime import datetime, date
def my_date_converter(o):
if isinstance(o, datetime) or isinstance(o, date):
return "%s" % o
def appdump(path, func):
fname = os.path.join(*path)
path_dir = os.path.join(*path[:-1])
if not os.path.isdir(path_dir):
os.mkdir(path_dir)
with open(fname, 'w') as f:
dump(func(), f, default=my_date_converter, ensure_ascii=False)
if not os.path.isdir('fixtures'):
os.mkdir('fixtures')
appdump(['fixtures', 'group_app', 'groups_fixture.json'], dump_groups)
appdump(['fixtures', 'tariff_app', 'tariffs_fixture.json'], dump_tariffs)
appdump(['fixtures', 'photo_app', 'photos_fixture.json'], dump_photos)
appdump(['fixtures', 'devapp', 'devs_fixture.json'], dump_devs)
appdump(['fixtures', 'accounts_app', 'accounts_fixture.json'], dump_accounts)
appdump(['fixtures', 'abonapp', 'abon_fixture.json'], dump_abonapp)
appdump(['fixtures', 'chatbot', 'chatbot_fixture.json'], dump_chatbot)
appdump(['fixtures', 'mapapp', 'map_fixture.json'], dump_map)
appdump(['fixtures', 'taskapp', 'task_fixture.json'], dump_task_app)
appdump(['fixtures', 'accounts_app', 'auth_fixture.json'], dump_auth)
appdump(['fixtures', 'accounts_app', 'guardian_fixture.json'], dump_guardian)
def move_to_fixtures_dirs():
fixdir = 'fixtures'
for dr in os.listdir(fixdir):
fixture_dir = os.path.join(fixdir, dr)
for fixture_file in os.listdir(fixture_dir):
from_file = os.path.join(fixture_dir, fixture_file)
dst_dir = os.path.join(dr, fixdir)
to_file = os.path.join(dst_dir, fixture_file)
if not os.path.isdir(dst_dir):
os.mkdir(dst_dir)
shutil.copyfile(from_file, to_file)
print('cp %s -> %s' % (from_file, to_file))
def apply_fixtures():
from django.core.management import execute_from_command_line
from accounts_app.models import UserProfile
from django.contrib.auth import models
UserProfile.objects.filter(username='AnonymousUser').delete()
print('clearing auth.group')
models.Group.objects.all().delete()
print('clearing auth.permission')
models.Permission.objects.all().delete()
print('./manage.py loaddata -v2 ...')
execute_from_command_line([sys.argv[0], 'loaddata', '-v', '2',
'groups_fixture.json', 'tariffs_fixture.json', 'photos_fixture.json',
'devs_fixture.json', 'accounts_fixture.json', 'abon_fixture.json',
'chatbot_fixture.json', 'map_fixture.json', 'task_fixture.json',
'auth_fixture.json', 'guardian_fixture.json'
])
if __name__ == '__main__':
if len(sys.argv) < 2:
print('Usage: ./migrate_to_0.2.py [makedump OR applydump]')
exit(1)
choice = sys.argv[1]
if choice == 'applydump':
django.setup()
move_to_fixtures_dirs()
apply_fixtures()
os.remove('fixtures')
elif choice == 'makedump':
django.setup()
make_migration()
else:
print('Unexpected choice')

15
static/js/my.js

@ -214,7 +214,7 @@ $(document).ajaxError(function (ev, jqXHR, ajaxSettings, thrownError) {
} }
if(settings.news_url){ if(settings.news_url){
// прверяем новости раз в минуту
// once per minute check news
var tiid = setInterval(check_news, settings.check_interval*1000); var tiid = setInterval(check_news, settings.check_interval*1000);
//Notification.requestPermission(on_ask_perm); //Notification.requestPermission(on_ask_perm);
@ -266,13 +266,20 @@ $(document).ready(function () {
}); });
$('.btn-modal').on('click', function(){ $('.btn-modal').on('click', function(){
$.get(this.href, function(r){
show_ModalMyContent(r);
$.get(this.href, function(response){
console.log(response);
try{
var r = $.parseJSON(response);
console.log(r.text);
window.location.replace(r.url);
}catch (e){
show_ModalMyContent(response);
}
}); });
return false; return false;
}); });
// кнопка посылающая комманду и возвращающая результат выполнения
// button that send command and return response of that
$('.btn-cmd').on('click', function(){ $('.btn-cmd').on('click', function(){
var cmd_param = $(this).attr('data-param'); var cmd_param = $(this).attr('data-param');
var self = $(this); var self = $(this);

23
systemd_units/webdav_backup.py

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import webdav.client as wc
from webdav.client import WebDavException
from sys import argv from sys import argv
from datetime import datetime, timedelta
import webdav.client as wc
options = { options = {
@ -10,11 +10,26 @@ options = {
'webdav_password': "YANDEX PASSWORD" 'webdav_password': "YANDEX PASSWORD"
} }
def remove_old_files(border_time : datetime, client):
# files that older than border_time will be removed
for file in client.list('ISBackups'):
fdate = datetime.strptime(file, 'djing%Y-%m-%d_%H.%M.%S.sql.gz')
if fdate < border_time:
del_fname = 'ISBackups/%' % file
client.clean( del_fname )
print("rm %s" % del_fname)
if __name__ == '__main__': if __name__ == '__main__':
reqfile = argv[1] reqfile = argv[1]
try: try:
client = wc.Client(options) client = wc.Client(options)
client.upload_sync(remote_path="ISBackups/%s" % reqfile, local_path="/var/backups/%s" % reqfile)
except WebDavException as we:
if reqfile == 'rotate':
border_time = datetime.now() - timedelta(month=3)
remove_old_files(border_time, client)
else:
client.upload_sync(remote_path="ISBackups/%s" % reqfile, local_path="/var/backups/%s" % reqfile)
except wc.WebDavException as we:
print(we, type(we)) print(we, type(we))
Loading…
Cancel
Save