mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-11-15 09:46:11 +01:00
Add subdomain log fix functionality and update templates. Introduce new views and URLs for fixing subdomain logs, enhance log configuration handling in the upgrade script, and update vHost configuration paths for better log management. Include a new menu item for accessing the log fix interface.
This commit is contained in:
@@ -13289,6 +13289,16 @@ app.controller('manageAliasController', function ($scope, $http, $timeout, $wind
|
||||
$scope.manageAliasLoading = true;
|
||||
$scope.operationSuccess = true;
|
||||
|
||||
// Initialize the page to show aliases list
|
||||
$scope.showAliasesList = function() {
|
||||
$scope.aliasTable = true;
|
||||
$scope.addAliasButton = true;
|
||||
$scope.domainAliasForm = false;
|
||||
};
|
||||
|
||||
// Auto-show aliases list on page load
|
||||
$scope.showAliasesList();
|
||||
|
||||
$scope.createAliasEnter = function ($event) {
|
||||
var keyCode = $event.which || $event.keyCode;
|
||||
if (keyCode === 13) {
|
||||
@@ -13536,6 +13546,64 @@ app.controller('manageAliasController', function ($scope, $http, $timeout, $wind
|
||||
|
||||
};
|
||||
|
||||
$scope.issueAliasSSL = function (masterDomain, aliasDomain) {
|
||||
$scope.manageAliasLoading = false;
|
||||
|
||||
url = "/websites/issueAliasSSL";
|
||||
|
||||
var data = {
|
||||
masterDomain: masterDomain,
|
||||
aliasDomain: aliasDomain
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
|
||||
|
||||
function ListInitialDatas(response) {
|
||||
if (response.data.issueAliasSSL === 1) {
|
||||
$scope.aliasTable = false;
|
||||
$scope.addAliasButton = true;
|
||||
$scope.domainAliasForm = true;
|
||||
$scope.aliasError = true;
|
||||
$scope.couldNotConnect = true;
|
||||
$scope.aliasCreated = true;
|
||||
$scope.manageAliasLoading = true;
|
||||
$scope.operationSuccess = false;
|
||||
|
||||
$timeout(function () {
|
||||
$window.location.reload();
|
||||
}, 3000);
|
||||
} else {
|
||||
$scope.aliasTable = false;
|
||||
$scope.addAliasButton = true;
|
||||
$scope.domainAliasForm = true;
|
||||
$scope.aliasError = false;
|
||||
$scope.couldNotConnect = true;
|
||||
$scope.aliasCreated = true;
|
||||
$scope.manageAliasLoading = true;
|
||||
$scope.operationSuccess = true;
|
||||
|
||||
$scope.errorMessage = response.data.error_message;
|
||||
}
|
||||
}
|
||||
|
||||
function cantLoadInitialDatas(response) {
|
||||
$scope.aliasTable = false;
|
||||
$scope.addAliasButton = true;
|
||||
$scope.domainAliasForm = true;
|
||||
$scope.aliasError = true;
|
||||
$scope.couldNotConnect = false;
|
||||
$scope.aliasCreated = true;
|
||||
$scope.manageAliasLoading = true;
|
||||
$scope.operationSuccess = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////// create domain part
|
||||
|
||||
|
||||
@@ -175,37 +175,52 @@
|
||||
|
||||
|
||||
<div class="col-sm-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Domain</th>
|
||||
<th>Launch</th>
|
||||
<th>Path</th>
|
||||
<th>SSL</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="record in childDomains | filter:logSearch">
|
||||
<td ng-bind="record.childDomain"></td>
|
||||
<td><a href="{$ record.childLunch $}"><img width="30px" height="30"
|
||||
class="center-block"
|
||||
src="{% static 'baseTemplate/assets/image-resources/webPanel.png' %}"></a>
|
||||
</td>
|
||||
<td ng-bind="record.path"></td>
|
||||
<td>
|
||||
<button type="button"
|
||||
ng-click="issueSSL(record.childDomain,record.path)"
|
||||
class="btn ra-50 btn-primary">{% trans "Issue" %}</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
ng-click="deleteChildDomain(record.childDomain)"
|
||||
class="btn ra-50 btn-primary">{% trans "Delete" %}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- Show message when no aliases exist -->
|
||||
<div ng-hide="{{ noAlias }}" class="alert alert-info">
|
||||
<p>{% trans "No domain aliases found for this domain." %}</p>
|
||||
</div>
|
||||
|
||||
<!-- Show aliases table when aliases exist -->
|
||||
<div ng-show="{{ noAlias }}">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Alias Domain" %}</th>
|
||||
<th>{% trans "Master Domain" %}</th>
|
||||
<th>{% trans "Launch" %}</th>
|
||||
<th>{% trans "SSL" %}</th>
|
||||
<th>{% trans "Delete" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for alias in aliases %}
|
||||
<tr>
|
||||
<td>{{ alias }}</td>
|
||||
<td>{{ masterDomain }}</td>
|
||||
<td>
|
||||
<a href="http://{{ alias }}" target="_blank">
|
||||
<img width="30px" height="30" class="center-block"
|
||||
src="{% static 'baseTemplate/assets/image-resources/webPanel.png' %}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
ng-click="issueAliasSSL('{{ masterDomain }}', '{{ alias }}')"
|
||||
class="btn ra-50 btn-primary">{% trans "Issue SSL" %}</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
ng-click="removeAlias('{{ masterDomain }}', '{{ alias }}')"
|
||||
class="btn ra-50 btn-danger"
|
||||
onclick="return confirm('{% trans "Are you sure you want to delete this alias?" %}')">
|
||||
{% trans "Delete" %}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,334 @@
|
||||
{% extends "baseTemplate/index.html" %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}Fix Subdomain Logs{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0">Fix Subdomain Logs</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="{% url 'loadWebsitesHome' %}">Websites</a></li>
|
||||
<li class="breadcrumb-item active">Fix Subdomain Logs</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Information Card -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Subdomain Log Issue Fix</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-info">
|
||||
<h5><i class="icon fas fa-info"></i> Issue Description</h5>
|
||||
<p>This tool fixes a known issue where child domains (subdomains) share log files with their master domains, causing log contamination. This fix ensures each subdomain has its own separate log files.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<h5><i class="icon fas fa-exclamation-triangle"></i> What This Fix Does</h5>
|
||||
<ul>
|
||||
<li>Updates vHost configurations to use separate log files for each subdomain</li>
|
||||
<li>Creates individual log files: <code>subdomain.error_log</code> and <code>subdomain.access_log</code></li>
|
||||
<li>Restarts LiteSpeed to apply changes</li>
|
||||
<li>Maintains proper file ownership and permissions</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fix Options -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Fix Options</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="fixLogsForm">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label>Action</label>
|
||||
<select class="form-control" id="action" name="action" required>
|
||||
<option value="">Select Action</option>
|
||||
<option value="fix_all">Fix All Child Domains</option>
|
||||
<option value="fix_domain">Fix Specific Domain</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6" id="domainInputGroup" style="display: none;">
|
||||
<div class="form-group">
|
||||
<label>Domain Name</label>
|
||||
<input type="text" class="form-control" id="domain" name="domain" placeholder="e.g., diabetes.example.com">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="dryRun" name="dry_run">
|
||||
<label class="form-check-label" for="dryRun">
|
||||
Dry Run (Show what would be changed without making changes)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="createBackup" name="create_backup">
|
||||
<label class="form-check-label" for="createBackup">
|
||||
Create Backup of Original Configuration
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="fixButton">
|
||||
<i class="fas fa-wrench"></i> Fix Subdomain Logs
|
||||
</button>
|
||||
<button type="button" class="btn btn-info" id="checkButton">
|
||||
<i class="fas fa-search"></i> Check Current Status
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Results -->
|
||||
<div class="card card-default" id="resultsCard" style="display: none;">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Results</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="resultsContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Child Domains List -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Current Child Domains</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped" id="childDomainsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Domain</th>
|
||||
<th>Master Domain</th>
|
||||
<th>Log Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Will be populated by JavaScript -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const actionSelect = document.getElementById('action');
|
||||
const domainInputGroup = document.getElementById('domainInputGroup');
|
||||
const domainInput = document.getElementById('domain');
|
||||
const fixButton = document.getElementById('fixButton');
|
||||
const checkButton = document.getElementById('checkButton');
|
||||
const resultsCard = document.getElementById('resultsCard');
|
||||
const resultsContent = document.getElementById('resultsContent');
|
||||
const childDomainsTable = document.getElementById('childDomainsTable');
|
||||
|
||||
// Show/hide domain input based on action selection
|
||||
actionSelect.addEventListener('change', function() {
|
||||
if (this.value === 'fix_domain') {
|
||||
domainInputGroup.style.display = 'block';
|
||||
domainInput.required = true;
|
||||
} else {
|
||||
domainInputGroup.style.display = 'none';
|
||||
domainInput.required = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Load child domains list
|
||||
loadChildDomains();
|
||||
|
||||
// Check current status
|
||||
checkButton.addEventListener('click', function() {
|
||||
loadChildDomains();
|
||||
showResults('Checking current status...', 'info');
|
||||
});
|
||||
|
||||
// Fix logs form submission
|
||||
document.getElementById('fixLogsForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(this);
|
||||
const action = formData.get('action');
|
||||
const domain = formData.get('domain');
|
||||
|
||||
if (!action) {
|
||||
showResults('Please select an action', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === 'fix_domain' && !domain.trim()) {
|
||||
showResults('Please enter a domain name', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
fixButton.disabled = true;
|
||||
fixButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
|
||||
|
||||
fetch('{% url "fixSubdomainLogsAction" %}', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
fixButton.disabled = false;
|
||||
fixButton.innerHTML = '<i class="fas fa-wrench"></i> Fix Subdomain Logs';
|
||||
|
||||
if (data.status === 1) {
|
||||
showResults(data.message, 'success');
|
||||
loadChildDomains(); // Refresh the list
|
||||
} else {
|
||||
showResults(data.error_message, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
fixButton.disabled = false;
|
||||
fixButton.innerHTML = '<i class="fas fa-wrench"></i> Fix Subdomain Logs';
|
||||
showResults('Error: ' + error.message, 'error');
|
||||
});
|
||||
});
|
||||
|
||||
function loadChildDomains() {
|
||||
fetch('{% url "fetchChildDomainsMain" %}')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 1) {
|
||||
populateChildDomainsTable(data.data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading child domains:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function populateChildDomainsTable(domains) {
|
||||
const tbody = childDomainsTable.querySelector('tbody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
domains.forEach(domain => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${domain.domain}</td>
|
||||
<td>${domain.master}</td>
|
||||
<td><span class="badge badge-warning">Needs Fix</span></td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-primary" onclick="fixSingleDomain('${domain.domain}')">
|
||||
<i class="fas fa-wrench"></i> Fix
|
||||
</button>
|
||||
</td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function fixSingleDomain(domain) {
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'fix_domain');
|
||||
formData.append('domain', domain);
|
||||
formData.append('dry_run', 'false');
|
||||
formData.append('create_backup', 'true');
|
||||
formData.append('csrfmiddlewaretoken', getCookie('csrftoken'));
|
||||
|
||||
showResults(`Fixing logs for ${domain}...`, 'info');
|
||||
|
||||
fetch('{% url "fixSubdomainLogsAction" %}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 1) {
|
||||
showResults(data.message, 'success');
|
||||
loadChildDomains(); // Refresh the list
|
||||
} else {
|
||||
showResults(data.error_message, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showResults('Error: ' + error.message, 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function showResults(message, type) {
|
||||
resultsCard.style.display = 'block';
|
||||
|
||||
let alertClass = 'alert-info';
|
||||
let icon = 'fas fa-info';
|
||||
|
||||
if (type === 'success') {
|
||||
alertClass = 'alert-success';
|
||||
icon = 'fas fa-check';
|
||||
} else if (type === 'error') {
|
||||
alertClass = 'alert-danger';
|
||||
icon = 'fas fa-times';
|
||||
} else if (type === 'warning') {
|
||||
alertClass = 'alert-warning';
|
||||
icon = 'fas fa-exclamation-triangle';
|
||||
}
|
||||
|
||||
resultsContent.innerHTML = `
|
||||
<div class="alert ${alertClass}">
|
||||
<i class="${icon}"></i> ${message}
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Scroll to results
|
||||
resultsCard.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -207,5 +207,9 @@ urlpatterns = [
|
||||
|
||||
path('get_website_resources/', views.get_website_resources, name='get_website_resources'),
|
||||
|
||||
# Subdomain Log Fix
|
||||
path('fixSubdomainLogs', views.fixSubdomainLogs, name='fixSubdomainLogs'),
|
||||
path('fixSubdomainLogsAction', views.fixSubdomainLogsAction, name='fixSubdomainLogsAction'),
|
||||
|
||||
|
||||
]
|
||||
|
||||
@@ -3936,6 +3936,7 @@ context /cyberpanel_suspension_page.html {
|
||||
if is_child:
|
||||
# Use child domain template
|
||||
default_config = vhostConfs.olsChildConf
|
||||
default_config = default_config.replace('{virtualHostName}', virtualHost)
|
||||
default_config = default_config.replace('{path}', path)
|
||||
default_config = default_config.replace('{masterDomain}', master_domain)
|
||||
default_config = default_config.replace('{adminEmails}', admin_email)
|
||||
@@ -8200,3 +8201,174 @@ StrictHostKeyChecking no
|
||||
json_data = json.dumps(data_ret)
|
||||
return HttpResponse(json_data)
|
||||
|
||||
def fixSubdomainLogs(self, request):
|
||||
"""Display subdomain log fix interface"""
|
||||
try:
|
||||
currentACL = ACLManager.loadedACL(request.user.pk)
|
||||
admin = ACLManager.loadedAdmin(request.user.pk)
|
||||
|
||||
if ACLManager.currentContextPermission(currentACL, 'websites') == 0:
|
||||
return ACLManager.loadErrorJson('websites', 0)
|
||||
|
||||
return render(request, 'websiteFunctions/fixSubdomainLogs.html', {
|
||||
'acls': currentACL,
|
||||
'admin': admin
|
||||
})
|
||||
|
||||
except BaseException as msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [fixSubdomainLogs]")
|
||||
return ACLManager.loadErrorJson('websites', 0)
|
||||
|
||||
def fixSubdomainLogsAction(self, request):
|
||||
"""Execute subdomain log fix"""
|
||||
try:
|
||||
currentACL = ACLManager.loadedACL(request.user.pk)
|
||||
admin = ACLManager.loadedAdmin(request.user.pk)
|
||||
|
||||
if ACLManager.currentContextPermission(currentACL, 'websites') == 0:
|
||||
return ACLManager.loadErrorJson('websites', 0)
|
||||
|
||||
action = request.POST.get('action')
|
||||
domain = request.POST.get('domain', '').strip()
|
||||
dry_run = request.POST.get('dry_run', 'false').lower() == 'true'
|
||||
create_backup = request.POST.get('create_backup', 'false').lower() == 'true'
|
||||
|
||||
if action == 'fix_all':
|
||||
# Fix all child domains
|
||||
from websiteFunctions.models import ChildDomains
|
||||
child_domains = ChildDomains.objects.all()
|
||||
fixed_count = 0
|
||||
failed_domains = []
|
||||
|
||||
for child_domain in child_domains:
|
||||
if self._fix_single_domain_logs(child_domain.domain, dry_run, create_backup):
|
||||
fixed_count += 1
|
||||
else:
|
||||
failed_domains.append(child_domain.domain)
|
||||
|
||||
if failed_domains:
|
||||
message = f"Fixed {fixed_count} domains. Failed: {', '.join(failed_domains)}"
|
||||
else:
|
||||
message = f"Successfully fixed {fixed_count} child domains"
|
||||
|
||||
data_ret = {'status': 1, 'message': message}
|
||||
|
||||
elif action == 'fix_domain' and domain:
|
||||
# Fix specific domain
|
||||
if self._fix_single_domain_logs(domain, dry_run, create_backup):
|
||||
data_ret = {'status': 1, 'message': f"Successfully fixed logs for {domain}"}
|
||||
else:
|
||||
data_ret = {'status': 0, 'error_message': f"Failed to fix logs for {domain}"}
|
||||
else:
|
||||
data_ret = {'status': 0, 'error_message': "Invalid action or missing domain"}
|
||||
|
||||
json_data = json.dumps(data_ret)
|
||||
return HttpResponse(json_data)
|
||||
|
||||
except BaseException as msg:
|
||||
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [fixSubdomainLogsAction]")
|
||||
data_ret = {'status': 0, 'error_message': str(msg)}
|
||||
json_data = json.dumps(data_ret)
|
||||
return HttpResponse(json_data)
|
||||
|
||||
def _fix_single_domain_logs(self, domain_name, dry_run=False, create_backup=False):
|
||||
"""Fix log configuration for a single domain"""
|
||||
try:
|
||||
import re
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from websiteFunctions.models import ChildDomains
|
||||
|
||||
# Get child domain info
|
||||
try:
|
||||
child_domain = ChildDomains.objects.get(domain=domain_name)
|
||||
master_domain = child_domain.master.domain
|
||||
domain_path = child_domain.path
|
||||
except ChildDomains.DoesNotExist:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Domain {domain_name} is not a child domain')
|
||||
return False
|
||||
|
||||
vhost_conf_path = f"/usr/local/lsws/conf/vhosts/{domain_name}/vhost.conf"
|
||||
|
||||
if not os.path.exists(vhost_conf_path):
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'VHost config not found for {domain_name}')
|
||||
return False
|
||||
|
||||
# Read current configuration
|
||||
with open(vhost_conf_path, 'r') as f:
|
||||
config_content = f.read()
|
||||
|
||||
# Check if fix is needed
|
||||
if f'{master_domain}.error_log' not in config_content and f'{master_domain}.access_log' not in config_content:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'{domain_name} already has correct log configuration')
|
||||
return True
|
||||
|
||||
if dry_run:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'[DRY RUN] Would fix log paths for {domain_name}')
|
||||
return True
|
||||
|
||||
# Create backup if requested
|
||||
if create_backup:
|
||||
backup_path = f"{vhost_conf_path}.backup.{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
shutil.copy2(vhost_conf_path, backup_path)
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Created backup: {backup_path}')
|
||||
|
||||
# Fix the configuration
|
||||
fixed_content = config_content
|
||||
|
||||
# Fix error log path
|
||||
fixed_content = re.sub(
|
||||
rf'errorlog\s+\$VH_ROOT/logs/{re.escape(master_domain)}\.error_log',
|
||||
f'errorlog $VH_ROOT/logs/{domain_name}.error_log',
|
||||
fixed_content
|
||||
)
|
||||
|
||||
# Fix access log path
|
||||
fixed_content = re.sub(
|
||||
rf'accesslog\s+\$VH_ROOT/logs/{re.escape(master_domain)}\.access_log',
|
||||
f'accesslog $VH_ROOT/logs/{domain_name}.access_log',
|
||||
fixed_content
|
||||
)
|
||||
|
||||
# Fix CustomLog paths (for Apache configurations)
|
||||
fixed_content = re.sub(
|
||||
rf'CustomLog\s+/home/{re.escape(master_domain)}/logs/{re.escape(master_domain)}\.access_log',
|
||||
f'CustomLog /home/{domain_name}/logs/{domain_name}.access_log',
|
||||
fixed_content
|
||||
)
|
||||
|
||||
# Write the fixed configuration
|
||||
with open(vhost_conf_path, 'w') as f:
|
||||
f.write(fixed_content)
|
||||
|
||||
# Set proper ownership
|
||||
ProcessUtilities.executioner(f'chown lsadm:lsadm {vhost_conf_path}')
|
||||
|
||||
# Create the log directory if it doesn't exist
|
||||
log_dir = f"/home/{master_domain}/logs"
|
||||
if not os.path.exists(log_dir):
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
ProcessUtilities.executioner(f'chown -R {child_domain.master.externalApp}:{child_domain.master.externalApp} {log_dir}')
|
||||
|
||||
# Create separate log files for the child domain
|
||||
error_log_path = f"{log_dir}/{domain_name}.error_log"
|
||||
access_log_path = f"{log_dir}/{domain_name}.access_log"
|
||||
|
||||
# Create empty log files if they don't exist
|
||||
for log_path in [error_log_path, access_log_path]:
|
||||
if not os.path.exists(log_path):
|
||||
with open(log_path, 'w') as f:
|
||||
f.write('')
|
||||
ProcessUtilities.executioner(f'chown {child_domain.master.externalApp}:{child_domain.master.externalApp} {log_path}')
|
||||
ProcessUtilities.executioner(f'chmod 644 {log_path}')
|
||||
|
||||
# Restart LiteSpeed to apply changes
|
||||
ProcessUtilities.executioner('systemctl restart lsws')
|
||||
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Fixed subdomain log configuration for {domain_name}')
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error fixing subdomain logs for {domain_name}: {str(e)}')
|
||||
return False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user