mirror of https://github.com/kf7eel/hbnet
implement pages, clean web service, add option to disable fallback
This commit is contained in:
parent
1e311d86c6
commit
391e76d72c
|
|
@ -1,4 +1,4 @@
|
||||||
## HBNet is still under heavy development. Documentation is being added to the Wiki as I write it, so check perodically to see if there is any new information. V1.0 will be ready in the next few months. See [HBNet.xyz](https://hbnet.xyz) or [here](https://github.com/kf7eel/hbnet/discussions/33) for the development news.
|
## HBNet is still under heavy development and currently undergoing a partiaql rewrite. Documentation is being added to the Wiki as I write it, so check perodically to see if there is any new information. V1.0 will be ready in the next few months. See [here](https://github.com/kf7eel/hbnet/discussions/33) for the development news.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1691,6 +1691,9 @@ if __name__ == '__main__':
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Control server unreachable or other error. Using local config.')
|
logger.error('Control server unreachable or other error. Using local config.')
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
if LOCAL_CONFIG['WEB_SERVICE']['DISABLE_FALLBACK']:
|
||||||
|
logger.info('Falback disabled. Exiting...')
|
||||||
|
sys.exit()
|
||||||
spec = importlib.util.spec_from_file_location("module.name", cli_args.RULES_FILE)
|
spec = importlib.util.spec_from_file_location("module.name", cli_args.RULES_FILE)
|
||||||
rules_module = importlib.util.module_from_spec(spec)
|
rules_module = importlib.util.module_from_spec(spec)
|
||||||
try:
|
try:
|
||||||
|
|
@ -1764,4 +1767,5 @@ if __name__ == '__main__':
|
||||||
else:
|
else:
|
||||||
Path('/tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/')).mkdir()
|
Path('/tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/')).mkdir()
|
||||||
|
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ def build_config(_config_file):
|
||||||
'THIS_SERVER_NAME': config.get(section, 'THIS_SERVER_NAME'),
|
'THIS_SERVER_NAME': config.get(section, 'THIS_SERVER_NAME'),
|
||||||
'URL': config.get(section, 'URL'),
|
'URL': config.get(section, 'URL'),
|
||||||
'REMOTE_CONFIG_ENABLED': config.getboolean(section, 'REMOTE_CONFIG_ENABLED'),
|
'REMOTE_CONFIG_ENABLED': config.getboolean(section, 'REMOTE_CONFIG_ENABLED'),
|
||||||
|
'DISABLE_FALLBACK': config.getboolean(section, 'DISABLE_FALLBACK'),
|
||||||
'APPEND_INT': config.getint(section, 'APPEND_INT'),
|
'APPEND_INT': config.getint(section, 'APPEND_INT'),
|
||||||
'EXTRA_INT_1': config.getint(section, 'EXTRA_INT_1'),
|
'EXTRA_INT_1': config.getint(section, 'EXTRA_INT_1'),
|
||||||
'EXTRA_INT_2': config.getint(section, 'EXTRA_INT_2'),
|
'EXTRA_INT_2': config.getint(section, 'EXTRA_INT_2'),
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ STALE_DAYS: 7
|
||||||
# This is where to configure the details for use with a user managment script
|
# This is where to configure the details for use with a user managment script
|
||||||
[WEB_SERVICE]
|
[WEB_SERVICE]
|
||||||
THIS_SERVER_NAME: MMDVM_Server
|
THIS_SERVER_NAME: MMDVM_Server
|
||||||
|
# When web service unreachable, die.
|
||||||
|
DISABLE_FALLBACK: True
|
||||||
REMOTE_CONFIG_ENABLED: True
|
REMOTE_CONFIG_ENABLED: True
|
||||||
# URL of the user managment server
|
# URL of the user managment server
|
||||||
URL: http://localhost:8080/svr
|
URL: http://localhost:8080/svr
|
||||||
|
|
@ -197,7 +199,7 @@ REG_ACL: DENY:1
|
||||||
SUB_ACL: DENY:1
|
SUB_ACL: DENY:1
|
||||||
TGID_TS1_ACL: PERMIT:ALL
|
TGID_TS1_ACL: PERMIT:ALL
|
||||||
TGID_TS2_ACL: PERMIT:ALL
|
TGID_TS2_ACL: PERMIT:ALL
|
||||||
|
OTHER_OPTIONS:
|
||||||
# PEER INSTANCES - DUPLICATE SECTION FOR MULTIPLE PEERS
|
# PEER INSTANCES - DUPLICATE SECTION FOR MULTIPLE PEERS
|
||||||
# There are a LOT of errors in the HB Protocol specifications on this one!
|
# There are a LOT of errors in the HB Protocol specifications on this one!
|
||||||
# MOST of these items are just strings and will be properly dealt with by the program
|
# MOST of these items are just strings and will be properly dealt with by the program
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,5 @@ cryptography
|
||||||
setproctitle
|
setproctitle
|
||||||
scapy
|
scapy
|
||||||
paho-mqtt
|
paho-mqtt
|
||||||
|
service_identity
|
||||||
|
|
||||||
|
|
|
||||||
274
web/app.py
274
web/app.py
|
|
@ -53,8 +53,10 @@ import os, ast
|
||||||
|
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
|
|
||||||
|
from flaskext.markdown import Markdown
|
||||||
|
|
||||||
peer_locations = {}
|
peer_locations = {}
|
||||||
hbnet_version = 'HWS 0.0.1-pre_pre_alpha/MQTT'
|
hbnet_version = 'V 09102022'
|
||||||
|
|
||||||
# Query radioid.net for list of IDs
|
# Query radioid.net for list of IDs
|
||||||
def get_ids(callsign):
|
def get_ids(callsign):
|
||||||
|
|
@ -138,6 +140,7 @@ def hbnet_web_service():
|
||||||
# Create Flask app load app.config
|
# Create Flask app load app.config
|
||||||
mail = Mail()
|
mail = Mail()
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
Markdown(app)
|
||||||
app.config.from_object(__name__+'.ConfigClass')
|
app.config.from_object(__name__+'.ConfigClass')
|
||||||
|
|
||||||
# Initialize Flask-BabelEx
|
# Initialize Flask-BabelEx
|
||||||
|
|
@ -544,7 +547,14 @@ def hbnet_web_service():
|
||||||
boo_2 = db.Column(db.Boolean(), nullable=True, server_default='1')
|
boo_2 = db.Column(db.Boolean(), nullable=True, server_default='1')
|
||||||
time = db.Column(db.DateTime())
|
time = db.Column(db.DateTime())
|
||||||
|
|
||||||
|
class Pages(db.Model):
|
||||||
|
__tablename__ = 'pages'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(1000))
|
||||||
|
enabled = db.Column(db.Boolean(), nullable=False, server_default='1')
|
||||||
|
notes = db.Column(db.String(1000))
|
||||||
|
data = db.Column(db.String(10000))
|
||||||
|
time = db.Column(db.DateTime())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -642,24 +652,26 @@ def hbnet_web_service():
|
||||||
time = datetime.datetime.utcnow()
|
time = datetime.datetime.utcnow()
|
||||||
)
|
)
|
||||||
db.session.add(flash_entry_add)
|
db.session.add(flash_entry_add)
|
||||||
tos_entry_add = Misc(
|
|
||||||
field_1 = 'terms_of_service',
|
|
||||||
field_2 = '''<div class="panel panel-default">
|
|
||||||
<div class="panel-heading" style="text-align: center;"><h4>Terms of Use</h4></div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<p>By using <strong>''' + title + '''</strong>, you agree not to do anything malicious. You agree to use the system with respect and courtesy to others. Please operate within the laws of your country.</p>
|
|
||||||
|
|
||||||
</div>
|
add_pg = Pages(
|
||||||
</div>''',
|
name='Home Page',
|
||||||
|
data="Welcome to your HBNet installation.",
|
||||||
|
notes = "Created on first start",
|
||||||
time = datetime.datetime.utcnow()
|
time = datetime.datetime.utcnow()
|
||||||
)
|
)
|
||||||
db.session.add(tos_entry_add)
|
db.session.add(add_pg)
|
||||||
home_entry_add = Misc(
|
|
||||||
field_1 = 'home_page',
|
add_tos = Pages(
|
||||||
field_2 = '<p>Welcome to <strong>' + title + '</strong>.</p>',
|
name='Terms of Service',
|
||||||
|
data='''### Terms of Use
|
||||||
|
|
||||||
|
By using this service, you agree not to do anything malicious. You agree to use the system with respect and courtesy to others. Please operate within the laws of your country.
|
||||||
|
''',
|
||||||
|
notes = "Created on first start",
|
||||||
time = datetime.datetime.utcnow()
|
time = datetime.datetime.utcnow()
|
||||||
)
|
)
|
||||||
db.session.add(home_entry_add)
|
db.session.add(add_tos)
|
||||||
|
|
||||||
ping_list_initial = Misc(
|
ping_list_initial = Misc(
|
||||||
field_1 = 'ping_list',
|
field_1 = 'ping_list',
|
||||||
field_2 = '{}',
|
field_2 = '{}',
|
||||||
|
|
@ -681,6 +693,15 @@ def hbnet_web_service():
|
||||||
time = datetime.datetime.utcnow()
|
time = datetime.datetime.utcnow()
|
||||||
)
|
)
|
||||||
db.session.add(script_links_initial)
|
db.session.add(script_links_initial)
|
||||||
|
|
||||||
|
add_news = News(
|
||||||
|
subject = 'Welcome',
|
||||||
|
date = 'Today',
|
||||||
|
text = 'Welcome',
|
||||||
|
time = datetime.datetime.utcnow()
|
||||||
|
)
|
||||||
|
db.session.add(add_news)
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
# Query radioid.net for list of DMR IDs, then add to DB
|
# Query radioid.net for list of DMR IDs, then add to DB
|
||||||
|
|
@ -787,37 +808,85 @@ def hbnet_web_service():
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def home_page():
|
def home_page():
|
||||||
if mode == 'FULL' or mode == 'DMR_ONLY':
|
if mode == 'FULL' or mode == 'DMR_ONLY':
|
||||||
home_text = Misc.query.filter_by(field_1='home_page').first()
|
home_text = Pages.query.filter_by(id=1).first()
|
||||||
#content = Markup('<strong>Index</strong>')
|
#content = Markup('<strong>Index</strong>')
|
||||||
try:
|
|
||||||
l_news = News.query.order_by(News.time.desc()).first()
|
|
||||||
content = '''
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="card-title"><a href="news/''' + str(l_news.id) + '''">''' + l_news.subject + '''</h4></a>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p style="text-align: center;">''' + l_news.date + '''</p>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p class="card-text">''' + l_news.text + '''</p>
|
|
||||||
<p style="text-align: center;"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
'''
|
|
||||||
except:
|
|
||||||
content = ''
|
content = ''
|
||||||
return render_template('index.html', news = Markup(content), content_block = Markup(home_text.field_2))
|
# try:
|
||||||
|
l_news = News.query.order_by(News.time.desc()).first()
|
||||||
|
return render_template('index.html', news = Markup(content), content_block = Markup(home_text.data), text = l_news.text, subject = l_news.subject, date = l_news.date, news_id = l_news.id)
|
||||||
|
# except:
|
||||||
|
# content = ''
|
||||||
|
# return render_template('index.html', content_block = Markup(home_text.data))
|
||||||
else:
|
else:
|
||||||
return redirect('/data_overview')
|
return redirect('/data_overview')
|
||||||
|
|
||||||
@app.route('/tos')
|
@app.route('/tos')
|
||||||
def tos_page():
|
def tos_page():
|
||||||
tos_text = Misc.query.filter_by(field_1='terms_of_service').first()
|
tos_text = Pages.query.filter_by(id=2).first()
|
||||||
content = tos_text.field_2
|
|
||||||
|
return render_template('generic.html', markup_content = tos_text.data)
|
||||||
|
|
||||||
|
@app.route('/page/<id>')
|
||||||
|
def other_page(id):
|
||||||
|
page = Pages.query.filter_by(id=int(id)).first()
|
||||||
|
|
||||||
|
# return render_template('index.html')
|
||||||
|
return render_template('page.html', content=Markup(page.data), page_title = page.name, page_time = local_time(page.time))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/pages')
|
||||||
|
def all_pages():
|
||||||
|
content = ''
|
||||||
|
all_pages = Pages.query.order_by(Pages.name).all()
|
||||||
|
for i in all_pages:
|
||||||
|
if i.id == 1 or i.id == 2:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
content = content + '<tr><td><a href="/page/' + str(i.id) + '">' + i.name + '</a></td><td>' + i.notes + '</td></tr>'
|
||||||
|
return render_template('view_pages.html', content = Markup(content))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/manage_page', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
@roles_required('Admin')
|
||||||
|
def manage_page():
|
||||||
|
if request.args.get('new'):
|
||||||
|
return render_template('add_page.html')
|
||||||
|
elif request.args.get('save'):
|
||||||
|
add_page(request.form.get('name'), request.form.get('data'), request.form.get('notes'))
|
||||||
|
content = '''<h3 style="text-align: center;">Page Saved.</h3>
|
||||||
|
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
||||||
|
<meta http-equiv="refresh" content="3; URL=/manage_page" /> '''
|
||||||
|
return render_template('flask_user_layout.html', markup_content=Markup(content))
|
||||||
|
|
||||||
|
elif request.args.get('delete'):
|
||||||
|
delete_page(int(request.args.get('delete')))
|
||||||
|
content = '''<h3 style="text-align: center;">Page Deleted.</h3>
|
||||||
|
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
||||||
|
<meta http-equiv="refresh" content="3; URL=/manage_page" /> '''
|
||||||
|
return render_template('flask_user_layout.html', markup_content=Markup(content))
|
||||||
|
|
||||||
|
elif request.args.get('edit'):
|
||||||
|
page = Pages.query.filter_by(id=int(request.args.get('edit'))).first()
|
||||||
|
return render_template('edit_page.html', name = page.name, notes = page.notes, data = page.data, id = page.id)
|
||||||
|
|
||||||
|
elif request.args.get('edit_save'):
|
||||||
|
edit_page(int(request.args.get('edit_save')), request.form.get('name'), request.form.get('data'), request.form.get('notes'))
|
||||||
|
content = '''<h3 style="text-align: center;">Page Saved.</h3>
|
||||||
|
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
||||||
|
<meta http-equiv="refresh" content="3; URL=/manage_page" /> '''
|
||||||
|
return render_template('flask_user_layout.html', markup_content=Markup(content))
|
||||||
|
|
||||||
|
else:
|
||||||
|
content = ''
|
||||||
|
all_pages = Pages.query.order_by(Pages.name).all()
|
||||||
|
for i in all_pages:
|
||||||
|
delete_button = ' - <a href="/manage_page?delete=' + str(i.id) + '"><button type="button" class="btn btn-danger">Delete</button></a>'
|
||||||
|
if i.id == 1 or i.id == 2:
|
||||||
|
delete_button = ''
|
||||||
|
content = content + '<tr><td><a href="/page/' + str(i.id) + '">' + i.name + '</a> - <a href="/manage_page?edit=' + str(i.id) + '"><button type="button" class="btn btn-primary">Edit</button></a>' + delete_button + '</td><td>' + i.notes + '</td></tr>'
|
||||||
|
return render_template('view_pages.html', content = Markup(content), admin_page = True)
|
||||||
|
|
||||||
return render_template('generic.html', markup_content = Markup(content))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/map_gps/<call_ssid>')
|
@app.route('/map_gps/<call_ssid>')
|
||||||
|
|
@ -2162,54 +2231,24 @@ def hbnet_web_service():
|
||||||
## view_news = News.query.order_by(News.time.desc()).paginate(page=page, per_page=1)
|
## view_news = News.query.order_by(News.time.desc()).paginate(page=page, per_page=1)
|
||||||
|
|
||||||
#content = '''<table style="width: 600px; margin-left: auto; margin-right: auto;" border="1"><tbody>'''
|
#content = '''<table style="width: 600px; margin-left: auto; margin-right: auto;" border="1"><tbody>'''
|
||||||
|
|
||||||
|
content = ''
|
||||||
|
|
||||||
news_content = ''
|
news_content = ''
|
||||||
art_count = 0
|
art_count = 0
|
||||||
for article in view_news:
|
print(view_news)
|
||||||
if request.args.get('all_news'):
|
for i in view_news:
|
||||||
art_count = 1
|
content = content + '<tr><td><a href="/news/' + str(i.id) + '">' + i.subject + '</a></td><td>' + i.date + '</td></tr>'
|
||||||
if art_count < 16:
|
|
||||||
news_content = news_content + '''
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="card-title"><a href="news/''' + str(article.id) + '''">''' + article.subject + '''</h4></a>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p style="text-align: center;">''' + article.date + '''</p>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p class="card-text">''' + article.text + '''</p>
|
|
||||||
<p style="text-align: center;"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
|
return render_template('news_list.html', content = Markup(content))
|
||||||
'''
|
|
||||||
art_count = art_count + 1
|
|
||||||
#content = content + '''</tbody></table><p> </p>'''
|
|
||||||
return render_template('news.html', markup_content = Markup(news_content))
|
|
||||||
|
|
||||||
@app.route('/news/<article>') #, methods=['POST', 'GET'])
|
@app.route('/news/<article>') #, methods=['POST', 'GET'])
|
||||||
def view_arts(article):
|
def view_arts(article):
|
||||||
|
|
||||||
view_arti = News.query.filter_by(id=article).first()
|
view_arti = News.query.filter_by(id=article).first()
|
||||||
|
|
||||||
content = '''
|
content = ''
|
||||||
<div class="card">
|
return render_template('news.html', markup_content = Markup(content), subject = view_arti.subject, date = view_arti.date, text = view_arti.text)
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="card-title">''' + view_arti.subject + '''</h4>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p style="text-align: center;">''' + view_arti.date + '''</p>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p class="card-text">''' + view_arti.text + '''</p>
|
|
||||||
<p style="text-align: center;"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
'''
|
|
||||||
return render_template('news.html', markup_content = Markup(content))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2284,10 +2323,14 @@ def hbnet_web_service():
|
||||||
<tbody>
|
<tbody>
|
||||||
'''
|
'''
|
||||||
for a in view_news:
|
for a in view_news:
|
||||||
|
if a.id == 1:
|
||||||
|
delete_button = ''
|
||||||
|
else:
|
||||||
|
delete_button = '''<a href="manage_news?delete=''' + str(a.id )+ '''"><button type="button" class="btn btn-danger">Delete</button></a>'''
|
||||||
content = content + '''
|
content = content + '''
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="news/''' + str(a.id) + '''">''' + a.subject + '''</a> | <a href="manage_news?delete=''' + str(a.id )+ '''"><button type="button" class="btn btn-danger">Delete</button></a></td>
|
<td><a href="news/''' + str(a.id) + '''">''' + a.subject + '''</a> | ''' + delete_button + '''</td>
|
||||||
<td>''' + a.date + '''</td>
|
<td>''' + a.date + '''</td>
|
||||||
<td>''' + str(a.id) + '''</td>
|
<td>''' + str(a.id) + '''</td>
|
||||||
|
|
||||||
|
|
@ -2313,16 +2356,6 @@ def hbnet_web_service():
|
||||||
content = '''<h3 style="text-align: center;">Saved flash text.</h3>
|
content = '''<h3 style="text-align: center;">Saved flash text.</h3>
|
||||||
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
||||||
<meta http-equiv="refresh" content="3; URL=misc_settings" /> '''
|
<meta http-equiv="refresh" content="3; URL=misc_settings" /> '''
|
||||||
elif request.args.get('home') == 'save':
|
|
||||||
misc_edit_field_1('home_page', request.form.get('home_text'), None, None, None, None, None, None, None, None)
|
|
||||||
content = '''<h3 style="text-align: center;">Saved home page.</h3>
|
|
||||||
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
|
||||||
<meta http-equiv="refresh" content="3; URL=misc_settings" /> '''
|
|
||||||
elif request.args.get('tos') == 'save':
|
|
||||||
misc_edit_field_1('terms_of_service', request.form.get('tos_text'), None, None, None, None, None, None, None, None)
|
|
||||||
content = '''<h3 style="text-align: center;">Saved terms of service.</h3>
|
|
||||||
<p style="text-align: center;">Redirecting in 3 seconds.</p>
|
|
||||||
<meta http-equiv="refresh" content="3; URL=misc_settings" /> '''
|
|
||||||
elif request.args.get('aprs') == 'save':
|
elif request.args.get('aprs') == 'save':
|
||||||
misc_edit_field_1('unregistered_aprs', request.form.get('aprs_text'), None, None, None, None, None, None, None, None)
|
misc_edit_field_1('unregistered_aprs', request.form.get('aprs_text'), None, None, None, None, None, None, None, None)
|
||||||
content = '''<h3 style="text-align: center;">Saved terms of service.</h3>
|
content = '''<h3 style="text-align: center;">Saved terms of service.</h3>
|
||||||
|
|
@ -2372,39 +2405,6 @@ def hbnet_web_service():
|
||||||
|
|
||||||
<p> </p>
|
<p> </p>
|
||||||
|
|
||||||
<form action="misc_settings?home=save" method="POST">
|
|
||||||
<table style="width: 500px; margin-left: auto; margin-right: auto;" border="1">
|
|
||||||
<tbody>
|
|
||||||
<tr style="height: 51.1667px;">
|
|
||||||
<td style="height: 51.1667px; text-align: center;"><label for="home_text">Homepage (HTML OK, 5000 characters max):</label><br /> <textarea id="home_text" cols="65" name="home_text" rows="4">''' + home_text.field_2 + '''</textarea></td>
|
|
||||||
</tr>
|
|
||||||
<tr style="height: 27px;">
|
|
||||||
<td style="text-align: center; height: 27px;">
|
|
||||||
<p> </p>
|
|
||||||
<p><input type="submit" value="Submit" /></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<form action="misc_settings?tos=save" method="POST">
|
|
||||||
<table style="width: 500px; margin-left: auto; margin-right: auto;" border="1">
|
|
||||||
<tbody>
|
|
||||||
<tr style="height: 51.1667px;">
|
|
||||||
<td style="height: 51.1667px; text-align: center;"><label for="tos_text">Terms of Service (HTML OK, 5000 characters max):</label><br /> <textarea id="tos_text" cols="65" name="tos_text" rows="4">''' + tos_text.field_2 + '''</textarea></td>
|
|
||||||
</tr>
|
|
||||||
<tr style="height: 27px;">
|
|
||||||
<td style="text-align: center; height: 27px;">
|
|
||||||
<p> </p>
|
|
||||||
<p><input type="submit" value="Submit" /></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<form action="misc_settings?aprs=save" method="POST">
|
<form action="misc_settings?aprs=save" method="POST">
|
||||||
<table style="width: 500px; margin-left: auto; margin-right: auto;" border="1">
|
<table style="width: 500px; margin-left: auto; margin-right: auto;" border="1">
|
||||||
|
|
@ -3404,6 +3404,38 @@ Name: <strong>''' + p.name + '''</strong> - Port: <strong>''' + str(
|
||||||
|
|
||||||
###### DB functions #############################
|
###### DB functions #############################
|
||||||
|
|
||||||
|
def local_time(time_utc):
|
||||||
|
l_time = (time_utc + datetime.timedelta(hours=hbnet_tz)).strftime(time_format)
|
||||||
|
return l_time
|
||||||
|
|
||||||
|
|
||||||
|
def local_time_to_utc(time):
|
||||||
|
u_time = (time - datetime.timedelta(hours=hbnet_tz))
|
||||||
|
return u_time
|
||||||
|
|
||||||
|
def add_page(name, data, notes):
|
||||||
|
add_pg = Pages(
|
||||||
|
name=name,
|
||||||
|
data=data,
|
||||||
|
notes = notes,
|
||||||
|
time = datetime.datetime.utcnow()
|
||||||
|
)
|
||||||
|
db.session.add(add_pg)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
def edit_page(id, name, data, notes):
|
||||||
|
page = Pages.query.filter_by(id=id).first()
|
||||||
|
page.name = name
|
||||||
|
page.data = data
|
||||||
|
page.time = datetime.datetime.utcnow()
|
||||||
|
page.notes = notes
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
def delete_page(id):
|
||||||
|
page = Pages.query.filter_by(id=id).first()
|
||||||
|
db.session.delete(page)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
def sms_que(_server):
|
def sms_que(_server):
|
||||||
que_db = SMS_Que.query.filter_by(server=_server).all()
|
que_db = SMS_Que.query.filter_by(server=_server).all()
|
||||||
que_list = []
|
que_list = []
|
||||||
|
|
|
||||||
|
|
@ -46,15 +46,15 @@ default_account_state = True
|
||||||
|
|
||||||
# Allow users to generate and send SMS messages via the web service
|
# Allow users to generate and send SMS messages via the web service
|
||||||
# and API.
|
# and API.
|
||||||
allow_user_sms = True
|
allow_user_sms = False
|
||||||
|
|
||||||
# Legacy passphrase used in hblink.cfg
|
# Legacy passphrase used in hblink.cfg
|
||||||
legacy_passphrase = 'passw0rd'
|
legacy_passphrase = 'passw0rd'
|
||||||
|
|
||||||
# Coordinates to center map over
|
# Coordinates to center map over
|
||||||
center_map = [45.372, -121.6972]
|
center_map = [00.000, 000.0000]
|
||||||
# Default map zoom level
|
# Default map zoom level
|
||||||
map_zoom = 5
|
map_zoom = 10
|
||||||
|
|
||||||
# Passphrase calculation config. If REMOTE_CONFIG is not used in your DMR server config
|
# Passphrase calculation config. If REMOTE_CONFIG is not used in your DMR server config
|
||||||
# (hblink.cfg), then the values in section [USER_MANAGER] MUST match the values below.
|
# (hblink.cfg), then the values in section [USER_MANAGER] MUST match the values below.
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,4 @@ libscrc
|
||||||
dmr_utils3
|
dmr_utils3
|
||||||
cryptography
|
cryptography
|
||||||
uwsgi
|
uwsgi
|
||||||
|
Flask-Markdown
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends 'flask_user/_public_base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2 style="text-align: center;">Add Page</h2>
|
||||||
|
|
||||||
|
<form action="/manage_page?save=true" method="post">
|
||||||
|
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<span class="input-group-text" id="basic-addon1">Title</span>
|
||||||
|
<input type="text" name="name" class="form-control" aria-describedby="basic-addon1">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
<textarea id="ed1" name="data" class="form-control" aria-label="Data"></textarea>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">Notes</span>
|
||||||
|
<textarea id="ed1" name="notes" class="form-control" aria-label="Notes"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<p style="text-align: center;"><input class="btn btn-primary" type="submit" value="Save" /></form></p>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const easyMDE = new EasyMDE({element: document.getElementById('ed1')});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -7,12 +7,15 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="container-fluid col-centered">
|
||||||
|
|
||||||
{{markup_content}}
|
{{markup_content}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
{% extends 'flask_user/_public_base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2 style="text-align: center;">Add Page</h2>
|
||||||
|
|
||||||
|
<form action="/manage_page?edit_save={{id}}" method="post">
|
||||||
|
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<span class="input-group-text" id="basic-addon1">Title</span>
|
||||||
|
<input type="text" name="name" class="form-control" aria-describedby="basic-addon1" value="{{name}}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<textarea id="ed1" name="data" class="form-control" aria-label="Data">{{data}}</textarea>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">Notes</span>
|
||||||
|
<textarea id="ed1" name="notes" class="form-control" aria-label="Notes">{{notes}}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<p style="text-align: center;"><input class="btn btn-primary" type="submit" value="Save" /></form></p>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const easyMDE = new EasyMDE({element: document.getElementById('ed1')});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -10,6 +10,13 @@
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.15.5/dist/bootstrap-table.min.css">
|
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.15.5/dist/bootstrap-table.min.css">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
|
||||||
|
<!-- Markdown editor -->
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
|
||||||
|
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
|
||||||
|
|
||||||
|
<!--Bootstrap select-->
|
||||||
|
<!-- Latest compiled and minified CSS -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.14.0-beta3/dist/css/bootstrap-select.min.css">
|
||||||
|
|
||||||
|
|
||||||
<!-- In-lining styles to avoid needing a separate .css file -->
|
<!-- In-lining styles to avoid needing a separate .css file -->
|
||||||
|
|
@ -48,6 +55,9 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{url}}/"><i class="bi bi-house-fill"></i> Home </a>
|
<a class="nav-link" href="{{url}}/"><i class="bi bi-house-fill"></i> Home </a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{url}}/pages"><i class="bi bi-file-earmark-break-fill"></i> Pages </a>
|
||||||
|
</li>
|
||||||
{% if global_config['mode'] == 'FULL' or global_config['mode'] == 'DMR_ONLY' %}
|
{% if global_config['mode'] == 'FULL' or global_config['mode'] == 'DMR_ONLY' %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{url}}/talkgroups"><i class="bi bi-card-list"></i> Talkgroups </a>
|
<a class="nav-link" href="{{url}}/talkgroups"><i class="bi bi-card-list"></i> Talkgroups </a>
|
||||||
|
|
@ -133,6 +143,7 @@
|
||||||
<li><a class="dropdown-item" href="{{url}}/approve_users">Waiting Approval</a></li>
|
<li><a class="dropdown-item" href="{{url}}/approve_users">Waiting Approval</a></li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><a class="dropdown-item" href="{{url}}/manage_news">Manage News</a></li>
|
<li><a class="dropdown-item" href="{{url}}/manage_news">Manage News</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/manage_page"> Manage Pages </a></li>
|
||||||
<li><a class="dropdown-item" href="{{url}}/misc_settings">Misc Options</a></li>
|
<li><a class="dropdown-item" href="{{url}}/misc_settings">Misc Options</a></li>
|
||||||
{% if global_config['mode'] == 'FULL' or global_config['mode'] == 'DMR_ONLY' %}
|
{% if global_config['mode'] == 'FULL' or global_config['mode'] == 'DMR_ONLY' %}
|
||||||
<li><a class="dropdown-item" href="{{url}}/auth_log">Authorization Log</a></li>
|
<li><a class="dropdown-item" href="{{url}}/auth_log">Authorization Log</a></li>
|
||||||
|
|
@ -238,8 +249,10 @@
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||||||
<script src="https://unpkg.com/bootstrap-table@1.18.3/dist/bootstrap-table.min.js"></script>
|
<script src="https://unpkg.com/bootstrap-table@1.18.3/dist/bootstrap-table.min.js"></script>
|
||||||
|
<!-- Latest compiled and minified JavaScript -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.14.0-beta3/dist/js/bootstrap-select.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
{# *** Allow sub-templates to insert extra html to the bottom of the body *** #}
|
{# *** Allow sub-templates to insert extra html to the bottom of the body *** #}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
|
|
||||||
{{markup_content}}
|
{{markup_content|markdown}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
|
|
||||||
{{content_block}}
|
{{content_block|markdown}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -18,6 +18,20 @@
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
<h4>Latest News:</h4>
|
<h4>Latest News:</h4>
|
||||||
{{news}}
|
{{news}}
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title"><a href="news/{{news_id}}">{{subject}}</h4></a>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<p style="text-align: center;">{{date}}</p>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<p class="card-text">{{text|markdown}}</p>
|
||||||
|
<p style="text-align: center;"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,21 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<p style="text-align: center;"><a href="/news?all_news=true"><strong><button type="button" class="btn btn-primary">View All News</button></strong></a></p>
|
<p style="text-align: center;"><a href="/news?all_news=true"><strong><button type="button" class="btn btn-primary">View All News</button></strong></a></p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">{{markup_content}}</div>
|
<div class="col-lg-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title">{{subject}}</h4>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<p style="text-align: center;">{{date}}</p>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<p class="card-text">{{text|markdown}}</p>
|
||||||
|
<p style="text-align: center;"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p> </p>
|
<p> </p>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{% extends 'flask_user/_public_base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<table data-toggle="table" data-pagination="true" data-search="true" >
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Subject</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{content}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends 'flask_user/_public_base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2 style="text-align: center;">{{page_title}}</h2>
|
||||||
|
<p style="text-align: center;">Last updated: {{page_time}}</p>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{{content|markdown}}
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends 'flask_user/_public_base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1 style="text-align: center;">Pages</h1>
|
||||||
|
|
||||||
|
{% if admin_page %}
|
||||||
|
|
||||||
|
{% if call_or_get(current_user.has_roles(['Admin'])) %}
|
||||||
|
<table style="margin-left: auto; margin-right: auto;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/manage_page?new=yes"><button type="button" class="btn btn-success">Add Page</button></a></td>
|
||||||
|
<td>.</td>
|
||||||
|
<td>.</td>
|
||||||
|
<td>.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table data-toggle="table" data-pagination="true" data-search="true" >
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Notes</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{content}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
Loading…
Reference in New Issue