Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Vladislav Rykov
THSO.server
Commits
05dcf3a5
Commit
05dcf3a5
authored
Jun 07, 2020
by
Vladislav Rykov
Browse files
privilege system in progress
parent
9f3cc723
Changes
10
Hide whitespace changes
Inline
Side-by-side
app/app/__pycache__/views.cpython-37.pyc
View file @
05dcf3a5
No preview for this file type
app/app/__pycache__/views_admin.cpython-37.pyc
View file @
05dcf3a5
No preview for this file type
app/app/dao/misc/__pycache__/misc.cpython-37.pyc
View file @
05dcf3a5
No preview for this file type
app/app/dao/misc/misc.py
View file @
05dcf3a5
...
...
@@ -9,7 +9,6 @@ import app.dao.device.device as dd
def
get_user_data_count
(
cur
,
username
):
apps
=
ad
.
get_list
(
username
)[
1
]
devs
=
[]
for
a
in
apps
:
devs
.
append
(
dd
.
get_list
(
a
[
1
])[
1
])
...
...
@@ -22,7 +21,7 @@ def get_user_data_count(cur, username):
i
+=
1
query
=
query
[
0
:
-
9
]
query
+=
') SELECT SUM(count) FROM t'
print
(
query
)
cur
.
execute
(
query
,
())
return
(
True
,
cur
.
fetchone
())
...
...
app/app/helpers/__pycache__/misc.cpython-37.pyc
View file @
05dcf3a5
No preview for this file type
app/app/helpers/device_data_model.py
View file @
05dcf3a5
...
...
@@ -142,6 +142,7 @@ def read_data(data, ddm):
for
k
,
v
in
ddm
[
'format'
].
items
():
if
v
[
-
1
]
==
's'
:
data
[
k
]
=
data
[
k
].
decode
(
'utf-8'
)
data
[
k
]
=
data
[
k
][:
data
[
k
].
index
(
'
\0
'
)]
return
data
elif
ddm
[
'model'
]
==
'json'
:
return
json
.
loads
(
data
.
decode
(
'utf-8'
))
...
...
app/app/helpers/misc.py
View file @
05dcf3a5
...
...
@@ -87,13 +87,24 @@ def restricted(access_level):
@
wraps
(
f
)
def
decorated_function
(
*
args
,
**
kwargs
):
if
'role'
in
session
and
session
[
'role'
]
!=
access_level
:
flash
(
'Access
level "{}" required for this page.'
.
format
(
access_level
)
,
'danger'
)
flash
(
'Access
denied.'
,
'danger'
)
return
redirect
(
url_for
(
'index'
))
return
f
(
*
args
,
**
kwargs
)
return
decorated_function
return
user_control
def
required_privilege
(
privilege
):
def
privilege_control
(
f
):
@
wraps
(
f
)
def
decorated_function
(
*
args
,
**
kwargs
):
if
'privilege'
in
session
and
session
[
'privilege'
]
<
privilege
:
flash
(
'Access denied.'
,
'danger'
)
return
redirect
(
url_for
(
'index'
))
return
f
(
*
args
,
**
kwargs
)
return
decorated_function
return
privilege_control
def
clean_data_folder
():
try
:
filelist
=
[
f
for
f
in
os
.
listdir
(
app
.
config
[
'DATA_DOWNLOAD_DIR_OS'
])]
...
...
app/app/templates/new/admin/users.html
View file @
05dcf3a5
...
...
@@ -82,12 +82,14 @@
<thead>
<th>
Name
</th>
<th>
Role
</th>
<th>
Privilege Level
</th>
</thead>
<tbody
id=
"users_body"
>
{% for u in users %}
<tr
onclick=
"window.location='/administration/users/{{ u[0] }}';"
>
<th>
{{ u[0] }}
</th>
<th>
{{ u[2] }}
</th>
<th>
{{ u[3] }}
</th>
</tr>
{% endfor %}
</tbody>
...
...
app/app/views.py
View file @
05dcf3a5
...
...
@@ -27,6 +27,7 @@ MAX_PG_ENTRIES_USERS = 10
MAX_PG_ENTRIES_DATA
=
10
MAX_PG_ENTRIES_GRAPH_HOURS
=
24
@
app
.
route
(
'/'
)
def
index
():
if
'name'
in
session
and
len
(
session
[
'name'
])
>
0
:
...
...
@@ -40,6 +41,7 @@ def index():
else
:
return
redirect
(
url_for
(
'login'
))
@
app
.
route
(
'/register'
,
methods
=
[
'GET'
,
'POST'
])
def
register
():
if
app
.
config
[
'USERS_SIGNUP'
]:
...
...
@@ -68,7 +70,6 @@ def register():
return
redirect
(
url_for
(
'login'
))
@
app
.
route
(
'/login'
,
methods
=
[
'GET'
,
'POST'
])
def
login
():
if
request
.
method
==
'GET'
:
...
...
@@ -88,6 +89,7 @@ def login():
else
:
session
[
'name'
]
=
username
session
[
'role'
]
=
res
[
1
][
2
]
session
[
'privilege'
]
=
res
[
1
][
3
]
return
redirect
(
url_for
(
'index'
))
...
...
@@ -120,6 +122,7 @@ def application(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/new-application'
,
methods
=
[
'GET'
,
'POST'
])
def
application_create
():
if
'name'
in
session
:
...
...
@@ -155,6 +158,7 @@ def application_create():
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/delete'
)
def
application_delete
(
appkey
):
if
'name'
in
session
:
...
...
@@ -184,6 +188,7 @@ def application_delete(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>'
)
def
application_device
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
@@ -206,6 +211,8 @@ def application_device(appkey, devid):
else
:
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/add-device'
,
methods
=
[
'GET'
,
'POST'
])
def
application_add_device
(
appkey
):
if
'name'
in
session
:
...
...
@@ -232,6 +239,7 @@ def application_add_device(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/delete'
)
def
application_device_delete
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
@@ -251,6 +259,7 @@ def application_device_delete(appkey, devid):
return
redirect
(
utl_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/configure'
,
methods
=
[
'GET'
,
'POST'
])
def
application_device_configuration
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
@@ -279,6 +288,7 @@ def application_device_configuration(appkey, devid):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/download-csv'
)
def
application_device_download_csv
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
@@ -332,7 +342,6 @@ def recent_activity():
ra
=
''
for
r
in
recent_activity
:
print
(
r
)
dev
=
dd
.
get
(
r
[
5
],
r
[
6
])[
1
]
ra
+=
'<tr><th scope="row">'
+
r
[
1
]
+
'</th><th>'
+
r
[
2
]
+
'</th><th>'
+
r
[
0
]
+
'</th><th>'
+
str
(
ddm
.
read_data
(
r
[
3
],
dev
[
3
]))
+
'</th></tr>'
...
...
@@ -341,6 +350,7 @@ def recent_activity():
return
''
,
401
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/remove-configuration'
)
def
application_device_configuration_remove
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
@@ -356,6 +366,7 @@ def application_device_configuration_remove(appkey, devid):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/variables'
)
def
application_device_variables
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
@@ -371,6 +382,7 @@ def application_device_variables(appkey, devid):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/delete-account'
)
def
delete_account
():
user
=
ud
.
get
(
request
.
args
.
get
(
'name'
))
...
...
@@ -409,6 +421,7 @@ def delete_account():
return
redirect
(
url_for
(
'settings'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/settings'
,
methods
=
[
'GET'
,
'POST'
])
def
settings
():
if
request
.
method
==
'GET'
:
...
...
@@ -431,6 +444,7 @@ def settings():
return
redirect
(
request
.
url
)
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>'
)
def
application_device_data
(
appkey
,
devid
,
var
,
dest
,
page
):
dev
=
dd
.
get
(
appkey
,
devid
)[
1
]
...
...
@@ -455,6 +469,7 @@ def application_device_data(appkey, devid, var, dest, page):
return
t
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/alerts'
)
def
application_alerts
(
appkey
):
if
'name'
in
session
:
...
...
@@ -465,6 +480,7 @@ def application_alerts(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/new-alert'
,
methods
=
[
'GET'
,
'POST'
])
def
application_new_alert
(
appkey
):
if
'name'
in
session
:
...
...
@@ -497,6 +513,7 @@ def application_new_alert(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/delete-<ntype>'
)
def
application_notification_remove
(
appkey
,
ntype
):
if
'name'
in
session
:
...
...
@@ -515,6 +532,7 @@ def application_notification_remove(appkey, ntype):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/automation'
)
def
application_automation
(
appkey
):
if
'name'
in
session
:
...
...
@@ -526,6 +544,7 @@ def application_automation(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/new-automation'
,
methods
=
[
'GET'
,
'POST'
])
def
application_new_automation
(
appkey
):
if
'name'
in
session
:
...
...
@@ -561,6 +580,7 @@ def application_new_automation(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/settings'
,
methods
=
[
'GET'
,
'POST'
])
def
application_settings
(
appkey
):
if
'name'
in
session
:
...
...
@@ -585,6 +605,7 @@ def application_settings(appkey):
return
redirect
(
url_for
(
'login'
))
@
misc
.
required_privilege
(
20
)
@
app
.
route
(
'/application/<appkey>/device/<devid>/settings'
,
methods
=
[
'GET'
,
'POST'
])
def
application_device_settings
(
appkey
,
devid
):
if
'name'
in
session
:
...
...
app/app/views_admin.py
View file @
05dcf3a5
...
...
@@ -13,7 +13,7 @@ import app.dao.notification_queue.notification_queue as nq
import
app.dao.misc.misc
as
md
#import app.helpers.misc as misc
from
app.helpers.misc
import
restricted
from
app.helpers.misc
import
restricted
,
required_privilege
import
app.helpers.device_data_model
as
ddm
import
app.helpers.misc
as
misc
...
...
@@ -26,6 +26,8 @@ MAX_PG_ENTRIES_USERS = 10
MAX_PG_ENTRIES_DATA
=
10
MAX_PG_ENTRIES_GRAPH_HOURS
=
24
@
required_privilege
(
40
)
@
app
.
route
(
'/administration'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration
():
...
...
@@ -45,6 +47,7 @@ def administration():
return
redirect
(
request
.
url
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users
():
...
...
@@ -59,6 +62,7 @@ def administration_users():
return
render_template
(
'new/admin/users.html'
,
users
=
users
,
info
=
info
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user
(
name
):
...
...
@@ -71,6 +75,7 @@ def administration_users_user(name):
return
render_template
(
'new/admin/user-dashboard.html'
,
info
=
info
,
user
=
name
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/applications'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_applications
(
name
):
...
...
@@ -78,6 +83,7 @@ def administration_users_user_applications(name):
return
render_template
(
'new/admin/user-applications.html'
,
apps
=
apps
,
user
=
name
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/new-application'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_create
(
name
):
...
...
@@ -111,6 +117,7 @@ def administration_users_user_application_create(name):
return
redirect
(
url_for
(
'administration_users_user_applications'
,
name
=
name
))
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application
(
name
,
appkey
):
...
...
@@ -121,6 +128,7 @@ def administration_users_user_application(name, appkey):
return
render_template
(
'new/admin/user-application.html'
,
app
=
ap
,
devs
=
devs
,
user
=
name
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/add-device'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_add_device
(
name
,
appkey
):
...
...
@@ -146,6 +154,7 @@ def administration_users_user_application_add_device(name, appkey):
return
redirect
(
url_for
(
'administration_users_user_application'
,
name
=
name
,
appkey
=
appkey
))
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device
(
name
,
appkey
,
devid
):
...
...
@@ -166,6 +175,7 @@ def administration_users_user_application_device(name, appkey, devid):
return
render_template
(
'new/admin/user-device.html'
,
dev
=
dev
[
1
],
app
=
ap
[
1
],
ltup
=
ltup
,
data
=
[],
total
=
cnt
[
1
][
0
],
user
=
name
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/settings'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_settings
(
name
,
appkey
,
devid
):
...
...
@@ -185,6 +195,7 @@ def administration_users_user_application_device_settings(name, appkey, devid):
return
redirect
(
request
.
url
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/delete'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_delete
(
name
,
appkey
,
devid
):
...
...
@@ -201,6 +212,7 @@ def administration_users_user_application_device_delete(name, appkey, devid):
return
redirect
(
url_for
(
'administration_users_user_application'
,
name
=
name
,
appkey
=
appkey
))
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/alerts'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_alerts
(
name
,
appkey
):
...
...
@@ -209,6 +221,7 @@ def administration_users_user_application_alerts(name, appkey):
return
render_template
(
'new/admin/user-application-alerts.html'
,
alert_list
=
alerts
[
1
],
app
=
ap
[
1
],
user
=
name
)
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/new-alert'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_new_alert
(
name
,
appkey
):
...
...
@@ -239,6 +252,7 @@ def administration_users_user_application_new_alert(name, appkey):
return
redirect
(
request
.
url
)
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/automation'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_automation
(
name
,
appkey
):
...
...
@@ -248,6 +262,7 @@ def administration_users_user_application_automation(name, appkey):
return
render_template
(
'new/admin/user-application-automation.html'
,
automations
=
ats
[
1
],
app
=
ap
[
1
],
user
=
name
)
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/new-automation'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_new_automation
(
name
,
appkey
):
...
...
@@ -281,6 +296,7 @@ def administration_users_user_application_new_automation(name, appkey):
return
redirect
(
request
.
url
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/delete'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_delete
(
name
,
appkey
):
...
...
@@ -308,6 +324,7 @@ def administration_users_user_application_delete(name, appkey):
return
redirect
(
url_for
(
'administration_users_user_applications'
,
name
=
name
))
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/settings'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_settings
(
name
,
appkey
):
...
...
@@ -330,6 +347,7 @@ def administration_users_user_application_settings(name, appkey):
return
redirect
(
request
.
url
)
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/delete-<ntype>'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_notification_remove
(
name
,
appkey
,
ntype
):
...
...
@@ -346,6 +364,7 @@ def administration_users_user_application_notification_remove(name, appkey, ntyp
return
''
,
500
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/variables'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_variables
(
name
,
appkey
,
devid
):
...
...
@@ -359,6 +378,7 @@ def administration_users_user_application_device_variables(name, appkey, devid):
return
select
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_data
(
name
,
appkey
,
devid
,
var
,
dest
,
page
):
...
...
@@ -380,6 +400,7 @@ def administration_users_user_application_device_data(name, appkey, devid, var,
return
t
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/configure'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_configuration
(
name
,
appkey
,
devid
):
...
...
@@ -406,6 +427,7 @@ def administration_users_user_application_device_configuration(name, appkey, dev
return
''
,
201
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/remove-configuration'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_configuration_remove
(
name
,
appkey
,
devid
):
...
...
@@ -419,6 +441,7 @@ def administration_users_user_application_device_configuration_remove(name, appk
return
''
,
200
@
required_privilege
(
60
)
@
app
.
route
(
'/administration/users/<name>/application/<appkey>/device/<devid>/download-csv'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_application_device_download_csv
(
name
,
appkey
,
devid
):
...
...
@@ -454,6 +477,7 @@ def administration_users_user_application_device_download_csv(name, appkey, devi
return
send_from_directory
(
app
.
config
[
'DATA_DOWNLOAD_DIR'
],
fn
,
as_attachment
=
True
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/chart-update'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_chart_update
(
name
):
...
...
@@ -470,6 +494,7 @@ def administration_users_user_chart_update(name):
return
"[{}, {}]"
.
format
(
day_chart
,
week_chart
)
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/recent-activity'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_recent_activity
(
name
):
...
...
@@ -485,6 +510,7 @@ def administration_users_user_recent_activity(name):
return
''
,
401
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/table/<page>'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_table
(
page
):
...
...
@@ -494,6 +520,7 @@ def administration_users_table(page):
return
str
(
users
),
200
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/new-user'
,
methods
=
[
'POST'
,
'GET'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_new_user
():
...
...
@@ -519,6 +546,7 @@ def administration_users_new_user():
return
redirect
(
url_for
(
'administration/users'
,
name
=
username
))
@
required_privilege
(
40
)
@
app
.
route
(
'/administration/users/<name>/settings'
,
methods
=
[
'GET'
,
'POST'
])
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_settings
(
name
):
...
...
@@ -540,11 +568,12 @@ def administration_users_user_settings(name):
return
redirect
(
request
.
url
)
@
required_privilege
(
80
)
@
app
.
route
(
'/administration/users/<name>/delete-account'
)
@
restricted
(
access_level
=
'admin'
)
def
administration_users_user_delete_account
(
name
):
user
=
ud
.
get
(
name
)
if
user
[
0
]
and
user
[
1
][
2
]
!=
'admin'
:
if
user
[
0
]
and
(
user
[
1
][
2
]
!=
'admin'
or
user
[
1
][
3
]
>
80
)
:
app_list
=
ad
.
get_list
(
user
[
1
][
0
])
res
=
(
True
,)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment