simo 1.7.8__py3-none-any.whl → 1.7.10__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/fleet/controllers.py CHANGED
@@ -201,6 +201,9 @@ class PWMOutput(FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
201
201
 
202
202
  return value
203
203
 
204
+ def _val_to_success(self, value):
205
+ return self._prepare_for_set(value)
206
+
204
207
 
205
208
  class RGBLight(FleeDeviceMixin, BasicOutputMixin, BaseRGBWLight):
206
209
  config_form = ColonelRGBLightConfigForm
@@ -140,10 +140,17 @@ class FleetConsumer(AsyncWebsocketConsumer):
140
140
  port=settings.MQTT_PORT)
141
141
  self.mqtt_client.loop_start()
142
142
 
143
- config = await self.get_config_data()
144
- await self.send(json.dumps({
145
- 'command': 'set_config', 'data': config
146
- }))
143
+ # DO NOT FORCE CONFIG DATA!!!!
144
+ # as colonels might already have config and want to
145
+ # send updated values of components, like for example
146
+ # somebody turned some lights on/off while colonel was
147
+ # not connected to the main hub.
148
+ # If we force this, vales get overridden by what is last
149
+ # known by the hub
150
+ # config = await self.get_config_data()
151
+ # await self.send(json.dumps({
152
+ # 'command': 'set_config', 'data': config
153
+ # }))
147
154
 
148
155
  asyncio.create_task(self.watch_connection())
149
156
 
@@ -9,6 +9,8 @@ from django.utils.translation import gettext_lazy as _
9
9
  from django.conf import settings
10
10
  from django.urls import reverse_lazy
11
11
  from simo.conf import dynamic_settings
12
+ from simo.users.middleware import get_current_user, introduce
13
+ from simo.users.utils import get_system_user
12
14
  from simo.core.events import ObjectCommand
13
15
  from simo.core.models import RUN_STATUS_CHOICES_MAP, Component
14
16
  from simo.core.utils.helpers import get_random_string
@@ -241,6 +243,9 @@ class Thermostat(ControllerBase):
241
243
  low = target_temp - self.component.config['reaction_difference'] / 2
242
244
  high = target_temp + self.component.config['reaction_difference'] / 2
243
245
 
246
+ if not get_current_user():
247
+ introduce(get_system_user())
248
+
244
249
  if mode in ('auto', 'heater'):
245
250
  if (not heater or not heater.alive) and mode == 'heater':
246
251
  print(f"No heater on {self.component}!")
@@ -934,6 +939,7 @@ class Watering(ControllerBase):
934
939
  minute_to_start -= 24*60
935
940
 
936
941
  if minute_to_start <= local_minute < minute_to_start + gap:
942
+ introduce(get_system_user())
937
943
  self.reset()
938
944
  self.start()
939
945
 
@@ -1078,16 +1084,14 @@ class AlarmClock(ControllerBase):
1078
1084
  comp = Component.objects.filter(id=event['component']).first()
1079
1085
  if comp:
1080
1086
  if forward:
1081
- action_name = 'play_method'
1087
+ action_name = 'play_action'
1082
1088
  else:
1083
- action_name = 'reverse_method'
1089
+ action_name = 'reverse_action'
1084
1090
  action = event.get(action_name)
1085
1091
  action = getattr(comp, action, None)
1086
1092
  if action:
1087
- try:
1088
- action()
1089
- except:
1090
- pass
1093
+ action()
1094
+
1091
1095
 
1092
1096
  def _check_alarm(self, alarms, current_value):
1093
1097
 
@@ -1105,13 +1109,15 @@ class AlarmClock(ControllerBase):
1105
1109
 
1106
1110
  remove_ignores = []
1107
1111
  for ignore_alarm_uid, timestamp in current_value.get(
1108
- 'ignore_alarms',{}
1112
+ 'ignore_alarms',{}
1109
1113
  ).items():
1110
1114
  # if ignore alarm entry is now past the current time + maximum offset
1111
1115
  # drop it out from ignore_alarms map
1112
1116
  if timestamp < localtime.timestamp():
1113
1117
  print(
1114
- f"remove ignore alarm because {timestamp} < {localtime.timestamp()}")
1118
+ f"remove ignore alarm because "
1119
+ f"{timestamp} < {localtime.timestamp()}"
1120
+ )
1115
1121
  remove_ignores.append(ignore_alarm_uid)
1116
1122
  for ignore_alarm_uid in remove_ignores:
1117
1123
  current_value['ignore_alarms'].pop(ignore_alarm_uid, None)
@@ -1184,14 +1190,16 @@ class AlarmClock(ControllerBase):
1184
1190
  continue
1185
1191
  if event['uid'] in current_value['events_triggered']:
1186
1192
  continue
1193
+ introduce(get_system_user())
1187
1194
  self._execute_event(event)
1188
1195
  current_value['events_triggered'].append(event['uid'])
1189
1196
 
1190
- current_value['in_alarm'] = bool(current_value['events_triggered'])
1197
+ if not current_value['in_alarm']:
1198
+ current_value['in_alarm'] = bool(current_value['events_triggered'])
1191
1199
 
1192
1200
  # If alarm time is in the past and all events executed move to next alarm
1193
1201
  if current_value['in_alarm'] \
1194
- and current_value['alarm_timestamp'] < localtime.timestamp() \
1202
+ and current_value['alarm_timestamp'] + 60 < localtime.timestamp() \
1195
1203
  and len(current_value['events_triggered']) >= len(
1196
1204
  [e for e in current_value['events'] if e.get('enabled')]
1197
1205
  ):
@@ -1291,15 +1299,15 @@ class AlarmClock(ControllerBase):
1291
1299
  current_value['alarm_datetime'] = str(datetime.datetime.fromtimestamp(
1292
1300
  current_value['alarm_timestamp'],
1293
1301
  ).astimezone(tz=timezone.localtime().tzinfo))
1294
- triggered_events = []
1302
+ events_triggered = []
1295
1303
  for event in current_value['events']:
1296
1304
  event['fire_timestamp'] += mins * 60
1297
1305
  if event['uid'] in current_value['events_triggered']:
1298
1306
  if event['fire_timestamp'] > localtime.timestamp():
1299
1307
  self._execute_event(event, False)
1300
1308
  else:
1301
- triggered_events.append(event['uid'])
1302
- current_value['triggered_events'] = triggered_events
1309
+ events_triggered.append(event['uid'])
1310
+ current_value['events_triggered'] = events_triggered
1303
1311
 
1304
1312
  self.component.value = current_value
1305
1313
  self.component.save()
Binary file
simo/users/api.py CHANGED
@@ -102,12 +102,14 @@ class UsersViewSet(mixins.RetrieveModelMixin,
102
102
  def destroy(self, request, *args, **kwargs):
103
103
  user = self.get_object()
104
104
  if request.user.pk == user.pk:
105
- pass
106
- elif request.user.is_superuser:
105
+ raise ValidationError(
106
+ 'Deleting yourself is not allowed!', code=403
107
+ )
108
+ if request.user.is_superuser:
107
109
  pass
108
110
  else:
109
111
  role = request.user.get_role(self.instance)
110
- if not role or not role.is_superuser:
112
+ if not role or not role.can_manage_users:
111
113
  raise ValidationError(
112
114
  'You do not have permission for this!', code=403
113
115
  )
simo/users/middleware.py CHANGED
@@ -1,11 +1,24 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import threading
3
3
 
4
+ # This is only ment for logging component history actions.
5
+ # Do not use this for anything permissions related!
6
+
7
+ # This technique can only be used with asgi/wsgi runners that
8
+ # are not performing thread swapping for handling simultaneous requests.
9
+ # For example gunicorn does that when configured with more than one worker,
10
+ # which eventually messes up this system.
11
+
12
+ # We use daphne for asgi, which seems to be working fine for what we have already
13
+ # observed. However, this is a good candidate for reworking it in to something
14
+ # more rboust.
15
+
16
+ # TODO: rework this in to something more roboust
17
+
4
18
  _thread_locals = threading.local()
5
19
 
6
20
 
7
21
  def get_current_user():
8
- #TODO: VERY BAD PRACTICE!!! DROP THIS!
9
22
  try:
10
23
  return getattr(_thread_locals, 'user')
11
24
  except:
simo/users/models.py CHANGED
@@ -255,6 +255,10 @@ class User(AbstractBaseUser, SimoAdminMixin):
255
255
 
256
256
  @property
257
257
  def is_active(self):
258
+ if self.is_master and not self.instance_roles.all():
259
+ # Master that has no roles on any instance is in GOD mode!
260
+ # It can not be disabled by anybody, nor it is seen by anybody. :)
261
+ return True
258
262
  if self._instance:
259
263
  return bool(
260
264
  self.instance_roles.filter(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 1.7.8
3
+ Version: 1.7.10
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
@@ -10112,13 +10112,13 @@ simo/fleet/admin.py,sha256=NXlvKIe8ZDDcF1U6bwAXP1d8LX-0QAfruoS5pKIcdCM,4789
10112
10112
  simo/fleet/api.py,sha256=38_RUZxGRdvRCgHoX59zXqlzI-3vS2O_pCVP-lyBlR8,446
10113
10113
  simo/fleet/auto_urls.py,sha256=9kP8M_HqiXF6Dl8JLOHgXT0UaUTOr6DMH2Qr4POvecM,607
10114
10114
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10115
- simo/fleet/controllers.py,sha256=voctXyfEXDWpMxPoUpG_6bKAeawIWViktQACu2krgFo,8073
10115
+ simo/fleet/controllers.py,sha256=u3xTeGFUs4pVHWQl-va-INe4zqmaS1XqB2h5OeWg8P0,8156
10116
10116
  simo/fleet/forms.py,sha256=mG7yUbjzhSFy3hCnIrmFxxslZziq51qcBmd2_7zPIJ8,41720
10117
10117
  simo/fleet/gateways.py,sha256=W87o1P8Nubf3_v1RNn134rivHCiYIHbj4Za4sRQzSqw,204
10118
10118
  simo/fleet/models.py,sha256=4SHPX7HuZBfNwSkoDFwJjgNQs3oaSbhw_j85cXAxkqE,10092
10119
10119
  simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
10120
10120
  simo/fleet/serializers.py,sha256=uz_OE_bMdlE_C28gnBpUP0P08FdZKvFP-hgRKvJRYT0,348
10121
- simo/fleet/socket_consumers.py,sha256=wt6aXI4YY7GFij0QfuqoGgTxkoIFn3aFD2DvXz6Y_v4,11746
10121
+ simo/fleet/socket_consumers.py,sha256=pKXXkDKuGoL_Lg9IL6xgb6r4-E-kTuRwq0Nmw1mvAbg,12139
10122
10122
  simo/fleet/tasks.py,sha256=QcMgXUE2V--CsNfzmbW35F-Q3b8D53-Q6twlWOow2Ig,704
10123
10123
  simo/fleet/utils.py,sha256=ZGxN94Wp472SEZRXVC6ZkUd2dmh_tMHc0qbMtoMfDRg,4511
10124
10124
  simo/fleet/views.py,sha256=1AwE_JC13n76JiM3cQ__8CgBidCoRFUbJN-Yaz1s4HQ,1198
@@ -10132,7 +10132,7 @@ simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=hZZlVkARLKo0VwiENJh65hgiuG
10132
10132
  simo/fleet/__pycache__/models.cpython-38.pyc,sha256=RNzIw4bNTwuEvHVqs2VSLKMWa8xKPfTXD_f6WrwC-1k,8519
10133
10133
  simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
10134
10134
  simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=nbkFJzjZP27U0fvMi_yPOhH7Hj1vK0HB44wn5yT6m_Y,869
10135
- simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=PALYpTLf9FPk3E34YAMeFqHvUykVtdXXWMLHpW3UvyY,9506
10135
+ simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=GTO0-0ThS8ZGbcWKe_dF1Z3cI9FRSvF1ckuz8RDqsmc,9419
10136
10136
  simo/fleet/__pycache__/utils.cpython-38.pyc,sha256=txFY3LyTkjtEdaGfcjrjgZogMIoq4T1XR5OQCTkwh7w,2815
10137
10137
  simo/fleet/__pycache__/views.cpython-38.pyc,sha256=FAenBel5MTzNDM8Qa-QBr_5gjSYmCMWMyVjWnfz-HYM,1757
10138
10138
  simo/fleet/migrations/0001_initial.py,sha256=lce8nkD8Sz6pYr-XJSpDm4CMDuB6TA__WtnHpIp-eA4,1326
@@ -10188,7 +10188,7 @@ simo/fleet/migrations/__pycache__/__init__.cpython-38.pyc,sha256=5k1KW0jeSDzw6Rn
10188
10188
  simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10189
10189
  simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
10190
10190
  simo/generic/base_types.py,sha256=djymox_boXTHX1BTTCLXrCH7ED-uAsV_idhaDOc3OLI,409
10191
- simo/generic/controllers.py,sha256=-32OfzDsOWNVISgG-Tz4LwKyy9dQqjlM2m7eQd9EcfA,51463
10191
+ simo/generic/controllers.py,sha256=AgOOVQrIEm8_6__BMme2tB05BSGm4V15miKQhhu5dDc,51752
10192
10192
  simo/generic/forms.py,sha256=zF-QYfu6C0TZ7sJ5_-VkhUweV0_J8gg0CC07At6RIK8,19829
10193
10193
  simo/generic/gateways.py,sha256=Pp29L_2AoZ_4nW6rLHmDCbDoac-yK9evJ1ZTcfMOItc,14807
10194
10194
  simo/generic/models.py,sha256=XG8VnLSpMSiBnbKwvMknF9J9kdbmBolXvJ9L3Giz8pQ,3330
@@ -10200,7 +10200,7 @@ simo/generic/__pycache__/__init__.cpython-38.pyc,sha256=MCjhrSijserYi14I03LlOwRU
10200
10200
  simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=QGPG6EkuNwk5PhFtNFIYfbJVrXiA76fBZlu31lwuvdY,2366
10201
10201
  simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=ePcCgG0U4mrc_I3MLs2cnUh5KPX-Kf13jTy_d5pTP78,547
10202
10202
  simo/generic/__pycache__/controllers.cpython-37.pyc,sha256=5cET2P5vw-ujjYhyyLOoski91fXqiuV4zZdhRKgb028,2461
10203
- simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=ia-Qo0ZRKWfEone45ca2kKYMnS5LtuzUJtZV_q1971M,35375
10203
+ simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=4DN-Y57ts0OrkAzeAH_khTnmocBmarHMiwm-O0-Fkuk,35330
10204
10204
  simo/generic/__pycache__/forms.cpython-38.pyc,sha256=fhJCmt60aYabvuylL4ZADGuIcI7YA62iJVFav9zZ_QU,15457
10205
10205
  simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=RcFpnL04ruMINc4gr-gi8LmzqlUdHPqR7MDdxuzTMjE,10005
10206
10206
  simo/generic/__pycache__/models.cpython-38.pyc,sha256=8upnlvxpuYsg16gghJg9JZCcuyatsrWuYzDYT4psaC0,3035
@@ -10281,12 +10281,12 @@ simo/notifications/migrations/__pycache__/0002_notification_instance.cpython-38.
10281
10281
  simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=wXGUV-iMXaTLV1UNZ8FtuSK85VPF07qIr5wKwlv5yuc,186
10282
10282
  simo/users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10283
10283
  simo/users/admin.py,sha256=XpUrz1zIVLuK3Y9MF7kCJBExHpMEMkU3iNZG1YZdxO0,6560
10284
- simo/users/api.py,sha256=in_rxvuZWB2jPvy9P-DI5r5_lKbYtpwozerBewDNvdA,7790
10284
+ simo/users/api.py,sha256=_1Z8m4pU-9LAbLfSdZ6qXLj0amgulVPqmLX2kRGJWF4,7886
10285
10285
  simo/users/auth_backends.py,sha256=I5pnaTa20-Lxfw_dFG8471xDITb0_fQl1PVhJalp5vU,3992
10286
10286
  simo/users/auto_urls.py,sha256=ee0d6fWABkJY5mQOTC8KhrqDI6d8xZkYZ4ja-gZJ-rw,269
10287
10287
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10288
- simo/users/middleware.py,sha256=FhsAwgUVHSq99qbcyjZ6CXtevvZiLYQ11kPPpkI5uk0,737
10289
- simo/users/models.py,sha256=iaGqXLM94U_lqwtP4T7zesEt3Lu_HIS6wbs41RfrrJQ,17012
10288
+ simo/users/middleware.py,sha256=9epN8xDcnYAMoEjAeJGg4W9e54szTgh48LKz3rlywFI,1287
10289
+ simo/users/models.py,sha256=aSWcLp-UCrLgebYca5-w2Vnbgqe2da3AOFDGbrXsMXI,17247
10290
10290
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10291
10291
  simo/users/serializers.py,sha256=Mh2pWmsKDp7CNIxK2OTw3CfVkteZHiVoXWNF1fluvX8,2161
10292
10292
  simo/users/sso_urls.py,sha256=pcb_GhYHRtmairxJhMXE1bdcTma0BcYfKU3nCRtHQMQ,244
@@ -10296,12 +10296,12 @@ simo/users/utils.py,sha256=bbdBVDzXY3xyy8SdB8ERZF6PCmKbR137AnIyrn4HqLQ,867
10296
10296
  simo/users/views.py,sha256=dOQVvmlHG7ihWKJLFUBcqKOA0UDctlMKR0pTc36JZqg,3487
10297
10297
  simo/users/__pycache__/__init__.cpython-38.pyc,sha256=qVNCdQSNCAQRCsXJ__8eDa_UuFbLz4j_twP9f0TrCMk,144
10298
10298
  simo/users/__pycache__/admin.cpython-38.pyc,sha256=RAAzAh_7fTAKOnK-VaITHJkieOwmL8zYhDqrajHOHGs,7274
10299
- simo/users/__pycache__/api.cpython-38.pyc,sha256=bwuezVy5VBdlIut7fE3JxJCzIFGS1aokDCSl5ioo-MQ,6620
10299
+ simo/users/__pycache__/api.cpython-38.pyc,sha256=Tt3vjPEfeK2SioWa5eIE-Ujr2iNKUCADcV7RQNaPv8U,6676
10300
10300
  simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=BMVsMoWcoYUQevvj-2OSJShHbMhxbzJzP8SwqJ3Kg2E,3007
10301
10301
  simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=UCgzFKwKi1_W9jTQ2BBFq7GF7Q-wbP8r-d4Jsw8644c,423
10302
10302
  simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=dexiY5hjMsvBrxCb5_ww1rlETHtSihVRLS_j_-dLCSw,856
10303
10303
  simo/users/__pycache__/middleware.cpython-38.pyc,sha256=L1kh7QWOsrpBd6yfaiG-3MGdsB3hm-HWOzHPMUbtMnU,1165
10304
- simo/users/__pycache__/models.cpython-38.pyc,sha256=RPd5pi9Of8tRch0fGzVGhuIWfCLWleWVKyUlmJy5Bls,16541
10304
+ simo/users/__pycache__/models.cpython-38.pyc,sha256=C1RmjoSBn6aBV7SkFKPNf3uqo2hNlRqKhcEuM1JOn3E,16563
10305
10305
  simo/users/__pycache__/permissions.cpython-38.pyc,sha256=bIV9s6Y4uTX6KisJeWA_MZZ7aaDuIKu0sSYIPMXUCoo,625
10306
10306
  simo/users/__pycache__/serializers.cpython-38.pyc,sha256=XtCwvcq1BT0pVVPrmjF59ME3V9kP2Or-QAzV2ozwiR0,2868
10307
10307
  simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=DlIv-bsQRFX1LI-sr-COJb8Ah1iuAvaiVIZtY7fD2WI,395
@@ -10362,8 +10362,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=3hTtUm-Cr1axOjlwAIKsSj9
10362
10362
  simo/users/templates/invitations/expired_suggestion.html,sha256=pT67ludJdeohrlF0QIzs4eqy1SI_oH2i6H0ecEIgaCg,100
10363
10363
  simo/users/templates/invitations/taken_msg.html,sha256=Dv1MaxVVmSdL20gri4Ei-K0aZ0OTmIdmO6a3l5MKwCs,445
10364
10364
  simo/users/templates/invitations/taken_suggestion.html,sha256=NCE2XQail0WQGW8v6y3BkQoM3IOWlh02z9XPEws659E,301
10365
- simo-1.7.8.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10366
- simo-1.7.8.dist-info/METADATA,sha256=BsplD0jGI9Y5AwsGOvkspvfC930bdDqYkQkHhiduEpk,1748
10367
- simo-1.7.8.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
10368
- simo-1.7.8.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10369
- simo-1.7.8.dist-info/RECORD,,
10365
+ simo-1.7.10.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10366
+ simo-1.7.10.dist-info/METADATA,sha256=xRuEwYtKb2OMY_lpMvvyj1ipx31C0jHOTnUV67nTgWM,1749
10367
+ simo-1.7.10.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
10368
+ simo-1.7.10.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10369
+ simo-1.7.10.dist-info/RECORD,,
File without changes