simo 1.7.16__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.

Files changed (31) hide show
  1. simo/__pycache__/asgi.cpython-38.pyc +0 -0
  2. simo/__pycache__/on_http_start.cpython-38.pyc +0 -0
  3. simo/asgi.py +2 -0
  4. simo/core/__pycache__/app_widgets.cpython-38.pyc +0 -0
  5. simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
  6. simo/core/__pycache__/models.cpython-38.pyc +0 -0
  7. simo/core/__pycache__/socket_consumers.cpython-38.pyc +0 -0
  8. simo/core/__pycache__/tasks.cpython-38.pyc +0 -0
  9. simo/core/app_widgets.py +5 -0
  10. simo/core/controllers.py +34 -6
  11. simo/core/migrations/0025_auto_20240122_1321.py +32 -0
  12. simo/core/migrations/__pycache__/0025_auto_20240122_1321.cpython-38.pyc +0 -0
  13. simo/core/models.py +8 -0
  14. simo/core/socket_consumers.py +1 -0
  15. simo/core/tasks.py +12 -0
  16. simo/core/templates/admin/controller_widgets/lock.html +11 -0
  17. simo/core/templates/admin/controller_widgets/switch.html +1 -2
  18. simo/on_http_start.py +78 -0
  19. simo/users/__pycache__/models.cpython-38.pyc +0 -0
  20. simo/users/migrations/0024_fingerprint.py +26 -0
  21. simo/users/migrations/__pycache__/0024_fingerprint.cpython-38.pyc +0 -0
  22. simo/users/models.py +12 -2
  23. {simo-1.7.16.dist-info → simo-1.7.17.dist-info}/METADATA +1 -2
  24. {simo-1.7.16.dist-info → simo-1.7.17.dist-info}/RECORD +27 -24
  25. simo/core/__pycache__/apps.cpython-38.pyc +0 -0
  26. simo/core/apps.py +0 -28
  27. simo/users/__pycache__/apps.cpython-38.pyc +0 -0
  28. simo/users/apps.py +0 -56
  29. {simo-1.7.16.dist-info → simo-1.7.17.dist-info}/LICENSE.md +0 -0
  30. {simo-1.7.16.dist-info → simo-1.7.17.dist-info}/WHEEL +0 -0
  31. {simo-1.7.16.dist-info → simo-1.7.17.dist-info}/top_level.txt +0 -0
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
simo/core/app_widgets.py CHANGED
@@ -89,3 +89,8 @@ class QuintupleSwitchWidget(BaseAppWidget):
89
89
  size = [4, 1]
90
90
 
91
91
 
92
+ class LockWidget(BaseAppWidget):
93
+ uid = 'lock'
94
+ name = _("Lock")
95
+ size = [2, 2]
96
+
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=5):
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
- if self.component.change_init_to == to_value:
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', 'change_init_to']
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
@@ -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
+ ]
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
  )
@@ -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"
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()
@@ -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
+ ]
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.16
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=L8CUVZLM32IMzWDZ4IShdDN-m69t7oxAUeHods4-xNM,822
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=bOdmI-G4socquYp4aZk2H-v5JSPcjKrGgPjEodme7NQ,845
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,13 +26,12 @@ 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=SP1txwI8_robAapIjalciS1cnJGoPH6udi6-k3fGC-g,1928
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=tJif3k3aJNFEks929BK99qZ1b_gSedrXDKhiYGUIT-M,22474
34
+ simo/core/controllers.py,sha256=-6WAduDDoXPoRk2za3LpSRUYrn-50X_kjgf1rMBJLFs,23493
34
35
  simo/core/dynamic_settings.py,sha256=U2WNL96JzVXdZh0EqMPWrxqO6BaRR2Eo5KTDqz7MC4o,1943
35
36
  simo/core/events.py,sha256=gfew3bduIjiFusbnIoQg1LhOXRIfyLTilNMc0ROfpr8,4198
36
37
  simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
@@ -38,14 +39,14 @@ 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=HzpkUsmBwBIhFzvkIfMPlIX9wmkO-DGPNOC8H4ngPyw,18110
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=5kUaUlmeKF3V6tZaV9MFaezRNMPHwGvdpx1XaA3eJFc,9789
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=TSMI2jijUxXqQ9AwamLFc1wGFcR_qLw13kfW4kYf9II,10330
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,14 +58,13 @@ 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=4oI7IrXxPx2esGzEpAGikyJlDYYYtLaQK4yeBQHRqlA,3290
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=d2EajsCcWnZQtV-58J8-JoQJ9em2xy7VU60NRXmqQJo,20659
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
70
  simo/core/__pycache__/events.cpython-38.pyc,sha256=5EJe1jSpBzqSuH_hCKAY7vsNIfeYX0KUtPaU-cIjX6w,4973
@@ -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=JoFoaTq5mDvvImzSsVKscbEfaYYXsE6s5DDL7YjeNCM,15957
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=YqoBkpezPLw5GIfuqVz0uTqjV1QjBvRmWJkN7pngAls,8808
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=BaRm0XSvTc4OBEiYQvC8ZnLFxxGTUQw_dS5Gmrdq8K8,7678
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
@@ -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=pCXJ7k6TFbeSU_2rBSc50cqtRpLmCoyb8ON37T1tcIM,358
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
@@ -10283,12 +10286,11 @@ simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=wXGUV-i
10283
10286
  simo/users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10284
10287
  simo/users/admin.py,sha256=XpUrz1zIVLuK3Y9MF7kCJBExHpMEMkU3iNZG1YZdxO0,6560
10285
10288
  simo/users/api.py,sha256=_1Z8m4pU-9LAbLfSdZ6qXLj0amgulVPqmLX2kRGJWF4,7886
10286
- simo/users/apps.py,sha256=rf_6OOpkiwTrOTY8pIsozrVUlx-0wpOheLEPj0lIYsU,1728
10287
10289
  simo/users/auth_backends.py,sha256=I5pnaTa20-Lxfw_dFG8471xDITb0_fQl1PVhJalp5vU,3992
10288
10290
  simo/users/auto_urls.py,sha256=ee0d6fWABkJY5mQOTC8KhrqDI6d8xZkYZ4ja-gZJ-rw,269
10289
10291
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10290
10292
  simo/users/middleware.py,sha256=9epN8xDcnYAMoEjAeJGg4W9e54szTgh48LKz3rlywFI,1287
10291
- simo/users/models.py,sha256=kSBRc7Y-P15q6LwJJLOVhtc5z7tooaFvNFWvyUtPrtU,18121
10293
+ simo/users/models.py,sha256=HyN4Euh4j4dQqToR0LOBLHphztHGdQgDN41lSLarlRU,18552
10292
10294
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10293
10295
  simo/users/serializers.py,sha256=Mh2pWmsKDp7CNIxK2OTw3CfVkteZHiVoXWNF1fluvX8,2161
10294
10296
  simo/users/sso_urls.py,sha256=pcb_GhYHRtmairxJhMXE1bdcTma0BcYfKU3nCRtHQMQ,244
@@ -10299,12 +10301,11 @@ simo/users/views.py,sha256=dOQVvmlHG7ihWKJLFUBcqKOA0UDctlMKR0pTc36JZqg,3487
10299
10301
  simo/users/__pycache__/__init__.cpython-38.pyc,sha256=9otuYxq331c4lGy0DR8pigaPpzq0lQ4nrNLhlYiFAF0,159
10300
10302
  simo/users/__pycache__/admin.cpython-38.pyc,sha256=ggaIuUdEjvYZ6Y5msOlhP_LmYnqUQpkJeS6FuZr6ass,7274
10301
10303
  simo/users/__pycache__/api.cpython-38.pyc,sha256=W_VuG6hotcDA2iIsbO1p01ouqcWIl7C3JZbAk4Wp3l8,6676
10302
- simo/users/__pycache__/apps.cpython-38.pyc,sha256=E14VsKsNu8V3dPk089YREOzWUB_1xGLgprEbpMh2kMw,1694
10303
10304
  simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=MuOieBIXt6lrDx83-UQtdDyI_U8kE3pU9XR4yFLKBnE,3007
10304
10305
  simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=q8SFA5EN-tpypBzfiAsorpWdXlrC_kt4HgMCZS9bcoI,431
10305
10306
  simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
10306
10307
  simo/users/__pycache__/middleware.cpython-38.pyc,sha256=U2ENmFDCHK4qtf2Q6xLqe-VNmM6dN-sUb6q70epSgZs,1165
10307
- simo/users/__pycache__/models.cpython-38.pyc,sha256=PVjKOiTNQAT4cV6L0_U3_kJAV2B9YZJKCjtL2jnPTaw,17102
10308
+ simo/users/__pycache__/models.cpython-38.pyc,sha256=KH1jIoLIZgG22dYuuZqnVCSsnPfe4D74k76gGQdw9jk,17498
10308
10309
  simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
10309
10310
  simo/users/__pycache__/serializers.cpython-38.pyc,sha256=rCAdmyL95NkChqspE-FmAtJ6vAWjdJnPa2jrd8e6hUo,2868
10310
10311
  simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=9TkKOWZugSPhwModg5yJn2IE3YgvMQA8Vm3WGznoOuk,403
@@ -10335,6 +10336,7 @@ simo/users/migrations/0020_rename_is_god_user_is_master.py,sha256=opZkM36xt6sKuJ
10335
10336
  simo/users/migrations/0021_alter_permissionsrole_instance.py,sha256=Taw2fdHy6U1PlThC3QIWaL_ADbx7gchWsJcGxoMMElo,630
10336
10337
  simo/users/migrations/0022_userdevicereportlog_instance.py,sha256=h0ue6uMcIyVs2o58Aj0PyjGLPvCCfS28HfPIiIu_VLc,549
10337
10338
  simo/users/migrations/0023_auto_20240105_0719.py,sha256=OAkWJusXjzT6dx4EgwjvNvMEgrP_zvcG8zgi774pYG0,700
10339
+ simo/users/migrations/0024_fingerprint.py,sha256=0wfplJ3iHv_6heJx7yIQYX3D68Nf9pLPlIZoM5NcPk8,1021
10338
10340
  simo/users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10339
10341
  simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=ngXA1QR-Qc2VS-BTTZWybVXiEfifIgKaVS6bADiN8nU,4269
10340
10342
  simo/users/migrations/__pycache__/0002_componentpermission.cpython-38.pyc,sha256=pknJnpic8p6Vdx9DX41FfODXNnvexDswJtUCmC5w1tg,995
@@ -10359,6 +10361,7 @@ simo/users/migrations/__pycache__/0020_rename_is_god_user_is_master.cpython-38.p
10359
10361
  simo/users/migrations/__pycache__/0021_alter_permissionsrole_instance.cpython-38.pyc,sha256=aC1h7lz5JZbpZU55X9GdW_XJ_JixSxh0_I7TCheO_rM,863
10360
10362
  simo/users/migrations/__pycache__/0022_userdevicereportlog_instance.cpython-38.pyc,sha256=xGtWss6Blm02eNE-sBYQxwbRydqii2YcSGJNh1zseEw,785
10361
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
10362
10365
  simo/users/migrations/__pycache__/__init__.cpython-38.pyc,sha256=NKq7WLgktK8WV1oOqCPbAbdkrPV5GRGhYx4VxxI4dcs,170
10363
10366
  simo/users/templates/conf/mosquitto.conf,sha256=1eIGNuRu4Y3hfAU6qiWix648eCRrw0oOT24PnyFI4ys,189
10364
10367
  simo/users/templates/conf/mosquitto_acls.conf,sha256=ga44caTDNQE0CBKw55iM2jOuna6-9fKGwAhjyERZdRE,500
@@ -10368,8 +10371,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10368
10371
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10369
10372
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10370
10373
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10371
- simo-1.7.16.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10372
- simo-1.7.16.dist-info/METADATA,sha256=zEGTcyYdQQs9AeLo_HOSbBmyJd0uTaver9BFk4OCnzU,1749
10373
- simo-1.7.16.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
10374
- simo-1.7.16.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10375
- simo-1.7.16.dist-info/RECORD,,
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/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