diff --git a/requirements.txt b/requirements.txt index bd5a2b5..2972670 100755 --- a/requirements.txt +++ b/requirements.txt @@ -13,6 +13,5 @@ email_validator flask_babelex pymysql folium -json requests libsrc diff --git a/web/app.py b/web/app.py new file mode 100644 index 0000000..e391739 --- /dev/null +++ b/web/app.py @@ -0,0 +1,5127 @@ +# 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 +from flask_user import login_required, UserManager, UserMixin, user_registered, roles_required +from werkzeug.security import check_password_hash +from flask_login import current_user, login_user, logout_user +from wtforms import StringField, SubmitField +import requests +import base64, hashlib +from dmr_utils3.utils import int_id, bytes_4 +from config import * +import ast +import json +import datetime, time +from flask_babelex import Babel +import libscrc +import random +from flask_mail import Message, Mail +from socket import gethostbyname + + +try: + from gen_script_template import gen_script +except: + pass + +import os, ast +##import hb_config + +script_links = {} +active_tgs = {} + +# Query radioid.net for list of IDs +def get_ids(callsign): + try: + url = "https://www.radioid.net" + response = requests.get(url+"/api/dmr/user/?callsign=" + callsign) + result = response.json() +## print(result) + # id_list = [] + id_list = {} + f_name = result['results'][0]['fname'] + l_name = result['results'][0]['surname'] + try: + city = str(result['results'][0]['city'] + ', ' + result['results'][0]['state'] + ', ' + result['results'][0]['country']) + except: + city = result['results'][0]['country'] + for i in result['results']: + id_list[i['id']] = 0 + return str([id_list, f_name, l_name, city]) + except: + return str([{}, '', '', '']) + + +# Return string in NATO phonetics +def convert_nato(string): + d_nato = { 'A': 'ALPHA', 'B': 'BRAVO', 'C': 'CHARLIE', 'D': 'DELTA', + 'E': 'ECHO', 'F': 'FOXTROT', 'G': 'GOLF', 'H': 'HOTEL', + 'I': 'INDIA', 'J': 'JULIETT','K': 'KILO', 'L': 'LIMA', + 'M': 'MIKE', 'N': 'NOVEMBER','O': 'OSCAR', 'P': 'PAPA', + 'Q': 'QUEBEC', 'R': 'ROMEO', 'S': 'SIERRA', 'T': 'TANGO', + 'U': 'UNIFORM', 'V': 'VICTOR', 'W': 'WHISKEY', 'X': 'X-RAY', + 'Y': 'YANKEE', 'Z': 'ZULU', '0': 'zero(0)', '1': 'one(1)', + '2': 'two(2)', '3': 'three(3)', '4': 'four(4)', '5': 'five(5)', + '6': 'six(6)', '7': 'seven(7)', '8': 'eight(8)', '9': 'nine(9)', + 'a': 'alpha', 'b': 'bravo', 'c': 'charlie', 'd': 'delta', + 'e': 'echo', 'f': 'foxtrot', 'g': 'golf', 'h': 'hotel', + 'i': 'india', 'j': 'juliett','k': 'kilo', 'l': 'lima', + 'm': 'mike', 'n': 'november','o': 'oscar', 'p': 'papa', + 'q': 'quebec', 'r': 'romeo', 's': 'sierra', 't': 'tango', + 'u': 'uniform', 'v': 'victor', 'w': 'whiskey', 'x': 'x-ray', + 'y': 'yankee', 'z': 'Zulu'} + ns = '' + for c in string: + try: + ns = ns + d_nato[c] + ' ' + except: + ns = ns + c + ' ' + return ns + +# Class-based application configuration +class ConfigClass(object): + from config import MAIL_SERVER, MAIL_PORT, MAIL_USE_SSL, MAIL_USE_TLS, MAIL_USERNAME, MAIL_PASSWORD, MAIL_DEFAULT_SENDER, USER_ENABLE_EMAIL, USER_ENABLE_USERNAME, USER_REQUIRE_RETYPE_PASSWORD, USER_ENABLE_CHANGE_USERNAME, USER_ENABLE_MULTIPLE_EMAILS, USER_ENABLE_CONFIRM_EMAIL, USER_ENABLE_REGISTER, USER_AUTO_LOGIN_AFTER_CONFIRM, USER_SHOW_USERNAME_DOES_NOT_EXIST + """ Flask application config """ + + # Flask settings + SECRET_KEY = secret_key + + # Flask-SQLAlchemy settings + SQLALCHEMY_DATABASE_URI = db_location # File-based SQL database + SQLALCHEMY_TRACK_MODIFICATIONS = False # Avoids SQLAlchemy warning + + # Flask-User settings + USER_APP_NAME = title # Shown in and email templates and page footers + USER_EMAIL_SENDER_EMAIL = MAIL_DEFAULT_SENDER + USER_EDIT_USER_PROFILE_TEMPLATE = 'flask_user/edit_user_profile.html' + + + + + +# Setup Flask-User +def create_app(): + """ Flask application factory """ + + # Create Flask app load app.config + mail = Mail() + app = Flask(__name__) + app.config.from_object(__name__+'.ConfigClass') + + # Initialize Flask-BabelEx + babel = Babel(app) + + # Initialize Flask-SQLAlchemy + db = SQLAlchemy(app) + + # Define the User data-model. + # NB: Make sure to add flask_user UserMixin !!! + class User(db.Model, UserMixin): + __tablename__ = 'users' + id = db.Column(db.Integer, primary_key=True) + active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1') + + # 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,), 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), nullable=False, unique=True) + + # User information + 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 + roles = db.relationship('Role', secondary='user_roles') + + # Define the Role data-model + class Role(db.Model): + __tablename__ = 'roles' + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(50), unique=True) + + # Define the UserRoles association table + class UserRoles(db.Model): + __tablename__ = 'user_roles' + id = db.Column(db.Integer(), primary_key=True) + user_id = db.Column(db.Integer(), db.ForeignKey('users.id', ondelete='CASCADE')) + 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' + 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), 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), nullable=False, server_default='127.0.0.1') + port = db.Column(db.Integer(), primary_key=False) + 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), 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), 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), nullable=False, server_default='') + use_acl = db.Column(db.Boolean(), nullable=False, server_default='0') + 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), 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), nullable=False, server_default='127.0.0.1') + port = db.Column(db.Integer(), primary_key=False) + 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), 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), 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), 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), 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), nullable=False, server_default='') + port = db.Column(db.Integer(), primary_key=False) + 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), nullable=False, server_default='') + port = db.Column(db.Integer(), primary_key=False) + 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), 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), 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), 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), 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), 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) + + class GPS_LocLog(db.Model): + __tablename__ = 'gps_locations' + id = db.Column(db.Integer(), primary_key=True) + callsign = db.Column(db.String(100), nullable=False, server_default='') + comment = db.Column(db.String(100), nullable=False, server_default='') + lat = db.Column(db.String(100), nullable=False, server_default='') + lon = db.Column(db.String(100), nullable=False, server_default='') + time = db.Column(db.DateTime()) + server = db.Column(db.String(100), nullable=False, server_default='') + system_name = db.Column(db.String(100), nullable=False, server_default='') + dmr_id = db.Column(db.Integer(), primary_key=False) + + class BulletinBoard(db.Model): + __tablename__ = 'sms_bb' + id = db.Column(db.Integer(), primary_key=True) + callsign = db.Column(db.String(100), nullable=False, server_default='') + bulletin = db.Column(db.String(100), nullable=False, server_default='') + time = db.Column(db.DateTime()) + server = db.Column(db.String(100), nullable=False, server_default='') + system_name = db.Column(db.String(100), nullable=False, server_default='') + dmr_id = db.Column(db.Integer(), primary_key=False) + + class SMSLog(db.Model): + __tablename__ = 'sms_log' + id = db.Column(db.Integer(), primary_key=True) + snd_callsign = db.Column(db.String(100), nullable=False, server_default='') + rcv_callsign = db.Column(db.String(100), nullable=False, server_default='') + message = db.Column(db.String(100), nullable=False, server_default='') + time = db.Column(db.DateTime()) + server = db.Column(db.String(100), nullable=False, server_default='') + system_name = db.Column(db.String(100), nullable=False, server_default='') + snd_id = db.Column(db.Integer(), primary_key=False) + rcv_id = db.Column(db.Integer(), primary_key=False) + + class MailBox(db.Model): + __tablename__ = 'sms_aprs_mailbox' + id = db.Column(db.Integer(), primary_key=True) + snd_callsign = db.Column(db.String(100), nullable=False, server_default='') + rcv_callsign = db.Column(db.String(100), nullable=False, server_default='') + message = db.Column(db.String(100), nullable=False, server_default='') + time = db.Column(db.DateTime()) + server = db.Column(db.String(100), nullable=False, server_default='') + system_name = db.Column(db.String(100), nullable=False, server_default='') + snd_id = db.Column(db.Integer(), primary_key=False) + rcv_id = db.Column(db.Integer(), primary_key=False) + + + + + # Customize Flask-User + class CustomUserManager(UserManager): + # Override or extend the default login view method + def login_view(self): + """Prepare and process the login form.""" + + # Authenticate username/email and login authenticated users. + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_LOGIN_ENDPOINT) + safe_reg_next = self._get_safe_next_url('reg_next', self.USER_AFTER_REGISTER_ENDPOINT) + + # Immediately redirect already logged in users + if self.call_or_get(current_user.is_authenticated) and self.USER_AUTO_LOGIN_AT_LOGIN: + return redirect(safe_next_url) + + # Initialize form + login_form = self.LoginFormClass(request.form) # for login.html + register_form = self.RegisterFormClass() # for login_or_register.html + if request.method != 'POST': + login_form.next.data = register_form.next.data = safe_next_url + login_form.reg_next.data = register_form.reg_next.data = safe_reg_next + + # Process valid POST + if request.method == 'POST' and login_form.validate(): + # Retrieve User + user = None + user_email = None + if self.USER_ENABLE_USERNAME: + # Find user record by username + user = self.db_manager.find_user_by_username(login_form.username.data) + + # Find user record by email (with form.username) + if not user and self.USER_ENABLE_EMAIL: + user, user_email = self.db_manager.get_user_and_user_email_by_email(login_form.username.data) + else: + # Find user by email (with form.email) + user, user_email = self.db_manager.get_user_and_user_email_by_email(login_form.email.data) + #Add aditional message + if not user.initial_admin_approved: + flash('You account is waiting for approval from an administrator. See the Help page for more information. You will receive an email when your account is approved.', 'success') + + if user: + # Log user in + safe_next_url = self.make_safe_url(login_form.next.data) + return self._do_login_user(user, safe_next_url, login_form.remember_me.data) + + # Render form + self.prepare_domain_translations() + template_filename = self.USER_LOGIN_AUTH0_TEMPLATE if self.USER_ENABLE_AUTH0 else self.USER_LOGIN_TEMPLATE + return render_template(template_filename, + form=login_form, + login_form=login_form, + register_form=register_form) + + #user_manager = UserManager(app, db, User) + user_manager = CustomUserManager(app, db, User) + + + # Create all database tables + db.create_all() + + + if not User.query.filter(User.username == 'admin').first(): + user = User( + username='admin', + email='admin@no.reply', + email_confirmed_at=datetime.datetime.utcnow(), + password=user_manager.hash_password('admin'), + initial_admin_approved = True, + notes='Default admin account created during installation.', + dmr_ids='{}' + ) + user.roles.append(Role(name='Admin')) + user.roles.append(Role(name='User')) + db.session.add(user) + db.session.commit() + + # Query radioid.net for list of DMR IDs, then add to DB + @user_registered.connect_via(app) + def _after_user_registered_hook(sender, user, **extra): + edit_user = User.query.filter(User.username == user.username).first() + radioid_data = ast.literal_eval(get_ids(user.username)) + edit_user.dmr_ids = str(radioid_data[0]) + edit_user.first_name = str(radioid_data[1]) + edit_user.last_name = str(radioid_data[2]) + edit_user.city = str(radioid_data[3]) + user_role = UserRoles( + user_id=edit_user.id, + role_id=2, + ) + db.session.add(user_role) + if default_account_state == False: + edit_user.active = default_account_state + edit_user.initial_admin_approved = False + db.session.commit() + + def gen_passphrase(dmr_id): + _new_peer_id = bytes_4(int(str(dmr_id)[:7])) + trimmed_id = int(str(dmr_id)[:7]) + b_list = get_burnlist() + # print(b_list) + burned = False + for ui in b_list.items(): + # print(ui) + #print(b_list) + if ui[0] == trimmed_id: + if ui[0] != 0: + calc_passphrase = hashlib.sha256(str(extra_1).encode() + str(extra_int_1).encode() + str(_new_peer_id).encode()[-3:]).hexdigest().upper().encode()[::14] + base64.b64encode(bytes.fromhex(str(hex(libscrc.ccitt((_new_peer_id) + b_list[trimmed_id].to_bytes(2, 'big') + burn_int.to_bytes(2, 'big') + append_int.to_bytes(2, 'big') + bytes.fromhex(str(hex(libscrc.posix((_new_peer_id) + b_list[trimmed_id].to_bytes(2, 'big') + burn_int.to_bytes(2, 'big') + append_int.to_bytes(2, 'big'))))[2:].zfill(8)))))[2:].zfill(4)) + (_new_peer_id) + b_list[trimmed_id].to_bytes(2, 'big') + burn_int.to_bytes(2, 'big') + append_int.to_bytes(2, 'big') + bytes.fromhex(str(hex(libscrc.posix((_new_peer_id) + b_list[trimmed_id].to_bytes(2, 'big') + burn_int.to_bytes(2, 'big') + append_int.to_bytes(2, 'big'))))[2:].zfill(8))) + hashlib.sha256(str(extra_2).encode() + str(extra_int_2).encode() + str(_new_peer_id).encode()[-3:]).hexdigest().upper().encode()[::14] + burned = True + if burned == False: + calc_passphrase = hashlib.sha256(str(extra_1).encode() + str(extra_int_1).encode() + str(_new_peer_id).encode()[-3:]).hexdigest().upper().encode()[::14] + base64.b64encode(bytes.fromhex(str(hex(libscrc.ccitt((_new_peer_id) + append_int.to_bytes(2, 'big') + bytes.fromhex(str(hex(libscrc.posix((_new_peer_id) + append_int.to_bytes(2, 'big'))))[2:].zfill(8)))))[2:].zfill(4)) + (_new_peer_id) + append_int.to_bytes(2, 'big') + bytes.fromhex(str(hex(libscrc.posix((_new_peer_id) + append_int.to_bytes(2, 'big'))))[2:].zfill(8))) + hashlib.sha256(str(extra_2).encode() + str(extra_int_2).encode() + str(_new_peer_id).encode()[-3:]).hexdigest().upper().encode()[::14] + if use_short_passphrase == True: + trim_pass = str(calc_passphrase)[2:-1] + new_pass = trim_pass[::int(shorten_sample)][-int(shorten_length):] + return str(new_pass) + elif use_short_passphrase ==False: + return str(calc_passphrase)[2:-1] + + + def update_from_radioid(callsign): + edit_user = User.query.filter(User.username == callsign).first() + #edit_user.dmr_ids = str(ast.literal_eval(get_ids(callsign))[0]) + radioid_dict = ast.literal_eval(get_ids(callsign))[0] + db_id_dict = ast.literal_eval(edit_user.dmr_ids) + new_id_dict = db_id_dict.copy() + for i in radioid_dict.items(): + if i[0] in db_id_dict: + pass + elif i[0] not in db_id_dict: + new_id_dict[i[0]] = 0 + edit_user.dmr_ids = str(new_id_dict) + edit_user.first_name = str(ast.literal_eval(get_ids(callsign))[1]) + edit_user.last_name = str(ast.literal_eval(get_ids(callsign))[2]) + edit_user.city = str(ast.literal_eval(get_ids(callsign))[3]) + + db.session.commit() + + # The Home page is accessible to anyone + @app.route('/') + def home_page(): + #content = Markup('Index') + return render_template('index.html') #, markup_content = content) + + @app.route('/help') + def help_page(): + #content = Markup('Index') + + return render_template('help.html') + + @app.route('/generate_passphrase/pi-star', methods = ['GET']) + @login_required + def gen_pi_star(): + try: + u = current_user + ## print(u.username) + id_dict = ast.literal_eval(u.dmr_ids) + #u = User.query.filter_by(username=user).first() + ## print(user_id) + ## print(request.args.get('mode')) + ## if request.args.get('mode') == 'generated': + content = ''' + + + + + + +
+

Pi-Star Instructions

+

 

+

1: Log into your Pi-Star device.
2: Change to Read-Write mode of the device by issuing the command:

+
rpi-rw
+


3a: Change to the root user by issuing the command:

+
sudo su -
+


3b: Now type pwd and verify you get a return indicating you are in the /root directory. If you are in the wrong directory, it is because you're not following the instructions and syntax above! This is a show stopper, and your attempt to load the files correctly, will fail !

4: Issue one of the commands below for the chosen DMR ID:

+

Note: Link can be used only once. To run the script again, simply reload the page and paste a new command into the command line.

+ +''' + for i in id_dict.items(): + #if i[1] == '': + link_num = str(random.randint(1,99999999)).zfill(8) + str(time.time()) + str(random.randint(1,99999999)).zfill(8) + script_links[i[0]] = link_num + content = content + '''\n +

DMR ID: ''' + str(i[0]) + ''':

+

bash <(curl -s "''' + str(url) + '/get_script?dmr_id=' + str(i[0]) + '&number=' + str(link_num) + '''")

+

 

+ ''' + #else: + # content = content + '''\n

Error

''' + content = content + '''\n


5: When asked for server ports, use the information above to populate the correct fields.
6: Reboot your Pi-Star device

+
+

 

''' + except: + content = Markup('No DMR IDs found or other error.') + + + #return str(content) + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + + @app.route('/generate_passphrase', methods = ['GET']) + @login_required + def gen(): + #print(str(gen_passphrase(3153591))) #(int(i[0]))) + try: + #content = Markup('The HTML String') + #user_id = request.args.get('user_id') + u = current_user + ## print(u.username) + id_dict = ast.literal_eval(u.dmr_ids) + #u = User.query.filter_by(username=user).first() + ## print(user_id) + ## print(request.args.get('mode')) + ## if request.args.get('mode') == 'generated': + #print(id_dict) + content = '\n' + for i in id_dict.items(): + if isinstance(i[1], int) == True and i[1] != 0: + link_num = str(random.randint(1,99999999)).zfill(8) + str(time.time()) + str(random.randint(1,99999999)).zfill(8) + script_links[i[0]] = link_num + #print(script_links) + content = content + '''\n + + + + + + +
+

Your passphrase for ''' + str(i[0]) + ''':

+

Copy and paste: ''' + str(gen_passphrase(int(i[0]))) + '''

+
+ +

Phonetically spelled: ''' + convert_nato(str(gen_passphrase(int(i[0])))) + '''

+ +
+

 

+ ''' + elif i[1] == 0: + link_num = str(random.randint(1,99999999)).zfill(8) + str(time.time()) + str(random.randint(1,99999999)).zfill(8) + script_links[i[0]] = link_num + #print(script_links) + content = content + '''\n + + + + + + +
+

Your passphrase for ''' + str(i[0]) + ''':

+

Copy and paste: ''' + str(gen_passphrase(int(i[0]))) + '''

+
+ +

Phonetically spelled: ''' + convert_nato(str(gen_passphrase(int(i[0])))) + '''

+ +
+

 

+ ''' + elif i[1] == '': + content = content + ''' + + + + + + +
+

Your passphrase for ''' + str(i[0]) + ''':

+

Copy and paste: ''' + legacy_passphrase + '''

+
+

Phonetically spelled: ''' + convert_nato(legacy_passphrase) + '''

+
+

 

''' + else: + content = content + ''' + + + + + + +
+

Your passphrase for ''' + str(i[0]) + ''':

+

Copy and paste: ''' + str(i[1]) + '''

+
+

Phonetically spelled: ''' + convert_nato(str(i[1])) + '''

+
+

 

+ ''' + #content = content + '\n\n' + str(script_links[i[0]]) + except: + content = Markup('No DMR IDs found or other error.') + + + #return str(content) + return render_template('view_passphrase.html', markup_content = Markup(content)) + +## # The Members page is only accessible to authenticated users via the @login_required decorator +## @app.route('/members') +## @login_required # User must be authenticated +## def member_page(): +## content = 'Mem only' +## return render_template('flask_user_layout.html', markup_content = content) + + @app.route('/update_ids', methods=['POST', 'GET']) + @login_required # User must be authenticated + def update_info(): + #print(request.args.get('callsign')) + #print(current_user.username) + if request.args.get('callsign') == current_user.username or request.args.get('callsign') and request.args.get('callsign') != current_user.username and current_user.has_roles('Admin'): + content = '

Updated your information.

' + update_from_radioid(request.args.get('callsign')) + else: + content = ''' +

Use this page to sync changes from RadioID.net with this system (such as a new DMR ID, name change, etc.).

+

Updating your information from RadioID.net will overwrite any custom authentication passphrases, your city, and name in the database. Are you sure you want to continue?

+

 

+

Yes, update my information.

+ +''' + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + @app.route('/email_user', methods=['POST', 'GET']) + @roles_required('Admin') + @login_required # User must be authenticated + def email_user(): + + if request.method == 'GET' and request.args.get('callsign'): + content = ''' +

Send email to user: ''' + request.args.get('callsign') + '''

+ + + + + + +
+







+
+

 

''' + 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) + content = '

Sent email to: ' + u.email + '

' + else: + content = '''

Find user in "List Users", then click on the email link.'

''' + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + + @app.route('/list_users') + @roles_required('Admin') + @login_required # User must be authenticated + def list_users(): + u = User.query.all() + # Broken for now, link taken out -

List/edit users:

 

Enter Callsign

+ u_list = '''

 

+ + + + + + + +''' + for i in u: + u_list = u_list + ''' + + + + + + + +'''+ '\n' + content = u_list + ''' +
CallsignNameEnabledDMR ID:AuthenticationNotes
 ''' + str(i.username) + '''  ''' + str(i.first_name) + ' ' + str(i.last_name) + '''  ''' + str(i.active) + '''  ''' + str(i.dmr_ids) + '''  ''' + str(i.notes) + ''' 
+

 

''' + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + @app.route('/approve_users', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') # Use of @roles_required decorator + def approve_list(): + u = User.query.all() + wait_list = '''

Users waiting for approval:

 

+ + + + + + +''' + for i in u: +## print(i.username) +## print(i.initial_admin_approved) + if i.initial_admin_approved == False: + wait_list = wait_list+ ''' + + + + + + +'''+ '\n' + content = wait_list + ''' +
CallsignNameEnabledDMR ID:Authentication
 ''' + str(i.username) + '''  ''' + str(i.first_name) + ' ' + str(i.last_name) + '''  ''' + str(i.active) + '''  ''' + str(i.dmr_ids) + ''' 
+

 

''' + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + + # The Admin page requires an 'Admin' role. + @app.route('/edit_user', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') # Use of @roles_required decorator + def admin_page(): + #print(request.args.get('callsign')) + #print(request.args.get('callsign')) +## if request.method == 'POST' and request.form.get('callsign'): +## #result = request.json +## callsign = request.form.get('callsign') +## u = User.query.filter_by(username=callsign).first() +## content = u.dmr_ids + if request.method == 'POST' and request.args.get('callsign') == None: + content = 'Not found' + elif request.method == 'POST' and request.args.get('callsign') and request.form.get('user_status'): + user = request.args.get('callsign') + #print(user) + edit_user = User.query.filter(User.username == user).first() + content = '' + if request.form.get('user_status') != edit_user.active: + if request.form.get('user_status') == "True": + edit_user.active = True + content = content + '''

User ''' + str(user) + ''' has been enabled.

\n''' + if request.form.get('user_status') == "False": + edit_user.active = False + content = content + '''

User ''' + str(user) + ''' has been disabled.

\n''' +## print(request.form.get('username')) + if user != request.form.get('username'): +#### #print(edit_user.username) + content = content + '''

User ''' + str(user) + ''' changed to ''' + request.form.get('username') + '''.

\n''' + edit_user.username = request.form.get('username') + if request.form.get('email') != edit_user.email: + edit_user.email = request.form.get('email') + content = content + '''

Changed email for user: ''' + str(user) + ''' to ''' + request.form.get('email') + '''

\n''' + if request.form.get('notes') != edit_user.notes: + edit_user.notes = request.form.get('notes') + content = content + '''

Changed notes for user: ''' + str(user) + '''.

\n''' + if request.form.get('password') != '': + edit_user.password = user_manager.hash_password(request.form.get('password')) + content = content + '''

Changed password for user: ''' + str(user) + '''

\n''' + if request.form.get('dmr_ids') != edit_user.dmr_ids: + edit_user.dmr_ids = request.form.get('dmr_ids') + dmr_auth_dict = ast.literal_eval(request.form.get('dmr_ids')) + for id_user in dmr_auth_dict: + if isinstance(dmr_auth_dict[id_user], int) == True and dmr_auth_dict[id_user] != 0: + #print('burn it') + if id_user in get_burnlist(): +## print('burned') + if get_burnlist()[id_user] != dmr_auth_dict[id_user]: +## print('update vers') + update_burnlist(id_user, dmr_auth_dict[id_user]) + else: + pass +## print('no update') + else: + add_burnlist(id_user, dmr_auth_dict[id_user]) +## print('not in list, adding') + elif isinstance(dmr_auth_dict[id_user], int) == False and id_user in get_burnlist(): + delete_burnlist(id_user) +## print('remove from burn list - string') + elif dmr_auth_dict[id_user] == 0: +## print('remove from burn list') + if id_user in get_burnlist(): + delete_burnlist(id_user) + + + + content = content + '''

Changed authentication settings for user: ''' + str(user) + '''

\n''' + db.session.commit() + #edit_user = User.query.filter(User.username == request.args.get('callsign')).first() + elif request.method == 'GET' and request.args.get('callsign') and request.args.get('delete_user') == 'true': + delete_user = User.query.filter(User.username == request.args.get('callsign')).first() + db.session.delete(delete_user) + db.session.commit() + content = '''

Deleted user: ''' + str(delete_user.username) + '''

\n''' + + elif request.method == 'GET' and request.args.get('callsign') and request.args.get('make_user_admin') == 'true': + u = User.query.filter_by(username=request.args.get('callsign')).first() + u_role = UserRoles.query.filter_by(user_id=u.id).first() + u_role.role_id = 1 + db.session.commit() + content = '''

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

\n''' + + elif request.method == 'GET' and request.args.get('callsign') and request.args.get('make_user_admin') == 'false': + u = User.query.filter_by(username=request.args.get('callsign')).first() + u_role = UserRoles.query.filter_by(user_id=u.id).first() + u_role.role_id = 2 + db.session.commit() + content = '''

Admin now a user: ''' + str(request.args.get('callsign') ) + '''

\n''' + + elif request.method == 'GET' and request.args.get('callsign') and request.args.get('admin_approve') == 'true': + edit_user = User.query.filter(User.username == request.args.get('callsign')).first() + edit_user.active = True + edit_user.initial_admin_approved = True + db.session.commit() + msg = Message(recipients=[edit_user.email], + 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''' + + elif request.method == 'GET' and request.args.get('callsign') and request.args.get('email_verified') == 'true': + edit_user = User.query.filter(User.username == request.args.get('callsign')).first() + edit_user.email_confirmed_at = datetime.datetime.utcnow() + db.session.commit() + content = '''

Email verified for: ''' + str(request.args.get('callsign')) + '''

\n''' + + elif request.method == 'POST' and request.form.get('callsign') and not request.form.get('user_status') or request.method == 'GET' and request.args.get('callsign'):# and request.form.get('user_status') : + if request.args.get('callsign'): + callsign = request.args.get('callsign') + if request.form.get('callsign'): + callsign = request.form.get('callsign') + u = User.query.filter_by(username=callsign).first() + confirm_link = '' + if u.email_confirmed_at == None: + confirm_link = '''

Verify email - ''' + str(u.username) + '''

\n''' + u_role = UserRoles.query.filter_by(user_id=u.id).first() + if u_role.role_id == 2: + # Link to promote to Admin + role_link = '''

Give Admin role: ''' + str(u.username) + '''

\n''' + if u_role.role_id == 1: + # Link to promote to User + role_link = '''

Revert to User role: ''' + str(u.username) + '''

\n''' + id_dict = ast.literal_eval(u.dmr_ids) + passphrase_list = ''' + + + + + + ''' + for i in id_dict.items(): + print(i[1]) + if isinstance(i[1], int) == True: + passphrase_list = passphrase_list + ''' + + + + \n''' + if i[1] == '': + passphrase_list = passphrase_list + ''' + + + \n''' + if not isinstance(i[1], int) == True and i[1] != '': + passphrase_list = passphrase_list + ''' + + + \n''' + + passphrase_list = passphrase_list + '
DMR IDPassphrase
''' + str(i[0]) + '''''' + str(gen_passphrase(int(i[0]))) + '''
''' + str(i[0]) + '''''' + legacy_passphrase + '''
''' + str(i[0]) + '''''' + str(i[1]) + '''
' + content = ''' +

 

+ + + + + + + + + + + + + + + + +
First NameLast Name
 ''' + u.first_name + ''' ''' + u.last_name + '''
City''' + u.city + '''
+

 

+ +''' + passphrase_list + ''' + +

 Options for: ''' + u.username + ''' 

+ + + + + + + + + + + + + + + + +
  +

Update from RadioID.net

 ''' + confirm_link + ''' 

Email confirmed: ''' + str(u.email_confirmed_at) + '''

  +

Send user an email

 ''' + role_link + ''' 
 

View user auth log

  +

Deleted user

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+ + + + +

 

+ +

 Passphrase Authentication Method Key

+ + + + + + + + + + + + + +
CalculatedLegacy (config)Custom
0 - default,
1-999 - new calculation
'''passphrase'
+

{DMR ID: Method, 2nd DMR ID: Method}

+

Example:
{1234567: '', 134568: 0, 1234569: 'passphr8s3'}

+ + +''' + else: + content = ''' + + + + + + +
+ + + + + + + + + + + + +
+

+
+
+

 

+''' + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + @app.route('/get_script') + def get_script(): + dmr_id = int(request.args.get('dmr_id')) + number = float(request.args.get('number')) + #print(type(script_links[dmr_id])) + u = User.query.filter(User.dmr_ids.contains(request.args.get('dmr_id'))).first() + #print(u.dmr_ids) + + if authorized_peer(dmr_id)[1] == 0: + passphrase = gen_passphrase(dmr_id) + elif authorized_peer(dmr_id)[1] != 0 and isinstance(authorized_peer(dmr_id)[1], int) == True: + passphrase = gen_passphrase(dmr_id) + elif authorized_peer(dmr_id)[1] == '': + passphrase = legacy_passphrase + print(passphrase) + elif authorized_peer(dmr_id)[1] != '' or authorized_peer(dmr_id)[1] != 0: + passphrase = authorized_peer(dmr_id)[1] + #try: + if dmr_id in script_links and number == float(script_links[dmr_id]): + script_links.pop(dmr_id) + return str(gen_script(dmr_id, passphrase)) + #except: + #else: + #content = 'Link used or other error.' + #return content + #return render_template('flask_user_layout.html', markup_content = content, logo = logo) + + + def authorized_peer(peer_id): + try: + u = User.query.filter(User.dmr_ids.contains(str(peer_id))).first() + login_passphrase = ast.literal_eval(u.dmr_ids) + return [u.is_active, login_passphrase[peer_id], str(u.username)] + except: + return [False] + + @app.route('/auth_log', methods=['POST', 'GET']) + @login_required # User must be authenticated + @roles_required('Admin') + def all_auth_list(): + if request.args.get('flush_db') == 'true': + content = '''

Flushed entire auth DB.

\n''' + authlog_flush() + elif request.args.get('flush_user_db') == 'true' and request.args.get('portal_username'): + content = '''

Flushed auth DB for: ''' + request.args.get('portal_username') + '''

\n''' + authlog_flush_user(request.args.get('portal_username')) + elif request.args.get('flush_db_mmdvm') == 'true' and request.args.get('mmdvm_server'): + content = '''

Flushed auth DB for: ''' + request.args.get('mmdvm_server') + '''

\n''' + authlog_flush_mmdvm_server(request.args.get('mmdvm_server')) + elif request.args.get('flush_db_ip') == 'true' and request.args.get('peer_ip'): + content = '''

Flushed auth DB for: ''' + request.args.get('peer_ip') + '''

\n''' + authlog_flush_ip(request.args.get('peer_ip')) + elif request.args.get('flush_dmr_id_db') == 'true' and request.args.get('dmr_id'): + content = '''

Flushed auth DB for: ''' + request.args.get('dmr_id') + '''

\n''' + authlog_flush_dmr_id(request.args.get('dmr_id')) + elif request.args.get('portal_username') and not request.args.get('flush_user_db') and not request.args.get('flush_dmr_id_db') or request.args.get('dmr_id') and not request.args.get('flush_user_db') and not request.args.get('flush_dmr_id_db'): + if request.args.get('portal_username'): +## s_filter = portal_username=request.args.get('portal_username') + a = AuthLog.query.filter_by(portal_username=request.args.get('portal_username')).order_by(AuthLog.login_time.desc()).all() + g_arg = request.args.get('portal_username') + f_link = '''

Flush auth log for: ''' + request.args.get('portal_username') + '''

''' + elif request.args.get('dmr_id'): +## s_filter = login_dmr_id=request.args.get('dmr_id') + a = AuthLog.query.filter_by(login_dmr_id=request.args.get('dmr_id')).order_by(AuthLog.login_time.desc()).all() + g_arg = request.args.get('dmr_id') + f_link = '''

Flush auth log for: ''' + request.args.get('dmr_id') + '''

''' +## print(s_filter) +## a = AuthLog.query.filter_by(s_filter).order_by(AuthLog.login_dmr_id.desc()).all() + + content = ''' +

 

+

Log for: ''' + g_arg + '''

+ + ''' + f_link + ''' + + + + + + + + + + + + \n''' + for i in a: + if i.login_type == 'Attempt': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Confirmed': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Failed': + content = content + ''' + + + + + + + + + +''' + content = content + '
+

 DMR ID 

+
+

 Portal Username 

+
+

 Login IP 

+
+

 Passphrase 

+
+

 Server 

+
+

 Time (UTC) 

+
+

 Login Status 

+
 ''' + str(i.login_dmr_id) + '''   ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
' + + elif request.args.get('mmdvm_server') and not request.args.get('flush_db_mmdvm'): + a = AuthLog.query.filter_by(server_name=request.args.get('mmdvm_server')).order_by(AuthLog.login_time.desc()).all() + content = ''' +

 

+

Flush authentication log for server: ''' + request.args.get('mmdvm_server') + '''

+

Log for MMDVM server: ''' + request.args.get('mmdvm_server') + '''

+ + + + + + + + + + + + + \n''' + for i in a: + if i.login_type == 'Attempt': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Confirmed': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Failed': + content = content + ''' + + + + + + + + + +''' + content = content + '
+

 DMR ID 

+
+

 Portal Username 

+
+

 Login IP 

+
+

 Passphrase 

+
+

 Server 

+
+

 Time (UTC) 

+
+

 Login Status 

+
 ''' + str(i.login_dmr_id) + '''   ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + i.server_name + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + i.server_name + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + i.server_name + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
' + + elif request.args.get('peer_ip') and not request.args.get('flush_db_ip'): + a = AuthLog.query.filter_by(peer_ip=request.args.get('peer_ip')).order_by(AuthLog.login_time.desc()).all() + content = ''' +

 

+

Flush authentication log for IP: ''' + request.args.get('peer_ip') + '''

+

Log for IP address: ''' + request.args.get('peer_ip') + '''

+ + + + + + + + + + + + + \n''' + for i in a: + if i.login_type == 'Attempt': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Confirmed': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Failed': + content = content + ''' + + + + + + + + + +''' + content = content + '
+

 DMR ID 

+
+

 Portal Username 

+
+

 Login IP 

+
+

 Passphrase 

+
+

 Server 

+
+

 Time (UTC) 

+
+

 Login Status 

+
 ''' + str(i.login_dmr_id) + '''   ''' + i.portal_username + '''  ''' + i.peer_ip + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''  ''' + i.peer_ip + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''  ''' + i.peer_ip + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
' + + else: + #a = AuthLog.query.all() +## a = AuthLog.query.order_by(AuthLog.login_time.desc()).limit(300).all() + a = AuthLog.query.order_by(AuthLog.login_time.desc()).all() + recent_list = [] +## r = AuthLog.query.order_by(AuthLog.login_dmr_id.desc()).all() + content = ''' +

 

+

Flush entire authentication log

+

Un-registered authentication attempts

+

Authentication log by DMR ID

+ + + + + + + + + + + + \n''' + for i in a: + if i.login_dmr_id not in recent_list: + recent_list.append(i.login_dmr_id) + if i.login_type == 'Attempt': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Confirmed': + content = content + ''' + + + + + + + + + +''' + if i.login_type == 'Failed': + content = content + ''' + + + + + + + + + +''' + + content = content + '
+

 DMR ID 

+
+

 Portal Username 

+
+

 Login IP 

+
+

 Passphrase 

+
+

 Server 

+
+

 Time (UTC) 

+
+

 Last Login Status 

+
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
 ''' + str(i.login_dmr_id) + '''  ''' + i.portal_username + '''   ''' + str(i.peer_ip) + '''  ''' + i.login_auth_method + '''  ''' + str(i.server_name) + '''  ''' + str(i.login_time) + '''  ''' + str(i.login_type) + ''' 
' + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + @app.route('/user_tg') + def tg_status(): + cu = current_user + u = User.query.filter_by(username=cu.username).first() + sl = ServerList.query.all() + user_ids = ast.literal_eval(u.dmr_ids) + content = '

Currently active talkgroups. Updated every 2 minutes.

' +## print(active_tgs) + for s in sl: + for i in user_ids.items(): + for ts in active_tgs[s.name].items(): +## print(ts) +## print(ts[1][3]['peer_id']) + if i[0] == ts[1][3]['peer_id']: +## print(i[0]) + print(ts) +## if i[0] in active_tgs[s.name]: +## for x in ts[1]: +## print(x) +## ## if i[0] != ts[1][x][3]['peer_id']: +## ## print('nope') +## ## pass +## ## elif i[0] == ts[1][x][3]['peer_id']: +## ## print(x) +## ## print(s.name) +## ## print('-----ts-----') +## ## print(ts[1][x][3]['peer_id']) #[s.name][3]['peer_id']) +## ## print(active_tgs) +## +## ## print(active_tgs[s.name]) +## ## print(str(active_tgs[ts[1]])) +## # Remove 0 from TG list + try: + active_tgs[s.name][ts[0]][0]['1'].remove(0) + active_tgs[s.name][ts[0]][1]['2'].remove(0) + except: + pass +#### try: + content = content + ''' + + + + + + + + +
+

Server: ''' + str(s.name) + '''

+

DMR ID: ''' + str(i[0]) + '''

+
  + + + + + + + + + + + +
Timeslot 1 ''' + str(active_tgs[s.name][ts[0]][0]['1'])[1:-1] + '''
Timeslot 2 ''' + str(active_tgs[s.name][ts[0]][1]['2'])[1:-1] + '''
+
''' +## except: +## pass + + +## #TS1 +## for tg in active_tgs[s.name][i[0]][1]['2']: +## content = content + ''' ''' + str(tg) + ''' +##''' +## print(active_tgs[s.name][i[0]]) +## content = active_tgs[s.name][i[0]][1]['2'] +## content = 'hji' + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + @app.route('/test') + def test_peer(): + #user = User( + # username='admin3', + # email_confirmed_at=datetime.datetime.utcnow(), + # password=user_manager.hash_password('admin'), + # ) + #user.roles.append(Role(name='Admin')) + #user.roles.append(Role(name='User')) + #user.add_roles('Admin') + #db.session.add(user) + #db.session.commit() + u = User.query.filter_by(username='admin').first() + #u = Role.query.all() +## u = User.query.filter(User.dmr_ids.contains('3153591')).first() + #u = User.query.all() +## #tu = User.query().all() +#### print((tu.dmr_ids)) +#### #print(tu.dmr_ids) +#### return str(tu.dmr_ids) #str(get_ids('kf7eel')) +## login_passphrase = ast.literal_eval(u.dmr_ids) +## print('|' + login_passphrase[3153591] + '|') +## #print(u.dmr_ids) +## #tu.dmr_ids = 'jkgfldj' +## #db.session.commit() +## return str(u.dmr_ids) +## u = User.query.filter(User.dmr_ids.contains('3153591')).first() +## #tu = User.query.all() +## #tu = User.query().all() +#### print((tu.dmr_ids)) +#### #print(tu.dmr_ids) +#### return str(tu.dmr_ids) #str(get_ids('kf7eel')) +## print(u) +## login_passphrase = ast.literal_eval(u.dmr_ids) +## +## #tu.dmr_ids = 'jkgfldj' +## #db.session.commit() +## return str([u.is_active, login_passphrase[3153591]]) + #edit_user = User.query.filter(User.username == 'bob').first() + #edit_user.active = False + + #db.session.commit() + #print((current_user.has_roles('Admin'))) + #u.roles.append(Role(name='Admin')) + #print((current_user.has_roles('Admin'))) + #db.session.commit() + #db.session.add(u) + #db.session.commit() +## admin_role = UserRoles( +## user_id=3, +## role_id=1, +## ) +## user_role = UserRoles( +## user_id=3, +## role_id=2, +## ) +## db.session.add(user_role) +## db.session.add(admin_role) +## db.session.commit() + #print(role) +## for i in u: +## print(i.username) + #u = User.query.filter_by(username='kf7eel').first() + #print(u.id) + #u_role = UserRoles.query.filter_by(user_id=u.id).first() + #if u_role.role_id == 2: + # print('userhasjkdhfdsejksfdahjkdhjklhjkhjkl') +## print(u.has_roles('Admin')) + #u_role.role_id = 1 + #print(u) + # for i in u: + ##print(i.initial_admin_approved) + #if not i.initial_admin_approved: + #print(i.username) + # print(i) + #u_role = UserRoles.query.filter_by(id=2).first().role_id + #u_role = 1 + # db.session.commit() + #u_role = UserRoles.query.filter_by(id=u.id).first().role_id + #print(u_role) + #return str(u) +## if not u.active: +## flash('We come in peace', 'success') +## content = 'hello' + #add +## burn_list = BurnList( +## dmr_id=3153595, +## version=1, +## ) +## db.session.add(burn_list) +## db.session.commit() +## + #generate dict +## b = BurnList.query.all() +## print(b) +## burn_dict = {} +## for i in b: +## print(i.dmr_id) +## burn_dict[i.dmr_id] = i.version +## content = burn_dict +## # delete +#### delete_b = BurnList.query.filter_by(dmr_id=3153591).first() +#### db.session.delete(delete_b) +#### db.session.commit() +## a = AuthLog.query.all() +## print(a) +## authlog_flush() +## peer_delete('mmdvm', 1) + user_ids = ast.literal_eval(u.dmr_ids) + for i in user_ids.items():# active_tgs: + print(active_tgs['test'][i[0]]) + content = active_tgs['test'][i[0]][1]['2'] +## content = user_ids + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + def get_peer_configs(_server_name): + mmdvm_pl = mmdvmPeer.query.filter_by(server=_server_name).filter_by(enabled=True).all() + xlx_pl = xlxPeer.query.filter_by(server=_server_name).filter_by(enabled=True).all() +## print(mmdvm_pl) + peer_config_list = {} + for i in mmdvm_pl: +## print(i.master_ip) + peer_config_list.update({i.name: { + 'MODE': 'PEER', + 'ENABLED': i.enabled, + 'LOOSE': i.loose, + 'SOCK_ADDR': (gethostbyname(i.ip), i.port), + 'IP': i.ip, + 'PORT': i.port, + 'MASTER_SOCKADDR': (gethostbyname(i.master_ip), i.master_port), + 'MASTER_IP': i.master_ip, + 'MASTER_PORT': i.master_port, + + 'PASSPHRASE': i.passphrase, + 'CALLSIGN': i.callsign, + 'RADIO_ID': int(i.radio_id), #int(i.radio_id).to_bytes(4, 'big'), + 'RX_FREQ': i.rx_freq, + 'TX_FREQ': i.tx_freq, + 'TX_POWER': i.tx_power, + 'COLORCODE': i.color_code, + 'LATITUDE': i.latitude, + 'LONGITUDE': i.longitude, + 'HEIGHT': i.height, + 'LOCATION': i.location, + 'DESCRIPTION': i.description, + 'SLOTS': i.slots, + 'URL': i.url, + 'GROUP_HANGTIME': i.group_hangtime, + 'OPTIONS': i.options, + 'USE_ACL': i.use_acl, + 'SUB_ACL': i.sub_acl, + 'TG1_ACL': i.tg1_acl, + 'TG2_ACL': i.tg2_acl + }}) + for i in xlx_pl: + peer_config_list.update({i.name: { + 'MODE': 'XLXPEER', + 'ENABLED': i.enabled, + 'LOOSE': i.loose, + 'SOCK_ADDR': (gethostbyname(i.ip), i.port), + 'IP': i.ip, + 'PORT': i.port, + 'MASTER_SOCKADDR': (gethostbyname(i.master_ip), i.master_port), + 'MASTER_IP': i.master_ip, + 'MASTER_PORT': i.master_port, + + 'PASSPHRASE': i.passphrase, + 'CALLSIGN': i.callsign, + 'RADIO_ID': int(i.radio_id), #int(i.radio_id).to_bytes(4, 'big'), + 'RX_FREQ': i.rx_freq, + 'TX_FREQ': i.tx_freq, + 'TX_POWER': i.tx_power, + 'COLORCODE': i.color_code, + 'LATITUDE': i.latitude, + 'LONGITUDE': i.longitude, + 'HEIGHT': i.height, + 'LOCATION': i.location, + 'DESCRIPTION': i.description, + 'SLOTS': i.slots, + 'URL': i.url, + 'OPTIONS': i.options, + 'GROUP_HANGTIME': i.group_hangtime, + 'XLXMODULE': i.xlxmodule, + 'USE_ACL': i.use_acl, + 'SUB_ACL': i.sub_acl, + 'TG1_ACL': i.tg1_acl, + 'TG2_ACL': i.tg2_acl + }}) +#### print('peers') +## print('----------------') + return peer_config_list + + def get_burnlist(): + b = BurnList.query.all() + #print(b) + burn_dict = {} + for i in b: + #print(i.dmr_id) + burn_dict[i.dmr_id] = i.version + return burn_dict + + def add_burnlist(_dmr_id, _version): + burn_list = BurnList( + dmr_id=_dmr_id, + version=_version, + ) + db.session.add(burn_list) + db.session.commit() + + def update_burnlist(_dmr_id, _version): + update_b = BurnList.query.filter_by(dmr_id=_dmr_id).first() + update_b.version=_version + db.session.commit() + def delete_burnlist(_dmr_id): + delete_b = BurnList.query.filter_by(dmr_id=_dmr_id).first() + db.session.delete(delete_b) + db.session.commit() + + def authlog_add(_dmr_id, _peer_ip, _server_name, _portal_username, _auth_method, _login_type): + auth_log_add = AuthLog( + login_dmr_id=_dmr_id, + login_time=datetime.datetime.utcnow(), + portal_username = _portal_username, + peer_ip = _peer_ip, + server_name = _server_name, + login_auth_method=_auth_method, + login_type=_login_type + ) + db.session.add(auth_log_add) + db.session.commit() + + def authlog_flush(): + AuthLog.query.delete() + db.session.commit() + + def authlog_flush_user(_user): + flush_e = AuthLog.query.filter_by(portal_username=_user).all() + for i in flush_e: + db.session.delete(i) + db.session.commit() + + def authlog_flush_dmr_id(_dmr_id): + flush_e = AuthLog.query.filter_by(login_dmr_id=_dmr_id).all() + for i in flush_e: + db.session.delete(i) + db.session.commit() + def authlog_flush_mmdvm_server(_mmdvm_serv): + flush_e = AuthLog.query.filter_by(server_name=_mmdvm_serv).all() + for i in flush_e: + db.session.delete(i) + db.session.commit() + def authlog_flush_ip(_ip): + flush_e = AuthLog.query.filter_by(peer_ip=_ip).all() + for i in flush_e: + db.session.delete(i) + db.session.commit() +## def peer_delete(_mode, _id): +## if _mode == 'xlx': +## p = xlxPeer.query.filter_by(id=_id).first() +## if _mode == 'mmdvm': +## p = mmdvmPeer.query.filter_by(id=_id).first() +## db.session.delete(p) +## db.session.commit() + + def server_delete(_name): + s = ServerList.query.filter_by(name=_name).first() + m = MasterList.query.filter_by(server=_name).all() + p = ProxyList.query.filter_by(server=_name).all() + o = OBP.query.filter_by(server=_name).all() + dr = BridgeRules.query.filter_by(server=_name).all() + mp = mmdvmPeer.query.filter_by(server=_name).all() + xp = xlxPeer.query.filter_by(server=_name).all() + for d in m: + db.session.delete(d) + for d in p: + db.session.delete(d) + for d in o: + db.session.delete(d) + for d in dr: + db.session.delete(d) + for d in mp: + db.session.delete(d) + for d in xp: + db.session.delete(d) + db.session.delete(s) + + db.session.commit() + def peer_delete(_mode, _server, _name): + if _mode == 'mmdvm': + p = mmdvmPeer.query.filter_by(server=_server).filter_by(name=_name).first() + if _mode == 'xlx': + p = xlxPeer.query.filter_by(server=_server).filter_by(name=_name).first() + dr = BridgeRules.query.filter_by(server=_server).filter_by(system_name=_name).all() + for d in dr: + db.session.delete(d) + db.session.delete(p) + db.session.commit() + + def shared_secrets(): + s = ServerList.query.all() #filter_by(name=_name).first() + r_list = [] + for i in s: + r_list.append(str(i.secret)) + return r_list + + def bridge_add(_name, _desc, _public, _tg): + add_bridge = BridgeList( + bridge_name = _name, + description = _desc, + public_list = _public, + tg = _tg + ) + db.session.add(add_bridge) + db.session.commit() + def update_bridge_list(_name, _desc, _public, _new_name, _tg): + bl = BridgeList.query.filter_by(bridge_name=_name).first() + bl.bridge_name = _new_name + bl.description = _desc + bl.public_list = _public + bl.tg = _tg + db.session.commit() + + def bridge_delete(_name): #, _server): + bl = BridgeList.query.filter_by(bridge_name=_name).first() + db.session.delete(bl) + sl = ServerList.query.all() + for i in sl: + delete_system_bridge(_name, i.name) + db.session.commit() + + def generate_rules(_name): + + # generate UNIT list +## print('get rules') +## print(_name) + xlx_p = xlxPeer.query.filter_by(server=_name).all() + mmdvm_p = mmdvmPeer.query.filter_by(server=_name).all() + all_m = MasterList.query.filter_by(server=_name).all() + all_o = OBP.query.filter_by(server=_name).all() + all_p = ProxyList.query.filter_by(server=_name).all() + rules = BridgeRules.query.filter_by(server=_name).all() + UNIT = [] + BRIDGES = {} + disabled = {} + for i in all_m: + if i.active == False: + disabled[i.name] = i.name + else: + if i.enable_unit == True: + UNIT.append(i.name) + for i in all_p: + if i.active == False: + disabled[i.name] = i.name + else: + if i.enable_unit == True: + n_systems = i.internal_stop_port - i.internal_start_port + n_count = 0 + while n_count < n_systems: + UNIT.append(i.name + '-' + str(n_count)) + n_count = n_count + 1 + for i in all_o: + if i.enabled == False: + disabled[i.name] = i.name + else: + if i.enable_unit == True: + UNIT.append(i.name) + for i in xlx_p: + if i.enabled == False: + disabled[i.name] = i.name + else: + if i.enable_unit == True: + UNIT.append(i.name) + for i in mmdvm_p: + if i.enabled == False: + disabled[i.name] = i.name + else: + if i.enable_unit == True: + UNIT.append(i.name) + temp_dict = {} + # populate dict with needed bridges + for r in rules: +## print(r.bridge_name) +## b = BridgeRules.query.filter_by(server=_name).filter_by(server=_name).all() +## for d in temp_dict.items(): +## if r.bridge_name == d[0]: +## print('update rule') +## if r.bridge_name != d[0]: +## print('add dict entry and rule') + temp_dict[r.bridge_name] = [] +## print(temp_dict) + BRIDGES = temp_dict.copy() + for r in temp_dict.items(): + b = BridgeRules.query.filter_by(bridge_name=r[0]).filter_by(server=_name).all() + for s in b: + try: + if s.system_name == disabled[s.system_name]: + pass + except: + if s.timeout == '': + timeout = 0 + else: + timeout = int(s.timeout) + if s.proxy == True: + p = ProxyList.query.filter_by(server=_name).filter_by(name=s.system_name).first() + print(p.external_port) + n_systems = p.internal_stop_port - p.internal_start_port + n_count = 0 + while n_count < n_systems: + BRIDGES[r[0]].append({'SYSTEM': s.system_name + '-' + str(n_count), 'TS': s.ts, 'TGID': s.tg, 'ACTIVE': s.active, 'TIMEOUT': timeout, 'TO_TYPE': s.to_type, 'ON': ast.literal_eval(str('[' + s.on + ']')), 'OFF': ast.literal_eval(str('[4000,' + s.off + ']')), 'RESET': ast.literal_eval(str('[' + s.reset + ']'))}) + n_count = n_count + 1 + + else: + BRIDGES[r[0]].append({'SYSTEM': s.system_name, 'TS': s.ts, 'TGID': s.tg, 'ACTIVE': s.active, 'TIMEOUT': timeout, 'TO_TYPE': s.to_type, 'ON': ast.literal_eval(str('[' + s.on + ']')), 'OFF': ast.literal_eval(str('[' + s.off + ']')), 'RESET': ast.literal_eval(str('[' + s.reset + ']'))}) + +## for d in b: +## print(b.system_name) + +## if r.bridge_name == d[0]: +## print('update rule') +## if r.bridge_name != d[0]: +## print('add dict entry and rule') + +## print(r.tg) +## print(BRIDGES) + return [UNIT, BRIDGES] + + + def server_get(_name): +## print(_name) + #s = ServerList.query.filter_by(name=_name).first() + # print(s.name) + i = ServerList.query.filter_by(name=_name).first() +## print(i.name) + s_config = {} + s_config['GLOBAL'] = {} + s_config['REPORTS'] = {} + s_config['ALIASES'] = {} + s_config['USER_MANAGER'] = {} + + s_config['GLOBAL'].update({ + 'PATH': i.global_path, + 'PING_TIME': i.global_ping_time, + 'MAX_MISSED': i.global_max_missed, + 'USE_ACL': i.global_use_acl, + 'REG_ACL': i.global_reg_acl, + 'SUB_ACL': i.global_sub_acl, + 'TG1_ACL': i.global_tg1_acl, + 'TG2_ACL': i.global_tg2_acl + }) + + s_config['REPORTS'].update({ + 'REPORT': i.report_enable, + 'REPORT_INTERVAL': i.report_interval, + 'REPORT_PORT': i.report_port, + 'REPORT_CLIENTS': i.report_clients.split(',') + }) + s_config['ALIASES'].update({ + 'TRY_DOWNLOAD':i.ai_try_download, + 'PATH': i.ai_path, + 'PEER_FILE': i.ai_peer_file, + 'SUBSCRIBER_FILE': i.ai_subscriber_file, + 'TGID_FILE': i.ai_tgid_file, + 'PEER_URL': i.ai_peer_url, + 'SUBSCRIBER_URL': i.ai_subs_url, + 'STALE_TIME': i.ai_stale * 86400, + }) + s_config['USER_MANAGER'].update({ + 'SHORTEN_LENGTH': shorten_length, + 'SHORTEN_SAMPLE': shorten_sample, + 'EXTRA_1': extra_1, + 'EXTRA_2': extra_2, + 'EXTRA_INT_1': extra_int_1, + 'EXTRA_INT_2': extra_int_2, + 'APPEND_INT': append_int, + 'SHORTEN_PASSPHRASE': i.um_shorten_passphrase, + 'BURN_FILE': i.um_burn_file, + 'BURN_INT': burn_int, + + + }) + print(s_config['REPORTS']) + return s_config + def masters_get(_name): +## # print(_name) + #s = ServerList.query.filter_by(name=_name).first() + # print(s.name) + i = MasterList.query.filter_by(server=_name).filter_by(active=True).all() + o = OBP.query.filter_by(server=_name).filter_by(enabled=True).all() + p = ProxyList.query.filter_by(server=_name).filter_by(active=True).all() + # print('get masters') + master_config_list = {} +## master_config_list['SYSTEMS'] = {} + # print(i) + for m in i: +## print (m.name) + master_config_list.update({m.name: { + 'MODE': 'MASTER', + 'ENABLED': m.active, + 'USE_USER_MAN': m.enable_um, + 'STATIC_APRS_POSITION_ENABLED': m.static_positions, + 'REPEAT': m.repeat, + 'MAX_PEERS': m.max_peers, + 'IP': m.ip, + 'PORT': m.port, + 'PASSPHRASE': m.passphrase, #bytes(m.passphrase, 'utf-8'), + 'GROUP_HANGTIME': m.group_hang_time, + 'USE_ACL': m.use_acl, + 'REG_ACL': m.reg_acl, + 'SUB_ACL': m.sub_acl, + 'TG1_ACL': m.tg1_acl, + 'TG2_ACL': m.tg2_acl + }}) + master_config_list[m.name].update({'PEERS': {}}) + for obp in o: +## print(type(obp.network_id)) + master_config_list.update({obp.name: { + 'MODE': 'OPENBRIDGE', + 'ENABLED': obp.enabled, + 'NETWORK_ID': obp.network_id, #int(obp.network_id).to_bytes(4, 'big'), + 'IP': gethostbyname(obp.ip), + 'PORT': obp.port, + 'PASSPHRASE': obp.passphrase, #bytes(obp.passphrase.ljust(20,'\x00')[:20], 'utf-8'), + 'TARGET_SOCK': (obp.target_ip, obp.target_port), + 'TARGET_IP': gethostbyname(obp.target_ip), + 'TARGET_PORT': obp.target_port, + 'BOTH_SLOTS': obp.both_slots, + 'USE_ACL': obp.use_acl, + 'SUB_ACL': obp.sub_acl, + 'TG1_ACL': obp.tg_acl, + 'TG2_ACL': 'PERMIT:ALL' + }}) + for pr in p: + master_config_list.update({pr.name: { + 'MODE': 'PROXY', + 'ENABLED': pr.active, + 'EXTERNAL_PROXY_SCRIPT': pr.external_proxy, + 'STATIC_APRS_POSITION_ENABLED': pr.static_positions, + 'USE_USER_MAN': pr.enable_um, + 'REPEAT': pr.repeat, + 'PASSPHRASE': pr.passphrase, #bytes(pr.passphrase, 'utf-8'), + 'EXTERNAL_PORT': pr.external_port, + 'INTERNAL_PORT_START': pr.internal_start_port, + 'INTERNAL_PORT_STOP': pr.internal_stop_port, + 'GROUP_HANGTIME': pr.group_hang_time, + 'USE_ACL': pr.use_acl, + 'REG_ACL': pr.reg_acl, + 'SUB_ACL': pr.sub_acl, + 'TG1_ACL': pr.tg1_acl, + 'TG2_ACL': pr.tg2_acl + }}) + master_config_list[pr.name].update({'PEERS': {}}) + + # print(master_config_list) + return master_config_list + + def add_system_rule(_bridge_name, _system_name, _ts, _tg, _active, _timeout, _to_type, _on, _off, _reset, _server, _public_list): + proxy = ProxyList.query.filter_by(server=_server).filter_by(name=_system_name).first() + is_proxy = False + try: + if _system_name == proxy.name: + is_proxy = True + except: + pass + add_system = BridgeRules( + bridge_name = _bridge_name, + system_name = _system_name, + ts = _ts, + tg = _tg, + active = _active, + timeout = _timeout, + to_type = _to_type, + on = _on, + off = _off, + reset = _reset, + server = _server, + public_list = _public_list, + proxy = is_proxy + ) + db.session.add(add_system) + db.session.commit() + + def edit_system_rule(_bridge_name, _system_name, _ts, _tg, _active, _timeout, _to_type, _on, _off, _reset, _server, _public_list): + proxy = ProxyList.query.filter_by(server=_server).filter_by(name=_system_name).first() + is_proxy = False + try: + if _system_name == proxy.name: + is_proxy = True + except: + pass + r = BridgeRules.query.filter_by(system_name=_system_name).filter_by(bridge_name=_bridge_name).first() + print('---') + print(_system_name) + print(_bridge_name) + print(r) +## for i in r: +## print(i.name) +## add_system = BridgeRules( + r.bridge_name = _bridge_name + r.system_name = _system_name + r.ts = _ts + r.tg = _tg + r.active = _active + r.timeout = _timeout + r.to_type = _to_type + r.on = _on + r.off = _off + r.reset = _reset + r.server = _server + r.public_list = _public_list + r.proxy = is_proxy +## db.session.add(add_system) + db.session.commit() + + def delete_system_bridge(_name, _server): + dr = BridgeRules.query.filter_by(server=_server).filter_by(bridge_name=_name).all() + for i in dr: + db.session.delete(i) + db.session.commit() + + def delete_system_rule(_name, _server, _system): + dr = BridgeRules.query.filter_by(server=_server).filter_by(bridge_name=_name).filter_by(system_name=_system).first() + db.session.delete(dr) + db.session.commit() + + + def server_edit(_name, _secret, _ip, _public_list, _port, _global_path, _global_ping_time, _global_max_missed, _global_use_acl, _global_reg_acl, _global_sub_acl, _global_tg1_acl, _global_tg2_acl, _ai_subscriber_file, _ai_try_download, _ai_path, _ai_peer_file, _ai_tgid_file, _ai_peer_url, _ai_subs_url, _ai_stale, _um_shorten_passphrase, _um_burn_file, _report_enable, _report_interval, _report_port, _report_clients, _unit_time, _notes): + s = ServerList.query.filter_by(name=_name).first() + # print(_name) + if _secret == '': + s.secret = s.secret + else: + s.secret = hashlib.sha256(_secret.encode()).hexdigest() + s.public_list = _public_list + s.ip = _ip + s.port = _port + s.global_path =_global_path + s.global_ping_time = _global_ping_time + s.global_max_missed = _global_max_missed + s.global_use_acl = _global_use_acl + s.global_reg_acl = _global_reg_acl + s.global_sub_acl = _global_sub_acl + s.global_tg1_acl = _global_tg1_acl + s.global_tg2_acl = _global_tg2_acl + s.ai_try_download = _ai_try_download + s.ai_path = _ai_path + s.ai_peer_file = _ai_peer_file + s.ai_subscriber_file = _ai_subscriber_file + s.ai_tgid_file = _ai_tgid_file + s.ai_peer_url = _ai_peer_url + s.ai_subs_url = _ai_subs_url + s.ai_stale = _ai_stale + # Pull from config file for now +## um_append_int = db.Column(db.Integer(), primary_key=False, server_default='2') + s.um_shorten_passphrase = _um_shorten_passphrase + s.um_burn_file = _um_burn_file + # Pull from config file for now +## um_burn_int = db.Column(db.Integer(), primary_key=False, server_default='6') + s.report_enable = _report_enable + s.report_interval = _report_interval + s.report_port = _report_port + s.report_clients = _report_clients + s.unit_time = int(_unit_time) + s.notes = _notes + db.session.commit() + + def master_delete(_mode, _server, _name): + if _mode == 'MASTER': + m = MasterList.query.filter_by(server=_server).filter_by(name=_name).first() + if _mode == 'PROXY': + m = ProxyList.query.filter_by(server=_server).filter_by(name=_name).first() + if _mode == 'OBP': + m = OBP.query.filter_by(server=_server).filter_by(name=_name).first() + dr = BridgeRules.query.filter_by(server=_server).filter_by(system_name=_name).all() + for d in dr: + db.session.delete(d) + db.session.delete(m) + db.session.commit() + + def edit_master(_mode, _name, _server, _static_positions, _repeat, _active, _max_peers, _ip, _port, _enable_um, _passphrase, _group_hang_time, _use_acl, _reg_acl, _sub_acl, _tg1_acl, _tg2_acl, _enable_unit, _notes, _external_proxy, _int_start_port, _int_stop_port, _network_id, _target_ip, _target_port, _both_slots, _public): +## print(_mode) +#### print(_server) +## print(_name) + if _mode == 'MASTER': +## print(_name) + m = MasterList.query.filter_by(server=_server).filter_by(name=_name).first() +## m.name = _name, + m.static_positions = _static_positions + m.repeat = _repeat + m.active = _active + m.max_peers = int(_max_peers) + m.ip = _ip + m.port = int(_port) + m.enable_um = _enable_um + m.passphrase = str(_passphrase) + m.group_hang_time = int(_group_hang_time) + m.use_acl = _use_acl + m.reg_acl = _reg_acl + m.sub_acl = _sub_acl + m.tg1_acl = _tg1_acl + m.tg2_acl = _tg2_acl + m.enable_unit = _enable_unit +## m.server = _server + m.notes = _notes + m.public_list = _public + db.session.commit() + if _mode == 'OBP': + # print(_enable_unit) +## print(enable_unit) + o = OBP.query.filter_by(server=_server).filter_by(name=_name).first() + o.enabled = _active + o.network_id = _network_id + o.ip = _ip + o.port = _port + o.passphrase = _passphrase + o.target_ip = _target_ip + o.target_port = _target_port + o.both_slots = _both_slots + o.use_acl = _use_acl + o.sub_acl = _sub_acl + o.tg1_acl = _tg1_acl + o.tg2_acl = _tg2_acl + o.enable_unit = _enable_unit + o.notes = _notes + db.session.commit() + if _mode == 'PROXY': +## print(_int_start_port) +## print(_int_stop_port) + p = ProxyList.query.filter_by(server=_server).filter_by(name=_name).first() + p.name = _name + p.static_positions = _static_positions + p.repeat = _repeat + p.active = _active + p.enable_um = _enable_um + p.passphrase = _passphrase + p.external_proxy = _external_proxy + external_port = int(_port) + p.group_hang_time = int(_group_hang_time) + p.internal_start_port = _int_start_port + p.internal_stop_port = _int_stop_port + p.use_acl = _use_acl + p.reg_acl = _reg_acl + p.sub_acl = _sub_acl + p.tg1_acl = _tg1_acl + p.tg2_acl = _tg2_acl + p.enable_unit = _enable_unit + p.server = _server + p.notes = _notes + p.public_list = _public + db.session.commit() +## add_proxy = ProxyList( +## name = _name, +## static_positions = _static_positions, +## repeat = _repeat, +## active = _active, +## enable_um = _enable_um, +## passphrase = _passphrase, +## external_proxy = _external_proxy, +## group_hang_time = int(_group_hang_time), +## internal_start_port = int(_int_start_port), +## internal_stop_port = int(_int_stop_port), +## use_acl = _use_acl, +## reg_acl = _reg_acl, +## sub_acl = _sub_acl, +## tg1_acl = _tg1_acl, +## tg2_acl = _tg2_acl, +## enable_unit = _enable_unit, +## server = _server, +## notes = _notes +## ) +## db.session.add(add_master) + + def add_master(_mode, _name, _server, _static_positions, _repeat, _active, _max_peers, _ip, _port, _enable_um, _passphrase, _group_hang_time, _use_acl, _reg_acl, _sub_acl, _tg1_acl, _tg2_acl, _enable_unit, _notes, _external_proxy, _int_start_port, _int_stop_port, _network_id, _target_ip, _target_port, _both_slots, _public): + # print(_mode) + if _mode == 'MASTER': + add_master = MasterList( + name = _name, + static_positions = _static_positions, + repeat = _repeat, + active = _active, + max_peers = int(_max_peers), + ip = _ip, + port = int(_port), + enable_um = _enable_um, + passphrase = _passphrase, + group_hang_time = int(_group_hang_time), + use_acl = _use_acl, + reg_acl = _reg_acl, + sub_acl = _sub_acl, + tg1_acl = _tg1_acl, + tg2_acl = _tg2_acl, + enable_unit = _enable_unit, + server = _server, + notes = _notes, + public_list = _public + ) + db.session.add(add_master) + db.session.commit() + if _mode == 'PROXY': + add_proxy = ProxyList( + name = _name, + static_positions = _static_positions, + repeat = _repeat, + active = _active, + enable_um = _enable_um, + passphrase = _passphrase, + external_proxy = _external_proxy, + external_port = int(_port), + group_hang_time = int(_group_hang_time), + internal_start_port = int(_int_start_port), + internal_stop_port = int(_int_stop_port), + use_acl = _use_acl, + reg_acl = _reg_acl, + sub_acl = _sub_acl, + tg1_acl = _tg1_acl, + tg2_acl = _tg2_acl, + enable_unit = _enable_unit, + server = _server, + notes = _notes, + public_list = _public + ) + db.session.add(add_proxy) + db.session.commit() + if _mode == 'OBP': + # print(_name) + # print(_network_id) + add_OBP = OBP( + name = _name, + enabled = _active, + network_id = _network_id, # + ip = _ip, + port = _port, + passphrase = _passphrase, + target_ip = _target_ip,# + target_port = _target_port,# + both_slots = _both_slots,# + use_acl = _use_acl, + sub_acl = _sub_acl, + tg_acl = _tg1_acl, + enable_unit = _enable_unit, + server = _server, + notes = _notes, + ) + db.session.add(add_OBP) + db.session.commit() + + + def server_add(_name, _secret, _ip, _port, _global_path, _global_ping_time, _global_max_missed, _global_use_acl, _global_reg_acl, _global_sub_acl, _global_tg1_acl, _global_tg2_acl, _ai_subscriber_file, _ai_try_download, _ai_path, _ai_peer_file, _ai_tgid_file, _ai_peer_url, _ai_subs_url, _ai_stale, _um_shorten_passphrase, _um_burn_file, _report_enable, _report_interval, _report_port, _report_clients, _unit_time, _notes): + add_server = ServerList( + name = _name, + secret = hashlib.sha256(_secret.encode()).hexdigest(), +## public_list = _public_list, + ip = _ip, + port = _port, + global_path =_global_path, + global_ping_time = _global_ping_time, + global_max_missed = _global_max_missed, + global_use_acl = _global_use_acl, + global_reg_acl = _global_reg_acl, + global_sub_acl = _global_sub_acl, + global_tg1_acl = _global_tg1_acl, + global_tg2_acl = _global_tg2_acl, + ai_try_download = _ai_try_download, + ai_path = _ai_path, + ai_peer_file = _ai_peer_file, + ai_subscriber_file = _ai_subscriber_file, + ai_tgid_file = _ai_tgid_file, + ai_peer_url = _ai_peer_url, + ai_subs_url = _ai_subs_url, + ai_stale = _ai_stale, + # Pull from config file for now +## um_append_int = db.Column(db.Integer(), primary_key=False, server_default='2') + um_shorten_passphrase = _um_shorten_passphrase, + um_burn_file = _um_burn_file, + # Pull from config file for now +## um_burn_int = db.Column(db.Integer(), primary_key=False, server_default='6') + report_enable = _report_enable, + report_interval = _report_interval, + report_port = _report_port, + report_clients = _report_clients, + unit_time = int(_unit_time), + notes = _notes + ) + db.session.add(add_server) + db.session.commit() + def peer_add(_mode, _name, _enabled, _loose, _ip, _port, _master_ip, _master_port, _passphrase, _callsign, _radio_id, _rx, _tx, _tx_power, _cc, _lat, _lon, _height, _loc, _desc, _slots, _url, _grp_hang, _xlx_mod, _opt, _use_acl, _sub_acl, _1_acl, _2_acl, _svr, _enable_unit, _notes): + if _mode == 'xlx': + xlx_peer_add = xlxPeer( + name = _name, + enabled = _enabled, + loose = _loose, + ip = _ip, + port = _port, + master_ip = _master_ip, + master_port = _master_port, + passphrase = _passphrase, + callsign = _callsign, + radio_id = _radio_id, + rx_freq = _rx, + tx_freq = _tx, + tx_power = _tx_power, + color_code = _cc, + latitude = _lat, + longitude = _lon, + height = _height, + location = _loc, + description = _desc, + slots = _slots, + xlxmodule = _xlx_mod, + url = _url, + enable_unit = _enable_unit, + group_hangtime = _grp_hang, + use_acl = _use_acl, + sub_acl = _sub_acl, + tg1_acl = _1_acl, + tg2_acl = _2_acl, + server = _svr, + notes = _notes + ) + db.session.add(xlx_peer_add) + db.session.commit() + if _mode == 'mmdvm': + mmdvm_peer_add = mmdvmPeer( + name = _name, + enabled = _enabled, + loose = _loose, + ip = _ip, + port = _port, + master_ip = _master_ip, + master_port = _master_port, + passphrase = _passphrase, + callsign = _callsign, + radio_id = _radio_id, + rx_freq = _rx, + tx_freq = _tx, + tx_power = _tx_power, + color_code = _cc, + latitude = _lat, + longitude = _lon, + height = _height, + location = _loc, + description = _desc, + slots = _slots, + url = _url, + enable_unit = _enable_unit, + group_hangtime = _grp_hang, + use_acl = _use_acl, + sub_acl = _sub_acl, + tg1_acl = _1_acl, + tg2_acl = _2_acl, + server = _svr, + notes = _notes + ) + db.session.add(mmdvm_peer_add) + db.session.commit() + def peer_edit(_mode, _server, _name, _enabled, _loose, _ip, _port, _master_ip, _master_port, _passphrase, _callsign, _radio_id, _rx, _tx, _tx_power, _cc, _lat, _lon, _height, _loc, _desc, _slots, _url, _grp_hang, _xlx_mod, _opt, _use_acl, _sub_acl, _1_acl, _2_acl, _enable_unit, _notes): +## print(_mode) + if _mode == 'mmdvm': +## print(_server) +## print(_name) +## print(_name) +## s = mmdvmPeer.query.filter_by(server=_server).filter_by(name=_name).first() + p = mmdvmPeer.query.filter_by(server=_server).filter_by(name=_name).first() + p.enabled = _enabled + p.loose = _loose + p.ip = _ip + p.port = _port + p.master_ip = _master_ip + p.master_port = _master_port + p.passphrase = _passphrase + p.callsign = _callsign + p.radio_id = _radio_id + p.rx_freq = _rx + p.tx_freq = _tx + p.tx_power = _tx_power + p.color_code = _cc + p.latitude = _lat + p.longitude = _lon + p.height = _height + p.location = _loc + p.description = _desc + p.slots = _slots + p.url = _url + p.enable_unit = _enable_unit + p.group_hangtime = _grp_hang + p.options = _opt + p.use_acl = _use_acl + p.sub_acl = _sub_acl + p.tg1_acl = _1_acl + p.tg2_acl = _2_acl + p.notes = _notes + if _mode == 'xlx': +## print(type(_server)) +## print(type(_name)) +## print(type(_enabled)) +## print((_enable_unit)) +## print(type(_use_acl)) +#### print(_port) + + +## s = mmdvmPeer.query.filter_by(server=_server).filter_by(name=_name).first() + p = xlxPeer.query.filter_by(server=_server).filter_by(name=_name).first() + # print(type(p.enable_unit)) + p.enabled = _enabled + p.loose = _loose + p.ip = _ip + p.port = _port + p.master_ip = _master_ip + p.master_port = _master_port + p.passphrase = _passphrase + p.callsign = _callsign + p.radio_id = _radio_id + p.rx_freq = _rx + p.tx_freq = _tx + p.tx_power = _tx_power + p.color_code = _cc + p.latitude = _lat + p.longitude = _lon + p.height = _height + p.location = _loc + p.description = _desc + p.slots = _slots + p.url = _url + p.options = _opt + p.enable_unit = _enable_unit + p.xlxmodule = _xlx_mod + p.group_hangtime = _grp_hang + p.use_acl = _use_acl + p.sub_acl = _sub_acl + p.tg1_acl = _1_acl + p.tg2_acl = _2_acl + p.notes = _notes + db.session.commit() + + + + +# Test server configs + + @app.route('/manage_servers', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') + def edit_server_db(): + # Edit server + if request.args.get('save_mode'):# == 'new' and request.form.get('server_name'): + _port = int(request.form.get('server_port')) + _global_ping_time = int(request.form.get('ping_time')) + _global_max_missed = int(request.form.get('max_missed')) + _ai_stale = int(request.form.get('stale_days')) + _report_interval = int(request.form.get('report_interval')) + _report_port = int(request.form.get('report_port')) + if request.form.get('use_acl') == 'True': + _global_use_acl = True + if request.form.get('aliases_enabled') == 'True': + _ai_try_download = True + if request.form.get('um_shorten_passphrase') == 'True': + _um_shorten_passphrase = True + if request.form.get('report') == 'True': + _report_enabled = True +## if request.form.get('public_list') == 'True': +## public_list = True + else: + _global_use_acl = False + _ai_try_download = False + _um_shorten_passphrase = False + _report_enabled = False +## public_list = False + + if request.args.get('save_mode') == 'new': + if request.form.get('server_name') == '': + content = '''

Server can't have blank name.

+

Redirecting in 3 seconds.

+''' + else: + server_add(request.form.get('server_name'), request.form.get('server_secret'), request.form.get('server_ip'), _port, request.form.get('global_path'), _global_ping_time, _global_max_missed, _global_use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('global_ts1_acl'), request.form.get('global_ts2_acl'), request.form.get('sub_file'), _ai_try_download, request.form.get('aliases_path'), request.form.get('peer_file'), request.form.get('tgid_file'), request.form.get('peer_url'), request.form.get('sub_url'), _ai_stale, _um_shorten_passphrase, request.form.get('um_burn_file'), _report_enabled, _report_interval, _report_port, request.form.get('report_clients'), request.form.get('unit_time'), request.form.get('notes')) + content = '''

Server saved.

+

Redirecting in 3 seconds.

+ ''' + if request.args.get('save_mode') == 'edit': +## print(request.args.get('server')) + server_edit(request.args.get('server'), request.form.get('server_secret'), request.form.get('server_ip'), _port, request.form.get('global_path'), _global_ping_time, _global_max_missed, _global_use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('global_ts1_acl'), request.form.get('global_ts2_acl'), request.form.get('sub_file'), _ai_try_download, request.form.get('aliases_path'), request.form.get('peer_file'), request.form.get('tgid_file'), request.form.get('peer_url'), request.form.get('sub_url'), _ai_stale, _um_shorten_passphrase, request.form.get('um_burn_file'), _report_enabled, _report_interval, _report_port, request.form.get('report_clients'), request.form.get('unit_time'), request.form.get('notes')) + content = '''

Server changed.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('delete_server'): + server_delete(request.args.get('delete_server')) + content = '''

Server deleted.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('edit_server'): + s = ServerList.query.filter_by(name=request.args.get('edit_server')).first() + + content = ''' +

 

+ +

Delete server

+ +
+

 

+

Server

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Server Name: ''' + str(s.name) + '''
 Server Secret: 
 Host (IP/DNS, for listing on passphrase page): 
 Port (for listing on passphrase page): 
 Unit Call Timeout (minutes): 
 Notes: 
+

Global

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Path: 
 Ping Time: 
 Max Missed: 
 Use ACLs: 
 Regular ACLs: 
 Subscriber ACSs: 
 Timeslot 1 ACLs: 
 Timeslot 2 ACLs: 
+

 

+

Reports

+ + + + + + + + + + + + + + + + + + + +
 Enable: 
 Interval: 
 Port: 
 Clients: 
+ +

 

+

Aliases

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Download: 
 Path: 
 Peer File: 
 Subscriber File: 
 Talkgroup ID File: 
 Peer URL: 
 Subscriber URL: 
 Stale time(days): 
+
+

 

+

User Manager

+ + + + + + + + + + + + +
 Use short passphrase:
 Burned IDs File: 
+

 

+

+

 

+''' + # Add new server + elif request.args.get('add'): # == 'yes': + content = ''' +
+

 

+

Server

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Server Name: 
 Server Secret: 
 Host (IP/DNS): 
 Port: 
 Unit Call Timeout (minutes): 
 Notes: 
+

Global

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Path: 
 Ping Time: 
 Max Missed: 
 Use ACLs: 
 Regular ACLs: 
 Subscriber ACSs: 
 Timeslot 1 ACLs: 
 Timeslot 2 ACLs: 
+

 

+

Reports

+ + + + + + + + + + + + + + + + + + + +
 Enable: 
 Interval: 
 Port: 
 Clients: 
+ +

 

+

Aliases

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Download: 
 Path: 
 Peer File: 
 Subscriber File: 
 Talkgroup ID File: 
 Peer URL: 
 Subscriber URL: 
 Stale time(days): 
+
+

 

+

User Manager

+ + + + + + + + + + + + + +
 Use short passphrase:
 Burned IDs File: 
+

 

+

+

 

+''' + else: + all_s = ServerList.query.all() + p_list = ''' +

View/Edit Servers

+ + + + + + + +
Add Server Config
+

 

+ + + + + + +''' + for s in all_s: + p_list = p_list + ''' + + + +\n +''' + p_list = p_list + '''
Name
Notes
''' + str(s.name) + '''''' + s.notes + '''
''' + content = p_list + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + @app.route('/manage_peers', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') + def test_peer_db(): + if request.args.get('save_mode'): + if request.form.get('enabled') == 'true': + peer_enabled = True +## if request.form.get('loose') == 'true': +## peer_loose = True + if request.form.get('use_acl') == 'true': + use_acl = True + if request.form.get('enable_unit') == 'True': + unit_enabled = True +## else: +## peer_loose = False + peer_enabled = False + use_acl = False + unit_enabled = False + peer_loose = True +## print(request.form.get('enable_unit')) +## print(enable_unit) + if request.form.get('name_text') == '': + content = '''

Peer can't have blank name.

+

Redirecting in 3 seconds.

+''' + else: + if request.args.get('save_mode') == 'mmdvm_peer': + peer_add('mmdvm', request.form.get('name_text'), peer_enabled, peer_loose, request.form.get('ip'), request.form.get('port'), request.form.get('master_ip'), request.form.get('master_port'), request.form.get('passphrase'), request.form.get('callsign'), request.form.get('radio_id'), request.form.get('rx'), request.form.get('tx'), request.form.get('tx_power'), request.form.get('cc'), request.form.get('lat'), request.form.get('lon'), request.form.get('height'), request.form.get('location'), request.form.get('description'), request.form.get('slots'), request.form.get('url'), request.form.get('group_hangtime'), 'MMDVM', request.form.get('options'), use_acl, request.form.get('sub_acl'), request.form.get('tgid_ts1_acl'), request.form.get('tgid_ts2_acl'), request.form.get('server'), unit_enabled, request.form.get('notes')) + content = '''

MMDVM PEER saved.

+

Redirecting in 3 seconds.

+ ''' + if request.args.get('save_mode') == 'xlx_peer': + peer_add('xlx', request.form.get('name_text'), peer_enabled, peer_loose, request.form.get('ip'), request.form.get('port'), request.form.get('master_ip'), request.form.get('master_port'), request.form.get('passphrase'), request.form.get('callsign'), request.form.get('radio_id'), request.form.get('rx'), request.form.get('tx'), request.form.get('tx_power'), request.form.get('cc'), request.form.get('lat'), request.form.get('lon'), request.form.get('height'), request.form.get('location'), request.form.get('description'), request.form.get('slots'), request.form.get('url'), request.form.get('group_hangtime'), request.form.get('xlxmodule'), request.form.get('options'), use_acl, request.form.get('sub_acl'), request.form.get('tgid_ts1_acl'), request.form.get('tgid_ts2_acl'), request.form.get('server'), unit_enabled, request.form.get('notes')) + content = '''

XLX PEER saved.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('add') == 'mmdvm' or request.args.get('add') == 'xlx': + s = ServerList.query.all() + if request.args.get('add') == 'mmdvm': + mode = 'MMDVM' + submit_link = 'manage_peers?save_mode=mmdvm_peer' + xlx_module = '' + if request.args.get('add') == 'xlx': + xlx_module = ''' + + XLX Module: + +''' + mode = 'XLX' + submit_link = 'manage_peers?save_mode=xlx_peer' + server_options = '' + for i in s: + server_options = server_options + '''\n''' + content = ''' +

 

+

Add an ''' + mode + ''' peer

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +''' + xlx_module + ''' + + + + + + + + + + + + + + + + + + + + + + + + + +
Assign to Server: 
Connection Name: 
 Active: 
 IP: 
 Port: 
 Passphrase: 
 Master IP: 
 Master Port: 
 Callsign: 
 Radio ID: 
 Transmit Frequency: 
 Receive Frequency: 
 Transmit Power: 
 Color Code: 
 Slots: 
 Latitude: 
 Longitude: 
 Height 
 Location: 
 Description: 
 URL: 
 Group Hangtime: 
 Options: 
 Enable Unit Calls: 
 Use ACLs: 
 Subscriber ACLs: 
 Talkgroup Slot 1 ACLs: 
 Talkgroup Slot 2 ACLs: 
 Notes: 
+

 

+

+''' + +## elif request.args.get('edit_server') and request.args.get('edit_peer') and request.args.get('mode') == 'mmdvm': + elif request.args.get('delete_peer') and request.args.get('peer_server'): + peer_delete(request.args.get('mode'), request.args.get('peer_server'), request.args.get('delete_peer')) + content = '''

PEER deleted.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('edit_mmdvm') == 'save' or request.args.get('edit_xlx') == 'save': + peer_enabled = False + use_acl = False + peer_loose = True + unit_enabled = False + if request.form.get('enabled') == 'true': + peer_enabled = True +## if request.form.get('loose') == 'true': +## peer_loose = True + if request.form.get('use_acl') == 'True': + use_acl = True + if request.form.get('enable_unit') == 'True': + unit_enabled = True +## else: +## peer_loose = False +## print((unit_enabled)) +## print(type(peer_enabled)) +## print(type(use_acl)) + if request.args.get('edit_mmdvm') == 'save': + peer_edit('mmdvm', request.args.get('server'), request.args.get('name'), peer_enabled, peer_loose, request.form.get('ip'), request.form.get('port'), request.form.get('master_ip'), request.form.get('master_port'), request.form.get('passphrase'), request.form.get('callsign'), request.form.get('radio_id'), request.form.get('rx'), request.form.get('tx'), request.form.get('tx_power'), request.form.get('cc'), request.form.get('lat'), request.form.get('lon'), request.form.get('height'), request.form.get('location'), request.form.get('description'), request.form.get('slots'), request.form.get('url'), request.form.get('group_hangtime'), 'MMDVM', request.form.get('options'), use_acl, request.form.get('sub_acl'), request.form.get('tgid_ts1_acl'), request.form.get('tgid_ts2_acl'), unit_enabled, request.form.get('notes')) + content = '''

MMDVM PEER changed.

+

Redirecting in 3 seconds.

+''' + if request.args.get('edit_xlx') == 'save': + peer_edit('xlx', request.args.get('server'), request.args.get('name'), peer_enabled, peer_loose, request.form.get('ip'), request.form.get('port'), request.form.get('master_ip'), request.form.get('master_port'), request.form.get('passphrase'), request.form.get('callsign'), request.form.get('radio_id'), request.form.get('rx'), request.form.get('tx'), request.form.get('tx_power'), request.form.get('cc'), request.form.get('lat'), request.form.get('lon'), request.form.get('height'), request.form.get('location'), request.form.get('description'), request.form.get('slots'), request.form.get('url'), request.form.get('group_hangtime'), request.form.get('xlxmodule'), request.form.get('options'), use_acl, request.form.get('sub_acl'), request.form.get('tgid_ts1_acl'), request.form.get('tgid_ts2_acl'), unit_enabled, request.form.get('notes')) + content = '''

XLX PEER changed.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('server') and request.args.get('peer_name') and request.args.get('mode'): # and request.args.get('edit_peer') and request.args.get('mode') == 'mmdvm': + if request.args.get('mode') == 'mmdvm': + p = mmdvmPeer.query.filter_by(server=request.args.get('server')).filter_by(name=request.args.get('peer_name')).first() + xlx_module = '' + mode = "MMDVM" + form_submit = '''
''' + if request.args.get('mode') == 'xlx': + p = xlxPeer.query.filter_by(server=request.args.get('server')).filter_by(name=request.args.get('peer_name')).first() + form_submit = '''''' + xlx_module = ''' + + XLX Module: + +''' + mode = "XLX" + + content = ''' +

 

+

View/Edit an ''' + mode + ''' peer

+ +

Delete peer

+ +''' + form_submit + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +''' + xlx_module + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Connection Name:  ''' + str(p.name) + '''
 Active: 
 IP: 
 Port: 
 Passphrase: 
 Master IP: 
 Master Port: 
 Callsign: 
 Radio ID: 
 Transmit Frequency: 
 Receive Frequency: 
 Transmit Power: 
 Color Code: 
 Slots: 
 Latitude: 
 Longitude: 
 Height 
 Location: 
 Description: 
 URL: 
 Group Call Hangtime: 
 Options: 
 Enable Unit Calls: 
 Use ACLs: 
 Subscriber ACLs: 
 Talkgroup Slot 1 ACLs: 
 Talkgroup Slot 2 ACLs: 
 Notes: 
+

 

+

+ +

 

+''' + else: + all_s = ServerList.query.all() + p_list = '' + for s in all_s: + # print(s.name) + p_list = p_list + ''' +

Server: ''' + str(s.name) + '''

+ + + + + + + +\n +''' + all_p = mmdvmPeer.query.filter_by(server=s.name).all() + all_x = xlxPeer.query.filter_by(server=s.name).all() + for p in all_p: + p_list = p_list + ''' + + + + + + +''' + for x in all_x: + p_list = p_list + ''' + + + + + + +''' + p_list = p_list + '''
NameModeNotes
''' + str(p.name) + '''MMDVM''' + p.notes + '''
''' + str(x.name) + '''XLX''' + x.notes + '''
\n''' + content = ''' + +

View/Edit Peers

+ + + + + + + + +
Add MMDVM peerAdd XLX peer
+

 

+ +''' + p_list + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + @app.route('/manage_masters', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') + def manage_masters(): + #PROXY + if request.args.get('proxy_save'): + active = False + use_acl = False + enable_unit = False + repeat = True + aprs_pos = False + enable_um = True + external_proxy = False + public = False + if request.form.get('enable_um') == 'False': + enable_um = False + if request.form.get('aprs_pos') == 'True': + aprs_pos = True + if request.form.get('enabled') == 'True': + active = True + if request.form.get('use_acl') == 'True': + use_acl = True + if request.form.get('enable_unit') == 'True': + enable_unit = True + if request.form.get('repeat') == 'False': + repeat = False + if request.form.get('external_proxy') == 'True': + external_proxy = True + if request.form.get('public_list') == 'True': + public = True + if request.args.get('proxy_save') == 'add': + if request.form.get('name_text') == '': + content = '''

PROXY can't have blank name.

+

Redirecting in 3 seconds.

+''' + else: + add_master('PROXY', request.form.get('name_text'), request.form.get('server'), aprs_pos, repeat, active, 0, request.form.get('ip'), request.form.get('external_port'), enable_um, request.form.get('passphrase'), request.form.get('group_hangtime'), use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('ts1_acl'), request.form.get('ts2_acl'), enable_unit, request.form.get('notes'), external_proxy, request.form.get('int_port_start'), request.form.get('int_port_stop'), '', '', '', '', public) + content = '''

PROXY saved.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('proxy_save') == 'edit': +## print(request.args.get('name')) + edit_master('PROXY', request.args.get('name'), request.args.get('server'), aprs_pos, repeat, active, 0, request.form.get('ip'), request.form.get('external_port'), enable_um, request.form.get('passphrase'), request.form.get('group_hangtime'), use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('ts1_acl'), request.form.get('ts2_acl'), enable_unit, request.form.get('notes'), external_proxy, request.form.get('int_port_start'), request.form.get('int_port_stop'), '', '', '', '', public) + content = '''

PROXY changed.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('proxy_save') == 'delete': + master_delete('PROXY', request.args.get('server'), request.args.get('name')) + content = '''

PROXY deleted.

+

Redirecting in 3 seconds.

+''' + # OBP + elif request.args.get('OBP_save'): + enabled = False + use_acl = False + enable_unit = False + both_slots = True + if request.form.get('enabled') == 'True': + enabled = True + if request.form.get('use_acl') == 'True': + use_acl = True + if request.form.get('enable_unit') == 'True': + enable_unit = True + if request.form.get('both_slots') == 'False': + both_slots = False + if request.args.get('OBP_save') == 'add': + if request.form.get('name_text') == '': + content = '''

OpenBridge connection can't have blank name.

+

Redirecting in 3 seconds.

+''' + else: + add_master('OBP', request.form.get('name_text'), request.form.get('server'), '', '', enabled, request.form.get('max_peers'), request.form.get('ip'), request.form.get('port'), '', request.form.get('passphrase'), request.form.get('group_hangtime'), use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('tg_acl'), '', enable_unit, request.form.get('notes'), '', '', '', request.form.get('network_id'), request.form.get('target_ip'), request.form.get('target_port'), both_slots, '') + content = '''

OpenBridge connection saved.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('OBP_save') == 'edit': + edit_master('OBP', request.args.get('name'), request.args.get('server'), '', '', enabled, request.form.get('max_peers'), request.form.get('ip'), request.form.get('port'), '', request.form.get('passphrase'), request.form.get('group_hangtime'), use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('tg_acl'), '', enable_unit, request.form.get('notes'), '', '', '', request.form.get('network_id'), request.form.get('target_ip'), request.form.get('target_port'), both_slots, '') + content = '''

OpenBridge connection changed.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('OBP_save') == 'delete': + master_delete('OBP', request.args.get('server'), request.args.get('name')) + content = '''

OpenBridge connection deleted.

+

Redirecting in 3 seconds.

+''' + # MASTER + elif request.args.get('master_save'): + aprs_pos = False + repeat = False + active = False + use_acl = False + enable_um = False + enable_unit = False + public = False + if request.form.get('aprs_pos') == 'True': + aprs_pos = True + if request.form.get('repeat') == 'True': + repeat = True + if request.form.get('enabled') == 'True': + active = True + if request.form.get('use_acl') == 'True': + use_acl = True + if request.form.get('enable_um') == 'True': + enable_um = True + if request.form.get('enable_unit') == 'True': + enable_unit = True + if request.form.get('public_list') == 'True': + public = True + if request.args.get('master_save') == 'add': + if request.form.get('name_text') == '': + content = '''

MASTER can't have blank name.

+

Redirecting in 3 seconds.

+''' + else: + add_master('MASTER', request.form.get('name_text'), request.form.get('server'), aprs_pos, repeat, active, request.form.get('max_peers'), request.form.get('ip'), request.form.get('port'), enable_um, request.form.get('passphrase'), request.form.get('group_hangtime'), use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('ts1_acl'), request.form.get('ts2_acl'), enable_unit, request.form.get('notes'), '', '', '', '', '', '', '', public) + content = '''

MASTER saved.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('master_save') == 'edit': + edit_master('MASTER', request.args.get('name'), request.args.get('server'), aprs_pos, repeat, active, request.form.get('max_peers'), request.form.get('ip'), request.form.get('port'), enable_um, request.form.get('passphrase'), request.form.get('group_hangtime'), use_acl, request.form.get('reg_acl'), request.form.get('sub_acl'), request.form.get('ts1_acl'), request.form.get('ts2_acl'), enable_unit, request.form.get('notes'), '', '', '', '', '', '', '', public) + content = '''

MASTER changed.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('master_save') == 'delete': + master_delete('MASTER', request.args.get('server'), request.args.get('name')) + content = '''

MASTER deleted.

+

Redirecting in 3 seconds.

+''' + elif request.args.get('add_OBP'): + s = ServerList.query.all() + server_options = '' + for i in s: + server_options = server_options + '''\n''' + content = ''' +

 

+ +

Add an OpenBridge Connection

+

 

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Name: 
 Assign to Server: 
 Active: 
 IP: 
 Port: 
 Passphrase: 
 Network ID: 
 Target IP: 
 Target Port: 
 Use ACLs: 
 Subscriber ACLs: 
 Talkgroup ACLs: 
 Use Both Slots: 
 Enable Unit Calls: 
 Notes: 
+

 

+

+

 

+ +''' + elif request.args.get('edit_proxy'): + # print(request.args.get('server')) + # print(request.args.get('edit_proxy')) + p = ProxyList.query.filter_by(server=request.args.get('server')).filter_by(name=request.args.get('edit_proxy')).first() + content = ''' +

 

+ +

View/Edit Proxy

+ +

Delete Proxy

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Name: ''' + str(p.name) + '''
 Active: 
 Repeat: 
 External Proxy Script: 
 Static APRS positions: 
 User Manager for login: 
 External Port: 
 Internal Port Start: 
 Internal Port Stop: 
 Passphrase: 
 Group Hangtime: 
 Use ACLs: 
 Register ACLs: 
 Subscriber ACLs: 
 Talkgroup Slot 1 ACLs: 
 Talkgroup Slot 2 ACLs: 
 Enable Unit Calls: 
 Public List: 
 Notes: 
+

 

+
+

 

+''' + + elif request.args.get('add_proxy'): + s = ServerList.query.all() + server_options = '' + for i in s: + server_options = server_options + '''\n''' + content = ''' +

 

+ +

Add a PROXY

+

 

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Assign to Server: 
 Name: 
 Active: 
 Repeat: 
 External Proxy Script: 
 Static APRS positions: 
 User Manager for login: 
 IP: 
 External Port: 
 Internal Port Start (lower than stop port): 
 Internal Port Stop: 
 Passphrase: 
 Group Hangtime: 
 Use ACLs: 
 Register ACLs: 
 Subscriber ACLs: 
 Talkgroup Slot 1 ACLs: 
 Talkgroup Slot 2 ACLs: 
 Enable Unit Calls: 
 Public List: 
 Notes: 
+

 

+

+

 

+''' + + + elif request.args.get('add_master'): + s = ServerList.query.all() + server_options = '' + for i in s: + server_options = server_options + '''\n''' + + content = ''' +

 

+

Add an MASTER

+

 

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Assign to Server: 
 Name: 
 Active: 
 Repeat: 
 Max Peers: 
 Static APRS positions: 
 User Manager for login: 
 IP: 
 PORT: 
 Passphrase: 
 Group Hangtime: 
 Use ACLs: 
 Register ACLs: 
 Subscriber ACLs: 
 Talkgroup Slot 1 ACLs: 
 Talkgroup Slot 2 ACLs: 
 Enable Unit Calls: 
 Public List: 
 Notes: 
+

 

+

+

 

+''' + elif request.args.get('edit_OBP'): +## print(request.args.get('server')) +## print(request.args.get('edit_OBP')) +## s = ServerList.query.all() + o = OBP.query.filter_by(server=request.args.get('server')).filter_by(name=request.args.get('edit_OBP')).first() +## print(o.notes) + content = ''' +

 

+

View/Edit OpenBridge Connection

+

Delete OpenBridge Connection

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Name: ''' + str(o.name) + '''
 Active: 
 IP: 
 Port: 
 Passphrase: 
 Network ID: 
 Target IP: 
 Target Port: 
 Use ACLs: 
 Subscriber ACLs: 
 Talkgroup ACLs: 
 Use Both Slots: 
 Enable Unit Calls: 
 Notes: 
+

 

+

+
+

 

+ + ''' + + elif request.args.get('edit_master'): +## s = ServerList.query.all() + m = MasterList.query.filter_by(server=request.args.get('server')).filter_by(name=request.args.get('edit_master')).first() + + content = ''' +

 

+

View/Edit a MASTER

+

Delete MASTER

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Name: ''' + str(m.name) + '''
 Active: 
 Repeat: 
 Max Peers: 
 Static APRS positions: 
 User Manager for login: 
 IP: 
 PORT: 
 Passphrase: 
 Group Hangtime: 
 Use ACLs: 
 Register ACLs: 
 Subscriber ACLs: 
 Talkgroup Slot 1 ACLs: 
 Talkgroup Slot 2 ACLs: 
 Enable Unit Calls: 
 Public List: 
 Notes: 
+

 

+

+

 

+''' +## elif not request.args.get('edit_master') and not request.args.get('edit_OBP') and not request.args.get('add_OBP') and not request.args.get('add_master'): +## content = 'jglkdjklsd' + else: + #elif not request.args.get('add_proxy') or not request.args.get('add_OBP') or not request.args.get('add_master'): # or not request.args.get('proxy_save') or not request.args.get('master_save') or not request.args.get('OBP_save'): + all_s = ServerList.query.all() + m_list = '' + for s in all_s: +## print(s.name) + m_list = m_list + ''' +

Server: ''' + str(s.name) + '''

+ + + + + + + + +''' + all_m = MasterList.query.filter_by(server=s.name).all() + all_p = ProxyList.query.filter_by(server=s.name).all() + all_o = OBP.query.filter_by(server=s.name).all() + for o in all_o: + m_list = m_list + ''' + + + + + + +''' + for p in all_p: + m_list = m_list + ''' + + + + + + +''' + for x in all_m: + m_list = m_list + ''' + + + + + + + +''' + m_list = m_list + '''
NameModeNotes
''' + str(o.name) + '''OpenBridge''' + str(o.notes) + '''
''' + str(p.name) + '''PROXY''' + str(p.notes) + '''
''' + str(x.name) + '''MASTER''' + str(x.notes) + '''
\n''' + content = ''' + +

View/Edit Masters

+ + + + + + + + + + +
Add MASTERAdd PROXYAdd OpenBridge
+

 

+ +''' + m_list + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + + @app.route('/add_user', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') + def add_admin(): + if request.method == 'GET': + content = ''' +
+ + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+ + + +

 

+''' + elif request.method == 'POST' and request.form.get('username'): + if not User.query.filter(User.username == request.form.get('username')).first(): + radioid_data = ast.literal_eval(get_ids(request.form.get('username'))) + user = User( + username=request.form.get('username'), + email=request.form.get('email'), + email_confirmed_at=datetime.datetime.utcnow(), + password=user_manager.hash_password(request.form.get('password')), + dmr_ids = str(radioid_data[0]), + initial_admin_approved = True, + first_name = str(radioid_data[1]), + last_name = str(radioid_data[2]), + city = str(radioid_data[3]) + + ) + + db.session.add(user) + u = User.query.filter_by(username=request.form.get('username')).first() + user_role = UserRoles( + user_id=u.id, + role_id=2, + ) + db.session.add(user_role) + db.session.commit() + content = '''

Created user: ''' + str(request.form.get('username')) + '''

\n''' + elif User.query.filter(User.username == request.form.get('username')).first(): + content = 'Existing user: ' + str(request.form.get('username') + '. New user not created.') + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + @app.route('/manage_rules', methods=['POST', 'GET']) + @login_required + @roles_required('Admin') + def manage_rules(): + + if request.args.get('save_bridge') == 'save': + public = False + if request.form.get('public_list') == 'True': + public = True + if request.form.get('bridge_name') == '': + content = '''

Bridge can't have blank name.

+

Redirecting in 3 seconds.

+''' + else: + bridge_add(request.form.get('bridge_name'), request.form.get('description'), public, request.form.get('tg')) + content = '''

Bridge (talkgroup) saved.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('save_bridge') == 'edit': + public = False + if request.form.get('public_list') == 'True': + public = True + update_bridge_list(request.args.get('bridge'), request.form.get('description'), public, request.form.get('bridge_name'), request.form.get('tg')) + content = '''

Bridge (talkgroup) changed.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('save_bridge') == 'delete': + bridge_delete(request.args.get('bridge')) + content = '''

Bridge (talkgroup) deleted.

+

Redirecting in 3 seconds.

+ ''' + + + #Rules + elif request.args.get('save_rule'): + public_list = False + active = False + if request.form.get('active_dropdown') == 'True': + active = True + if request.args.get('save_rule') == 'new': + add_system_rule(request.form.get('bridge_dropdown'), request.form.get('system_text'), request.form.get('ts_dropdown'), request.form.get('tgid'), active, request.form.get('timer_time'), request.form.get('type_dropdown'), request.form.get('on'), request.form.get('off'), request.form.get('reset'), request.args.get('server'), public_list) + content = '''

Bridge (talkgroup) rule saved.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('save_rule') == 'edit': + content = '''

Bridge (talkgroup) rule changed.

+

Redirecting in 3 seconds.

+ ''' + elif request.args.get('save_rule') == 'delete': + # print(request.args.get('bridge')) + # print(request.args.get('server')) + if request.args.get('system'): + delete_system_rule(request.args.get('bridge'), request.args.get('server'), request.args.get('system')) + else: + delete_system_bridge(request.args.get('bridge'), request.args.get('server')) + +## delete_system_rule(request.args.get('bridge'), request.args.get('server'), request.args.get('system')) + content = '''

System rule deleted.

+

Redirecting in 3 seconds.

+ ''' + + elif request.args.get('add_rule'): +## svl = ServerList.query.all() + bl = BridgeList.query.all() #filter(bridge_name== request.form.get('username')).all() + all_o = OBP.query.filter_by(server=request.args.get('add_rule')).all() + all_m = MasterList.query.filter_by(server=request.args.get('add_rule')).all() + all_p = ProxyList.query.filter_by(server=request.args.get('add_rule')).all() + m_l = mmdvmPeer.query.filter_by(server=request.args.get('add_rule')).all() + x_l = xlxPeer.query.filter_by(server=request.args.get('add_rule')).all() +## print(sl) +## print(bl) +## svl_option = '' + bl_option = '' + sl_option = '' + for i in all_o: + sl_option = sl_option + '''''' + for i in all_m: + sl_option = sl_option + '''''' + for i in all_p: + sl_option = sl_option + '''''' + for i in m_l: + sl_option = sl_option + '''''' + for i in x_l: + sl_option = sl_option + '''''' + for i in bl: + bl_option = bl_option + '''''' + content = ''' +

Add rule to server: ''' + request.args.get('add_rule') + '''

+ +
+

 

+ + + + + + + + + + + + + + + + + +
Bridge (Talkgroup): System: Timeslot: Talkgroup number: Activate on start:  
Timer Time (minutes):  Timer Type:  Trigger ON TGs:   Trigger OFF TGs:  Trigger Reset TGs:  
+

 

+

+
+

 

+ +''' + elif request.args.get('edit_rule') and request.args.get('bridge'): + br = BridgeRules.query.filter_by(server=request.args.get('edit_rule')).filter_by(bridge_name=request.args.get('bridge')).all() + print(br) + br_view = '''

Rules for bridge ''' + request.args.get('bridge') + ''' on server ''' + request.args.get('edit_rule') + '''.

''' + for i in br: + br_view = br_view + ''' + + + +  + + + + + +
Delete SYSTEM Rule
+

 

+ + + + + + + + + + + + + + + + + +
Bridge (Talkgroup): ''' + str(i.bridge_name) + '''System: ''' + str(i.system_name) + '''Timeslot: Talkgroup number: Activate on start:  
Timer Time (minutes):  Timer Type:  Trigger ON TGs:   Trigger OFF TGs:  Trigger Reset TGs:  
+

 

+

+
+

 

+
+

 

+ +''' + content = br_view + + elif request.args.get('edit_rule') == 'save' and request.args.get('bridge_edit'): + public_list = False + active = False + if request.form.get('active_dropdown') == 'True': + active = True + edit_system_rule(request.args.get('bridge_edit'), request.args.get('system'), request.form.get('ts_dropdown'), request.form.get('tgid'), active, request.form.get('timer_time'), request.form.get('type_dropdown'), request.form.get('on'), request.form.get('off'), request.form.get('reset'), request.args.get('server'), public_list) + content = '''

System rule changed.

+

Redirecting in 3 seconds.

+ ''' + + elif request.args.get('add_bridge'): + s = ServerList.query.all() +## server_options = '' +## for i in s: +## server_options = server_options + '''\n''' + + content = ''' +

 

+

Add a Talk Group

+
+ + + + + + + + + + + + + + + + + + + + +

 

+

 

+


 

+
+

 

+ +

+
+
+''' + elif request.args.get('edit_bridge'): + b = BridgeList.query.filter_by(bridge_name=request.args.get('edit_bridge')).first() +## s = ServerList.query.all() +## server_options = '' +## for i in s: +## server_options = server_options + '''\n''' + + content = ''' +

 

+

Edit a Talk Group

+

Delete Talk Group

+

 

+ +
+ + + + + + + + + + + + + + + + + + + + +

 

+

 

+


 

+
+

 

+ +

+
+
+''' + else: + all_b = BridgeList.query.all() + s = ServerList.query.all() + b_list = ''' +

View/Edit Bridges (Talk Groups)

+ + + + + + + + +
Add Bridge
+

 

+ + + + + + + + + + +''' + for i in all_b: + b_list = b_list + ''' + + + + + + +''' + b_list = b_list + '''
NamePublicDescriptionTGID
''' + str(i.bridge_name) + ''' +''' + str(i.public_list) + '''''' + str(i.description) + '''''' + str(i.tg) + '''
+

View/Edit Rules

+ +''' + r_list = '' + for i in s: + # print(i) + r_list = r_list + ''' + + + + + + +
Add a rule to server: ''' + str(i.name) + '''
+ + + + + + +''' + br = BridgeRules.query.filter_by(server=i.name).all() + temp_list = [] + for x in br: #.filter_by(bridge_name=request.args.get('bridge')).all() + if x.bridge_name in temp_list: + pass + else: + temp_list.append(x.bridge_name) + r_list = r_list + ''' + + + + + +''' + r_list = r_list + '''
Bridge Name--
''' + str(x.bridge_name) + '''Edit Bridge RulesDelete Bridge from this server

 

''' + content = b_list + r_list + '''''' + + return render_template('flask_user_layout.html', markup_content = Markup(content)) + + @app.route('/svr', methods=['POST']) + def auth(): + hblink_req = request.json + # print((hblink_req)) + if hblink_req['secret'] in shared_secrets(): + if 'login_id' in hblink_req and 'login_confirmed' not in hblink_req: + if type(hblink_req['login_id']) == int: + if authorized_peer(hblink_req['login_id'])[0]: + print(active_tgs) + if isinstance(authorized_peer(hblink_req['login_id'])[1], int) == True: + authlog_add(hblink_req['login_id'], hblink_req['login_ip'], hblink_req['login_server'], authorized_peer(hblink_req['login_id'])[2], gen_passphrase(hblink_req['login_id']), 'Attempt') +## active_tgs[hblink_req['login_server']][hblink_req['system']] = [{'1':[]}, {'2':[]}, {'SYSTEM': ''}, {'peer_id':hblink_req['login_id']}] + response = jsonify( + allow=True, + mode='normal', + ) + elif authorized_peer(hblink_req['login_id'])[1] == '': + authlog_add(hblink_req['login_id'], hblink_req['login_ip'], hblink_req['login_server'], authorized_peer(hblink_req['login_id'])[2], 'Config Passphrase: ' + legacy_passphrase, 'Attempt') +## active_tgs[hblink_req['login_server']][hblink_req['system']] = [{'1':[]}, {'2':[]}, {'SYSTEM': ''}, {'peer_id':hblink_req['login_id']}] + response = jsonify( + allow=True, + mode='legacy', + ) + elif authorized_peer(hblink_req['login_id'])[1] != '' or isinstance(authorized_peer(hblink_req['login_id'])[1], int) == False: + authlog_add(hblink_req['login_id'], hblink_req['login_ip'], hblink_req['login_server'], authorized_peer(hblink_req['login_id'])[2], authorized_peer(hblink_req['login_id'])[1], 'Attempt') +## active_tgs[hblink_req['login_server']][hblink_req['system']] = [{'1':[]}, {'2':[]}, {'SYSTEM': ''}, {'peer_id':hblink_req['login_id']}] + # print(authorized_peer(hblink_req['login_id'])) + response = jsonify( + allow=True, + mode='override', + value=authorized_peer(hblink_req['login_id'])[1] + ) + try: + active_tgs[hblink_req['login_server']][hblink_req['system']] = [{'1':[]}, {'2':[]}, {'SYSTEM': ''}, {'peer_id':hblink_req['login_id']}] +## print('Restart ' + hblink_req['login_server'] + ' please.') + except: +## active_tgs[hblink_req['login_server']] = {} + pass + elif authorized_peer(hblink_req['login_id'])[0] == False: +## print('log fail') + authlog_add(hblink_req['login_id'], hblink_req['login_ip'], hblink_req['login_server'], 'Not Registered', '-', 'Failed') + response = jsonify( + allow=False) + elif not type(hblink_req['login_id']) == int: + user = hblink_req['login_id'] + u = User.query.filter_by(username=user).first() + + if not u: + msg = jsonify(auth=False, + reason='User not found') + response = make_response(msg, 401) + if u: + u_role = UserRoles.query.filter_by(user_id=u.id).first() + password = user_manager.verify_password(hblink_req['password'], u.password) + if u_role.role_id == 2: + role = 'user' + if u_role.role_id == 1: + role = 'admin' + if password: + response = jsonify(auth=True, role=role) + else: + msg = jsonify(auth=False, + reason='Incorrect password') + response = make_response(msg, 401) + elif 'login_id' in hblink_req and 'login_confirmed' in hblink_req: + if hblink_req['old_auth'] == True: + authlog_add(hblink_req['login_id'], hblink_req['login_ip'], hblink_req['login_server'], authorized_peer(hblink_req['login_id'])[2], 'CONFIG, NO UMS', 'Confirmed') + else: + authlog_add(hblink_req['login_id'], hblink_req['login_ip'], hblink_req['login_server'], authorized_peer(hblink_req['login_id'])[2], 'USER MANAGER', 'Confirmed') + response = jsonify( + logged=True + ) + elif 'burn_list' in hblink_req: # ['burn_list']: # == 'burn_list': + response = jsonify( + burn_list=get_burnlist() + ) + + elif 'get_config' in hblink_req: + if hblink_req['get_config']: + active_tgs[hblink_req['get_config']] = {} + print(active_tgs) + ## try: +## print(get_peer_configs(hblink_req['get_config'])) + response = jsonify( + config=server_get(hblink_req['get_config']), + peers=get_peer_configs(hblink_req['get_config']), + masters=masters_get(hblink_req['get_config']), + ## OBP=get_OBP(hblink_req['get_config']) + + ) + ## except: + ## message = jsonify(message='Config error') + ## response = make_response(message, 401) + elif 'get_rules' in hblink_req: + if hblink_req['get_rules']: # == 'burn_list': + + ## try: + response = jsonify( + rules=generate_rules(hblink_req['get_rules']), + ## OBP=get_OBP(hblink_req['get_config']) + + ) + ## except: + ## message = jsonify(message='Config error') + ## response = make_response(message, 401) + elif 'update_tg' in hblink_req: + if hblink_req['update_tg']: + print(hblink_req) +## print(hblink_req['data'][0]['SYSTEM']) + if 'on' == hblink_req['mode']: +## try: + if hblink_req['dmr_id'] == 0: + print('id 0') +## print(active_tgs) + for system in active_tgs[hblink_req['update_tg']].items(): + ## print(system) + ## print('sys') + if system[0] == hblink_req['data'][0]['SYSTEM']: + print(active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][0]['1']) +## print(hblink_req['data'][2]['tg']) + print('---------') + print(active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][1]['2']) + ## print(hblink_req['data'][1]['ts']) + if hblink_req['data'][1]['ts'] == 1: + #### print(active_tgs[hblink_req['update_tg']][system[0]][0]['1']) + + if active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][0]['1'] == hblink_req['data'][2]['tg']: + pass + else: + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][0]['1'].append(hblink_req['data'][2]['tg']) + #### active_tgs[hblink_req['update_tg']][system[0]][0]['1'].append(0) + if hblink_req['data'][1]['ts'] == 2: + if active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][1]['2'] == hblink_req['data'][2]['tg']: + pass + #### print(active_tgs[hblink_req['update_tg']][system[0]][1]['2']) + else: + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][1]['2'].append(hblink_req['data'][2]['tg']) + else: + try: + print('---------on------------') + print(hblink_req['data']) + print(active_tgs[hblink_req['update_tg']]) + print(hblink_req['data'][2]['ts2']) + print('-----------------------') + ## active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][2]['SYSTEM'] = hblink_req['data'][0]['SYSTEM'] + #### active_tgs[hblink_req['update_tg']][hblink_req['dmr_id']].update({hblink_req['data'][0]['SYSTEM']: [{1:[hblink_req['data'][1]['ts1']]}, {2:[hblink_req['data'][2]['ts2']]}]}) #.update({[hblink_req['dmr_id']]:hblink_req['data']}) + if hblink_req['data'][1]['ts1'] not in active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][0]['1']: + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][0]['1'].append(hblink_req['data'][1]['ts1']) + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][2]['SYSTEM'] = hblink_req['data'][0]['SYSTEM'] + if hblink_req['data'][2]['ts2'] not in active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][1]['2']: + print('---0---') + print(hblink_req['data'][0]['SYSTEM']) + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][2]['SYSTEM'] = hblink_req['data'][0]['SYSTEM'] + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][1]['2'].append(hblink_req['data'][2]['ts2']) +## print('append') + #### active_tgs[hblink_req['update_tg']][system[0]][1]['2'].append(0) + ## print(hblink_req['data'][0]['SYSTEM']) + + ## print(active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']]) + ## print(active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][2]['2']) + ## print(hblink_req['data'][1]['ts2']) + ## print(active_tgs[hblink_req['update_tg']]) + except: +## active_tgs[hblink_req['update_tg']] = {} + pass + +## except: +## pass + + + elif 'off' == hblink_req['mode']: + print('off') + for system in active_tgs[hblink_req['update_tg']].items(): + print(system) + if system[0] == hblink_req['data'][0]['SYSTEM']: + print('yes it is') +#### print(system[0]) +#### print(active_tgs[hblink_req['update_tg']][system[0]]) + if hblink_req['data'][1]['ts'] == 1: +#### print(active_tgs[hblink_req['update_tg']][system[0]][0]['1']) + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][0]['1'].remove(hblink_req['data'][2]['tg']) +#### active_tgs[hblink_req['update_tg']][system[0]][0]['1'].append(0) + if hblink_req['data'][1]['ts'] == 2: +#### print(active_tgs[hblink_req['update_tg']][system[0]][1]['2']) + active_tgs[hblink_req['update_tg']][hblink_req['data'][0]['SYSTEM']][1]['2'].remove(hblink_req['data'][2]['tg']) +#### active_tgs[hblink_req['update_tg']][system[0]][1]['2'].append(0) + + + +## print() +## print(system) +## print(system[1][2]['SYSTEM']) +## print('off') +## print(hblink_req['data'][1]['ts']) +## print(hblink_req['data'][2]['tg']) + print(active_tgs) + response = 'got it' + else: + message = jsonify(message='Authentication error') + response = make_response(message, 401) + return response + + + + return app + + +if __name__ == '__main__': + app = create_app() + app.run(debug = True, port=hws_port, host=hws_host) diff --git a/web/config-SAMPLE.py b/web/config-SAMPLE.py new file mode 100644 index 0000000..db58108 --- /dev/null +++ b/web/config-SAMPLE.py @@ -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 + '" ' + +# 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' + diff --git a/web/gen_script_template-SAMPLE.py b/web/gen_script_template-SAMPLE.py new file mode 100644 index 0000000..459718e --- /dev/null +++ b/web/gen_script_template-SAMPLE.py @@ -0,0 +1,5 @@ +def gen_script(dmr_id, passphrase): + script = ''' +DMR ID: ''' + str(dmr_id) + ''' \n Passphrase: ''' + str(passphrase) + ''' +''' + return script diff --git a/web/static/HBnet.png b/web/static/HBnet.png new file mode 100644 index 0000000..c670424 Binary files /dev/null and b/web/static/HBnet.png differ diff --git a/web/templates/flask_user/edit_user_profile.html b/web/templates/flask_user/edit_user_profile.html new file mode 100644 index 0000000..ad30a56 --- /dev/null +++ b/web/templates/flask_user/edit_user_profile.html @@ -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 %} +

{%trans%}User profile{%endtrans%}

+ +
+ {{ 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 %} +
+
+

Update your information from RadioID.net

+{% if not user_manager.USER_ENABLE_AUTH0 %} + {% if user_manager.USER_ENABLE_CHANGE_USERNAME %} +

{%trans%}Change username{%endtrans%}

+ {% endif %} + {% if user_manager.USER_ENABLE_CHANGE_PASSWORD %} +

{%trans%}Change password{%endtrans%}

+ {% endif %} +{% endif %} + +{% endblock %} diff --git a/web/templates/flask_user/emails/base_message.html b/web/templates/flask_user/emails/base_message.html new file mode 100644 index 0000000..5a4c0d7 --- /dev/null +++ b/web/templates/flask_user/emails/base_message.html @@ -0,0 +1,8 @@ +

Dear {{ user.email }} - {{ user.username }},

+ +{% block message %} +{% endblock %} + +

Sincerely,
+{{ app_name }} +

diff --git a/web/templates/flask_user/login.html b/web/templates/flask_user/login.html new file mode 100644 index 0000000..3dcab9e --- /dev/null +++ b/web/templates/flask_user/login.html @@ -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 %} +

{%trans%}Sign in{%endtrans%}

+

 

+ +Your username MUST be your callsign or email address. +

 

+ +
+ {{ form.hidden_tag() }} + + {# Username or Email field #} + {% set field = form.username if user_manager.USER_ENABLE_USERNAME else form.email %} +
+ {# Label on left, "New here? Register." on right #} +
+
+ +
+
+ {% if user_manager.USER_ENABLE_REGISTER and not user_manager.USER_REQUIRE_INVITATION %} + + {%trans%}New here? Register.{%endtrans%} + {% endif %} +
+
+ {{ field(class_='form-control', tabindex=110) }} + {% if field.errors %} + {% for e in field.errors %} +

{{ e }}

+ {% endfor %} + {% endif %} +
+ + {# Password field #} + {% set field = form.password %} +
+ {# Label on left, "Forgot your Password?" on right #} +
+
+ +
+
+ {% if user_manager.USER_ENABLE_FORGOT_PASSWORD %} + + {%trans%}Forgot your Password?{%endtrans%} + {% endif %} +
+
+ {{ field(class_='form-control', tabindex=120) }} + {% if field.errors %} + {% for e in field.errors %} +

{{ e }}

+ {% endfor %} + {% endif %} +
+ + {# 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) }} +
+ +{% endblock %} diff --git a/web/templates/flask_user/register.html b/web/templates/flask_user/register.html new file mode 100644 index 0000000..f938afb --- /dev/null +++ b/web/templates/flask_user/register.html @@ -0,0 +1,50 @@ +{% extends 'flask_user/_public_base.html' %} + +{% block content %} +{% from "flask_user/_macros.html" import render_field, render_submit_field %} +

{%trans%}Register{%endtrans%}

+

 

+ +Your username MUST be your callsign. After filling out the fields, a confirmation link will be emailed to you. +

 

+ +
+ {{ form.hidden_tag() }} + + {# Username or Email #} + {% set field = form.username if user_manager.USER_ENABLE_USERNAME else form.email %} +
+ {# Label on left, "Already registered? Sign in." on right #} +
+
+ +
+
+ {% if user_manager.USER_ENABLE_REGISTER %} + + {%trans%}Already registered? Sign in.{%endtrans%} + {% endif %} +
+
+ {{ field(class_='form-control', tabindex=210) }} + {% if field.errors %} + {% for e in field.errors %} +

{{ e }}

+ {% endfor %} + {% endif %} +
+ + {% 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) }} +
+ +{% endblock %} diff --git a/web/templates/flask_user_layout.html b/web/templates/flask_user_layout.html new file mode 100644 index 0000000..9d7a848 --- /dev/null +++ b/web/templates/flask_user_layout.html @@ -0,0 +1,144 @@ + + + + + + + {{ user_manager.USER_APP_NAME }} + + + + + + + + + + + + {# *** Allow sub-templates to insert extra html to the head section *** #} + {% block extra_css %}{% endblock %} + + + + +

{{ user_manager.USER_APP_NAME }}

+

Logo

+

{{title}}

+
+ + + + + + {% if not call_or_get(current_user.is_authenticated) %} + + + {% endif %} + {% if call_or_get(current_user.is_authenticated) %} + {% if call_or_get(current_user.has_roles('Admin')) %} + + + + + + {% endif %} + + + + + + {% endif %} + + +
HomeRegisterSign inAdd a UserEdit UsersWaiting ApprovalAuth LogHelpView Passphrase(s)Current TGsEdit {{ current_user.username or current_user.email }}Sign out
+ +{% if call_or_get(current_user.is_authenticated) %} + {% if call_or_get(current_user.has_roles('Admin')) %} + + + + + + + + + +
Manage ServersManage PeersManage MastersManage Rules
+ {% endif %} + {% endif %} + +
+ {% block body %} + +
+ +
+ {# 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 %} +
{{ message|safe }}
+ {% endfor %} + {% endif %} + {%- endwith %} + {% endblock %} + {% block main %} + {% block content %} + + {{markup_content}} + + + {% endblock %} + {% endblock %} +
+ +
+
+ + {% endblock %} + + + + + + + {# *** Allow sub-templates to insert extra html to the bottom of the body *** #} + {% block extra_js %}{% endblock %} + + + diff --git a/web/templates/help.html b/web/templates/help.html new file mode 100644 index 0000000..3a063f2 --- /dev/null +++ b/web/templates/help.html @@ -0,0 +1,4 @@ +{% extends 'flask_user/_public_base.html' %} +{% block content %} +This is a help page.

+{% endblock %} diff --git a/web/templates/index.html b/web/templates/index.html new file mode 100644 index 0000000..8cb812a --- /dev/null +++ b/web/templates/index.html @@ -0,0 +1,4 @@ +{% extends 'flask_user/_public_base.html' %} +{% block content %} +

Welcome to the {{ user_manager.USER_APP_NAME }}. This tool is used to manage your access.

+{% endblock %} diff --git a/web/templates/view_passphrase.html b/web/templates/view_passphrase.html new file mode 100644 index 0000000..aaf231e --- /dev/null +++ b/web/templates/view_passphrase.html @@ -0,0 +1,34 @@ +{% extends 'flask_user/_public_base.html' %} +{% block content %} +

 

Click here for automated Pi-Star script.

 

+ + + + + + + + +
+ + + + + + + + + + + + + + + + +
Name:My Server
Host/IP:127.0.0.1
Port:62030
+ +
{{markup_content}} +
+

 

+{% endblock %}