mirror of
https://github.com/mynodebtc/mynode.git
synced 2024-12-26 14:34:00 +00:00
Improve error and success message logging
This commit is contained in:
parent
185539e8a6
commit
22f76f4d07
|
@ -1,4 +1,4 @@
|
|||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect, send_from_directory, url_for
|
||||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect, send_from_directory, url_for, flash
|
||||
from pprint import pprint, pformat
|
||||
from threading import Timer
|
||||
from bitcoin_info import *
|
||||
|
@ -53,20 +53,13 @@ def page_lnd():
|
|||
wallet_logged_in = is_lnd_logged_in()
|
||||
channel_backup_exists = lnd_channel_backup_exists()
|
||||
|
||||
message = ""
|
||||
if request.args.get('error_message'):
|
||||
message = Markup("<div class='error_message'>"+request.args.get('error_message')+"</div>")
|
||||
if request.args.get('success_message'):
|
||||
message = Markup("<div class='success_message'>"+request.args.get('success_message')+"</div>")
|
||||
|
||||
if not lnd_wallet_exists():
|
||||
templateData = {
|
||||
"title": "myNode Lightning Wallet",
|
||||
"wallet_exists": wallet_exists,
|
||||
"wallet_logged_in": wallet_logged_in,
|
||||
"version": get_lnd_version(),
|
||||
"status": status,
|
||||
"message": message
|
||||
"status": status
|
||||
}
|
||||
return render_template('lnd.html', **templateData)
|
||||
|
||||
|
@ -76,8 +69,7 @@ def page_lnd():
|
|||
"wallet_exists": wallet_exists,
|
||||
"wallet_logged_in": wallet_logged_in,
|
||||
"status": get_lnd_status(),
|
||||
"version": get_lnd_version(),
|
||||
"message": message
|
||||
"version": get_lnd_version()
|
||||
}
|
||||
return render_template('lnd.html', **templateData)
|
||||
|
||||
|
@ -135,7 +127,8 @@ def lnd_macaroon():
|
|||
p = pam.pam()
|
||||
pw = request.form.get('password_download_macaroon')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_lnd", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
# Download macaroon
|
||||
return send_from_directory(directory="/mnt/hdd/mynode/lnd/data/chain/bitcoin/mainnet/", filename="admin.macaroon")
|
||||
|
@ -175,10 +168,12 @@ def page_lnd_create_wallet_with_seed():
|
|||
# Create wallet!
|
||||
seed = request.form.get('seed').strip()
|
||||
if create_wallet(seed):
|
||||
return redirect(url_for(".page_lnd", success_message="Wallet Created!"))
|
||||
flash("Wallet Created!", category="message")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
# Error creating wallet
|
||||
return redirect(url_for(".page_lnd", error_message="Error Creating Wallet"))
|
||||
flash("Error Creating Wallet!", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
|
||||
@mynode_lnd.route("/lnd/create_wallet_confirm", methods=['GET','POST'])
|
||||
|
@ -194,15 +189,18 @@ def page_lnd_create_wallet_confirm():
|
|||
seed = request.form.get('seed').strip()
|
||||
if seed != session['seed']:
|
||||
session["seed"] = None
|
||||
return redirect(url_for(".page_lnd", error_message="Incorrect Seed"))
|
||||
flash("Incorrect Seed", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
session["seed"] = None
|
||||
|
||||
# Seed matches, create wallet!
|
||||
if create_wallet(seed):
|
||||
return redirect(url_for(".page_lnd", success_message="Wallet Created!"))
|
||||
flash("Wallet Created!", category="message")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
# Error creating wallet
|
||||
return redirect(url_for(".page_lnd", error_message="Error Creating Wallet"))
|
||||
flash("Error Creating Wallet!", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
|
||||
@mynode_lnd.route("/lnd/lndconnect", methods=["GET","POST"])
|
||||
|
@ -213,8 +211,14 @@ def page_lnd_lndconnect():
|
|||
|
||||
p = pam.pam()
|
||||
pw = request.form.get('password_lndconnect')
|
||||
from_homepage = request.form.get('lndconnect_from_homepage')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_lnd", error_message="Invalid Password"))
|
||||
if from_homepage != None:
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect("/")
|
||||
else:
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
lndconnect_local_grpc_text = get_text_contents("/tmp/mynode_lndconnect/lndconnect_local_grpc.txt")
|
||||
lndconnect_local_rest_text = get_text_contents("/tmp/mynode_lndconnect/lndconnect_local_rest.txt")
|
||||
|
@ -253,14 +257,17 @@ def page_lnd_change_alias():
|
|||
p = pam.pam()
|
||||
pw = request.form.get('password_change_alias')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_lnd", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
|
||||
# Change alias
|
||||
alias = request.form.get('alias')
|
||||
if alias == None or alias == "":
|
||||
return redirect(url_for(".page_lnd", error_message="Empty Alias"))
|
||||
flash("Empty Alias", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
if len(alias) > 35:
|
||||
return redirect(url_for(".page_lnd", error_message="Invalid Alias"))
|
||||
flash("Invalid Alias", category="error")
|
||||
return redirect(url_for(".page_lnd"))
|
||||
with open("/mnt/hdd/mynode/settings/.lndalias", "w") as f:
|
||||
utf8_alias = alias.decode('utf-8', 'ignore')
|
||||
f.write(utf8_alias)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from config import *
|
||||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect, send_from_directory, url_for
|
||||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect, send_from_directory, url_for, flash
|
||||
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
|
||||
from pprint import pprint, pformat
|
||||
from threading import Timer
|
||||
|
@ -130,15 +130,8 @@ def page_settings():
|
|||
except:
|
||||
quicksync_status = "ERROR"
|
||||
|
||||
message = ""
|
||||
if request.args.get('error_message'):
|
||||
message = Markup("<div class='error_message'>"+request.args.get('error_message')+"</div>")
|
||||
if request.args.get('success_message'):
|
||||
message = Markup("<div class='success_message'>"+request.args.get('success_message')+"</div>")
|
||||
|
||||
templateData = {
|
||||
"title": "myNode Settings",
|
||||
"message": message,
|
||||
"password_message": "",
|
||||
"current_version": current_version,
|
||||
"latest_version": latest_version,
|
||||
|
@ -236,7 +229,8 @@ def factory_reset_page():
|
|||
p = pam.pam()
|
||||
pw = request.form.get('password_factory_reset')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_settings", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_settings"))
|
||||
else:
|
||||
t = Timer(2.0, factory_reset)
|
||||
t.start()
|
||||
|
@ -254,24 +248,25 @@ def change_password_page():
|
|||
if not request:
|
||||
return redirect("/settings")
|
||||
|
||||
message = "<div class='success_message'>Successfully changed password!</div>"
|
||||
|
||||
# Verify current password
|
||||
p = pam.pam()
|
||||
current = request.form.get('current_password')
|
||||
if current == None or p.authenticate("admin", current) == False:
|
||||
return redirect(url_for(".page_settings", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_settings"))
|
||||
|
||||
p1 = request.form.get('password1')
|
||||
p2 = request.form.get('password2')
|
||||
|
||||
if p1 == None or p2 == None or p1 == "" or p2 == "" or p1 != p2:
|
||||
return redirect(url_for(".page_settings", error_message="Passwords did not match or were empty!"))
|
||||
flash("Passwords did not match or were empty!", category="error")
|
||||
return redirect(url_for(".page_settings"))
|
||||
else:
|
||||
# Change password
|
||||
subprocess.call(['/usr/bin/mynode_chpasswd.sh', p1])
|
||||
|
||||
return redirect(url_for(".page_settings", success_message="Password Updated!"))
|
||||
flash("Password Updated!", category="message")
|
||||
return redirect(url_for(".page_settings"))
|
||||
|
||||
|
||||
@mynode_settings.route("/settings/delete-lnd-wallet", methods=['POST'])
|
||||
|
@ -279,13 +274,15 @@ def page_lnd_delete_wallet():
|
|||
p = pam.pam()
|
||||
pw = request.form.get('password_lnd_delete')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_settings", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_settings"))
|
||||
else:
|
||||
# Successful Auth
|
||||
delete_lnd_data()
|
||||
restart_lnd()
|
||||
|
||||
return redirect(url_for(".page_settings", success_message="Lightning wallet deleted!"))
|
||||
flash("Lightning wallet deleted!", category="message")
|
||||
return redirect(url_for(".page_settings"))
|
||||
|
||||
@mynode_settings.route("/settings/mynode_logs.tar.gz")
|
||||
def download_logs_page():
|
||||
|
|
BIN
rootfs/standard/var/www/mynode/static/images/lndconnect.png
Normal file
BIN
rootfs/standard/var/www/mynode/static/images/lndconnect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -1,45 +0,0 @@
|
|||
<div class="app_tile_row">
|
||||
<div class="app_tile">
|
||||
<div class="app_status_icon {{ rtl_status_color }}"></div>
|
||||
<div class="app_logo"><img class="app_logo_icon" src="{{ url_for('static', filename="images/rtl.png")}}"/></div>
|
||||
<div class="app_title">RTL</div>
|
||||
<div class="app_status">{% if not lnd_ready %}Waiting on LND...{% else %}{{ rtl_status }}{% endif %}</div>
|
||||
<div class="app_contents">
|
||||
{% if lnd_ready %}
|
||||
<a class="ui-button ui-widget ui-corner-all mynode_button" href="#" id="rtl">RTL</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="app_tile">
|
||||
<div class="app_status_icon {{ lnd_admin_status_color }}"></div>
|
||||
<div class="app_logo"><img class="app_logo_icon" src="{{ url_for('static', filename="images/lnd_admin.png")}}"/></div>
|
||||
<div class="app_title">LND Admin</div>
|
||||
<div class="app_status">{% if not lnd_ready %}Waiting on LND...{% else %}{{ lnd_admin_status }}{% endif %}</div>
|
||||
<div class="app_contents">
|
||||
{% if lnd_ready %}
|
||||
<a class="ui-button ui-widget ui-corner-all mynode_button" href="#" id="lnd_admin">LND Admin</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="app_tile">
|
||||
<div class="app_status_icon {{ lndhub_status_color }}"></div>
|
||||
<div class="app_logo"><img class="app_logo_icon" src="{{ url_for('static', filename="images/lndhub.png")}}"/></div>
|
||||
<div class="app_title">LND Hub</div>
|
||||
<div class="app_status">{% if not lnd_ready %}Waiting on LND...{% endif %}</div>
|
||||
<div class="app_contents">
|
||||
{% if lnd_ready %}
|
||||
{% if lndhub_enabled %}
|
||||
<a class="ui-button ui-widget ui-corner-all mynode_button" href="#" id="lndhub">LND Hub</a>
|
||||
{% endif %}
|
||||
<a class="ui-button ui-widget ui-corner-all mynode_button" href="/toggle-lndhub" id="toggle-lndhub">{% if lndhub_enabled %}Disable{% else %}Enable{% endif %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="app_tile">
|
||||
<div class="app_status_icon"></div>
|
||||
<div class="app_logo"><img class="app_logo_icon" src="{{ url_for('static', filename="images/cli.png")}}"/></div>
|
||||
<div class="app_title">BTC CLI</div>
|
||||
<div class="app_status"></div>
|
||||
<div class="app_contents"><a class="ui-button ui-widget ui-corner-all mynode_button" href="/bitcoin-cli">CLI</a></div>
|
||||
</div>
|
||||
</div>
|
|
@ -22,6 +22,17 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="app_tile">
|
||||
<div class="app_status_icon {{ lnd_status_color }}"></div>
|
||||
<div class="app_logo"><img class="app_logo_icon" src="{{ url_for('static', filename="images/lndconnect.png")}}"/></div>
|
||||
<div class="app_title">LND Connect</div>
|
||||
<div class="app_status">{% if not lnd_ready %}Waiting on LND...{% endif %}</div>
|
||||
<div class="app_contents">
|
||||
{% if lnd_ready %}
|
||||
<a class="ui-button ui-widget ui-corner-all mynode_button" href="#" id="lndconnect">LND Admin</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="app_tile">
|
||||
<div class="app_status_icon {{ lndhub_status_color }}"></div>
|
||||
<div class="app_logo"><img class="app_logo_icon" src="{{ url_for('static', filename="images/lndhub.png")}}"/></div>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Show any Success -->
|
||||
{% with errors = get_flashed_messages(category_filter=["message"]) %}
|
||||
{% if errors %}
|
||||
<div style="margin: auto; text-align: center;">
|
||||
{%- for msg in errors %}
|
||||
<div class='success_message'>{{ msg }}</div><br/>
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<!-- Show any Errors -->
|
||||
{% with errors = get_flashed_messages(category_filter=["error"]) %}
|
||||
{% if errors %}
|
||||
<div style="margin: auto; text-align: center;">
|
||||
{%- for msg in errors %}
|
||||
<div class='error_message'>{{ msg }}</div><br/>
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
|
@ -115,9 +115,7 @@
|
|||
<a class="ui-button ui-widget ui-corner-all mynode_back" href="/"><span class="ui-icon ui-icon-home"></span>home </a>
|
||||
</div>
|
||||
|
||||
<div style="margin: auto; text-align: center;">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% include 'includes/message_display.html' %}
|
||||
|
||||
<div class="main_header">Lightning Status</div>
|
||||
<div class="app_tile_row">
|
||||
|
|
|
@ -85,6 +85,35 @@
|
|||
window.location.href="/toggle-btcrpcexplorer"
|
||||
});
|
||||
|
||||
function lndconnect() {
|
||||
$("#lndconnect_form").submit();
|
||||
lndconnect_dialog.dialog( "close" );
|
||||
}
|
||||
lndconnect_dialog = $( "#lndconnect-dialog" ).dialog({
|
||||
autoOpen: false,
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: 600,
|
||||
modal: true,
|
||||
position: { my: "center top", at: "center top", of: window, collision: "none" },
|
||||
buttons: {
|
||||
"View": lndconnect,
|
||||
Cancel: function() {
|
||||
lndconnect_dialog.dialog( "close" );
|
||||
}
|
||||
},
|
||||
open: function() {
|
||||
$("#password_lndconnect").val("")
|
||||
}
|
||||
});
|
||||
$("#lndconnect").on("click", function() {
|
||||
lndconnect_dialog.dialog( "open" );
|
||||
});
|
||||
|
||||
$("#lndconnect_form").on("submit", function() {
|
||||
lndconnect_dialog.dialog( "close" );
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
@ -98,6 +127,8 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include 'includes/message_display.html' %}
|
||||
|
||||
<div class="app_tile_row">
|
||||
<div>
|
||||
<div class="main_header">Core Services</div>
|
||||
|
@ -247,6 +278,21 @@
|
|||
|
||||
<div id="confirm-dialog"></div>
|
||||
<div id="info-dialog"></div>
|
||||
|
||||
<div id="lndconnect-dialog" title="LND Connect Access" style="display:none;">
|
||||
<form id="lndconnect_form" name="lndconnect_form" action="/lnd/lndconnect" method="POST">
|
||||
<p>LND Connect info will allow access to your Lightning Wallet! Do not share this info with others
|
||||
or they will be able to control your funds.</p>
|
||||
<p>Please enter your password to view your lndconnect codes.</p>
|
||||
<b>Password:</b>
|
||||
<br/>
|
||||
<input type="password" name="password_lndconnect" id="password_lndconnect" value="" class="text ui-widget-content ui-corner-all">
|
||||
<input type="hidden" name="lndconnect_from_homepage" id="lndconnect_from_homepage" value="1"/>
|
||||
|
||||
<!-- Allow form submission with keyboard without duplicating the dialog button -->
|
||||
<input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% include 'includes/footer.html' %}
|
||||
</body>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect
|
||||
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
|
||||
from pprint import pprint, pformat
|
||||
from device_info import is_community_edition
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
|
@ -13,20 +14,39 @@ mynode_tor = Blueprint('mynode_tor',__name__)
|
|||
def page_tor():
|
||||
electrs_onion_hostname = "..."
|
||||
electrs_onion_command = "..."
|
||||
lnd_onion_hostname = "..."
|
||||
lnd_onion_password = "..."
|
||||
|
||||
# Check if we are premium
|
||||
if is_community_edition():
|
||||
return redirect("/")
|
||||
|
||||
# Get Onion URLs
|
||||
if os.path.isfile("/var/lib/tor/electrs_hidden_service/hostname"):
|
||||
with open("/var/lib/tor/electrs_hidden_service/hostname") as f:
|
||||
electrs_onion_hostname = f.read().strip()
|
||||
electrs_onion_command = "./electrum -1 -s {}:50001:t -p socks5:localhost:9050".format(electrs_onion_hostname)
|
||||
else:
|
||||
electrs_onion_hostname = "disabled"
|
||||
electrs_onion_command = "disabled"
|
||||
try:
|
||||
if os.path.isfile("/var/lib/tor/electrs_hidden_service/hostname"):
|
||||
with open("/var/lib/tor/electrs_hidden_service/hostname") as f:
|
||||
electrs_onion_hostname = f.read().strip()
|
||||
electrs_onion_command = "./electrum -1 -s {}:50001:t -p socks5:localhost:9050".format(electrs_onion_hostname)
|
||||
else:
|
||||
electrs_onion_hostname = "disabled"
|
||||
electrs_onion_command = "disabled"
|
||||
|
||||
if os.path.isfile("/var/lib/tor/lnd_api/hostname"):
|
||||
with open("/var/lib/tor/lnd_api/hostname") as f:
|
||||
contents = f.read().split()
|
||||
lnd_onion_hostname = contents[0]
|
||||
lnd_onion_password = contents[1]
|
||||
except:
|
||||
electrs_onion_hostname = "error"
|
||||
lnd_onion_hostname = "error"
|
||||
|
||||
|
||||
# Load page
|
||||
templateData = {
|
||||
"title": "myNode Tor Services",
|
||||
"electrs_onion_hostname": electrs_onion_hostname,
|
||||
"electrs_onion_command": electrs_onion_command
|
||||
"electrs_onion_command": electrs_onion_command,
|
||||
"lnd_onion_hostname": lnd_onion_hostname,
|
||||
"lnd_onion_password": lnd_onion_password
|
||||
}
|
||||
return render_template('tor.html', **templateData)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect, send_from_directory, url_for
|
||||
from flask import Blueprint, render_template, session, abort, Markup, request, redirect, send_from_directory, url_for, flash
|
||||
from thread_functions import get_public_ip
|
||||
from device_info import is_community_edition
|
||||
import subprocess
|
||||
import pam
|
||||
import os
|
||||
|
@ -14,11 +15,9 @@ mynode_vpn = Blueprint('mynode_vpn',__name__)
|
|||
@mynode_vpn.route("/vpn-info")
|
||||
def page_vpn_info():
|
||||
|
||||
message = ""
|
||||
if request.args.get('error_message'):
|
||||
message = Markup("<div class='error_message'>"+request.args.get('error_message')+"</div>")
|
||||
if request.args.get('success_message'):
|
||||
message = Markup("<div class='success_message'>"+request.args.get('success_message')+"</div>")
|
||||
# Check if we are premium
|
||||
if is_community_edition():
|
||||
return redirect("/")
|
||||
|
||||
# Check if port is forwarded
|
||||
port_forwarded = False
|
||||
|
@ -36,7 +35,6 @@ def page_vpn_info():
|
|||
templateData = {
|
||||
"title": "myNode VPN Info",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"vpn_file_exists": vpn_file_exists,
|
||||
"port_forwarded": port_forwarded,
|
||||
"public_ip": ip,
|
||||
|
@ -49,7 +47,8 @@ def page_regen_vpn():
|
|||
p = pam.pam()
|
||||
pw = request.form.get('password_regen_ovpn')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_vpn_info", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_vpn_info"))
|
||||
|
||||
# Stop
|
||||
#os.system("rm /home/pivpn/ovpns/mynode_vpn.ovpn")
|
||||
|
@ -64,14 +63,16 @@ def page_regen_vpn():
|
|||
os.system("systemctl start vpn")
|
||||
|
||||
# Download ovpn
|
||||
return redirect(url_for(".page_vpn_info", success_message="Regenerating VPN files..."))
|
||||
flash("Regenerating VPN files...", category="message")
|
||||
return redirect(url_for(".page_vpn_info"))
|
||||
|
||||
@mynode_vpn.route("/mynode.ovpn", methods=["POST"])
|
||||
def page_download_ovpn():
|
||||
p = pam.pam()
|
||||
pw = request.form.get('password_download_ovpn')
|
||||
if pw == None or p.authenticate("admin", pw) == False:
|
||||
return redirect(url_for(".page_vpn_info", error_message="Invalid Password"))
|
||||
flash("Invalid Password", category="error")
|
||||
return redirect(url_for(".page_vpn_info"))
|
||||
|
||||
# Download ovpn
|
||||
return send_from_directory(directory="/home/pivpn/ovpns/", filename="mynode_vpn.ovpn")
|
||||
|
|
Loading…
Reference in New Issue
Block a user