Implement comprehensive account management system

- Create dedicated Account page (/account) for users and admins
- Add password change functionality with current password verification
- Implement token top-up system with predefined packages and custom amounts
- Add payment method selection (Credit Card, PayPal, Crypto) with UI
- Create account balance display with prominent token counter
- Add navigation links to Account page across all templates
- Implement backend routes for password changes and token purchases
- Add update_user_password function to database operations
- Include demo token purchase functionality (no real payments)
- Maintain consistent navigation experience across the application
- Ensure proper access control for account management features
parent 82e0f6a0
This diff is collapsed.
......@@ -57,6 +57,7 @@
<a href="/train">Train</a>
<a href="/history">History</a>
<a href="/api_tokens">API Tokens</a>
<a href="/account">Account</a>
<a href="/admin" class="active">Admin</a>
</nav>
<div class="user-menu">
......
......@@ -179,6 +179,7 @@
<a href="/train">Train</a>
<a href="/history">History</a>
<a href="/api_tokens">API Tokens</a>
<a href="/account">Account</a>
{% if user.get('role') == 'admin' %}
<a href="/admin">Admin</a>
{% endif %}
......
......@@ -43,6 +43,7 @@
<a href="/train">Train</a>
<a href="/history">History</a>
<a href="/api_tokens">API Tokens</a>
<a href="/account">Account</a>
<a href="/settings">Settings</a>
{% if user.get('role') == 'admin' %}
<a href="/admin">Admin</a>
......
......@@ -42,6 +42,7 @@
<a href="/train">Train</a>
<a href="/history" class="active">History</a>
<a href="/api_tokens">API Tokens</a>
<a href="/account">Account</a>
<a href="/settings">Settings</a>
{% if user.get('role') == 'admin' %}
<a href="/admin">Admin</a>
......
......@@ -40,6 +40,7 @@
<a href="/train">Train</a>
<a href="/history">History</a>
<a href="/api_tokens">API Tokens</a>
<a href="/account">Account</a>
<a href="/settings" class="active">Settings</a>
{% if user.get('role') == 'admin' %}
<a href="/admin">Admin</a>
......
......@@ -41,6 +41,7 @@
<a href="/train" class="active">Train</a>
<a href="/history">History</a>
<a href="/api_tokens">API Tokens</a>
<a href="/account">Account</a>
<a href="/settings">Settings</a>
{% if user.get('role') == 'admin' %}
<a href="/admin">Admin</a>
......
......@@ -971,6 +971,17 @@ def update_user_tokens_admin(user_id: int, tokens: int) -> bool:
return success
def update_user_password(user_id: int, password_hash: str) -> bool:
"""Update user password."""
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('UPDATE users SET password_hash = ? WHERE id = ?', (password_hash, user_id))
conn.commit()
success = cursor.rowcount > 0
conn.close()
return success
def create_user(username: str, password: str, email: str, role: str = 'user', tokens: int = 0) -> tuple[bool, str]:
"""Create a new user (admin function)."""
conn = get_db_connection()
......
......@@ -400,6 +400,96 @@ def delete_api_token(token_id):
return redirect(url_for('api_tokens'))
@app.route('/account')
@login_required
def account():
"""User account management page."""
user = get_current_user_session()
return render_template('account.html', user=user)
@app.route('/account/change_password', methods=['POST'])
@login_required
def change_password():
"""Change user password."""
user = get_current_user_session()
current_password = request.form.get('current_password')
new_password = request.form.get('new_password')
confirm_password = request.form.get('confirm_password')
if not current_password or not new_password or not confirm_password:
flash('All password fields are required.', 'error')
return redirect(url_for('account'))
if new_password != confirm_password:
flash('New passwords do not match.', 'error')
return redirect(url_for('account'))
if len(new_password) < 6:
flash('New password must be at least 6 characters long.', 'error')
return redirect(url_for('account'))
# Verify current password
from .database import authenticate_user
auth_user = authenticate_user(user['username'], current_password)
if not auth_user:
flash('Current password is incorrect.', 'error')
return redirect(url_for('account'))
# Update password
import hashlib
password_hash = hashlib.sha256(new_password.encode()).hexdigest()
from .database import update_user_password
if update_user_password(user['id'], password_hash):
flash('Password changed successfully!', 'success')
else:
flash('Failed to change password.', 'error')
return redirect(url_for('account'))
@app.route('/account/purchase_tokens', methods=['POST'])
@login_required
def purchase_tokens():
"""Purchase tokens for user account."""
user = get_current_user_session()
package = request.form.get('package')
payment_method = request.form.get('payment_method')
custom_tokens = request.form.get('custom_tokens')
if not package or not payment_method:
flash('Please select a package and payment method.', 'error')
return redirect(url_for('account'))
# Calculate tokens and cost
if package == 'starter':
tokens = 500
cost = 4.99
elif package == 'professional':
tokens = 1200
cost = 9.99
elif package == 'enterprise':
tokens = 3000
cost = 19.99
elif package == 'custom':
tokens = int(custom_tokens) if custom_tokens else 100
cost = (tokens / 100) * 0.10 # $0.10 per token
else:
flash('Invalid package selected.', 'error')
return redirect(url_for('account'))
# In a real implementation, this would process payment
# For demo purposes, we'll just add the tokens
from .database import update_user_tokens
if update_user_tokens(user['id'], tokens):
flash(f'Successfully purchased {tokens} tokens! (Demo - no actual payment processed)', 'success')
else:
flash('Failed to process token purchase.', 'error')
return redirect(url_for('account'))
@app.route('/update_database_settings', methods=['POST'])
@admin_required
def update_database_settings():
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment