Finalize mail settings admin UI and Mailrise compatibility
This commit is contained in:
@@ -1,13 +1,88 @@
|
||||
|
||||
|
||||
from flask import Blueprint, render_template, request, flash, redirect, url_for, jsonify, current_app
|
||||
from flask_mail import Message
|
||||
from flask_login import login_required, current_user
|
||||
from functools import wraps
|
||||
from datetime import datetime, timedelta
|
||||
from sqlalchemy import func, desc
|
||||
import secrets
|
||||
from app.routes.mail import mail
|
||||
from app.extensions import db
|
||||
from app.models import User, Post, PostImage, GPXFile, Comment, Like, PageView
|
||||
from app.models import User, Post, PostImage, GPXFile, Comment, Like, PageView, MailSettings, SentEmail
|
||||
|
||||
admin = Blueprint('admin', __name__, url_prefix='/admin')
|
||||
|
||||
def admin_required(f):
|
||||
"""Decorator to require admin access"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not current_user.is_authenticated or not current_user.is_admin:
|
||||
flash('Admin access required.', 'error')
|
||||
return redirect(url_for('auth.login'))
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
@admin.route('/mail-settings', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def mail_settings():
|
||||
settings = MailSettings.query.first()
|
||||
if request.method == 'POST':
|
||||
enabled = bool(request.form.get('enabled'))
|
||||
provider = request.form.get('provider')
|
||||
server = request.form.get('server')
|
||||
port = int(request.form.get('port') or 0)
|
||||
use_tls = bool(request.form.get('use_tls'))
|
||||
username = request.form.get('username')
|
||||
password = request.form.get('password')
|
||||
default_sender = request.form.get('default_sender')
|
||||
if not settings:
|
||||
settings = MailSettings()
|
||||
db.session.add(settings)
|
||||
settings.enabled = enabled
|
||||
settings.provider = provider
|
||||
settings.server = server
|
||||
settings.port = port
|
||||
settings.use_tls = use_tls
|
||||
settings.username = username
|
||||
settings.password = password
|
||||
settings.default_sender = default_sender
|
||||
db.session.commit()
|
||||
flash('Mail settings updated.', 'success')
|
||||
sent_emails = SentEmail.query.order_by(SentEmail.sent_at.desc()).limit(50).all()
|
||||
return render_template('admin/mail_settings.html', settings=settings, sent_emails=sent_emails)
|
||||
|
||||
|
||||
## Duplicate imports and Blueprint definitions removed
|
||||
|
||||
# Password reset token generator (simple, for demonstration)
|
||||
def generate_reset_token(user):
|
||||
# In production, use itsdangerous or Flask-Security for secure tokens
|
||||
return secrets.token_urlsafe(32)
|
||||
|
||||
# Admin: Send password reset email to user
|
||||
@admin.route('/users/<int:user_id>/reset-password', methods=['POST'])
|
||||
@login_required
|
||||
@admin_required
|
||||
def reset_user_password(user_id):
|
||||
user = User.query.get_or_404(user_id)
|
||||
token = generate_reset_token(user)
|
||||
# In production, save token to DB or cache, and validate on reset
|
||||
reset_url = url_for('auth.reset_password', token=token, _external=True)
|
||||
msg = Message(
|
||||
subject="Password Reset Request",
|
||||
recipients=[user.email],
|
||||
body=f"Hello {user.nickname},\n\nAn admin has requested a password reset for your account. Click the link below to reset your password:\n{reset_url}\n\nIf you did not request this, please ignore this email."
|
||||
)
|
||||
try:
|
||||
mail.send(msg)
|
||||
flash(f"Password reset email sent to {user.email}.", "success")
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Error sending reset email: {e}")
|
||||
flash(f"Failed to send password reset email: {e}", "danger")
|
||||
return redirect(url_for('admin.user_detail', user_id=user.id))
|
||||
|
||||
def admin_required(f):
|
||||
"""Decorator to require admin access"""
|
||||
@wraps(f)
|
||||
@@ -98,7 +173,7 @@ def dashboard():
|
||||
def posts():
|
||||
"""Admin post management - review posts"""
|
||||
page = request.args.get('page', 1, type=int)
|
||||
status = request.args.get('status', 'pending') # pending, published, all
|
||||
status = request.args.get('status', 'all') # pending, published, all
|
||||
|
||||
query = Post.query
|
||||
|
||||
|
||||
Reference in New Issue
Block a user