mirror of
https://github.com/ail-project/ail-framework.git
synced 2024-11-27 00:07:16 +00:00
chg: [user_managemant] clean code + check password and email length
This commit is contained in:
parent
5b58872b15
commit
34e57fe7af
10 changed files with 53 additions and 147 deletions
|
@ -44,10 +44,8 @@ class User(UserMixin):
|
||||||
|
|
||||||
def check_password(self, password):
|
def check_password(self, password):
|
||||||
password = password.encode()
|
password = password.encode()
|
||||||
print(self.id)
|
|
||||||
hashed_password = self.r_serv_db.hget('user:all', self.id).encode()
|
hashed_password = self.r_serv_db.hget('user:all', self.id).encode()
|
||||||
if bcrypt.checkpw(password, hashed_password):
|
if bcrypt.checkpw(password, hashed_password):
|
||||||
print('password correct')
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*-coding:UTF-8 -*
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
import redis
|
import redis
|
||||||
import configparser
|
import configparser
|
||||||
import random
|
import random
|
||||||
|
@ -15,10 +19,7 @@ import bcrypt
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from os.path import join
|
from os.path import join
|
||||||
import sys
|
|
||||||
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/'))
|
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/'))
|
||||||
sys.path.append('./modules/')
|
sys.path.append('./modules/')
|
||||||
import Paste
|
import Paste
|
||||||
|
@ -31,52 +32,20 @@ from pytaxonomies import Taxonomies
|
||||||
# Import config
|
# Import config
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
# Import Role_Manager
|
||||||
|
from Role_Manager import create_user_db, check_password_strength
|
||||||
|
|
||||||
def flask_init():
|
def flask_init():
|
||||||
# check if an account exists
|
# # TODO: move this to update
|
||||||
if not r_serv_db.exists('user:all'):
|
# role init
|
||||||
password = secrets.token_urlsafe()
|
|
||||||
create_user_db('admin@admin.test', password, role='admin',default=True)
|
|
||||||
# add default roles
|
|
||||||
if not r_serv_db.exists('ail:all_role'):
|
if not r_serv_db.exists('ail:all_role'):
|
||||||
r_serv_db.zadd('ail:all_role', 1, 'admin')
|
r_serv_db.zadd('ail:all_role', 1, 'admin')
|
||||||
r_serv_db.zadd('ail:all_role', 2, 'analyst')
|
r_serv_db.zadd('ail:all_role', 2, 'analyst')
|
||||||
|
|
||||||
def hashing_password(bytes_password):
|
# check if an account exists
|
||||||
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
|
if not r_serv_db.exists('user:all'):
|
||||||
return hashed
|
password = secrets.token_urlsafe()
|
||||||
|
create_user_db('admin@admin.test', password, role='admin',default=True)
|
||||||
def verify_password(id, bytes_password):
|
|
||||||
hashed_password = r_serv_db.hget('user:all', id)
|
|
||||||
if bcrypt.checkpw(password, hashed):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def check_password_strength(password):
|
|
||||||
result = regex_password.match(password)
|
|
||||||
if result:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def create_user_db(username_id , password, default=False, role=None, update=False):
|
|
||||||
password = password.encode()
|
|
||||||
password_hash = hashing_password(password)
|
|
||||||
r_serv_db.hset('user:all', username_id, password_hash)
|
|
||||||
if update:
|
|
||||||
r_serv_db.hdel('user_metadata:{}'.format(username_id), 'change_passwd')
|
|
||||||
if username_id=='admin@admin.test':
|
|
||||||
os.remove(default_passwd_file)
|
|
||||||
else:
|
|
||||||
if default:
|
|
||||||
r_serv_db.hset('user_metadata:{}'.format(username_id), 'change_passwd', True)
|
|
||||||
if role:
|
|
||||||
if role in get_all_role():
|
|
||||||
r_serv_db.sadd('user_role:{}'.format(role), username_id)
|
|
||||||
|
|
||||||
def get_all_role():
|
|
||||||
return r_serv_db.zrange('ail:all_role', 0 , -1)
|
|
||||||
|
|
||||||
# CONFIG #
|
# CONFIG #
|
||||||
cfg = Flask_config.cfg
|
cfg = Flask_config.cfg
|
||||||
|
@ -85,11 +54,6 @@ baseUrl = baseUrl.replace('/', '')
|
||||||
if baseUrl != '':
|
if baseUrl != '':
|
||||||
baseUrl = '/'+baseUrl
|
baseUrl = '/'+baseUrl
|
||||||
|
|
||||||
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
|
|
||||||
|
|
||||||
regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,}$'
|
|
||||||
regex_password = re.compile(regex_password)
|
|
||||||
|
|
||||||
# ========= REDIS =========#
|
# ========= REDIS =========#
|
||||||
r_serv_db = redis.StrictRedis(
|
r_serv_db = redis.StrictRedis(
|
||||||
host=cfg.get("ARDB_DB", "host"),
|
host=cfg.get("ARDB_DB", "host"),
|
||||||
|
@ -181,9 +145,6 @@ modified_header = modified_header.replace('<!--insert here-->', '\n'.join(to_add
|
||||||
with open('templates/header.html', 'w') as f:
|
with open('templates/header.html', 'w') as f:
|
||||||
f.write(modified_header)
|
f.write(modified_header)
|
||||||
|
|
||||||
flask_init()
|
|
||||||
|
|
||||||
|
|
||||||
# ========= JINJA2 FUNCTIONS ========
|
# ========= JINJA2 FUNCTIONS ========
|
||||||
def list_len(s):
|
def list_len(s):
|
||||||
return len(s)
|
return len(s)
|
||||||
|
@ -213,7 +174,6 @@ def login():
|
||||||
user = User.get(username)
|
user = User.get(username)
|
||||||
if user and user.check_password(password):
|
if user and user.check_password(password):
|
||||||
login_user(user) ## TODO: use remember me ?
|
login_user(user) ## TODO: use remember me ?
|
||||||
print(user.is_active)
|
|
||||||
if user.request_password_change():
|
if user.request_password_change():
|
||||||
return redirect(url_for('change_password'))
|
return redirect(url_for('change_password'))
|
||||||
else:
|
else:
|
||||||
|
@ -245,37 +205,12 @@ def change_password():
|
||||||
else:
|
else:
|
||||||
return render_template("change_password.html")
|
return render_template("change_password.html")
|
||||||
|
|
||||||
@app.route('/role', methods=['POST', 'GET'])
|
|
||||||
def role():
|
|
||||||
return 'ERROR role'
|
|
||||||
|
|
||||||
@app.route('/logout')
|
@app.route('/logout')
|
||||||
@login_required
|
@login_required
|
||||||
def logout():
|
def logout():
|
||||||
logout_user()
|
logout_user()
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
@app.route('/create_user')
|
|
||||||
@login_required
|
|
||||||
def create_user():
|
|
||||||
username = request.form.get('username')
|
|
||||||
password = request.form.get('password')
|
|
||||||
#role = request.form.get('role') ## TODO: create role
|
|
||||||
|
|
||||||
## TODO: validate username
|
|
||||||
## TODO: validate password
|
|
||||||
|
|
||||||
username = 'admin@admin.test'
|
|
||||||
password = 'admin'
|
|
||||||
|
|
||||||
if r_serv_db.hexists('user:all', username):
|
|
||||||
return 'this id is not available'
|
|
||||||
|
|
||||||
create_user_db(username, password)
|
|
||||||
|
|
||||||
return 'True'
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/searchbox/')
|
@app.route('/searchbox/')
|
||||||
def searchbox():
|
def searchbox():
|
||||||
return render_template("searchbox.html")
|
return render_template("searchbox.html")
|
||||||
|
|
|
@ -3,60 +3,21 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import redis
|
|
||||||
import configparser
|
|
||||||
|
|
||||||
import bcrypt
|
|
||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
# Import config
|
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/'))
|
||||||
sys.path.append('./modules/')
|
sys.path.append('./modules/')
|
||||||
|
|
||||||
def get_all_role():
|
from Role_Manager import create_user_db, get_default_admin_token
|
||||||
return r_serv_db.zrange('ail:all_role', 0 , -1)
|
|
||||||
|
|
||||||
def hashing_password(bytes_password):
|
|
||||||
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
|
|
||||||
return hashed
|
|
||||||
|
|
||||||
def create_user_db(username_id , password, default=False, role=None, update=False):
|
|
||||||
password = password.encode()
|
|
||||||
password_hash = hashing_password(password)
|
|
||||||
r_serv_db.hset('user:all', username_id, password_hash)
|
|
||||||
if update:
|
|
||||||
r_serv_db.hdel('user_metadata:{}'.format(username_id), 'change_passwd')
|
|
||||||
else:
|
|
||||||
if default:
|
|
||||||
r_serv_db.hset('user_metadata:{}'.format(username_id), 'change_passwd', True)
|
|
||||||
r_serv_db.hset('user_metadata:{}'.format(username_id), 'role', role)
|
|
||||||
if role:
|
|
||||||
if role in get_all_role():
|
|
||||||
r_serv_db.sadd('user_role:{}'.format(role), username_id)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
configfile = os.path.join(os.environ['AIL_BIN'], 'packages/config.cfg')
|
|
||||||
if not os.path.exists(configfile):
|
|
||||||
raise Exception('Unable to find the configuration file. \
|
|
||||||
Did you set environment variables? \
|
|
||||||
Or activate the virtualenv.')
|
|
||||||
|
|
||||||
cfg = configparser.ConfigParser()
|
|
||||||
cfg.read(configfile)
|
|
||||||
|
|
||||||
r_serv_db = redis.StrictRedis(
|
|
||||||
host=cfg.get("ARDB_DB", "host"),
|
|
||||||
port=cfg.getint("ARDB_DB", "port"),
|
|
||||||
db=cfg.getint("ARDB_DB", "db"),
|
|
||||||
decode_responses=True)
|
|
||||||
|
|
||||||
username = 'admin@admin.test'
|
username = 'admin@admin.test'
|
||||||
password = secrets.token_urlsafe()
|
password = secrets.token_urlsafe()
|
||||||
create_user_db(username, password, role='admin', default=True)
|
create_user_db(username, password, role='admin', default=True)
|
||||||
|
token = get_default_admin_token()
|
||||||
# create user token
|
|
||||||
token = secrets.token_urlsafe(41)
|
|
||||||
r_serv_db.hset('user:tokens', token, username)
|
|
||||||
r_serv_db.hset('user_metadata:{}'.format(username), 'token', token)
|
|
||||||
|
|
||||||
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
|
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
|
||||||
to_write_str = '# Password Generated by default\n# This file is deleted after the first login\n#\nemail=admin@admin.test\npassword='
|
to_write_str = '# Password Generated by default\n# This file is deleted after the first login\n#\nemail=admin@admin.test\npassword='
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
import configparser
|
import configparser
|
||||||
import redis
|
import redis
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# FLASK #
|
# FLASK #
|
||||||
|
@ -176,9 +175,6 @@ max_dashboard_logs = int(cfg.get("Flask", "max_dashboard_logs"))
|
||||||
|
|
||||||
crawler_enabled = cfg.getboolean("Crawler", "activate_crawler")
|
crawler_enabled = cfg.getboolean("Crawler", "activate_crawler")
|
||||||
|
|
||||||
regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,}$'
|
|
||||||
regex_password = re.compile(regex_password)
|
|
||||||
|
|
||||||
# VT
|
# VT
|
||||||
try:
|
try:
|
||||||
from virusTotalKEYS import vt_key
|
from virusTotalKEYS import vt_key
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*-coding:UTF-8 -*
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import redis
|
import redis
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import secrets
|
import secrets
|
||||||
|
@ -31,6 +32,15 @@ r_serv_db = redis.StrictRedis(
|
||||||
db=cfg.getint("ARDB_DB", "db"),
|
db=cfg.getint("ARDB_DB", "db"),
|
||||||
decode_responses=True)
|
decode_responses=True)
|
||||||
|
|
||||||
|
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
|
||||||
|
|
||||||
|
regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,100}$'
|
||||||
|
regex_password = re.compile(regex_password)
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
############### CHECK ROLE ACCESS ##################
|
||||||
|
###############################################################
|
||||||
|
|
||||||
def login_admin(func):
|
def login_admin(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def decorated_view(*args, **kwargs):
|
def decorated_view(*args, **kwargs):
|
||||||
|
@ -57,7 +67,11 @@ def login_analyst(func):
|
||||||
###############################################################
|
###############################################################
|
||||||
###############################################################
|
###############################################################
|
||||||
|
|
||||||
|
def get_default_admin_token():
|
||||||
|
if r_serv_db.exists('user_metadata:admin@admin.test'):
|
||||||
|
return r_serv_db.hget('user_metadata:admin@admin.test', 'token')
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
def create_user_db(username_id , password, default=False, role=None, update=False):
|
def create_user_db(username_id , password, default=False, role=None, update=False):
|
||||||
password = password.encode()
|
password = password.encode()
|
||||||
|
@ -70,6 +84,9 @@ def create_user_db(username_id , password, default=False, role=None, update=Fals
|
||||||
|
|
||||||
if update:
|
if update:
|
||||||
r_serv_db.hdel('user_metadata:{}'.format(username_id), 'change_passwd')
|
r_serv_db.hdel('user_metadata:{}'.format(username_id), 'change_passwd')
|
||||||
|
# remove default user password file
|
||||||
|
if username_id=='admin@admin.test':
|
||||||
|
os.remove(default_passwd_file)
|
||||||
else:
|
else:
|
||||||
if default:
|
if default:
|
||||||
r_serv_db.hset('user_metadata:{}'.format(username_id), 'change_passwd', True)
|
r_serv_db.hset('user_metadata:{}'.format(username_id), 'change_passwd', True)
|
||||||
|
@ -93,22 +110,17 @@ def edit_user_db(user_id, role, password=None):
|
||||||
|
|
||||||
if current_role < request_level:
|
if current_role < request_level:
|
||||||
role_to_remove = get_user_role_by_range(current_role -1, request_level - 2)
|
role_to_remove = get_user_role_by_range(current_role -1, request_level - 2)
|
||||||
print('to remove')
|
|
||||||
print(role_to_remove)
|
|
||||||
for role_id in role_to_remove:
|
for role_id in role_to_remove:
|
||||||
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
|
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
|
||||||
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
|
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
|
||||||
else:
|
else:
|
||||||
role_to_add = get_user_role_by_range(request_level -1, current_role)
|
role_to_add = get_user_role_by_range(request_level -1, current_role)
|
||||||
print('to add')
|
|
||||||
print(role_to_add)
|
|
||||||
for role_id in role_to_add:
|
for role_id in role_to_add:
|
||||||
r_serv_db.sadd('user_role:{}'.format(role_id), user_id)
|
r_serv_db.sadd('user_role:{}'.format(role_id), user_id)
|
||||||
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
|
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
|
||||||
|
|
||||||
def delete_user_db(user_id):
|
def delete_user_db(user_id):
|
||||||
if r_serv_db.exists('user_metadata:{}'.format(user_id)):
|
if r_serv_db.exists('user_metadata:{}'.format(user_id)):
|
||||||
print('r')
|
|
||||||
role_to_remove =get_all_role()
|
role_to_remove =get_all_role()
|
||||||
for role_id in role_to_remove:
|
for role_id in role_to_remove:
|
||||||
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
|
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
|
||||||
|
@ -121,6 +133,13 @@ def hashing_password(bytes_password):
|
||||||
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
|
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
|
||||||
return hashed
|
return hashed
|
||||||
|
|
||||||
|
def check_password_strength(password):
|
||||||
|
result = regex_password.match(password)
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def get_all_role():
|
def get_all_role():
|
||||||
return r_serv_db.zrange('ail:all_role', 0, -1)
|
return r_serv_db.zrange('ail:all_role', 0, -1)
|
||||||
|
|
||||||
|
@ -132,6 +151,4 @@ def get_all_user_role(user_role):
|
||||||
return r_serv_db.zrange('ail:all_role', current_role_val -1, -1)
|
return r_serv_db.zrange('ail:all_role', current_role_val -1, -1)
|
||||||
|
|
||||||
def get_user_role_by_range(inf, sup):
|
def get_user_role_by_range(inf, sup):
|
||||||
print(inf)
|
|
||||||
print(sup)
|
|
||||||
return r_serv_db.zrange('ail:all_role', inf, sup)
|
return r_serv_db.zrange('ail:all_role', inf, sup)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
|
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
from Role_Manager import login_admin, login_analyst, create_user_db, edit_user_db, delete_user_db
|
from Role_Manager import login_admin, login_analyst, create_user_db, edit_user_db, delete_user_db, check_password_strength
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import secrets
|
import secrets
|
||||||
|
@ -26,7 +26,6 @@ max_preview_char = Flask_config.max_preview_char
|
||||||
max_preview_modal = Flask_config.max_preview_modal
|
max_preview_modal = Flask_config.max_preview_modal
|
||||||
REPO_ORIGIN = Flask_config.REPO_ORIGIN
|
REPO_ORIGIN = Flask_config.REPO_ORIGIN
|
||||||
dict_update_description = Flask_config.dict_update_description
|
dict_update_description = Flask_config.dict_update_description
|
||||||
regex_password = Flask_config.regex_password
|
|
||||||
|
|
||||||
settings = Blueprint('settings', __name__, template_folder='templates')
|
settings = Blueprint('settings', __name__, template_folder='templates')
|
||||||
|
|
||||||
|
@ -36,13 +35,6 @@ settings = Blueprint('settings', __name__, template_folder='templates')
|
||||||
def one():
|
def one():
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def check_password_strength(password):
|
|
||||||
result = regex_password.match(password)
|
|
||||||
if result:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def generate_new_token(user_id):
|
def generate_new_token(user_id):
|
||||||
# create user token
|
# create user token
|
||||||
current_token = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
|
current_token = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
|
||||||
|
@ -162,7 +154,7 @@ def create_user_post():
|
||||||
|
|
||||||
all_roles = get_all_roles()
|
all_roles = get_all_roles()
|
||||||
|
|
||||||
if email and role:
|
if email and len(email)< 300 and role:
|
||||||
if role in all_roles:
|
if role in all_roles:
|
||||||
# password set
|
# password set
|
||||||
if password1 and password2:
|
if password1 and password2:
|
||||||
|
@ -206,7 +198,6 @@ def users_list():
|
||||||
new_user_dict['email'] = new_user
|
new_user_dict['email'] = new_user
|
||||||
new_user_dict['edited'] = request.args.get('new_user_edited')
|
new_user_dict['edited'] = request.args.get('new_user_edited')
|
||||||
new_user_dict['password'] = request.args.get('new_user_password')
|
new_user_dict['password'] = request.args.get('new_user_password')
|
||||||
print(new_user)
|
|
||||||
return render_template("users_list.html", all_users=all_users, new_user=new_user_dict)
|
return render_template("users_list.html", all_users=all_users, new_user=new_user_dict)
|
||||||
|
|
||||||
@settings.route("/settings/edit_user", methods=['GET'])
|
@settings.route("/settings/edit_user", methods=['GET'])
|
||||||
|
|
|
@ -83,6 +83,10 @@
|
||||||
Digits: 0-9
|
Digits: 0-9
|
||||||
<span class="badge badge-primary badge-pill">2</span>
|
<span class="badge badge-primary badge-pill">2</span>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Maximum length
|
||||||
|
<span class="badge badge-primary badge-pill">100</span>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$("#nav_edit_profile").addClass("active");
|
$("#nav_users_list").addClass("active");
|
||||||
$("#nav_user_management").removeClass("text-muted");
|
$("#nav_user_management").removeClass("text-muted");
|
||||||
} );
|
} );
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -91,6 +91,10 @@
|
||||||
Digits: 0-9
|
Digits: 0-9
|
||||||
<span class="badge badge-primary badge-pill">2</span>
|
<span class="badge badge-primary badge-pill">2</span>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Maximum length
|
||||||
|
<span class="badge badge-primary badge-pill">100</span>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</h5>
|
</h5>
|
||||||
<ul class="nav flex-md-column flex-row navbar-nav justify-content-between w-100"> <!--nav-pills-->
|
<ul class="nav flex-md-column flex-row navbar-nav justify-content-between w-100"> <!--nav-pills-->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{url_for('hashDecoded.hashDecoded_page')}}" id="nav_server_status">
|
<a class="nav-link" href="{{url_for('settings.settings_page')}}" id="nav_server_status">
|
||||||
<i class="fas fa-tools"></i>
|
<i class="fas fa-tools"></i>
|
||||||
<span>Server Status</span>
|
<span>Server Status</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
Loading…
Reference in a new issue