simo 2.1.13__py3-none-any.whl → 2.2.2__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/core/__pycache__/managers.cpython-38.pyc +0 -0
- simo/core/controllers.py +1 -1
- simo/core/managers.py +3 -3
- simo/fleet/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/models.cpython-38.pyc +0 -0
- simo/fleet/controllers.py +36 -1
- simo/fleet/forms.py +76 -6
- simo/fleet/models.py +4 -1
- simo/fleet/templates/fleet/controllers_info/ENS160AirQualitySensor.md +15 -0
- simo/generic/__pycache__/models.cpython-38.pyc +0 -0
- simo/generic/controllers.py +4 -4
- simo/generic/models.py +12 -2
- simo/users/__pycache__/api.cpython-38.pyc +0 -0
- simo/users/__pycache__/auth_backends.cpython-38.pyc +0 -0
- simo/users/__pycache__/managers.cpython-38.pyc +0 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- simo/users/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/users/api.py +16 -3
- simo/users/auth_backends.py +5 -3
- simo/users/managers.py +7 -0
- simo/users/migrations/0001_initial.py +1 -1
- simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc +0 -0
- simo/users/models.py +8 -9
- simo/users/serializers.py +0 -1
- {simo-2.1.13.dist-info → simo-2.2.2.dist-info}/METADATA +1 -1
- {simo-2.1.13.dist-info → simo-2.2.2.dist-info}/RECORD +32 -29
- {simo-2.1.13.dist-info → simo-2.2.2.dist-info}/WHEEL +1 -1
- /simo/fleet/templates/fleet/controllers_info/{button.md → Button.md} +0 -0
- {simo-2.1.13.dist-info → simo-2.2.2.dist-info}/LICENSE.md +0 -0
- {simo-2.1.13.dist-info → simo-2.2.2.dist-info}/entry_points.txt +0 -0
- {simo-2.1.13.dist-info → simo-2.2.2.dist-info}/top_level.txt +0 -0
|
Binary file
|
simo/core/controllers.py
CHANGED
|
@@ -78,7 +78,7 @@ class ControllerBase(ABC):
|
|
|
78
78
|
@property
|
|
79
79
|
def info_template_path(self) -> str:
|
|
80
80
|
return f"{self.__class__.__module__.split('.')[-2]}/" \
|
|
81
|
-
f"controllers_info/{self.__class__.__name__
|
|
81
|
+
f"controllers_info/{self.__class__.__name__}.md"
|
|
82
82
|
|
|
83
83
|
@abstractmethod
|
|
84
84
|
def _validate_val(self, value, occasion=None):
|
simo/core/managers.py
CHANGED
|
@@ -25,7 +25,7 @@ class InstanceManager(models.Manager):
|
|
|
25
25
|
class ZonesManager(models.Manager):
|
|
26
26
|
|
|
27
27
|
def get_queryset(self):
|
|
28
|
-
qs = super().get_queryset()
|
|
28
|
+
qs = super().get_queryset().filter(instance__is_active=True)
|
|
29
29
|
instance = get_current_instance()
|
|
30
30
|
if instance:
|
|
31
31
|
qs = qs.filter(instance=instance)
|
|
@@ -35,7 +35,7 @@ class ZonesManager(models.Manager):
|
|
|
35
35
|
class CategoriesManager(models.Manager):
|
|
36
36
|
|
|
37
37
|
def get_queryset(self):
|
|
38
|
-
qs = super().get_queryset()
|
|
38
|
+
qs = super().get_queryset().filter(instance__is_active=True)
|
|
39
39
|
instance = get_current_instance()
|
|
40
40
|
if instance:
|
|
41
41
|
qs = qs.filter(instance=instance)
|
|
@@ -45,7 +45,7 @@ class CategoriesManager(models.Manager):
|
|
|
45
45
|
class ComponentsManager(models.Manager):
|
|
46
46
|
|
|
47
47
|
def get_queryset(self):
|
|
48
|
-
qs = super().get_queryset()
|
|
48
|
+
qs = super().get_queryset().filter(zone__instance__is_active=True)
|
|
49
49
|
instance = get_current_instance()
|
|
50
50
|
if instance:
|
|
51
51
|
qs = qs.filter(zone__instance=instance)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/fleet/controllers.py
CHANGED
|
@@ -25,7 +25,7 @@ from .forms import (
|
|
|
25
25
|
ColonelSwitchConfigForm, ColonelPWMOutputConfigForm,
|
|
26
26
|
ColonelNumericSensorConfigForm, ColonelRGBLightConfigForm,
|
|
27
27
|
ColonelDHTSensorConfigForm, DS18B20SensorConfigForm,
|
|
28
|
-
BME680SensorConfigForm, MPC9808SensorConfigForm,
|
|
28
|
+
BME680SensorConfigForm, MPC9808SensorConfigForm, ENS160SensorConfigForm,
|
|
29
29
|
DualMotorValveForm, BlindsConfigForm, BurglarSmokeDetectorConfigForm,
|
|
30
30
|
TTLockConfigForm, DALIDeviceConfigForm, DaliLampForm, DaliGearGroupForm,
|
|
31
31
|
DaliSwitchConfigForm,
|
|
@@ -210,6 +210,41 @@ class MPC9808TempSensor(FleeDeviceMixin, BaseNumericSensor):
|
|
|
210
210
|
name = "MPC9808 Temperature Sensor (I2C)"
|
|
211
211
|
|
|
212
212
|
|
|
213
|
+
class ENS160AirQualitySensor(FleeDeviceMixin, BaseMultiSensor):
|
|
214
|
+
gateway_class = FleetGatewayHandler
|
|
215
|
+
config_form = ENS160SensorConfigForm
|
|
216
|
+
name = "ENS160 Air Quality Sensor (I2C)"
|
|
217
|
+
|
|
218
|
+
default_value = [
|
|
219
|
+
["CO2", 0, "ppm"],
|
|
220
|
+
["TVOC", 0, "ppb"],
|
|
221
|
+
["AQI (UBA)", 0, ""]
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
def get_co2(self):
|
|
225
|
+
try:
|
|
226
|
+
for entry in self.component.value:
|
|
227
|
+
if entry[0] == 'CO2':
|
|
228
|
+
return entry[1]
|
|
229
|
+
except:
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
def get_tvoc(self):
|
|
233
|
+
try:
|
|
234
|
+
for entry in self.component.value:
|
|
235
|
+
if entry[0] == 'TVOC':
|
|
236
|
+
return entry[1]
|
|
237
|
+
except:
|
|
238
|
+
return
|
|
239
|
+
|
|
240
|
+
def get_aqi(self):
|
|
241
|
+
try:
|
|
242
|
+
for entry in self.component.value:
|
|
243
|
+
if entry[0] == 'AQI (UBA)':
|
|
244
|
+
return entry[1]
|
|
245
|
+
except:
|
|
246
|
+
return
|
|
247
|
+
|
|
213
248
|
|
|
214
249
|
class BasicOutputMixin:
|
|
215
250
|
gateway_class = FleetGatewayHandler
|
simo/fleet/forms.py
CHANGED
|
@@ -462,9 +462,9 @@ class BME680SensorConfigForm(ColonelComponentForm):
|
|
|
462
462
|
]
|
|
463
463
|
)
|
|
464
464
|
)
|
|
465
|
-
i2c_address = forms.
|
|
466
|
-
|
|
467
|
-
|
|
465
|
+
i2c_address = forms.TypedChoiceField(
|
|
466
|
+
coerce=int, initial=118,
|
|
467
|
+
choices=((118, "0x76"), (119, "0x77")),
|
|
468
468
|
)
|
|
469
469
|
read_frequency_s = forms.IntegerField(
|
|
470
470
|
initial=60, min_value=1, max_value=60*60*24,
|
|
@@ -482,6 +482,13 @@ class BME680SensorConfigForm(ColonelComponentForm):
|
|
|
482
482
|
f"This interface is on {self.cleaned_data['interface'].colonel}, "
|
|
483
483
|
f"however we need an interface from {self.cleaned_data['colonel']}."
|
|
484
484
|
)
|
|
485
|
+
other_comp = Component.objects.filter(
|
|
486
|
+
config__colonel=self.cleaned_data['colonel'].id,
|
|
487
|
+
config__interface=self.cleaned_data['interface'].id,
|
|
488
|
+
config__i2c_address=self.cleaned_data['i2c_address']
|
|
489
|
+
).exclude(id=self.instance.id).first()
|
|
490
|
+
if other_comp:
|
|
491
|
+
self.add_error('i2c_address', f'Already occupied by {other_comp}!')
|
|
485
492
|
return self.cleaned_data
|
|
486
493
|
|
|
487
494
|
def save(self, commit=True):
|
|
@@ -504,9 +511,14 @@ class MPC9808SensorConfigForm(ColonelComponentForm):
|
|
|
504
511
|
]
|
|
505
512
|
)
|
|
506
513
|
)
|
|
507
|
-
i2c_address = forms.
|
|
508
|
-
|
|
509
|
-
|
|
514
|
+
i2c_address = forms.TypedChoiceField(
|
|
515
|
+
coerce=int, initial=24,
|
|
516
|
+
choices=(
|
|
517
|
+
(24, "Default"),
|
|
518
|
+
(25, "AD0"), (25, "AD1"), (28, "AD2"),
|
|
519
|
+
(27, "AD0 + AD1"), (29, "AD0 + AD2"), (30, "AD1 + AD2"),
|
|
520
|
+
(31, "AD0 + AD1 + AD2")
|
|
521
|
+
),
|
|
510
522
|
)
|
|
511
523
|
read_frequency_s = forms.IntegerField(
|
|
512
524
|
initial=60, min_value=1, max_value=60 * 60 * 24,
|
|
@@ -524,6 +536,14 @@ class MPC9808SensorConfigForm(ColonelComponentForm):
|
|
|
524
536
|
f"This interface is on {self.cleaned_data['interface'].colonel}, "
|
|
525
537
|
f"however we need an interface from {self.cleaned_data['colonel']}."
|
|
526
538
|
)
|
|
539
|
+
|
|
540
|
+
other_comp = Component.objects.filter(
|
|
541
|
+
config__colonel=self.cleaned_data['colonel'].id,
|
|
542
|
+
config__interface=self.cleaned_data['interface'].id,
|
|
543
|
+
config__i2c_address=self.cleaned_data['i2c_address']
|
|
544
|
+
).exclude(id=self.instance.id).first()
|
|
545
|
+
if other_comp:
|
|
546
|
+
self.add_error('i2c_address', f'Already occupied by {other_comp}!')
|
|
527
547
|
return self.cleaned_data
|
|
528
548
|
|
|
529
549
|
def save(self, commit=True):
|
|
@@ -532,6 +552,56 @@ class MPC9808SensorConfigForm(ColonelComponentForm):
|
|
|
532
552
|
return super().save(commit=commit)
|
|
533
553
|
|
|
534
554
|
|
|
555
|
+
class ENS160SensorConfigForm(ColonelComponentForm):
|
|
556
|
+
interface = ColonelInterfacesChoiceField(
|
|
557
|
+
queryset=Interface.objects.filter(type='i2c'),
|
|
558
|
+
widget=autocomplete.ListSelect2(
|
|
559
|
+
url='autocomplete-interfaces',
|
|
560
|
+
forward=[
|
|
561
|
+
forward.Self(),
|
|
562
|
+
forward.Field('colonel'),
|
|
563
|
+
forward.Const(
|
|
564
|
+
{'type': 'i2c'}, 'filters'
|
|
565
|
+
)
|
|
566
|
+
]
|
|
567
|
+
)
|
|
568
|
+
)
|
|
569
|
+
i2c_address = forms.TypedChoiceField(
|
|
570
|
+
coerce=int, initial=83,
|
|
571
|
+
choices=((82, "0x52"), (83, "0x53")),
|
|
572
|
+
)
|
|
573
|
+
read_frequency_s = forms.IntegerField(
|
|
574
|
+
initial=10, min_value=1, max_value=60 * 60 * 24,
|
|
575
|
+
help_text='read and report air quality values every s. '
|
|
576
|
+
'Can not be less than 1s.'
|
|
577
|
+
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
def clean(self):
|
|
581
|
+
if not self.cleaned_data.get('colonel'):
|
|
582
|
+
return self.cleaned_data
|
|
583
|
+
if self.cleaned_data['interface'].colonel != self.cleaned_data['colonel']:
|
|
584
|
+
self.add_error(
|
|
585
|
+
'interface',
|
|
586
|
+
f"This interface is on {self.cleaned_data['interface'].colonel}, "
|
|
587
|
+
f"however we need an interface from {self.cleaned_data['colonel']}."
|
|
588
|
+
)
|
|
589
|
+
other_comp = Component.objects.filter(
|
|
590
|
+
config__colonel=self.cleaned_data['colonel'].id,
|
|
591
|
+
config__interface=self.cleaned_data['interface'].id,
|
|
592
|
+
config__i2c_address=self.cleaned_data['i2c_address']
|
|
593
|
+
).exclude(id=self.instance.id).first()
|
|
594
|
+
if other_comp:
|
|
595
|
+
self.add_error('i2c_address', f'Already occupied by {other_comp}!')
|
|
596
|
+
return self.cleaned_data
|
|
597
|
+
|
|
598
|
+
def save(self, commit=True):
|
|
599
|
+
if 'interface' in self.cleaned_data:
|
|
600
|
+
self.instance.config['i2c_interface'] = \
|
|
601
|
+
self.cleaned_data['interface'].no
|
|
602
|
+
return super().save(commit=commit)
|
|
603
|
+
|
|
604
|
+
|
|
535
605
|
class ColonelTouchSensorConfigForm(ColonelComponentForm):
|
|
536
606
|
pin = ColonelPinChoiceField(
|
|
537
607
|
label="Port",
|
simo/fleet/models.py
CHANGED
|
@@ -11,7 +11,6 @@ from dirtyfields import DirtyFieldsMixin
|
|
|
11
11
|
from simo.core.models import Instance, Gateway, Component
|
|
12
12
|
from simo.core.utils.helpers import get_random_string
|
|
13
13
|
from simo.core.events import GatewayObjectCommand
|
|
14
|
-
from .gateways import FleetGatewayHandler
|
|
15
14
|
from .managers import ColonelsManager, ColonelPinsManager, InterfacesManager
|
|
16
15
|
from .utils import GPIO_PINS, INTERFACES_PINS_MAP
|
|
17
16
|
|
|
@@ -146,6 +145,7 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
146
145
|
return resp.json()
|
|
147
146
|
|
|
148
147
|
def update_firmware(self, to_version):
|
|
148
|
+
from .gateways import FleetGatewayHandler
|
|
149
149
|
for gateway in Gateway.objects.filter(type=FleetGatewayHandler.uid):
|
|
150
150
|
GatewayObjectCommand(
|
|
151
151
|
gateway, self,
|
|
@@ -153,12 +153,14 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
153
153
|
).publish()
|
|
154
154
|
|
|
155
155
|
def restart(self):
|
|
156
|
+
from .gateways import FleetGatewayHandler
|
|
156
157
|
for gateway in Gateway.objects.filter(type=FleetGatewayHandler.uid):
|
|
157
158
|
GatewayObjectCommand(
|
|
158
159
|
gateway, self, command='restart'
|
|
159
160
|
).publish()
|
|
160
161
|
|
|
161
162
|
def update_config(self):
|
|
163
|
+
from .gateways import FleetGatewayHandler
|
|
162
164
|
for gateway in Gateway.objects.filter(type=FleetGatewayHandler.uid):
|
|
163
165
|
GatewayObjectCommand(
|
|
164
166
|
gateway, self, command='update_config'
|
|
@@ -371,6 +373,7 @@ class Interface(models.Model):
|
|
|
371
373
|
|
|
372
374
|
|
|
373
375
|
def broadcast_reset(self):
|
|
376
|
+
from .gateways import FleetGatewayHandler
|
|
374
377
|
gw = Gateway.objects.filter(type=FleetGatewayHandler.uid).first()
|
|
375
378
|
if not gw:
|
|
376
379
|
return
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
### Initial Start-Up
|
|
2
|
+
|
|
3
|
+
Initial Start-Up is the time the ENS160 needs to exhibit reasonable air quality readings after
|
|
4
|
+
its first ever power-on.
|
|
5
|
+
The ENS160 sensor raw resistance signals and sensitivities will change upon first power-on.
|
|
6
|
+
The change in resistance is greatest in the first 48 hours of operation. Therefore, the ENS160
|
|
7
|
+
employs a start-up algorithm, allowing eCO2-, TVOC- and AQI-output signals to be used from
|
|
8
|
+
first power-on after 1 hour of operation.
|
|
9
|
+
|
|
10
|
+
### Warm-Up
|
|
11
|
+
|
|
12
|
+
Further to “Initial Start-Up” the conditioning or “Warm-Up” period is the time required to
|
|
13
|
+
achieve adequate sensor stability before measuring VOCs after idle periods or power-off.
|
|
14
|
+
Typically, the ENS160 requires 1 minute of warm-up before reasonable air quality readings
|
|
15
|
+
can be expected.
|
|
Binary file
|
simo/generic/controllers.py
CHANGED
|
@@ -1048,8 +1048,8 @@ class Watering(ControllerBase):
|
|
|
1048
1048
|
def _perform_schedule(self):
|
|
1049
1049
|
self.component.refresh_from_db()
|
|
1050
1050
|
next_run = self._get_next_run()
|
|
1051
|
-
if self.component.
|
|
1052
|
-
self.component.
|
|
1051
|
+
if self.component.meta['next_run'] != next_run:
|
|
1052
|
+
self.component.meta['next_run'] = next_run
|
|
1053
1053
|
self.component.save()
|
|
1054
1054
|
|
|
1055
1055
|
if self.component.value['status'] == 'running_program':
|
|
@@ -1065,8 +1065,8 @@ class Watering(ControllerBase):
|
|
|
1065
1065
|
str(localtime.weekday() + 1)
|
|
1066
1066
|
]
|
|
1067
1067
|
if not times_to_start:
|
|
1068
|
-
if self.component.
|
|
1069
|
-
self.component.
|
|
1068
|
+
if self.component.meta.get('next_run'):
|
|
1069
|
+
self.component.meta['next_run'] = None
|
|
1070
1070
|
self.component.save()
|
|
1071
1071
|
return
|
|
1072
1072
|
|
simo/generic/models.py
CHANGED
|
@@ -6,8 +6,6 @@ from django.db.models.signals import pre_save, post_save, post_delete
|
|
|
6
6
|
from django.dispatch import receiver
|
|
7
7
|
from simo.core.models import Instance, Component
|
|
8
8
|
from simo.users.models import InstanceUser
|
|
9
|
-
from .controllers import AlarmGroup
|
|
10
|
-
|
|
11
9
|
|
|
12
10
|
|
|
13
11
|
@receiver(post_save, sender=Component)
|
|
@@ -20,6 +18,8 @@ def handle_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
20
18
|
if 'arm_status' not in dirty_fields:
|
|
21
19
|
return
|
|
22
20
|
|
|
21
|
+
from .controllers import AlarmGroup
|
|
22
|
+
|
|
23
23
|
for alarm_group in Component.objects.filter(
|
|
24
24
|
controller_uid=AlarmGroup.uid,
|
|
25
25
|
config__components__contains=instance.id,
|
|
@@ -76,6 +76,8 @@ def handle_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
76
76
|
|
|
77
77
|
@receiver(pre_save, sender=Component)
|
|
78
78
|
def manage_alarm_groups(sender, instance, *args, **kwargs):
|
|
79
|
+
from .controllers import AlarmGroup
|
|
80
|
+
|
|
79
81
|
if instance.controller_uid != AlarmGroup.uid:
|
|
80
82
|
return
|
|
81
83
|
|
|
@@ -104,6 +106,8 @@ def manage_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
104
106
|
def clear_alarm_group_config_on_component_delete(
|
|
105
107
|
sender, instance, *args, **kwargs
|
|
106
108
|
):
|
|
109
|
+
from .controllers import AlarmGroup
|
|
110
|
+
|
|
107
111
|
for ag in Component.objects.filter(
|
|
108
112
|
base_type=AlarmGroup.base_type,
|
|
109
113
|
config__components__contains=instance.id
|
|
@@ -120,6 +124,9 @@ def bind_controlling_locks_to_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
120
124
|
return
|
|
121
125
|
if 'value' not in instance.get_dirty_fields():
|
|
122
126
|
return
|
|
127
|
+
|
|
128
|
+
from .controllers import AlarmGroup
|
|
129
|
+
|
|
123
130
|
if instance.value == 'locked':
|
|
124
131
|
for ag in Component.objects.filter(
|
|
125
132
|
base_type=AlarmGroup.base_type,
|
|
@@ -169,6 +176,9 @@ def bind_alarm_groups(sender, instance, created, *args, **kwargs):
|
|
|
169
176
|
).exclude(is_active=False).exclude(id=instance.id).count()
|
|
170
177
|
if users_at_home:
|
|
171
178
|
return
|
|
179
|
+
|
|
180
|
+
from .controllers import AlarmGroup
|
|
181
|
+
|
|
172
182
|
for ag in Component.objects.filter(
|
|
173
183
|
zone__instance=instance.instance,
|
|
174
184
|
base_type=AlarmGroup.base_type,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/users/api.py
CHANGED
|
@@ -211,9 +211,22 @@ class InvitationsViewSet(InstanceMixin, viewsets.ModelViewSet):
|
|
|
211
211
|
return InstanceInvitation.objects.none()
|
|
212
212
|
return InstanceInvitation.objects.filter(instance=self.instance)
|
|
213
213
|
|
|
214
|
-
def
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
def create(self, request, *args, **kwargs):
|
|
215
|
+
role = PermissionsRole.objects.filter(
|
|
216
|
+
instance=self.instance, is_default=True
|
|
217
|
+
).first()
|
|
218
|
+
if not role:
|
|
219
|
+
role = PermissionsRole.objects.filter(
|
|
220
|
+
instance=self.instance
|
|
221
|
+
).first()
|
|
222
|
+
if role:
|
|
223
|
+
request.data['role'] = role.id
|
|
224
|
+
serializer = self.get_serializer(data=request.data)
|
|
225
|
+
serializer.is_valid(raise_exception=True)
|
|
226
|
+
serializer.save(instance=self.instance, from_user=self.request.user)
|
|
227
|
+
headers = self.get_success_headers(serializer.data)
|
|
228
|
+
return RESTResponse(
|
|
229
|
+
serializer.data, status=status.HTTP_201_CREATED, headers=headers
|
|
217
230
|
)
|
|
218
231
|
|
|
219
232
|
@action(detail=True, methods=['post'])
|
simo/users/auth_backends.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import io
|
|
3
3
|
import requests
|
|
4
|
+
from django.db import transaction
|
|
4
5
|
from django.utils import timezone
|
|
5
6
|
from django.contrib.auth import get_user_model
|
|
6
7
|
from django.contrib.auth.models import Permission
|
|
@@ -54,6 +55,7 @@ class SIMOUserBackend(ModelBackend):
|
|
|
54
55
|
|
|
55
56
|
class SSOBackend(ModelBackend):
|
|
56
57
|
|
|
58
|
+
@transaction.atomic
|
|
57
59
|
def authenticate(self, request, user_data=None, **kwargs):
|
|
58
60
|
system_user_emails = ('system@simo.io', 'device@simo.io')
|
|
59
61
|
if not user_data:
|
|
@@ -93,9 +95,9 @@ class SSOBackend(ModelBackend):
|
|
|
93
95
|
if invitation:
|
|
94
96
|
invitation.taken_by = user
|
|
95
97
|
invitation.save()
|
|
96
|
-
InstanceUser.objects.
|
|
97
|
-
user=user,
|
|
98
|
-
|
|
98
|
+
InstanceUser.objects.update_or_create(
|
|
99
|
+
user=user, instance=invitation.instance,
|
|
100
|
+
defaults={'role': invitation.role}
|
|
99
101
|
)
|
|
100
102
|
|
|
101
103
|
if user_data.get('name'):
|
simo/users/managers.py
ADDED
|
@@ -103,7 +103,7 @@ class Migration(migrations.Migration):
|
|
|
103
103
|
('last_sent', models.DateTimeField(blank=True, null=True)),
|
|
104
104
|
('taken_date', models.DateTimeField(blank=True, null=True)),
|
|
105
105
|
('from_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='issued_hub_invitations', to=settings.AUTH_USER_MODEL)),
|
|
106
|
-
('role', models.ForeignKey(
|
|
106
|
+
('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.permissionsrole')),
|
|
107
107
|
('taken_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accepted_hub_invitations', to=settings.AUTH_USER_MODEL)),
|
|
108
108
|
],
|
|
109
109
|
options={
|
|
Binary file
|
simo/users/models.py
CHANGED
|
@@ -24,7 +24,7 @@ from simo.core.utils.helpers import get_random_string
|
|
|
24
24
|
from simo.core.events import OnChangeMixin
|
|
25
25
|
from .middleware import get_current_user
|
|
26
26
|
from .utils import rebuild_authorized_keys
|
|
27
|
-
from .
|
|
27
|
+
from .managers import ActiveInstanceManager
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class PermissionsRole(models.Model):
|
|
@@ -49,6 +49,8 @@ class PermissionsRole(models.Model):
|
|
|
49
49
|
default=False, help_text="Default new user role."
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
+
objects = ActiveInstanceManager()
|
|
53
|
+
|
|
52
54
|
class Meta:
|
|
53
55
|
verbose_name = "role"
|
|
54
56
|
verbose_name_plural = "roles"
|
|
@@ -97,6 +99,8 @@ class InstanceUser(DirtyFieldsMixin, models.Model, OnChangeMixin):
|
|
|
97
99
|
at_home = models.BooleanField(default=False, db_index=True)
|
|
98
100
|
is_active = models.BooleanField(default=True, db_index=True)
|
|
99
101
|
|
|
102
|
+
objects = ActiveInstanceManager()
|
|
103
|
+
|
|
100
104
|
class Meta:
|
|
101
105
|
unique_together = 'user', 'instance'
|
|
102
106
|
|
|
@@ -529,12 +533,6 @@ def get_default_inviation_expire_date():
|
|
|
529
533
|
return timezone.now() + datetime.timedelta(days=14)
|
|
530
534
|
|
|
531
535
|
|
|
532
|
-
def get_default_invitation_role():
|
|
533
|
-
role = PermissionsRole.objects.filter(is_default=True).first()
|
|
534
|
-
if not role:
|
|
535
|
-
return PermissionsRole.objects.all().first().id
|
|
536
|
-
return role.id
|
|
537
|
-
|
|
538
536
|
|
|
539
537
|
class InstanceInvitation(models.Model):
|
|
540
538
|
instance = models.ForeignKey('core.Instance', on_delete=models.CASCADE)
|
|
@@ -542,8 +540,7 @@ class InstanceInvitation(models.Model):
|
|
|
542
540
|
max_length=50, default=get_random_string, db_index=True
|
|
543
541
|
)
|
|
544
542
|
role = models.ForeignKey(
|
|
545
|
-
PermissionsRole, on_delete=models.CASCADE
|
|
546
|
-
default=get_default_invitation_role
|
|
543
|
+
PermissionsRole, on_delete=models.CASCADE
|
|
547
544
|
)
|
|
548
545
|
issue_date = models.DateTimeField(auto_now_add=True)
|
|
549
546
|
expire_date = models.DateTimeField(
|
|
@@ -561,6 +558,8 @@ class InstanceInvitation(models.Model):
|
|
|
561
558
|
)
|
|
562
559
|
taken_date = models.DateTimeField(null=True, blank=True)
|
|
563
560
|
|
|
561
|
+
objects = ActiveInstanceManager()
|
|
562
|
+
|
|
564
563
|
|
|
565
564
|
class Meta:
|
|
566
565
|
verbose_name = "invitation"
|
simo/users/serializers.py
CHANGED
|
@@ -23,7 +23,7 @@ simo/core/auto_urls.py,sha256=nNXEgLAAAQAhRWQDA9AbDtw-zcPKmu_pufJaSa8g818,1102
|
|
|
23
23
|
simo/core/autocomplete_views.py,sha256=JT5LA2_Wtr60XYSAIqaXFKFYPjrmkEf6yunXD9y2zco,4022
|
|
24
24
|
simo/core/base_types.py,sha256=qVh6MrXZEfN7bFOyFftC7u0yyz0PkvpsjllLBc6SCp4,616
|
|
25
25
|
simo/core/context.py,sha256=98PXAMie43faRVBFkOG22uNpvGRNprcGhzjBFkrxaRY,1367
|
|
26
|
-
simo/core/controllers.py,sha256=
|
|
26
|
+
simo/core/controllers.py,sha256=y6nB_iv1KxsyNutGRYZIBAHua2BHuV7OMRBD9nJXFbg,29521
|
|
27
27
|
simo/core/dynamic_settings.py,sha256=U9pY7p_hoeD1LxobIvxZqQ7Zn_4MhYMqZvsr4O0PAYs,1871
|
|
28
28
|
simo/core/events.py,sha256=LvtonJGNyCb6HLozs4EG0WZItnDwNdtnGQ4vTcnKvUs,4438
|
|
29
29
|
simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
|
|
@@ -31,7 +31,7 @@ simo/core/form_fields.py,sha256=9tIjiEN3IE55GPyB4tOlfkd51JDne3-h8pKhpL3tLFE,2220
|
|
|
31
31
|
simo/core/forms.py,sha256=QTPEe7nxzhg8NNCQFsVJpoO1LQW6MNNTHkEhBs7keYw,21386
|
|
32
32
|
simo/core/gateways.py,sha256=m0eS3XjVe34Dge6xtoCq16kFWCKJcdQrT0JW0REqoq8,3715
|
|
33
33
|
simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
|
|
34
|
-
simo/core/managers.py,sha256=
|
|
34
|
+
simo/core/managers.py,sha256=n-b3I4uXzfHKTeB1VMjSaMsDUxp8FegFJwnbV1IsWQ4,3019
|
|
35
35
|
simo/core/middleware.py,sha256=Go4DAdnXWd7i0ZEbftwfcZI5YGjZ31aQqDzWE4s676c,1970
|
|
36
36
|
simo/core/models.py,sha256=Mg6UjGQjA5WtxO2kq9fO-iW2f9UzDh58etcZ9-X5RSU,21570
|
|
37
37
|
simo/core/permissions.py,sha256=D8JA3gdsbSfA1Lz6-AIP5ILsYYZ59_Rw4csLqVpuKuE,2928
|
|
@@ -64,7 +64,7 @@ simo/core/__pycache__/form_fields.cpython-38.pyc,sha256=u0voKXkA64xbH6LY_-jMBHQS
|
|
|
64
64
|
simo/core/__pycache__/forms.cpython-38.pyc,sha256=gDYKULuBTMLxrKfzWXaLDbxuCJvhi2rwR5rIMC_IIVI,17672
|
|
65
65
|
simo/core/__pycache__/gateways.cpython-38.pyc,sha256=D1ooHL-iSpQrxnD8uAl4xWFJmm-QWZfbkLiLlFOMtdU,4553
|
|
66
66
|
simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
|
|
67
|
-
simo/core/__pycache__/managers.cpython-38.pyc,sha256=
|
|
67
|
+
simo/core/__pycache__/managers.cpython-38.pyc,sha256=6RTIxyjOgpQGtAqcUyE2vFPS09w1V5Wmd_vOV7rHRRI,3370
|
|
68
68
|
simo/core/__pycache__/middleware.cpython-38.pyc,sha256=94jRByEYOhsIuiMgPq_oHrRKrvD8rgQw8plS0n1Mrz8,1933
|
|
69
69
|
simo/core/__pycache__/models.cpython-38.pyc,sha256=rKg-_vQ-3L3_NKbCd0HIij7Nyev1t7SOz32-6PS4Rds,17907
|
|
70
70
|
simo/core/__pycache__/permissions.cpython-38.pyc,sha256=pg11ulzmKh4IeWGPIDJ-KYG-S0dKyY5lHh-S3iljb0E,2930
|
|
@@ -10191,11 +10191,11 @@ simo/fleet/api.py,sha256=Hxn84xI-Q77HxjINgRbjSJQOv9jii4OL20LxK0VSrS8,2499
|
|
|
10191
10191
|
simo/fleet/auto_urls.py,sha256=UX66eR2ykMqFgfIllW-RTdjup5-FieCWl_BVm3CcXKg,702
|
|
10192
10192
|
simo/fleet/base_types.py,sha256=wL9RVkHr0gA7HI1wZq0pruGEIgvQqpfnCL4cC3ywsvw,102
|
|
10193
10193
|
simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
|
|
10194
|
-
simo/fleet/controllers.py,sha256=
|
|
10195
|
-
simo/fleet/forms.py,sha256=
|
|
10194
|
+
simo/fleet/controllers.py,sha256=mASn88pUAFnkmd0UreXh2M0amZpjbv3xMghfTC8OB94,29744
|
|
10195
|
+
simo/fleet/forms.py,sha256=gp95NiQl6Lik-FzY6pSXNAa85VN-HeSOe5vr8Lc2pVc,57219
|
|
10196
10196
|
simo/fleet/gateways.py,sha256=lKEJW0MgaOEiNnijH50DNSVChvaUT3TA3UurcI57P8k,5677
|
|
10197
10197
|
simo/fleet/managers.py,sha256=XOpDOA9L-f_550TNSyXnJbun2EmtGz1TenVTMlUSb8E,807
|
|
10198
|
-
simo/fleet/models.py,sha256=
|
|
10198
|
+
simo/fleet/models.py,sha256=t_oi6EYSkg8Y5p3trJPv4MqW6AyUcylge9Bfw83mWCg,16462
|
|
10199
10199
|
simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
|
|
10200
10200
|
simo/fleet/serializers.py,sha256=-16BjY_bp9VbDOYuD0V54h7r_RHpuLNkJX0SydWL9aU,2247
|
|
10201
10201
|
simo/fleet/socket_consumers.py,sha256=aBNTxvYIw5a5l2ns9x0LnjVJvp4NValEJG4MT4hGAT0,17903
|
|
@@ -10208,11 +10208,11 @@ simo/fleet/__pycache__/api.cpython-38.pyc,sha256=rL9fb7cCQatyFvXyKmlNOKmxVo8vHYe
|
|
|
10208
10208
|
simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=Tc6a6BCXHjijP8U2jE2ghlJwnSNrGm59-hW5t-80wF0,689
|
|
10209
10209
|
simo/fleet/__pycache__/base_types.cpython-38.pyc,sha256=deyPwjpT6xZiFxBGFnj5b7R-lbdOTh2krgpJhrcGVhc,274
|
|
10210
10210
|
simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
|
|
10211
|
-
simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
10212
|
-
simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=
|
|
10211
|
+
simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=CagiILAhdfOsckuO6nh5ukKjAqke4O1m4LSHbAQru5I,24830
|
|
10212
|
+
simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=bdJgWyMfvGtnQiord-SawX8it5OVqJdY21hH5qkPjOQ,38820
|
|
10213
10213
|
simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=0RKVn0ndreVKhsrukqeLPSdMnRrsQ_W7yeVeBkRLfIk,5058
|
|
10214
10214
|
simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=8uz-xpUiqbGDgXIZ_XRZtFb-Tju6NGxflGg-Ee4Yo6k,1310
|
|
10215
|
-
simo/fleet/__pycache__/models.cpython-38.pyc,sha256=
|
|
10215
|
+
simo/fleet/__pycache__/models.cpython-38.pyc,sha256=GZ01BjdvTn6_XJBfV8VrSldJ67X06ne-xW4CsQ6N6Wc,13756
|
|
10216
10216
|
simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
|
|
10217
10217
|
simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=9ljhwoHkolcVrJwOVbYCbGPAUKgALRwor_M3W_K0adE,3173
|
|
10218
10218
|
simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=oAnUJbrKjhC3-G-o4F-bx3ZztQf7JhmHi-Sh3cm4-4s,13549
|
|
@@ -10295,14 +10295,15 @@ simo/fleet/migrations/__pycache__/0035_auto_20240514_0855.cpython-38.pyc,sha256=
|
|
|
10295
10295
|
simo/fleet/migrations/__pycache__/0036_auto_20240605_0702.cpython-38.pyc,sha256=SDGibhEg0SYDF6fCte8l8NLChvHKn1qhLIrNZ_WoZQk,1654
|
|
10296
10296
|
simo/fleet/migrations/__pycache__/0037_alter_colonelpin_options_alter_colonelpin_no_and_more.cpython-38.pyc,sha256=ZappGrTStz3EIHlQ94y5ieXI-SkM9J1ashPey13ncFA,955
|
|
10297
10297
|
simo/fleet/migrations/__pycache__/__init__.cpython-38.pyc,sha256=5k1KW0jeSDzw6RnVPRq4CaO13Lg7M0F-pxA_gqqZ6Mg,170
|
|
10298
|
-
simo/fleet/templates/fleet/controllers_info/
|
|
10298
|
+
simo/fleet/templates/fleet/controllers_info/Button.md,sha256=GIuxqG617174NEtpPeCGVocxO4YMe7-CacgVSu_L5-E,739
|
|
10299
|
+
simo/fleet/templates/fleet/controllers_info/ENS160AirQualitySensor.md,sha256=3LSTY9YPFuVPIbVsYCAifcotrXJcOXl2k774_vo6nAE,770
|
|
10299
10300
|
simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10300
10301
|
simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
|
|
10301
10302
|
simo/generic/base_types.py,sha256=djymox_boXTHX1BTTCLXrCH7ED-uAsV_idhaDOc3OLI,409
|
|
10302
|
-
simo/generic/controllers.py,sha256=
|
|
10303
|
+
simo/generic/controllers.py,sha256=lnojSqDQ-1FArF2wH_c11y0qd906Wog-qrSG1DoqeXc,58284
|
|
10303
10304
|
simo/generic/forms.py,sha256=IAfDtmEk1-CP0JBoetOD_ahLm64nK41GOUXjmbUzNtY,29550
|
|
10304
10305
|
simo/generic/gateways.py,sha256=cc_q_g2HsI2_rWmr8yZ3spnMPwsgoYS5ApWRimc11wU,18831
|
|
10305
|
-
simo/generic/models.py,sha256=
|
|
10306
|
+
simo/generic/models.py,sha256=flpK2jsBFghrvRHzl6IKT-t3WZ-hNOj4ZP2vmBzx0K8,7657
|
|
10306
10307
|
simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
|
|
10307
10308
|
simo/generic/socket_consumers.py,sha256=NfTQGYtVAc864IoogZRxf_0xpDPM0eMCWn0SlKA5P7Y,1751
|
|
10308
10309
|
simo/generic/__pycache__/__init__.cpython-38.pyc,sha256=mLu54WS9KIl-pHwVCBKpsDFIlOqml--JsOVzAUHg6cU,161
|
|
@@ -10311,7 +10312,7 @@ simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=ptw6axyAqemZA35oa6vzr7
|
|
|
10311
10312
|
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=9ZnI6Z084og6Q-9fmhT-PZEM5w_yOC1rwMAHHA6af_Q,36460
|
|
10312
10313
|
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=v85YEQR9l0QyUgYW_uTKr5qFCjp8TYOAAnfYQvYActI,21227
|
|
10313
10314
|
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=8NbsLVDww3Ov5DKF--LKgyrgnrn8yVcKrY21cdvV5aA,13979
|
|
10314
|
-
simo/generic/__pycache__/models.cpython-38.pyc,sha256=
|
|
10315
|
+
simo/generic/__pycache__/models.cpython-38.pyc,sha256=n3FeTMJYh4B6nCPiPKeXiWsUOOWkLHca7qTvfTK6Iik,5844
|
|
10315
10316
|
simo/generic/__pycache__/routing.cpython-38.pyc,sha256=xtxTUTBTdivzFyA5Wh7k-hUj1WDO_FiRq6HYXdbr9Ks,382
|
|
10316
10317
|
simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=piFHces0J9QuXu_CNBCQCYjoZEeoaxyVjLfJ9KaR8C8,1898
|
|
10317
10318
|
simo/generic/static/weather_icons/01d@2x.png,sha256=TZfWi6Rfddb2P-oldWWcjUiuCHiU9Yrc5hyrQAhF26I,948
|
|
@@ -10402,15 +10403,16 @@ simo/notifications/migrations/__pycache__/0002_notification_instance.cpython-38.
|
|
|
10402
10403
|
simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=YMBRHVon2nWDtIUbghckjnC12sIg_ykPWhV5aM0tto4,178
|
|
10403
10404
|
simo/users/__init__.py,sha256=6a7uBpCWB_DR7p54rbHusc0xvi1qfT1ZCCQGb6TiBh8,52
|
|
10404
10405
|
simo/users/admin.py,sha256=6RKGnwcrmewJFPzpqnxYn8rxjHO4tJPVFJvA3eMum2s,6746
|
|
10405
|
-
simo/users/api.py,sha256=
|
|
10406
|
+
simo/users/api.py,sha256=HUY4H9kK_HZKeN4VFERcbNDp6Mmp6p2LdDKBDFvWGUE,10096
|
|
10406
10407
|
simo/users/apps.py,sha256=cq0A8-U1HALEwev0TicgFhr4CAu7Icz8rwq0HfOaL4E,207
|
|
10407
|
-
simo/users/auth_backends.py,sha256=
|
|
10408
|
+
simo/users/auth_backends.py,sha256=bBSNXQJ88TRXaQxyh1aETfmOIfiDr08Jnj8rSY9sHDk,4074
|
|
10408
10409
|
simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
|
|
10409
10410
|
simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
|
|
10411
|
+
simo/users/managers.py,sha256=M_51bk9z4jn8e2Ci3pJfIqbf6cRNqfQNSOAg0vPl6Vo,175
|
|
10410
10412
|
simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
|
|
10411
|
-
simo/users/models.py,sha256=
|
|
10413
|
+
simo/users/models.py,sha256=ud-OOiFuDn8yJK2xrae3Qx-ku9vYBljIHNd3BCHAhM4,19708
|
|
10412
10414
|
simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
|
|
10413
|
-
simo/users/serializers.py,sha256=
|
|
10415
|
+
simo/users/serializers.py,sha256=a4R408ZgWVbF7OFw4bBfN33Wnn8ljqS8iFcsqmllkWU,2552
|
|
10414
10416
|
simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
|
|
10415
10417
|
simo/users/sso_views.py,sha256=-XI67TvQ7SN3goU4OuAHyn84u_1vtusvpn7Pu0K97zo,4648
|
|
10416
10418
|
simo/users/tasks.py,sha256=HJAqiyWGsaN3wSfquU0UyQ20jL-njXeaaTOdDT3TQ3s,979
|
|
@@ -10418,21 +10420,22 @@ simo/users/utils.py,sha256=7gU_TDnAOsDYqJM0CFo8efPah2bTXfGpXxRqzD5RiSs,1270
|
|
|
10418
10420
|
simo/users/views.py,sha256=dOQVvmlHG7ihWKJLFUBcqKOA0UDctlMKR0pTc36JZqg,3487
|
|
10419
10421
|
simo/users/__pycache__/__init__.cpython-38.pyc,sha256=VFoDJE_SKKaPqqYaaBYd1Ndb1hjakkTo_u0EG_XJ1GM,211
|
|
10420
10422
|
simo/users/__pycache__/admin.cpython-38.pyc,sha256=paoWxwJgOyDF7RT7LIviDqggdELG9-fbydc9UfqHV10,7500
|
|
10421
|
-
simo/users/__pycache__/api.cpython-38.pyc,sha256=
|
|
10423
|
+
simo/users/__pycache__/api.cpython-38.pyc,sha256=QqQL0MyG8-_7HkqPvqwINuYoco-pJEQ8zT8Crr7t3Rc,8602
|
|
10422
10424
|
simo/users/__pycache__/apps.cpython-38.pyc,sha256=dgbWL8CxzzISJQTmq_4IztPJ2UzykNVdqA2Ae1PmeGk,605
|
|
10423
|
-
simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=
|
|
10425
|
+
simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=n5nx2QSXNj2idzRcGE6bAagMN-8qxoCs580H1EFZXls,3105
|
|
10424
10426
|
simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=K-3sz2h-cEitoflSmZk1t0eUg5mQMMGLNZFREVwG7_o,430
|
|
10425
10427
|
simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
|
|
10428
|
+
simo/users/__pycache__/managers.cpython-38.pyc,sha256=C5-diljm874RAFMTkZdcfzPhkHzlUGPAhz2gTvqkDy8,604
|
|
10426
10429
|
simo/users/__pycache__/middleware.cpython-38.pyc,sha256=Tj4nVEAvxEW3xA63fBRiJWRJpz_M848ZOqbHioc_IPE,1149
|
|
10427
|
-
simo/users/__pycache__/models.cpython-38.pyc,sha256=
|
|
10430
|
+
simo/users/__pycache__/models.cpython-38.pyc,sha256=RiBi5YNHt38s4uUd8Xliswnv7s--v72mjUrBvpal_is,18179
|
|
10428
10431
|
simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
|
|
10429
|
-
simo/users/__pycache__/serializers.cpython-38.pyc,sha256=
|
|
10432
|
+
simo/users/__pycache__/serializers.cpython-38.pyc,sha256=PuMy6H0PhEhq89RFmdnFH4pMHB0N3w7opJEFS90JUCY,3477
|
|
10430
10433
|
simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=uAwDozpOmrhUald-8tOHANILXkH7-TI8fNYXOtPkSY8,402
|
|
10431
10434
|
simo/users/__pycache__/sso_views.cpython-38.pyc,sha256=sHEoxLOac3U3Epmhm197huFnW_J3gGCDZSji57itijU,3969
|
|
10432
10435
|
simo/users/__pycache__/tasks.cpython-38.pyc,sha256=XLMKt3suT7BlcXrJZoH9ZIhhtBuqyiW4lsOB9IbBkko,1225
|
|
10433
10436
|
simo/users/__pycache__/utils.cpython-38.pyc,sha256=CGaRBk-y9A-8lWWY4bYkI9faAziO0pVYdr5BJNmqbUg,1600
|
|
10434
10437
|
simo/users/__pycache__/views.cpython-38.pyc,sha256=AXuUnVYRD0ai4FSFDp4qJwryukujAoN6LD3oIj-Cv3o,2426
|
|
10435
|
-
simo/users/migrations/0001_initial.py,sha256=
|
|
10438
|
+
simo/users/migrations/0001_initial.py,sha256=_SnJemhNOs8Jjj-PjyvTVCBoxfs5V3lR_4ypUHUdLUg,7017
|
|
10436
10439
|
simo/users/migrations/0002_componentpermission.py,sha256=rH9pC9HERf_5WWn3LCsNiu03BiHqURTF62pSNfswStI,918
|
|
10437
10440
|
simo/users/migrations/0003_create_roles_and_system_user.py,sha256=24kNpyPF_DzCRJbx5wi9pvR78YNNNKRJg6TGI8kQiUY,1141
|
|
10438
10441
|
simo/users/migrations/0004_user_secret_key.py,sha256=ptNOxBVOkkqoowvu_Y9z8uScDzIoq9yokBxIAkG6P5w,491
|
|
@@ -10462,7 +10465,7 @@ simo/users/migrations/0027_permissionsrole_can_manage_components.py,sha256=VcGZE
|
|
|
10462
10465
|
simo/users/migrations/0028_auto_20240506_1146.py,sha256=7RUFF2rJH-bnPeHwc77p8Q4kEAc3owyG4qp9Kc4aKhU,716
|
|
10463
10466
|
simo/users/migrations/0029_alter_instanceuser_instance.py,sha256=5ebO0vX9lCnTXBMkWg8633sBCBLNtMLfbocVY-uyQhE,588
|
|
10464
10467
|
simo/users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10465
|
-
simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=
|
|
10468
|
+
simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=e4XOKaYRb7l0P7cBnHHi5FQQJMlwjK0g7iqgM-xKmNI,4215
|
|
10466
10469
|
simo/users/migrations/__pycache__/0002_componentpermission.cpython-38.pyc,sha256=pknJnpic8p6Vdx9DX41FfODXNnvexDswJtUCmC5w1tg,995
|
|
10467
10470
|
simo/users/migrations/__pycache__/0003_create_roles_and_system_user.cpython-38.pyc,sha256=jcxB_WItrY8APyG_ZiCs3sBvaIVQonm8GSakK82Dc7s,750
|
|
10468
10471
|
simo/users/migrations/__pycache__/0004_user_secret_key.cpython-38.pyc,sha256=fPLGDwNli7BAThDaXhNWOjJzAzF1wB45hQugim1dcWc,733
|
|
@@ -10502,9 +10505,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10502
10505
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10503
10506
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10504
10507
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10505
|
-
simo-2.
|
|
10506
|
-
simo-2.
|
|
10507
|
-
simo-2.
|
|
10508
|
-
simo-2.
|
|
10509
|
-
simo-2.
|
|
10510
|
-
simo-2.
|
|
10508
|
+
simo-2.2.2.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10509
|
+
simo-2.2.2.dist-info/METADATA,sha256=Ru0FCahOkylESH_ERFdMhvY_J5YwYXMmIBsjAZvsdKY,1847
|
|
10510
|
+
simo-2.2.2.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
10511
|
+
simo-2.2.2.dist-info/entry_points.txt,sha256=SJBxiDpH7noO0STxVI_eRIsGR-nLgdXXeqCDe8cXlbM,65
|
|
10512
|
+
simo-2.2.2.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10513
|
+
simo-2.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|