From 3c461363a4a357a1a96d248a4c4acece85f3d70f Mon Sep 17 00:00:00 2001 From: KF7EEL Date: Sat, 19 Jun 2021 08:58:15 -0700 Subject: [PATCH] page rename, successful MySQL test --- README.md | 19 +- user_managment/app.py | 257 ++++++++++-------- user_managment/config-SAMPLE.py | 83 ++++-- .../templates/flask_user_layout.html | 2 +- 4 files changed, 212 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index fb25f19..2ae8e13 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ ![ ](https://raw.githubusercontent.com/kf7eel/hblink3/hbnet/HBNet.png "Logo") -HBNet is a fork of HBLink3 the extends the functionality of HBLink through several optional features, making it more of a usable application and less of a framework. HBNet aims to be complete and easy to use application that can be used to build, administrate, and run a DMR network. +HBNet is a fork of [HBlink3](https://github.com/HBLink-org/hblink3) the extends the functionality of HBLink through several optional features, making it more of a usable application and less of a framework. HBNet aims to be complete and easy to use application that can be used to build, administrate, and run a DMR network. -HBNet consists of 2 parts, web control panel, and the actual DMR server, based on HBLink. +HBNet consists of 2 parts, HBNet Web Server and the actual DMR server, based on HBLink. ### User end features: @@ -11,16 +11,29 @@ HBNet consists of 2 parts, web control panel, and the actual DMR server, based o * Individual passphrases for each user +* Automatic retrieval of DMR IDs on registration + +* Monitor and change active talkgroups (WORK IN PROGRESS) + ### Administrative features: * Administrate multiple DMR servers through the web panel +* Optional manual approval of new users + * Multiple Admin user logins -* Entirely configure HBLink in web panel +* Entirely configure DMR server (HBlink) in web server + +* Log all peer authentication +### Other features + +* SQLite or MySQL backend + +* APRS and SMS features (WORK IN PROGRESS) --- ### FOR SUPPORT, DISCUSSION, GETTING INVOLVED ### diff --git a/user_managment/app.py b/user_managment/app.py index 4c2cf42..5cabd09 100644 --- a/user_managment/app.py +++ b/user_managment/app.py @@ -1,4 +1,25 @@ -# HBLink User Managment Server +# HBNet Web Server +############################################################################### +# HBNet Web Server - Copyright (C) 2020 Eric Craw, KF7EEL +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +############################################################################### + +''' +Flask based application that is the web server for HBNet. Controls user authentication, DMR server config, etc. +''' from flask import Flask, render_template_string, request, make_response, jsonify, render_template, Markup, flash, redirect, url_for, current_app from flask_sqlalchemy import SQLAlchemy @@ -124,17 +145,17 @@ def create_app(): # User authentication information. The collation='NOCASE' is required # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'. - username = db.Column(db.String(100, collation='NOCASE'), nullable=False, unique=True) + username = db.Column(db.String(100,), nullable=False, unique=True) password = db.Column(db.String(255), nullable=False, server_default='') email_confirmed_at = db.Column(db.DateTime()) - email = db.Column(db.String(255, collation='NOCASE'), nullable=False, unique=True) + email = db.Column(db.String(255), nullable=False, unique=True) # User information - first_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - last_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - dmr_ids = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - city = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + first_name = db.Column(db.String(100), nullable=False, server_default='') + last_name = db.Column(db.String(100), nullable=False, server_default='') + dmr_ids = db.Column(db.String(100), nullable=False, server_default='') + city = db.Column(db.String(100), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') #Used for initial approval initial_admin_approved = db.Column('initial_admin_approved', db.Boolean(), nullable=False, server_default='1') # Define the relationship to Role via UserRoles @@ -154,212 +175,214 @@ def create_app(): role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE')) class BurnList(db.Model): __tablename__ = 'burn_list' +## id = db.Column(db.Integer(), primary_key=True) dmr_id = db.Column(db.Integer(), unique=True, primary_key=True) version = db.Column(db.Integer(), primary_key=True) class AuthLog(db.Model): __tablename__ = 'auth_log' - login_dmr_id = db.Column(db.Integer(), primary_key=True) - login_time = db.Column(db.DateTime(), primary_key=True) - peer_ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - server_name = db.Column(db.Integer(), primary_key=True) - login_auth_method = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - portal_username = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - login_type = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + id = db.Column(db.Integer(), primary_key=True) + login_dmr_id = db.Column(db.Integer()) + login_time = db.Column(db.DateTime()) + peer_ip = db.Column(db.String(100), nullable=False, server_default='') + server_name = db.Column(db.String(100)) + login_auth_method = db.Column(db.String(100), nullable=False, server_default='') + portal_username = db.Column(db.String(100), nullable=False, server_default='') + login_type = db.Column(db.String(100), nullable=False, server_default='') class mmdvmPeer(db.Model): __tablename__ = 'MMDVM_peers' id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + name = db.Column(db.String(100), nullable=False, server_default='') enabled = db.Column(db.Boolean(), nullable=False, server_default='1') loose = db.Column(db.Boolean(), nullable=False, server_default='1') - ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='127.0.0.1') + ip = db.Column(db.String(100), nullable=False, server_default='127.0.0.1') port = db.Column(db.Integer(), primary_key=False) - master_ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + master_ip = db.Column(db.String(100), nullable=False, server_default='') master_port = db.Column(db.Integer(), primary_key=False) - passphrase = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - callsign = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + passphrase = db.Column(db.String(100), nullable=False, server_default='') + callsign = db.Column(db.String(100), nullable=False, server_default='') radio_id = db.Column(db.Integer(), primary_key=False) - rx_freq = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tx_freq = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tx_power = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - color_code = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - latitude = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - longitude = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - height = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - location = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - description = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - slots = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - url = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - group_hangtime = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + rx_freq = db.Column(db.String(100), nullable=False, server_default='') + tx_freq = db.Column(db.String(100), nullable=False, server_default='') + tx_power = db.Column(db.String(100), nullable=False, server_default='') + color_code = db.Column(db.String(100), nullable=False, server_default='') + latitude = db.Column(db.String(100), nullable=False, server_default='') + longitude = db.Column(db.String(100), nullable=False, server_default='') + height = db.Column(db.String(100), nullable=False, server_default='') + location = db.Column(db.String(100), nullable=False, server_default='') + description = db.Column(db.String(100), nullable=False, server_default='') + slots = db.Column(db.String(100), nullable=False, server_default='') + url = db.Column(db.String(100), nullable=False, server_default='') + group_hangtime = db.Column(db.String(100), nullable=False, server_default='') enable_unit = db.Column(db.Boolean(), nullable=False, server_default='1') - options = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + options = db.Column(db.String(100), nullable=False, server_default='') use_acl = db.Column(db.Boolean(), nullable=False, server_default='0') - sub_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg1_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg2_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - server = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + sub_acl = db.Column(db.String(100), nullable=False, server_default='') + tg1_acl = db.Column(db.String(100), nullable=False, server_default='') + tg2_acl = db.Column(db.String(100), nullable=False, server_default='') + server = db.Column(db.String(100), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') class xlxPeer(db.Model): __tablename__ = 'XLX_peers' id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + name = db.Column(db.String(100), nullable=False, server_default='') enabled = db.Column(db.Boolean(), nullable=False, server_default='1') loose = db.Column(db.Boolean(), nullable=False, server_default='1') - ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='127.0.0.1') + ip = db.Column(db.String(100), nullable=False, server_default='127.0.0.1') port = db.Column(db.Integer(), primary_key=False) - master_ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + master_ip = db.Column(db.String(100), nullable=False, server_default='') master_port = db.Column(db.Integer(), primary_key=False) - passphrase = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - callsign = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + passphrase = db.Column(db.String(100), nullable=False, server_default='') + callsign = db.Column(db.String(100), nullable=False, server_default='') radio_id = db.Column(db.Integer(), primary_key=False) - rx_freq = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tx_freq = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tx_power = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - color_code = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - latitude = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - longitude = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - height = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - location = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - description = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - slots = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - url = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - group_hangtime = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - xlxmodule = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - options = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + rx_freq = db.Column(db.String(100), nullable=False, server_default='') + tx_freq = db.Column(db.String(100), nullable=False, server_default='') + tx_power = db.Column(db.String(100), nullable=False, server_default='') + color_code = db.Column(db.String(100), nullable=False, server_default='') + latitude = db.Column(db.String(100), nullable=False, server_default='') + longitude = db.Column(db.String(100), nullable=False, server_default='') + height = db.Column(db.String(100), nullable=False, server_default='') + location = db.Column(db.String(100), nullable=False, server_default='') + description = db.Column(db.String(100), nullable=False, server_default='') + slots = db.Column(db.String(100), nullable=False, server_default='') + url = db.Column(db.String(100), nullable=False, server_default='') + group_hangtime = db.Column(db.String(100), nullable=False, server_default='') + xlxmodule = db.Column(db.String(100), nullable=False, server_default='') + options = db.Column(db.String(100), nullable=False, server_default='') enable_unit = db.Column(db.Boolean(), nullable=False, server_default='1') use_acl = db.Column(db.Boolean(), nullable=False, server_default='0') - sub_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg1_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg2_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - server = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + sub_acl = db.Column(db.String(100), nullable=False, server_default='') + tg1_acl = db.Column(db.String(100), nullable=False, server_default='') + tg2_acl = db.Column(db.String(100), nullable=False, server_default='') + server = db.Column(db.String(100), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') class ServerList(db.Model): __tablename__ = 'server_list' - name = db.Column(db.String(100, collation='NOCASE'), unique=True, primary_key=True) + name = db.Column(db.String(100), unique=True, primary_key=True) secret = db.Column(db.String(255), nullable=False, server_default='') ## public_list = db.Column(db.Boolean(), nullable=False, server_default='1') id = db.Column(db.Integer(), primary_key=False) - ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + ip = db.Column(db.String(100), nullable=False, server_default='') port = db.Column(db.Integer(), primary_key=False) - global_path = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='./') + global_path = db.Column(db.String(100), nullable=False, server_default='./') global_ping_time = db.Column(db.Integer(), primary_key=False) global_max_missed = db.Column(db.Integer(), primary_key=False) global_use_acl = db.Column(db.Boolean(), nullable=False, server_default='1') - global_reg_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='PERMIT:ALL') - global_sub_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='DENY:1') - global_tg1_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='PERMIT:ALL') - global_tg2_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='PERMIT:ALL') + global_reg_acl = db.Column(db.String(100), nullable=False, server_default='PERMIT:ALL') + global_sub_acl = db.Column(db.String(100), nullable=False, server_default='DENY:1') + global_tg1_acl = db.Column(db.String(100), nullable=False, server_default='PERMIT:ALL') + global_tg2_acl = db.Column(db.String(100), nullable=False, server_default='PERMIT:ALL') ai_try_download = db.Column(db.Boolean(), nullable=False, server_default='1') - ai_path = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='./') - ai_peer_file = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='peer_ids.json') - ai_subscriber_file = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='subscriber_ids.json') - ai_tgid_file = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='talkgroup_ids.json') - ai_peer_url = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='https://www.radioid.net/static/rptrs.json') - ai_subs_url = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='https://www.radioid.net/static/users.json') + ai_path = db.Column(db.String(100), nullable=False, server_default='./') + ai_peer_file = db.Column(db.String(100), nullable=False, server_default='peer_ids.json') + ai_subscriber_file = db.Column(db.String(100), nullable=False, server_default='subscriber_ids.json') + ai_tgid_file = db.Column(db.String(100), nullable=False, server_default='talkgroup_ids.json') + ai_peer_url = db.Column(db.String(100), nullable=False, server_default='https://www.radioid.net/static/rptrs.json') + ai_subs_url = db.Column(db.String(100), nullable=False, server_default='https://www.radioid.net/static/users.json') ai_stale = db.Column(db.Integer(), primary_key=False, server_default='7') # Pull from config file for now ## um_append_int = db.Column(db.Integer(), primary_key=False, server_default='2') um_shorten_passphrase = db.Column(db.Boolean(), nullable=False, server_default='0') - um_burn_file = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='./burned_ids.txt') + um_burn_file = db.Column(db.String(100), nullable=False, server_default='./burned_ids.txt') # Pull from config file for now ## um_burn_int = db.Column(db.Integer(), primary_key=False, server_default='6') report_enable = db.Column(db.Boolean(), nullable=False, server_default='1') report_interval = db.Column(db.Integer(), primary_key=False, server_default='60') report_port = db.Column(db.Integer(), primary_key=False, server_default='4321') - report_clients =db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='127.0.0.1') + report_clients =db.Column(db.String(100), nullable=False, server_default='127.0.0.1') unit_time = db.Column(db.Integer(), primary_key=False, server_default='10080') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') class MasterList(db.Model): __tablename__ = 'master_list' id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + name = db.Column(db.String(100), nullable=False, server_default='') static_positions = db.Column(db.Boolean(), nullable=False, server_default='0') repeat = db.Column(db.Boolean(), nullable=False, server_default='1') active = db.Column(db.Boolean(), nullable=False, server_default='1') max_peers = db.Column(db.Integer(), primary_key=False, server_default='10') - ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + ip = db.Column(db.String(100), nullable=False, server_default='') port = db.Column(db.Integer(), primary_key=False) enable_um = db.Column(db.Boolean(), nullable=False, server_default='1') - passphrase = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + passphrase = db.Column(db.String(100), nullable=False, server_default='') group_hang_time = db.Column(db.Integer(), primary_key=False, server_default='5') use_acl = db.Column(db.Boolean(), nullable=False, server_default='1') - reg_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - sub_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg1_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg2_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + reg_acl = db.Column(db.String(100), nullable=False, server_default='') + sub_acl = db.Column(db.String(100), nullable=False, server_default='') + tg1_acl = db.Column(db.String(100), nullable=False, server_default='') + tg2_acl = db.Column(db.String(100), nullable=False, server_default='') enable_unit = db.Column(db.Boolean(), nullable=False, server_default='1') - server = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + server = db.Column(db.String(100), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') public_list = db.Column(db.Boolean(), nullable=False, server_default='1') class ProxyList(db.Model): __tablename__ = 'proxy_list' id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + name = db.Column(db.String(100), nullable=False, server_default='') active = db.Column(db.Boolean(), nullable=False, server_default='1') static_positions = db.Column(db.Boolean(), nullable=False, server_default='0') repeat = db.Column(db.Boolean(), nullable=False, server_default='1') enable_um = db.Column(db.Boolean(), nullable=False, server_default='1') - passphrase = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + passphrase = db.Column(db.String(100), nullable=False, server_default='') external_proxy = db.Column(db.Boolean(), nullable=False, server_default='0') external_port = db.Column(db.Integer(), primary_key=False) group_hang_time = db.Column(db.Integer(), primary_key=False) internal_start_port = db.Column(db.Integer(), primary_key=False) internal_stop_port = db.Column(db.Integer(), primary_key=False) use_acl = db.Column(db.Boolean(), nullable=False, server_default='1') - reg_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - sub_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg1_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg2_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + reg_acl = db.Column(db.String(100), nullable=False, server_default='') + sub_acl = db.Column(db.String(100), nullable=False, server_default='') + tg1_acl = db.Column(db.String(100), nullable=False, server_default='') + tg2_acl = db.Column(db.String(100), nullable=False, server_default='') enable_unit = db.Column(db.Boolean(), nullable=False, server_default='1') - server = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + server = db.Column(db.String(100), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') public_list = db.Column(db.Boolean(), nullable=False, server_default='1') class OBP(db.Model): __tablename__ = 'OpenBridge' id = db.Column(db.Integer(), primary_key=True) - name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + name = db.Column(db.String(100), nullable=False, server_default='') enabled = db.Column(db.Boolean(), nullable=False, server_default='1') network_id = db.Column(db.Integer(), primary_key=False) - ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + ip = db.Column(db.String(100), nullable=False, server_default='') port = db.Column(db.Integer(), primary_key=False) - passphrase = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - target_ip = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + passphrase = db.Column(db.String(100), nullable=False, server_default='') + target_ip = db.Column(db.String(100), nullable=False, server_default='') target_port = db.Column(db.Integer(), primary_key=False) both_slots = db.Column(db.Boolean(), nullable=False, server_default='1') use_acl = db.Column(db.Boolean(), nullable=False, server_default='1') - sub_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - tg_acl = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + sub_acl = db.Column(db.String(100), nullable=False, server_default='') + tg_acl = db.Column(db.String(100), nullable=False, server_default='') enable_unit = db.Column(db.Boolean(), nullable=False, server_default='1') - server = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - notes = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + server = db.Column(db.String(100), nullable=False, server_default='') + notes = db.Column(db.String(100), nullable=False, server_default='') class BridgeRules(db.Model): __tablename__ = 'bridge_rules' id = db.Column(db.Integer(), primary_key=True) - bridge_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - system_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + bridge_name = db.Column(db.String(100), nullable=False, server_default='') + system_name = db.Column(db.String(100), nullable=False, server_default='') ts = db.Column(db.Integer(), primary_key=False) tg = db.Column(db.Integer(), primary_key=False) active = db.Column(db.Boolean(), nullable=False, server_default='1') timeout = db.Column(db.Integer(), primary_key=False) - to_type = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - on = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - off = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - reset = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - server = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + to_type = db.Column(db.String(100), nullable=False, server_default='') + on = db.Column(db.String(100), nullable=False, server_default='') + off = db.Column(db.String(100), nullable=False, server_default='') + reset = db.Column(db.String(100), nullable=False, server_default='') + server = db.Column(db.String(100), nullable=False, server_default='') public_list = db.Column(db.Boolean(), nullable=False, server_default='0') proxy = db.Column(db.Boolean(), nullable=False, server_default='0') class BridgeList(db.Model): __tablename__ = 'bridge_list' id = db.Column(db.Integer(), primary_key=True) - bridge_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') - description = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='') + bridge_name = db.Column(db.String(100), nullable=False, server_default='') + description = db.Column(db.String(100), nullable=False, server_default='') public_list = db.Column(db.Boolean(), nullable=False, server_default='0') tg = db.Column(db.Integer(), primary_key=False) @@ -712,6 +735,7 @@ def create_app(): elif request.method == 'POST': # and request.form.get('callsign') and request.form.get('subject') and request.form.get('message'): u = User.query.filter_by(username=request.args.get('callsign')).first() msg = Message(recipients=[u.email], + sender=(title, MAIL_DEFAULT_SENDER), subject=request.form.get('subject'), body=request.form.get('message')) mail.send(msg) @@ -880,8 +904,9 @@ def create_app(): edit_user.initial_admin_approved = True db.session.commit() msg = Message(recipients=[edit_user.email], - subject='Account Approval - ' + title, - body='''You are receiving this message because an administrator has approved your account. You may now login and view your MMDVM passphrase(s).''') + sender=(title, MAIL_DEFAULT_SENDER), + subject='Account Approval', + body='''You are receiving this message because an administrator has approved your account. You may now login and use ''' + title + '''.''') mail.send(msg) content = '''

User approved: ''' + str(request.args.get('callsign')) + '''

\n''' @@ -1457,7 +1482,7 @@ def create_app(): content = content + '' return render_template('flask_user_layout.html', markup_content = Markup(content)) - @app.route('/self_care') + @app.route('/user_tg') def tg_status(): cu = current_user u = User.query.filter_by(username=cu.username).first() @@ -4967,4 +4992,4 @@ def create_app(): if __name__ == '__main__': app = create_app() - app.run(debug = True, port=ums_port, host=ums_host) + app.run(debug = True, port=hws_port, host=hws_host) diff --git a/user_managment/config-SAMPLE.py b/user_managment/config-SAMPLE.py index c96f1e9..db58108 100644 --- a/user_managment/config-SAMPLE.py +++ b/user_managment/config-SAMPLE.py @@ -1,33 +1,65 @@ ''' -Settings for user management portal. +Settings for HBNet Web Server. ''' -# Database location -db_location = 'sqlite:///./users.db' +# 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' +#legacy_passphrase = 'passw0rd' -# Trim passphrases to 8 characters -use_short_passphrase = False -# Title of the Dashboard -title = 'MMDVM User Portal' -# Port to run server -ums_port = 8080 -# IP to run server on -ums_host = '127.0.0.1' - -url = 'http://localhost:8080' +# 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 -shared_secrets = ['test'] - - +# Set to a value between 1 - 99. This value is used for compromised passphrases. burn_int = 5 -legacy_passphrase = 'passw0rd' +# 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' @@ -38,12 +70,10 @@ MAIL_USERNAME = 'app@gmail.com' MAIL_PASSWORD = 'password' MAIL_DEFAULT_SENDER = '"' + title + '" ' -# UMS settings -secret_key = 'SUPER SECRET LONG KEY' - +# User settings settings USER_ENABLE_EMAIL = True -USER_ENABLE_USERNAME = True # Enable username authentication -USER_REQUIRE_RETYPE_PASSWORD = True # Simplify register form +USER_ENABLE_USERNAME = True +USER_REQUIRE_RETYPE_PASSWORD = True USER_ENABLE_CHANGE_USERNAME = False USER_ENABLE_MULTIPLE_EMAILS = True USER_ENABLE_CONFIRM_EMAIL = True @@ -51,12 +81,7 @@ USER_ENABLE_REGISTER = True USER_AUTO_LOGIN_AFTER_CONFIRM = False USER_SHOW_USERNAME_DOES_NOT_EXIST = True -# Gateway contact info displayed on about page. -contact_name = 'your name' -contact_call = 'N0CALL' -contact_email = 'email@example.org' -contact_website = 'https://hbl.ink' -# Time format for display +# Time format for display on some pages time_format = '%H:%M:%S - %m/%d/%y' diff --git a/user_managment/templates/flask_user_layout.html b/user_managment/templates/flask_user_layout.html index c42c379..d6d44c9 100644 --- a/user_managment/templates/flask_user_layout.html +++ b/user_managment/templates/flask_user_layout.html @@ -53,7 +53,7 @@ {% endif %} Help View Passphrase(s) -Self Care +Current TGs Edit {{ current_user.username or current_user.email }} Sign out {% endif %}