From 53aea5613642d823bb39de7e5c9e376370cdf30e Mon Sep 17 00:00:00 2001 From: Master3395 Date: Sat, 20 Sep 2025 21:50:22 +0200 Subject: [PATCH] Add home directory management features: Introduce models and views for managing user home directories, including dynamic home directory assignment during user creation. Update frontend to allow selection of home directories and display relevant information. Enhance backend logic for home directory migration and statistics retrieval, improving overall user management capabilities. --- guides/HOME_DIRECTORY_MANAGEMENT_GUIDE.md | 533 ++++++++++++++ guides/INDEX.md | 8 +- plogical/vhost.py | 12 +- userManagment/homeDirectoryManager.py | 230 ++++++ userManagment/homeDirectoryUtils.py | 148 ++++ userManagment/homeDirectoryViews.py | 254 +++++++ userManagment/management/__init__.py | 1 + userManagment/management/commands/__init__.py | 1 + .../commands/init_home_directories.py | 49 ++ .../migrations/0001_home_directories.py | 48 ++ userManagment/models.py | 87 ++- .../templates/userManagment/createUser.html | 110 +++ .../homeDirectoryManagement.html | 688 ++++++++++++++++++ .../userManagment/userMigration.html | 259 +++++++ userManagment/urls.py | 11 + userManagment/views.py | 53 ++ .../websiteFunctions/websiteFunctions.js | 38 +- .../websiteFunctions/modifyWebsite.html | 25 + websiteFunctions/website.py | 48 +- 19 files changed, 2593 insertions(+), 10 deletions(-) create mode 100644 guides/HOME_DIRECTORY_MANAGEMENT_GUIDE.md create mode 100644 userManagment/homeDirectoryManager.py create mode 100644 userManagment/homeDirectoryUtils.py create mode 100644 userManagment/homeDirectoryViews.py create mode 100644 userManagment/management/__init__.py create mode 100644 userManagment/management/commands/__init__.py create mode 100644 userManagment/management/commands/init_home_directories.py create mode 100644 userManagment/migrations/0001_home_directories.py create mode 100644 userManagment/templates/userManagment/homeDirectoryManagement.html create mode 100644 userManagment/templates/userManagment/userMigration.html diff --git a/guides/HOME_DIRECTORY_MANAGEMENT_GUIDE.md b/guides/HOME_DIRECTORY_MANAGEMENT_GUIDE.md new file mode 100644 index 000000000..4d99e70da --- /dev/null +++ b/guides/HOME_DIRECTORY_MANAGEMENT_GUIDE.md @@ -0,0 +1,533 @@ +# Home Directory Management Guide for CyberPanel + +## Overview + +The Home Directory Management feature allows CyberPanel administrators to manage multiple home directories across different storage volumes (e.g., `/home`, `/home2`, `/home3`). This enables storage balancing, helps avoid upgrading main volume plans by utilizing cheaper additional volumes, and provides better resource distribution across your server. + +## Table of Contents + +1. [Features](#features) +2. [Getting Started](#getting-started) +3. [Managing Home Directories](#managing-home-directories) +4. [User Management](#user-management) +5. [Website Management Integration](#website-management-integration) +6. [Storage Balancing](#storage-balancing) +7. [User Migration](#user-migration) +8. [Troubleshooting](#troubleshooting) +9. [Best Practices](#best-practices) +10. [Advanced Configuration](#advanced-configuration) + +## Features + +### Core Capabilities +- **Multiple Home Directories**: Manage `/home`, `/home2`, `/home3`, etc. +- **Automatic Detection**: Auto-discover existing home directories +- **Storage Monitoring**: Real-time space usage and availability tracking +- **User Distribution**: Balance users across different storage volumes +- **Website Integration**: Manage home directories directly from website modification +- **User Migration**: Move users between home directories seamlessly +- **Storage Analytics**: Detailed usage statistics and recommendations + +### Benefits +- **Cost Optimization**: Use cheaper additional volumes instead of upgrading main storage +- **Performance**: Distribute load across multiple storage devices +- **Scalability**: Easy expansion as your server grows +- **Flexibility**: Choose optimal storage for different user types +- **Monitoring**: Real-time visibility into storage usage + +## Getting Started + +### Prerequisites +- CyberPanel v2.5.5 or higher +- Administrator access +- Multiple storage volumes available (optional but recommended) +- Sufficient disk space for home directories + +### Initial Setup + +1. **Access Home Directory Management** + - Log in to CyberPanel admin panel + - Navigate to **User Management** → **Home Directory Management** + +2. **Auto-Detect Existing Directories** + - Click **"Detect Directories"** button + - System will automatically find `/home`, `/home2`, `/home3`, etc. + - Review detected directories and their status + +3. **Configure Default Settings** + - Set default home directory (usually `/home`) + - Configure storage limits and user limits + - Enable/disable directories as needed + +### Database Migration (For Developers) +```bash +cd /usr/local/CyberCP +python manage.py makemigrations userManagment +python manage.py migrate +``` + +### Technical Implementation Details + +#### Core Components +- **Models** (`models.py`): `HomeDirectory` and `UserHomeMapping` models +- **Management** (`homeDirectoryManager.py`): Core functionality for operations +- **Utilities** (`homeDirectoryUtils.py`): Helper functions for path resolution +- **Views** (`homeDirectoryViews.py`): Admin interface and API endpoints +- **Templates**: Management interfaces and user creation forms + +#### File Structure +``` +cyberpanel/userManagment/ +├── models.py # Database models +├── homeDirectoryManager.py # Core management logic +├── homeDirectoryUtils.py # Utility functions +├── homeDirectoryViews.py # API endpoints +├── templates/userManagment/ +│ ├── homeDirectoryManagement.html +│ ├── userMigration.html +│ └── createUser.html (updated) +└── migrations/ + └── 0001_home_directories.py +``` + +## Managing Home Directories + +### Adding New Home Directories + +#### Method 1: Automatic Detection +```bash +# The system automatically detects directories matching pattern /home[0-9]* +# No manual intervention required +``` + +#### Method 2: Manual Creation +1. **Create Directory on Server** + ```bash + sudo mkdir /home2 + sudo chown root:root /home2 + sudo chmod 755 /home2 + ``` + +2. **Detect in CyberPanel** + - Go to Home Directory Management + - Click **"Detect Directories"** + - New directory will appear in the list + +### Configuring Home Directories + +#### Basic Configuration +- **Name**: Display name for the directory +- **Path**: Full system path (e.g., `/home2`) +- **Description**: Optional description for identification +- **Status**: Active/Inactive +- **Default**: Set as default for new users + +#### Advanced Settings +- **Maximum Users**: Limit number of users per directory +- **Storage Quota**: Set storage limits (if supported by filesystem) +- **Priority**: Directory selection priority for auto-assignment + +### Directory Status Management + +#### Active Directories +- Available for new user assignments +- Included in auto-selection algorithms +- Monitored for storage usage + +#### Inactive Directories +- Not available for new users +- Existing users remain unaffected +- Useful for maintenance or decommissioning + +## User Management + +### Creating Users with Home Directory Selection + +1. **Navigate to User Creation** + - Go to **User Management** → **Create User** + +2. **Select Home Directory** + - Choose from dropdown list of available directories + - View real-time storage information + - Select "Auto-select" for automatic assignment + +3. **Review Assignment** + - System shows selected directory details + - Displays available space and user count + - Confirms assignment before creation + +### Auto-Assignment Logic + +The system automatically selects the best home directory based on: +- **Available Space**: Prioritizes directories with more free space +- **User Count**: Balances users across directories +- **Directory Status**: Only considers active directories +- **User Limits**: Respects maximum user limits per directory + +### Manual User Assignment + +1. **Access User Migration** + - Go to **User Management** → **User Migration** + +2. **Select User and Target Directory** + - Choose user to migrate + - Select destination home directory + - Review migration details + +3. **Execute Migration** + - System moves user data + - Updates all references + - Verifies successful migration + +## Website Management Integration + +### Modifying Website Home Directory + +1. **Access Website Modification** + - Go to **Websites** → **Modify Website** + - Select website to modify + +2. **Change Home Directory** + - Select new home directory from dropdown + - View current and available options + - See real-time storage information + +3. **Save Changes** + - System migrates website owner + - Updates all website references + - Maintains website functionality + +### Website Owner Migration + +When changing a website's home directory: +- **User Data**: Website owner is migrated to new directory +- **Website Files**: All website files are moved +- **Database References**: All database references updated +- **Permissions**: File permissions maintained +- **Services**: Email, FTP, and other services updated + +## Storage Balancing + +### Monitoring Storage Usage + +#### Real-Time Statistics +- **Total Space**: Combined storage across all directories +- **Available Space**: Free space available +- **Usage Percentage**: Visual progress bars +- **User Distribution**: Users per directory + +#### Storage Alerts +- **Low Space Warning**: When directory approaches capacity +- **Full Directory Alert**: When directory reaches maximum users +- **Performance Impact**: Storage performance recommendations + +### Balancing Strategies + +#### Automatic Balancing +- **New User Assignment**: Distributes users evenly +- **Space-Based Selection**: Prioritizes directories with more space +- **Load Distribution**: Spreads load across multiple volumes + +#### Manual Balancing +- **User Migration**: Move users between directories +- **Directory Management**: Enable/disable directories +- **Capacity Planning**: Monitor and plan for growth + +## User Migration + +### Migration Process + +1. **Pre-Migration Checks** + - Verify source and destination directories + - Check available space + - Validate user permissions + +2. **Data Migration** + - Copy user home directory + - Update system references + - Verify data integrity + +3. **Post-Migration Verification** + - Test user access + - Verify website functionality + - Update service configurations + +### Migration Safety + +#### Backup Recommendations +```bash +# Always backup before migration +sudo tar -czf /backup/user-backup-$(date +%Y%m%d).tar.gz /home/username +``` + +#### Rollback Procedures +- Keep original data until migration verified +- Maintain backup of system configurations +- Document all changes made + +### Migration Commands + +#### Manual Migration (Advanced Users) +```bash +# Stop user services +sudo systemctl stop user@username + +# Copy user data +sudo rsync -av /home/username/ /home2/username/ + +# Update user home in system +sudo usermod -d /home2/username username + +# Update CyberPanel database +# (Use web interface for this) +``` + +## Troubleshooting + +### Common Issues + +#### 1. Directory Not Detected +**Problem**: New home directory not appearing in list +**Solution**: +```bash +# Check directory exists and has correct permissions +ls -la /home2 +sudo chown root:root /home2 +sudo chmod 755 /home2 + +# Refresh detection in CyberPanel +# Click "Detect Directories" button +``` + +#### 2. Migration Fails +**Problem**: User migration fails with errors +**Solution**: +- Check available space in destination +- Verify user permissions +- Review CyberPanel logs +- Ensure destination directory is active + +#### 3. Website Access Issues +**Problem**: Website not accessible after migration +**Solution**: +- Check file permissions +- Verify web server configuration +- Update virtual host settings +- Restart web server services + +#### 4. Storage Not Updating +**Problem**: Storage statistics not reflecting changes +**Solution**: +- Click "Refresh Stats" button +- Check filesystem mount status +- Verify directory accessibility +- Review system logs + +### Diagnostic Commands + +#### Check Directory Status +```bash +# List all home directories +ls -la /home* + +# Check disk usage +df -h /home* + +# Check permissions +ls -la /home*/username +``` + +#### Verify User Assignments +```bash +# Check user home directories +getent passwd | grep /home + +# Check CyberPanel database +# (Use web interface or database tools) +``` + +#### Monitor Storage Usage +```bash +# Real-time disk usage +watch -n 5 'df -h /home*' + +# Directory sizes +du -sh /home* + +# User directory sizes +du -sh /home*/username +``` + +### Log Files + +#### CyberPanel Logs +```bash +# Main CyberPanel log +tail -f /usr/local/CyberCP/logs/cyberpanel.log + +# Home directory specific logs +grep "home.*directory" /usr/local/CyberCP/logs/cyberpanel.log +``` + +#### System Logs +```bash +# System messages +tail -f /var/log/messages + +# Authentication logs +tail -f /var/log/auth.log +``` + +## Best Practices + +### Storage Planning + +#### Directory Organization +- **Primary Directory** (`/home`): Default for most users +- **Secondary Directories** (`/home2`, `/home3`): For specific user groups +- **Naming Convention**: Use descriptive names (e.g., `/home-ssd`, `/home-hdd`) + +#### Capacity Management +- **Monitor Usage**: Regular storage monitoring +- **Set Alerts**: Configure low-space warnings +- **Plan Growth**: Anticipate future storage needs +- **Regular Cleanup**: Remove unused user data + +### User Management + +#### Assignment Strategy +- **New Users**: Use auto-assignment for balanced distribution +- **Special Cases**: Manually assign users with specific requirements +- **Regular Review**: Periodically review user distribution + +#### Migration Planning +- **Schedule Migrations**: Plan during low-usage periods +- **Test First**: Verify migration process with test users +- **Communicate Changes**: Inform users of planned migrations + +### Security Considerations + +#### Access Control +- **Directory Permissions**: Maintain proper file permissions +- **User Isolation**: Ensure users can only access their directories +- **System Security**: Regular security updates and monitoring + +#### Backup Strategy +- **Regular Backups**: Backup user data regularly +- **Migration Backups**: Always backup before migrations +- **Configuration Backups**: Backup CyberPanel configurations + +## Advanced Configuration + +### Custom Directory Paths + +#### Non-Standard Paths +```bash +# Create custom home directory +sudo mkdir /var/home +sudo chown root:root /var/home +sudo chmod 755 /var/home + +# Add to CyberPanel manually +# (Use web interface to add custom paths) +``` + +#### Network Storage +- **NFS Mounts**: Use NFS for network-attached storage +- **iSCSI**: Configure iSCSI for block-level storage +- **Cloud Storage**: Integrate with cloud storage solutions + +### Performance Optimization + +#### Storage Performance +- **SSD vs HDD**: Use SSDs for frequently accessed data +- **RAID Configuration**: Optimize RAID for performance +- **Caching**: Implement appropriate caching strategies + +#### Load Balancing +- **User Distribution**: Balance users across storage devices +- **I/O Optimization**: Optimize I/O patterns +- **Monitoring**: Monitor performance metrics + +### Integration with Other Features + +#### Backup Integration +- **Automated Backups**: Include home directories in backup schedules +- **Incremental Backups**: Use incremental backup strategies +- **Restore Procedures**: Test restore procedures regularly + +#### Monitoring Integration +- **Storage Monitoring**: Integrate with monitoring systems +- **Alerting**: Set up automated alerts +- **Reporting**: Generate regular usage reports + +## API Reference + +### Home Directory Management API + +#### Get Home Directories +```bash +curl -X POST https://your-server:8090/userManagement/getUserHomeDirectories/ \ + -H "Content-Type: application/json" \ + -d '{}' +``` + +#### Update Home Directory +```bash +curl -X POST https://your-server:8090/userManagement/updateHomeDirectory/ \ + -H "Content-Type: application/json" \ + -d '{ + "id": 1, + "description": "Updated description", + "max_users": 100, + "is_active": true + }' +``` + +#### Migrate User +```bash +curl -X POST https://your-server:8090/userManagement/migrateUser/ \ + -H "Content-Type: application/json" \ + -d '{ + "user_id": 123, + "new_home_directory_id": 2 + }' +``` + +### Complete API Endpoints + +#### Home Directory Management +- `POST /userManagement/detectHomeDirectories/` - Detect new home directories +- `POST /userManagement/updateHomeDirectory/` - Update home directory settings +- `POST /userManagement/deleteHomeDirectory/` - Delete home directory +- `POST /userManagement/getHomeDirectoryStats/` - Get storage statistics + +#### User Operations +- `POST /userManagement/getUserHomeDirectories/` - Get available home directories +- `POST /userManagement/migrateUser/` - Migrate user to different home directory + +#### Website Integration +- `POST /websites/saveWebsiteChanges/` - Save website changes including home directory +- `POST /websites/getWebsiteDetails/` - Get website details including current home directory + +## Support and Resources + +### Documentation +- **CyberPanel Documentation**: https://cyberpanel.net/docs/ +- **User Management Guide**: This guide +- **API Documentation**: Available in CyberPanel interface + +### Community Support +- **CyberPanel Forums**: https://community.cyberpanel.net +- **GitHub Issues**: https://github.com/usmannasir/cyberpanel/issues +- **Discord Server**: https://discord.gg/cyberpanel + +### Professional Support +- **CyberPanel Support**: Available through official channels +- **Custom Implementation**: Contact for enterprise solutions + +--- + +**Note**: This guide covers the complete Home Directory Management feature in CyberPanel. For the latest updates and additional features, refer to the official CyberPanel documentation and community resources. + +*Last updated: January 2025* diff --git a/guides/INDEX.md b/guides/INDEX.md index 11fbc6c59..951257df0 100644 --- a/guides/INDEX.md +++ b/guides/INDEX.md @@ -46,6 +46,9 @@ Welcome to the CyberPanel documentation hub! This folder contains all guides, tu ### 💻 Command Line Interface - **[CLI Command Reference](CLI_COMMAND_REFERENCE.md)** - Complete reference for all CyberPanel CLI commands +### 🏠 Storage & User Management +- **[Home Directory Management Guide](HOME_DIRECTORY_MANAGEMENT_GUIDE.md)** - Complete guide for managing multiple home directories and storage balancing + ### 📖 General Documentation - **[README](../README.md)** - Main CyberPanel documentation with installation instructions and feature overview - **[Contributing Guide](CONTRIBUTING.md)** - Guidelines for contributing to the CyberPanel project @@ -57,7 +60,8 @@ Welcome to the CyberPanel documentation hub! This folder contains all guides, tu 3. **Need Docker help?** Check the [Docker Command Execution Guide](Docker_Command_Execution_Guide.md) 4. **Setting up email marketing?** Follow the [Mautic Installation Guide](MAUTIC_INSTALLATION_GUIDE.md) 5. **Want to customize the interface?** Check the [Custom CSS Guide](CUSTOM_CSS_GUIDE.md) -6. **Want to contribute?** Read the [Contributing Guide](CONTRIBUTING.md) +6. **Managing multiple storage volumes?** Follow the [Home Directory Management Guide](HOME_DIRECTORY_MANAGEMENT_GUIDE.md) +7. **Want to contribute?** Read the [Contributing Guide](CONTRIBUTING.md) ## 🔍 Finding What You Need @@ -83,6 +87,7 @@ Welcome to the CyberPanel documentation hub! This folder contains all guides, tu - **Docker Features**: [Docker Command Execution Guide](Docker_Command_Execution_Guide.md) - **Security Features**: [AI Scanner Documentation](AIScannerDocs.md) - **Email Marketing**: [Mautic Installation Guide](MAUTIC_INSTALLATION_GUIDE.md) +- **Storage Management**: [Home Directory Management Guide](HOME_DIRECTORY_MANAGEMENT_GUIDE.md) - **Customization & Design**: [Custom CSS Guide](CUSTOM_CSS_GUIDE.md) - **Command Line Interface**: [CLI Command Reference](CLI_COMMAND_REFERENCE.md) - **Development**: [Contributing Guide](CONTRIBUTING.md) @@ -93,6 +98,7 @@ Welcome to the CyberPanel documentation hub! This folder contains all guides, tu - Docker container management - Command execution - Security scanning +- Home directory management - CLI command reference ### 🔧 **Integrations** diff --git a/plogical/vhost.py b/plogical/vhost.py index a3f5df68e..bf702e588 100644 --- a/plogical/vhost.py +++ b/plogical/vhost.py @@ -196,9 +196,15 @@ class vhost: command = 'mkdir -p /usr/local/lsws/Example/html/.well-known/acme-challenge' ProcessUtilities.normalExecutioner(command) - path = "/home/" + virtualHostName - pathHTML = "/home/" + virtualHostName + "/public_html" - pathLogs = "/home/" + virtualHostName + "/logs" + # Get user's home directory dynamically + from userManagment.homeDirectoryUtils import HomeDirectoryUtils + home_path = HomeDirectoryUtils.getUserHomeDirectory(virtualHostUser) + if not home_path: + home_path = "/home" # Fallback to default + + path = os.path.join(home_path, virtualHostName) + pathHTML = os.path.join(home_path, virtualHostName, "public_html") + pathLogs = os.path.join(home_path, virtualHostName, "logs") confPath = vhost.Server_root + "/conf/vhosts/"+virtualHostName completePathToConfigFile = confPath +"/vhost.conf" diff --git a/userManagment/homeDirectoryManager.py b/userManagment/homeDirectoryManager.py new file mode 100644 index 000000000..d81821a0c --- /dev/null +++ b/userManagment/homeDirectoryManager.py @@ -0,0 +1,230 @@ +#!/usr/local/CyberCP/bin/python +import os +import sys +import json +import shutil +import subprocess +import pwd +import grp +from django.db import models +from django.conf import settings +from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging +from plogical.processUtilities import ProcessUtilities + +class HomeDirectoryManager: + """ + Manages multiple home directories for CyberPanel users + Supports /home, /home2, /home3, etc. for storage balance + """ + + @staticmethod + def detectHomeDirectories(): + """ + Automatically detect all available home directories + Returns list of available home directories + """ + try: + home_dirs = [] + + # Check for /home (default) + if os.path.exists('/home') and os.path.isdir('/home'): + home_dirs.append({ + 'path': '/home', + 'name': 'home', + 'available_space': HomeDirectoryManager.getAvailableSpace('/home'), + 'total_space': HomeDirectoryManager.getTotalSpace('/home'), + 'user_count': HomeDirectoryManager.getUserCount('/home') + }) + + # Check for /home2, /home3, etc. + for i in range(2, 10): # Check up to /home9 + home_path = f'/home{i}' + if os.path.exists(home_path) and os.path.isdir(home_path): + home_dirs.append({ + 'path': home_path, + 'name': f'home{i}', + 'available_space': HomeDirectoryManager.getAvailableSpace(home_path), + 'total_space': HomeDirectoryManager.getTotalSpace(home_path), + 'user_count': HomeDirectoryManager.getUserCount(home_path) + }) + + return home_dirs + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error detecting home directories: {str(e)}") + return [] + + @staticmethod + def getAvailableSpace(path): + """Get available space in bytes for a given path""" + try: + statvfs = os.statvfs(path) + return statvfs.f_frsize * statvfs.f_bavail + except: + return 0 + + @staticmethod + def getTotalSpace(path): + """Get total space in bytes for a given path""" + try: + statvfs = os.statvfs(path) + return statvfs.f_frsize * statvfs.f_blocks + except: + return 0 + + @staticmethod + def getUserCount(path): + """Get number of users in a home directory""" + try: + count = 0 + for item in os.listdir(path): + item_path = os.path.join(path, item) + if os.path.isdir(item_path) and not item.startswith('.'): + # Check if it's a user directory (has public_html) + if os.path.exists(os.path.join(item_path, 'public_html')): + count += 1 + return count + except: + return 0 + + @staticmethod + def getBestHomeDirectory(): + """ + Automatically select the best home directory based on available space + Returns the path with most available space + """ + try: + home_dirs = HomeDirectoryManager.detectHomeDirectories() + if not home_dirs: + return '/home' # Fallback to default + + # Sort by available space (descending) + home_dirs.sort(key=lambda x: x['available_space'], reverse=True) + return home_dirs[0]['path'] + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error selecting best home directory: {str(e)}") + return '/home' + + @staticmethod + def createUserDirectory(username, home_path, owner_uid=5003, owner_gid=5003): + """ + Create user directory in specified home path + """ + try: + user_path = os.path.join(home_path, username) + + # Create user directory + if not os.path.exists(user_path): + os.makedirs(user_path, mode=0o755) + + # Create public_html directory + public_html_path = os.path.join(user_path, 'public_html') + if not os.path.exists(public_html_path): + os.makedirs(public_html_path, mode=0o755) + + # Create logs directory + logs_path = os.path.join(user_path, 'logs') + if not os.path.exists(logs_path): + os.makedirs(logs_path, mode=0o755) + + # Set ownership + HomeDirectoryManager.setOwnership(user_path, owner_uid, owner_gid) + + return True + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error creating user directory: {str(e)}") + return False + + @staticmethod + def setOwnership(path, uid, gid): + """Set ownership for a path recursively""" + try: + # Set ownership for the directory + os.chown(path, uid, gid) + + # Set ownership for all contents recursively + for root, dirs, files in os.walk(path): + for d in dirs: + os.chown(os.path.join(root, d), uid, gid) + for f in files: + os.chown(os.path.join(root, f), uid, gid) + + return True + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error setting ownership: {str(e)}") + return False + + @staticmethod + def migrateUser(username, from_home, to_home, owner_uid=5003, owner_gid=5003): + """ + Migrate user from one home directory to another + """ + try: + from_path = os.path.join(from_home, username) + to_path = os.path.join(to_home, username) + + if not os.path.exists(from_path): + return False, f"User directory {from_path} does not exist" + + if os.path.exists(to_path): + return False, f"User directory {to_path} already exists" + + # Create target directory structure + if not HomeDirectoryManager.createUserDirectory(username, to_home, owner_uid, owner_gid): + return False, "Failed to create target directory" + + # Copy all files and directories + shutil.copytree(from_path, to_path, dirs_exist_ok=True) + + # Set proper ownership + HomeDirectoryManager.setOwnership(to_path, owner_uid, owner_gid) + + # Remove old directory + shutil.rmtree(from_path) + + return True, "User migrated successfully" + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error migrating user: {str(e)}") + return False, str(e) + + @staticmethod + def getHomeDirectoryStats(): + """ + Get comprehensive statistics for all home directories + """ + try: + home_dirs = HomeDirectoryManager.detectHomeDirectories() + stats = { + 'total_directories': len(home_dirs), + 'total_users': sum(d['user_count'] for d in home_dirs), + 'total_space': sum(d['total_space'] for d in home_dirs), + 'total_available': sum(d['available_space'] for d in home_dirs), + 'directories': home_dirs + } + + # Calculate usage percentages + for directory in stats['directories']: + if directory['total_space'] > 0: + used_space = directory['total_space'] - directory['available_space'] + directory['usage_percentage'] = (used_space / directory['total_space']) * 100 + else: + directory['usage_percentage'] = 0 + + return stats + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error getting home directory stats: {str(e)}") + return None + + @staticmethod + def formatBytes(bytes_value): + """Convert bytes to human readable format""" + for unit in ['B', 'KB', 'MB', 'GB', 'TB']: + if bytes_value < 1024.0: + return f"{bytes_value:.1f} {unit}" + bytes_value /= 1024.0 + return f"{bytes_value:.1f} PB" diff --git a/userManagment/homeDirectoryUtils.py b/userManagment/homeDirectoryUtils.py new file mode 100644 index 000000000..4d49ef75a --- /dev/null +++ b/userManagment/homeDirectoryUtils.py @@ -0,0 +1,148 @@ +#!/usr/local/CyberCP/bin/python +import os +import sys +from django.db import models +from loginSystem.models import Administrator +from .models import HomeDirectory, UserHomeMapping +from .homeDirectoryManager import HomeDirectoryManager + +class HomeDirectoryUtils: + """ + Utility functions for getting user home directories + """ + + @staticmethod + def getUserHomeDirectory(username): + """ + Get the home directory path for a specific user + Returns the home directory path or None if not found + """ + try: + user = Administrator.objects.get(userName=username) + try: + mapping = UserHomeMapping.objects.get(user=user) + return mapping.home_directory.path + except UserHomeMapping.DoesNotExist: + # Fallback to default home directory + default_home = HomeDirectory.objects.filter(is_default=True).first() + if default_home: + return default_home.path + else: + return HomeDirectoryManager.getBestHomeDirectory() + except Administrator.DoesNotExist: + return None + + @staticmethod + def getUserHomeDirectoryObject(username): + """ + Get the home directory object for a specific user + Returns the HomeDirectory object or None if not found + """ + try: + user = Administrator.objects.get(userName=username) + try: + mapping = UserHomeMapping.objects.get(user=user) + return mapping.home_directory + except UserHomeMapping.DoesNotExist: + # Fallback to default home directory + return HomeDirectory.objects.filter(is_default=True).first() + except Administrator.DoesNotExist: + return None + + @staticmethod + def getWebsitePath(domain, username=None): + """ + Get the website path for a domain, using the user's home directory + """ + if username: + home_path = HomeDirectoryUtils.getUserHomeDirectory(username) + else: + home_path = HomeDirectoryManager.getBestHomeDirectory() + + if not home_path: + home_path = '/home' # Fallback + + return os.path.join(home_path, domain) + + @staticmethod + def getPublicHtmlPath(domain, username=None): + """ + Get the public_html path for a domain + """ + website_path = HomeDirectoryUtils.getWebsitePath(domain, username) + return os.path.join(website_path, 'public_html') + + @staticmethod + def getLogsPath(domain, username=None): + """ + Get the logs path for a domain + """ + website_path = HomeDirectoryUtils.getWebsitePath(domain, username) + return os.path.join(website_path, 'logs') + + @staticmethod + def updateUserHomeDirectory(username, new_home_directory_id): + """ + Update a user's home directory + """ + try: + user = Administrator.objects.get(userName=username) + home_dir = HomeDirectory.objects.get(id=new_home_directory_id) + + # Update or create mapping + mapping, created = UserHomeMapping.objects.get_or_create( + user=user, + defaults={'home_directory': home_dir} + ) + + if not created: + mapping.home_directory = home_dir + mapping.save() + + return True, "Home directory updated successfully" + + except Administrator.DoesNotExist: + return False, "User not found" + except HomeDirectory.DoesNotExist: + return False, "Home directory not found" + except Exception as e: + return False, str(e) + + @staticmethod + def getAllUsersInHomeDirectory(home_directory_id): + """ + Get all users assigned to a specific home directory + """ + try: + home_dir = HomeDirectory.objects.get(id=home_directory_id) + mappings = UserHomeMapping.objects.filter(home_directory=home_dir) + return [mapping.user for mapping in mappings] + except HomeDirectory.DoesNotExist: + return [] + + @staticmethod + def getHomeDirectoryUsageStats(): + """ + Get usage statistics for all home directories + """ + home_dirs = HomeDirectory.objects.filter(is_active=True) + stats = [] + + for home_dir in home_dirs: + user_count = UserHomeMapping.objects.filter(home_directory=home_dir).count() + available_space = home_dir.get_available_space() + total_space = home_dir.get_total_space() + usage_percentage = home_dir.get_usage_percentage() + + stats.append({ + 'id': home_dir.id, + 'name': home_dir.name, + 'path': home_dir.path, + 'user_count': user_count, + 'available_space': available_space, + 'total_space': total_space, + 'usage_percentage': usage_percentage, + 'is_default': home_dir.is_default + }) + + return stats diff --git a/userManagment/homeDirectoryViews.py b/userManagment/homeDirectoryViews.py new file mode 100644 index 000000000..af0f71070 --- /dev/null +++ b/userManagment/homeDirectoryViews.py @@ -0,0 +1,254 @@ +#!/usr/local/CyberCP/bin/python +import json +import os +import sys +from django.shortcuts import render +from django.http import HttpResponse, JsonResponse +from django.views.decorators.csrf import csrf_exempt +from loginSystem.views import loadLoginPage +from loginSystem.models import Administrator +from plogical.acl import ACLManager +from plogical.httpProc import httpProc +from .homeDirectoryManager import HomeDirectoryManager +from .models import HomeDirectory, UserHomeMapping +from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging + +def loadHomeDirectoryManagement(request): + """Load home directory management interface""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return ACLManager.loadError() + + # Get all home directories + home_directories = HomeDirectory.objects.all().order_by('name') + + # Get statistics + stats = HomeDirectoryManager.getHomeDirectoryStats() + + proc = httpProc(request, 'userManagment/homeDirectoryManagement.html', { + 'home_directories': home_directories, + 'stats': stats + }, 'admin') + return proc.render() + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error loading home directory management: {str(e)}") + return ACLManager.loadError() + +def detectHomeDirectories(request): + """Detect and add new home directories""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'}) + + # Detect home directories + detected_dirs = HomeDirectoryManager.detectHomeDirectories() + added_count = 0 + + for dir_info in detected_dirs: + # Check if directory already exists in database + if not HomeDirectory.objects.filter(path=dir_info['path']).exists(): + # Create new home directory entry + home_dir = HomeDirectory( + name=dir_info['name'], + path=dir_info['path'], + is_active=True, + is_default=(dir_info['path'] == '/home') + ) + home_dir.save() + added_count += 1 + + return JsonResponse({ + 'status': 1, + 'message': f'Detected and added {added_count} new home directories', + 'added_count': added_count + }) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error detecting home directories: {str(e)}") + return JsonResponse({'status': 0, 'error_message': str(e)}) + +def updateHomeDirectory(request): + """Update home directory settings""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'}) + + data = json.loads(request.body) + home_dir_id = data.get('id') + is_active = data.get('is_active', True) + is_default = data.get('is_default', False) + max_users = data.get('max_users', 0) + description = data.get('description', '') + + try: + home_dir = HomeDirectory.objects.get(id=home_dir_id) + + # If setting as default, unset other defaults + if is_default: + HomeDirectory.objects.filter(is_default=True).update(is_default=False) + + home_dir.is_active = is_active + home_dir.is_default = is_default + home_dir.max_users = max_users + home_dir.description = description + home_dir.save() + + return JsonResponse({'status': 1, 'message': 'Home directory updated successfully'}) + + except HomeDirectory.DoesNotExist: + return JsonResponse({'status': 0, 'error_message': 'Home directory not found'}) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error updating home directory: {str(e)}") + return JsonResponse({'status': 0, 'error_message': str(e)}) + +def deleteHomeDirectory(request): + """Delete home directory (only if no users assigned)""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'}) + + data = json.loads(request.body) + home_dir_id = data.get('id') + + try: + home_dir = HomeDirectory.objects.get(id=home_dir_id) + + # Check if any users are assigned to this home directory + user_count = UserHomeMapping.objects.filter(home_directory=home_dir).count() + if user_count > 0: + return JsonResponse({ + 'status': 0, + 'error_message': f'Cannot delete home directory. {user_count} users are assigned to it.' + }) + + # Don't allow deletion of /home (default) + if home_dir.path == '/home': + return JsonResponse({ + 'status': 0, + 'error_message': 'Cannot delete the default /home directory' + }) + + home_dir.delete() + return JsonResponse({'status': 1, 'message': 'Home directory deleted successfully'}) + + except HomeDirectory.DoesNotExist: + return JsonResponse({'status': 0, 'error_message': 'Home directory not found'}) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error deleting home directory: {str(e)}") + return JsonResponse({'status': 0, 'error_message': str(e)}) + +def getHomeDirectoryStats(request): + """Get home directory statistics""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'}) + + stats = HomeDirectoryManager.getHomeDirectoryStats() + return JsonResponse({'status': 1, 'stats': stats}) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error getting home directory stats: {str(e)}") + return JsonResponse({'status': 0, 'error_message': str(e)}) + +def getUserHomeDirectories(request): + """Get available home directories for user creation""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1 and currentACL['createNewUser'] != 1: + return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'}) + + # Get active home directories + home_dirs = HomeDirectory.objects.filter(is_active=True).order_by('name') + + directories = [] + for home_dir in home_dirs: + directories.append({ + 'id': home_dir.id, + 'name': home_dir.name, + 'path': home_dir.path, + 'available_space': home_dir.get_available_space(), + 'user_count': home_dir.get_user_count(), + 'is_default': home_dir.is_default, + 'description': home_dir.description + }) + + return JsonResponse({'status': 1, 'directories': directories}) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error getting user home directories: {str(e)}") + return JsonResponse({'status': 0, 'error_message': str(e)}) + +def migrateUser(request): + """Migrate user to different home directory""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'}) + + data = json.loads(request.body) + username = data.get('username') + target_home_id = data.get('target_home_id') + + try: + user = Administrator.objects.get(userName=username) + target_home = HomeDirectory.objects.get(id=target_home_id) + + # Get current home directory + try: + current_mapping = UserHomeMapping.objects.get(user=user) + current_home = current_mapping.home_directory + except UserHomeMapping.DoesNotExist: + current_home = HomeDirectory.objects.filter(is_default=True).first() + if not current_home: + current_home = HomeDirectory.objects.first() + + if not current_home: + return JsonResponse({'status': 0, 'error_message': 'No home directory found for user'}) + + # Perform migration + success, message = HomeDirectoryManager.migrateUser( + username, + current_home.path, + target_home.path + ) + + if success: + # Update user mapping + UserHomeMapping.objects.update_or_create( + user=user, + defaults={'home_directory': target_home} + ) + return JsonResponse({'status': 1, 'message': message}) + else: + return JsonResponse({'status': 0, 'error_message': message}) + + except Administrator.DoesNotExist: + return JsonResponse({'status': 0, 'error_message': 'User not found'}) + except HomeDirectory.DoesNotExist: + return JsonResponse({'status': 0, 'error_message': 'Target home directory not found'}) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error migrating user: {str(e)}") + return JsonResponse({'status': 0, 'error_message': str(e)}) diff --git a/userManagment/management/__init__.py b/userManagment/management/__init__.py new file mode 100644 index 000000000..65cb83aca --- /dev/null +++ b/userManagment/management/__init__.py @@ -0,0 +1 @@ +# Management commands package diff --git a/userManagment/management/commands/__init__.py b/userManagment/management/commands/__init__.py new file mode 100644 index 000000000..2c1c7c158 --- /dev/null +++ b/userManagment/management/commands/__init__.py @@ -0,0 +1 @@ +# Management commands diff --git a/userManagment/management/commands/init_home_directories.py b/userManagment/management/commands/init_home_directories.py new file mode 100644 index 000000000..c093b8d36 --- /dev/null +++ b/userManagment/management/commands/init_home_directories.py @@ -0,0 +1,49 @@ +#!/usr/local/CyberCP/bin/python +from django.core.management.base import BaseCommand +from userManagment.homeDirectoryManager import HomeDirectoryManager +from userManagment.models import HomeDirectory +import os + +class Command(BaseCommand): + help = 'Initialize home directories for CyberPanel' + + def handle(self, *args, **options): + self.stdout.write('Initializing home directories...') + + # Detect home directories + detected_dirs = HomeDirectoryManager.detectHomeDirectories() + + if not detected_dirs: + self.stdout.write(self.style.WARNING('No home directories detected')) + return + + # Create default /home if it doesn't exist + if not os.path.exists('/home'): + self.stdout.write('Creating default /home directory...') + os.makedirs('/home', mode=0o755) + detected_dirs.insert(0, { + 'path': '/home', + 'name': 'home', + 'available_space': HomeDirectoryManager.getAvailableSpace('/home'), + 'total_space': HomeDirectoryManager.getTotalSpace('/home'), + 'user_count': 0 + }) + + # Create database entries + created_count = 0 + for dir_info in detected_dirs: + if not HomeDirectory.objects.filter(path=dir_info['path']).exists(): + home_dir = HomeDirectory( + name=dir_info['name'], + path=dir_info['path'], + is_active=True, + is_default=(dir_info['path'] == '/home'), + description=f"Auto-detected home directory: {dir_info['path']}" + ) + home_dir.save() + created_count += 1 + self.stdout.write(f'Created home directory: {dir_info["name"]} ({dir_info["path"]})') + + self.stdout.write( + self.style.SUCCESS(f'Successfully initialized {created_count} home directories') + ) diff --git a/userManagment/migrations/0001_home_directories.py b/userManagment/migrations/0001_home_directories.py new file mode 100644 index 000000000..762462c8a --- /dev/null +++ b/userManagment/migrations/0001_home_directories.py @@ -0,0 +1,48 @@ +# Generated migration for home directories feature + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('loginSystem', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='HomeDirectory', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Directory name (e.g., home, home2)', max_length=50, unique=True)), + ('path', models.CharField(help_text='Full path to home directory', max_length=255, unique=True)), + ('is_active', models.BooleanField(default=True, help_text='Whether this home directory is active')), + ('is_default', models.BooleanField(default=False, help_text='Whether this is the default home directory')), + ('max_users', models.IntegerField(default=0, help_text='Maximum number of users (0 = unlimited)')), + ('description', models.TextField(blank=True, help_text='Description of this home directory')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Home Directory', + 'verbose_name_plural': 'Home Directories', + 'db_table': 'home_directories', + }, + ), + migrations.CreateModel( + name='UserHomeMapping', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('home_directory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='userManagment.homedirectory')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='home_mapping', to='loginSystem.administrator')), + ], + options={ + 'verbose_name': 'User Home Mapping', + 'verbose_name_plural': 'User Home Mappings', + 'db_table': 'user_home_mappings', + }, + ), + ] diff --git a/userManagment/models.py b/userManagment/models.py index 4e6a8e76d..9f31e5aec 100644 --- a/userManagment/models.py +++ b/userManagment/models.py @@ -1,6 +1,85 @@ -# -*- coding: utf-8 -*- - - from django.db import models +from loginSystem.models import Administrator -# Create your models here. +class HomeDirectory(models.Model): + """ + Model to store home directory configurations + """ + name = models.CharField(max_length=50, unique=True, help_text="Directory name (e.g., home, home2)") + path = models.CharField(max_length=255, unique=True, help_text="Full path to home directory") + is_active = models.BooleanField(default=True, help_text="Whether this home directory is active") + is_default = models.BooleanField(default=False, help_text="Whether this is the default home directory") + max_users = models.IntegerField(default=0, help_text="Maximum number of users (0 = unlimited)") + description = models.TextField(blank=True, help_text="Description of this home directory") + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + db_table = 'home_directories' + verbose_name = 'Home Directory' + verbose_name_plural = 'Home Directories' + + def __str__(self): + return f"{self.name} ({self.path})" + + def get_available_space(self): + """Get available space in bytes""" + try: + import os + statvfs = os.statvfs(self.path) + return statvfs.f_frsize * statvfs.f_bavail + except: + return 0 + + def get_total_space(self): + """Get total space in bytes""" + try: + import os + statvfs = os.statvfs(self.path) + return statvfs.f_frsize * statvfs.f_blocks + except: + return 0 + + def get_user_count(self): + """Get number of users in this home directory""" + try: + import os + count = 0 + if os.path.exists(self.path): + for item in os.listdir(self.path): + item_path = os.path.join(self.path, item) + if os.path.isdir(item_path) and not item.startswith('.'): + # Check if it's a user directory (has public_html) + if os.path.exists(os.path.join(item_path, 'public_html')): + count += 1 + return count + except: + return 0 + + def get_usage_percentage(self): + """Get usage percentage""" + try: + total = self.get_total_space() + if total > 0: + used = total - self.get_available_space() + return (used / total) * 100 + return 0 + except: + return 0 + +class UserHomeMapping(models.Model): + """ + Model to map users to their home directories + """ + user = models.OneToOneField(Administrator, on_delete=models.CASCADE, related_name='home_mapping') + home_directory = models.ForeignKey(HomeDirectory, on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + db_table = 'user_home_mappings' + verbose_name = 'User Home Mapping' + verbose_name_plural = 'User Home Mappings' + + def __str__(self): + return f"{self.user.userName} -> {self.home_directory.name}" \ No newline at end of file diff --git a/userManagment/templates/userManagment/createUser.html b/userManagment/templates/userManagment/createUser.html index 9de5aeea8..8c0b48297 100644 --- a/userManagment/templates/userManagment/createUser.html +++ b/userManagment/templates/userManagment/createUser.html @@ -342,6 +342,21 @@

{% trans "Choose the security level for this account" %}

+
+ + +

{% trans "Choose the home directory for this user's files" %}

+
+ {{selectedHomeDirectoryInfo.name}}: {{selectedHomeDirectoryInfo.description || 'No description available'}}
+ Available Space: {{selectedHomeDirectoryInfo.available_space | filesize}} | Users: {{selectedHomeDirectoryInfo.user_count}} +
+
+
+ + {% endblock %} \ No newline at end of file diff --git a/userManagment/templates/userManagment/homeDirectoryManagement.html b/userManagment/templates/userManagment/homeDirectoryManagement.html new file mode 100644 index 000000000..1bbe71f92 --- /dev/null +++ b/userManagment/templates/userManagment/homeDirectoryManagement.html @@ -0,0 +1,688 @@ +{% extends "baseTemplate/index.html" %} +{% load static %} +{% block title %} + Home Directory Management - CyberPanel +{% endblock %} + +{% block header_scripts %} + +{% endblock %} + +{% block content %} +
+
+ + + +
+
+
+ +
+
{{ stats.total_directories|default:0 }}
+
Total Directories
+
+
+
+ +
+
{{ stats.total_users|default:0 }}
+
Total Users
+
+
+
+ +
+
{{ stats.total_space|default:0|filesizeformat }}
+
Total Space
+
+
+
+ +
+
{{ stats.total_available|default:0|filesizeformat }}
+
Available Space
+
+
+ +
+
+ + Home Directories +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + {% for home_dir in home_directories %} + + + + + + + + + + + + {% endfor %} + +
NamePathUsersTotal SpaceAvailable SpaceUsage %StatusDefaultActions
+ {{ home_dir.name }} + {% if home_dir.description %} +
{{ home_dir.description }} + {% endif %} +
{{ home_dir.path }} + {{ home_dir.get_user_count }} + {% if home_dir.max_users > 0 %} + / {{ home_dir.max_users }} + {% endif %} + {{ home_dir.get_total_space|filesizeformat }}{{ home_dir.get_available_space|filesizeformat }} +
+
+
+ {{ home_dir.get_usage_percentage|floatformat:1 }}% +
+ + {% if home_dir.is_active %}Active{% else %}Inactive{% endif %} + + + {% if home_dir.is_default %} + Default + {% else %} + + {% endif %} + +
+ + {% if not home_dir.is_default and home_dir.get_user_count == 0 %} + + {% endif %} +
+
+
+
+
+
+ + + + + +{% endblock %} diff --git a/userManagment/templates/userManagment/userMigration.html b/userManagment/templates/userManagment/userMigration.html new file mode 100644 index 000000000..a2ac444ca --- /dev/null +++ b/userManagment/templates/userManagment/userMigration.html @@ -0,0 +1,259 @@ +{% extends "baseTemplate/index.html" %} +{% load static %} +{% block title %} + User Migration - CyberPanel +{% endblock %} + +{% block content %} +
+
+
+
+
+

User Migration

+
+ +
+
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+
+ + + + + +
+ +
+ + + + + + +
+
+
+
+
+ + +{% endblock %} diff --git a/userManagment/urls.py b/userManagment/urls.py index bf3ff26fd..9c4468f9f 100644 --- a/userManagment/urls.py +++ b/userManagment/urls.py @@ -1,5 +1,6 @@ from django.urls import path from . import views +from . import homeDirectoryViews urlpatterns = [ path('', views.loadUserHome, name='loadUsersHome'), @@ -27,4 +28,14 @@ urlpatterns = [ path('listUsers', views.listUsers, name='listUsers'), path('fetchTableUsers', views.fetchTableUsers, name='fetchTableUsers'), path('controlUserState', views.controlUserState, name='controlUserState'), + + # Home Directory Management URLs + path('homeDirectoryManagement', homeDirectoryViews.loadHomeDirectoryManagement, name='homeDirectoryManagement'), + path('detectHomeDirectories', homeDirectoryViews.detectHomeDirectories, name='detectHomeDirectories'), + path('updateHomeDirectory', homeDirectoryViews.updateHomeDirectory, name='updateHomeDirectory'), + path('deleteHomeDirectory', homeDirectoryViews.deleteHomeDirectory, name='deleteHomeDirectory'), + path('getHomeDirectoryStats', homeDirectoryViews.getHomeDirectoryStats, name='getHomeDirectoryStats'), + path('getUserHomeDirectories', homeDirectoryViews.getUserHomeDirectories, name='getUserHomeDirectories'), + path('migrateUser', homeDirectoryViews.migrateUser, name='migrateUser'), + path('userMigration', views.userMigration, name='userMigration'), ] diff --git a/userManagment/views.py b/userManagment/views.py index 94afe7101..11b07926e 100644 --- a/userManagment/views.py +++ b/userManagment/views.py @@ -133,6 +133,7 @@ def submitUserCreation(request): password = data['password'] websitesLimit = data['websitesLimit'] selectedACL = data['selectedACL'] + selectedHomeDirectory = data.get('selectedHomeDirectory', '') if ACLManager.CheckRegEx("^[\w'\-,.][^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]]{2,}$", firstName) == 0: data_ret = {'status': 0, 'createStatus': 0, 'error_message': 'First Name can only contain alphabetic characters, and should be more than 2 characters long...'} @@ -239,6 +240,42 @@ def submitUserCreation(request): final_json = json.dumps(data_ret) return HttpResponse(final_json) + # Handle home directory assignment + from .homeDirectoryManager import HomeDirectoryManager + from .models import HomeDirectory, UserHomeMapping + + if selectedHomeDirectory: + # Use selected home directory + try: + home_dir = HomeDirectory.objects.get(id=selectedHomeDirectory) + home_path = home_dir.path + except HomeDirectory.DoesNotExist: + home_path = HomeDirectoryManager.getBestHomeDirectory() + else: + # Auto-select best home directory + home_path = HomeDirectoryManager.getBestHomeDirectory() + try: + home_dir = HomeDirectory.objects.get(path=home_path) + except HomeDirectory.DoesNotExist: + # Create home directory entry if it doesn't exist + home_dir = HomeDirectory.objects.create( + name=home_path.split('/')[-1], + path=home_path, + is_active=True, + is_default=(home_path == '/home') + ) + + # Create user directory + if HomeDirectoryManager.createUserDirectory(userName, home_path): + # Create user-home mapping + UserHomeMapping.objects.create( + user=newAdmin, + home_directory=home_dir + ) + else: + # Log error but don't fail user creation + logging.CyberCPLogFileWriter.writeToFile(f"Failed to create user directory for {userName} in {home_path}") + data_ret = {'status': 1, 'createStatus': 1, 'error_message': "None"} final_json = json.dumps(data_ret) @@ -926,3 +963,19 @@ def controlUserState(request): data_ret = {'status': 0, 'saveStatus': 0, 'error_message': "Not logged in as admin", } json_data = json.dumps(data_ret) return HttpResponse(json_data) + +def userMigration(request): + """Load user migration interface""" + try: + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] != 1: + return ACLManager.loadError() + + proc = httpProc(request, 'userManagment/userMigration.html', {}, 'admin') + return proc.render() + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error loading user migration: {str(e)}") + return ACLManager.loadError() diff --git a/websiteFunctions/static/websiteFunctions/websiteFunctions.js b/websiteFunctions/static/websiteFunctions/websiteFunctions.js index 562eeddb8..f178d4810 100644 --- a/websiteFunctions/static/websiteFunctions/websiteFunctions.js +++ b/websiteFunctions/static/websiteFunctions/websiteFunctions.js @@ -10730,6 +10730,39 @@ $("#modifyWebsiteLoading").hide(); $("#modifyWebsiteButton").hide(); app.controller('modifyWebsitesController', function ($scope, $http) { + + // Initialize home directory variables + $scope.homeDirectories = []; + $scope.selectedHomeDirectory = ''; + $scope.selectedHomeDirectoryInfo = null; + $scope.currentHomeDirectory = ''; + + // Load home directories on page load + $scope.loadHomeDirectories = function() { + $http.post('/userManagement/getUserHomeDirectories/', {}) + .then(function(response) { + if (response.data.status === 1) { + $scope.homeDirectories = response.data.directories; + } + }) + .catch(function(error) { + console.error('Error loading home directories:', error); + }); + }; + + // Update home directory info when selection changes + $scope.updateHomeDirectoryInfo = function() { + if ($scope.selectedHomeDirectory) { + $scope.selectedHomeDirectoryInfo = $scope.homeDirectories.find(function(dir) { + return dir.id == $scope.selectedHomeDirectory; + }); + } else { + $scope.selectedHomeDirectoryInfo = null; + } + }; + + // Initialize home directories + $scope.loadHomeDirectories(); $scope.fetchWebsites = function () { @@ -10774,6 +10807,7 @@ app.controller('modifyWebsitesController', function ($scope, $http) { $scope.webpacks = JSON.parse(response.data.packages); $scope.adminNames = JSON.parse(response.data.adminNames); $scope.currentAdmin = response.data.currentAdmin; + $scope.currentHomeDirectory = response.data.currentHomeDirectory || 'Default'; $("#webSiteDetailsToBeModified").fadeIn(); $("#websiteModifySuccess").fadeIn(); @@ -10801,6 +10835,7 @@ app.controller('modifyWebsitesController', function ($scope, $http) { var email = $scope.adminEmail; var phpVersion = $scope.phpSelection; var admin = $scope.selectedAdmin; + var homeDirectory = $scope.selectedHomeDirectory; $("#websiteModifyFailure").hide(); @@ -10817,7 +10852,8 @@ app.controller('modifyWebsitesController', function ($scope, $http) { packForWeb: packForWeb, email: email, phpVersion: phpVersion, - admin: admin + admin: admin, + homeDirectory: homeDirectory }; var config = { diff --git a/websiteFunctions/templates/websiteFunctions/modifyWebsite.html b/websiteFunctions/templates/websiteFunctions/modifyWebsite.html index 7769b4340..ab289504c 100644 --- a/websiteFunctions/templates/websiteFunctions/modifyWebsite.html +++ b/websiteFunctions/templates/websiteFunctions/modifyWebsite.html @@ -463,6 +463,31 @@ +
+ +
+ + +
+ {% trans "Current:" %} {$ currentHomeDirectory $} +
+
+ +
+
{{selectedHomeDirectoryInfo.name}}
+
+ {{selectedHomeDirectoryInfo.description || 'No description available'}}
+ Available Space: {{selectedHomeDirectoryInfo.available_space | filesize}} | Users: {{selectedHomeDirectoryInfo.user_count}} +
+
+
+
+