mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-06 19:06:46 +02:00
fix: Rspamd installer, Email Delivery migrations, dns sys.path
- mailUtilities: insert CyberCP first on sys.path (dnspython dns shadowing); Rspamd log under /var/log/cyberpanel; log before ServiceManager; dnf on EL8/9; append package stderr - emailPremium: Rspamd admin UI without cloud addon gate; JsonResponse; fetchRspamdSettings unlocked - emailDelivery: AutoField PKs; 0001_initial SeparateDatabaseAndState for int FK to loginSystem
This commit is contained in:
128
emailDelivery/migrations/0001_initial.py
Normal file
128
emailDelivery/migrations/0001_initial.py
Normal file
@@ -0,0 +1,128 @@
|
||||
# CyberMail Email Delivery — initial schema.
|
||||
# Database DDL uses int(11) FK to legacy loginSystem_administrator.id (MariaDB rejects bigint FK -> int PK).
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
CREATE_CYBERMAIL_TABLES = '''
|
||||
CREATE TABLE `cybermail_accounts` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`platform_account_id` int(11) DEFAULT NULL,
|
||||
`api_key` varchar(255) NOT NULL,
|
||||
`email` varchar(255) NOT NULL,
|
||||
`plan_name` varchar(100) NOT NULL,
|
||||
`plan_slug` varchar(50) NOT NULL,
|
||||
`emails_per_month` int(11) NOT NULL,
|
||||
`is_connected` tinyint(1) NOT NULL,
|
||||
`relay_enabled` tinyint(1) NOT NULL,
|
||||
`smtp_credential_id` int(11) DEFAULT NULL,
|
||||
`smtp_username` varchar(255) NOT NULL,
|
||||
`smtp_host` varchar(255) NOT NULL,
|
||||
`smtp_port` int(11) NOT NULL,
|
||||
`created_at` datetime(6) NOT NULL,
|
||||
`updated_at` datetime(6) NOT NULL,
|
||||
`admin_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `cybermail_accounts_admin_id_uniq` (`admin_id`),
|
||||
CONSTRAINT `cybermail_accounts_admin_id_fk` FOREIGN KEY (`admin_id`)
|
||||
REFERENCES `loginSystem_administrator` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE `cybermail_domains` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain` varchar(255) NOT NULL,
|
||||
`platform_domain_id` int(11) DEFAULT NULL,
|
||||
`status` varchar(50) NOT NULL,
|
||||
`spf_verified` tinyint(1) NOT NULL,
|
||||
`dkim_verified` tinyint(1) NOT NULL,
|
||||
`dmarc_verified` tinyint(1) NOT NULL,
|
||||
`dns_configured` tinyint(1) NOT NULL,
|
||||
`created_at` datetime(6) NOT NULL,
|
||||
`account_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `cybermail_domains_account_id_fk` (`account_id`),
|
||||
CONSTRAINT `cybermail_domains_account_id_fk` FOREIGN KEY (`account_id`)
|
||||
REFERENCES `cybermail_accounts` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
'''
|
||||
|
||||
DROP_CYBERMAIL_TABLES = '''
|
||||
DROP TABLE IF EXISTS `cybermail_domains`;
|
||||
DROP TABLE IF EXISTS `cybermail_accounts`;
|
||||
'''
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('loginSystem', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.SeparateDatabaseAndState(
|
||||
database_operations=[
|
||||
migrations.RunSQL(CREATE_CYBERMAIL_TABLES, DROP_CYBERMAIL_TABLES),
|
||||
],
|
||||
state_operations=[
|
||||
migrations.CreateModel(
|
||||
name='CyberMailAccount',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('platform_account_id', models.IntegerField(null=True)),
|
||||
('api_key', models.CharField(blank=True, max_length=255)),
|
||||
('email', models.CharField(max_length=255)),
|
||||
('plan_name', models.CharField(default='Free', max_length=100)),
|
||||
('plan_slug', models.CharField(default='free', max_length=50)),
|
||||
('emails_per_month', models.IntegerField(default=15000)),
|
||||
('is_connected', models.BooleanField(default=False)),
|
||||
('relay_enabled', models.BooleanField(default=False)),
|
||||
('smtp_credential_id', models.IntegerField(null=True)),
|
||||
('smtp_username', models.CharField(blank=True, max_length=255)),
|
||||
('smtp_host', models.CharField(default='mail.cyberpersons.com', max_length=255)),
|
||||
('smtp_port', models.IntegerField(default=587)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
'admin',
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='cybermail_account',
|
||||
to='loginSystem.administrator',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'db_table': 'cybermail_accounts',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CyberMailDomain',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('domain', models.CharField(max_length=255)),
|
||||
('platform_domain_id', models.IntegerField(null=True)),
|
||||
('status', models.CharField(default='pending', max_length=50)),
|
||||
('spf_verified', models.BooleanField(default=False)),
|
||||
('dkim_verified', models.BooleanField(default=False)),
|
||||
('dmarc_verified', models.BooleanField(default=False)),
|
||||
('dns_configured', models.BooleanField(default=False)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
(
|
||||
'account',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='domains',
|
||||
to='emailDelivery.cybermailaccount',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'db_table': 'cybermail_domains',
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
# CyberMail Email Delivery migrations
|
||||
|
||||
@@ -3,6 +3,8 @@ from loginSystem.models import Administrator
|
||||
|
||||
|
||||
class CyberMailAccount(models.Model):
|
||||
# int(11) PK/FK to match legacy loginSystem_administrator.id (not DEFAULT_AUTO_FIELD BigAutoField)
|
||||
id = models.AutoField(primary_key=True)
|
||||
admin = models.OneToOneField(Administrator, on_delete=models.CASCADE, related_name='cybermail_account')
|
||||
platform_account_id = models.IntegerField(null=True)
|
||||
api_key = models.CharField(max_length=255, blank=True)
|
||||
@@ -27,6 +29,7 @@ class CyberMailAccount(models.Model):
|
||||
|
||||
|
||||
class CyberMailDomain(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
account = models.ForeignKey(CyberMailAccount, on_delete=models.CASCADE, related_name='domains')
|
||||
domain = models.CharField(max_length=255)
|
||||
platform_domain_id = models.IntegerField(null=True)
|
||||
|
||||
@@ -3,7 +3,7 @@ import os
|
||||
import time
|
||||
|
||||
from django.shortcuts import redirect
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
|
||||
from loginSystem.models import Administrator
|
||||
from mailServer.models import Domains, EUsers
|
||||
@@ -1233,32 +1233,28 @@ def installStatusMailScanner(request):
|
||||
###Rspamd
|
||||
|
||||
def Rspamd(request):
|
||||
url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission"
|
||||
data = {
|
||||
"name": "email-debugger",
|
||||
"IP": ACLManager.GetServerIP()
|
||||
}
|
||||
"""Rspamd UI — allow for any logged-in admin (do not require cloud addon permission)."""
|
||||
try:
|
||||
userID = request.session['userID']
|
||||
currentACL = ACLManager.loadedACL(userID)
|
||||
if currentACL['admin'] != 1:
|
||||
return ACLManager.loadError()
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
|
||||
import requests
|
||||
response = requests.post(url, data=json.dumps(data))
|
||||
Status = response.json()['status']
|
||||
checkIfRspamdInstalled = 0
|
||||
|
||||
if (Status == 1) or ProcessUtilities.decideServer() == ProcessUtilities.ent:
|
||||
checkIfRspamdInstalled = 0
|
||||
ipFile = "/etc/cyberpanel/machineIP"
|
||||
f = open(ipFile)
|
||||
ipData = f.read()
|
||||
ipAddress = ipData.split('\n', 1)[0]
|
||||
|
||||
ipFile = "/etc/cyberpanel/machineIP"
|
||||
f = open(ipFile)
|
||||
ipData = f.read()
|
||||
ipAddress = ipData.split('\n', 1)[0]
|
||||
if mailUtilities.checkIfRspamdInstalled() == 1:
|
||||
checkIfRspamdInstalled = 1
|
||||
|
||||
if mailUtilities.checkIfRspamdInstalled() == 1:
|
||||
checkIfRspamdInstalled = 1
|
||||
|
||||
proc = httpProc(request, 'emailPremium/Rspamd.html',
|
||||
{'checkIfRspamdInstalled': checkIfRspamdInstalled, 'ipAddress': ipAddress}, 'admin')
|
||||
return proc.render()
|
||||
else:
|
||||
return redirect("https://cyberpanel.net/cyberpanel-addons")
|
||||
proc = httpProc(request, 'emailPremium/Rspamd.html',
|
||||
{'checkIfRspamdInstalled': checkIfRspamdInstalled, 'ipAddress': ipAddress}, 'admin')
|
||||
return proc.render()
|
||||
|
||||
def installRspamd(request):
|
||||
try:
|
||||
@@ -1268,35 +1264,20 @@ def installRspamd(request):
|
||||
if currentACL['admin'] == 1:
|
||||
pass
|
||||
else:
|
||||
return ACLManager.loadErrorJson()
|
||||
return JsonResponse({'status': 0, 'error_message': 'Admin access required.'})
|
||||
|
||||
url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission"
|
||||
data = {
|
||||
"name": "email-debugger",
|
||||
"IP": ACLManager.GetServerIP()
|
||||
}
|
||||
|
||||
import requests
|
||||
response = requests.post(url, data=json.dumps(data))
|
||||
Status = response.json()['status']
|
||||
|
||||
if (Status == 1) or ProcessUtilities.decideServer() == ProcessUtilities.ent:
|
||||
try:
|
||||
|
||||
execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/mailUtilities.py"
|
||||
execPath = execPath + " installRspamd"
|
||||
ProcessUtilities.popenExecutioner(execPath)
|
||||
|
||||
final_json = json.dumps({'status': 1, 'error_message': "None"})
|
||||
return HttpResponse(final_json)
|
||||
except BaseException as msg:
|
||||
final_dic = {'status': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
try:
|
||||
execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/mailUtilities.py"
|
||||
execPath = execPath + " installRspamd"
|
||||
ProcessUtilities.popenExecutioner(execPath)
|
||||
return JsonResponse({'status': 1, 'error_message': 'None'})
|
||||
except BaseException as msg:
|
||||
return JsonResponse({'status': 0, 'error_message': str(msg)})
|
||||
except KeyError:
|
||||
final_dic = {'status': 0, 'error_message': "Not Logged In, please refresh the page or login again."}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
return JsonResponse({
|
||||
'status': 0,
|
||||
'error_message': 'Not Logged In, please refresh the page or login again.',
|
||||
})
|
||||
|
||||
def installStatusRspamd(request):
|
||||
try:
|
||||
@@ -1310,8 +1291,15 @@ def installStatusRspamd(request):
|
||||
try:
|
||||
if request.method == 'POST':
|
||||
|
||||
command = "sudo cat " + mailUtilities.RspamdInstallLogPath
|
||||
installStatus = ProcessUtilities.outputExecutioner(command)
|
||||
if not os.path.isfile(mailUtilities.RspamdInstallLogPath):
|
||||
installStatus = (
|
||||
'Waiting for installation to start... '
|
||||
'(Progress file: /var/log/cyberpanel/rspamd-install.log — if this persists, '
|
||||
'click Install again or run as root: tail -f /var/log/cyberpanel/rspamd-install.log)\n'
|
||||
)
|
||||
else:
|
||||
command = "sudo cat " + mailUtilities.RspamdInstallLogPath
|
||||
installStatus = ProcessUtilities.outputExecutioner(command)
|
||||
|
||||
if installStatus.find("[200]") > -1:
|
||||
|
||||
@@ -1365,19 +1353,8 @@ def fetchRspamdSettings(request):
|
||||
else:
|
||||
return ACLManager.loadErrorJson('fetchStatus', 0)
|
||||
|
||||
url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission"
|
||||
data = {
|
||||
"name": "email-debugger",
|
||||
"IP": ACLManager.GetServerIP()
|
||||
}
|
||||
|
||||
import requests
|
||||
response = requests.post(url, data=json.dumps(data))
|
||||
Status = response.json()['status']
|
||||
|
||||
if (Status == 1) or ProcessUtilities.decideServer() == ProcessUtilities.ent:
|
||||
try:
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
if request.method == 'POST':
|
||||
|
||||
enabled = True
|
||||
action = ''
|
||||
@@ -1577,10 +1554,10 @@ def fetchRspamdSettings(request):
|
||||
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
except BaseException as msg:
|
||||
final_dic = {'fetchStatus': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
except BaseException as msg:
|
||||
final_dic = {'fetchStatus': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
except KeyError:
|
||||
return redirect(loadLoginPage)
|
||||
|
||||
@@ -1747,21 +1724,17 @@ def unistallRspamd(request):
|
||||
ProcessUtilities.popenExecutioner(execPath)
|
||||
|
||||
|
||||
final_json = json.dumps({'status': 1, 'error_message': "None"})
|
||||
return HttpResponse(final_json)
|
||||
return JsonResponse({'status': 1, 'error_message': 'None'})
|
||||
except BaseException as msg:
|
||||
final_dic = {'status': 0, 'error_message': str(msg)}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
return JsonResponse({'status': 0, 'error_message': str(msg)})
|
||||
|
||||
|
||||
except KeyError:
|
||||
|
||||
final_dic = {'status': 0, 'error_message': "Not Logged In, please refresh the page or login again."}
|
||||
|
||||
final_json = json.dumps(final_dic)
|
||||
|
||||
return HttpResponse(final_json)
|
||||
return JsonResponse({
|
||||
'status': 0,
|
||||
'error_message': 'Not Logged In, please refresh the page or login again.',
|
||||
})
|
||||
|
||||
def uninstallStatusRspamd(request):
|
||||
try:
|
||||
@@ -1775,8 +1748,14 @@ def uninstallStatusRspamd(request):
|
||||
try:
|
||||
if request.method == 'POST':
|
||||
|
||||
command = "sudo cat " + mailUtilities.RspamdUnInstallLogPath
|
||||
installStatus = ProcessUtilities.outputExecutioner(command)
|
||||
if not os.path.isfile(mailUtilities.RspamdUnInstallLogPath):
|
||||
installStatus = (
|
||||
'Waiting for uninstall to start... '
|
||||
'(Progress file: /var/log/cyberpanel/rspamd-uninstall.log)\n'
|
||||
)
|
||||
else:
|
||||
command = "sudo cat " + mailUtilities.RspamdUnInstallLogPath
|
||||
installStatus = ProcessUtilities.outputExecutioner(command)
|
||||
|
||||
if installStatus.find("[200]") > -1:
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import json
|
||||
import os,sys
|
||||
import os, sys
|
||||
import time
|
||||
|
||||
# CyberPanel Django app "dns" must win over PyPI "dns" (dnspython). append() leaves site-packages first.
|
||||
_cybercp_root = '/usr/local/CyberCP'
|
||||
if _cybercp_root not in sys.path:
|
||||
sys.path.insert(0, _cybercp_root)
|
||||
|
||||
from django.http import HttpResponse
|
||||
|
||||
|
||||
|
||||
sys.path.append('/usr/local/CyberCP')
|
||||
import django
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
||||
try:
|
||||
@@ -37,8 +38,10 @@ class mailUtilities:
|
||||
|
||||
installLogPath = "/home/cyberpanel/openDKIMInstallLog"
|
||||
spamassassinInstallLogPath = "/home/cyberpanel/spamassassinInstallLogPath"
|
||||
RspamdInstallLogPath = "/home/cyberpanel/RspamdInstallLogPath"
|
||||
RspamdUnInstallLogPath = "/home/cyberpanel/RspamdUnInstallLogPath"
|
||||
# Use /var/log (not /home/cyberpanel mode 0700) so lscpd workers can always write install progress.
|
||||
rspamdLogDir = "/var/log/cyberpanel"
|
||||
RspamdInstallLogPath = "/var/log/cyberpanel/rspamd-install.log"
|
||||
RspamdUnInstallLogPath = "/var/log/cyberpanel/rspamd-uninstall.log"
|
||||
cyberPanelHome = "/home/cyberpanel"
|
||||
mailScannerInstallLogPath = "/home/cyberpanel/mailScannerInstallLogPath"
|
||||
RSpamdLogPath = '/var/log/rspamd/rspamd.log'
|
||||
@@ -822,12 +825,16 @@ return custom_keywords
|
||||
|
||||
@staticmethod
|
||||
def installRspamd(install, rspamd):
|
||||
# Progress file before ServiceManager import (import can fail; panel polls this path).
|
||||
os.makedirs(mailUtilities.rspamdLogDir, mode=0o755, exist_ok=True)
|
||||
if not os.path.isdir(mailUtilities.cyberPanelHome):
|
||||
os.makedirs(mailUtilities.cyberPanelHome, mode=0o750, exist_ok=True)
|
||||
with open(mailUtilities.RspamdInstallLogPath, 'w') as lf:
|
||||
lf.write('Starting Rspamd installation (preparing Redis and packages)...\n')
|
||||
lf.flush()
|
||||
|
||||
from manageServices.serviceManager import ServiceManager
|
||||
try:
|
||||
if os.path.exists(mailUtilities.RspamdInstallLogPath):
|
||||
os.remove(mailUtilities.RspamdInstallLogPath)
|
||||
|
||||
|
||||
####Frist install redis
|
||||
ServiceManager.InstallRedis()
|
||||
|
||||
@@ -862,16 +869,18 @@ return custom_keywords
|
||||
command = 'rpm --import https://rspamd.com/rpm-stable/gpg.key'
|
||||
ProcessUtilities.normalExecutioner(command, True)
|
||||
|
||||
command = 'yum update'
|
||||
command = 'dnf update -y'
|
||||
ProcessUtilities.normalExecutioner(command, True)
|
||||
|
||||
command = 'sudo yum install rspamd clamav clamd clamav-update -y'
|
||||
command = 'sudo dnf install -y rspamd clamav clamd clamav-update'
|
||||
else:
|
||||
command = 'DEBIAN_FRONTEND=noninteractive apt-get install rspamd clamav clamav-daemon -y'
|
||||
|
||||
|
||||
with open(mailUtilities.RspamdInstallLogPath, 'w') as f:
|
||||
res = subprocess.call(command, stdout=f, shell=True)
|
||||
with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
|
||||
f.write('\n--- Package install ---\n')
|
||||
f.flush()
|
||||
res = subprocess.call(command, stdout=f, stderr=f, shell=True)
|
||||
|
||||
|
||||
###### makefile
|
||||
@@ -1119,6 +1128,16 @@ LogFile /var/log/clamav/clamav.log
|
||||
if os.path.exists(mailUtilities.RspamdUnInstallLogPath):
|
||||
os.remove(mailUtilities.RspamdUnInstallLogPath)
|
||||
|
||||
try:
|
||||
os.makedirs(mailUtilities.rspamdLogDir, mode=0o755, exist_ok=True)
|
||||
if not os.path.isdir(mailUtilities.cyberPanelHome):
|
||||
os.makedirs(mailUtilities.cyberPanelHome, mode=0o750, exist_ok=True)
|
||||
with open(mailUtilities.RspamdUnInstallLogPath, 'w') as lf:
|
||||
lf.write('Starting Rspamd removal...\n')
|
||||
lf.flush()
|
||||
except BaseException as log_err:
|
||||
logging.CyberCPLogFileWriter.writeToFile(
|
||||
str(log_err) + ' [uninstallRspamd init log]')
|
||||
|
||||
if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
|
||||
command = 'sudo yum remove rspamd clamav clamav-daemon -y'
|
||||
@@ -1129,7 +1148,7 @@ LogFile /var/log/clamav/clamav.log
|
||||
|
||||
|
||||
|
||||
with open(mailUtilities.RspamdUnInstallLogPath, 'w') as f:
|
||||
with open(mailUtilities.RspamdUnInstallLogPath, 'a') as f:
|
||||
res = subprocess.call(cmd, stdout=f)
|
||||
if res == 1:
|
||||
writeToFile = open(mailUtilities.RspamdUnInstallLogPath, 'a')
|
||||
|
||||
Reference in New Issue
Block a user