Major Feature Update: Modern Chat System & Admin Management

Features Added:
🔥 Modern Chat System:
- Real-time messaging with modern Tailwind CSS design
- Post-linked discussions for adventure sharing
- Chat categories (general, technical-support, adventure-planning)
- Mobile-responsive interface with gradient backgrounds
- JavaScript polling for live message updates

🎯 Comprehensive Admin Panel:
- Chat room management with merge capabilities
- Password reset system with email templates
- User management with admin controls
- Chat statistics and analytics dashboard
- Room binding to posts and categorization

�� Mobile API Integration:
- RESTful API endpoints at /api/v1/chat
- Session-based authentication for mobile apps
- Comprehensive endpoints for rooms, messages, users
- Mobile app compatibility (React Native, Flutter)

🛠️ Technical Improvements:
- Enhanced database models with ChatRoom categories
- Password reset token system with email verification
- Template synchronization fixes for Docker deployment
- Migration scripts for database schema updates
- Improved error handling and validation

🎨 UI/UX Enhancements:
- Modern card-based layouts matching app design
- Consistent styling across chat and admin interfaces
- Mobile-optimized touch interactions
- Professional gradient designs and glass morphism effects

📚 Documentation:
- Updated README with comprehensive API documentation
- Added deployment instructions for Docker (port 8100)
- Configuration guide for production environments
- Mobile integration examples and endpoints

This update transforms the platform into a comprehensive motorcycle adventure community with modern chat capabilities and professional admin management tools.
This commit is contained in:
ske087
2025-08-10 00:22:33 +03:00
parent 1661f5f588
commit 30bd4c62ad
20 changed files with 3649 additions and 349 deletions

View File

@@ -1,7 +1,7 @@
from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required, current_user
from werkzeug.security import check_password_hash
from app.models import User, db
from app.models import User, db, PasswordResetToken
from app.routes.reset_password import RequestResetForm, ResetPasswordForm
from flask_mail import Message
from app.routes.mail import mail
@@ -161,26 +161,6 @@ def forgot_password():
flash('Your password reset request has been sent to administrators. They will contact you soon to help reset your password.', 'info')
return redirect(url_for('auth.login'))
return render_template('auth/forgot_password.html', form=form)
# Password reset route
@auth.route('/reset-password/<token>', methods=['GET', 'POST'])
def reset_password(token):
if current_user.is_authenticated:
return redirect(url_for('main.index'))
email = verify_reset_token(token)
if not email:
flash('Invalid or expired reset link.', 'danger')
return redirect(url_for('auth.forgot_password'))
user = User.query.filter_by(email=email).first()
if not user:
flash('Invalid or expired reset link.', 'danger')
return redirect(url_for('auth.forgot_password'))
form = ResetPasswordForm()
if form.validate_on_submit():
user.set_password(form.password.data)
db.session.commit()
flash('Your password has been reset. You can now log in.', 'success')
return redirect(url_for('auth.login'))
return render_template('auth/reset_password.html', form=form)
@auth.route('/change-password', methods=['POST'])
@login_required
@@ -235,3 +215,59 @@ def is_valid_password(password):
if not re.search(r'\d', password):
return False
return True
class ResetPasswordWithTokenForm(FlaskForm):
password = PasswordField('New Password', validators=[DataRequired(), Length(min=8)])
password2 = PasswordField('Confirm New Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Reset Password')
@auth.route('/reset-password/<token>', methods=['GET', 'POST'])
def reset_password_with_token(token):
"""Reset password using admin-generated token"""
# Find the token in database
reset_token = PasswordResetToken.query.filter_by(token=token).first()
if not reset_token:
flash('Invalid or expired reset link.', 'error')
return redirect(url_for('auth.login'))
# Check if token is expired
if reset_token.is_expired:
flash('This reset link has expired. Please request a new one.', 'error')
return redirect(url_for('auth.login'))
# Check if token is already used
if reset_token.is_used:
flash('This reset link has already been used.', 'error')
return redirect(url_for('auth.login'))
form = ResetPasswordWithTokenForm()
if form.validate_on_submit():
user = reset_token.user
# Validate password strength
if not is_valid_password(form.password.data):
flash('Password must be at least 8 characters long and contain both letters and numbers.', 'error')
return render_template('auth/reset_password_with_token.html', form=form, token=token)
# Update password
user.set_password(form.password.data)
# Mark token as used
reset_token.used_at = datetime.utcnow()
reset_token.user_ip = request.environ.get('REMOTE_ADDR')
# Update request status
if reset_token.request:
reset_token.request.status = 'completed'
reset_token.request.updated_at = datetime.utcnow()
db.session.commit()
flash('Your password has been reset successfully! You can now log in with your new password.', 'success')
return redirect(url_for('auth.login'))
return render_template('auth/reset_password_with_token.html', form=form, token=token, user=reset_token.user)