Version {{ version }}
{% trans "Settings page for My First Plugin" %}
{% load i18n %}
{% trans "Hello, world!" %}
{% url 'myPlugin:main' %} {{ variable }} {{ object.attribute }} {{ object.method }} {{ text|upper }} {{ text|truncatewords:10 }} {{ date|date:"Y-m-d" }} {% if condition %} {% elif other_condition %} {% else %} {% endif %} {% for item in items %}{{ item }}
{% empty %}No items
{% endfor %} ``` ### 5. Static Files #### Organizing Static Files ``` static/ └── pluginName/ ├── css/ │ └── style.css ├── js/ │ └── script.js └── images/ └── logo.png ``` #### Using Static Files in Templates ```html {% load static %}
```
#### Collecting Static Files
After installation, static files are automatically collected. To manually collect:
```bash
cd /usr/local/CyberCP
python3 manage.py collectstatic --noinput
```
### 6. Database Models
#### Creating Models
```python
# models.py
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
class Meta:
db_table = 'my_plugin_mymodel'
ordering = ['-created_at']
verbose_name = 'My Model'
verbose_name_plural = 'My Models'
def __str__(self):
return self.name
```
#### Using Models in Views
```python
from .models import MyModel
@cyberpanel_login_required
def list_items(request):
items = MyModel.objects.filter(is_active=True)
context = {'items': items}
return render(request, 'myPlugin/list.html', context)
@cyberpanel_login_required
def create_item(request):
if request.method == 'POST':
name = request.POST.get('name')
description = request.POST.get('description')
item = MyModel.objects.create(
name=name,
description=description
)
return redirect('myPlugin:list')
return render(request, 'myPlugin/create.html')
```
#### Database Migrations
```bash
# Create migrations
cd /usr/local/CyberCP
python3 manage.py makemigrations pluginName
# Apply migrations
python3 manage.py migrate pluginName
# Show migration status
python3 manage.py showmigrations pluginName
```
---
## Advanced Features
### 1. Forms & Validation
#### Creating Forms
```python
# forms.py
from django import forms
class MyForm(forms.Form):
name = forms.CharField(
max_length=255,
required=True,
widget=forms.TextInput(attrs={'class': 'form-control'})
)
email = forms.EmailField(
required=True,
widget=forms.EmailInput(attrs={'class': 'form-control'})
)
description = forms.CharField(
required=False,
widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 5})
)
```
#### Using Forms in Views
```python
from .forms import MyForm
@cyberpanel_login_required
def my_form_view(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
# Process valid form data
name = form.cleaned_data['name']
email = form.cleaned_data['email']
# Save or process data
return JsonResponse({'success': True})
else:
# Return form errors
return JsonResponse({'success': False, 'errors': form.errors})
else:
form = MyForm()
context = {'form': form}
return render(request, 'myPlugin/form.html', context)
```
#### Rendering Forms in Templates
```html
```
### 2. AJAX & API Endpoints
#### Creating API Endpoints
```python
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
import json
@cyberpanel_login_required
@csrf_exempt # Only if not using CSRF token in AJAX
@require_http_methods(["POST"])
def api_endpoint(request):
try:
data = json.loads(request.body)
# Process data
result = {
'success': True,
'message': 'Operation completed',
'data': data
}
return JsonResponse(result)
except Exception as e:
return JsonResponse({
'success': False,
'error': str(e)
}, status=400)
```
#### JavaScript AJAX Example
```javascript
function sendAjaxRequest(data) {
// Get CSRF token
const csrftoken = getCookie('csrftoken');
fetch('/plugins/myPlugin/api/', {
method: 'POST',
headers: {
'X-CSRFToken': csrftoken,
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Success:', data.message);
} else {
console.error('Error:', data.error);
}
})
.catch(error => {
console.error('Request failed:', error);
});
}
```
### 3. File Uploads
#### Handling File Uploads
```python
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
@cyberpanel_login_required
def upload_file(request):
if request.method == 'POST' and request.FILES.get('file'):
uploaded_file = request.FILES['file']
# Validate file
if uploaded_file.size > 10 * 1024 * 1024: # 10MB limit
return JsonResponse({'success': False, 'error': 'File too large'})
# Save file
file_path = f'myPlugin/uploads/{uploaded_file.name}'
path = default_storage.save(file_path, ContentFile(uploaded_file.read()))
return JsonResponse({
'success': True,
'file_path': path
})
return JsonResponse({'success': False, 'error': 'No file provided'})
```
### 4. Logging
#### Using CyberPanel's Logging System
```python
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
# Write to log file
logging.writeToFile("Plugin message: Something happened")
# Write error
logging.writeToFile(f"Error: {str(exception)}", 1) # 1 = error level
# Write with plugin name
logging.writeToFile(f"[MyPlugin] Action completed successfully")
```
### 5. Background Tasks
#### Using Subprocess for Long-Running Tasks
```python
import subprocess
import threading
def run_background_task(command):
"""Run a command in the background"""
def task():
try:
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True
)
logging.writeToFile(f"Task completed: {result.stdout}")
except Exception as e:
logging.writeToFile(f"Task error: {str(e)}", 1)
thread = threading.Thread(target=task)
thread.daemon = True
thread.start()
return thread
```
---
## Best Practices
### 1. Code Organization
- **Keep files under 500 lines**: Split large files into modules
- **Use descriptive names**: Functions, variables, and classes should be self-documenting
- **Follow PEP 8**: Python style guide
- **Add comments**: Explain complex logic
- **Modular structure**: Separate concerns (views, models, utils)
### 2. Error Handling
```python
from django.http import JsonResponse
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
@cyberpanel_login_required
def my_view(request):
try:
# Your code here
result = perform_operation()
return JsonResponse({'success': True, 'data': result})
except ValueError as e:
logging.writeToFile(f"Validation error: {str(e)}", 1)
return JsonResponse({'success': False, 'error': str(e)}, status=400)
except Exception as e:
logging.writeToFile(f"Unexpected error: {str(e)}", 1)
return JsonResponse({'success': False, 'error': 'An error occurred'}, status=500)
```
### 3. Security Best Practices
- **Always validate input**: Never trust user input
- **Use parameterized queries**: When using raw SQL
- **Sanitize output**: Escape HTML in templates
- **Check permissions**: Verify user has access
- **Use HTTPS**: For sensitive operations
- **Rate limiting**: Prevent abuse
- **CSRF protection**: Always include CSRF tokens
### 4. Performance Optimization
- **Database queries**: Use `select_related()` and `prefetch_related()`
- **Caching**: Cache expensive operations
- **Lazy loading**: Load data only when needed
- **Pagination**: For large datasets
- **Static files**: Minify CSS/JS in production
### 5. Testing
```python
# tests.py
from django.test import TestCase, Client
from django.urls import reverse
class MyPluginTests(TestCase):
def setUp(self):
self.client = Client()
# Set up test data
def test_main_view(self):
# Test main view
response = self.client.get(reverse('myPlugin:main'))
self.assertEqual(response.status_code, 200)
def test_api_endpoint(self):
# Test API endpoint
response = self.client.post(
reverse('myPlugin:api'),
data={'key': 'value'},
content_type='application/json'
)
self.assertEqual(response.status_code, 200)
```
---
## Security Guidelines
### 1. Input Validation
```python
import re
from django.core.exceptions import ValidationError
def validate_input(data):
"""Validate and sanitize user input"""
if not data:
raise ValidationError("Input cannot be empty")
# Remove dangerous characters
data = re.sub(r'[<>"\']', '', data)
# Check length
if len(data) > 1000:
raise ValidationError("Input too long")
return data.strip()
```
### 2. SQL Injection Prevention
**Always use Django ORM (recommended):**
```python
# ✅ GOOD - Using ORM
items = MyModel.objects.filter(name=user_input)
# ❌ BAD - Raw SQL with string formatting
items = MyModel.objects.raw(f"SELECT * FROM table WHERE name = '{user_input}'")
```
**If using raw SQL, use parameterized queries:**
```python
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT * FROM table WHERE name = %s", [user_input])
```
### 3. XSS Prevention
**Django templates auto-escape by default:**
```html
{{ user_input }}
{{ user_input|safe }}
```
**Only use `|safe` if you're certain the content is safe:**
```python
from django.utils.html import escape
# Escape in Python
safe_html = escape(user_input)
```
### 4. File Upload Security
```python
import os
from django.core.exceptions import ValidationError
ALLOWED_EXTENSIONS = ['.jpg', '.png', '.pdf']
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
def validate_uploaded_file(file):
"""Validate uploaded file"""
# Check extension
ext = os.path.splitext(file.name)[1].lower()
if ext not in ALLOWED_EXTENSIONS:
raise ValidationError(f"File type {ext} not allowed")
# Check size
if file.size > MAX_FILE_SIZE:
raise ValidationError("File too large")
# Check content type
if file.content_type not in ['image/jpeg', 'image/png', 'application/pdf']:
raise ValidationError("Invalid file type")
return True
```
---
## Testing & Debugging
### 1. Debugging Tools
#### Enable Django Debug Mode (Development Only)
```python
# In your view
import logging
logger = logging.getLogger(__name__)
def my_view(request):
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
```
#### Check Logs
```bash
# CyberPanel logs
tail -f /usr/local/lscp/logs/error.log
# Django logs (if configured)
tail -f /var/log/cyberpanel/error.log
# Plugin-specific logs
tail -f /home/cyberpanel/plugin_logs/myPlugin.log
```
### 2. Common Issues & Solutions
#### Template Not Found
**Problem:** `TemplateDoesNotExist` error
**Solutions:**
- Check template path: `templates/pluginName/template.html`
- Verify template name in `render()` call
- Ensure template extends `baseTemplate/index.html`
- Run `python3 manage.py collectstatic`
#### URL Not Found
**Problem:** 404 error when accessing plugin URL
**Solutions:**
- Verify URL pattern in `urls.py`
- Check `app_name` is set correctly
- Ensure plugin is in `INSTALLED_APPS`
- Restart CyberPanel: `systemctl restart lscpd`
#### Import Errors
**Problem:** `ImportError` or `ModuleNotFoundError`
**Solutions:**
- Check Python syntax: `python3 -m py_compile views.py`
- Verify `__init__.py` exists
- Check import paths
- Ensure plugin is installed correctly
#### Static Files Not Loading
**Problem:** CSS/JS/images not appearing
**Solutions:**
- Run `python3 manage.py collectstatic --noinput`
- Check static file paths in templates
- Verify files exist in `static/pluginName/`
- Clear browser cache
---
## Packaging & Distribution
### 1. Creating Plugin Package
```bash
# Navigate to plugin directory
cd /home/cyberpanel/plugins/myPlugin
# Create ZIP file
zip -r myPlugin-v1.0.0.zip . \
-x "*.pyc" \
-x "__pycache__/*" \
-x "*.log" \
-x ".git/*" \
-x ".DS_Store"
```
### 2. Plugin Distribution Checklist
- [ ] Plugin tested and working
- [ ] All required files included
- [ ] `meta.xml` is valid and complete
- [ ] README.md with installation instructions
- [ ] No sensitive data (passwords, API keys)
- [ ] Proper file permissions
- [ ] Version number updated
- [ ] Documentation complete
### 3. Version Management
**Semantic Versioning:**
- **MAJOR.MINOR.PATCH** (e.g., 1.2.3)
- **MAJOR**: Breaking changes
- **MINOR**: New features, backward compatible
- **PATCH**: Bug fixes, backward compatible
**Update version in:**
- `meta.xml`
- `views.py` (if version displayed)
- `README.md`
- Git tags (if using version control)
---
## Troubleshooting
### Installation Issues
**Plugin not appearing in list:**
- Check `meta.xml` format and validity
- Verify plugin directory exists in `/home/cyberpanel/plugins/`
- Check file permissions
- Review CyberPanel logs
**Installation fails:**
- Check Python syntax errors
- Verify all required files exist
- Check file permissions
- Review installation logs
- Ensure sufficient disk space
### Runtime Issues
**Plugin page not loading:**
- Verify URL routing
- Check authentication decorator
- Review template paths
- Check for JavaScript errors
- Verify plugin is enabled
**Database errors:**
- Run migrations: `python3 manage.py migrate pluginName`
- Check database permissions
- Verify model definitions
- Review migration files
**Static files missing:**
- Run `python3 manage.py collectstatic`
- Check static file paths
- Verify file permissions
- Clear browser cache
---
## Examples & References
### Reference Plugins
1. **examplePlugin**: Basic plugin structure
- Location: `/usr/local/CyberCP/examplePlugin/`
- URL: `/plugins/examplePlugin/`
2. **testPlugin**: Comprehensive example
- Location: `/usr/local/CyberCP/testPlugin/`
- URL: `/plugins/testPlugin/`
- **Author:** usmannasir
3. **discordWebhooks**: Discord webhook integration plugin
- Location: `/usr/local/CyberCP/discordWebhooks/` (if installed)
- URL: `/plugins/discordWebhooks/`
- **Author:** Master3395
### Useful Resources
- **CyberPanel Documentation**: https://cyberpanel.net/KnowledgeBase/
- **Django Documentation**: https://docs.djangoproject.com/
- **Python Documentation**: https://docs.python.org/
- **CyberPanel GitHub**: https://github.com/usmannasir/cyberpanel
- **Plugin Repository**: https://github.com/master3395/cyberpanel-plugins
### Code Examples Repository
Check the `examplePlugin` and `testPlugin` directories in CyberPanel for complete working examples.
---
## Conclusion
This guide provides comprehensive information for developing CyberPanel plugins. Start with a simple plugin and gradually add more features as you become familiar with the system.
### Quick Start Checklist
1. ✅ Create plugin directory structure
2. ✅ Create `meta.xml` with required fields
3. ✅ Create `urls.py` with URL patterns
4. ✅ Create `views.py` with view functions
5. ✅ Create templates extending `baseTemplate/index.html`
6. ✅ Test plugin locally
7. ✅ Install via CyberPanel UI
8. ✅ Verify plugin works correctly
### Getting Help
- Review existing plugins for examples
- Check CyberPanel community forum
- Review Django documentation
- Examine CyberPanel source code
- Create GitHub issues for bugs
---
**Happy Plugin Development!**
**Author:** master3395
**Last Updated:** 2026-01-04
**Version:** 2.0.0