From 7018ae13f03c3769f3d8e1a3134e2085bed60aaa Mon Sep 17 00:00:00 2001 From: ske087 Date: Thu, 24 Jul 2025 03:07:52 +0300 Subject: [PATCH] feat: Add comprehensive admin user management system - Add user status toggle (activate/deactivate) functionality - Add user deletion with post/comment transfer to admin - Implement safety checks for admin protection - Add interactive JavaScript for user management actions - Update admin users interface with action buttons - Add confirmation dialogs for destructive operations - Update README with new admin features and capabilities - Add database migration utility for future updates Features: - Toggle user active/inactive status - Delete users with content preservation - Transfer all posts/comments to admin on user deletion - Prevent admin self-modification and deletion - AJAX-powered interface with real-time feedback - Comprehensive error handling and user notifications --- README.md | 322 ++++++++++++++++++++++++--------- app/routes/admin.py | 74 ++++++++ app/templates/admin/users.html | 97 +++++++++- migrate_database.py | 0 4 files changed, 409 insertions(+), 84 deletions(-) create mode 100644 migrate_database.py diff --git a/README.md b/README.md index ddf2914..493a8b7 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,118 @@ -# Motorcycle Adventure Community +# Motorcycle Adventure Community 🏍️ -A Flask-based web application for motorcycle enthusiasts featuring adventure stories, route sharing, and accommodation recommendations. +A modern Flask-based web application for motorcycle enthusiasts featuring adventure stories, interactive GPS route sharing, and community engagement. -## Features +## ✨ Features -- **Landing Page**: Hero section with call-to-action, featured adventures, and accommodation promotion -- **User Authentication**: Registration and login system with Flask-Login -- **Community Section**: Share stories, tracks, and experiences -- **Admin Panel**: Content management for administrators -- **Responsive Design**: Built with Tailwind CSS for mobile-first design -- **Error Handling**: Custom 404 and 500 error pages +### 🎨 Modern UI/UX Design +- **Tailwind CSS Integration**: Complete redesign with modern gradient backgrounds and glass morphism effects +- **Responsive Design**: Mobile-first approach with optimized layouts for all screen sizes +- **Interactive Components**: Smooth animations, hover effects, and modern card-based layouts +- **Consistent Design Language**: Unified color scheme and component patterns throughout the app -## Technology Stack +### πŸ—ΊοΈ Advanced GPS & Route Features +- **Interactive Maps**: Leaflet.js integration with OpenStreetMap tiles +- **GPX File Support**: Upload, download, and visualize GPS tracks +- **Route Statistics**: Distance, elevation gain, max elevation, and track points +- **Start/End Markers**: Visual indicators with custom icons for route endpoints +- **Map Fitting**: Automatic zoom and centering to display complete routes -- **Backend**: Python Flask 3.0.0 -- **Database**: SQLAlchemy with PostgreSQL support -- **Authentication**: Flask-Login -- **Email**: Flask-Mail -- **Forms**: WTForms with validation -- **Styling**: Tailwind CSS (CDN) -- **Deployment**: Docker with Gunicorn +### πŸ“Έ Enhanced Media Management +- **Photo Gallery**: Grid-based layout with modal view and zoom functionality +- **Image Thumbnails**: Automatic thumbnail generation for optimized loading +- **Cover Image System**: Designated cover photos for adventure posts +- **Image Descriptions**: Support for photo captions and descriptions +- **Hover Effects**: Interactive image previews with smooth transitions -## Project Structure +### πŸ‘₯ Community & Social Features +- **Adventure Posts**: Rich content creation with titles, subtitles, and detailed stories +- **Comment System**: Community discussions on adventure posts +- **Like System**: Engagement tracking with real-time updates +- **User Profiles**: Personal dashboards with adventure statistics +- **Difficulty Ratings**: 5-star system for adventure difficulty assessment +- **Publication Workflow**: Admin approval system for content moderation + +### πŸ” User Management & Authentication +- **Secure Authentication**: Flask-Login with session management +- **User Profiles**: Personal information and adventure history +- **Role-Based Access**: User and admin permissions +- **Adventure Statistics**: Published vs pending post counts +- **Registration System**: Email-based user registration + +### πŸ› οΈ Admin Panel & Analytics +- **Comprehensive Dashboard**: User and post management interface +- **Content Moderation**: Review and approve community posts +- **User Analytics**: User engagement and activity metrics +- **Post Management**: Bulk operations and detailed post information +- **System Configuration**: Admin-only settings and controls + +### πŸ“± Mobile-Optimized Experience +- **Touch-Friendly Interface**: Optimized buttons and interactions for mobile devices +- **Responsive Grids**: Adaptive layouts that work perfectly on phones and tablets +- **Progressive Enhancement**: Graceful degradation for older browsers +- **Fast Loading**: Optimized images and efficient CSS delivery + +## πŸš€ Technology Stack + +- **Backend**: Python Flask 3.0.0 with Blueprint architecture +- **Database**: SQLAlchemy with PostgreSQL/SQLite support +- **Authentication**: Flask-Login with secure session management +- **Email**: Flask-Mail for notifications and verification +- **Forms**: WTForms with comprehensive validation +- **Frontend**: Tailwind CSS 3.x with custom components +- **Maps**: Leaflet.js with OpenStreetMap integration +- **File Handling**: Secure media uploads with thumbnail generation +- **Deployment**: Docker with Gunicorn WSGI server + +## πŸ“ Project Structure ``` / β”œβ”€β”€ app/ -β”‚ β”œβ”€β”€ __init__.py # Flask app factory -β”‚ β”œβ”€β”€ models.py # Database models -β”‚ β”œβ”€β”€ forms.py # WTForm definitions -β”‚ β”œβ”€β”€ routes/ # Route blueprints -β”‚ β”‚ β”œβ”€β”€ main.py # Main routes (index, about) -β”‚ β”‚ β”œβ”€β”€ auth.py # Authentication routes -β”‚ β”‚ └── community.py # Community features -β”‚ β”œβ”€β”€ templates/ # Jinja2 templates -β”‚ β”‚ β”œβ”€β”€ base.html # Base template -β”‚ β”‚ β”œβ”€β”€ index.html # Landing page -β”‚ β”‚ β”œβ”€β”€ auth/ # Auth templates -β”‚ β”‚ └── errors/ # Error pages -β”‚ └── static/ # Static assets +β”‚ β”œβ”€β”€ __init__.py # Flask app factory with extensions +β”‚ β”œβ”€β”€ models.py # Database models (User, Post, Image, GPX, Comment, Like) +β”‚ β”œβ”€β”€ forms.py # WTForm definitions for all features +β”‚ β”œβ”€β”€ extensions.py # Flask extensions configuration +β”‚ β”œβ”€β”€ media_config.py # Media handling and upload configuration +β”‚ β”œβ”€β”€ routes/ # Route blueprints +β”‚ β”‚ β”œβ”€β”€ main.py # Landing page and general routes +β”‚ β”‚ β”œβ”€β”€ auth.py # Authentication and user management +β”‚ β”‚ β”œβ”€β”€ community.py # Community features and post management +β”‚ β”‚ └── admin.py # Admin panel and analytics +β”‚ β”œβ”€β”€ templates/ # Jinja2 templates +β”‚ β”‚ β”œβ”€β”€ base.html # Base template with navigation +β”‚ β”‚ β”œβ”€β”€ index.html # Landing page with hero section +β”‚ β”‚ β”œβ”€β”€ auth/ # Authentication templates +β”‚ β”‚ β”œβ”€β”€ community/ # Community feature templates +β”‚ β”‚ β”‚ β”œβ”€β”€ index.html # Community homepage +β”‚ β”‚ β”‚ β”œβ”€β”€ new_post.html # Adventure creation form +β”‚ β”‚ β”‚ β”œβ”€β”€ edit_post.html # Adventure editing interface +β”‚ β”‚ β”‚ β”œβ”€β”€ post_detail.html # Detailed adventure view with maps +β”‚ β”‚ β”‚ └── profile.html # User profile dashboard +β”‚ β”‚ β”œβ”€β”€ admin/ # Admin panel templates +β”‚ β”‚ β”‚ β”œβ”€β”€ dashboard.html # Analytics dashboard +β”‚ β”‚ β”‚ β”œβ”€β”€ posts.html # Post management +β”‚ β”‚ β”‚ └── users.html # User management +β”‚ β”‚ └── errors/ # Error pages (404, 500) +β”‚ └── static/ # Static assets and media β”‚ β”œβ”€β”€ favicon.ico -β”‚ └── images/ -β”œβ”€β”€ config.py # Application configuration -β”œβ”€β”€ requirements.txt # Python dependencies -β”œβ”€β”€ run.py # Application entry point -β”œβ”€β”€ Dockerfile # Docker configuration -└── docker-compose.yml # Docker Compose setup +β”‚ β”œβ”€β”€ images/ # App images and logos +β”‚ └── media/ # User-uploaded content +β”‚ └── posts/ # Post media organized by ID +β”œβ”€β”€ instance/ # Instance-specific files +β”‚ β”œβ”€β”€ uploads/ # Legacy upload directory +β”‚ └── *.db # SQLite database files +β”œβ”€β”€ migrations/ # Database migration scripts +β”œβ”€β”€ config.py # Multi-environment configuration +β”œβ”€β”€ requirements.txt # Python dependencies +β”œβ”€β”€ run.py # Application entry point +β”œβ”€β”€ manage_media.py # Media management utilities +β”œβ”€β”€ test_media.py # Media system tests +β”œβ”€β”€ Dockerfile # Docker configuration +└── docker-compose.yml # Docker Compose setup ``` -## Quick Start +## πŸš€ Quick Start ### Local Development @@ -74,7 +138,7 @@ A Flask-based web application for motorcycle enthusiasts featuring adventure sto export FLASK_APP=run.py export FLASK_ENV=development export SECRET_KEY="your-secret-key-here" - export DATABASE_URL="sqlite:///motorcycle_adventures.db" + export DATABASE_URL="sqlite:///instance/moto_adventure_dev.db" ``` 5. **Initialize database** @@ -84,12 +148,23 @@ A Flask-based web application for motorcycle enthusiasts featuring adventure sto flask db upgrade ``` -6. **Run the application** +6. **Create media directories** + ```bash + mkdir -p app/static/media/posts + mkdir -p instance/uploads + ``` + +7. **Run the application** ```bash python run.py ``` -### Docker Deployment +8. **Access the application** + - Open http://localhost:5000 in your browser + - Register a new account to start sharing adventures + - Upload GPX files and photos to test the full functionality + +### 🐳 Docker Deployment 1. **Build and run with Docker Compose** ```bash @@ -100,60 +175,143 @@ A Flask-based web application for motorcycle enthusiasts featuring adventure sto - Web application: http://localhost:5000 - PostgreSQL database: localhost:5432 -## Configuration +### πŸ“± Testing Features + +1. **Create an Adventure Post** + - Register and login to your account + - Click "Share New Adventure" + - Upload photos and GPX files + - Add title, subtitle, and adventure story + +2. **Explore Interactive Maps** + - View adventure posts with GPS tracks + - See route statistics and elevation data + - Download GPX files for your own use + +3. **Admin Panel Access** + - Create admin user in database + - Access /admin for content management + - Review and approve community posts + - PostgreSQL database: localhost:5432 + +## βš™οΈ Configuration The application supports multiple environments through environment variables: +### Core Settings - `FLASK_ENV`: development, testing, production -- `SECRET_KEY`: Flask secret key for sessions -- `DATABASE_URL`: Database connection string -- `MAIL_SERVER`: SMTP server for email -- `MAIL_USERNAME`: Email username -- `MAIL_PASSWORD`: Email password +- `SECRET_KEY`: Flask secret key for sessions and CSRF protection +- `DATABASE_URL`: Database connection string (SQLite/PostgreSQL) -## Features Overview +### Media & Upload Settings +- `UPLOAD_FOLDER`: Directory for user uploads (default: instance/uploads) +- `MEDIA_FOLDER`: Directory for processed media (default: app/static/media) +- `MAX_CONTENT_LENGTH`: Maximum file upload size (default: 16MB) -### Landing Page -- Hero section with stunning mountain panorama background -- Call-to-action for adventure community -- Featured adventures showcase -- Pensiune BuonGusto accommodation promotion +### Email Configuration +- `MAIL_SERVER`: SMTP server for email notifications +- `MAIL_USERNAME`: Email username for authentication +- `MAIL_PASSWORD`: Email password or app-specific password +- `MAIL_USE_TLS`: Enable TLS encryption (default: True) -### Authentication System -- User registration with email validation -- Secure login/logout functionality -- Password hashing with Werkzeug -- Session management with Flask-Login +### Development Settings +- `FLASK_DEBUG`: Enable debug mode (development only) +- `WTF_CSRF_ENABLED`: Enable CSRF protection (default: True) -### Community Features -- Story and track sharing -- User profiles -- Image uploads for adventures -- GPX file support for route sharing -- Comment system -- Like/rating system +## 🌟 Features Overview -### Admin Panel -- User management -- Content moderation -- Analytics dashboard -- System configuration +### 🏠 Enhanced Landing Page +- **Hero Section**: Stunning Transalpina panorama background with glass morphism overlay +- **Featured Adventures**: Carousel showcasing community highlights +- **Statistics Dashboard**: Live counters for users, adventures, and community engagement +- **Call-to-Action**: Prominent registration and exploration prompts +- **Pensiune BuonGusto**: Integrated accommodation promotion -## Contributing +### πŸ” Advanced Authentication System +- **Secure Registration**: Email validation with password strength requirements +- **Session Management**: Persistent login with "Remember Me" functionality +- **Password Security**: Bcrypt hashing with salt for maximum security +- **User Profiles**: Comprehensive profile management with statistics +- **Role-Based Access**: Granular permissions for users and administrators -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Commit your changes (`git commit -m 'Add some amazing feature'`) -4. Push to the branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request +### πŸ—ΊοΈ Interactive Community Features +- **Rich Post Creation**: Multi-step form with media upload and GPS integration +- **Adventure Gallery**: Beautiful grid layout with filtering and search +- **Real-time Engagement**: Like system with instant feedback +- **Threaded Comments**: Nested discussion system for each adventure +- **Social Sharing**: Easy sharing of favorite adventures +- **Content Moderation**: Admin approval workflow for quality control -## License +### πŸ“Š Comprehensive Admin Panel +- **Analytics Dashboard**: User growth, post statistics, and engagement metrics +- **User Management**: Detailed user profiles with activity tracking +- **Content Review**: Streamlined post approval and moderation tools +- **System Health**: Monitoring and configuration management +- **Bulk Operations**: Efficient management of multiple users or posts + +### 🎨 Modern Design System +- **Tailwind CSS**: Utility-first CSS framework with custom components +- **Glass Morphism**: Modern translucent effects and backdrop blur +- **Gradient Backgrounds**: Beautiful color transitions throughout the app +- **Micro-interactions**: Smooth animations and hover effects +- **Accessibility**: WCAG compliant design with keyboard navigation support + +## 🀝 Contributing + +We welcome contributions from the motorcycle community! Here's how you can help: + +1. **Fork the repository** +2. **Create a feature branch** (`git checkout -b feature/amazing-feature`) +3. **Commit your changes** (`git commit -m 'Add some amazing feature'`) +4. **Push to the branch** (`git push origin feature/amazing-feature`) +5. **Open a Pull Request** + +### Development Guidelines +- Follow PEP 8 style guidelines for Python code +- Use semantic commit messages +- Add tests for new features +- Update documentation for any changes +- Ensure mobile responsiveness for UI changes + +### Reporting Issues +- Use the GitHub issue tracker +- Include steps to reproduce the problem +- Provide browser and device information +- Include screenshots for UI issues + +## πŸ“„ License This project is licensed under the MIT License - see the LICENSE file for details. -## Acknowledgments +## πŸ™ Acknowledgments -- Beautiful Transalpina panorama background image -- Tailwind CSS for responsive design -- Flask community for excellent documentation -- Bootstrap icons for UI elements +- **Beautiful Transalpina Panorama**: Stunning background image showcasing Romania's scenic highway +- **Tailwind CSS**: For providing an excellent utility-first CSS framework +- **Leaflet.js**: For powerful and flexible mapping capabilities +- **Flask Community**: For comprehensive documentation and support +- **OpenStreetMap**: For providing free and open map data +- **Font Awesome**: For beautiful and consistent iconography +- **Motorcycle Community**: For inspiration and feedback during development + +## 🚧 Roadmap + +### Upcoming Features +- [ ] **Real-time Chat**: Live messaging between community members +- [ ] **Event System**: Motorcycle meetups and group ride organization +- [ ] **Weather Integration**: Route weather conditions and forecasts +- [ ] **Mobile App**: Native iOS and Android applications +- [ ] **Advanced Search**: Filter adventures by location, difficulty, and tags +- [ ] **Social Features**: Follow users and curated adventure feeds +- [ ] **Offline Support**: PWA capabilities for offline map viewing + +### Performance Improvements +- [ ] **Image Optimization**: WebP conversion and lazy loading +- [ ] **Caching**: Redis integration for improved performance +- [ ] **CDN Integration**: Asset delivery optimization +- [ ] **Database Optimization**: Query optimization and indexing + +--- + +**Built with ❀️ for the motorcycle adventure community** + +For support or questions, please open an issue or contact the development team. diff --git a/app/routes/admin.py b/app/routes/admin.py index 0d39b58..faac197 100644 --- a/app/routes/admin.py +++ b/app/routes/admin.py @@ -190,6 +190,80 @@ def user_detail(user_id): user_posts=user_posts, user_comments=user_comments) +@admin.route('/users//toggle-status', methods=['POST']) +@login_required +@admin_required +def toggle_user_status(user_id): + """Toggle user active/inactive status""" + user = User.query.get_or_404(user_id) + + # Prevent self-modification if current user is admin + if user.is_admin and user.id == current_user.id: + return jsonify({'success': False, 'error': 'Cannot deactivate your own admin account'}) + + # Toggle status + user.is_active = not user.is_active + status = "activated" if user.is_active else "deactivated" + + try: + db.session.commit() + return jsonify({ + 'success': True, + 'message': f'User {user.nickname} has been {status}', + 'is_active': user.is_active + }) + except Exception as e: + db.session.rollback() + return jsonify({'success': False, 'error': f'Failed to update user status: {str(e)}'}) + +@admin.route('/users//delete', methods=['DELETE', 'POST']) +@login_required +@admin_required +def delete_user(user_id): + """Delete user and transfer their posts to admin""" + user = User.query.get_or_404(user_id) + + # Prevent self-deletion + if user.id == current_user.id: + return jsonify({'success': False, 'error': 'Cannot delete your own account'}) + + # Prevent deletion of other admins + if user.is_admin: + return jsonify({'success': False, 'error': 'Cannot delete admin accounts'}) + + try: + # Transfer all user's posts to current admin + user_posts = Post.query.filter_by(author_id=user.id).all() + for post in user_posts: + post.author_id = current_user.id + + # Transfer all user's comments to current admin + user_comments = Comment.query.filter_by(author_id=user.id).all() + for comment in user_comments: + comment.author_id = current_user.id + + # Delete user's likes (they will be orphaned) + Like.query.filter_by(user_id=user.id).delete() + + # Delete user's page views + PageView.query.filter_by(user_id=user.id).delete() + + username = user.nickname + user_posts_count = len(user_posts) + + # Delete the user + db.session.delete(user) + db.session.commit() + + return jsonify({ + 'success': True, + 'message': f'User {username} has been deleted. {user_posts_count} posts transferred to {current_user.nickname}.' + }) + + except Exception as e: + db.session.rollback() + return jsonify({'success': False, 'error': f'Failed to delete user: {str(e)}'}) + @admin.route('/analytics') @login_required @admin_required diff --git a/app/templates/admin/users.html b/app/templates/admin/users.html index 8fc8e2f..2bb01fd 100644 --- a/app/templates/admin/users.html +++ b/app/templates/admin/users.html @@ -74,8 +74,17 @@ {% if not user.is_admin or current_user.id != user.id %} - + {% endif %} + {% if not user.is_admin and current_user.id != user.id %} + {% endif %} @@ -134,4 +143,88 @@ {% endif %} + + + {% endblock %} diff --git a/migrate_database.py b/migrate_database.py new file mode 100644 index 0000000..e69de29