GUI: Settings / Changepassword page updates + Various fixes. (#318)

* GUI: Settings page updates / fixes.

* Fix Enabled/Disabled logic.

* GUI: Changepassword add warning / + disabled coins check / Various Fixes.
This commit is contained in:
Gerlof van Ek
2025-06-13 14:46:16 +02:00
committed by GitHub
parent 125fbb43db
commit 45b4ac8ca0
3 changed files with 99 additions and 6 deletions

View File

@@ -44,6 +44,48 @@
</section> </section>
{% include 'inc_messages.html' %} {% include 'inc_messages.html' %}
{% set disabled_coins = [] %}
{% for c in chains_formatted %}
{% if c.connection_type == "none" %}
{% set _ = disabled_coins.append(c.display_name) %}
{% endif %}
{% endfor %}
{% if disabled_coins|length > 0 %}
<section class="py-4 px-6" role="alert">
<div class="lg:container mx-auto">
<div class="p-6 text-red-800 rounded-lg bg-red-50 border border-red-400 dark:bg-gray-500 dark:text-red-400 rounded-md">
<div class="flex flex-wrap justify-between items-center -m-2">
<div class="flex-1 p-2">
<div class="flex flex-wrap -m-1">
<ul class="ml-4 mt-1">
<li class="font-semibold text-sm text-red-500 error_msg"><span class="bold">WARNING:</span></li>
<li class="font-medium text-sm text-red-500 error_msg mb-2">Password Change Blocked - Disabled Coins Detected</li>
<li class="font-medium text-sm text-red-500 error_msg mb-2">
<strong>Changing your password now will break your installation!</strong>
</li>
<li class="font-medium text-sm text-red-500 error_msg mb-2">
The following coins are currently disabled and will NOT have their passwords updated:
</li>
{% for coin_name in disabled_coins %}
<li class="font-medium text-sm text-red-500 error_msg ml-4">• {{ coin_name }}</li>
{% endfor %}
<li class="font-medium text-sm text-red-500 error_msg mb-2 mt-2">
<strong>What this means:</strong> When you re-enable these coins later, they will still have the old password while your other coins have the new password, causing authentication failures.
</li>
<li class="font-medium text-sm text-red-500 error_msg">
<strong>Solution:</strong> Please <a href="/settings" class="underline font-medium">enable all coins</a> before changing your password, or wait until all coins are enabled.
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</section>
{% endif %}
<section> <section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden"> <div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<div class="border-coolGray-100"> <div class="border-coolGray-100">
@@ -52,7 +94,7 @@
<div class="container mt-5 mx-auto"> <div class="container mt-5 mx-auto">
<div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl"> <div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6"> <div class="px-6">
<form method="post" autocomplete="off" id="change-password-form"> <form method="post" autocomplete="off" id="change-password-form" {% if disabled_coins|length > 0 %}class="form-disabled"{% endif %}>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div class="space-y-6"> <div class="space-y-6">
<div> <div>
@@ -66,6 +108,7 @@
name="oldpassword" name="oldpassword"
class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0"
placeholder="Enter your current password" placeholder="Enter your current password"
{% if disabled_coins|length > 0 %}disabled{% endif %}
required required
/> />
<button <button
@@ -95,6 +138,7 @@
name="newpassword" name="newpassword"
class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0"
placeholder="Enter your new password" placeholder="Enter your new password"
{% if disabled_coins|length > 0 %}disabled{% endif %}
required required
/> />
<button <button
@@ -142,6 +186,7 @@
name="confirmpassword" name="confirmpassword"
class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0"
placeholder="Confirm your new password" placeholder="Confirm your new password"
{% if disabled_coins|length > 0 %}disabled{% endif %}
required required
/> />
<button <button
@@ -179,7 +224,7 @@
<div class="space-y-6"> <div class="space-y-6">
<div class="bg-gray-50 dark:bg-gray-600 rounded-lg p-6"> <div class="bg-gray-50 dark:bg-gray-600 rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">Password Requirements</h3> <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">Password Suggestions</h3>
<div class="space-y-3"> <div class="space-y-3">
<div id="req-length" class="flex items-center text-gray-500 dark:text-gray-400"> <div id="req-length" class="flex items-center text-gray-500 dark:text-gray-400">
<svg class="w-5 h-5 mr-3" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-5 h-5 mr-3" fill="currentColor" viewBox="0 0 20 20">
@@ -215,8 +260,9 @@
type="submit" type="submit"
id="submit-btn" id="submit-btn"
class="bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-3 px-8 rounded-lg transition-colors focus:outline-none disabled:cursor-not-allowed" class="bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-medium py-3 px-8 rounded-lg transition-colors focus:outline-none disabled:cursor-not-allowed"
{% if disabled_coins|length > 0 %}disabled{% endif %}
> >
<span id="submit-text">Change Password</span> <span id="submit-text">{% if disabled_coins|length > 0 %}Disabled - Enable All Coins First{% else %}Change Password{% endif %}</span>
<svg id="submit-spinner" class="hidden animate-spin ml-2 h-5 w-5 text-white inline" fill="none" viewBox="0 0 24 24"> <svg id="submit-spinner" class="hidden animate-spin ml-2 h-5 w-5 text-white inline" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
@@ -418,6 +464,12 @@
if (form) { if (form) {
form.addEventListener('submit', function(e) { form.addEventListener('submit', function(e) {
if (form.classList.contains('form-disabled')) {
e.preventDefault();
alert('Cannot change password while coins are disabled. Please enable all coins first.');
return;
}
const newPassword = newPasswordInput.value; const newPassword = newPasswordInput.value;
const isStrongEnough = updatePasswordStrength(newPassword); const isStrongEnough = updatePasswordStrength(newPassword);
const passwordsMatch = checkPasswordMatch(); const passwordsMatch = checkPasswordMatch();
@@ -444,4 +496,27 @@
}); });
</script> </script>
<style>
.form-disabled {
opacity: 0.6;
pointer-events: none;
}
.form-disabled input[disabled] {
background-color: #f3f4f6 !important;
color: #9ca3af !important;
cursor: not-allowed !important;
}
.form-disabled button[disabled] {
background-color: #9ca3af !important;
cursor: not-allowed !important;
}
.dark .form-disabled input[disabled] {
background-color: #374151 !important;
color: #6b7280 !important;
}
.dark .form-disabled button[disabled] {
background-color: #6b7280 !important;
}
</style>
{% include 'footer.html' %} {% include 'footer.html' %}

View File

@@ -70,15 +70,15 @@
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center"> <div class="flex items-center">
<div class="flex-shrink-0"> <div class="flex-shrink-0">
<img class="h-10 w-10" src="/static/images/coins/{{ c.name }}.png" alt="{{ c.display_name }}"> <img class="h-10 w-10" src="/static/images/coins/{{ c.display_name }}.png" alt="{{ c.display_name }}">
</div> </div>
<div class="ml-4"> <div class="ml-4">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">{{ c.display_name }} ({{ c.ticker }})</h3> <h3 class="text-lg font-semibold text-gray-900 dark:text-white">{{ c.display_name }}</h3>
</div> </div>
</div> </div>
<div class="flex items-center space-x-4"> <div class="flex items-center space-x-4">
{% if c.can_disable == true %} {% if c.connection_type != "none" %}
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300"> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300">
<svg class="w-2 h-2 mr-1" fill="currentColor" viewBox="0 0 8 8"> <svg class="w-2 h-2 mr-1" fill="currentColor" viewBox="0 0 8 8">
<circle cx="4" cy="4" r="3"/> <circle cx="4" cy="4" r="3"/>

View File

@@ -6,6 +6,7 @@
from .util import ( from .util import (
get_data_entry_or, get_data_entry_or,
getCoinName,
) )
@@ -33,6 +34,22 @@ def page_changepassword(self, url_split, post_string):
except Exception as e: except Exception as e:
err_messages.append(str(e)) err_messages.append(str(e))
chains_formatted = []
sorted_names = sorted(swap_client.settings["chainclients"].keys())
for name in sorted_names:
c = swap_client.settings["chainclients"][name]
try:
display_name = getCoinName(swap_client.getCoinIdFromName(name))
except Exception:
display_name = name
chains_formatted.append(
{
"name": name,
"display_name": display_name,
"connection_type": c.get("connection_type", "Unknown"),
}
)
template = server.env.get_template("changepassword.html") template = server.env.get_template("changepassword.html")
return self.render_template( return self.render_template(
template, template,
@@ -40,6 +57,7 @@ def page_changepassword(self, url_split, post_string):
"messages": messages, "messages": messages,
"err_messages": err_messages, "err_messages": err_messages,
"summary": swap_client.getSummary(), "summary": swap_client.getSummary(),
"chains_formatted": chains_formatted,
}, },
) )