chg: [UI] add user management

pull/24/head
Terrtia 2019-08-14 12:53:51 +02:00
parent 113159f820
commit c8d2b8cb95
No known key found for this signature in database
GPG Key ID: 1E1B1F50D84613D0
9 changed files with 777 additions and 10 deletions

View File

@ -7,12 +7,35 @@
D4 core server is a complete server to handle clients (sensors) including the decapsulation of the [D4 protocol](https://github.com/D4-project/architecture/tree/master/format), control of
sensor registrations, management of decoding protocols and dispatching to adequate decoders/analysers.
## Database map
## Database map - Metadata
| Key | Value |
| --- | --- |
| | |
| | | |
```
DB 0 - Stats + sensor configs
DB 1 - Users
DB 2 - Analyzer queue
```
### DB 1
##### User Management:
| Hset Key | Field | Value |
| ------ | ------ | ------ |
| user:all | **user id** | **password hash** |
| | | |
| user:tokens | **token** | **user id** |
| | | |
| user_metadata:**user id** | token | **token** |
| | change_passwd | **boolean** |
| | role | **role** |
| Set Key | Value |
| ------ | ------ |
| user_role:**role** | **user id** |
| Zrank Key | Field | Value |
| ------ | ------ | ------ |
| ail:all_role | **role** | **int, role priority (1=admin)** |
### Server
| Key | Value |

64
server/lib/User.py Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
# -*-coding:UTF-8 -*
import os
import redis
import bcrypt
from flask_login import UserMixin
class User(UserMixin):
def __init__(self, id):
host_redis_metadata = os.getenv('D4_REDIS_METADATA_HOST', "localhost")
port_redis_metadata = int(os.getenv('D4_REDIS_METADATA_PORT', 6380))
self.r_serv_db = redis.StrictRedis(
host=host_redis_metadata,
port=port_redis_metadata,
db=1,
decode_responses=True)
if self.r_serv_db.hexists('user:all', id):
self.id = id
else:
self.id = "__anonymous__"
# return True or False
#def is_authenticated():
# return True or False
#def is_anonymous():
@classmethod
def get(self_class, id):
return self_class(id)
def user_is_anonymous(self):
if self.id == "__anonymous__":
return True
else:
return False
def check_password(self, password):
if self.user_is_anonymous():
return False
password = password.encode()
hashed_password = self.r_serv_db.hget('user:all', self.id).encode()
if bcrypt.checkpw(password, hashed_password):
return True
else:
return False
def request_password_change(self):
if self.r_serv_db.hget('user_metadata:{}'.format(self.id), 'change_passwd') == 'True':
return True
else:
return False
def is_in_role(self, role):
if self.r_serv_db.sismember('user_role:{}'.format(role), self.id):
return True
else:
return False

View File

@ -1,6 +1,8 @@
twisted[tls]
redis
flask
flask-login
bcrypt
#sudo python3 -m pip install --upgrade service_identity

View File

@ -3,12 +3,14 @@
import os
import re
import ssl
import sys
import uuid
import time
import json
import redis
import time
import uuid
import flask
import redis
import random
import datetime
import ipaddress
import configparser
@ -16,6 +18,17 @@ import configparser
import subprocess
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
import bcrypt
# Import Role_Manager
from Role_Manager import create_user_db, check_password_strength, check_user_role_integrity
from Role_Manager import login_admin, login_analyst
sys.path.append(os.path.join(os.environ['D4_HOME'], 'lib'))
from User import User
baseUrl = ''
if baseUrl != '':
@ -59,6 +72,12 @@ redis_server_metadata = redis.StrictRedis(
db=0,
decode_responses=True)
redis_users = redis.StrictRedis(
host=host_redis_metadata,
port=port_redis_metadata,
db=1,
decode_responses=True)
redis_server_analyzer = redis.StrictRedis(
host=host_redis_metadata,
port=port_redis_metadata,
@ -71,9 +90,31 @@ json_type_description = {}
for type_info in json_type:
json_type_description[type_info['type']] = type_info
Flask_dir = os.path.join(os.environ['D4_HOME'], 'web')
# ========= TLS =========#
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain(certfile=os.path.join(Flask_dir, 'server.crt'), keyfile=os.path.join(Flask_dir, 'server.key'))
#print(ssl_context.get_ciphers())
# ========= =========#
app = Flask(__name__, static_url_path=baseUrl+'/static/')
app.config['MAX_CONTENT_LENGTH'] = 900 * 1024 * 1024
# ========= session ========
app.secret_key = str(random.getrandbits(256))
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.init_app(app)
# ========= =========#
# ========= LOGIN MANAGER ========
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
# ========= =========#
# ========== FUNCTIONS ============
def is_valid_uuid_v4(header_uuid):
try:
@ -195,19 +236,137 @@ def get_uuid_disk_statistics(uuid_name, date_day='', type='', all_types_on_disk=
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
# API - JSON
if request.path.startswith('/api/'):
return Response(json.dumps({"status": "error", "reason": "404 Not Found"}, indent=2, sort_keys=True), mimetype='application/json'), 404
# UI - HTML Template
else:
return render_template('404.html'), 404
@app.errorhandler(405)
def _handle_client_error(e):
if request.path.startswith('/api/'):
res_dict = {"status": "error", "reason": "Method Not Allowed: The method is not allowed for the requested URL"}
anchor_id = request.path[8:]
anchor_id = anchor_id.replace('/', '_')
api_doc_url = 'https://d4-project.org#{}'.format(anchor_id)
res_dict['documentation'] = api_doc_url
return Response(json.dumps(res_dict, indent=2, sort_keys=True), mimetype='application/json'), 405
else:
return
# ========== ROUTES ============
@app.route('/login', methods=['POST', 'GET'])
def login():
'''
current_ip = request.remote_addr
login_failed_ip = r_cache.get('failed_login_ip:{}'.format(current_ip))
# brute force by ip
if login_failed_ip:
login_failed_ip = int(login_failed_ip)
if login_failed_ip >= 5:
error = 'Max Connection Attempts reached, Please wait {}s'.format(r_cache.ttl('failed_login_ip:{}'.format(current_ip)))
return render_template("login.html", error=error)
'''
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
#next_page = request.form.get('next_page')
if username is not None:
user = User.get(username)
'''
login_failed_user_id = r_cache.get('failed_login_user_id:{}'.format(username))
# brute force by user_id
if login_failed_user_id:
login_failed_user_id = int(login_failed_user_id)
if login_failed_user_id >= 5:
error = 'Max Connection Attempts reached, Please wait {}s'.format(r_cache.ttl('failed_login_user_id:{}'.format(username)))
return render_template("login.html", error=error)
'''
if user and user.check_password(password):
#if not check_user_role_integrity(user.get_id()):
# error = 'Incorrect User ACL, Please contact your administrator'
# return render_template("login.html", error=error)
login_user(user) ## TODO: use remember me ?
if user.request_password_change():
return redirect(url_for('change_password'))
else:
return redirect(url_for('index'))
# login failed
else:
# set brute force protection
#logger.warning("Login failed, ip={}, username={}".format(current_ip, username))
#r_cache.incr('failed_login_ip:{}'.format(current_ip))
#r_cache.expire('failed_login_ip:{}'.format(current_ip), 300)
#r_cache.incr('failed_login_user_id:{}'.format(username))
#r_cache.expire('failed_login_user_id:{}'.format(username), 300)
#
error = 'Password Incorrect'
return render_template("login.html", error=error)
return 'please provide a valid username'
else:
#next_page = request.args.get('next')
error = request.args.get('error')
return render_template("login.html" , error=error)
@app.route('/change_password', methods=['POST', 'GET'])
@login_required
def change_password():
password1 = request.form.get('password1')
password2 = request.form.get('password2')
error = request.args.get('error')
if error:
return render_template("change_password.html", error=error)
if current_user.is_authenticated and password1!=None:
if password1==password2:
if check_password_strength(password1):
user_id = current_user.get_id()
create_user_db(user_id , password1, update=True)
return redirect(url_for('index'))
else:
error = 'Incorrect password'
return render_template("change_password.html", error=error)
else:
error = "Passwords don't match"
return render_template("change_password.html", error=error)
else:
error = 'Please choose a new password'
return render_template("change_password.html", error=error)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
# role error template
@app.route('/role', methods=['POST', 'GET'])
@login_required
def role():
return render_template("error/403.html"), 403
@app.route('/test')
def test():
return 'test'
@app.route('/')
@login_required
def index():
date = datetime.datetime.now().strftime("%Y/%m/%d")
return render_template("index.html", date=date)
@app.route('/_json_daily_uuid_stats')
@login_required
def _json_daily_uuid_stats():
date = datetime.datetime.now().strftime("%Y%m%d")
daily_uuid = redis_server_metadata.zrange('daily_uuid:{}'.format(date), 0, -1, withscores=True)
@ -219,6 +378,7 @@ def _json_daily_uuid_stats():
return jsonify(data_daily_uuid)
@app.route('/_json_daily_type_stats')
@login_required
def _json_daily_type_stats():
date = datetime.datetime.now().strftime("%Y%m%d")
daily_uuid = redis_server_metadata.zrange('daily_type:{}'.format(date), 0, -1, withscores=True)
@ -235,6 +395,7 @@ def _json_daily_type_stats():
return jsonify(data_daily_uuid)
@app.route('/sensors_status')
@login_required
def sensors_status():
active_connection_filter = request.args.get('active_connection_filter')
if active_connection_filter is None:
@ -314,6 +475,7 @@ def sensors_status():
active_connection_filter=active_connection_filter)
@app.route('/show_active_uuid')
@login_required
def show_active_uuid():
#swap switch value
active_connection_filter = request.args.get('show_active_connection')
@ -328,6 +490,7 @@ def show_active_uuid():
return redirect(url_for('sensors_status', active_connection_filter=active_connection_filter))
@app.route('/server_management')
@login_required
def server_management():
blacklisted_ip = request.args.get('blacklisted_ip')
unblacklisted_ip = request.args.get('unblacklisted_ip')
@ -398,6 +561,7 @@ def server_management():
blacklisted_uuid=blacklisted_uuid, unblacklisted_uuid=unblacklisted_uuid)
@app.route('/uuid_management')
@login_required
def uuid_management():
uuid_sensor = request.args.get('uuid')
if is_valid_uuid_v4(uuid_sensor):
@ -470,6 +634,7 @@ def uuid_management():
return 'Invalid uuid'
@app.route('/blacklisted_ip')
@login_required
def blacklisted_ip():
blacklisted_ip = request.args.get('blacklisted_ip')
unblacklisted_ip = request.args.get('unblacklisted_ip')
@ -495,6 +660,7 @@ def blacklisted_ip():
unblacklisted_ip=unblacklisted_ip, blacklisted_ip=blacklisted_ip)
@app.route('/blacklisted_uuid')
@login_required
def blacklisted_uuid():
blacklisted_uuid = request.args.get('blacklisted_uuid')
unblacklisted_uuid = request.args.get('unblacklisted_uuid')
@ -521,6 +687,7 @@ def blacklisted_uuid():
@app.route('/uuid_change_stream_max_size')
@login_required
def uuid_change_stream_max_size():
uuid_sensor = request.args.get('uuid')
user = request.args.get('redirect')
@ -539,6 +706,7 @@ def uuid_change_stream_max_size():
return 'Invalid uuid'
@app.route('/uuid_change_description')
@login_required
def uuid_change_description():
uuid_sensor = request.args.get('uuid')
description = request.args.get('description')
@ -550,6 +718,7 @@ def uuid_change_description():
# # TODO: check analyser uuid dont exist
@app.route('/add_new_analyzer')
@login_required
def add_new_analyzer():
type = request.args.get('type')
user = request.args.get('redirect')
@ -576,6 +745,7 @@ def add_new_analyzer():
return 'Invalid uuid'
@app.route('/empty_analyzer_queue')
@login_required
def empty_analyzer_queue():
analyzer_uuid = request.args.get('analyzer_uuid')
type = request.args.get('type')
@ -598,6 +768,7 @@ def empty_analyzer_queue():
return 'Invalid uuid'
@app.route('/remove_analyzer')
@login_required
def remove_analyzer():
analyzer_uuid = request.args.get('analyzer_uuid')
type = request.args.get('type')
@ -623,6 +794,7 @@ def remove_analyzer():
return 'Invalid uuid'
@app.route('/analyzer_change_max_size')
@login_required
def analyzer_change_max_size():
analyzer_uuid = request.args.get('analyzer_uuid')
user = request.args.get('redirect')
@ -641,6 +813,7 @@ def analyzer_change_max_size():
return 'Invalid uuid'
@app.route('/kick_uuid')
@login_required
def kick_uuid():
uuid_sensor = request.args.get('uuid')
if is_valid_uuid_v4(uuid_sensor):
@ -650,6 +823,7 @@ def kick_uuid():
return 'Invalid uuid'
@app.route('/blacklist_uuid')
@login_required
def blacklist_uuid():
uuid_sensor = request.args.get('uuid')
user = request.args.get('redirect')
@ -670,6 +844,7 @@ def blacklist_uuid():
return 'Invalid uuid'
@app.route('/unblacklist_uuid')
@login_required
def unblacklist_uuid():
uuid_sensor = request.args.get('uuid')
user = request.args.get('redirect')
@ -693,6 +868,7 @@ def unblacklist_uuid():
return 'Invalid uuid'
@app.route('/blacklist_ip')
@login_required
def blacklist_ip():
ip = request.args.get('ip')
user = request.args.get('redirect')
@ -718,6 +894,7 @@ def blacklist_ip():
return 'Invalid ip'
@app.route('/unblacklist_ip')
@login_required
def unblacklist_ip():
ip = request.args.get('ip')
user = request.args.get('redirect')
@ -745,6 +922,7 @@ def unblacklist_ip():
return 'Invalid ip'
@app.route('/blacklist_ip_by_uuid')
@login_required
def blacklist_ip_by_uuid():
uuid_sensor = request.args.get('uuid')
user = request.args.get('redirect')
@ -756,6 +934,7 @@ def blacklist_ip_by_uuid():
return 'Invalid uuid'
@app.route('/unblacklist_ip_by_uuid')
@login_required
def unblacklist_ip_by_uuid():
uuid_sensor = request.args.get('uuid')
user = request.args.get('redirect')
@ -767,6 +946,7 @@ def unblacklist_ip_by_uuid():
return 'Invalid uuid'
@app.route('/add_accepted_type')
@login_required
def add_accepted_type():
type = request.args.get('type')
extended_type_name = request.args.get('extended_type_name')
@ -786,6 +966,7 @@ def add_accepted_type():
return 'Invalid type'
@app.route('/remove_accepted_type')
@login_required
def remove_accepted_type():
type = request.args.get('type')
user = request.args.get('redirect')
@ -798,6 +979,7 @@ def remove_accepted_type():
return 'Invalid type'
@app.route('/remove_accepted_extended_type')
@login_required
def remove_accepted_extended_type():
type_name = request.args.get('type_name')
redis_server_metadata.srem('server:accepted_extended_type', type_name)
@ -805,6 +987,7 @@ def remove_accepted_extended_type():
# demo function
@app.route('/delete_data')
@login_required
def delete_data():
date = datetime.datetime.now().strftime("%Y%m%d")
redis_server_metadata.delete('daily_type:{}'.format(date))
@ -813,6 +996,7 @@ def delete_data():
# demo function
@app.route('/set_uuid_hmac_key')
@login_required
def set_uuid_hmac_key():
uuid_sensor = request.args.get('uuid')
user = request.args.get('redirect')
@ -824,6 +1008,7 @@ def set_uuid_hmac_key():
# demo function
@app.route('/whois_data')
@login_required
def whois_data():
ip = request.args.get('ip')
if is_valid_ip:
@ -832,11 +1017,13 @@ def whois_data():
return 'Invalid IP'
@app.route('/generate_uuid')
@login_required
def generate_uuid():
new_uuid = uuid.uuid4()
return jsonify({'uuid': new_uuid})
@app.route('/get_analyser_sample')
@login_required
def get_analyser_sample():
type = request.args.get('type')
analyzer_uuid = request.args.get('analyzer_uuid')
@ -864,6 +1051,7 @@ def get_analyser_sample():
return jsonify('Incorrect UUID')
@app.route('/get_uuid_type_history_json')
@login_required
def get_uuid_type_history_json():
uuid_sensor = request.args.get('uuid_sensor')
if is_valid_uuid_v4(uuid_sensor):
@ -894,6 +1082,7 @@ def get_uuid_type_history_json():
return jsonify('Incorrect UUID')
@app.route('/get_uuid_stats_history_json')
@login_required
def get_uuid_stats_history_json():
uuid_sensor = request.args.get('uuid_sensor')
stats = request.args.get('stats')
@ -925,4 +1114,4 @@ def get_uuid_stats_history_json():
if __name__ == "__main__":
app.run(host='0.0.0.0', port=7000, threaded=True)
app.run(host='0.0.0.0', port=7000, threaded=True, ssl_context=ssl_context)

183
server/web/Role_Manager.py Normal file
View File

@ -0,0 +1,183 @@
#!/usr/bin/env python3
# -*-coding:UTF-8 -*
import os
import re
import redis
import bcrypt
from functools import wraps
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
from flask import request, current_app
login_manager = LoginManager()
login_manager.login_view = 'role'
host_redis_metadata = os.getenv('D4_REDIS_METADATA_HOST', "localhost")
port_redis_metadata = int(os.getenv('D4_REDIS_METADATA_PORT', 6380))
r_serv_db = redis.StrictRedis(
host=host_redis_metadata,
port=port_redis_metadata,
db=1,
decode_responses=True)
default_passwd_file = os.path.join(os.environ['D4_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):
@wraps(func)
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('admin')):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
def login_analyst(func):
@wraps(func)
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated:
return login_manager.unauthorized()
elif (not current_user.is_in_role('analyst')):
return login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
###############################################################
###############################################################
###############################################################
def gen_password(length=30, charset="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_!@#$%^&*()"):
random_bytes = os.urandom(length)
len_charset = len(charset)
indices = [int(len_charset * (byte / 256.0)) for byte in random_bytes]
return "".join([charset[index] for index in indices])
def gen_token(length=41, charset="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"):
random_bytes = os.urandom(length)
len_charset = len(charset)
indices = [int(len_charset * (byte / 256.0)) for byte in random_bytes]
return "".join([charset[index] for index in indices])
def generate_new_token(user_id):
# create user token
current_token = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
if current_token:
r_serv_db.hdel('user:tokens', current_token)
token = gen_token(41)
r_serv_db.hset('user:tokens', token, user_id)
r_serv_db.hset('user_metadata:{}'.format(user_id), 'token', token)
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):
password = password.encode()
password_hash = hashing_password(password)
# create user token
generate_new_token(username_id)
if update:
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:
if default:
r_serv_db.hset('user_metadata:{}'.format(username_id), 'change_passwd', 'True')
if role:
if role in get_all_role():
for role_to_add in get_all_user_role(role):
r_serv_db.sadd('user_role:{}'.format(role_to_add), username_id)
r_serv_db.hset('user_metadata:{}'.format(username_id), 'role', role)
r_serv_db.hset('user:all', username_id, password_hash)
def edit_user_db(user_id, role, password=None):
if password:
password_hash = hashing_password(password.encode())
r_serv_db.hset('user:all', user_id, password_hash)
current_role = r_serv_db.hget('user_metadata:{}'.format(user_id), 'role')
if role != current_role:
request_level = get_role_level(role)
current_role = get_role_level(current_role)
if current_role < request_level:
role_to_remove = get_user_role_by_range(current_role -1, request_level - 2)
for role_id in role_to_remove:
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
else:
role_to_add = get_user_role_by_range(request_level -1, current_role)
for role_id in role_to_add:
r_serv_db.sadd('user_role:{}'.format(role_id), user_id)
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
def delete_user_db(user_id):
if r_serv_db.exists('user_metadata:{}'.format(user_id)):
role_to_remove =get_all_role()
for role_id in role_to_remove:
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
user_token = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
r_serv_db.hdel('user:tokens', user_token)
r_serv_db.delete('user_metadata:{}'.format(user_id))
r_serv_db.hdel('user:all', user_id)
def hashing_password(bytes_password):
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
return hashed
def check_password_strength(password):
result = regex_password.match(password)
if result:
return True
else:
return False
def get_all_role():
return r_serv_db.zrange('d4:all_role', 0, -1)
def get_role_level(role):
return int(r_serv_db.zscore('d4:all_role', role))
def get_all_user_role(user_role):
current_role_val = get_role_level(user_role)
return r_serv_db.zrange('d4:all_role', current_role_val -1, -1)
def get_all_user_upper_role(user_role):
current_role_val = get_role_level(user_role)
# remove one rank
if current_role_val > 1:
return r_serv_db.zrange('d4:all_role', 0, current_role_val -2)
else:
return []
def get_user_role_by_range(inf, sup):
return r_serv_db.zrange('d4:all_role', inf, sup)
def get_user_role(user_id):
return r_serv_db.hget('user_metadata:{}'.format(user_id), 'role')
def check_user_role_integrity(user_id):
user_role = get_user_role(user_id)
all_user_role = get_all_user_role(user_role)
res = True
if user_role not in all_user_role:
return False
return res

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# -*-coding:UTF-8 -*
import os
import sys
import redis
import configparser
sys.path.append(os.path.join(os.environ['D4_HOME'], 'lib'))
from Role_Manager import create_user_db, edit_user_db, get_default_admin_token, gen_password
host_redis_metadata = os.getenv('D4_REDIS_METADATA_HOST', "localhost")
port_redis_metadata = int(os.getenv('D4_REDIS_METADATA_HOST', 6380))
r_serv = redis.StrictRedis(
host=host_redis_metadata,
port=port_redis_metadata,
db=1,
decode_responses=True)
if __name__ == "__main__":
# create role_list
if not r_serv.exists('d4:all_role'):
role_dict = {'admin': 1, 'user': 1, 'sensor_register': 20}
r_serv.zadd('d4:all_role', role_dict)
username = 'admin@admin.test'
password = gen_password()
if r_serv.exists('user_metadata:admin@admin.test'):
edit_user_db(username, password=password, role='admin')
else:
create_user_db(username, password, role='admin', default=True)
token = get_default_admin_token()
default_passwd_file = os.path.join(os.environ['D4_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 = to_write_str + password + '\nAPI_Key=' + token
with open(default_passwd_file, 'w') as f:
f.write(to_write_str)
print('new user created: {}'.format(username))
print('password: {}'.format(password))
print('token: {}'.format(token))

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>403 - D4-Project</title>
<link rel="icon" href="{{ url_for('static', filename='image/d4-logo.png') }}">
<!-- Core CSS -->
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='font-awesome/css/font-awesome.css') }}" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="{{ url_for('index') }}">
<img src="{{ url_for('static', filename='img/d4-logo.png')}}" alt="D4 Project" style="width:80px;">
</a>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link mr-3" href="{{ url_for('index') }}">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item" mr-3>
<a class="nav-link mr-3" href="{{ url_for('sensors_status') }}">Sensors Status</a>
</li>
<li class="nav-item mr-3">
<a class="nav-link" href="{{ url_for('server_management') }}" tabindex="-1" aria-disabled="true">Server Management</a>
</li>
</ul>
</nav>
<div>
<br>
<br>
<h1 class="text-center">403 Forbidden</h1>
</div>
<br>
<br>
<br>
<br>
<div class="d-flex justify-content-center">
<pre>
,d8 ,a8888a, ad888888b,
,d888 ,8P"' `"Y8, d8" "88
,d8" 88 ,8P Y8, a8P
,d8" 88 88 88 aad8"
,d8" 88 88 88 ""Y8,
8888888888888 `8b d8' "8b
88 `8ba, ,ad8' Y8, a88
88 "Y8888P" "Y888888P'
88888888888 88 88 88 88
88 88 "" 88 88
88 88 88 88
88aaaaa ,adPPYba, 8b,dPPYba, 88,dPPYba, 88 ,adPPYb,88 ,adPPYb,88 ,adPPYba, 8b,dPPYba,
88""""" a8" "8a 88P' "Y8 88P' "8a 88 a8" `Y88 a8" `Y88 a8P_____88 88P' `"8a
88 8b d8 88 88 d8 88 8b 88 8b 88 8PP""""""" 88 88
88 "8a, ,a8" 88 88b, ,a8" 88 "8a, ,d88 "8a, ,d88 "8b, ,aa 88 88
88 `"YbbdP"' 88 8Y"Ybbd8"' 88 `"8bbdP"Y8 `"8bbdP"Y8 `"Ybbd8"' 88 88
</pre>
</div>
{% include 'navfooter.html' %}
<body>
</html>

View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>D4-Project</title>
<link rel="icon" href="{{ url_for('static', filename='img/d4-logo.png')}}">
<!-- Core CSS -->
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='font-awesome/css/font-awesome.css') }}" rel="stylesheet">
<!-- JS -->
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
<script src="{{ url_for('static', filename='js/bootstrap.min.js')}}"></script>
<style>
html,
body {
height: 100%;
}
body {
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
width: 100%;
max-width: 330px;
padding: 15px;
margin: auto;
}
.form-signin .checkbox {
font-weight: 400;
}
.form-signin .form-control {
position: relative;
box-sizing: border-box;
height: auto;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>
</head>
<body class="text-center">
<form class="form-signin" action="{{ url_for('change_password')}}" autocomplete="off" method="post">
<img class="mb-4" src="{{ url_for('static', filename='img/d4-logo.png')}}" width="300">
<h1 class="h3 mb-3 text-secondary">Change Password</h1>
<label for="inputPassword1" class="sr-only">Password</label>
<input type="password" id="inputPassword1" name="password1" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Password" autocomplete="new-password" required autofocus>
<label for="inputPassword2" class="sr-only">Confirm Password</label>
<input type="password" id="inputPassword2" name="password2" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Confirm Password" value="" autocomplete="new-password" required>
{% if error %}
<div class="invalid-feedback">
{{error}}
</div>
{% endif %}
<button class="btn btn-lg btn-primary btn-block" type="submit">Submit</button>
<br>
<br>
<br>
<h5 class="h3 mb-3 text-secondary">Password Requirements</h5>
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center">
Minimal length
<span class="badge badge-primary badge-pill">10</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Upper characters: A-Z
<span class="badge badge-primary badge-pill">1</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Lower characters: a-z
<span class="badge badge-primary badge-pill">1</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Digits: 0-9
<span class="badge badge-primary badge-pill">2</span>
</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>
</form>
</body>

View File

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>D4-Project</title>
<link rel="icon" href="{{ url_for('static', filename='img/d4-logo.png')}}">
<!-- Core CSS -->
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='font-awesome/css/font-awesome.css') }}" rel="stylesheet">
<!-- JS -->
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
<script src="{{ url_for('static', filename='js/bootstrap.min.js')}}"></script>
<style>
html,
body {
height: 100%;
}
body {
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
width: 100%;
max-width: 330px;
padding: 15px;
margin: auto;
}
.form-signin .checkbox {
font-weight: 400;
}
.form-signin .form-control {
position: relative;
box-sizing: border-box;
height: auto;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>
</head>
<body class="text-center">
<form class="form-signin" action="{{ url_for('login')}}" method="post">
<img class="mb-4" src="{{ url_for('static', filename='img/d4-logo.png')}}" width="300">
<h1 class="h3 mb-3 text-secondary">Please sign in</h1>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" name="username" class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" name="password" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Password" required>
{% if error %}
<div class="invalid-feedback">
{{error}}
</div>
{% endif %}
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body>