From 3f74e776750d1ed06d8ec0227f818bfadc735d5f Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 29 Mar 2017 02:12:01 +0300 Subject: [PATCH 01/11] =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cron.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cron.py b/cron.py index 582ce34..020036e 100755 --- a/cron.py +++ b/cron.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import django @@ -51,7 +51,5 @@ def main(): if __name__ == "__main__": try: main() - except NasNetworkError as e: - print(e) - except NasFailedResult as e: - print(e) + except (NasNetworkError, NasFailedResult) as e: + print('NAS:', e) From d33112bacd099994a319b1a586568b4d59fe0098 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 4 Apr 2017 22:25:51 +0300 Subject: [PATCH 02/11] fixbug --- abonapp/models.py | 29 ++++++++++++++--------------- agent/mod_mikrotik.py | 19 +++++++++++++------ agent/structs.py | 8 +++++--- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/abonapp/models.py b/abonapp/models.py index 1f402b0..b271433 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -332,7 +332,7 @@ class Abon(UserProfile): agent_trf = TariffStruct(inst_tariff.id, inst_tariff.speedIn, inst_tariff.speedOut) else: agent_trf = TariffStruct() - return AbonStruct(self.pk, user_ip, agent_trf) + return AbonStruct(self.pk, user_ip, agent_trf, bool(self.is_active)) class InvoiceForPayment(models.Model): @@ -403,21 +403,20 @@ def abon_post_save(sender, instance, **kwargs): timeout = None if hasattr(instance, 'opt82'): timeout = 3600 - tm = Transmitter() agent_abon = instance.build_agent_struct() if agent_abon is None: return True - if kwargs['created']: - # создаём абонента - tm.add_user(agent_abon, ip_timeout=timeout) - else: - # обновляем абонента на NAS - tm.update_user(agent_abon, ip_timeout=timeout) - # если не активен то приостановим услугу - if instance.is_active: - tm.start_user(agent_abon) + try: + tm = Transmitter() + if kwargs['created']: + # создаём абонента + tm.add_user(agent_abon, ip_timeout=timeout) else: - tm.pause_user(agent_abon) + # обновляем абонента на NAS + tm.update_user(agent_abon, ip_timeout=timeout) + + except (NasFailedResult, NasNetworkError): + return True def abon_del_signal(sender, instance, **kwargs): @@ -427,7 +426,7 @@ def abon_del_signal(sender, instance, **kwargs): tm = Transmitter() # нашли абонента, и удаляем его на NAS tm.remove_user(ab) - except NasFailedResult: + except (NasFailedResult, NasNetworkError): return True @@ -444,7 +443,7 @@ def abontariff_post_save(sender, instance, **kwargs): return True tm = Transmitter() tm.update_user(agent_abon) - except NasFailedResult: + except (NasFailedResult, NasNetworkError): return True @@ -459,7 +458,7 @@ def abontariff_del_signal(sender, instance, **kwargs): agent_abon = instance.abon.build_agent_struct() tm = Transmitter() tm.pause_user(agent_abon) - except NasFailedResult: + except (NasFailedResult, NasNetworkError): return True diff --git a/agent/mod_mikrotik.py b/agent/mod_mikrotik.py index 76dd74e..086f8f0 100644 --- a/agent/mod_mikrotik.py +++ b/agent/mod_mikrotik.py @@ -10,7 +10,7 @@ from . import settings import re -DEBUG=False +DEBUG=True LIST_USERS_ALLOWED = 'DjingUsersAllowed' LIST_USERS_BLOCKED = 'DjingUsersBlocked' @@ -205,7 +205,8 @@ class TransmitterManager(BaseTransmitter): uid=int(info['=name'][3:]), #FIXME: тут в разных микротиках или =target-addresses или =target ip=info['=target'][:-3], - tariff=t + tariff=t, + is_active=False if info['=disabled'] == 'false' else True ) return ShapeItem(abon=a, sid=info['=.id'].replace('*', '')) except KeyError: @@ -388,6 +389,14 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager): #ищем ip абонента в списке ip find_res = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED) + if not user.is_active: + # если не активен - то и обновлять не надо + # но и выключить на всяк случай надо, а то вдруг был включён + if len(find_res) > 1: + # и если найден был - то удалим ip из разрешённых + IpAddressListManager.remove(self, find_res[0]['=.id']) + return + # если не найден (mikrotik возвращает пустой словарь в списке если ничего нет) if len(find_res) < 2: # добавим запись об абоненте @@ -408,13 +417,11 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager): # приостановливаем обслуживание абонента def pause_user(self, user): - IpAddressListManager.disable(self, user) - QueueManager.disable(self, user) + pass # продолжаем обслуживание абонента def start_user(self, user): - QueueManager.enable(self, user) - IpAddressListManager.enable(self, user) + pass # Тарифы хранить нам не надо, так что методы тарифов ниже не реализуем def add_tariff_range(self, tariff_list): diff --git a/agent/structs.py b/agent/structs.py index 9f444b0..7b84fc4 100644 --- a/agent/structs.py +++ b/agent/structs.py @@ -80,25 +80,27 @@ class TariffStruct(BaseStruct): # Абонент из базы class AbonStruct(BaseStruct): - def __init__(self, uid=None, ip=None, tariff=None): + def __init__(self, uid=None, ip=None, tariff=None, is_active=True): self.uid = int(uid) self.ip = IpStruct(ip) assert isinstance(tariff, TariffStruct) self.tariff = tariff + self.is_active = is_active def serialize(self): assert isinstance(self.tariff, TariffStruct) assert isinstance(self.ip, IpStruct) - dt = pack("!LII", self.uid, self.ip.get_int(), self.tariff.tid) + dt = pack("!LII?", self.uid, self.ip.get_int(), self.tariff.tid, self.is_active) return dt def deserialize(self, data, tariff=None): - dt = unpack("!LII", data) + dt = unpack("!LII?", data) self.uid = dt[0] self.ip = IpStruct(dt[1]) if tariff is not None: assert isinstance(tariff, TariffStruct) self.tariff = tariff + self.is_active = dt['3'] return self def __eq__(self, other): From 56ae5bf5ab5b2fb0e87b6963fcc20c244250780c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 4 Apr 2017 22:26:14 +0300 Subject: [PATCH 03/11] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BB=D0=B8=D1=88=D0=BD=D0=B5=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cron.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cron.py b/cron.py index 020036e..3e16d91 100755 --- a/cron.py +++ b/cron.py @@ -34,11 +34,6 @@ def main(): # ищем абонента в списке инфы из nas tm.update_user(ab) - # если не активен то приостановим услугу - if user.is_active: - tm.start_user(ab) - else: - tm.pause_user(ab) except NasNetworkError as er: print("Error:", er) From 76eda01d2df6530915c38020153dd717599e0e96 Mon Sep 17 00:00:00 2001 From: http Date: Thu, 6 Apr 2017 15:55:31 +0300 Subject: [PATCH 04/11] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20regexp=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=B0?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- abonapp/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abonapp/forms.py b/abonapp/forms.py index a253024..4d3e3e0 100644 --- a/abonapp/forms.py +++ b/abonapp/forms.py @@ -76,7 +76,7 @@ class AbonForm(forms.ModelForm): class Opt82Form(forms.ModelForm): - mac = MACAddressField(widget=forms.TextInput(attrs={'class': 'form-control', 'pattern': r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$', 'required': ''})) + mac = MACAddressField(widget=forms.TextInput(attrs={'class': 'form-control', 'pattern': r'^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$', 'required': ''})) class Meta: model = models.Opt82 fields = '__all__' From 84d7dd5de94a7571a2c68a7e96d1d5f439228202 Mon Sep 17 00:00:00 2001 From: http Date: Thu, 6 Apr 2017 15:56:44 +0300 Subject: [PATCH 05/11] =?UTF-8?q?=D0=9F=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=B8=D1=8E=20=D1=82=D1=80=D0=B0=D1=84=D0=B8?= =?UTF-8?q?=D0=BA=2064kb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent/structs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/structs.py b/agent/structs.py index 9f444b0..8ec5600 100644 --- a/agent/structs.py +++ b/agent/structs.py @@ -53,8 +53,8 @@ class TariffStruct(BaseStruct): def __init__(self, tariff_id=0, speedIn=None, speedOut=None): self.tid = tariff_id - self.speedIn = speedIn if speedIn is not None else 5.0625 - self.speedOut = speedOut if speedOut is not None else 5.0625 + self.speedIn = speedIn if speedIn is not None else 0.0625 + self.speedOut = speedOut if speedOut is not None else 0.0625 def serialize(self): dt = pack("!Iff", int(self.tid), float(self.speedIn), float(self.speedOut)) From cae86b750eec3a586bdd1f3319c71fc43e4a12bb Mon Sep 17 00:00:00 2001 From: http Date: Thu, 6 Apr 2017 22:14:52 +0300 Subject: [PATCH 06/11] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=83=D1=82=D1=8C=20=D0=BA=20attach?= =?UTF-8?q?ments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- taskapp/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskapp/models.py b/taskapp/models.py index 649ad70..e738742 100644 --- a/taskapp/models.py +++ b/taskapp/models.py @@ -67,7 +67,7 @@ class Task(models.Model): out_date = models.DateField(null=True, blank=True, default=_delta_add_days) time_of_create = models.DateTimeField(auto_now_add=True) state = models.CharField(max_length=1, choices=TASK_STATES, default=TASK_STATES[0][0]) - attachment = models.ImageField(upload_to='task_attachments/%Y.%m.%d', blank=True, null=True) + attachment = models.ImageField(upload_to='media/task_attachments/%Y.%m.%d', blank=True, null=True) mode = models.CharField(max_length=2, choices=TASK_TYPES, default=TASK_TYPES[0][0]) abon = models.ForeignKey(Abon, on_delete=models.SET_NULL, null=True, blank=True, related_name='+') From eaecd87e0dc9647a5c94625dad842039cb44ac55 Mon Sep 17 00:00:00 2001 From: http Date: Fri, 7 Apr 2017 01:14:01 +0300 Subject: [PATCH 07/11] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- djing/utils/load_from_nodeny.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/djing/utils/load_from_nodeny.py b/djing/utils/load_from_nodeny.py index f01e43c..c8aa523 100755 --- a/djing/utils/load_from_nodeny.py +++ b/djing/utils/load_from_nodeny.py @@ -35,9 +35,12 @@ def load_service(cursor, uid): def load_users(cursor, grp_id): # выбираем абонентов sql = r"SELECT users.name, users.fio, data0._adr_telefon, dictionary.v AS street, data0._adr_house, data0._birthday, " \ - "users.grp, INET_NTOA(ip_pool.ip) AS ip, users.balance, AES_DECRYPT(users.passwd, 'Vu6saiZa') as decr_passwd, users.id " \ - "FROM users LEFT JOIN data0 ON (data0.uid = users.id) LEFT JOIN dictionary ON (dictionary.k = data0._adr_street " \ - "AND dictionary.type = 'street') LEFT JOIN ip_pool ON (ip_pool.uid = users.id) WHERE users.grp = %d" % grp_id + "users.grp, INET_NTOA(ip_pool.ip) AS ip, users.balance, AES_DECRYPT(users.passwd, 'Vu6saiZa') as decr_passwd, users.id, " \ + "mac_uid.device_mac, mac_uid.device_port, mac_uid.oneconnect " \ + "FROM users " \ + "LEFT JOIN data0 ON (data0.uid = users.id) LEFT JOIN dictionary ON (dictionary.k = data0._adr_street AND dictionary.type = 'street') " \ + "LEFT JOIN mac_uid ON (mac_uid.uid=users.id) " \ + "LEFT JOIN ip_pool ON (ip_pool.uid = users.id) WHERE users.grp = %d" % grp_id cursor.execute(sql) users = [{ 'name': res[0], @@ -50,7 +53,12 @@ def load_users(cursor, grp_id): 'ip': str(res[7] or ''), 'balance': float(res[8]), 'passw': res[9].decode("utf-8") if res[9] is not None else '', - 'service': load_service(cursor, int(res[10])) + 'service': load_service(cursor, int(res[10])), + 'opt82': { + 'dev_mac': res[11], + 'dev_port': res[12], + 'oneconnect': res[13] + } } for res in cursor.fetchall()] return users From bbcb26d42f539fcdd5ddd4aba81e425b863790e4 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 7 Apr 2017 01:26:16 +0300 Subject: [PATCH 08/11] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D1=83=D1=82=D1=8C=20=D0=BA=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=80=D1=82=D0=B8=D0=BD=D0=BA=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- taskapp/migrations/0012_auto_20170407_0124.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 taskapp/migrations/0012_auto_20170407_0124.py diff --git a/taskapp/migrations/0012_auto_20170407_0124.py b/taskapp/migrations/0012_auto_20170407_0124.py new file mode 100644 index 0000000..9128309 --- /dev/null +++ b/taskapp/migrations/0012_auto_20170407_0124.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-04-06 22:24 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('taskapp', '0011_auto_20170116_0126'), + ] + + operations = [ + migrations.AlterField( + model_name='task', + name='attachment', + field=models.ImageField(blank=True, null=True, upload_to='media/task_attachments/%Y.%m.%d'), + ), + ] From e3e8a5e345dc55d69bdf17f8574561abeee36e3e Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 7 Apr 2017 04:12:23 +0300 Subject: [PATCH 09/11] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20option82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- djing/utils/save_from_nodeny.py | 70 +++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/djing/utils/save_from_nodeny.py b/djing/utils/save_from_nodeny.py index 060a43e..ab5cc4b 100755 --- a/djing/utils/save_from_nodeny.py +++ b/djing/utils/save_from_nodeny.py @@ -5,14 +5,14 @@ import os from json import load import django from django.utils import timezone +from django.core.exceptions import ValidationError os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings") django.setup() -from abonapp.models import Abon, AbonGroup, AbonRawPassword, AbonStreet, AbonTariff +from abonapp.models import Abon, AbonGroup, AbonRawPassword, AbonStreet, AbonTariff, Opt82 from ip_pool.models import IpPoolItem from tariff_app.models import Tariff - class DumpService(object): price = 0.0 speedIn = 0.0 @@ -65,6 +65,12 @@ class DumpAbon(object): self.ip = obj['ip'] if obj['ip'] != '' else None self.balance = obj['balance'] self.passw = obj['passw'] + if obj['opt82']['dev_mac'] is not None and obj['opt82']['dev_port'] is not None: + self.opt82 = { + 'dev_mac': obj['opt82']['dev_mac'], + 'dev_port': obj['opt82']['dev_port'] + } + if obj['service'] is not None: self.service = DumpService(obj['service']) else: @@ -99,6 +105,11 @@ class DumpAbon(object): self.service = DumpService.build_from_db(srv) else: self.service = None + if obj.opt82 is not None and obj.opt82.mac is not None and obj.opt82.port is not None: + self.opt82 = { + 'dev_mac': obj.opt82.mac, + 'dev_port': obj.opt82.port + } return self def __eq__(self, other): @@ -135,6 +146,26 @@ def add_service_if_not_exist(service): return obj +def add_raw_password_if_not_exist(acc, raw_passw): + try: + psw = AbonRawPassword.objects.get(account=acc) + #if psw != raw_passw: + # psw.passw_text = raw_passw + # psw.save(update_fields=['passw_text']) + except AbonRawPassword.DoesNotExist: + psw = AbonRawPassword.objects.create(account=acc, passw_text=raw_passw) + return psw + + +def add_opt82_if_not_exist(mac, port): + print(mac, port) + try: + opt82 = Opt82.objects.get(mac=mac, port=port) + except Opt82.DoesNotExist: + opt82 = Opt82.objects.create(mac=mac, port=port) + return opt82 + + def load_users(obj, group): if len(obj) < 1: return @@ -151,6 +182,8 @@ def load_users(obj, group): except Abon.DoesNotExist: # добавляем абонента abon = add_user(dump_abon, group) + if abon is None: + raise Exception("Чё за херня!? Не создался абонент") abon_service_from_dump = dump_abon.service if abon_service_from_dump is None: @@ -166,6 +199,12 @@ def load_users(obj, group): time_start=timezone.now(), deadline=calc_obj.calc_deadline() ) + try: + if hasattr(dump_abon, 'opt82'): + abon.opt82 = add_opt82_if_not_exist(dump_abon.opt82['dev_mac'], dump_abon.opt82['dev_port']) + abon.save(update_fields=['opt82']) + except ValidationError as e: + print('\t', e) def add_user(obj, user_group): @@ -182,17 +221,20 @@ def add_user(obj, user_group): except AbonStreet.DoesNotExist: street = AbonStreet.objects.create(name=obj.street, group=user_group) - return Abon.objects.create( - username=obj.name, - fio=obj.fio, - telephone=obj.tel, - street=street, - house=obj.house, - birth_day=obj.birth, - group = user_group, - ip_address=ip, - ballance=obj.balance - ) + abon = Abon() + abon.username = obj.name + abon.fio = obj.fio + abon.telephone = obj.tel + abon.street = street + abon.house = obj.house + abon.birth_day = obj.birth + abon.group = user_group + abon.ip_address = ip + abon.ballance = obj.balance + abon.set_password(obj.passw) + abon.save() + add_raw_password_if_not_exist(abon, obj.passw) + return abon def update_user(db_abon, obj, user_group): @@ -217,7 +259,9 @@ def update_user(db_abon, obj, user_group): db_abon.group = user_group db_abon.ip_address = ip db_abon.ballance = obj.balance + db_abon.set_password(obj.passw) db_abon.save() + add_raw_password_if_not_exist(db_abon, obj.passw) if __name__ == "__main__": From b9e68aa48acbbb5523bfc27aad7d6c8f467cbe87 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 7 Apr 2017 04:17:28 +0300 Subject: [PATCH 10/11] =?UTF-8?q?=D0=BD=D0=B5=20=D1=85=D0=B2=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BB=D0=BE=20=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- abonapp/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abonapp/models.py b/abonapp/models.py index b271433..8c26888 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -5,7 +5,7 @@ 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 +from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError from ip_pool.models import IpPoolItem from tariff_app.models import Tariff from accounts_app.models import UserProfile From b202a11a75b93c82baea4c5185001f27128d4555 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 7 Apr 2017 04:17:57 +0300 Subject: [PATCH 11/11] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20option82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- djing/utils/load_from_nodeny.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/djing/utils/load_from_nodeny.py b/djing/utils/load_from_nodeny.py index f01e43c..c8aa523 100755 --- a/djing/utils/load_from_nodeny.py +++ b/djing/utils/load_from_nodeny.py @@ -35,9 +35,12 @@ def load_service(cursor, uid): def load_users(cursor, grp_id): # выбираем абонентов sql = r"SELECT users.name, users.fio, data0._adr_telefon, dictionary.v AS street, data0._adr_house, data0._birthday, " \ - "users.grp, INET_NTOA(ip_pool.ip) AS ip, users.balance, AES_DECRYPT(users.passwd, 'Vu6saiZa') as decr_passwd, users.id " \ - "FROM users LEFT JOIN data0 ON (data0.uid = users.id) LEFT JOIN dictionary ON (dictionary.k = data0._adr_street " \ - "AND dictionary.type = 'street') LEFT JOIN ip_pool ON (ip_pool.uid = users.id) WHERE users.grp = %d" % grp_id + "users.grp, INET_NTOA(ip_pool.ip) AS ip, users.balance, AES_DECRYPT(users.passwd, 'Vu6saiZa') as decr_passwd, users.id, " \ + "mac_uid.device_mac, mac_uid.device_port, mac_uid.oneconnect " \ + "FROM users " \ + "LEFT JOIN data0 ON (data0.uid = users.id) LEFT JOIN dictionary ON (dictionary.k = data0._adr_street AND dictionary.type = 'street') " \ + "LEFT JOIN mac_uid ON (mac_uid.uid=users.id) " \ + "LEFT JOIN ip_pool ON (ip_pool.uid = users.id) WHERE users.grp = %d" % grp_id cursor.execute(sql) users = [{ 'name': res[0], @@ -50,7 +53,12 @@ def load_users(cursor, grp_id): 'ip': str(res[7] or ''), 'balance': float(res[8]), 'passw': res[9].decode("utf-8") if res[9] is not None else '', - 'service': load_service(cursor, int(res[10])) + 'service': load_service(cursor, int(res[10])), + 'opt82': { + 'dev_mac': res[11], + 'dev_port': res[12], + 'oneconnect': res[13] + } } for res in cursor.fetchall()] return users