simo 1.7.15__py3-none-any.whl → 1.7.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of simo might be problematic. Click here for more details.
- simo/__pycache__/asgi.cpython-38.pyc +0 -0
- simo/__pycache__/on_http_start.cpython-38.pyc +0 -0
- simo/asgi.py +2 -0
- simo/core/__pycache__/app_widgets.cpython-38.pyc +0 -0
- simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/core/__pycache__/events.cpython-38.pyc +0 -0
- simo/core/__pycache__/models.cpython-38.pyc +0 -0
- simo/core/__pycache__/socket_consumers.cpython-38.pyc +0 -0
- simo/core/__pycache__/tasks.cpython-38.pyc +0 -0
- simo/core/app_widgets.py +5 -0
- simo/core/controllers.py +34 -6
- simo/core/events.py +0 -3
- simo/core/management/commands/__pycache__/gateways_manager.cpython-38.pyc +0 -0
- simo/core/management/commands/gateways_manager.py +1 -1
- simo/core/migrations/0025_auto_20240122_1321.py +32 -0
- simo/core/migrations/__pycache__/0025_auto_20240122_1321.cpython-38.pyc +0 -0
- simo/core/models.py +8 -0
- simo/core/socket_consumers.py +1 -0
- simo/core/tasks.py +12 -0
- simo/core/templates/admin/controller_widgets/lock.html +11 -0
- simo/core/templates/admin/controller_widgets/switch.html +1 -2
- simo/generic/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/generic/controllers.py +2 -4
- simo/generic/gateways.py +11 -14
- simo/on_http_start.py +78 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- simo/users/migrations/0024_fingerprint.py +26 -0
- simo/users/migrations/__pycache__/0024_fingerprint.cpython-38.pyc +0 -0
- simo/users/models.py +12 -2
- {simo-1.7.15.dist-info → simo-1.7.17.dist-info}/METADATA +1 -2
- {simo-1.7.15.dist-info → simo-1.7.17.dist-info}/RECORD +35 -34
- simo/core/__pycache__/apps.cpython-38.pyc +0 -0
- simo/core/apps.py +0 -28
- simo/core/utils/__pycache__/serialization.cpython-38.pyc +0 -0
- simo/core/utils/serialization.py +0 -29
- simo/users/__pycache__/apps.cpython-38.pyc +0 -0
- simo/users/apps.py +0 -56
- {simo-1.7.15.dist-info → simo-1.7.17.dist-info}/LICENSE.md +0 -0
- {simo-1.7.15.dist-info → simo-1.7.17.dist-info}/WHEEL +0 -0
- {simo-1.7.15.dist-info → simo-1.7.17.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
simo/asgi.py
CHANGED
|
@@ -21,6 +21,8 @@ for name, app in apps.app_configs.items():
|
|
|
21
21
|
if isinstance(item, list) and var_name == 'urlpatterns':
|
|
22
22
|
urlpatterns.extend(item)
|
|
23
23
|
|
|
24
|
+
from .on_http_start import *
|
|
25
|
+
|
|
24
26
|
application = ProtocolTypeRouter({
|
|
25
27
|
"http": get_asgi_application(),
|
|
26
28
|
'websocket': AuthMiddlewareStack(
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/core/app_widgets.py
CHANGED
simo/core/controllers.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
import time
|
|
2
3
|
import datetime
|
|
3
4
|
import statistics
|
|
@@ -149,8 +150,10 @@ class ControllerBase(ABC):
|
|
|
149
150
|
]
|
|
150
151
|
|
|
151
152
|
def _get_actor(self, to_value):
|
|
153
|
+
if self.component.change_init_fingerprint and self.component.change_init_fingerprint.user:
|
|
154
|
+
return self.component.change_init_fingerprint.user
|
|
152
155
|
if self.component.change_init_by:
|
|
153
|
-
if self.component.change_init_date < timezone.now() - datetime.timedelta(seconds=
|
|
156
|
+
if self.component.change_init_date < timezone.now() - datetime.timedelta(seconds=30):
|
|
154
157
|
self.component.change_init_by = None
|
|
155
158
|
self.component.change_init_date = None
|
|
156
159
|
self.component.change_init_to = None
|
|
@@ -159,15 +162,15 @@ class ControllerBase(ABC):
|
|
|
159
162
|
'change_init_to', 'alive']
|
|
160
163
|
)
|
|
161
164
|
return None
|
|
162
|
-
|
|
165
|
+
else:
|
|
163
166
|
return self.component.change_init_by
|
|
164
167
|
|
|
165
168
|
def set(self, value, actor=None):
|
|
166
|
-
from .models import ComponentHistory
|
|
167
169
|
if not actor:
|
|
168
170
|
actor = self._get_actor(value)
|
|
169
171
|
if not actor:
|
|
170
172
|
actor = get_current_user()
|
|
173
|
+
|
|
171
174
|
# Introducing user to this thread for changes that might happen to other components
|
|
172
175
|
# in relation to the change of this component
|
|
173
176
|
introduce(actor)
|
|
@@ -175,13 +178,13 @@ class ControllerBase(ABC):
|
|
|
175
178
|
value = self.component.translate_before_set(value)
|
|
176
179
|
value = self._validate_val(value, BEFORE_SET)
|
|
177
180
|
self.component.refresh_from_db()
|
|
178
|
-
old_arm_status = self.component.arm_status
|
|
179
181
|
if value != self.component.value:
|
|
180
182
|
self.component.value_previous = self.component.value
|
|
181
183
|
self.component.value = value
|
|
182
184
|
self.component.change_init_by = None
|
|
183
185
|
self.component.change_init_date = None
|
|
184
186
|
self.component.change_init_to = None
|
|
187
|
+
self.component.change_init_fingerprint = None
|
|
185
188
|
self.component.save()
|
|
186
189
|
|
|
187
190
|
def _send_to_device(self, value):
|
|
@@ -214,9 +217,8 @@ class ControllerBase(ABC):
|
|
|
214
217
|
|
|
215
218
|
self.component.change_init_by = get_current_user()
|
|
216
219
|
self.component.change_init_date = timezone.now()
|
|
217
|
-
self.component.change_init_to = value
|
|
218
220
|
self.component.save(
|
|
219
|
-
update_fields=['change_init_by', 'change_init_date'
|
|
221
|
+
update_fields=['change_init_by', 'change_init_date']
|
|
220
222
|
)
|
|
221
223
|
value = self._prepare_for_send(value)
|
|
222
224
|
self._send_to_device(value)
|
|
@@ -668,9 +670,35 @@ class QuintupleSwitch(MultiSwitchBase):
|
|
|
668
670
|
class Lock(Switch):
|
|
669
671
|
name = _("Lock")
|
|
670
672
|
base_type = 'lock'
|
|
673
|
+
app_widget = LockWidget
|
|
674
|
+
admin_widget_template = 'admin/controller_widgets/lock.html'
|
|
671
675
|
|
|
672
676
|
def lock(self):
|
|
673
677
|
self.turn_on()
|
|
674
678
|
|
|
675
679
|
def unlock(self):
|
|
676
680
|
self.turn_off()
|
|
681
|
+
|
|
682
|
+
def _receive_from_device(self, value, is_alive=True):
|
|
683
|
+
if type(value) in (int, bool):
|
|
684
|
+
if value:
|
|
685
|
+
value = 'locked'
|
|
686
|
+
else:
|
|
687
|
+
value = 'unlocked'
|
|
688
|
+
return super()._receive_from_device(value, is_alive=is_alive)
|
|
689
|
+
|
|
690
|
+
def _validate_val(self, value, occasion=None):
|
|
691
|
+
if occasion == BEFORE_SEND:
|
|
692
|
+
if type(value) != bool:
|
|
693
|
+
raise ValidationError("Boolean required to lock/unlock.")
|
|
694
|
+
else:
|
|
695
|
+
available_values = (
|
|
696
|
+
'locked', 'unlocked', 'locking', 'unlocking',
|
|
697
|
+
'operating', 'fault'
|
|
698
|
+
)
|
|
699
|
+
if value not in available_values:
|
|
700
|
+
raise ValidationError(
|
|
701
|
+
f"Received value ({value}) that is not "
|
|
702
|
+
f"one of available values [{available_values}] for lock."
|
|
703
|
+
)
|
|
704
|
+
return value
|
simo/core/events.py
CHANGED
|
@@ -8,7 +8,6 @@ from django.conf import settings
|
|
|
8
8
|
import paho.mqtt.client as mqtt
|
|
9
9
|
from django.utils import timezone
|
|
10
10
|
import paho.mqtt.publish as mqtt_publish
|
|
11
|
-
from .utils.serialization import normalize
|
|
12
11
|
|
|
13
12
|
logger = logging.getLogger(__name__)
|
|
14
13
|
|
|
@@ -111,8 +110,6 @@ class OnChangeMixin:
|
|
|
111
110
|
return
|
|
112
111
|
if payload['obj_ct_pk'] != self._obj_ct_id:
|
|
113
112
|
return
|
|
114
|
-
if payload['event'] != 'changed':
|
|
115
|
-
return
|
|
116
113
|
if 'value' not in payload.get('dirty_fields', {}):
|
|
117
114
|
return
|
|
118
115
|
|
|
Binary file
|
|
@@ -138,7 +138,7 @@ class GatewaysManager:
|
|
|
138
138
|
return sys.exit()
|
|
139
139
|
|
|
140
140
|
def on_mqtt_connect(self, mqtt_client, userdata, flags, rc):
|
|
141
|
-
mqtt_client.subscribe(GatewayObjectCommand.TOPIC)
|
|
141
|
+
mqtt_client.subscribe(f'{GatewayObjectCommand.TOPIC}/*')
|
|
142
142
|
|
|
143
143
|
def on_mqtt_message(self, client, userdata, msg):
|
|
144
144
|
payload = json.loads(msg.payload)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated by Django 3.2.9 on 2024-01-22 13:21
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
import django.db.models.deletion
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
dependencies = [
|
|
11
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
12
|
+
('users', '0024_fingerprint'),
|
|
13
|
+
('core', '0024_alter_instance_device_report_history_days'),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.AddField(
|
|
18
|
+
model_name='component',
|
|
19
|
+
name='change_init_fingerprint',
|
|
20
|
+
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.fingerprint'),
|
|
21
|
+
),
|
|
22
|
+
migrations.AddField(
|
|
23
|
+
model_name='instance',
|
|
24
|
+
name='learn_fingerprints',
|
|
25
|
+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
|
|
26
|
+
),
|
|
27
|
+
migrations.AddField(
|
|
28
|
+
model_name='instance',
|
|
29
|
+
name='learn_fingerprints_start',
|
|
30
|
+
field=models.DateTimeField(blank=True, null=True),
|
|
31
|
+
),
|
|
32
|
+
]
|
|
Binary file
|
simo/core/models.py
CHANGED
|
@@ -107,6 +107,10 @@ class Instance(DirtyFieldsMixin, models.Model, SimoAdminMixin):
|
|
|
107
107
|
help_text="How many days of user device reports log do we keep? "
|
|
108
108
|
"Use 0 if you do not want to keep these logs at all."
|
|
109
109
|
)
|
|
110
|
+
learn_fingerprints_start = models.DateTimeField(null=True, blank=True)
|
|
111
|
+
learn_fingerprints = models.ForeignKey(
|
|
112
|
+
User, null=True, blank=True, on_delete=models.SET_NULL
|
|
113
|
+
)
|
|
110
114
|
|
|
111
115
|
def __str__(self):
|
|
112
116
|
return self.name
|
|
@@ -288,6 +292,10 @@ class Component(DirtyFieldsMixin, models.Model, SimoAdminMixin, OnChangeMixin):
|
|
|
288
292
|
)
|
|
289
293
|
change_init_date = models.DateTimeField(null=True, editable=False)
|
|
290
294
|
change_init_to = models.JSONField(null=True, editable=False)
|
|
295
|
+
change_init_fingerprint = models.ForeignKey(
|
|
296
|
+
'users.Fingerprint', null=True, editable=False,
|
|
297
|
+
on_delete=models.SET_NULL
|
|
298
|
+
)
|
|
291
299
|
last_change = models.DateTimeField(
|
|
292
300
|
null=True, editable=False, auto_now_add=True
|
|
293
301
|
)
|
simo/core/socket_consumers.py
CHANGED
|
@@ -257,6 +257,7 @@ class ComponentController(SIMOWebsocketConsumer):
|
|
|
257
257
|
))
|
|
258
258
|
|
|
259
259
|
def receive(self, text_data=None, bytes_data=None, **kwargs):
|
|
260
|
+
introduce(self.scope['user'])
|
|
260
261
|
json_data = json.loads(text_data)
|
|
261
262
|
self.send_value = json_data.pop('send_value', False)
|
|
262
263
|
for method, param in json_data.items():
|
simo/core/tasks.py
CHANGED
|
@@ -302,9 +302,21 @@ def update_latest_version_available():
|
|
|
302
302
|
dynamic_settings['core__latest_version_available'] = latest
|
|
303
303
|
|
|
304
304
|
|
|
305
|
+
@celery_app.task
|
|
306
|
+
def drop_fingerprints_learn():
|
|
307
|
+
Instance.objects.filter(
|
|
308
|
+
learn_fingerprints__isnull=False,
|
|
309
|
+
learn_fingerprints_start__lt=timezone.now() - datetime.timedelta(minutes=5)
|
|
310
|
+
).update(
|
|
311
|
+
learn_fingerprints=None,
|
|
312
|
+
learn_fingerprints_start=None
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
|
|
305
316
|
@celery_app.on_after_finalize.connect
|
|
306
317
|
def setup_periodic_tasks(sender, **kwargs):
|
|
307
318
|
sender.add_periodic_task(1, watch_timers.s())
|
|
308
319
|
sender.add_periodic_task(20, sync_with_remote.s())
|
|
309
320
|
sender.add_periodic_task(60 * 60, clear_history.s())
|
|
310
321
|
sender.add_periodic_task(60 * 60 * 6, update_latest_version_available.s())
|
|
322
|
+
sender.add_periodic_task(60, drop_fingerprints_learn.s())
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<div class="component-controller" data-ws_url="{{ obj.get_socket_url|default_if_none:"" }}">
|
|
2
|
+
{% if obj.value == 'locked' %}
|
|
3
|
+
<i class="fas fa-toggle-on fa-2x component_switch action"
|
|
4
|
+
data-method="turn_off"
|
|
5
|
+
></i>
|
|
6
|
+
{% else %}
|
|
7
|
+
<i class="fas fa-toggle-off fa-2x component_switch action"
|
|
8
|
+
data-method="turn_on"
|
|
9
|
+
></i>
|
|
10
|
+
{% endif %}
|
|
11
|
+
</div>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
<div class="component-controller"
|
|
2
|
-
data-ws_url="{{ obj.get_socket_url|default_if_none:"" }}">
|
|
1
|
+
<div class="component-controller" data-ws_url="{{ obj.get_socket_url|default_if_none:"" }}">
|
|
3
2
|
{% if obj.value %}
|
|
4
3
|
<i class="fas fa-toggle-on fa-2x component_switch action"
|
|
5
4
|
data-method="turn_off"
|
|
Binary file
|
|
Binary file
|
simo/generic/controllers.py
CHANGED
|
@@ -71,9 +71,7 @@ class Script(ControllerBase, TimerMixin):
|
|
|
71
71
|
self.component.refresh_from_db()
|
|
72
72
|
self.component.config['code'] = new_code
|
|
73
73
|
self.component.save(update_fields=['config'])
|
|
74
|
-
|
|
75
|
-
elif value == 'stop':
|
|
76
|
-
GatewayObjectCommand(self.component, **{'set_val': 'stop'}).publish()
|
|
74
|
+
return super()._send_to_device(value)
|
|
77
75
|
|
|
78
76
|
def _val_to_success(self, value):
|
|
79
77
|
if value == 'start':
|
|
@@ -1238,7 +1236,7 @@ class AlarmClock(ControllerBase):
|
|
|
1238
1236
|
|
|
1239
1237
|
# At this point there is an alarm that we are looking forward or we are in it already
|
|
1240
1238
|
|
|
1241
|
-
if current_value
|
|
1239
|
+
if current_value.get('alarm_uid') in current_value.get('ignore_alarms', {}):
|
|
1242
1240
|
return current_value
|
|
1243
1241
|
|
|
1244
1242
|
for event in current_value['events']:
|
simo/generic/gateways.py
CHANGED
|
@@ -239,28 +239,25 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
|
|
|
239
239
|
while len(script_ids):
|
|
240
240
|
time.sleep(0.1)
|
|
241
241
|
|
|
242
|
-
|
|
243
242
|
def on_mqtt_connect(self, mqtt_client, userdata, flags, rc):
|
|
244
|
-
|
|
243
|
+
command = GatewayObjectCommand(self.gateway_instance)
|
|
244
|
+
mqtt_client.subscribe(command.get_topic())
|
|
245
245
|
|
|
246
246
|
def on_mqtt_message(self, client, userdata, msg):
|
|
247
|
-
from simo.
|
|
248
|
-
from simo.generic.controllers import Script, Gate, Blinds
|
|
247
|
+
from simo.generic.controllers import Script, Blinds
|
|
249
248
|
payload = json.loads(msg.payload)
|
|
250
249
|
component = get_event_obj(payload, Component)
|
|
251
250
|
if not component:
|
|
252
251
|
return
|
|
253
252
|
|
|
254
|
-
if
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
elif component.controller_uid == Blinds.uid:
|
|
263
|
-
self.control_blinds(component, payload['kwargs'].get('set_val'))
|
|
253
|
+
if isinstance(component.controller, Script):
|
|
254
|
+
if payload.get('set_val') == 'start':
|
|
255
|
+
self.start_script(component)
|
|
256
|
+
elif payload.get('set_val') == 'stop':
|
|
257
|
+
self.stop_script(component)
|
|
258
|
+
return
|
|
259
|
+
elif component.controller_uid == Blinds.uid:
|
|
260
|
+
self.control_blinds(component, payload.get('set_val'))
|
|
264
261
|
|
|
265
262
|
def start_script(self, component):
|
|
266
263
|
print("START SCRIPT %s" % str(component))
|
simo/on_http_start.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pwd
|
|
3
|
+
import grp
|
|
4
|
+
import subprocess
|
|
5
|
+
from django.conf import settings
|
|
6
|
+
from django.template.loader import render_to_string
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def prepare_mosquitto():
|
|
10
|
+
if os.geteuid() != 0:
|
|
11
|
+
return
|
|
12
|
+
|
|
13
|
+
from simo.users.models import User
|
|
14
|
+
|
|
15
|
+
users_file = '/etc/mosquitto/mosquitto_users'
|
|
16
|
+
if not os.path.exists(users_file):
|
|
17
|
+
with open(users_file, 'w') as f:
|
|
18
|
+
f.write('')
|
|
19
|
+
|
|
20
|
+
uid = pwd.getpwnam("mosquitto").pw_uid
|
|
21
|
+
gid = grp.getgrnam("mosquitto").gr_gid
|
|
22
|
+
os.chown(users_file, uid, gid)
|
|
23
|
+
os.chmod(users_file, 0o640)
|
|
24
|
+
|
|
25
|
+
acls_file = '/etc/mosquitto/acls.conf'
|
|
26
|
+
with open(acls_file, 'w') as f:
|
|
27
|
+
f.write('')
|
|
28
|
+
|
|
29
|
+
uid = pwd.getpwnam("mosquitto").pw_uid
|
|
30
|
+
gid = grp.getgrnam("mosquitto").gr_gid
|
|
31
|
+
os.chown(acls_file, uid, gid)
|
|
32
|
+
os.chmod(acls_file, 0o640)
|
|
33
|
+
|
|
34
|
+
ps = subprocess.Popen(
|
|
35
|
+
['mosquitto_passwd /etc/mosquitto/mosquitto_users root'],
|
|
36
|
+
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
|
37
|
+
)
|
|
38
|
+
ps.communicate(f"{settings.SECRET_KEY}\n{settings.SECRET_KEY}".encode())
|
|
39
|
+
|
|
40
|
+
for user in User.objects.all():
|
|
41
|
+
user.update_mqtt_secret(reload=False)
|
|
42
|
+
|
|
43
|
+
from simo.users.utils import update_mqtt_acls
|
|
44
|
+
|
|
45
|
+
update_mqtt_acls()
|
|
46
|
+
|
|
47
|
+
if not os.path.exists('/etc/mosquitto/conf.d/simo.conf'):
|
|
48
|
+
with open('/etc/mosquitto/conf.d/simo.conf', 'w') as f:
|
|
49
|
+
f.write(render_to_string('conf/mosquitto.conf'))
|
|
50
|
+
|
|
51
|
+
subprocess.run(
|
|
52
|
+
['service', 'mosquitto', 'reload'], stdout=subprocess.PIPE
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
prepare_mosquitto()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def update_auto_update():
|
|
59
|
+
import simo
|
|
60
|
+
auto_update_file_path = os.path.join(
|
|
61
|
+
os.path.dirname(simo.__file__), 'auto_update.py'
|
|
62
|
+
)
|
|
63
|
+
st = os.stat(auto_update_file_path)
|
|
64
|
+
os.chmod(auto_update_file_path, st.st_mode | 0o111)
|
|
65
|
+
|
|
66
|
+
executable_path = '/usr/local/bin/simo-auto-update'
|
|
67
|
+
if os.geteuid() == 0:
|
|
68
|
+
# We are running as root!
|
|
69
|
+
if not os.path.islink(executable_path):
|
|
70
|
+
# There is no symbolic link yet made for auto updates.
|
|
71
|
+
# Let's make it!
|
|
72
|
+
os.symlink(auto_update_file_path, executable_path)
|
|
73
|
+
auto_update_cron = f'0 * * * * {executable_path} \n'
|
|
74
|
+
cron_out = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE)
|
|
75
|
+
cron_out.communicate(input=str.encode(auto_update_cron))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
update_auto_update()
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Generated by Django 3.2.9 on 2024-01-22 13:21
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
import django.db.models.deletion
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
dependencies = [
|
|
11
|
+
('users', '0023_auto_20240105_0719'),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.CreateModel(
|
|
16
|
+
name='Fingerprint',
|
|
17
|
+
fields=[
|
|
18
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
19
|
+
('value', models.CharField(db_index=True, max_length=200, unique=True)),
|
|
20
|
+
('date_created', models.DateTimeField(auto_now_add=True)),
|
|
21
|
+
('name', models.CharField(blank=True, max_length=100, null=True)),
|
|
22
|
+
('is_valid', models.BooleanField(db_index=True, default=True)),
|
|
23
|
+
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='fingerprints', to=settings.AUTH_USER_MODEL)),
|
|
24
|
+
],
|
|
25
|
+
),
|
|
26
|
+
]
|
|
Binary file
|
simo/users/models.py
CHANGED
|
@@ -120,7 +120,6 @@ def post_instance_user_save(sender, instance, created, **kwargs):
|
|
|
120
120
|
rebuild_mqtt_acls.delay()
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
|
|
124
123
|
class User(AbstractBaseUser, SimoAdminMixin):
|
|
125
124
|
name = models.CharField(_('name'), max_length=150)
|
|
126
125
|
email = models.EmailField(_('email address'), unique=True)
|
|
@@ -354,6 +353,17 @@ class User(AbstractBaseUser, SimoAdminMixin):
|
|
|
354
353
|
return components
|
|
355
354
|
|
|
356
355
|
|
|
356
|
+
class Fingerprint(models.Model):
|
|
357
|
+
value = models.CharField(max_length=200, db_index=True, unique=True)
|
|
358
|
+
user = models.ForeignKey(
|
|
359
|
+
User, on_delete=models.CASCADE, null=True, blank=True,
|
|
360
|
+
related_name='fingerprints'
|
|
361
|
+
)
|
|
362
|
+
date_created = models.DateTimeField(auto_now_add=True)
|
|
363
|
+
name = models.CharField(max_length=100, null=True, blank=True)
|
|
364
|
+
is_valid = models.BooleanField(default=True, db_index=True)
|
|
365
|
+
|
|
366
|
+
|
|
357
367
|
class UserDevice(models.Model, SimoAdminMixin):
|
|
358
368
|
user = models.ForeignKey(
|
|
359
369
|
User, on_delete=models.CASCADE, related_name='devices'
|
|
@@ -557,4 +567,4 @@ class InstanceInvitation(models.Model):
|
|
|
557
567
|
return response
|
|
558
568
|
|
|
559
569
|
def get_absolute_url(self):
|
|
560
|
-
return reverse('accept_invitation', kwargs={'token': self.token})
|
|
570
|
+
return reverse('accept_invitation', kwargs={'token': self.token})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: simo
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.17
|
|
4
4
|
Summary: Smart Home on Steroids!
|
|
5
5
|
Author-email: Simanas Venčkauskas <simanas@simo.io>
|
|
6
6
|
Project-URL: Homepage, https://simo.io
|
|
@@ -37,7 +37,6 @@ Requires-Dist: webservices ==0.7
|
|
|
37
37
|
Requires-Dist: opencv-python ==4.5.4.60
|
|
38
38
|
Requires-Dist: geopy ==2.2.0
|
|
39
39
|
Requires-Dist: requests ==2.26.0
|
|
40
|
-
Requires-Dist: click ==8.0.3
|
|
41
40
|
Requires-Dist: suntime ==1.2.5
|
|
42
41
|
Requires-Dist: django-location-field ==2.1.0
|
|
43
42
|
Requires-Dist: django-taggit ==2.0.0
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
simo/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
2
|
-
simo/asgi.py,sha256=
|
|
2
|
+
simo/asgi.py,sha256=625LsYcpGk0jKWUwZwjKNJx4btrzVCp6LThS2gga6Qo,852
|
|
3
3
|
simo/auto_update.py,sha256=KfYosx6_V0VvtASBED29l7HAyAIzMyLSob9OmAjyYxQ,2026
|
|
4
4
|
simo/celeryc.py,sha256=eab7_e9rw0c__DCeoUFUh_tjAGVlulxVrk75BaJf57Q,1512
|
|
5
5
|
simo/cli.py,sha256=kB1dhZ30Pnq7mDawWGbX5WnCuoZ6qNMcnWH-c8XxcaU,2233
|
|
6
6
|
simo/conf.py,sha256=H2BhXAV8MEDVXF8AbkaLSfR4ULd-9_bS4bnhE5sE5fg,112
|
|
7
|
+
simo/on_http_start.py,sha256=PJQlKYeZbtGCxRjDV6zcCqyA5Ns9d5NND30Tb6vIav4,2358
|
|
7
8
|
simo/scripting.py,sha256=PVIkGsiMDWj4CNTbOM3rq7pJ6ruavuns-ZMU7VudLa4,923
|
|
8
9
|
simo/settings.py,sha256=pMT2rdYKNpvXLxBFNWbqnRNkw8eVCW28u6DbI05AibM,6791
|
|
9
10
|
simo/urls.py,sha256=cmegi8VcNCq22k9v2rUYWDEcr2_ND2YQFUvpzISK7y0,2553
|
|
10
11
|
simo/__pycache__/__init__.cpython-38.pyc,sha256=j81de0BqHMr6bs0C7cuYrXl7HwtK_vv8hDEtAdSwDJc,153
|
|
11
|
-
simo/__pycache__/asgi.cpython-38.pyc,sha256=
|
|
12
|
+
simo/__pycache__/asgi.cpython-38.pyc,sha256=h60ZAnfczA1UpvJ1JofmQkC-DzmXSkFWOMyISyiABA8,880
|
|
12
13
|
simo/__pycache__/celeryc.cpython-38.pyc,sha256=eSRoaKwfYlxVaxAiwqpQ2ndEcx7W-VpZtbxRFSV8UYg,1653
|
|
13
14
|
simo/__pycache__/conf.cpython-38.pyc,sha256=MYP2yk3ULxiYwZsZR6tCLjKnU-z03A3avzQzIn66y3k,273
|
|
15
|
+
simo/__pycache__/on_http_start.cpython-38.pyc,sha256=QDNZHnJnLNmP3TSZ6oiySy2SbSgZ9LBs5m2KSwQPmAI,2067
|
|
14
16
|
simo/__pycache__/settings.cpython-38.pyc,sha256=lyN4n0YWf5paUvhBHZwAeg2TB2iqCjSuc5uxSZjxZLM,6040
|
|
15
17
|
simo/__pycache__/urls.cpython-38.pyc,sha256=_jjBuEJRAf7oXHOqt3MUElK2-uaYRL2jWK7l2StnUhQ,2210
|
|
16
18
|
simo/_hub_template/hub/asgi.py,sha256=ElN_fdeSkf0Ysa7pS9rJVmZ1HmLhFxb8jFaMLqe1220,126
|
|
@@ -24,28 +26,27 @@ simo/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
24
26
|
simo/core/admin.py,sha256=4l2XFoI9yUoOuQkyYdpwxt-PGj-VTVcMb-BiA_NHYok,16588
|
|
25
27
|
simo/core/api.py,sha256=Hv-Dy9Lc8H1hZXlz4Uoqx7CNVFoHy6ZbiHs1xEIaNCA,19157
|
|
26
28
|
simo/core/api_auth.py,sha256=2MRmCid_Fy67chKiJEt6_UaJZmb1PDF8KdbBlkA7YgU,1139
|
|
27
|
-
simo/core/app_widgets.py,sha256=
|
|
28
|
-
simo/core/apps.py,sha256=CbkdIxKG5geo3ObOI4bkp55yA-3Yjs7RFk0Q3blrAqc,1046
|
|
29
|
+
simo/core/app_widgets.py,sha256=EEQOto3fGR0syDqpJE38tQrx8DoTTyg26nF5kYzHY38,2018
|
|
29
30
|
simo/core/auto_urls.py,sha256=YZcvHqmAs4_azA_F_yz3CBsxrHAGijOPHib3SJCAoR0,1089
|
|
30
31
|
simo/core/autocomplete_views.py,sha256=ygbVEOfyygWNy2BanB46Ov0NfWxBFAwwKp5CqAkrGMc,3849
|
|
31
32
|
simo/core/base_types.py,sha256=OkRoAHp8P3r79k3IlUzkhycqlHDkeq7AAhOgsz7qGz8,552
|
|
32
33
|
simo/core/context.py,sha256=xmGQ5h6HXw9-_XTuJSXyNiWDRHAVauqGCxmSJo0mxjE,1261
|
|
33
|
-
simo/core/controllers.py,sha256
|
|
34
|
+
simo/core/controllers.py,sha256=-6WAduDDoXPoRk2za3LpSRUYrn-50X_kjgf1rMBJLFs,23493
|
|
34
35
|
simo/core/dynamic_settings.py,sha256=U2WNL96JzVXdZh0EqMPWrxqO6BaRR2Eo5KTDqz7MC4o,1943
|
|
35
|
-
simo/core/events.py,sha256=
|
|
36
|
+
simo/core/events.py,sha256=gfew3bduIjiFusbnIoQg1LhOXRIfyLTilNMc0ROfpr8,4198
|
|
36
37
|
simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
|
|
37
38
|
simo/core/forms.py,sha256=s-Cjw--vibCmxk6IQ_4M5IQOMuE3Z8re75NFPPmi4O4,19735
|
|
38
39
|
simo/core/gateways.py,sha256=MblN73zJC_6dBNJQel8KBblO4UvR-wLetea3FTrkWeE,3081
|
|
39
40
|
simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
|
|
40
41
|
simo/core/middleware.py,sha256=VKt9OBYU2o8BUjc5MESjt2vx_HixwprozmCRkAQDwZI,1252
|
|
41
|
-
simo/core/models.py,sha256=
|
|
42
|
+
simo/core/models.py,sha256=pnvSB-8HkdL6FWHvIxdb0gd-XuA3oBamZ8D2EIxjC5A,18443
|
|
42
43
|
simo/core/permissions.py,sha256=1GI59JZxl_sL9qzSt2uhoOnYnORDmcOJ8Fb37LbrhJE,576
|
|
43
44
|
simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
|
|
44
45
|
simo/core/serializers.py,sha256=styX6kt-h4k3GNu31RWEYIJ7I-u6BGRLfC0zhrtYV-U,4181
|
|
45
46
|
simo/core/signal_receivers.py,sha256=tyIljxTqvzBgYzcKDsSHeyFw9mKQiwA6NA1iJZEvL6I,2593
|
|
46
|
-
simo/core/socket_consumers.py,sha256=
|
|
47
|
+
simo/core/socket_consumers.py,sha256=y5I5BclO5i_pFGhh-oVxXSObVSMfvwQueQZfSZYSUTM,9827
|
|
47
48
|
simo/core/storage.py,sha256=YlxmdRs-zhShWtFKgpJ0qp2NDBuIkJGYC1OJzqkbttQ,572
|
|
48
|
-
simo/core/tasks.py,sha256=
|
|
49
|
+
simo/core/tasks.py,sha256=vvjXZGHfDqZl2eQxYedNPTqSE5tUcTFSqoy6T6SJQI4,10688
|
|
49
50
|
simo/core/todos.py,sha256=eYVXfLGiapkxKK57XuviSNe3WsUYyIWZ0hgQJk7ThKo,665
|
|
50
51
|
simo/core/types.py,sha256=WJEq48mIbFi_5Alt4wxWMGXxNxUTXqfQU5koH7wqHHI,1108
|
|
51
52
|
simo/core/views.py,sha256=Vr4eyLLIbxyPld-mOWH-hn0iqFfAbrK2jCHo_7nhvYE,5420
|
|
@@ -57,17 +58,16 @@ simo/core/__pycache__/admin.cpython-38.pyc,sha256=ZgDx7HuLwuV_9j6xEx090AU1-35jiA
|
|
|
57
58
|
simo/core/__pycache__/api.cpython-37.pyc,sha256=srtJhR4q9LU9VmVxkTC2YgjBiqFvSWytHmQiX9W897c,1780
|
|
58
59
|
simo/core/__pycache__/api.cpython-38.pyc,sha256=7oxM_bKV_uCAzcIasshtZYEOkzRbFPU4LNgsxS-DcUU,14480
|
|
59
60
|
simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=Df2nEIBP9BU4XB3NxlI335eIYOXjG6rjfLWQR-Jki7k,1627
|
|
60
|
-
simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=
|
|
61
|
-
simo/core/__pycache__/apps.cpython-38.pyc,sha256=p5MFXSBz2sEDRiuelD_hMIAzin2XSiJRLPbBPfJXr1w,1133
|
|
61
|
+
simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=o122Qpv-RrR61gsJVs29yNTVT7MmwxuqrqBHpFCPG_4,3465
|
|
62
62
|
simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=LmdNUMSWfwNXzyoxG4Ki82B6tegLSHn1ethfnPSRR5Y,836
|
|
63
63
|
simo/core/__pycache__/autocomplete_views.cpython-38.pyc,sha256=Rrrx6jwbhYDa9sU1eia9xBuTx-0H4F1aBsMvrK8cIz0,3861
|
|
64
64
|
simo/core/__pycache__/base_types.cpython-38.pyc,sha256=LyaOjfDh0ZQNUbYNoJwOAyeBOy1qoEyBvdV0aYV8w7E,693
|
|
65
65
|
simo/core/__pycache__/context.cpython-38.pyc,sha256=Dq_Z-4U7ppQhu8T-7kqu7LjT6DgbRI9bWbQ17rwX-Us,1184
|
|
66
66
|
simo/core/__pycache__/controllers.cpython-37.pyc,sha256=18C2XXXvrzaipTVWRx_KFDHP5TmeWM-xnTnqVkzy8as,1663
|
|
67
|
-
simo/core/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
67
|
+
simo/core/__pycache__/controllers.cpython-38.pyc,sha256=79kYGOmaJpZ8eqqcYfnmy-lKtmp0lQDXh8RG7Nf2y94,21360
|
|
68
68
|
simo/core/__pycache__/dynamic_settings.cpython-38.pyc,sha256=P14nFp70tx6eCkyQN0ZxLaX21DiUc3TeZ4bs3h8XJgA,2476
|
|
69
69
|
simo/core/__pycache__/events.cpython-37.pyc,sha256=E17-McBIoKrqwv1Qjh0WaVKYvcL-xzGRXvCg70uRUgs,3154
|
|
70
|
-
simo/core/__pycache__/events.cpython-38.pyc,sha256=
|
|
70
|
+
simo/core/__pycache__/events.cpython-38.pyc,sha256=5EJe1jSpBzqSuH_hCKAY7vsNIfeYX0KUtPaU-cIjX6w,4973
|
|
71
71
|
simo/core/__pycache__/filters.cpython-38.pyc,sha256=d2yr0vEtbHsi5L4dysiRz4_m3Zz6ZMGV569mJTzB9Ro,713
|
|
72
72
|
simo/core/__pycache__/forms.cpython-37.pyc,sha256=jTCg2uFkNumlWn5IEXay9_hL4wbAfZgmqZzhAaRBf6c,1784
|
|
73
73
|
simo/core/__pycache__/forms.cpython-38.pyc,sha256=5N-umEqnAyIh5gYYLLLKAT-uWlDRFFTjvIDeOphFGe8,16394
|
|
@@ -76,16 +76,16 @@ simo/core/__pycache__/gateways.cpython-38.pyc,sha256=YyscgVM5eGIE7dL5GcaSco6NzsF
|
|
|
76
76
|
simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
|
|
77
77
|
simo/core/__pycache__/middleware.cpython-38.pyc,sha256=vRjRp2hUrMLNvP2dExBVpP4T7wa6owWPCJbq5jPqY00,1480
|
|
78
78
|
simo/core/__pycache__/models.cpython-37.pyc,sha256=kJ1wVtRlrDNAD6svKaiDTNRx7d4t5ect_hsDgpgzb0M,4240
|
|
79
|
-
simo/core/__pycache__/models.cpython-38.pyc,sha256=
|
|
79
|
+
simo/core/__pycache__/models.cpython-38.pyc,sha256=VCiK_tFooJKrohW6Rmn1bZUySJLMFvHmEe5vYWL17iU,16139
|
|
80
80
|
simo/core/__pycache__/permissions.cpython-38.pyc,sha256=BBstKtFelsJz8oTC3b3M2Z2XUi7cYFjnBaTuvcRraoo,850
|
|
81
81
|
simo/core/__pycache__/routing.cpython-38.pyc,sha256=SnHuviYlYSp1pBON71-14yWa4jg5GDo8ksjfS5n1Gmk,591
|
|
82
82
|
simo/core/__pycache__/scripts.cpython-37.pyc,sha256=aVttBA4V6xl6hwaFNbhIp45VbP0wId0vIC6iTvvw7iQ,613
|
|
83
83
|
simo/core/__pycache__/serializers.cpython-37.pyc,sha256=SraS2BK9PTfrSXZGE7IeT6VvnuYDxrONwuDPba2Vcz8,3129
|
|
84
84
|
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=MhbEoC3bxpiqJc2iPmZRKnlclRdVWiwCLn6baoXNfXQ,5762
|
|
85
85
|
simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=BihR5Qnr9P72Xx4M9QWwCoxPa33ekDpLbQgS0kM0LC8,2321
|
|
86
|
-
simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=
|
|
86
|
+
simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=Xw_9Y0WcvO9vacbHA4uNHPW2dF2XcMG1nb0jiS8cRzs,8839
|
|
87
87
|
simo/core/__pycache__/storage.cpython-38.pyc,sha256=BTkYH8QQyjqI0WOtJC8fHNtgu0YA1vjqZclXjC2vCVI,1116
|
|
88
|
-
simo/core/__pycache__/tasks.cpython-38.pyc,sha256=
|
|
88
|
+
simo/core/__pycache__/tasks.cpython-38.pyc,sha256=vtkxATYpSP6hB0zh5hJykUM5HYS4MAHb1jN0P-t3imE,8048
|
|
89
89
|
simo/core/__pycache__/todos.cpython-38.pyc,sha256=CkHQ6v8gmynr83KQsJY6VPR3OnLZnHvVCX5R1Dr8J9Q,245
|
|
90
90
|
simo/core/__pycache__/views.cpython-38.pyc,sha256=I75ChNeoySYr2uXV0PScwpVWsOoPpyzP9cHKkTJfWAc,3825
|
|
91
91
|
simo/core/__pycache__/widgets.cpython-37.pyc,sha256=myov4OZi5dkR2dYs2hBAVgMIgOTJT5jdLiM93PI8gvw,688
|
|
@@ -97,11 +97,11 @@ simo/core/db_backend/__pycache__/base.cpython-38.pyc,sha256=e4S8FC9O5fNJPHO2H9M6
|
|
|
97
97
|
simo/core/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
98
98
|
simo/core/management/__pycache__/__init__.cpython-38.pyc,sha256=Fh8tziI4OtqmaJ_b1lAWh91jNunBUvA5mEbOnV6Vy9o,154
|
|
99
99
|
simo/core/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
100
|
-
simo/core/management/commands/gateways_manager.py,sha256=
|
|
100
|
+
simo/core/management/commands/gateways_manager.py,sha256=oogLAywD6-ohTHVA8RzZqQBcPvvf6BjWcnZK8kzXqJY,6974
|
|
101
101
|
simo/core/management/commands/run_gateway.py,sha256=bp0FQQoBeOSoxjHCCMicDL1fxPZZGyLgnq2QKht3bJo,645
|
|
102
102
|
simo/core/management/commands/update.py,sha256=Y2_6EL8E757nr-MjSuIpdSsEItI0yN42DT5P1e1zkno,175
|
|
103
103
|
simo/core/management/commands/__pycache__/__init__.cpython-38.pyc,sha256=xFGh3qGeMqHMcdTExaynbV7hr8jwuEa8nuSxsQIvCD4,163
|
|
104
|
-
simo/core/management/commands/__pycache__/gateways_manager.cpython-38.pyc,sha256=
|
|
104
|
+
simo/core/management/commands/__pycache__/gateways_manager.cpython-38.pyc,sha256=LV5RXd7eOKYwxvQ4cFleojEJqls-qe9Lt0qsWzX9zUw,6035
|
|
105
105
|
simo/core/management/commands/__pycache__/run_gateway.cpython-38.pyc,sha256=ojjiJmq5VYsongyLSLBYgudtRfnksTkKCR7NP4B-EGM,1059
|
|
106
106
|
simo/core/migrations/0001_initial.py,sha256=0Uy7IqJxQQYlurs8Mw_RJy7NaWS7BU0VFmZBBz8YkQI,9220
|
|
107
107
|
simo/core/migrations/0002_load_icons.py,sha256=s9TtGo5NWEyWV3BspfbDNAlWqmQWxmDj7GjEaJXruFk,2044
|
|
@@ -127,6 +127,7 @@ simo/core/migrations/0021_auto_20231020_1041.py,sha256=OmXoVeWfb8HPvGlP0iC1ZYqBy
|
|
|
127
127
|
simo/core/migrations/0022_auto_20231221_0735.py,sha256=XR4rfCHy6_oZkybvzcba_Oxx8HST-vSCKy8pPVxX8cs,23525
|
|
128
128
|
simo/core/migrations/0023_auto_20231229_1352.py,sha256=TuCDRtgmFDLW7e1oIs_3Ndxn-ub2rV87VAzZ_1U0bwQ,1267
|
|
129
129
|
simo/core/migrations/0024_alter_instance_device_report_history_days.py,sha256=CqCWl3GQNeFnNMr0hfdlQG9LcXbN9dILqxw0peHVihs,530
|
|
130
|
+
simo/core/migrations/0025_auto_20240122_1321.py,sha256=ocRAPsO2QRUBn8tOwtXNcc82fA0KHLsclDy2Nz5X-ds,1111
|
|
130
131
|
simo/core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
131
132
|
simo/core/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=ftWpf_RgprbqNo_syjYdeblvFH5nIEc87XEpdi1INHo,5373
|
|
132
133
|
simo/core/migrations/__pycache__/0002_load_icons.cpython-38.pyc,sha256=gYV4sH0cXffvNtVyFgRQQ1A4I5DeIRnZX9eUrTpEhlk,2115
|
|
@@ -152,6 +153,7 @@ simo/core/migrations/__pycache__/0021_auto_20231020_1041.cpython-38.pyc,sha256=p
|
|
|
152
153
|
simo/core/migrations/__pycache__/0022_auto_20231221_0735.cpython-38.pyc,sha256=RvnYOHFuY8siQ69Fed3oHoXbiF17Vr54YXRYyJFwp-4,16477
|
|
153
154
|
simo/core/migrations/__pycache__/0023_auto_20231229_1352.cpython-38.pyc,sha256=NYA0kVuQGWjz2epoLH0XG7FgyaC6JXW28J18bjRAqCk,1281
|
|
154
155
|
simo/core/migrations/__pycache__/0024_alter_instance_device_report_history_days.cpython-38.pyc,sha256=ALrhitBQRd-y9Ragwa0_ZuJ9DDkUIgw72A0CZpWznmE,777
|
|
156
|
+
simo/core/migrations/__pycache__/0025_auto_20240122_1321.cpython-38.pyc,sha256=u6tcFJClTrrgPrYhtKPea9IIwG4O2yWjjoUCR7_dQ60,1090
|
|
155
157
|
simo/core/migrations/__pycache__/__init__.cpython-38.pyc,sha256=a0yc0qWaV-D5f64GdcpP54haEDBzwmAWRGyErHeHztU,161
|
|
156
158
|
simo/core/static/ansi_styles.css,sha256=4ieJGrjZPKyPSago9FdB_gflHoGE1vxCHi8qVn5tY-Y,37352
|
|
157
159
|
simo/core/static/admin/Img/plus.svg,sha256=2NpSFPWqGIjpAQGFI7LDQHPKagEhYkJiJX95ufCoZaI,741
|
|
@@ -10058,8 +10060,9 @@ simo/core/templates/admin/zone_table_row.html,sha256=4XCgDsnrvn6s9ac0_e74pPsjDFd
|
|
|
10058
10060
|
simo/core/templates/admin/controller_widgets/binary_sensor.html,sha256=PTwoLyppBIH8VL3-PKXCT4SWFQOeWqrzfsriWyROnzU,277
|
|
10059
10061
|
simo/core/templates/admin/controller_widgets/generic.html,sha256=4TNLI0ri2qpuXNy4IIi4CTN4L98JtmERE0D16a4wCNE,163
|
|
10060
10062
|
simo/core/templates/admin/controller_widgets/knob.html,sha256=ukTJoQBZfly0gLUx0vJdqHbnggaiDV6jS5tM8Jd8JuA,221
|
|
10063
|
+
simo/core/templates/admin/controller_widgets/lock.html,sha256=JyIB5CIaXBb4cKLSg53lWBRjNIeTxVaHBJTuOI4nYkQ,363
|
|
10061
10064
|
simo/core/templates/admin/controller_widgets/rgb.html,sha256=3xRjo_d1jALiJabWYk5kTLhdwhylzOA-iwyDNfSKlgw,224
|
|
10062
|
-
simo/core/templates/admin/controller_widgets/switch.html,sha256=
|
|
10065
|
+
simo/core/templates/admin/controller_widgets/switch.html,sha256=fyNEZgxO0dY61QVSrnsSYt7-JsS9RQTGkPXaeMyNNWM,351
|
|
10063
10066
|
simo/core/templates/admin/core/icon_preview.html,sha256=D1FS0PwKRopFQgy4NlUPtQp7n78opB6XMRVf2CAAtaM,605
|
|
10064
10067
|
simo/core/templates/admin/gateway_control/widget.html,sha256=hJ8oL0wZjhwQXiVDCXVAqb-nJQUkSYPtfKoaAUl0Hwc,163
|
|
10065
10068
|
simo/core/templates/admin/gateway_control/widget_internals.html,sha256=6UsVKQtHWM2W29Rf1SLiLdNdkxL6P_WGZUKhHzcw48k,1262
|
|
@@ -10090,7 +10093,6 @@ simo/core/utils/logs.py,sha256=JBUHhnm9Cn81csrQ4xHbujBFRL9YWulMwUj_zJPNvyw,1057
|
|
|
10090
10093
|
simo/core/utils/mixins.py,sha256=X6kUPKAi_F-uw7tgm8LEaYalBXpvDA-yrLNFCGr2rks,259
|
|
10091
10094
|
simo/core/utils/model_helpers.py,sha256=3IzJeOvBoYdUJVXCJkY20npOZXPjNPAiEFvuT0OPhwA,884
|
|
10092
10095
|
simo/core/utils/relay.py,sha256=i1xy_nPTgY5Xn0l2W4lNI3xeVUpDQTUUfV3M8h2DeBg,457
|
|
10093
|
-
simo/core/utils/serialization.py,sha256=acx2a26rwsr5-Tb2oXhVk7EHRsrNn12SuiW273M3JzA,625
|
|
10094
10096
|
simo/core/utils/type_constants.py,sha256=y0YnRa7txooMZUVf1IuFUTXPwLaHo_UToKIChJH5Vgk,3544
|
|
10095
10097
|
simo/core/utils/validators.py,sha256=PGqW9E8tA6I68RiZg_38DS_MsZs1ew_6vQY4YRKhBdU,772
|
|
10096
10098
|
simo/core/utils/__pycache__/__init__.cpython-38.pyc,sha256=fm7tTfba3f_RZC2Q7UCRztAw55rK-ZCVYh0QHl8vvj8,149
|
|
@@ -10106,7 +10108,6 @@ simo/core/utils/__pycache__/logs.cpython-38.pyc,sha256=t2jOYAU8R58Jw4I7SXZ0M8Klx
|
|
|
10106
10108
|
simo/core/utils/__pycache__/mixins.cpython-38.pyc,sha256=PSdlUHeaURWWy6lQPROvhqVAQ397LKvyVWMTp6RPJ5U,600
|
|
10107
10109
|
simo/core/utils/__pycache__/model_helpers.cpython-38.pyc,sha256=fHAFterjLpjaLGMCkDpCYeCpAjhgNkI5kDBINkBupf4,1343
|
|
10108
10110
|
simo/core/utils/__pycache__/relay.cpython-38.pyc,sha256=J7k-psm64REAy3VpJ7dk9HDIoxl3Vj-u2sjL4Xd5P40,689
|
|
10109
|
-
simo/core/utils/__pycache__/serialization.cpython-38.pyc,sha256=hgXTkR2FavMlAeyaFdaGYeCMG2ZSYKddps_H6YDmSEw,686
|
|
10110
10111
|
simo/core/utils/__pycache__/type_constants.cpython-38.pyc,sha256=qg39w7UCcUET_Tt9md0wLVExeLTESwQn0FY5LDdMsVk,3008
|
|
10111
10112
|
simo/core/utils/__pycache__/validators.cpython-38.pyc,sha256=VyUnCgzm4LXCmPqVKfwfLI1uF7KUtrhu-pjMI0zjUok,841
|
|
10112
10113
|
simo/fleet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -10191,9 +10192,9 @@ simo/fleet/migrations/__pycache__/__init__.cpython-38.pyc,sha256=5k1KW0jeSDzw6Rn
|
|
|
10191
10192
|
simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10192
10193
|
simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
|
|
10193
10194
|
simo/generic/base_types.py,sha256=djymox_boXTHX1BTTCLXrCH7ED-uAsV_idhaDOc3OLI,409
|
|
10194
|
-
simo/generic/controllers.py,sha256=
|
|
10195
|
+
simo/generic/controllers.py,sha256=nD3w4X5Lt2wd2n6F9qJV3eAXqIaB5Fux5qfqB3DKtng,54307
|
|
10195
10196
|
simo/generic/forms.py,sha256=zF-QYfu6C0TZ7sJ5_-VkhUweV0_J8gg0CC07At6RIK8,19829
|
|
10196
|
-
simo/generic/gateways.py,sha256=
|
|
10197
|
+
simo/generic/gateways.py,sha256=A8jno143joAQSlbBLQ44SR0-yvYyoJhoSgdOmGGnUvU,11907
|
|
10197
10198
|
simo/generic/models.py,sha256=XG8VnLSpMSiBnbKwvMknF9J9kdbmBolXvJ9L3Giz8pQ,3330
|
|
10198
10199
|
simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
|
|
10199
10200
|
simo/generic/socket_consumers.py,sha256=NfTQGYtVAc864IoogZRxf_0xpDPM0eMCWn0SlKA5P7Y,1751
|
|
@@ -10203,9 +10204,9 @@ simo/generic/__pycache__/__init__.cpython-38.pyc,sha256=MCjhrSijserYi14I03LlOwRU
|
|
|
10203
10204
|
simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=QGPG6EkuNwk5PhFtNFIYfbJVrXiA76fBZlu31lwuvdY,2366
|
|
10204
10205
|
simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=ePcCgG0U4mrc_I3MLs2cnUh5KPX-Kf13jTy_d5pTP78,547
|
|
10205
10206
|
simo/generic/__pycache__/controllers.cpython-37.pyc,sha256=5cET2P5vw-ujjYhyyLOoski91fXqiuV4zZdhRKgb028,2461
|
|
10206
|
-
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
10207
|
+
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=nf4yQTt-E9dPVNLHuM-PGeuhTutrTNQCNGRs46BmT2A,35232
|
|
10207
10208
|
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=fhJCmt60aYabvuylL4ZADGuIcI7YA62iJVFav9zZ_QU,15457
|
|
10208
|
-
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=
|
|
10209
|
+
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=Wj69nJQ6ea7KahupRWTr3SEvq0OokTIf9SOJZ67BKS4,9218
|
|
10209
10210
|
simo/generic/__pycache__/models.cpython-38.pyc,sha256=8upnlvxpuYsg16gghJg9JZCcuyatsrWuYzDYT4psaC0,3035
|
|
10210
10211
|
simo/generic/__pycache__/routing.cpython-38.pyc,sha256=1-1r3oasl1nWP36UvPcqb-mSYDPOtiuO3HAMRSpS4b8,374
|
|
10211
10212
|
simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=KVv0940VOj7I2vIJySrBOeHelyxn12e8otavCFRtSO4,1890
|
|
@@ -10285,12 +10286,11 @@ simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=wXGUV-i
|
|
|
10285
10286
|
simo/users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10286
10287
|
simo/users/admin.py,sha256=XpUrz1zIVLuK3Y9MF7kCJBExHpMEMkU3iNZG1YZdxO0,6560
|
|
10287
10288
|
simo/users/api.py,sha256=_1Z8m4pU-9LAbLfSdZ6qXLj0amgulVPqmLX2kRGJWF4,7886
|
|
10288
|
-
simo/users/apps.py,sha256=rf_6OOpkiwTrOTY8pIsozrVUlx-0wpOheLEPj0lIYsU,1728
|
|
10289
10289
|
simo/users/auth_backends.py,sha256=I5pnaTa20-Lxfw_dFG8471xDITb0_fQl1PVhJalp5vU,3992
|
|
10290
10290
|
simo/users/auto_urls.py,sha256=ee0d6fWABkJY5mQOTC8KhrqDI6d8xZkYZ4ja-gZJ-rw,269
|
|
10291
10291
|
simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
|
|
10292
10292
|
simo/users/middleware.py,sha256=9epN8xDcnYAMoEjAeJGg4W9e54szTgh48LKz3rlywFI,1287
|
|
10293
|
-
simo/users/models.py,sha256=
|
|
10293
|
+
simo/users/models.py,sha256=HyN4Euh4j4dQqToR0LOBLHphztHGdQgDN41lSLarlRU,18552
|
|
10294
10294
|
simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
|
|
10295
10295
|
simo/users/serializers.py,sha256=Mh2pWmsKDp7CNIxK2OTw3CfVkteZHiVoXWNF1fluvX8,2161
|
|
10296
10296
|
simo/users/sso_urls.py,sha256=pcb_GhYHRtmairxJhMXE1bdcTma0BcYfKU3nCRtHQMQ,244
|
|
@@ -10301,12 +10301,11 @@ simo/users/views.py,sha256=dOQVvmlHG7ihWKJLFUBcqKOA0UDctlMKR0pTc36JZqg,3487
|
|
|
10301
10301
|
simo/users/__pycache__/__init__.cpython-38.pyc,sha256=9otuYxq331c4lGy0DR8pigaPpzq0lQ4nrNLhlYiFAF0,159
|
|
10302
10302
|
simo/users/__pycache__/admin.cpython-38.pyc,sha256=ggaIuUdEjvYZ6Y5msOlhP_LmYnqUQpkJeS6FuZr6ass,7274
|
|
10303
10303
|
simo/users/__pycache__/api.cpython-38.pyc,sha256=W_VuG6hotcDA2iIsbO1p01ouqcWIl7C3JZbAk4Wp3l8,6676
|
|
10304
|
-
simo/users/__pycache__/apps.cpython-38.pyc,sha256=E14VsKsNu8V3dPk089YREOzWUB_1xGLgprEbpMh2kMw,1694
|
|
10305
10304
|
simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=MuOieBIXt6lrDx83-UQtdDyI_U8kE3pU9XR4yFLKBnE,3007
|
|
10306
10305
|
simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=q8SFA5EN-tpypBzfiAsorpWdXlrC_kt4HgMCZS9bcoI,431
|
|
10307
10306
|
simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
|
|
10308
10307
|
simo/users/__pycache__/middleware.cpython-38.pyc,sha256=U2ENmFDCHK4qtf2Q6xLqe-VNmM6dN-sUb6q70epSgZs,1165
|
|
10309
|
-
simo/users/__pycache__/models.cpython-38.pyc,sha256=
|
|
10308
|
+
simo/users/__pycache__/models.cpython-38.pyc,sha256=KH1jIoLIZgG22dYuuZqnVCSsnPfe4D74k76gGQdw9jk,17498
|
|
10310
10309
|
simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
|
|
10311
10310
|
simo/users/__pycache__/serializers.cpython-38.pyc,sha256=rCAdmyL95NkChqspE-FmAtJ6vAWjdJnPa2jrd8e6hUo,2868
|
|
10312
10311
|
simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=9TkKOWZugSPhwModg5yJn2IE3YgvMQA8Vm3WGznoOuk,403
|
|
@@ -10337,6 +10336,7 @@ simo/users/migrations/0020_rename_is_god_user_is_master.py,sha256=opZkM36xt6sKuJ
|
|
|
10337
10336
|
simo/users/migrations/0021_alter_permissionsrole_instance.py,sha256=Taw2fdHy6U1PlThC3QIWaL_ADbx7gchWsJcGxoMMElo,630
|
|
10338
10337
|
simo/users/migrations/0022_userdevicereportlog_instance.py,sha256=h0ue6uMcIyVs2o58Aj0PyjGLPvCCfS28HfPIiIu_VLc,549
|
|
10339
10338
|
simo/users/migrations/0023_auto_20240105_0719.py,sha256=OAkWJusXjzT6dx4EgwjvNvMEgrP_zvcG8zgi774pYG0,700
|
|
10339
|
+
simo/users/migrations/0024_fingerprint.py,sha256=0wfplJ3iHv_6heJx7yIQYX3D68Nf9pLPlIZoM5NcPk8,1021
|
|
10340
10340
|
simo/users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10341
10341
|
simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=ngXA1QR-Qc2VS-BTTZWybVXiEfifIgKaVS6bADiN8nU,4269
|
|
10342
10342
|
simo/users/migrations/__pycache__/0002_componentpermission.cpython-38.pyc,sha256=pknJnpic8p6Vdx9DX41FfODXNnvexDswJtUCmC5w1tg,995
|
|
@@ -10361,6 +10361,7 @@ simo/users/migrations/__pycache__/0020_rename_is_god_user_is_master.cpython-38.p
|
|
|
10361
10361
|
simo/users/migrations/__pycache__/0021_alter_permissionsrole_instance.cpython-38.pyc,sha256=aC1h7lz5JZbpZU55X9GdW_XJ_JixSxh0_I7TCheO_rM,863
|
|
10362
10362
|
simo/users/migrations/__pycache__/0022_userdevicereportlog_instance.cpython-38.pyc,sha256=xGtWss6Blm02eNE-sBYQxwbRydqii2YcSGJNh1zseEw,785
|
|
10363
10363
|
simo/users/migrations/__pycache__/0023_auto_20240105_0719.cpython-38.pyc,sha256=VOc5g9AlyhnB3QhU6GmOw6RPWUh4WhtLIOypCYb4jXY,739
|
|
10364
|
+
simo/users/migrations/__pycache__/0024_fingerprint.cpython-38.pyc,sha256=y7usfd4nuqXG2ZKq2hEVPq8ukEeszGpLfNFOzeLX9yU,1132
|
|
10364
10365
|
simo/users/migrations/__pycache__/__init__.cpython-38.pyc,sha256=NKq7WLgktK8WV1oOqCPbAbdkrPV5GRGhYx4VxxI4dcs,170
|
|
10365
10366
|
simo/users/templates/conf/mosquitto.conf,sha256=1eIGNuRu4Y3hfAU6qiWix648eCRrw0oOT24PnyFI4ys,189
|
|
10366
10367
|
simo/users/templates/conf/mosquitto_acls.conf,sha256=ga44caTDNQE0CBKw55iM2jOuna6-9fKGwAhjyERZdRE,500
|
|
@@ -10370,8 +10371,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10370
10371
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10371
10372
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10372
10373
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10373
|
-
simo-1.7.
|
|
10374
|
-
simo-1.7.
|
|
10375
|
-
simo-1.7.
|
|
10376
|
-
simo-1.7.
|
|
10377
|
-
simo-1.7.
|
|
10374
|
+
simo-1.7.17.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10375
|
+
simo-1.7.17.dist-info/METADATA,sha256=pzt1U0wzNjr7EQHueQkcGXm1ZLAQ_0gDysSogCWA7pQ,1720
|
|
10376
|
+
simo-1.7.17.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
10377
|
+
simo-1.7.17.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10378
|
+
simo-1.7.17.dist-info/RECORD,,
|
|
Binary file
|
simo/core/apps.py
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import subprocess
|
|
3
|
-
from django.conf import settings
|
|
4
|
-
from django.template.loader import render_to_string
|
|
5
|
-
from django.apps import AppConfig
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class CoreAppConfig(AppConfig):
|
|
9
|
-
name = 'simo.core'
|
|
10
|
-
|
|
11
|
-
def ready(self):
|
|
12
|
-
import simo
|
|
13
|
-
auto_update_file_path = os.path.join(
|
|
14
|
-
os.path.dirname(simo.__file__), 'auto_update.py'
|
|
15
|
-
)
|
|
16
|
-
st = os.stat(auto_update_file_path)
|
|
17
|
-
os.chmod(auto_update_file_path, st.st_mode | 0o111)
|
|
18
|
-
|
|
19
|
-
executable_path = '/usr/local/bin/simo-auto-update'
|
|
20
|
-
if os.geteuid() == 0:
|
|
21
|
-
# We are running as root!
|
|
22
|
-
if not os.path.islink(executable_path):
|
|
23
|
-
# There is no symbolic link yet made for auto updates.
|
|
24
|
-
# Let's make it!
|
|
25
|
-
os.symlink(auto_update_file_path, executable_path)
|
|
26
|
-
auto_update_cron = f'0 * * * * {executable_path} \n'
|
|
27
|
-
cron_out = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE)
|
|
28
|
-
cron_out.communicate(input=str.encode(auto_update_cron))
|
|
Binary file
|
simo/core/utils/serialization.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
from collections.abc import Iterable
|
|
3
|
-
from decimal import Decimal as D
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def normalize(data):
|
|
7
|
-
|
|
8
|
-
if isinstance(data, dict):
|
|
9
|
-
result = {}
|
|
10
|
-
for key, val in data.items():
|
|
11
|
-
result[key] = normalize(val)
|
|
12
|
-
return result
|
|
13
|
-
|
|
14
|
-
if isinstance(data, Iterable):
|
|
15
|
-
result = []
|
|
16
|
-
for item in data:
|
|
17
|
-
result.append(normalize(item))
|
|
18
|
-
return result
|
|
19
|
-
|
|
20
|
-
if isinstance(data, D):
|
|
21
|
-
return float(data)
|
|
22
|
-
|
|
23
|
-
if isinstance(data, datetime.datetime):
|
|
24
|
-
return data.timestamp()
|
|
25
|
-
|
|
26
|
-
if type(data) in (bool, int, float):
|
|
27
|
-
return data
|
|
28
|
-
|
|
29
|
-
return str(data)
|
|
Binary file
|
simo/users/apps.py
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import pwd
|
|
3
|
-
import grp
|
|
4
|
-
import subprocess
|
|
5
|
-
from django.conf import settings
|
|
6
|
-
from django.template.loader import render_to_string
|
|
7
|
-
from django.apps import AppConfig
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class CoreAppConfig(AppConfig):
|
|
11
|
-
name = 'simo.users'
|
|
12
|
-
|
|
13
|
-
def ready(self):
|
|
14
|
-
if os.geteuid() != 0:
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
from .models import User
|
|
18
|
-
users_file = '/etc/mosquitto/mosquitto_users'
|
|
19
|
-
if not os.path.exists(users_file):
|
|
20
|
-
with open(users_file, 'w') as f:
|
|
21
|
-
f.write('')
|
|
22
|
-
|
|
23
|
-
uid = pwd.getpwnam("mosquitto").pw_uid
|
|
24
|
-
gid = grp.getgrnam("mosquitto").gr_gid
|
|
25
|
-
os.chown(users_file, uid, gid)
|
|
26
|
-
os.chmod(users_file, 0o640)
|
|
27
|
-
|
|
28
|
-
acls_file = '/etc/mosquitto/acls.conf'
|
|
29
|
-
with open(acls_file, 'w') as f:
|
|
30
|
-
f.write('')
|
|
31
|
-
|
|
32
|
-
uid = pwd.getpwnam("mosquitto").pw_uid
|
|
33
|
-
gid = grp.getgrnam("mosquitto").gr_gid
|
|
34
|
-
os.chown(acls_file, uid, gid)
|
|
35
|
-
os.chmod(acls_file, 0o640)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
ps = subprocess.Popen(
|
|
39
|
-
['mosquitto_passwd /etc/mosquitto/mosquitto_users root'],
|
|
40
|
-
shell=True, stdin=subprocess.PIPE,stdout=subprocess.PIPE
|
|
41
|
-
)
|
|
42
|
-
ps.communicate(f"{settings.SECRET_KEY}\n{settings.SECRET_KEY}".encode())
|
|
43
|
-
|
|
44
|
-
for user in User.objects.all():
|
|
45
|
-
user.update_mqtt_secret(reload=False)
|
|
46
|
-
|
|
47
|
-
from .utils import update_mqtt_acls
|
|
48
|
-
update_mqtt_acls()
|
|
49
|
-
|
|
50
|
-
if not os.path.exists('/etc/mosquitto/conf.d/simo.conf'):
|
|
51
|
-
with open('/etc/mosquitto/conf.d/simo.conf', 'w') as f:
|
|
52
|
-
f.write(render_to_string('conf/mosquitto.conf'))
|
|
53
|
-
|
|
54
|
-
subprocess.run(
|
|
55
|
-
['service', 'mosquitto', 'reload'], stdout=subprocess.PIPE
|
|
56
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|