mirror of
https://github.com/ail-project/ail-framework.git
synced 2024-11-10 00:28:22 +00:00
chg: [settings] refactor UI settings
This commit is contained in:
parent
0b8ff17c5b
commit
8a0c18c575
6 changed files with 249 additions and 181 deletions
|
@ -174,6 +174,14 @@ def exists_token(token):
|
|||
|
||||
# TODO USER LAST LOGIN TIME
|
||||
# TODO Check if logged
|
||||
|
||||
# TODO USER: - Creation Date
|
||||
# - Last Login
|
||||
# - Last Request
|
||||
# - Last API Usage
|
||||
# - Organisation ???
|
||||
# - Disabled / Lock
|
||||
|
||||
class AILUser(UserMixin):
|
||||
def __init__(self, user_id):
|
||||
self.user_id = user_id
|
||||
|
@ -200,8 +208,13 @@ class AILUser(UserMixin):
|
|||
def exists(self): # TODO CHECK USAGE
|
||||
return r_serv_db.exists(f'ail:user:metadata:{self.user_id}')
|
||||
|
||||
def get_meta(self):
|
||||
return {'email': self.user_id,}
|
||||
def get_meta(self, options=set()): # TODO user creation date
|
||||
meta = {'id': self.user_id}
|
||||
if 'api_key' in options: # TODO add option to censor key
|
||||
meta['api_key'] = self.get_api_key()
|
||||
if 'role' in options:
|
||||
meta['role'] = get_user_role(self.user_id)
|
||||
return meta
|
||||
|
||||
## SESSION ##
|
||||
|
||||
|
@ -253,6 +266,17 @@ class AILUser(UserMixin):
|
|||
# create new token
|
||||
generate_new_token(self.user_id)
|
||||
|
||||
## TOKEN ##
|
||||
|
||||
def get_api_key(self):
|
||||
return get_user_token(self.user_id)
|
||||
|
||||
def new_api_key(self):
|
||||
_delete_user_token(self.user_id)
|
||||
new_api_key = gen_token()
|
||||
_set_user_token(self.user_id, new_api_key)
|
||||
return new_api_key
|
||||
|
||||
## ROLE ##
|
||||
|
||||
def is_in_role(self, role): # TODO Get role via user alternative ID
|
||||
|
@ -266,14 +290,45 @@ class AILUser(UserMixin):
|
|||
def get_role(self):
|
||||
return r_serv_db.hget(f'ail:user:metadata:{self.user_id}', 'role')
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||
## ##
|
||||
|
||||
def delete(self): # TODO DESTROY SESSION
|
||||
def delete(self):
|
||||
kill_session_user(self.user_id)
|
||||
for role_id in get_all_roles():
|
||||
r_serv_db.srem(f'ail:users:role:{role_id}', self.user_id)
|
||||
user_token = self.get_api_key()
|
||||
if user_token:
|
||||
r_serv_db.hdel('ail:users:tokens', user_token)
|
||||
r_serv_db.delete(f'ail:user:metadata:{self.user_id}')
|
||||
r_serv_db.hdel('ail:users:all', self.user_id)
|
||||
|
||||
|
||||
# def create_user(user_id):
|
||||
|
||||
#### API ####
|
||||
|
||||
def api_get_users_meta():
|
||||
meta = {'users': []}
|
||||
options = {'api_key', 'role'}
|
||||
for user_id in get_users():
|
||||
user = AILUser(user_id)
|
||||
meta['users'].append(user.get_meta(options=options))
|
||||
return meta
|
||||
|
||||
def api_create_user_api_key(user_id, admin_id): # TODO LOG ADMIN ID
|
||||
user = AILUser(user_id)
|
||||
if not user.exists():
|
||||
return {'status': 'error', 'reason': 'User not found'}, 404
|
||||
print(admin_id)
|
||||
return user.new_api_key(), 200
|
||||
|
||||
def api_delete_user(user_id, admin_id): # TODO LOG ADMIN ID
|
||||
user = AILUser(user_id)
|
||||
if not user.exists():
|
||||
return {'status': 'error', 'reason': 'User not found'}, 404
|
||||
print(admin_id)
|
||||
return user.delete(), 200
|
||||
|
||||
########################################################################################################################
|
||||
########################################################################################################################
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ sys.path.append(os.environ['AIL_BIN'])
|
|||
# Import Project packages
|
||||
##################################
|
||||
from lib import ail_updates
|
||||
from lib import ail_users
|
||||
from packages import git_status
|
||||
|
||||
# ============ BLUEPRINT ============
|
||||
|
@ -40,9 +41,9 @@ def create_json_response(data, status_code):
|
|||
def settings_page():
|
||||
git_metadata = git_status.get_git_metadata()
|
||||
ail_version = ail_updates.get_ail_version()
|
||||
admin_level = current_user.is_in_role('admin')
|
||||
acl_admin = current_user.is_in_role('admin')
|
||||
return render_template("settings_index.html", git_metadata=git_metadata,
|
||||
ail_version=ail_version, admin_level=admin_level)
|
||||
ail_version=ail_version, acl_admin=acl_admin)
|
||||
|
||||
@settings_b.route("/settings/background_update/json", methods=['GET'])
|
||||
@login_required
|
||||
|
@ -54,12 +55,46 @@ def get_background_update_metadata_json():
|
|||
@login_required
|
||||
@login_read_only
|
||||
def settings_modules():
|
||||
admin_level = current_user.is_in_role('admin')
|
||||
return render_template("settings/modules.html", admin_level=admin_level)
|
||||
acl_admin = current_user.is_in_role('admin')
|
||||
return render_template("settings/modules.html", acl_admin=acl_admin)
|
||||
|
||||
@settings_b.route("/settings/user/profile", methods=['GET'])
|
||||
@login_required
|
||||
@login_read_only
|
||||
def user_profile():
|
||||
acl_admin = current_user.is_in_role('admin')
|
||||
|
||||
@settings_b.route("/settings/new_user_api_key", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def new_token_user():
|
||||
user_id = request.args.get('user_id')
|
||||
admin_id = current_user.get_user_id()
|
||||
r = ail_users.api_create_user_api_key(user_id, admin_id)
|
||||
if r[1] != 200:
|
||||
return create_json_response(r[0], r[1])
|
||||
else:
|
||||
return redirect(url_for('settings_b.users_list'))
|
||||
|
||||
@settings_b.route("/settings/delete_user", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def delete_user():
|
||||
user_id = request.args.get('user_id')
|
||||
admin_id = current_user.get_user_id()
|
||||
r = ail_users.api_delete_user(user_id, admin_id)
|
||||
if r[1] != 200:
|
||||
return create_json_response(r[0], r[1])
|
||||
else:
|
||||
return redirect(url_for('settings_b.users_list'))
|
||||
|
||||
@settings_b.route("/settings/users", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def users_list():
|
||||
meta = ail_users.api_get_users_meta()
|
||||
new_user = {}
|
||||
return render_template("users_list.html", meta=meta, new_user=new_user, acl_admin=True)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -61,17 +61,6 @@ def new_token():
|
|||
Users.generate_new_token(current_user.get_id())
|
||||
return redirect(url_for('settings.edit_profile'))
|
||||
|
||||
|
||||
@settings.route("/settings/new_token_user", methods=['POST'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def new_token_user():
|
||||
user_id = request.form.get('user_id')
|
||||
if Users.exists_user(user_id):
|
||||
Users.generate_new_token(user_id)
|
||||
return redirect(url_for('settings.users_list'))
|
||||
|
||||
|
||||
@settings.route("/settings/create_user", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
|
@ -133,18 +122,18 @@ def create_user_post():
|
|||
return render_template("create_user.html", all_roles=all_roles, error_mail=True, admin_level=True)
|
||||
|
||||
|
||||
@settings.route("/settings/users_list", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def users_list():
|
||||
all_users = Users.get_users_metadata(Users.get_all_users())
|
||||
new_user = request.args.get('new_user')
|
||||
new_user_dict = {}
|
||||
if new_user:
|
||||
new_user_dict['email'] = new_user
|
||||
new_user_dict['edited'] = request.args.get('new_user_edited')
|
||||
new_user_dict['password'] = request.args.get('new_user_password')
|
||||
return render_template("users_list.html", all_users=all_users, new_user=new_user_dict, admin_level=True)
|
||||
# @settings.route("/settings/users_list", methods=['GET'])
|
||||
# @login_required
|
||||
# @login_admin
|
||||
# def users_list():
|
||||
# all_users = Users.get_users_metadata(Users.get_all_users())
|
||||
# new_user = request.args.get('new_user')
|
||||
# new_user_dict = {}
|
||||
# if new_user:
|
||||
# new_user_dict['email'] = new_user
|
||||
# new_user_dict['edited'] = request.args.get('new_user_edited')
|
||||
# new_user_dict['password'] = request.args.get('new_user_password')
|
||||
# return render_template("users_list.html", all_users=all_users, new_user=new_user_dict, admin_level=True)
|
||||
|
||||
|
||||
@settings.route("/settings/edit_user", methods=['POST'])
|
||||
|
@ -155,15 +144,6 @@ def edit_user():
|
|||
return redirect(url_for('settings.create_user', user_id=user_id))
|
||||
|
||||
|
||||
@settings.route("/settings/delete_user", methods=['POST'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def delete_user():
|
||||
user_id = request.form.get('user_id')
|
||||
Users.delete_user(user_id)
|
||||
return redirect(url_for('settings.users_list'))
|
||||
|
||||
|
||||
@settings.route("/settings/passivedns", methods=['GET'])
|
||||
@login_required
|
||||
@login_read_only
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Server Management - AIL</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- JS -->
|
||||
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% include 'nav_bar.html' %}
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
{% include 'settings/menu_sidebar.html' %}
|
||||
|
||||
<div class="col-12 col-lg-10" id="core_content">
|
||||
|
||||
{% if new_user %}
|
||||
<div class="text-center my-3 ">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{% if new_user['edited']=='True' %}
|
||||
<h5 class="card-title">User Edited</h5>
|
||||
{% else %}
|
||||
<h5 class="card-title">User Created</h5>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>User: {{new_user['email']}}</p>
|
||||
<p>Password: {{new_user['password']}}</p>
|
||||
<a href="{{url_for('settings.users_list')}}" class="btn btn-primary"><i class="fas fa-eye-slash"></i> Hide</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="table-responsive mt-1 table-hover table-borderless table-striped">
|
||||
<table class="table">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Email</th>
|
||||
<th>Role</th>
|
||||
<th>Api Key</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody_last_crawled">
|
||||
{% for user in all_users %}
|
||||
<tr>
|
||||
<td>{{user['email']}}</td>
|
||||
<td>{{user['role']}}</td>
|
||||
<td>
|
||||
<form action="{{ url_for('settings.new_token_user') }}" id="post_new_token" method=POST>
|
||||
<span id="censored_key_{{loop.index0}}">
|
||||
{{user['api_key'][:4]}}*********************************{{user['api_key'][-4:]}}
|
||||
</span>
|
||||
<span id="uncensored_key_{{loop.index0}}" style="display: none;">
|
||||
{{user['api_key']}}
|
||||
</span>
|
||||
<input type="hidden" name="user_id" value="{{user['email']}}">
|
||||
<button class="btn btn-outline-info ml-3 px-1 py-0" type="submit">
|
||||
<i class="fas fa-random"></i>
|
||||
</button>
|
||||
<span class="btn btn-outline-secondary ml-1 px-1 py-0" id="btn_key_{{loop.index0}}" onclick="show_api_key({{loop.index0}})">
|
||||
<i class="fas fa-eye"></i>
|
||||
</span>
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-start">
|
||||
<form action="{{ url_for('settings.edit_user') }}" id="post_edit_user" method=POST>
|
||||
<input type="hidden" name="user_id" value="{{user['email']}}">
|
||||
<button class="btn btn-outline-primary ml-3 px-1 py-0" type="submit">
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
</button>
|
||||
</form>
|
||||
<form action="{{ url_for('settings.delete_user') }}" id="post_delete_user" method=POST>
|
||||
<input type="hidden" name="user_id" value="{{user['email']}}">
|
||||
<button class="btn btn-outline-danger ml-3 px-1 py-0" type="submit">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("#nav_users_list").addClass("active");
|
||||
$("#nav_user_management").removeClass("text-muted");
|
||||
} );
|
||||
|
||||
function toggle_sidebar(){
|
||||
if($('#nav_menu').is(':visible')){
|
||||
$('#nav_menu').hide();
|
||||
$('#side_menu').removeClass('border-right')
|
||||
$('#side_menu').removeClass('col-lg-2')
|
||||
$('#core_content').removeClass('col-lg-10')
|
||||
}else{
|
||||
$('#nav_menu').show();
|
||||
$('#side_menu').addClass('border-right')
|
||||
$('#side_menu').addClass('col-lg-2')
|
||||
$('#core_content').addClass('col-lg-10')
|
||||
}
|
||||
}
|
||||
|
||||
function show_api_key(key_id) {
|
||||
$('#censored_key_' + key_id).hide();
|
||||
$('#btn_key_' + key_id).hide();
|
||||
$('#uncensored_key_' + key_id).show();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -83,7 +83,7 @@
|
|||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% if admin_level %}
|
||||
{% if acl_admin %}
|
||||
<h5 class="d-flex text-muted w-100 py-2" id="nav_user_management">
|
||||
<span>User Management</span>
|
||||
</h5>
|
||||
|
@ -95,7 +95,7 @@
|
|||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{url_for('settings.users_list')}}" id="nav_users_list">
|
||||
<a class="nav-link" href="{{url_for('settings_b.users_list')}}" id="nav_users_list">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>Users List</span>
|
||||
</a>
|
||||
|
|
137
var/www/templates/settings/users_list.html
Normal file
137
var/www/templates/settings/users_list.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Users Settings - AIL</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/dataTables.bootstrap.min.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- JS -->
|
||||
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% include 'nav_bar.html' %}
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
{% include 'settings/menu_sidebar.html' %}
|
||||
<div class="col-12 col-lg-10" id="core_content">
|
||||
|
||||
{% if new_user %}
|
||||
<div class="text-center my-3 ">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{% if new_user['edited']=='True' %}
|
||||
<h5 class="card-title">User Edited</h5>
|
||||
{% else %}
|
||||
<h5 class="card-title">User Created</h5>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>User: {{new_user['email']}}</p>
|
||||
<p>Password: {{new_user['password']}}</p>
|
||||
<a href="{{url_for('settings.users_list')}}" class="btn btn-primary"><i class="fas fa-eye-slash"></i> Hide</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h3>AIL Users:</h3>
|
||||
<table id="tableusers" class="table table-hover table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>Role</th>
|
||||
<th>Api Key</th>
|
||||
<th></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody_last_crawled">
|
||||
{% for user in meta['users'] %}
|
||||
<tr>
|
||||
<td>{{user['id']}}</td>
|
||||
<td>{{user['role']}}</td>
|
||||
<td>
|
||||
<span id="censored_key_{{loop.index0}}">
|
||||
{{user['api_key'][:4]}}*********************************{{user['api_key'][-4:]}}
|
||||
</span>
|
||||
<span id="uncensored_key_{{loop.index0}}" style="display: none;">
|
||||
{{user['api_key']}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<a class="btn btn-outline-info ml-3 px-1 py-0" href="{{ url_for('settings_b.new_token_user', user_id=user['id']) }}">
|
||||
<i class="fas fa-random"></i>
|
||||
</a>
|
||||
<span class="btn btn-outline-secondary ml-1 px-1 py-0" id="btn_key_{{loop.index0}}" onclick="show_api_key({{loop.index0}})">
|
||||
<i class="fas fa-eye"></i>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-start">
|
||||
<form action="{{ url_for('settings.edit_user') }}" id="post_edit_user" method=POST>
|
||||
<input type="hidden" name="user_id" value="{{user['id']}}">
|
||||
<button class="btn btn-outline-primary ml-3 px-1 py-0" type="submit">
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
</button>
|
||||
</form>
|
||||
<a class="btn btn-outline-danger ml-3 px-1 py-0" href="{{ url_for('settings_b.delete_user', user_id=user['id']) }}">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("#nav_users_list").addClass("active");
|
||||
$("#nav_user_management").removeClass("text-muted");
|
||||
$('#tableusers').DataTable({
|
||||
"aLengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
|
||||
"iDisplayLength": 10,
|
||||
"order": [[ 0, "asc" ]]
|
||||
});
|
||||
});
|
||||
|
||||
function toggle_sidebar(){
|
||||
if($('#nav_menu').is(':visible')){
|
||||
$('#nav_menu').hide();
|
||||
$('#side_menu').removeClass('border-right')
|
||||
$('#side_menu').removeClass('col-lg-2')
|
||||
$('#core_content').removeClass('col-lg-10')
|
||||
}else{
|
||||
$('#nav_menu').show();
|
||||
$('#side_menu').addClass('border-right')
|
||||
$('#side_menu').addClass('col-lg-2')
|
||||
$('#core_content').addClass('col-lg-10')
|
||||
}
|
||||
}
|
||||
|
||||
function show_api_key(key_id) {
|
||||
$('#censored_key_' + key_id).hide();
|
||||
$('#btn_key_' + key_id).hide();
|
||||
$('#uncensored_key_' + key_id).show();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
Loading…
Reference in a new issue