simo 2.0.42__py3-none-any.whl → 2.1.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/__pycache__/asgi.cpython-38.pyc +0 -0
- simo/__pycache__/settings.cpython-38.pyc +0 -0
- simo/__pycache__/wsgi.cpython-38.pyc +0 -0
- simo/asgi.py +1 -1
- simo/core/__init__.py +1 -0
- simo/core/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/core/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/__pycache__/api.cpython-38.pyc +0 -0
- simo/core/__pycache__/api_meta.cpython-38.pyc +0 -0
- simo/core/__pycache__/app_widgets.cpython-38.pyc +0 -0
- simo/core/__pycache__/apps.cpython-38.pyc +0 -0
- simo/core/__pycache__/auto_urls.cpython-38.pyc +0 -0
- simo/core/__pycache__/base_types.cpython-38.pyc +0 -0
- simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/core/__pycache__/dynamic_settings.cpython-38.pyc +0 -0
- simo/core/__pycache__/form_fields.cpython-38.pyc +0 -0
- simo/core/__pycache__/forms.cpython-38.pyc +0 -0
- simo/core/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/core/__pycache__/managers.cpython-38.pyc +0 -0
- simo/core/__pycache__/models.cpython-38.pyc +0 -0
- simo/core/__pycache__/permissions.cpython-38.pyc +0 -0
- simo/core/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/core/__pycache__/signal_receivers.cpython-38.pyc +0 -0
- simo/core/__pycache__/tasks.cpython-38.pyc +0 -0
- simo/core/__pycache__/views.cpython-38.pyc +0 -0
- simo/core/admin.py +26 -26
- simo/core/api.py +22 -2
- simo/core/api_meta.py +23 -13
- simo/core/app_widgets.py +6 -0
- simo/core/apps.py +13 -0
- simo/core/auto_urls.py +2 -3
- simo/core/base_types.py +1 -0
- simo/core/controllers.py +57 -0
- simo/core/dynamic_settings.py +0 -8
- simo/core/form_fields.py +93 -0
- simo/core/forms.py +16 -101
- simo/core/gateways.py +1 -1
- simo/core/managers.py +14 -1
- simo/core/migrations/0037_auto_20240606_1057.py +33 -0
- simo/core/migrations/0038_remove_instance_cover_image_and_more.py +30 -0
- simo/core/migrations/__pycache__/0037_auto_20240606_1057.cpython-38.pyc +0 -0
- simo/core/migrations/__pycache__/0038_remove_instance_cover_image_and_more.cpython-38.pyc +0 -0
- simo/core/models.py +30 -16
- simo/core/permissions.py +6 -3
- simo/core/serializers.py +77 -5
- simo/core/signal_receivers.py +25 -0
- simo/core/static/admin/css/simo.css +14 -0
- simo/core/tasks.py +82 -49
- simo/core/templates/admin/controller_widgets/button.html +8 -0
- simo/core/templates/admin/core/component_change_form.html +97 -0
- simo/core/templates/admin/formset_widget.html +88 -118
- simo/core/templates/admin/formset_widget_old.html +122 -0
- simo/core/templates/admin/user_tools.html +0 -3
- simo/core/templates/admin/wizard/wizard_add.html +16 -9
- simo/core/utils/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/utils/__pycache__/cache.cpython-38.pyc +0 -0
- simo/core/utils/__pycache__/formsets.cpython-38.pyc +0 -0
- simo/core/utils/admin.py +11 -0
- simo/core/utils/cache.py +15 -0
- simo/core/utils/formsets.py +11 -18
- simo/core/views.py +2 -85
- simo/fleet/__pycache__/auto_urls.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/models.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/socket_consumers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/utils.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/views.cpython-38.pyc +0 -0
- simo/fleet/auto_urls.py +7 -1
- simo/fleet/controllers.py +194 -31
- simo/fleet/forms.py +223 -87
- simo/fleet/gateways.py +53 -2
- simo/fleet/migrations/0036_auto_20240605_0702.py +68 -0
- simo/fleet/migrations/0037_alter_colonelpin_options_alter_colonelpin_no_and_more.py +27 -0
- simo/fleet/migrations/__pycache__/0036_auto_20240605_0702.cpython-38.pyc +0 -0
- simo/fleet/migrations/__pycache__/0037_alter_colonelpin_options_alter_colonelpin_no_and_more.cpython-38.pyc +0 -0
- simo/fleet/models.py +35 -6
- simo/fleet/socket_consumers.py +1 -1
- simo/fleet/templates/fleet/controllers_info/button.md +16 -0
- simo/fleet/utils.py +31 -1
- simo/fleet/views.py +45 -0
- simo/generic/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/generic/__pycache__/forms.cpython-38.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/generic/controllers.py +61 -16
- simo/generic/forms.py +0 -3
- simo/generic/gateways.py +2 -0
- simo/generic/templates/admin/controller_widgets/blinds.html +2 -1
- simo/generic/templates/admin/controller_widgets/weather_forecast.html +1 -1
- simo/generic/templates/generic/controllers_info/dummy.md +3 -0
- simo/generic/templates/generic/controllers_info/stateselect.md +2 -0
- simo/management/__init__.py +0 -0
- simo/management/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/management/__pycache__/on_http_start.cpython-38.pyc +0 -0
- simo/{_hub_template → management/_hub_template}/hub/nginx.conf +2 -2
- simo/{auto_update.py → management/auto_update.py} +3 -0
- simo/{cli.py → management/copy_template.py} +3 -16
- simo/management/install.py +258 -0
- simo/{on_http_start.py → management/on_http_start.py} +22 -2
- simo/settings.py +20 -4
- simo/users/__init__.py +1 -0
- simo/users/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/users/__pycache__/admin.cpython-38.pyc +0 -0
- simo/users/__pycache__/apps.cpython-38.pyc +0 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- simo/users/apps.py +9 -0
- simo/users/migrations/__pycache__/0029_alter_instanceuser_options_instanceuser_order.cpython-38.pyc +0 -0
- simo/users/migrations/__pycache__/0030_alter_instanceuser_options_remove_instanceuser_order.cpython-38.pyc +0 -0
- simo/users/models.py +16 -3
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/METADATA +5 -3
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/RECORD +122 -95
- simo-2.1.2.dist-info/entry_points.txt +2 -0
- simo/__pycache__/on_http_start.cpython-38.pyc +0 -0
- simo/wsgi.py +0 -7
- /simo/{_hub_template → management/_hub_template}/hub/asgi.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/celeryc.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/manage.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/settings.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/supervisor.conf +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/urls.py +0 -0
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/LICENSE.md +0 -0
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/WHEEL +0 -0
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/top_level.txt +0 -0
|
@@ -26,6 +26,9 @@ def perform_update():
|
|
|
26
26
|
if proc.returncode:
|
|
27
27
|
raise Exception(err.decode())
|
|
28
28
|
|
|
29
|
+
from simo.management.install import install_dependencies
|
|
30
|
+
install_dependencies()
|
|
31
|
+
|
|
29
32
|
proc = subprocess.Popen(
|
|
30
33
|
[os.path.join(HUB_DIR, 'manage.py'), 'migrate'],
|
|
31
34
|
cwd=HUB_DIR,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env python
|
|
2
2
|
import sys
|
|
3
|
-
import click
|
|
4
3
|
import os
|
|
5
4
|
import shutil
|
|
6
5
|
import simo
|
|
@@ -8,7 +7,7 @@ from django.template import Context, Engine
|
|
|
8
7
|
from django.core.management.utils import get_random_secret_key
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
def
|
|
10
|
+
def copy_template(to_directory='/etc/SIMO'):
|
|
12
11
|
template_file_extensions = ['.py', '.conf']
|
|
13
12
|
|
|
14
13
|
context = Context({
|
|
@@ -49,18 +48,6 @@ def copy_default_template(to_directory='/etc/SIMO'):
|
|
|
49
48
|
os.makedirs(os.path.join(root, dirname), exist_ok=True)
|
|
50
49
|
|
|
51
50
|
|
|
52
|
-
@click.command()
|
|
53
|
-
def init():
|
|
54
|
-
copy_default_template()
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@click.group()
|
|
58
|
-
def main(args=None):
|
|
59
|
-
pass
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
main.add_command(init)
|
|
63
|
-
|
|
64
51
|
|
|
65
52
|
if __name__ == "__main__":
|
|
66
|
-
sys.exit(
|
|
53
|
+
sys.exit(copy_template())
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
This should be called after simo has just been installed.
|
|
5
|
+
It prepares and powers up SIMO.io hub.
|
|
6
|
+
However it is not guaranteed to be fully operational.
|
|
7
|
+
"""
|
|
8
|
+
import os, sys, json, subprocess, socket, shutil, traceback
|
|
9
|
+
import simo
|
|
10
|
+
from django.template import Context, Engine
|
|
11
|
+
from django.core.management.utils import get_random_secret_key
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def install_dependencies():
|
|
16
|
+
|
|
17
|
+
status = subprocess.call(
|
|
18
|
+
'apt install postgresql libpq-dev postgresql-client '
|
|
19
|
+
'postgresql-client-common python3-pip redis-server supervisor '
|
|
20
|
+
'mosquitto libopenjp2-7 libtiff5 pkg-config libcairo2-dev '
|
|
21
|
+
'libgirepository1.0-dev libcairo2 libudev-dev gdal-bin net-tools '
|
|
22
|
+
'timeshift nginx postgis openvpn ffmpeg libsm6 libxext6 ssh keychain -y',
|
|
23
|
+
shell=True
|
|
24
|
+
)
|
|
25
|
+
if status != 0:
|
|
26
|
+
print("Unable install required packages.")
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_ip():
|
|
33
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
34
|
+
try:
|
|
35
|
+
# doesn't even have to be reachable
|
|
36
|
+
s.connect(('10.255.255.255', 1))
|
|
37
|
+
IP = s.getsockname()[0]
|
|
38
|
+
except Exception:
|
|
39
|
+
IP = '127.0.0.1'
|
|
40
|
+
finally:
|
|
41
|
+
s.close()
|
|
42
|
+
return IP
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def copy_template(to_directory='/etc/SIMO'):
|
|
46
|
+
template_file_extensions = ['.py', '.conf']
|
|
47
|
+
|
|
48
|
+
context = Context({
|
|
49
|
+
'secret_key': get_random_secret_key(),
|
|
50
|
+
'project_dir': to_directory,
|
|
51
|
+
'base_dir': to_directory
|
|
52
|
+
}, autoescape=False)
|
|
53
|
+
template_dir = os.path.join(
|
|
54
|
+
os.path.dirname(simo.__file__), '_hub_template'
|
|
55
|
+
)
|
|
56
|
+
prefix_length = len(template_dir) + 1
|
|
57
|
+
for root, dirs, files in os.walk(template_dir):
|
|
58
|
+
relative_dir = root[prefix_length:]
|
|
59
|
+
target_dir = os.path.join(to_directory, relative_dir)
|
|
60
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
61
|
+
for filename in files:
|
|
62
|
+
if filename.endswith(('.pyo', '.pyc', '.py.class')):
|
|
63
|
+
# Ignore some files as they cause various breakages.
|
|
64
|
+
continue
|
|
65
|
+
old_path = os.path.join(root, filename)
|
|
66
|
+
new_path = os.path.join(target_dir, filename)
|
|
67
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
68
|
+
fn, file_extension = os.path.splitext(new_path)
|
|
69
|
+
if file_extension in template_file_extensions:
|
|
70
|
+
with open(old_path, encoding='utf-8') as template_file:
|
|
71
|
+
content = template_file.read()
|
|
72
|
+
template = Engine().from_string(content)
|
|
73
|
+
content = template.render(context)
|
|
74
|
+
with open(new_path, 'w', encoding='utf-8') as new_file:
|
|
75
|
+
new_file.write(content)
|
|
76
|
+
else:
|
|
77
|
+
shutil.copyfile(old_path, new_path)
|
|
78
|
+
shutil.copymode(old_path, new_path)
|
|
79
|
+
for dirname in dirs[:]:
|
|
80
|
+
if dirname.startswith('.') or dirname == '__pycache__':
|
|
81
|
+
dirs.remove(dirname)
|
|
82
|
+
else:
|
|
83
|
+
os.makedirs(os.path.join(root, dirname), exist_ok=True)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def install():
|
|
87
|
+
simo_directory = '/etc/SIMO'
|
|
88
|
+
installed_flag_file_path = os.path.join(simo_directory, 'is_installed.json')
|
|
89
|
+
|
|
90
|
+
if os.path.exists(installed_flag_file_path):
|
|
91
|
+
print("SIMO.io hub is already installed. ")
|
|
92
|
+
print(f"Please delete {installed_flag_file_path} file manually if you want to force this.")
|
|
93
|
+
return
|
|
94
|
+
|
|
95
|
+
step = 1
|
|
96
|
+
print(f"{step}.___________Install dependencies__________________")
|
|
97
|
+
status = subprocess.call(
|
|
98
|
+
'apt-add-repository ppa:mosquitto-dev/mosquitto-ppa -y', shell=True
|
|
99
|
+
)
|
|
100
|
+
if status != 0:
|
|
101
|
+
print("Unable to add mosquitto-dev dependency")
|
|
102
|
+
print("Installation failed!")
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
status = subprocess.call('apt-get update -y', shell=True)
|
|
106
|
+
if status != 0:
|
|
107
|
+
print("Unable to apt-update")
|
|
108
|
+
print("Installation failed!")
|
|
109
|
+
return
|
|
110
|
+
success = install_dependencies()
|
|
111
|
+
if not success:
|
|
112
|
+
print("Installation failed!")
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
step += 1
|
|
116
|
+
print(f"{step}.___________Copy default template__________________")
|
|
117
|
+
|
|
118
|
+
if os.path.exists(simo_directory):
|
|
119
|
+
print("Already exists!")
|
|
120
|
+
else:
|
|
121
|
+
try:
|
|
122
|
+
copy_template(simo_directory)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(traceback.format_exc(), file=sys.stderr)
|
|
125
|
+
shutil.rmtree(simo_directory, ignore_errors=True)
|
|
126
|
+
return
|
|
127
|
+
|
|
128
|
+
step += 1
|
|
129
|
+
print(f"{step}.___________Configure supervisor__________________")
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
os.remove('/etc/supervisor/conf.d/SIMO.conf', ignore_errors=True)
|
|
133
|
+
except:
|
|
134
|
+
pass
|
|
135
|
+
os.symlink(
|
|
136
|
+
f'{simo_directory}/hub/supervisor.conf',
|
|
137
|
+
'/etc/supervisor/conf.d/SIMO.conf'
|
|
138
|
+
)
|
|
139
|
+
status = subprocess.call(['supervisorctl', 'update', 'all'])
|
|
140
|
+
if status != 0:
|
|
141
|
+
sys.exit("INSTALLATION FAILED! Unable to start supervisord")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
step += 1
|
|
146
|
+
print("%d._____________ Configure NGINX _________________________" % step)
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
os.remove('/etc/nginx/sites-enabled/default')
|
|
150
|
+
except:
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
os.symlink(
|
|
154
|
+
'/etc/SIMO/hub/nginx.conf', '/etc/nginx/sites-enabled/SIMO'
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
os.remove('/etc/ssl/private/localhost.key')
|
|
159
|
+
except:
|
|
160
|
+
pass
|
|
161
|
+
try:
|
|
162
|
+
os.remove('/etc/ssl/certs/localhost.crt')
|
|
163
|
+
except:
|
|
164
|
+
pass
|
|
165
|
+
|
|
166
|
+
status = subprocess.call([
|
|
167
|
+
'openssl', 'req', '-x509', '-nodes', '-days', '36500',
|
|
168
|
+
'-newkey', 'rsa:2048',
|
|
169
|
+
'-subj', '/C=US/ST=Denial/L=Springfield/O=Dis/CN=simo.io',
|
|
170
|
+
'-keyout', '/etc/ssl/private/localhost.key',
|
|
171
|
+
'-out', '/etc/ssl/certs/localhost.crt'
|
|
172
|
+
])
|
|
173
|
+
if status != 0:
|
|
174
|
+
sys.exit(
|
|
175
|
+
"INSTALLATION FAILED! Unable to prepare self signed certificate.")
|
|
176
|
+
|
|
177
|
+
status = subprocess.call(['service', 'nginx', 'reload'])
|
|
178
|
+
if status != 0:
|
|
179
|
+
sys.exit("INSTALLATION FAILED! Something is wrong witn NGINX conf.")
|
|
180
|
+
|
|
181
|
+
step += 1
|
|
182
|
+
print("%d._____________ Configure SSH and Firewall_____________" % step)
|
|
183
|
+
new_ssh_conf = ''
|
|
184
|
+
with open('/etc/ssh/sshd_config', 'r') as ssh_conf:
|
|
185
|
+
line = ssh_conf.readline()
|
|
186
|
+
while line:
|
|
187
|
+
if 'PasswordAuthentication' in line:
|
|
188
|
+
new_ssh_conf += 'PasswordAuthentication no'
|
|
189
|
+
else:
|
|
190
|
+
new_ssh_conf += line
|
|
191
|
+
line = ssh_conf.readline()
|
|
192
|
+
with open('/etc/ssh/sshd_config', 'w') as ssh_conf:
|
|
193
|
+
ssh_conf.write(new_ssh_conf)
|
|
194
|
+
|
|
195
|
+
status = subprocess.call(['service', 'ssh', 'restart'])
|
|
196
|
+
if status != 0:
|
|
197
|
+
sys.exit("INSTALLATION FAILED! Unable to restart SSH")
|
|
198
|
+
|
|
199
|
+
stats = []
|
|
200
|
+
stats.append(subprocess.call(['ufw', 'allow', 'ssh']))
|
|
201
|
+
stats.append(subprocess.call(['ufw', 'allow', 'http']))
|
|
202
|
+
stats.append(subprocess.call(['ufw', 'allow', 'https']))
|
|
203
|
+
stats.append(subprocess.call(['ufw', 'allow', '1194']))
|
|
204
|
+
stats.append(subprocess.call(['ufw', 'allow', '1883']))
|
|
205
|
+
if any(stats):
|
|
206
|
+
sys.exit("INSTALLATION FAILED! Unable to update UFW rules")
|
|
207
|
+
|
|
208
|
+
status = subprocess.call('echo y | ufw enable', shell=True)
|
|
209
|
+
if status != 0:
|
|
210
|
+
sys.exit("INSTALLATION FAILED! Unable to enable UFW")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
step += 1
|
|
214
|
+
print("%d.__________ CONFIGURE TIMESHIFT _____________________" % step)
|
|
215
|
+
|
|
216
|
+
default_timeshift_file_path = '/etc/timeshift/default.json'
|
|
217
|
+
if not os.path.exists(default_timeshift_file_path):
|
|
218
|
+
default_timeshift_file_path = '/etc/timeshift/timeshift.json'
|
|
219
|
+
if not os.path.exists(default_timeshift_file_path):
|
|
220
|
+
default_timeshift_file_path = '/etc/default/timeshift.json'
|
|
221
|
+
|
|
222
|
+
if not os.path.exists(default_timeshift_file_path):
|
|
223
|
+
print("Unable to find default TimeShift config! Skip TimeShift configuration.")
|
|
224
|
+
|
|
225
|
+
else:
|
|
226
|
+
|
|
227
|
+
with open(default_timeshift_file_path, 'r') as conf_f:
|
|
228
|
+
timeshift_conf = json.loads(conf_f.read())
|
|
229
|
+
|
|
230
|
+
timeshift_conf['backup_device_uuid'] = subprocess.check_output(
|
|
231
|
+
"lsblk -no UUID $(df -P /etc/SIMO/hub/settings.py | awk 'END{print $1}')",
|
|
232
|
+
shell=True
|
|
233
|
+
).decode()[:-1]
|
|
234
|
+
timeshift_conf['schedule_monthly'] = "true"
|
|
235
|
+
timeshift_conf['schedule_weekly'] = "true"
|
|
236
|
+
timeshift_conf['schedule_daily'] = "true"
|
|
237
|
+
|
|
238
|
+
# Must be copied to /etc/timeshift.json to work
|
|
239
|
+
with open('/etc/timeshift.json', 'w') as conf_f:
|
|
240
|
+
conf_f.write(json.dumps(timeshift_conf))
|
|
241
|
+
|
|
242
|
+
status = subprocess.call([
|
|
243
|
+
'/usr/bin/timeshift', '--create',
|
|
244
|
+
'--comments', '"Initial backup"', '--tags', 'M'
|
|
245
|
+
])
|
|
246
|
+
if status != 0:
|
|
247
|
+
print("Unable to start TimeShift")
|
|
248
|
+
|
|
249
|
+
with open(installed_flag_file_path, 'w') as f:
|
|
250
|
+
f.write(json.dumps(True))
|
|
251
|
+
|
|
252
|
+
print("--------------------------------------------------------------")
|
|
253
|
+
print("DONE!")
|
|
254
|
+
print("Your SIMO.io Hub is Up and running at: https://%s/" % get_ip())
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
if __name__ == "__main__":
|
|
258
|
+
sys.exit(init())
|
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
import pwd
|
|
3
3
|
import grp
|
|
4
4
|
import subprocess
|
|
5
|
+
import pkg_resources
|
|
5
6
|
from django.conf import settings
|
|
6
7
|
from django.template.loader import render_to_string
|
|
7
8
|
|
|
@@ -58,7 +59,8 @@ prepare_mosquitto()
|
|
|
58
59
|
def update_auto_update():
|
|
59
60
|
import simo
|
|
60
61
|
auto_update_file_path = os.path.join(
|
|
61
|
-
os.path.dirname(simo.__file__), '
|
|
62
|
+
os.path.dirname(simo.__file__), 'management',
|
|
63
|
+
'auto_update.py'
|
|
62
64
|
)
|
|
63
65
|
st = os.stat(auto_update_file_path)
|
|
64
66
|
os.chmod(auto_update_file_path, st.st_mode | 0o111)
|
|
@@ -75,4 +77,22 @@ def update_auto_update():
|
|
|
75
77
|
cron_out.communicate(input=str.encode(auto_update_cron))
|
|
76
78
|
|
|
77
79
|
|
|
78
|
-
update_auto_update()
|
|
80
|
+
update_auto_update()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def maybe_update_to_latest_immediately():
|
|
84
|
+
from simo.core.tasks import update_latest_version_available, update
|
|
85
|
+
from simo.core.models import Instance
|
|
86
|
+
from simo.conf import dynamic_settings
|
|
87
|
+
update_latest_version_available()
|
|
88
|
+
if dynamic_settings['core__latest_version_available'] != \
|
|
89
|
+
pkg_resources.get_distribution('simo').version:
|
|
90
|
+
print("There is newer version, we should probably update!")
|
|
91
|
+
if not Instance.objects.all().count():
|
|
92
|
+
print("Yes let's do it asynchronously!")
|
|
93
|
+
return update.s()
|
|
94
|
+
print("Nope, we already have some instances running, "
|
|
95
|
+
"so we leave that for hub owners.")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
maybe_update_to_latest_immediately()
|
simo/settings.py
CHANGED
|
@@ -40,12 +40,14 @@ MEDIA_ROOT = os.path.join(VAR_DIR, 'media')
|
|
|
40
40
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
|
41
41
|
|
|
42
42
|
INSTALLED_APPS = [
|
|
43
|
-
'
|
|
43
|
+
'daphne',
|
|
44
|
+
#'channels',
|
|
44
45
|
'dal',
|
|
45
46
|
'dal_select2',
|
|
46
47
|
'django.forms',
|
|
47
48
|
|
|
48
49
|
'django.contrib.auth',
|
|
50
|
+
'django.contrib.sites',
|
|
49
51
|
'django.contrib.contenttypes',
|
|
50
52
|
'django.contrib.sessions',
|
|
51
53
|
'django.contrib.gis',
|
|
@@ -58,9 +60,11 @@ INSTALLED_APPS = [
|
|
|
58
60
|
'dynamic_preferences',
|
|
59
61
|
'easy_thumbnails',
|
|
60
62
|
'django_filters',
|
|
61
|
-
'
|
|
63
|
+
'markdownify.apps.MarkdownifyConfig',
|
|
64
|
+
|
|
62
65
|
'bootstrap4',
|
|
63
66
|
'taggit',
|
|
67
|
+
'actstream',
|
|
64
68
|
|
|
65
69
|
'simo.core',
|
|
66
70
|
'simo.users',
|
|
@@ -70,6 +74,7 @@ INSTALLED_APPS = [
|
|
|
70
74
|
'simo.fleet',
|
|
71
75
|
|
|
72
76
|
'django.contrib.admin',
|
|
77
|
+
'adminsortable2',
|
|
73
78
|
]
|
|
74
79
|
|
|
75
80
|
|
|
@@ -90,7 +95,7 @@ MIDDLEWARE = [
|
|
|
90
95
|
FILE_UPLOAD_MAX_MEMORY_SIZE = 20971520 # 20Mb
|
|
91
96
|
|
|
92
97
|
ROOT_URLCONF = 'urls'
|
|
93
|
-
WSGI_APPLICATION = 'simo.wsgi.application'
|
|
98
|
+
#WSGI_APPLICATION = 'simo.wsgi.application'
|
|
94
99
|
|
|
95
100
|
CHANNELS_URLCONF = 'simo.asgi'
|
|
96
101
|
ASGI_APPLICATION = "asgi.application"
|
|
@@ -223,6 +228,8 @@ DEFAULT_FILE_STORAGE = 'simo.core.storage.ProxyingFileSystemStorage'
|
|
|
223
228
|
THUMBNAIL_DEFAULT_STORAGE = DEFAULT_FILE_STORAGE
|
|
224
229
|
|
|
225
230
|
|
|
231
|
+
SITE_ID = 1
|
|
232
|
+
|
|
226
233
|
LOGGING = {
|
|
227
234
|
'version': 1,
|
|
228
235
|
'disable_existing_loggers': False,
|
|
@@ -273,5 +280,14 @@ LOCATION_FIELD = {
|
|
|
273
280
|
'search.provider': 'nominatim',
|
|
274
281
|
}
|
|
275
282
|
|
|
276
|
-
|
|
277
283
|
TAGGIT_CASE_INSENSITIVE = True
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
ACTSTREAM_SETTINGS = {
|
|
288
|
+
'MANAGER': 'simo.core.managers.ActionManager',
|
|
289
|
+
'FETCH_RELATIONS': True,
|
|
290
|
+
'USE_PREFETCH': True,
|
|
291
|
+
'USE_JSONFIELD': True,
|
|
292
|
+
'GFK_FETCH_DEPTH': 1,
|
|
293
|
+
}
|
simo/users/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
default_app_config = 'users.apps.SIMOUsersAppConfig'
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/users/apps.py
ADDED
simo/users/migrations/__pycache__/0029_alter_instanceuser_options_instanceuser_order.cpython-38.pyc
ADDED
|
Binary file
|
|
Binary file
|
simo/users/models.py
CHANGED
|
@@ -11,6 +11,7 @@ from django.dispatch import receiver
|
|
|
11
11
|
from dirtyfields import DirtyFieldsMixin
|
|
12
12
|
from django.contrib.gis.geos import Point
|
|
13
13
|
from geopy.distance import distance
|
|
14
|
+
from actstream import action
|
|
14
15
|
from django.contrib.auth.models import (
|
|
15
16
|
AbstractBaseUser, PermissionsMixin, UserManager as DefaultUserManager
|
|
16
17
|
)
|
|
@@ -68,6 +69,10 @@ class PermissionsRole(models.Model):
|
|
|
68
69
|
|
|
69
70
|
class UserManager(DefaultUserManager):
|
|
70
71
|
|
|
72
|
+
def get_queryset(self):
|
|
73
|
+
qs = super().get_queryset()
|
|
74
|
+
return qs.prefetch_related('instance_roles')
|
|
75
|
+
|
|
71
76
|
def _create_user(self, name, email, password, **extra_fields):
|
|
72
77
|
if not name:
|
|
73
78
|
raise ValueError('The given name must be set')
|
|
@@ -115,6 +120,15 @@ def post_instance_user_save(sender, instance, created, **kwargs):
|
|
|
115
120
|
dirty_fields = instance.get_dirty_fields()
|
|
116
121
|
if 'at_home' in dirty_fields:
|
|
117
122
|
def post_update():
|
|
123
|
+
if instance.at_home:
|
|
124
|
+
verb = 'came home'
|
|
125
|
+
else:
|
|
126
|
+
verb = 'left'
|
|
127
|
+
action.send(
|
|
128
|
+
instance.user, verb=verb,
|
|
129
|
+
instance_id=instance.instance.id,
|
|
130
|
+
action_type='user_presence', value=instance.at_home
|
|
131
|
+
)
|
|
118
132
|
ObjectChangeEvent(
|
|
119
133
|
instance.instance, instance, dirty_fields=dirty_fields
|
|
120
134
|
).publish()
|
|
@@ -291,9 +305,8 @@ class User(AbstractBaseUser, SimoAdminMixin):
|
|
|
291
305
|
instance=self._instance, is_active=True
|
|
292
306
|
).first()
|
|
293
307
|
)
|
|
294
|
-
return
|
|
295
|
-
|
|
296
|
-
)
|
|
308
|
+
return any([ir.is_active for ir in self.instance_roles.all()])
|
|
309
|
+
|
|
297
310
|
|
|
298
311
|
@is_active.setter
|
|
299
312
|
def is_active(self, val):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: simo
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.2
|
|
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
|
|
@@ -17,7 +17,7 @@ Requires-Dist: djangorestframework ==3.14.0
|
|
|
17
17
|
Requires-Dist: django-dynamic-preferences ==1.11.0
|
|
18
18
|
Requires-Dist: django-formtools ==2.3
|
|
19
19
|
Requires-Dist: easy-thumbnails ==2.8.5
|
|
20
|
-
Requires-Dist: channels ==4.
|
|
20
|
+
Requires-Dist: channels ==4.1.0
|
|
21
21
|
Requires-Dist: asgiref ==3.7.2
|
|
22
22
|
Requires-Dist: django-filter ==2.4.0
|
|
23
23
|
Requires-Dist: celery ==5.3.6
|
|
@@ -43,6 +43,8 @@ Requires-Dist: ansi2html ==1.7.0
|
|
|
43
43
|
Requires-Dist: slugify ==0.0.1
|
|
44
44
|
Requires-Dist: django-countries ==7.5.1
|
|
45
45
|
Requires-Dist: librosa ==0.10.1
|
|
46
|
-
Requires-Dist: daphne ==4.1.
|
|
46
|
+
Requires-Dist: daphne ==4.1.2
|
|
47
47
|
Requires-Dist: Pillow ==9.5.0
|
|
48
|
+
Requires-Dist: django-markdownify ==0.9.5
|
|
49
|
+
Requires-Dist: django-activity-stream ==2.0.0
|
|
48
50
|
|