worked on access groups/roles

This commit is contained in:
Ross Mountjoy 2020-02-05 09:26:59 -05:00
parent 4fe3cb6575
commit 1194b543c5
12 changed files with 531 additions and 430 deletions

View File

@ -0,0 +1,180 @@
import os
from configparser import ConfigParser
from dashmachine.main.models import Apps, ApiCalls, Groups
from dashmachine.settings_system.models import Settings
from dashmachine.paths import user_data_folder
from dashmachine import db
def row2dict(row):
d = {}
for column in row.__table__.columns:
d[column.name] = str(getattr(row, column.name))
return d
def read_config():
config = ConfigParser()
try:
config.read(os.path.join(user_data_folder, "config.ini"))
except Exception as e:
return {"msg": f"Invalid Config: {e}."}
Apps.query.delete()
ApiCalls.query.delete()
Settings.query.delete()
Groups.query.delete()
for section in config.sections():
# Settings creation
if section == "Settings":
settings = Settings()
if "theme" in config["Settings"]:
settings.theme = config["Settings"]["theme"]
else:
settings.theme = "light"
if "accent" in config["Settings"]:
settings.accent = config["Settings"]["accent"]
else:
settings.accent = "orange"
if "background" in config["Settings"]:
settings.background = config["Settings"]["background"]
else:
settings.background = "None"
if "roles" in config["Settings"]:
settings.roles = config["Settings"]["roles"]
if "admin" not in settings.roles:
settings.roles += ",admin"
if "user" not in settings.roles:
settings.roles += ",user"
if "public_user" not in settings.roles:
settings.roles += ",public_user"
else:
settings.roles = "admin,user,public_user"
if "home_access_groups" in config["Settings"]:
settings.home_access_groups = config["Settings"]["home_access_groups"]
else:
settings.home_access_groups = "admin_only"
if "settings_access_groups" in config["Settings"]:
settings.settings_access_groups = config["Settings"][
"settings_access_groups"
]
else:
settings.settings_access_groups = "admin_only"
db.session.add(settings)
db.session.commit()
# Groups creation
elif "roles" in config[section]:
group = Groups()
group.name = section
group.roles = config[section]["roles"]
db.session.add(group)
db.session.commit()
# API call creation
elif "platform" in config[section]:
api_call = ApiCalls()
api_call.name = section
if "resource" in config[section]:
api_call.resource = config[section]["resource"]
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()
continue
else:
# App creation
app = Apps()
app.name = section
if "prefix" in config[section]:
app.prefix = config[section]["prefix"]
else:
return {"msg": f"Invalid Config: {section} does not contain prefix."}
if "url" in config[section]:
app.url = config[section]["url"]
else:
return {"msg": f"Invalid Config: {section} does not contain url."}
if "icon" in config[section]:
app.icon = config[section]["icon"]
else:
app.icon = None
if "sidebar_icon" in config[section]:
app.sidebar_icon = config[section]["sidebar_icon"]
else:
app.sidebar_icon = app.icon
if "description" in config[section]:
app.description = config[section]["description"]
else:
app.description = None
if "open_in" in config[section]:
app.open_in = config[section]["open_in"]
else:
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]:
app.groups = config[section]["groups"]
else:
app.groups = None
db.session.add(app)
db.session.commit()
group = Groups.query.filter_by(name="admin_only").first()
if not group:
group = Groups()
group.name = "admin_only"
group.roles = "admin"
db.session.add(group)
db.session.commit()
return {"msg": "success", "settings": row2dict(settings)}

View File

@ -5,7 +5,8 @@ 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 from dashmachine.main.models import Files
from dashmachine.main.utils import get_rest_data from dashmachine.main.utils import get_rest_data, public_route, check_groups
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
@ -49,9 +50,13 @@ def check_valid_login():
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# /home # /home
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@public_route
@main.route("/") @main.route("/")
@main.route("/home", methods=["GET", "POST"]) @main.route("/home", methods=["GET", "POST"])
def home(): def home():
settings = Settings.query.first()
if not check_groups(settings.home_access_groups, current_user):
return redirect(url_for("user_system.login"))
return render_template("main/home.html") return render_template("main/home.html")

View File

@ -4,7 +4,8 @@ from shutil import copyfile
from requests import get from requests import get
from configparser import ConfigParser from configparser import ConfigParser
from dashmachine.paths import dashmachine_folder, images_folder, root_folder from dashmachine.paths import dashmachine_folder, images_folder, root_folder
from dashmachine.main.models import Apps, ApiCalls, TemplateApps, Groups from dashmachine.main.models import ApiCalls, TemplateApps, Groups
from dashmachine.main.read_config import read_config
from dashmachine.settings_system.models import Settings from dashmachine.settings_system.models import Settings
from dashmachine.user_system.models import User from dashmachine.user_system.models import User
from dashmachine.user_system.utils import add_edit_user from dashmachine.user_system.utils import add_edit_user
@ -19,158 +20,6 @@ def row2dict(row):
return d return d
def read_config():
config = ConfigParser()
try:
config.read("dashmachine/user_data/config.ini")
except Exception as e:
return {"msg": f"Invalid Config: {e}."}
Apps.query.delete()
ApiCalls.query.delete()
Settings.query.delete()
Groups.query.delete()
for section in config.sections():
# Settings creation
if section == "Settings":
settings = Settings()
if "theme" in config["Settings"]:
settings.theme = config["Settings"]["theme"]
else:
settings.theme = "light"
if "accent" in config["Settings"]:
settings.accent = config["Settings"]["accent"]
else:
settings.accent = "orange"
if "background" in config["Settings"]:
settings.background = config["Settings"]["background"]
else:
settings.background = "None"
if "roles" in config["Settings"]:
settings.roles = config["Settings"]["roles"]
else:
settings.roles = "admin"
if "home_access_groups" in config["Settings"]:
settings.home_access_groups = config["Settings"]["home_access_groups"]
else:
settings.home_access_groups = "admin_only"
if "settings_access_groups" in config["Settings"]:
settings.settings_access_groups = config["Settings"][
"settings_access_groups"
]
else:
settings.settings_access_groups = "admin_only"
db.session.add(settings)
db.session.commit()
# Groups creation
elif "roles" in config[section]:
group = Groups()
group.name = section
group.roles = config[section]["roles"]
db.session.add(group)
db.session.commit()
# API call creation
elif "platform" in config[section]:
api_call = ApiCalls()
api_call.name = section
if "resource" in config[section]:
api_call.resource = config[section]["resource"]
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()
continue
else:
# App creation
app = Apps()
app.name = section
if "prefix" in config[section]:
app.prefix = config[section]["prefix"]
else:
return {"msg": f"Invalid Config: {section} does not contain prefix."}
if "url" in config[section]:
app.url = config[section]["url"]
else:
return {"msg": f"Invalid Config: {section} does not contain url."}
if "icon" in config[section]:
app.icon = config[section]["icon"]
else:
app.icon = None
if "sidebar_icon" in config[section]:
app.sidebar_icon = config[section]["sidebar_icon"]
else:
app.sidebar_icon = app.icon
if "description" in config[section]:
app.description = config[section]["description"]
else:
app.description = None
if "open_in" in config[section]:
app.open_in = config[section]["open_in"]
else:
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]:
app.groups = config[section]["groups"]
else:
app.groups = None
db.session.add(app)
db.session.commit()
return {"msg": "success", "settings": row2dict(settings)}
def read_template_apps(): def read_template_apps():
config = ConfigParser() config = ConfigParser()
try: try:
@ -248,6 +97,11 @@ def dashmachine_init():
role=settings.roles.split(",")[0].strip(), role=settings.roles.split(",")[0].strip(),
) )
users = User.query.all()
for user in users:
if not user.role:
user.role = "admin"
def get_rest_data(template): def get_rest_data(template):
while template and template.find("{{") > -1: while template and template.find("{{") > -1:
@ -267,3 +121,25 @@ def do_api_call(key):
exec(f"{key} = {value.json()}") exec(f"{key} = {value.json()}")
value = str(eval(api_call.value_template)) value = str(eval(api_call.value_template))
return value return value
def check_groups(groups, current_user):
if current_user.is_anonymous:
current_user.role = "public_user"
if groups:
groups_list = groups.split(",")
roles_list = []
for group in groups_list:
group = Groups.query.filter_by(name=group.strip()).first()
for group_role in group.roles.split(","):
roles_list.append(group_role.strip())
if current_user.role in roles_list:
return True
else:
return False
else:
if current_user.role == "admin":
return True
else:
return False

View File

@ -13,6 +13,8 @@ root_folder = get_root_folder()
dashmachine_folder = os.path.join(root_folder, "dashmachine") dashmachine_folder = os.path.join(root_folder, "dashmachine")
user_data_folder = os.path.join(dashmachine_folder, "user_data")
static_folder = os.path.join(dashmachine_folder, "static") static_folder = os.path.join(dashmachine_folder, "static")
images_folder = os.path.join(static_folder, "images") images_folder = os.path.join(static_folder, "images")

View File

@ -1,5 +1,3 @@
import os
from flask import request
from flask_restful import Resource from flask_restful import Resource
from dashmachine.version import version from dashmachine.version import version
@ -7,15 +5,3 @@ from dashmachine.version import version
class GetVersion(Resource): class GetVersion(Resource):
def get(self): def get(self):
return {"Version": version} return {"Version": version}
class ServerShutdown(Resource):
def get(self):
os.system("shutdown now")
return {"Done"}
class ServerReboot(Resource):
def get(self):
os.system("reboot")
return {"Done"}

View File

@ -1,23 +1,35 @@
import os import os
from shutil import move from shutil import move
from flask import render_template, request, Blueprint, jsonify from flask_login import current_user
from dashmachine.settings_system.forms import ConfigForm from flask import render_template, request, Blueprint, jsonify, redirect, url_for
from dashmachine.user_system.forms import UserForm from dashmachine.user_system.forms import UserForm
from dashmachine.user_system.utils import add_edit_user from dashmachine.user_system.utils import add_edit_user
from dashmachine.main.utils import read_config, row2dict from dashmachine.main.utils import row2dict, public_route, check_groups
from dashmachine.main.read_config import read_config
from dashmachine.main.models import Files, TemplateApps from dashmachine.main.models import Files, TemplateApps
from dashmachine.paths import backgrounds_images_folder, icons_images_folder from dashmachine.settings_system.forms import ConfigForm
from dashmachine.version import version
from dashmachine.settings_system.utils import load_files_html from dashmachine.settings_system.utils import load_files_html
from dashmachine.settings_system.models import Settings
from dashmachine.paths import (
backgrounds_images_folder,
icons_images_folder,
user_data_folder,
)
from dashmachine.version import version
settings_system = Blueprint("settings_system", __name__) settings_system = Blueprint("settings_system", __name__)
@public_route
@settings_system.route("/settings", methods=["GET"]) @settings_system.route("/settings", methods=["GET"])
def settings(): def settings():
settings_db = Settings.query.first()
if not check_groups(settings_db.settings_access_groups, current_user):
return redirect(url_for("main.home"))
config_form = ConfigForm() config_form = ConfigForm()
user_form = UserForm() user_form = UserForm()
with open("dashmachine/user_data/config.ini", "r") as config_file: with open(os.path.join(user_data_folder, "config.ini"), "r") as config_file:
config_form.config.data = config_file.read() config_form.config.data = config_file.read()
files_html = load_files_html() files_html = load_files_html()
template_apps = [] template_apps = []
@ -36,7 +48,7 @@ def settings():
@settings_system.route("/settings/save_config", methods=["POST"]) @settings_system.route("/settings/save_config", methods=["POST"])
def save_config(): def save_config():
with open("dashmachine/user_data/config.ini", "w") as config_file: with open(os.path.join(user_data_folder, "config.ini"), "w") as config_file:
config_file.write(request.form.get("config")) config_file.write(request.form.get("config"))
msg = read_config() msg = read_config()
return jsonify(data=msg) return jsonify(data=msg)

View File

@ -1,8 +1,10 @@
import os import os
import random import random
from jsmin import jsmin from jsmin import jsmin
from flask_login import current_user
from dashmachine import app from dashmachine import app
from dashmachine.main.models import Apps from dashmachine.main.models import Apps
from dashmachine.main.utils import check_groups
from dashmachine.settings_system.models import Settings from dashmachine.settings_system.models import Settings
from dashmachine.paths import static_folder, backgrounds_images_folder from dashmachine.paths import static_folder, backgrounds_images_folder
from dashmachine.cssmin import cssmin from dashmachine.cssmin import cssmin
@ -72,7 +74,14 @@ def process_css_sources(process_bundle=None, src=None, app_global=False):
@app.context_processor @app.context_processor
def context_processor(): def context_processor():
apps = Apps.query.all() apps = []
apps_db = Apps.query.all()
for app_db in apps_db:
if not app_db.groups:
app_db.groups = None
if check_groups(app_db.groups, current_user):
apps.append(app_db)
settings = Settings.query.first() settings = Settings.query.first()
if settings.background == "random": if settings.background == "random":
settings.background = ( settings.background = (

View File

@ -0,0 +1,279 @@
{% macro ConfigReadme() %}
<div class="col s12">
<h4>Config.ini Readme
<span><i class="material-icons-outlined modal-close right icon-btn">close</i></span>
</h4>
</div>
<div id="config-help-col" class="col s12 theme-surface-1 padding-2 border-radius-10">
<h5 class="theme-primary-text">Settings</h5>
<code class="selectable-all">
[Settings]<br>
theme = dark<br>
accent = orange<br>
background = static/images/backgrounds/background.png<br>
</code>
<table class="mt-4 responsive-table">
<thead>
<tr class="theme-primary-text">
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[Settings]</td>
<td>Yes</td>
<td>Config section name.</td>
<td>string</td>
</tr>
<tr>
<td>theme</td>
<td>Yes</td>
<td>UI theme</td>
<td>light, dark</td>
</tr>
<tr>
<td>accent</td>
<td>Yes</td>
<td>UI accent color</td>
<td>
orange, red, pink, purple, deepPurple, indigo, blue, lightBlue,
cyan, teal, green, lightGreen, lime, yellow, amber, deepOrange, brown, grey, blueGrey
</td>
</tr>
<tr>
<td>background</td>
<td>Yes</td>
<td>Background image for the UI</td>
<td>/static/images/backgrounds/yourpicture.png, external link to image, None, random</td>
</tr>
<tr>
<td>roles</td>
<td>No</td>
<td>User roles for access groups.</td>
<td>string, if not defined, this is set to 'admin,user,public_user'. Note: admin, user, public_user roles are required and will be added automatically if omitted.</td>
</tr>
<tr>
<td>home_access_groups</td>
<td>No</td>
<td>Define which access groups can access the /home page</td>
<td>Roles defined in your config. If not defined, default is admin_only</td>
</tr>
<tr>
<td>settings_access_groups</td>
<td>No</td>
<td>Define which access groups can access the /settings page</td>
<td>Roles defined in your config. If not defined, default is admin_only</td>
</tr>
</tbody>
</table>
<h5 class="theme-primary-text">Apps</h5>
<code class="selectable-all">
[App Name]<br>
prefix = https://<br>
url = your-website.com<br>
icon = static/images/apps/default.png<br>
sidebar_icon = static/images/apps/default.png<br>
description = Example description<br>
open_in = iframe<br>
data_template = None
</code>
<table class="mt-4 responsive-table">
<thead>
<tr class="theme-primary-text">
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[App Name]</td>
<td>Yes</td>
<td>The name of your app.</td>
<td>string</td>
</tr>
<tr>
<td>prefix</td>
<td>Yes</td>
<td>The prefix for the app's url.</td>
<td>web prefix, e.g. http:// or https://</td>
</tr>
<tr>
<td>url</td>
<td>Yes</td>
<td>The url for your app.</td>
<td>web url, e.g. myapp.com</td>
</tr>
<tr>
<td>icon</td>
<td>No</td>
<td>Icon for the dashboard.</td>
<td>/static/images/icons/yourpicture.png, external link to image</td>
</tr>
<tr>
<td>sidebar_icon</td>
<td>No</td>
<td>Icon for the sidenav.</td>
<td>/static/images/icons/yourpicture.png, external link to image</td>
</tr>
<tr>
<td>description</td>
<td>No</td>
<td>A short description for the app.</td>
<td>string</td>
</tr>
<tr>
<td>open_in</td>
<td>Yes</td>
<td>open the app in the current tab, an iframe or a new tab</td>
<td>iframe, new_tab, this_tab</td>
</tr>
<tr>
<td>data_template</td>
<td>No</td>
<td>Template for displaying variable(s) from rest data *Note: you must have a rest data variable set up in the config</td>
<td>example: Data: {{ '{{ your_variable }}' }}</td>
</tr>
</tbody>
</table>
<h5 class="theme-primary-text">Access Groups</h5>
<code class="selectable-all">
[public]<br>
roles = admin, user, public_user<br>
</code>
<table class="mt-4 responsive-table">
<thead>
<tr class="theme-primary-text">
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[Group Name]</td>
<td>Yes</td>
<td>Name for access group</td>
<td>string</td>
</tr>
<tr>
<td>roles</td>
<td>Yes</td>
<td>A comma separated list of user roles allowed to view apps in this access group</td>
<td>Roles defined in your config. If not defined, defaults are admin and public_user</td>
</tr>
</tbody>
</table>
<h6 class="theme-primary-text">Note:</h6>
<span class="theme-secondary-text mb-4">
if no access groups are defined in the config, the application will create a default group called 'admin_only' with 'roles = admin'
</span>
<h5 class="theme-primary-text">Api Data</h5>
<code class="selectable-all">
[variable_name]<br>
platform = rest<br>
resource = your-website.com<br>
value_template = variable_name<br>
</code>
<table class="mt-4 responsive-table">
<thead>
<tr class="theme-primary-text">
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[variable_name]</td>
<td>Yes</td>
<td>The variable to be made available to apps.</td>
<td>variable (python syntax)</td>
</tr>
<tr>
<td>platform</td>
<td>Yes</td>
<td>Platform for data source</td>
<td>rest</td>
</tr>
<tr>
<td>resource</td>
<td>Yes</td>
<td>The url for the api call.</td>
<td>myapp.com/api/hello</td>
</tr>
<tr>
<td>value_template</td>
<td>No</td>
<td>Tranform the data returned by the api call (python syntax)</td>
<td>variable_name[0]['info']</td>
</tr>
<tr>
<td>method</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>payload</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>authentication</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>username</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>password</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
</tbody>
</table>
<h5 class="theme-primary-text">Api Data Example</h5>
<p>Say we wanted to display how many Pokemon there are using the PokeAPI, we would add the following to the config:</p>
<code class="selectable-all">
[num_pokemon]<br>
platform = rest<br>
resource = https://pokeapi.co/api/v2/pokemon<br>
value_template = num_pokemon['count']<br>
</code>
<p>Then in the config entry for the app you want to add this to, you would add:</p>
<code class="selectable-all">
data_template = Pokemon: {{ '{{ num_pokemon }}' }}
</code>
</div>
{% endmacro %}

View File

@ -1,6 +1,7 @@
{% extends "main/layout.html" %} {% extends "main/layout.html" %}
{% from 'global_macros.html' import input, button %} {% from 'global_macros.html' import input, button %}
{% from 'main/tcdrop.html' import tcdrop %} {% from 'main/tcdrop.html' import tcdrop %}
{% from 'settings_system/config-readme.html' import ConfigReadme %}
{% block page_vendor_css %} {% block page_vendor_css %}
{% endblock page_vendor_css %} {% endblock page_vendor_css %}
@ -22,228 +23,7 @@
<div id="config-wiki-modal" class="modal full-height-modal"> <div id="config-wiki-modal" class="modal full-height-modal">
<div class="modal-content"> <div class="modal-content">
<div class="row"> <div class="row">
<div class="col s12"> {{ ConfigReadme() }}
<h4>Config.ini Readme
<span><i class="material-icons-outlined modal-close right icon-btn">close</i></span>
</h4>
</div>
<div id="config-help-col" class="col s12 theme-surface-1 padding-2 border-radius-10">
<h5>Settings Reference</h5>
<code class="selectable-all">
[Settings]<br>
theme = dark<br>
accent = orange<br>
background = static/images/backgrounds/background.png<br>
</code>
<table class="mt-4 responsive-table">
<thead>
<tr>
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[Settings]</td>
<td>Yes</td>
<td>Config section name.</td>
<td>string</td>
</tr>
<tr>
<td>theme</td>
<td>Yes</td>
<td>UI theme</td>
<td>light, dark</td>
</tr>
<tr>
<td>accent</td>
<td>Yes</td>
<td>UI accent color</td>
<td>
orange, red, pink, purple, deepPurple, indigo, blue, lightBlue,
cyan, teal, green, lightGreen, lime, yellow, amber, deepOrange, brown, grey, blueGrey
</td>
</tr>
<tr>
<td>background</td>
<td>Yes</td>
<td>Background image for the UI</td>
<td>/static/images/backgrounds/yourpicture.png, external link to image, None, random</td>
</tr>
</tbody>
</table>
<h5>App Reference</h5>
<code class="selectable-all">
[App Name]<br>
prefix = https://<br>
url = your-website.com<br>
icon = static/images/apps/default.png<br>
sidebar_icon = static/images/apps/default.png<br>
description = Example description<br>
open_in = iframe<br>
data_template = None
</code>
<table class="mt-4 responsive-table">
<thead>
<tr>
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[App Name]</td>
<td>Yes</td>
<td>The name of your app.</td>
<td>string</td>
</tr>
<tr>
<td>prefix</td>
<td>Yes</td>
<td>The prefix for the app's url.</td>
<td>web prefix, e.g. http:// or https://</td>
</tr>
<tr>
<td>url</td>
<td>Yes</td>
<td>The url for your app.</td>
<td>web url, e.g. myapp.com</td>
</tr>
<tr>
<td>icon</td>
<td>No</td>
<td>Icon for the dashboard.</td>
<td>/static/images/icons/yourpicture.png, external link to image</td>
</tr>
<tr>
<td>sidebar_icon</td>
<td>No</td>
<td>Icon for the sidenav.</td>
<td>/static/images/icons/yourpicture.png, external link to image</td>
</tr>
<tr>
<td>description</td>
<td>No</td>
<td>A short description for the app.</td>
<td>string</td>
</tr>
<tr>
<td>open_in</td>
<td>Yes</td>
<td>open the app in the current tab, an iframe or a new tab</td>
<td>iframe, new_tab, this_tab</td>
</tr>
<tr>
<td>data_template</td>
<td>No</td>
<td>Template for displaying variable(s) from rest data *Note: you must have a rest data variable set up in the config</td>
<td>example: Data: {{ '{{ your_variable }}' }}</td>
</tr>
</tbody>
</table>
<h5>Api Data Reference</h5>
<code class="selectable-all">
[variable_name]<br>
platform = rest<br>
resource = your-website.com<br>
value_template = variable_name<br>
</code>
<table class="mt-4 responsive-table">
<thead>
<tr>
<th>Variable</th>
<th>Required</th>
<th>Description</th>
<th>Options</th>
</tr>
</thead>
<tbody class="selectable">
<tr>
<td>[variable_name]</td>
<td>Yes</td>
<td>The variable to be made available to apps.</td>
<td>variable (python syntax)</td>
</tr>
<tr>
<td>platform</td>
<td>Yes</td>
<td>Platform for data source</td>
<td>rest</td>
</tr>
<tr>
<td>resource</td>
<td>Yes</td>
<td>The url for the api call.</td>
<td>myapp.com/api/hello</td>
</tr>
<tr>
<td>value_template</td>
<td>No</td>
<td>Tranform the data returned by the api call (python syntax)</td>
<td>variable_name[0]['info']</td>
</tr>
<tr>
<td>method</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>payload</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>authentication</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>username</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
<tr>
<td>password</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
<td>NOT IMPLEMENTED</td>
</tr>
</tbody>
</table>
<h5>Api Data Example</h5>
<p>Say we wanted to display how many Pokemon there are using the PokeAPI, we would add the following to the config:</p>
<code class="selectable-all">
[num_pokemon]<br>
platform = rest<br>
resource = https://pokeapi.co/api/v2/pokemon<br>
value_template = num_pokemon['count']<br>
</code>
<p>Then in the config entry for the app you want to add this to, you would add:</p>
<code class="selectable-all">
data_template = Pokemon: {{ '{{ num_pokemon }}' }}
</code>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -18,9 +18,6 @@ user_system = Blueprint("user_system", __name__)
def login(): def login():
user = User.query.first() user = User.query.first()
if current_user.is_authenticated:
return redirect(url_for("main.home"))
form = UserForm() form = UserForm()
if form.validate_on_submit(): if form.validate_on_submit():

View File

@ -2,9 +2,11 @@ from dashmachine import db, bcrypt
from dashmachine.user_system.models import User from dashmachine.user_system.models import User
def add_edit_user(username, password, user_id=None, role=None): def add_edit_user(username, password, user_id=None, role=None, new=False):
if user_id: if user_id:
user = User.query.filter_by(id=user_id).first() user = User.query.filter_by(id=user_id).first()
elif new:
user = User()
else: else:
user = User.query.first() user = User.query.first()
if not user: if not user:

View File

@ -1,31 +1,4 @@
# --------
# SETTINGS
# --------
[Settings] [Settings]
theme = light theme = light
accent = orange accent = orange
background = None background = None
roles = admin, user, public_user
home_access_groups = admin_only
settings_access_groups = admin_only
# -------------
# ACCESS GROUPS
# -------------
[public]
roles = admin, user, public_user
[private]
roles = admin, user
[admin_only]
roles = admin
# --------
# API DATA
# --------
# ----
# APPS
# ----