building out databases and config files

This commit is contained in:
Phillip Tarrant 2020-08-12 21:33:36 -04:00
parent 2f12f95ab2
commit 85a69954ea
9 changed files with 188 additions and 18 deletions

3
.gitignore vendored
View File

@ -1,5 +1,6 @@
**/logs
*.log
*.sqlite
__pycache__/
*.py[cod]
@ -15,4 +16,4 @@ venv.bak/
.idea/
app/config/web
app/config/web

View File

@ -17,6 +17,7 @@ logger = logging.getLogger(__name__)
try:
from OpenSSL import crypto
from argon2 import PasswordHasher
except ModuleNotFoundError as e:
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
@ -29,23 +30,24 @@ class Helpers:
self.root_dir = os.path.abspath(os.path.curdir)
self.config_dir = os.path.join(self.root_dir, 'app', 'config')
self.session_file = os.path.join(self.root_dir, 'session.lock')
self.settings_file = os.path.join(self.root_dir, 'config.ini')
self.webroot = os.path.join(self.root_dir, 'app', 'frontend')
self.db_path = os.path.join(self.root_dir, 'app', 'config', 'commander.sqlite')
self.db_path = os.path.join(self.root_dir, 'commander.sqlite')
self.passhasher = PasswordHasher()
self.exiting = False
def get_setting(self, section, key):
config_file = os.path.join(self.config_dir, 'config.ini')
try:
our_config = configparser.ConfigParser()
our_config.read(config_file)
our_config.read(self.settings_file)
if our_config.has_option(section, key):
return our_config[section][key]
except Exception as e:
logger.critical("Config File Error: Unable to read {} due to {}".format(config_file, e))
console.critical("Config File Error: Unable to read {} due to {}".format(config_file, e))
logger.critical("Config File Error: Unable to read {} due to {}".format(self.settings_file, e))
console.critical("Config File Error: Unable to read {} due to {}".format(self.settings_file, e))
return False
@ -82,6 +84,17 @@ class Helpers:
console.critical("Unable to create exit file!")
sys.exit(1)
def encode_pass(self, password):
return self.passhasher.hash(password)
def verify_pass(self, password, currenthash):
try:
self.passhasher.verify(currenthash, password)
return True
except:
pass
return False
@staticmethod
def check_writeable(path: str):
filename = os.path.join(path, "tempfile.txt")
@ -97,20 +110,20 @@ class Helpers:
return False
def ensure_logging_setup(self):
log_file = os.path.join(os.path.curdir, 'app', 'logs', 'commander.log')
log_file = os.path.join(os.path.curdir, 'logs', 'commander.log')
logger.info("Checking app directory writable")
writeable = self.check_writeable(os.path.join(os.path.curdir, 'app'))
writeable = self.check_writeable(self.root_dir)
# if not writeable, let's bomb out
if not writeable:
logger.critical("Unable to write to app directory!")
logger.critical("Unable to write to {} directory!".format(self.root_dir))
sys.exit(1)
# ensure the log directory is there
try:
os.makedirs(os.path.join(os.path.curdir, 'app', 'logs'))
os.makedirs(os.path.join(self.root_dir, 'logs'))
except Exception as e:
pass
@ -121,9 +134,9 @@ class Helpers:
console.critical("Unable to open log file!")
sys.exit(1)
# del any old session.log file as this is a new session
# del any old session.lock file as this is a new session
try:
os.remove(os.path.join(os.path.curdir, "app", "logs", "session.log"))
os.remove(self.session_file)
except:
pass
@ -308,4 +321,5 @@ class Helpers:
"""
return ''.join(random.choice(chars) for x in range(size))
helper = Helpers()

View File

@ -0,0 +1,103 @@
import sys
import logging
import datetime
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
logger = logging.getLogger(__name__)
try:
from peewee import *
from playhouse.shortcuts import model_to_dict
except ModuleNotFoundError as e:
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
console.critical("Import Error: Unable to load {} module".format(e, e.name))
sys.exit(1)
database = SqliteDatabase(helper.db_path, pragmas={
'journal_mode': 'wal',
'cache_size': -1024 * 10})
class BaseModel(Model):
class Meta:
database = database
class Users(BaseModel):
user_id = AutoField()
created = DateTimeField(default=datetime.datetime.now)
last_login = DateTimeField(default=datetime.datetime.now)
last_ip = CharField(default="")
username = CharField(default="")
password = CharField(default="")
enabled = BooleanField(default=True)
api_token = CharField(default="")
allowed_servers = CharField(default="[]")
class Meta:
table_name = "users"
class Host_Stats(BaseModel):
time = DateTimeField(default=datetime.datetime.now)
boot_time = CharField(default="")
cpu_usage = FloatField(default=0)
cpu_cores = IntegerField(default=0)
cpu_cur_freq = FloatField(default=0)
cpu_max_freq = FloatField(default=0)
mem_percent = FloatField(default=0)
mem_usage = CharField(default="")
mem_total = CharField(default="")
disk_percent = FloatField(default=0)
disk_usage = CharField(default="")
disk_total = CharField(default="")
class Meta:
table_name = "host_stats"
class Webhooks(BaseModel):
id = AutoField()
name = CharField(max_length=64, unique=True)
method = CharField(default="POST")
url = CharField(unique=True)
event = CharField(default="")
send_data = BooleanField(default=True)
class Meta:
table_name = "webhooks"
class Backups(BaseModel):
directories = CharField()
storage_location = CharField()
max_backups = IntegerField()
server_id = IntegerField()
class Meta:
table_name = 'backups'
class db_builder:
@staticmethod
def create_tables():
with database:
database.create_tables([
Backups,
Users,
Host_Stats,
Webhooks
])
def default_settings(self):
Users.insert({
Users.username: 'Admin',
Users.password: helper.encode_pass('asdfasdf'),
Users.api_token: helper.random_string_generator(32),
Users.enabled: True
}).execute()
installer = db_builder()

View File

@ -38,9 +38,12 @@ class PublicHandler(BaseHandler):
self.clear_cookie("user")
self.clear_cookie("user_data")
error = bleach.clean(self.get_argument('error', ""))
template = "public/404.html"
# print(page)
if page is None:
self.redirect("public/login")
error = bleach.clean(self.get_argument('error', ""))
if error:
error_msg = "Invalid Login!"
@ -57,3 +60,44 @@ class PublicHandler(BaseHandler):
self.render(template, data=context)
def post(self, page=None):
if page == 'login':
next_page = "/public/login"
entered_email = bleach.clean(self.get_argument('email'))
entered_password = bleach.clean(self.get_argument('password'))
user_data = Users.get_or_none(Users.email_address == entered_email)
# if we already have a user with this email...
if not user_data:
next_page = "/public/login?error=Login_Failed"
self.redirect(next_page)
return False
login_result = helper.verify_pass(entered_password, user_data.password)
# Valid Login
if login_result:
self.set_current_user(entered_email)
logger.info("User: {} Logged in from IP: {}".format(entered_email, self.get_remote_ip()))
Users.update({
Users.last_ip: self.get_remote_ip()
}).execute()
cookie_data = {
"user_email": user_data.email_address,
"user_id": user_data,
"account_type": str(user_data.account_type).upper(),
}
self.set_secure_cookie('user_data', json.dumps(cookie_data))
next_page = "/pro/dashboard"
self.redirect(next_page)
else:
self.redirect("/public/login")

View File

@ -84,7 +84,10 @@ class webserver:
debug_errors = helper.get_setting("WEB", 'show_errors')
cookie_secret = helper.get_setting("WEB", 'cookie_secret')
if cookie_secret.lower == "random" or cookie_secret is False:
if cookie_secret is False:
cookie_secret = helper.random_string_generator(32)
if cookie_secret.lower == "random":
cookie_secret = helper.random_string_generator(32)
if not lang:
@ -114,6 +117,7 @@ class webserver:
handlers = [
(r'/', PublicHandler),
(r'/public/(.*)', PublicHandler),
]
app = tornado.web.Application(

View File

@ -17,7 +17,7 @@
"main_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"formatter": "commander",
"filename": "app/logs/commander.log",
"filename": "logs/commander.log",
"maxBytes": 5242880,
"backupCount": 20,
"encoding": "utf8"
@ -25,7 +25,7 @@
"session_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"formatter": "commander",
"filename": "app/logs/session.log",
"filename": "logs/session.log",
"backupCount": 0,
"encoding": "utf8"
}

View File

@ -31,6 +31,7 @@
<img src="/static/assets/images/logo_long.jpg">
</div>
<form action="/public/login" method="post">
{% raw xsrf_form_html() %}
<div class="form-group">
<label class="label">Email</label>
<div class="input-group">

View File

@ -8,7 +8,7 @@ import logging.config
""" Our custom classes / pip packages """
from app.classes.shared.console import console
from app.classes.shared.helpers import helper
from app.classes.shared.models import installer
from app.classes.shared.tasks import tasks_manager
def do_intro():
@ -89,6 +89,9 @@ if __name__ == '__main__':
# this should always be last
tasks_manager.start_main_kill_switch_watcher()
installer.create_tables()
installer.default_settings()
# our main loop
while True:
if tasks_manager.get_main_thread_run_status():