Commit 2ad202cf authored by Vladislav Rykov's avatar Vladislav Rykov
Browse files

user restrictions and application protection implemented

parent 7dcc292e
from app import app
from flask import session,flash,redirect,url_for
from functools import wraps
import app.dao.user.user as ud
import app.dao.application.application as ad
from app.helpers.misc import grant_view
def restricted(access_level, user_protect=False):
def user_control(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'role' in session:
if not grant_view(access_level, session['role']):
flash('Access denied.', 'danger')
return redirect(url_for('index'))
if user_protect:
user = ud.get(kwargs['name'])
if not user[0] or not grant_view(user[1][2], session['role']):
flash('Access denied.', 'danger')
return redirect(url_for('index'))
return f(*args, **kwargs)
return redirect(url_for('login'))
return decorated_function
return user_control
def application_protected(f):
def decorated_function(*args, **kwargs):
ap = ad.get(kwargs['appkey'])
print(ap, session)
if not ap[0] or ap[1][2] != session['name']:
flash('Access denied.', 'danger')
return redirect(url_for('index'))
return f(*args, **kwargs)
return decorated_function
......@@ -5,7 +5,6 @@ import os
import psycopg2
import binascii
from datetime import datetime
from functools import wraps
import collections
import json
......@@ -22,15 +21,9 @@ USER_LEVELS = {
'superuser' : 100
}
@app.context_processor
def get_user_levels():
return dict(user_levels=USER_LEVELS)
@app.context_processor
def grant_view():
def check(require, wants):
return USER_LEVELS[require] <= USER_LEVELS[wants]
return dict(grant=check)
def grant_view(require, wants):
return USER_LEVELS[require] <= USER_LEVELS[wants]
app.jinja_env.globals.update(grant_view=grant_view)
def rand_str(length):
if length % 2 == 0:
......@@ -103,20 +96,6 @@ def with_psql(f):
return _with_psql
def restricted(access_level):
def user_control(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'role' in session:
if USER_LEVELS[access_level] > USER_LEVELS[session['role']]:
flash('Access denied.', 'danger')
return redirect(url_for('index'))
return f(*args, **kwargs)
return redirect(url_for('login'))
return decorated_function
return user_control
def clean_data_folder():
try:
filelist = [f for f in os.listdir(app.config['DATA_DOWNLOAD_DIR_OS'])]
......
......@@ -92,7 +92,7 @@
<i class="ni ni-air-baloon text-yellow"></i> Applications
</a>
</li>
{% if get_user_levels() %}
{% if grant_view('admin', session['role']) %}
<li class="nav-item">
<a class="nav-link " href="/administration">
<i class="ni ni-briefcase-24 text-pink"></i> Administration
......
......@@ -17,6 +17,7 @@ import app.dao.misc.misc as md
import app.helpers.misc as misc
import app.helpers.mailer as mailer
import app.helpers.device_data_model as ddm
import app.helpers.decorators as decorators
import os
import binascii
......@@ -28,8 +29,8 @@ MAX_PG_ENTRIES_DATA = 10
MAX_PG_ENTRIES_GRAPH_HOURS = 24
@misc.restricted('interface')
@app.route('/')
@decorators.restricted('interface')
def index():
created_apps = ad.get_count_by_user(session['name'])[1][0]
active_devices = dd.get_count_by_user(session['name'])
......@@ -97,16 +98,17 @@ def logout():
return redirect(url_for('login'))
@misc.restricted('interface')
@app.route('/applications')
@decorators.restricted('interface')
def applications():
apps = ad.get_list(session['name'])
return render_template('new/public/applications.html', apps=apps[1])
@misc.restricted('interface')
@app.route('/application/<appkey>')
@decorators.restricted('interface')
@decorators.application_protected
def application(appkey):
ap = list(ad.get(appkey)[1])
ap[5] = misc.skey_b64_to_hex(ap[5])
......@@ -115,8 +117,8 @@ def application(appkey):
return render_template('new/public/application.html', app=ap, devs=devs)
@misc.restricted('user')
@app.route('/new-application', methods=['GET', 'POST'])
@decorators.restricted('user')
def application_create():
if request.method == 'GET':
return render_template('new/public/new-application.html')
......@@ -148,8 +150,9 @@ def application_create():
return redirect(url_for('applications'))
@misc.restricted('user')
@app.route('/application/<appkey>/delete')
@decorators.restricted('user')
@decorators.application_protected
def application_delete(appkey):
devs = dd.get_list(appkey)
......@@ -175,8 +178,9 @@ def application_delete(appkey):
return redirect(url_for('applications'))
@misc.restricted('interface')
@app.route('/application/<appkey>/device/<devid>')
@decorators.restricted('interface')
@decorators.application_protected
def application_device(appkey, devid):
ap = ad.get(appkey)
if session['name'] == ap[1][2]:
......@@ -193,8 +197,9 @@ def application_device(appkey, devid):
return render_template('new/public/device.html', dev=dev[1], app=ap[1], ltup=ltup, total=cnt[1][0], table_max=MAX_PG_ENTRIES_DATA)
@misc.restricted('user')
@app.route('/application/<appkey>/add-device', methods=['GET', 'POST'])
@decorators.restricted('user')
@decorators.application_protected
def application_add_device(appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -217,8 +222,9 @@ def application_add_device(appkey):
return redirect(url_for('application', appkey=appkey))
@misc.restricted('user')
@app.route('/application/<appkey>/device/<devid>/delete')
@decorators.restricted('user')
@decorators.application_protected
def application_device_delete(appkey, devid):
nq.delete_per_device(appkey, devid)
nfss = nfs.get_per_device(appkey, devid)
......@@ -234,8 +240,9 @@ def application_device_delete(appkey, devid):
return redirect(url_for('application', appkey=appkey))
@misc.restricted('user')
@app.route('/application/<appkey>/device/<devid>/configure', methods=['GET', 'POST'])
@decorators.restricted('user')
@decorators.application_protected
def application_device_configuration(appkey, devid):
if request.method == 'GET':
pend_msgs = pend.get_list(appkey, devid)
......@@ -260,9 +267,20 @@ def application_device_configuration(appkey, devid):
return '', 201
@misc.restricted('interface')
@app.route('/application/<appkey>/device/<devid>/download-csv')
@decorators.restricted('interface')
@decorators.application_protected
def application_device_download_csv(appkey, devid):
@after_this_request
def clean_data_folder(response):
try:
filelist = [f for f in os.listdir(app.config['DATA_DOWNLOAD_DIR_OS'])]
for f in filelist:
os.remove(app.config['DATA_DOWNLOAD_DIR_OS']+'/'+f)
except OSError:
pass
return response
dumpd = data.get_all(appkey, devid)
ap = ad.get(appkey)[1]
dev = dd.get(appkey, devid)[1]
......@@ -286,8 +304,8 @@ def application_device_download_csv(appkey, devid):
return send_from_directory(app.config['DATA_DOWNLOAD_DIR'], fn, as_attachment=True)
@misc.restricted('interface')
@app.route('/chart-update')
@decorators.restricted('interface')
def chart_update():
day_chart_values = md.get_user_data_count_per_hour_period(session['name'], 11)[1]
day_chart_values = [x[0] for x in day_chart_values]
......@@ -302,8 +320,8 @@ def chart_update():
return "[{}, {}]".format(day_chart, week_chart), 200
@misc.restricted('interface')
@app.route('/recent-activity')
@decorators.restricted('interface')
def recent_activity():
recent_activity = md.get_recent_activity(session['name'])[1]
......@@ -316,8 +334,9 @@ def recent_activity():
return ra, 200
@misc.restricted('user')
@app.route('/application/<appkey>/device/<devid>/remove-configuration')
@decorators.restricted('user')
@decorators.application_protected
def application_device_configuration_remove(appkey, devid):
res = pend.delete(appkey, devid, request.args.get('conf')+'_')
......@@ -329,8 +348,9 @@ def application_device_configuration_remove(appkey, devid):
return '', 200
@misc.restricted('user')
@app.route('/application/<appkey>/device/<devid>/variables')
@decorators.restricted('user')
@decorators.application_protected
def application_device_variables(appkey, devid):
dmodel = dd.get(appkey, devid)
if dmodel[0]:
......@@ -342,8 +362,8 @@ def application_device_variables(appkey, devid):
return select
@misc.restricted('user')
@app.route('/delete-account')
@decorators.restricted('user')
def delete_account():
user = ud.get(request.args.get('name'))
app_list = ad.get_list(user[1][0])
......@@ -377,8 +397,8 @@ def delete_account():
return redirect(url_for('login'))
@misc.restricted('user')
@app.route('/settings', methods=['GET', 'POST'])
@decorators.restricted('user')
def settings():
if request.method == 'GET':
return render_template('new/public/settings.html', user=session['name'])
......@@ -400,8 +420,9 @@ def settings():
return redirect(request.url)
@misc.restricted('interface')
@app.route('/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>')
@decorators.restricted('interface')
@decorators.application_protected
def application_device_data(appkey, devid, var, dest, page):
dev = dd.get(appkey, devid)[1]
if dest == 'graph':
......@@ -425,16 +446,18 @@ def application_device_data(appkey, devid, var, dest, page):
return t
@misc.restricted('interface')
@app.route('/application/<appkey>/alerts')
@decorators.restricted('interface')
@decorators.application_protected
def application_alerts(appkey):
ap = ad.get(appkey)
alerts = nfs.get_alerts_list(appkey)
return render_template('new/public/alerts.html', alert_list=alerts[1], app=ap[1])
@misc.restricted('user')
@app.route('/application/<appkey>/new-alert', methods=['GET', 'POST'])
@decorators.restricted('user')
@decorators.application_protected
def application_new_alert(appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -463,8 +486,9 @@ def application_new_alert(appkey):
return redirect(request.url)
@misc.restricted('user')
@app.route('/application/<appkey>/delete-<ntype>')
@decorators.restricted('user')
@decorators.application_protected
def application_notification_remove(appkey, ntype):
nq.delete(appkey, request.args.get('devid'), request.args.get('id'))
tr.delete(appkey, request.args.get('devid'), request.args.get('id'))
......@@ -479,8 +503,9 @@ def application_notification_remove(appkey, ntype):
return '', 500
@misc.restricted('interface')
@app.route('/application/<appkey>/automation')
@decorators.restricted('interface')
@decorators.application_protected
def application_automation(appkey):
ap = ad.get(appkey)
ats = nfs.get_automation_list(appkey)
......@@ -488,8 +513,9 @@ def application_automation(appkey):
return render_template('new/public/automation.html', automations=ats[1], app=ap[1])
@misc.restricted('user')
@app.route('/application/<appkey>/new-automation', methods=['GET', 'POST'])
@decorators.restricted('user')
@decorators.application_protected
def application_new_automation(appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -521,8 +547,9 @@ def application_new_automation(appkey):
return redirect(request.url)
@misc.restricted('user')
@app.route('/application/<appkey>/settings', methods=['GET', 'POST'])
@decorators.restricted('user')
@decorators.application_protected
def application_settings(appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -543,8 +570,9 @@ def application_settings(appkey):
return redirect(request.url)
@misc.restricted('user')
@app.route('/application/<appkey>/device/<devid>/settings', methods=['GET', 'POST'])
@decorators.restricted('user')
@decorators.application_protected
def application_device_settings(appkey, devid):
if request.method == 'GET':
ap = ad.get(appkey)
......
......@@ -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.decorators import restricted
import app.helpers.device_data_model as ddm
import app.helpers.misc as misc
......@@ -47,7 +47,7 @@ def administration():
@app.route('/administration/users')
@restricted(access_level='admin')
@restricted('admin')
def administration_users():
user_cnt = ud.get_count()[1][0]
apps_cnt = ad.get_count()[1][0]
......@@ -61,30 +61,25 @@ def administration_users():
@app.route('/administration/users/<name>')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user(name):
user = ud.get(name)
if user[0]:
created_apps = ad.get_count_by_user(name)[1][0]
active_devices = dd.get_count_by_user(name)
total_activity = md.get_user_data_count(name)[1][0]
last_activity = md.get_user_data_count_per_day(name)[1][0]
info = [created_apps, active_devices, total_activity, last_activity]
return render_template('new/admin/user-dashboard.html', info=info, user=name)
else:
flash('Access denied', 'danger')
return redirect(url_for('administration_users'))
created_apps = ad.get_count_by_user(name)[1][0]
active_devices = dd.get_count_by_user(name)
total_activity = md.get_user_data_count(name)[1][0]
last_activity = md.get_user_data_count_per_day(name)[1][0]
info = [created_apps, active_devices, total_activity, last_activity]
return render_template('new/admin/user-dashboard.html', info=info, user=name)
@app.route('/administration/users/<name>/applications')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_applications(name):
apps = ad.get_list(name)[1]
return render_template('new/admin/user-applications.html', apps=apps, user=name)
@app.route('/administration/users/<name>/new-application', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_create(name):
if request.method == 'GET':
return render_template('new/admin/user-new-application.html', user=name)
......@@ -117,7 +112,7 @@ def administration_users_user_application_create(name):
@app.route('/administration/users/<name>/application/<appkey>')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application(name, appkey):
ap = list(ad.get(appkey)[1])
ap[5] = misc.skey_b64_to_hex(ap[5])
......@@ -127,7 +122,7 @@ def administration_users_user_application(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/add-device', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_add_device(name, appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -152,7 +147,7 @@ def administration_users_user_application_add_device(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device(name, appkey, devid):
ap = ad.get(appkey)
dev = dd.get(appkey, devid)
......@@ -169,7 +164,7 @@ def administration_users_user_application_device(name, appkey, devid):
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/settings', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_settings(name, appkey, devid):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -188,7 +183,7 @@ def administration_users_user_application_device_settings(name, appkey, devid):
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/delete')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_delete(name, appkey, devid):
nq.delete_per_device(appkey, devid)
nfss = nfs.get_per_device(appkey, devid)
......@@ -204,7 +199,7 @@ def administration_users_user_application_device_delete(name, appkey, devid):
@app.route('/administration/users/<name>/application/<appkey>/alerts')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_alerts(name, appkey):
ap = ad.get(appkey)
alerts = nfs.get_alerts_list(appkey)
......@@ -212,37 +207,37 @@ def administration_users_user_application_alerts(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/new-alert', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_new_alert(name, appkey):
if request.method == 'GET':
ap = ad.get(appkey)
devs = dd.get_list(appkey)
return render_template('new/admin/user-new-alert.html', devs=devs[1], app=ap[1], user=name)
elif request.method == 'POST':
# create new notification
nid = misc.rand_str(app.config['NID_LENGTH']).decode('utf-8')
dev = dd.get(appkey, request.form['devid'])
try:
desc = dev[1][0]+'.'+request.form['varname']+' '+request.form['operation']+' '+request.form['avalue']
res = nfs.create(nid, appkey, request.form['devid'], request.form['alertname'], desc, 'alert', request.form['alertemail'])
if res[0]:
# create new function and trigger
tr.create_function(appkey, request.form['devid'], nid, [request.form['varname'],request.form['operation'],request.form['avalue']])
tr.create(appkey, request.form['devid'], nid)
flash('Alert created', 'success')
return redirect(url_for('administration_users_user_application_alerts', name=name, appkey=appkey))
else:
flash('Error creating new alert: {}'.format(res[1]), 'danger')
if request.method == 'GET':
ap = ad.get(appkey)
devs = dd.get_list(appkey)
return render_template('new/admin/user-new-alert.html', devs=devs[1], app=ap[1], user=name)
elif request.method == 'POST':
# create new notification
nid = misc.rand_str(app.config['NID_LENGTH']).decode('utf-8')
dev = dd.get(appkey, request.form['devid'])
try:
desc = dev[1][0]+'.'+request.form['varname']+' '+request.form['operation']+' '+request.form['avalue']
res = nfs.create(nid, appkey, request.form['devid'], request.form['alertname'], desc, 'alert', request.form['alertemail'])
if res[0]:
# create new function and trigger
tr.create_function(appkey, request.form['devid'], nid, [request.form['varname'],request.form['operation'],request.form['avalue']])
tr.create(appkey, request.form['devid'], nid)
flash('Alert created', 'success')
return redirect(url_for('administration_users_user_application_alerts', name=name, appkey=appkey))
else:
flash('Error creating new alert: {}'.format(res[1]), 'danger')
return redirect(request.url)
except Exception as e:
flash('Error creating new alert: {}. Make sure you have filled all form fields.'.format(e), 'danger')
return redirect(request.url)
except Exception as e:
flash('Error creating new alert: {}. Make sure you have filled all form fields.'.format(e), 'danger')
return redirect(request.url)
@app.route('/administration/users/<name>/application/<appkey>/automation')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_automation(name, appkey):
ap = ad.get(appkey)
ats = nfs.get_automation_list(appkey)
......@@ -251,7 +246,7 @@ def administration_users_user_application_automation(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/new-automation', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_new_automation(name, appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -284,7 +279,7 @@ def administration_users_user_application_new_automation(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/delete')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_delete(name, appkey):
devs = dd.get_list(appkey)
......@@ -311,7 +306,7 @@ def administration_users_user_application_delete(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/settings', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_settings(name, appkey):
if request.method == 'GET':
ap = ad.get(appkey)
......@@ -333,7 +328,7 @@ def administration_users_user_application_settings(name, appkey):
@app.route('/administration/users/<name>/application/<appkey>/delete-<ntype>')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_notification_remove(name, appkey, ntype):
nq.delete(appkey, request.args.get('devid'), request.args.get('id'))
tr.delete(appkey, request.args.get('devid'), request.args.get('id'))
......@@ -349,19 +344,19 @@ def administration_users_user_application_notification_remove(name, appkey, ntyp
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/variables')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_variables(name, appkey, devid):
dev = dd.get(appkey, devid)[1]
select = '<select class="form-control" id="varname" name="varname" onchange="validate_form();" required>'
select += '<option value="-">Select Variable</option>'
for k in dev[3]['format']:
select += '<option>'+k+'</option>'
select += '</select>'
return select
dev = dd.get(appkey, devid)[1]
select = '<select class="form-control" id="varname" name="varname" onchange="validate_form();" required>'
select += '<option value="-">Select Variable</option>'
for k in dev[3]['format']:
select += '<option>'+k+'</option>'
select += '</select>'
return select
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_data(name, appkey, devid, var, dest, page):
dev = dd.get(appkey, devid)[1]
if dest == 'graph':
......@@ -385,7 +380,7 @@ def administration_users_user_application_device_data(name, appkey, devid, var,
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/configure', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_configuration(name, appkey, devid):
if request.method == 'GET':
pend_msgs = pend.get_list(appkey, devid)
......@@ -411,7 +406,7 @@ def administration_users_user_application_device_configuration(name, appkey, dev
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/remove-configuration')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_configuration_remove(name, appkey, devid):
res = pend.delete(appkey, devid, request.args.get('conf')+'_')
......@@ -424,7 +419,7 @@ def administration_users_user_application_device_configuration_remove(name, appk
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/download-csv')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_application_device_download_csv(name, appkey, devid):
@after_this_request
def clean_data_folder(response):
......@@ -459,7 +454,7 @@ def administration_users_user_application_device_download_csv(name, appkey, devi
@app.route('/administration/users/<name>/chart-update')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_chart_update(name):
day_chart_values = md.get_user_data_count_per_hour_period(name, 11)[1]
day_chart_values = [x[0] for x in day_chart_values]
......@@ -475,7 +470,7 @@ def administration_users_user_chart_update(name):
@app.route('/administration/users/<name>/recent-activity')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_recent_activity(name):
recent_activity = md.get_recent_activity(name)[1]
ra = ''
......@@ -488,7 +483,7 @@ def administration_users_user_recent_activity(name):
@app.route('/administration/users/table/<page>')
@restricted(access_level='admin')
@restricted('admin')
def administration_users_table(page):
users = ud.get_range_name(request.args.get('name'), [MAX_PG_ENTRIES_USERS, (int(page)-1)*MAX_PG_ENTRIES_USERS])[1]
users = [[u[0],u[2]] for u in users]
......@@ -497,7 +492,7 @@ def administration_users_table(page):
@app.route('/administration/users/new-user', methods=['POST', 'GET'])
@restricted(access_level='admin')
@restricted('admin')
def administration_users_new_user():
if request.method == 'GET':
return render_template('new/admin/new-user.html')
......@@ -522,10 +517,10 @@ def administration_users_new_user():
@app.route('/administration/users/<name>/settings', methods=['GET', 'POST'])
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_settings(name):
user = ud.get(name)
if user[0] and (misc.USER_LEVELS[user[1][2]] < misc.USER_LEVELS[session['role']]):
if user[0] and misc.grant_view(user[1][2], session['role']):
if request.method == 'GET':
return render_template('new/admin/user-settings.html', user=name, user_role=user[1][2])
else:
......@@ -552,10 +547,10 @@ def administration_users_user_settings(name):
@app.route('/administration/users/<name>/delete-account')
@restricted(access_level='admin')
@restricted('admin', True)
def administration_users_user_delete_account(name):
user = ud.get(name)
if user[0] and (misc.USER_LEVELS[user[1][2]] < misc.USER_LEVELS[session['role']]):
if user[0] and misc.grant_view(user[1][2], session['role']):
app_list = ad.get_list(user[1][0])
res = (True,)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment