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}} +
+
+
+
+