implement edit of system rule, update requirements

This commit is contained in:
KF7EEL 2021-07-26 15:41:40 -07:00
parent e55c1395f6
commit ea1c04528c
13 changed files with 5562 additions and 1 deletions

View File

@ -13,6 +13,5 @@ email_validator
flask_babelex
pymysql
folium
json
requests
libsrc

5127
web/app.py Normal file

File diff suppressed because it is too large Load Diff

87
web/config-SAMPLE.py Normal file
View File

@ -0,0 +1,87 @@
'''
Settings for HBNet Web Server.
'''
# Database options
# Using SQLite is simple and easiest. Comment out this line and uncomment the MySQL
# line to use a MySQL/MariaDB server.
db_location = 'sqlite:///hbnet.sqlite'
# Uncomment and change this line to use a MySQL DB. It is best to start with a fresh
# DB without data in it.
#db_location = 'mysql+pymysql://DB_USERNAME:DB_PASSWORD@DB_HOST:MySQL_PORT/DB_NAME'
# Title of the HBNet Web Server
title = 'HBNet DMR server'
# Port to run server
hws_port = 8080
# IP to run server on
hws_host = '127.0.0.1'
# Publicly accessible URL of the web server. THIS IS REQUIRED AND MUST BE CORRECT.
url = 'http://localhost:8080'
# Replace below with some random string such as an SHA256
secret_key = 'SUPER SECRET LONG KEY'
# Default state for newly created user accounts. Setting to False will require
# the approval of an admin user before the user can login.
default_account_state = True
# Legacy passphrase used in hblink.cfg
#legacy_passphrase = 'passw0rd'
# 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.
# If REMOTE_CONFIG is enabled, the DMR server (hblink) will automatically use the values below.
# These config options affect the generation of user passphrases.
# Set to a value between 1 - 99. This value is used in the normal calculation.
append_int = 1
# Set to a value between 1 - 99. This value is used for compromised passphrases.
burn_int = 5
# Set to a value between 1 - 99 This value is used in the normal calculation.
extra_int_1 = 5
# Set to a value between 1 - 99 This value is used in the normal calculation.
extra_int_2 = 8
# Set to a length of about 10 characters.
extra_1 = 'TeSt'
extra_2 = 'DmR4'
# Shorten generated passphrases
use_short_passphrase = True
# Character length of shortened passphrase
shorten_length = 6
# How often to pick character from long passphrase when shortening.
shorten_sample = 4
# Email settings
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 465
MAIL_USE_SSL = True
MAIL_USE_TLS = False
MAIL_USERNAME = 'app@gmail.com'
MAIL_PASSWORD = 'password'
MAIL_DEFAULT_SENDER = '"' + title + '" <app@gmail.com>'
# User settings settings
USER_ENABLE_EMAIL = True
USER_ENABLE_USERNAME = True
USER_REQUIRE_RETYPE_PASSWORD = True
USER_ENABLE_CHANGE_USERNAME = False
USER_ENABLE_MULTIPLE_EMAILS = True
USER_ENABLE_CONFIRM_EMAIL = True
USER_ENABLE_REGISTER = True
USER_AUTO_LOGIN_AFTER_CONFIRM = False
USER_SHOW_USERNAME_DOES_NOT_EXIST = True
# Time format for display on some pages
time_format = '%H:%M:%S - %m/%d/%y'

View File

@ -0,0 +1,5 @@
def gen_script(dmr_id, passphrase):
script = '''
DMR ID: ''' + str(dmr_id) + ''' \n Passphrase: ''' + str(passphrase) + '''
'''
return script

BIN
web/static/HBnet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -0,0 +1,30 @@
{% extends 'flask_user/_authorized_base.html' %}
{% block content %}
{% from "flask_user/_macros.html" import render_field, render_checkbox_field, render_submit_field %}
<h1>{%trans%}User profile{%endtrans%}</h1>
<form action="" method="POST" class="form" role="form">
{{ form.hidden_tag() }}
{% for field in form %}
{% if not field.flags.hidden %}
{% if field.type=='SubmitField' %}
{{ render_submit_field(field, tabindex=loop.index*10) }}
{% else %}
{{ render_field(field, tabindex=loop.index*10) }}
{% endif %}
{% endif %}
{% endfor %}
</form>
<br/>
<p><a href="../update_ids"><strong>Update your information from RadioID.net</strong></a></p>
{% if not user_manager.USER_ENABLE_AUTH0 %}
{% if user_manager.USER_ENABLE_CHANGE_USERNAME %}
<p><a href="{{ url_for('user.change_username') }}">{%trans%}Change username{%endtrans%}</a></p>
{% endif %}
{% if user_manager.USER_ENABLE_CHANGE_PASSWORD %}
<p><a href="{{ url_for('user.change_password') }}">{%trans%}Change password{%endtrans%}</a></p>
{% endif %}
{% endif %}
{% endblock %}

View File

@ -0,0 +1,8 @@
<p>Dear {{ user.email }} - {{ user.username }},</p>
{% block message %}
{% endblock %}
<p>Sincerely,<br/>
{{ app_name }}
</p>

View File

@ -0,0 +1,69 @@
{% extends 'flask_user/_public_base.html' %}
{% block content %}
{% from "flask_user/_macros.html" import render_field, render_checkbox_field, render_submit_field %}
<h1>{%trans%}Sign in{%endtrans%}</h1>
<p>&nbsp;</p>
<strong>Your username MUST be your callsign or email address.</strong>
<p>&nbsp;</p>
<form action="" method="POST" class="form" role="form">
{{ form.hidden_tag() }}
{# Username or Email field #}
{% set field = form.username if user_manager.USER_ENABLE_USERNAME else form.email %}
<div class="form-group {% if field.errors %}has-error{% endif %}">
{# Label on left, "New here? Register." on right #}
<div class="row">
<div class="col-xs-6">
<label for="{{ field.id }}" class="control-label">{{ field.label.text }}</label>
</div>
<div class="col-xs-6 text-right">
{% if user_manager.USER_ENABLE_REGISTER and not user_manager.USER_REQUIRE_INVITATION %}
<a href="{{ url_for('user.register') }}" tabindex='190'>
{%trans%}New here? Register.{%endtrans%}</a>
{% endif %}
</div>
</div>
{{ field(class_='form-control', tabindex=110) }}
{% if field.errors %}
{% for e in field.errors %}
<p class="help-block">{{ e }}</p>
{% endfor %}
{% endif %}
</div>
{# Password field #}
{% set field = form.password %}
<div class="form-group {% if field.errors %}has-error{% endif %}">
{# Label on left, "Forgot your Password?" on right #}
<div class="row">
<div class="col-xs-6">
<label for="{{ field.id }}" class="control-label">{{ field.label.text }}</label>
</div>
<div class="col-xs-6 text-right">
{% if user_manager.USER_ENABLE_FORGOT_PASSWORD %}
<a href="{{ url_for('user.forgot_password') }}" tabindex='195'>
{%trans%}Forgot your Password?{%endtrans%}</a>
{% endif %}
</div>
</div>
{{ field(class_='form-control', tabindex=120) }}
{% if field.errors %}
{% for e in field.errors %}
<p class="help-block">{{ e }}</p>
{% endfor %}
{% endif %}
</div>
{# Remember me #}
{% if user_manager.USER_ENABLE_REMEMBER_ME %}
{{ render_checkbox_field(login_form.remember_me, tabindex=130) }}
{% endif %}
{# Submit button #}
{{ render_submit_field(form.submit, tabindex=180) }}
</form>
{% endblock %}

View File

@ -0,0 +1,50 @@
{% extends 'flask_user/_public_base.html' %}
{% block content %}
{% from "flask_user/_macros.html" import render_field, render_submit_field %}
<h1>{%trans%}Register{%endtrans%}</h1>
<p>&nbsp;</p>
<strong>Your username MUST be your callsign.</strong> After filling out the fields, a confirmation link will be emailed to you.
<p>&nbsp;</p>
<form action="" method="POST" novalidate formnovalidate class="form" role="form">
{{ form.hidden_tag() }}
{# Username or Email #}
{% set field = form.username if user_manager.USER_ENABLE_USERNAME else form.email %}
<div class="form-group {% if field.errors %}has-error{% endif %}">
{# Label on left, "Already registered? Sign in." on right #}
<div class="row">
<div class="col-xs-6">
<label for="{{ field.id }}" class="control-label">{{ field.label.text }}</label>
</div>
<div class="col-xs-6 text-right">
{% if user_manager.USER_ENABLE_REGISTER %}
<a href="{{ url_for('user.login') }}" tabindex='290'>
{%trans%}Already registered? Sign in.{%endtrans%}</a>
{% endif %}
</div>
</div>
{{ field(class_='form-control', tabindex=210) }}
{% if field.errors %}
{% for e in field.errors %}
<p class="help-block">{{ e }}</p>
{% endfor %}
{% endif %}
</div>
{% if user_manager.USER_ENABLE_EMAIL and user_manager.USER_ENABLE_USERNAME %}
{{ render_field(form.email, tabindex=220) }}
{% endif %}
{{ render_field(form.password, tabindex=230) }}
{% if user_manager.USER_REQUIRE_RETYPE_PASSWORD %}
{{ render_field(form.retype_password, tabindex=240) }}
{% endif %}
{{ render_submit_field(form.submit, tabindex=280) }}
</form>
{% endblock %}

View File

@ -0,0 +1,144 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ user_manager.USER_APP_NAME }}</title>
<!-- Bootstrap -->
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<!-- In-lining styles to avoid needing a separate .css file -->
<style>
hr { border-color: #cccccc; margin: 0; }
.no-margins { margin: 0px; }
.with-margins { margin: 10px; }
.col-centered { float: none; margin: 0 auto; }
</style>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7/html5shiv.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.js"></script>
<![endif]-->
{# *** Allow sub-templates to insert extra html to the head section *** #}
{% block extra_css %}{% endblock %}
</head>
<body>
<h1 style="text-align: center;">{{ user_manager.USER_APP_NAME }}</h1>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="{{ url_for('static', filename='HBnet.png') }}" alt="Logo" width="300" height="144" /></p>
<h1 style="text-align: center;">{{title}}</h1>
<hr />
<table style="width: 700px; margin-left: auto; margin-right: auto;" border="black" cellspacing="3" cellpadding="3">
<tbody>
<tr>
<td style="text-align: center;"><a href={{url}}/>Home</a></td>
{% if not call_or_get(current_user.is_authenticated) %}
<td style="text-align: center;"><a href={{ url_for('user.register') }}>Register</a></td>
<td style="text-align: center;"><a href={{ url_for('user.login') }}>Sign in</a></td>
{% endif %}
{% if call_or_get(current_user.is_authenticated) %}
{% if call_or_get(current_user.has_roles('Admin')) %}
<td style="text-align: center;"><a href={{url}}/add_user><strong>Add a User</strong></a></td>
<td style="text-align: center;"><a href={{url}}/list_users><strong>Edit Users</strong></a></td>
<td style="text-align: center;"><a href={{url}}/approve_users><strong>Waiting Approval</strong></a></td>
<td style="text-align: center;"><a href={{url}}/auth_log><strong>Auth Log</strong></a></td>
{% endif %}
<td style="text-align: center;"><a href={{url}}/help>Help</a></td>
<td style="text-align: center;"><a href={{url}}/generate_passphrase>View Passphrase(s)</a></td>
<td style="text-align: center;"><a href={{url}}/user_tg>Current TGs</a></td>
<td style="text-align: center;"><a href="{{ url_for('user.edit_user_profile') }}">Edit {{ current_user.username or current_user.email }}</a></td>
<td style="text-align: center;"><a href={{ url_for('user.logout') }}>Sign out</a></td>
{% endif %}
</tr>
</tbody>
</table>
{% if call_or_get(current_user.is_authenticated) %}
{% if call_or_get(current_user.has_roles('Admin')) %}
<table style="width: 700px; margin-left: auto; margin-right: auto;" border="black" cellspacing="3" cellpadding="3">
<tbody>
<tr>
<td style="text-align: center;"><a href={{url}}/manage_servers>Manage Servers</a></td>
<td style="text-align: center;"><a href={{url}}/manage_peers>Manage Peers</a></td>
<td style="text-align: center;"><a href={{url}}/manage_masters>Manage Masters</a></td>
<td style="text-align: center;"><a href={{url}}/manage_rules>Manage Rules</a></td>
</tr>
</tbody>
</table>
{% endif %}
{% endif %}
<hr />
{% block body %}
<!--
<div id="header-div" class="clearfix with-margins">
<div class="pull-left"><a href="/"><h1 class="no-margins">{{ user_manager.USER_APP_NAME }}</h1></a></div>
<div class="pull-right">
{% if call_or_get(current_user.is_authenticated) %}
<a href="{{ url_for('user.edit_user_profile') }}">{{ current_user.username or current_user.email }}</a>
&nbsp; | &nbsp;
<a href="{{ url_for('user.logout') }}">{%trans%}Sign out{%endtrans%}</a>
{% else %}
<a href="{{ url_for('user.login') }}">{%trans%}Sign in{%endtrans%}</a>
{% endif %}
</div>
</div>
{% block menu %}
<div id="menu-div" class="with-margins">
<a href="/">{%trans%}Home page{%endtrans%}</a>
</div>
{% endblock %}
-->
<hr class="no-margins"/>
<div id="main-div" class="with-margins">
{# One-time system messages called Flash messages #}
{% block flash_messages %}
{%- with messages = get_flashed_messages(with_categories=true) -%}
{% if messages %}
{% for category, message in messages %}
{% if category=='error' %}
{% set category='danger' %}
{% endif %}
<div class="alert alert-{{category}}">{{ message|safe }}</div>
{% endfor %}
{% endif %}
{%- endwith %}
{% endblock %}
{% block main %}
{% block content %}
{{markup_content}}
{% endblock %}
{% endblock %}
</div>
<br/>
<hr class="no-margins"/>
<div id="footer-div" class="clearfix with-margins">
<p style="text-align: center;"><strong>{{ user_manager.USER_APP_NAME }}<br /></strong><a href="https://hbnet.xyz">HBNet Project</a><br />Created by KF7EEL<br />Contributors:&nbsp; W7NCX</p>
</div>
{% endblock %}
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<!-- Bootstrap -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
{# *** Allow sub-templates to insert extra html to the bottom of the body *** #}
{% block extra_js %}{% endblock %}
</body>
</html>

4
web/templates/help.html Normal file
View File

@ -0,0 +1,4 @@
{% extends 'flask_user/_public_base.html' %}
{% block content %}
This is a help page.</p>
{% endblock %}

4
web/templates/index.html Normal file
View File

@ -0,0 +1,4 @@
{% extends 'flask_user/_public_base.html' %}
{% block content %}
<p>Welcome to the <strong>{{ user_manager.USER_APP_NAME }}</strong>. This tool is used to manage your access.</p>
{% endblock %}

View File

@ -0,0 +1,34 @@
{% extends 'flask_user/_public_base.html' %}
{% block content %}
<p>&nbsp;</p><h4 style="text-align: center;"><a href="/generate_passphrase/pi-star">Click here</a> for automated Pi-Star script.</h4><p>&nbsp;</p>
<table style="width: 900px; margin-left: auto; margin-right: auto;">
<tbody>
<tr>
<td>
<table style="width: 218px;" border="1">
<tbody>
<tr>
<td style="width: 53.8333px;">Name:</td>
<td style="width: 147.167px; text-align: center;"><strong>My Server</strong></td>
</tr>
<tr>
<td style="width: 53.8333px;">Host/IP:</td>
<td style="width: 147.167px; text-align: center;"><strong>127.0.0.1</strong></td>
</tr>
<tr>
<td style="width: 53.8333px;">Port:</td>
<td style="width: 147.167px; text-align: center;"><strong>62030</strong></td>
</tr>
</tbody>
</table>
</td>
<td>{{markup_content}}
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
{% endblock %}