started work on the platform/plugin system

This commit is contained in:
Ross Mountjoy 2020-02-06 10:57:45 -05:00
parent b4764d1046
commit 43ae3103e1
7 changed files with 149 additions and 56 deletions

View File

@ -1,5 +1,11 @@
from dashmachine import db from dashmachine import db
rel_app_data_source = db.Table(
"rel_app_data_source",
db.Column("data_source_id", db.Integer, db.ForeignKey("data_sources.id")),
db.Column("app_id", db.Integer, db.ForeignKey("apps.id")),
)
class Files(db.Model): class Files(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
@ -46,6 +52,25 @@ class ApiCalls(db.Model):
value_template = db.Column(db.String()) value_template = db.Column(db.String())
class DataSources(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
platform = db.Column(db.String())
args = db.relationship("DataSourcesArgs", backref="data_source")
apps = db.relationship(
"Apps",
secondary=rel_app_data_source,
backref=db.backref("data_sources", lazy="dynamic"),
)
class DataSourcesArgs(db.Model):
id = db.Column(db.Integer, primary_key=True)
key = db.Column(db.String())
value = db.Column(db.String())
data_source_id = db.Column(db.Integer, db.ForeignKey("data_sources.id"))
class Groups(db.Model): class Groups(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String()) name = db.Column(db.String())

View File

@ -1,6 +1,6 @@
import os import os
from configparser import ConfigParser from configparser import ConfigParser
from dashmachine.main.models import Apps, ApiCalls, Groups from dashmachine.main.models import Apps, ApiCalls, Groups, DataSources, DataSourcesArgs
from dashmachine.settings_system.models import Settings from dashmachine.settings_system.models import Settings
from dashmachine.paths import user_data_folder from dashmachine.paths import user_data_folder
from dashmachine import db from dashmachine import db
@ -21,6 +21,11 @@ def read_config():
except Exception as e: except Exception as e:
return {"msg": f"Invalid Config: {e}."} return {"msg": f"Invalid Config: {e}."}
ds_list = DataSources.query.all()
for ds in ds_list:
ds.apps.clear()
DataSources.query.delete()
DataSourcesArgs.query.delete()
Apps.query.delete() Apps.query.delete()
ApiCalls.query.delete() ApiCalls.query.delete()
Settings.query.delete() Settings.query.delete()
@ -80,48 +85,21 @@ def read_config():
db.session.add(group) db.session.add(group)
db.session.commit() db.session.commit()
# API call creation # Data source creation
elif "platform" in config[section]: elif "platform" in config[section]:
api_call = ApiCalls() data_source = DataSources()
api_call.name = section data_source.name = section
if "resource" in config[section]: data_source.platform = config[section]["platform"]
api_call.resource = config[section]["resource"] db.session.add(data_source)
else:
return {"msg": f"Invalid Config: {section} does not contain resource."}
if "method" in config[section]:
api_call.method = config[section]["method"]
else:
api_call.method = "GET"
if "payload" in config[section]:
api_call.payload = config[section]["payload"]
else:
api_call.payload = None
if "authentication" in config[section]:
api_call.authentication = config[section]["authentication"]
else:
api_call.authentication = None
if "username" in config[section]:
api_call.username = config[section]["username"]
else:
api_call.username = None
if "password" in config[section]:
api_call.password = config[section]["password"]
else:
api_call.password = None
if "value_template" in config[section]:
api_call.value_template = config[section]["value_template"]
else:
api_call.value_template = section
db.session.add(api_call)
db.session.commit() db.session.commit()
continue for key, value in config[section].items():
if key not in ["name", "platform"]:
arg = DataSourcesArgs()
arg.key = key
arg.value = value
arg.data_source = data_source
db.session.add(arg)
db.session.commit()
else: else:
# App creation # App creation
@ -157,11 +135,6 @@ def read_config():
else: else:
app.open_in = "this_tab" app.open_in = "this_tab"
if "data_template" in config[section]:
app.data_template = config[section]["data_template"]
else:
app.data_template = None
if "groups" in config[section]: if "groups" in config[section]:
app.groups = config[section]["groups"] app.groups = config[section]["groups"]
else: else:
@ -170,6 +143,18 @@ def read_config():
db.session.add(app) db.session.add(app)
db.session.commit() db.session.commit()
if "data_sources" in config[section]:
for config_ds in config[section]["data_sources"].split(","):
db_ds = DataSources.query.filter_by(name=config_ds.strip()).first()
if db_ds:
app.data_sources.append(db_ds)
db.session.merge(app)
db.session.commit()
else:
return {
"msg": f"Invalid Config: {section} has a data_source variable that doesn't exist."
}
group = Groups.query.filter_by(name="admin_only").first() group = Groups.query.filter_by(name="admin_only").first()
if not group: if not group:
group = Groups() group = Groups()

View File

@ -4,8 +4,13 @@ from secrets import token_hex
from htmlmin.main import minify from htmlmin.main import minify
from flask import render_template, url_for, redirect, request, Blueprint, jsonify from flask import render_template, url_for, redirect, request, Blueprint, jsonify
from flask_login import current_user from flask_login import current_user
from dashmachine.main.models import Files, Apps from dashmachine.main.models import Files, Apps, DataSources
from dashmachine.main.utils import get_rest_data, public_route, check_groups from dashmachine.main.utils import (
get_rest_data,
public_route,
check_groups,
get_data_source,
)
from dashmachine.settings_system.models import Settings from dashmachine.settings_system.models import Settings
from dashmachine.paths import cache_folder from dashmachine.paths import cache_folder
from dashmachine import app, db from dashmachine import app, db
@ -72,6 +77,13 @@ def load_rest_data():
return data_template return data_template
@main.route("/load_data_source", methods=["GET"])
def load_data_source():
data_source = DataSources.query.filter_by(id=request.args.get("id")).first()
data = get_data_source(data_source)
return data
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# TCDROP routes # TCDROP routes
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -1,5 +1,6 @@
import os import os
import subprocess import subprocess
import importlib
from shutil import copyfile from shutil import copyfile
from requests import get from requests import get
from configparser import ConfigParser from configparser import ConfigParser
@ -143,3 +144,15 @@ def check_groups(groups, current_user):
return True return True
else: else:
return False return False
def get_data_source(data_source):
data_source_args = []
for arg in data_source.args:
data_source_args.append(row2dict(arg))
data_source = row2dict(data_source)
module = importlib.import_module(
f"dashmachine.platform.{data_source['platform']}", "."
)
platform = module.Platform(data_source, data_source_args)
return platform.process()

View File

@ -1,6 +1,47 @@
from requests import get
class Platform: class Platform:
def __init__(self, *args, **kwargs): def __init__(self, data_source, data_source_args):
pass self.data_source = data_source
self.name = data_source["name"]
# parse the user's options from the config entries
for source_arg in data_source_args:
if source_arg.get("key") == "resource":
self.resource = source_arg.get("value")
if source_arg.get("key") == "method":
self.method = source_arg.get("value")
else:
self.method = "GET"
if source_arg.get("key") == "payload":
self.payload = source_arg.get("value")
if source_arg.get("key") == "authentication":
self.authentication = source_arg.get("value")
if source_arg.get("key") == "username":
self.username = source_arg.get("value")
if source_arg.get("key") == "password":
self.password = source_arg.get("value")
if source_arg.get("key") == "value_template":
self.value_template = source_arg.get("value")
else:
self.value_template = "value"
if source_arg.get("key") == "data_template":
self.data_template = source_arg.get("value")
else:
self.value_template = self.name
def process(self): def process(self):
pass if self.method.upper() == "GET":
try:
value = get(self.resource)
except:
pass
return self.name

View File

@ -15,6 +15,19 @@ $( document ).ready(function() {
}); });
}); });
$(".data-source-container").each(function(e) {
var el = $(this);
$.ajax({
url: el.attr('data-url'),
type: 'GET',
data: {id: el.attr('data-id')},
success: function(data){
el.closest('.col').find('.data-source-loading').addClass('hide');
el.text(data);
}
});
});
$(".data-template").each(function(e) { $(".data-template").each(function(e) {
var el = $(this); var el = $(this);
$.ajax({ $.ajax({

View File

@ -1,5 +1,5 @@
{% extends "main/layout.html" %} {% extends "main/layout.html" %}
{% from 'global_macros.html' import data %} {% from 'global_macros.html' import data, preload_circle %}
{% block page_vendor_css %} {% block page_vendor_css %}
{% endblock page_vendor_css %} {% endblock page_vendor_css %}
@ -42,16 +42,20 @@
<div class="col s12 m6 l3"> <div class="col s12 m6 l3">
<div class="card theme-surface-transparent app-card"> <div class="card theme-surface-transparent app-card">
<div class="card-content center-align scrollbar" style="max-height: 118px; min-height: 118px; scrollbar-width: none;"> <div class="card-content center-align scrollbar" style="max-height: 118px; min-height: 118px; scrollbar-width: none;">
{% if app.data_template %} {% if app.data_sources.count() > 0 %}
<div class="row"> <div class="row">
<div class="col s6 center-align"> <div class="col s6 center-align">
<img src="{{ app.icon }}" height="64px"> <img src="{{ app.icon }}" height="64px">
</div> </div>
<div class="col s6 left-align"> <div class="col s6 left-align">
<p class="data-template hide theme-text" data-url="{{ url_for('main.load_rest_data') }}" style="white-space: pre-line"> <span class="data-source-loading">{{ preload_circle() }}</span>
{{ app.data_template|safe }} {% for data_source in app.data_sources %}
</p> <p class="data-source-container"
data-url="{{ url_for('main.load_data_source') }}"
data-id="{{ data_source.id }}">
</p>
{% endfor %}
</div> </div>
</div> </div>
{% else %} {% else %}