Merge remote-tracking branch 'upstream/1.8.0' into 1.8.0

This commit is contained in:
Julio Rodríguez Cruz
2019-10-05 00:10:22 +02:00
13 changed files with 894 additions and 202 deletions

View File

@@ -60,7 +60,7 @@ class secMiddleware:
if request.build_absolute_uri().find('saveSpamAssassinConfigurations') > -1 or request.build_absolute_uri().find('docker') > -1 or request.build_absolute_uri().find('cloudAPI') > -1 or request.build_absolute_uri().find('filemanager') > -1 or request.build_absolute_uri().find('verifyLogin') > -1 or request.build_absolute_uri().find('submitUserCreation') > -1:
continue
if key == 'ports' or key == 'imageByPass' or key == 'passwordByPass' or key == 'cronCommand' or key == 'emailMessage' or key == 'configData' or key == 'rewriteRules' or key == 'modSecRules' or key == 'recordContentTXT' or key == 'SecAuditLogRelevantStatus' or key == 'fileContent':
if key == 'backupDestinations' or key == 'ports' or key == 'imageByPass' or key == 'passwordByPass' or key == 'cronCommand' or key == 'emailMessage' or key == 'configData' or key == 'rewriteRules' or key == 'modSecRules' or key == 'recordContentTXT' or key == 'SecAuditLogRelevantStatus' or key == 'fileContent':
continue
if value.find(';') > -1 or value.find('&&') > -1 or value.find('|') > -1 or value.find('...') > -1 \
or value.find("`") > -1 or value.find("$") > -1 or value.find("(") > -1 or value.find(")") > -1 \

375
IncBackups/IncBackups.py Normal file
View File

@@ -0,0 +1,375 @@
#!/usr/local/CyberCP/bin/python2
import os,sys
sys.path.append('/usr/local/CyberCP')
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
django.setup()
import threading as multi
from plogical.processUtilities import ProcessUtilities
import time
from .models import IncJob, JobSnapshots
from websiteFunctions.models import Websites
import plogical.randomPassword as randomPassword
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
from xml.etree.ElementTree import Element, SubElement
from xml.etree import ElementTree
from xml.dom import minidom
from backup.models import DBUsers
import plogical.mysqlUtilities as mysqlUtilities
from plogical.backupUtilities import backupUtilities
from plogical.dnsUtilities import DNS
from mailServer.models import Domains as eDomains
from random import randint
class IncJobs(multi.Thread):
def __init__(self, function, extraArgs):
multi.Thread.__init__(self)
self.function = function
self.extraArgs = extraArgs
self.repoPath = ''
self.passwordFile = ''
self.statusPath = ''
self.website = ''
self.backupDestinations = ''
self.jobid = 0
def run(self):
if self.function == 'createBackup':
self.createBackup()
def prepareBackupMeta(self):
try:
######### Generating meta
## XML Generation
metaFileXML = Element('metaFile')
child = SubElement(metaFileXML, 'masterDomain')
child.text = self.website.domain
child = SubElement(metaFileXML, 'phpSelection')
child.text = self.website.phpSelection
child = SubElement(metaFileXML, 'externalApp')
child.text = self.website.externalApp
childDomains = self.website.childdomains_set.all()
databases = self.website.databases_set.all()
## Child domains XML
childDomainsXML = Element('ChildDomains')
for items in childDomains:
childDomainXML = Element('domain')
child = SubElement(childDomainXML, 'domain')
child.text = items.domain
child = SubElement(childDomainXML, 'phpSelection')
child.text = items.phpSelection
child = SubElement(childDomainXML, 'path')
child.text = items.path
childDomainsXML.append(childDomainXML)
metaFileXML.append(childDomainsXML)
## Databases XML
databasesXML = Element('Databases')
for items in databases:
try:
dbuser = DBUsers.objects.get(user=items.dbUser)
userToTry = items.dbUser
except:
dbusers = DBUsers.objects.all().filter(user=items.dbUser)
userToTry = items.dbUser
for it in dbusers:
dbuser = it
break
userToTry = mysqlUtilities.mysqlUtilities.fetchuser(items.dbUser)
try:
dbuser = DBUsers.objects.get(user=userToTry)
except:
dbusers = DBUsers.objects.all().filter(user=userToTry)
for it in dbusers:
dbuser = it
break
databaseXML = Element('database')
child = SubElement(databaseXML, 'dbName')
child.text = items.dbName
child = SubElement(databaseXML, 'dbUser')
child.text = userToTry
child = SubElement(databaseXML, 'password')
child.text = dbuser.password
databasesXML.append(databaseXML)
metaFileXML.append(databasesXML)
## Get Aliases
aliasesXML = Element('Aliases')
aliases = backupUtilities.getAliases(self.website.domain)
for items in aliases:
child = SubElement(aliasesXML, 'alias')
child.text = items
metaFileXML.append(aliasesXML)
## Finish Alias
## DNS Records XML
try:
dnsRecordsXML = Element("dnsrecords")
dnsRecords = DNS.getDNSRecords(self.website.domain)
for items in dnsRecords:
dnsRecordXML = Element('dnsrecord')
child = SubElement(dnsRecordXML, 'type')
child.text = items.type
child = SubElement(dnsRecordXML, 'name')
child.text = items.name
child = SubElement(dnsRecordXML, 'content')
child.text = items.content
child = SubElement(dnsRecordXML, 'priority')
child.text = str(items.prio)
dnsRecordsXML.append(dnsRecordXML)
metaFileXML.append(dnsRecordsXML)
except BaseException, msg:
logging.statusWriter(self.statusPath, '%s. [158:prepMeta]' % (str(msg)), 1)
## Email accounts XML
try:
emailRecordsXML = Element('emails')
eDomain = eDomains.objects.get(domain=self.website.domain)
emailAccounts = eDomain.eusers_set.all()
for items in emailAccounts:
emailRecordXML = Element('emailAccount')
child = SubElement(emailRecordXML, 'email')
child.text = items.email
child = SubElement(emailRecordXML, 'password')
child.text = items.password
emailRecordsXML.append(emailRecordXML)
metaFileXML.append(emailRecordsXML)
except BaseException, msg:
logging.writeToFile(self.statusPath, '%s. [warning:179:prepMeta]' % (str(msg)), 1)
## Email meta generated!
def prettify(elem):
"""Return a pretty-printed XML string for the Element.
"""
rough_string = ElementTree.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
## /home/example.com/backup/backup-example-06-50-03-Thu-Feb-2018/meta.xml -- metaPath
metaPath = '/home/cyberpanel/%s' % (str(randint(1000, 9999)))
xmlpretty = prettify(metaFileXML).encode('ascii', 'ignore')
metaFile = open(metaPath, 'w')
metaFile.write(xmlpretty)
metaFile.close()
os.chmod(metaPath, 0640)
## meta generated
logging.statusWriter(self.statusPath, 'Meta data is ready..', 1)
metaPathNew = '/home/%s/meta.xml' % (self.website.domain)
command = 'mv %s %s' % (metaPath, metaPathNew)
ProcessUtilities.executioner(command)
command = 'chown %s:%s %s' % (self.website.externalApp, self.website.externalApp, metaPathNew)
ProcessUtilities.executioner(command)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath, "%s [207][5009]" % (str(msg)), 1)
return 0
def backupData(self):
try:
logging.statusWriter(self.statusPath, 'Backing up data..', 1)
if self.backupDestinations == 'local':
backupPath = '/home/%s' % (self.website.domain)
command = 'restic -r %s backup %s --password-file %s --exclude %s' % (self.repoPath, backupPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (backupPath), snapshotid=snapShotid, destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
backupPath = '/home/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='data:%s' % (remotePath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'Data for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupData.223][5009]' % str(msg), 1)
return 0
def backupDatabases(self):
try:
logging.statusWriter(self.statusPath, 'Backing up databases..', 1)
databases = self.website.databases_set.all()
for items in databases:
if mysqlUtilities.mysqlUtilities.createDatabaseBackup(items.dbName, '/home/cyberpanel') == 0:
return 0
dbPath = '/home/cyberpanel/%s.sql' % (items.dbName)
if self.backupDestinations == 'local':
command = 'restic -r %s backup %s --password-file %s' % (self.repoPath, dbPath, self.passwordFile)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid, destination=self.backupDestinations)
newSnapshot.save()
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, dbPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='database:%s' % (items.dbName), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupDatabases.269][5009]' % str(msg), 1)
return 0
def emailBackup(self):
try:
logging.statusWriter(self.statusPath, 'Backing up emails..', 1)
backupPath = '/home/vmail/%s' % (self.website.domain)
if os.path.exists(backupPath):
if self.backupDestinations == 'local':
logging.statusWriter(self.statusPath, 'hello world', 1)
command = 'restic -r %s backup %s --password-file %s' % (
self.repoPath, backupPath, self.passwordFile)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'hello world 2', 1)
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s backup %s --password-file %s --exclude %s' % (
self.backupDestinations, remotePath, backupPath, self.passwordFile, self.repoPath)
snapShotid = ProcessUtilities.outputExecutioner(command).split(' ')[-2]
newSnapshot = JobSnapshots(job=self.jobid, type='email:%s' % (backupPath), snapshotid=snapShotid,
destination=self.backupDestinations)
newSnapshot.save()
logging.statusWriter(self.statusPath, 'Emails for %s backed to %s.' % (self.website.domain, self.backupDestinations), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.backupDatabases.269][5009]' % str(msg), 1)
return 0
def initiateRepo(self):
try:
logging.statusWriter(self.statusPath, 'Will first initiate backup repo..', 1)
if self.backupDestinations == 'local':
command = 'restic init --repo %s --password-file %s' % (self.repoPath, self.passwordFile)
ProcessUtilities.executioner(command, self.website.externalApp)
elif self.backupDestinations[:4] == 'sftp':
remotePath = '/home/backup/%s' % (self.website.domain)
command = 'export PATH=${PATH}:/usr/bin && restic init --repo %s:%s --password-file %s' % (self.backupDestinations, remotePath, self.passwordFile)
ProcessUtilities.executioner(command)
logging.statusWriter(self.statusPath, 'Repo %s initiated for %s.' % (self.backupDestinations, self.website.domain), 1)
return 1
except BaseException, msg:
logging.statusWriter(self.statusPath,'%s. [IncJobs.initiateRepo.47][5009]' % str(msg), 1)
return 0
def createBackup(self):
self.statusPath = self.extraArgs['tempPath']
website = self.extraArgs['website']
self.backupDestinations = self.extraArgs['backupDestinations']
websiteData = self.extraArgs['websiteData']
websiteEmails = self.extraArgs['websiteEmails']
websiteSSLs = self.extraArgs['websiteSSLs']
websiteDatabases = self.extraArgs['websiteDatabases']
self.website = Websites.objects.get(domain=website)
newJob = IncJob(website=self.website)
newJob.save()
self.jobid = newJob
self.passwordFile = '/home/%s/%s' % (self.website.domain, self.website.domain)
password = randomPassword.generate_pass()
self.repoPath = '/home/%s/incbackup' % (self.website.domain)
if not os.path.exists(self.passwordFile):
command = 'echo "%s" > %s' % (password, self.passwordFile)
ProcessUtilities.executioner(command, self.website.externalApp)
if self.initiateRepo() == 0:
return
if self.prepareBackupMeta() == 0:
return
if websiteData:
if self.backupData() == 0:
return
if websiteDatabases:
if self.backupDatabases() == 0:
return
if websiteEmails:
if self.emailBackup() == 0:
return
logging.statusWriter(self.statusPath, 'Completed', 1)

View File

@@ -1,6 +1,15 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
from websiteFunctions.models import Websites
from datetime import datetime
# Create your models here.
class IncJob(models.Model):
website = models.ForeignKey(Websites)
date = models.DateTimeField(default=datetime.now, blank=True)
class JobSnapshots(models.Model):
job = models.ForeignKey(IncJob)
type = models.CharField(max_length=300)
snapshotid = models.CharField(max_length=50)
destination = models.CharField(max_length=200, default='')

View File

@@ -6,50 +6,24 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
$scope.backupButton = true;
$scope.cyberpanelLoading = true;
$scope.runningBackup = true;
$scope.cancelButton = true;
populateCurrentRecords();
$scope.cancelBackup = function () {
var backupCancellationDomain = $scope.websiteToBeBacked;
url = "/backup/cancelBackupCreation";
var data = {
backupCancellationDomain: backupCancellationDomain,
fileName: $scope.fileName,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
};
$scope.fetchDetails = function () {
getBackupStatus();
populateCurrentRecords();
$scope.populateCurrentRecords();
$scope.destination = false;
$scope.runningBackup = true;
};
function getBackupStatus() {
$scope.cyberpanelLoadingBottom = false;
var websiteToBeBacked = $scope.websiteToBeBacked;
url = "/backup/backupStatus";
url = "/IncrementalBackups/getBackupStatus";
var data = {
websiteToBeBacked: websiteToBeBacked,
websiteToBeBacked: $scope.websiteToBeBacked,
tempPath: $scope.tempPath
};
var config = {
@@ -72,18 +46,16 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
$scope.cyberpanelLoadingBottom = true;
$scope.destination = false;
$scope.runningBackup = false;
$scope.cancelButton = true;
$scope.backupButton = false;
$scope.cyberpanelLoading = true;
$scope.fileName = response.data.fileName;
$scope.status = response.data.status;
populateCurrentRecords();
$scope.populateCurrentRecords();
return;
} else {
$scope.destination = true;
$scope.backupButton = true;
$scope.runningBackup = false;
$scope.cancelButton = false;
$scope.fileName = response.data.fileName;
$scope.status = response.data.status;
@@ -94,7 +66,6 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
$timeout.cancel();
$scope.cyberpanelLoadingBottom = true;
$scope.cyberpanelLoading = true;
$scope.cancelButton = true;
$scope.backupButton = false;
}
@@ -103,22 +74,18 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
function cantLoadInitialDatas(response) {
}
};
}
$scope.destinationSelection = function () {
$scope.backupButton = false;
};
$scope.populateCurrentRecords = function () {
function populateCurrentRecords() {
var websiteToBeBacked = $scope.websiteToBeBacked;
url = "/backup/getCurrentBackups";
url = "/IncrementalBackups/fetchCurrentBackups";
var data = {
websiteToBeBacked: websiteToBeBacked,
websiteToBeBacked: $scope.websiteToBeBacked,
};
var config = {
@@ -132,31 +99,43 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
function ListInitialDatas(response) {
if (response.data.fetchStatus == 1) {
if (response.data.status === 1) {
$scope.records = JSON.parse(response.data.data);
} else {
new PNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
$scope.createBackup = function () {
var websiteToBeBacked = $scope.websiteToBeBacked;
$scope.cyberpanelLoading = false;
url = "/backup/submitBackupCreation";
url = "/IncrementalBackups/submitBackupCreation";
var data = {
websiteToBeBacked: websiteToBeBacked,
websiteToBeBacked: $scope.websiteToBeBacked,
backupDestinations: $scope.backupDestinations,
websiteData: $scope.websiteData,
websiteEmails: $scope.websiteEmails,
websiteSSLs: $scope.websiteSSLs,
websiteDatabases: $scope.websiteDatabases
};
var config = {
@@ -171,8 +150,8 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
function ListInitialDatas(response) {
if (response.data.metaStatus === 1) {
if (response.data.status === 1) {
$scope.tempPath = response.data.tempPath;
getBackupStatus();
}
@@ -183,11 +162,10 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
};
$scope.deleteBackup = function (id) {
url = "/backup/deleteBackup";
url = "/IncrementalBackups/deleteBackup";
var data = {
backupID: id,
@@ -206,22 +184,64 @@ app.controller('createIncrementalBackups', function ($scope, $http, $timeout) {
function ListInitialDatas(response) {
if (response.data.deleteStatus == 1) {
if (response.data.status === 1) {
populateCurrentRecords();
$scope.populateCurrentRecords();
} else {
}
}
function cantLoadInitialDatas(response) {
}
};
$scope.restore = function (id) {
$scope.cyberpanelLoading = false;
url = "/IncrementalBackups/fetchRestorePoints";
var data = {
id: id
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
$scope.jobs = JSON.parse(response.data.data);
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
@@ -256,9 +276,9 @@ app.controller('incrementalDestinations', function ($scope, $http) {
url = "/IncrementalBackups/populateCurrentRecords";
var type = 'SFTP';
if ($scope.destinationType === 'SFTP'){
if ($scope.destinationType === 'SFTP') {
type = 'SFTP';
}else{
} else {
type = 'AWS';
}
@@ -307,14 +327,14 @@ app.controller('incrementalDestinations', function ($scope, $http) {
url = "/IncrementalBackups/addDestination";
if(type === 'SFTP'){
if (type === 'SFTP') {
var data = {
type: type,
IPAddress: $scope.IPAddress,
password: $scope.password,
backupSSHPort: $scope.backupSSHPort
};
}else {
} else {
var data = {
type: type,
AWS_ACCESS_KEY_ID: $scope.AWS_ACCESS_KEY_ID,

View File

@@ -1,52 +1,58 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Create Incremental Backup" %}{% endblock %}
{% block content %}
{% load static %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Back up Website" %} - <a target="_blank" href="http://go.cyberpanel.net/backup" style="height: 23px;line-height: 21px;" class="btn btn-border btn-alt border-red btn-link font-red" title=""><span>{% trans "Backup Docs" %}</span></a></h2>
<p>{% trans "This page can be used to create incremental backups for your websites." %}</p>
</div>
<div class="container">
<div id="page-title">
<h2>{% trans "Back up Website" %} - <a target="_blank" href="http://go.cyberpanel.net/backup"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red" title=""><span>{% trans "Backup Docs" %}</span></a>
</h2>
<p>{% trans "This page can be used to create incremental backups for your websites." %}</p>
</div>
<div ng-controller="createIncrementalBackups" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Back up Website" %} <img ng-hide="backupLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<div ng-controller="createIncrementalBackups" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Back up Website" %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Website" %} </label>
<div class="col-sm-6">
<select ng-change="fetchDetails()" ng-model="websiteToBeBacked" class="form-control">
{% for items in websiteList %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Website" %} </label>
<div class="col-sm-6">
<select ng-change="fetchDetails()" ng-model="websiteToBeBacked" class="form-control">
{% for items in websiteList %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div ng-hide="destination" class="form-group">
<label class="col-sm-3 control-label">{% trans "Destination" %}</label>
<div class="col-sm-6">
<select ng-change="destinationSelection()" ng-model="backupDestinations" class="form-control">
<option>{% trans "Local" %}</option>
</select>
</div>
</div>
<div ng-hide="destination" class="form-group">
<label class="col-sm-3 control-label">{% trans "Destination" %}</label>
<div class="col-sm-6">
<select ng-change="destinationSelection()" ng-model="backupDestinations"
class="form-control">
{% for items in destinations %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div ng-hide="destination" class="form-group">
<div ng-hide="destination" class="form-group">
<label class="col-sm-3 control-label">{% trans "Backup Content" %}</label>
<div class="col-sm-9">
<div class="checkbox">
@@ -57,6 +63,15 @@
</div>
</div>
<label class="col-sm-3 control-label"></label>
<div class="col-sm-9">
<div class="checkbox">
<label>
<input ng-model="websiteDatabases" type="checkbox" value="">
Databases
</label>
</div>
</div>
<label class="col-sm-3 control-label"></label>
<div class="col-sm-9">
<div class="checkbox">
<label>
@@ -65,6 +80,7 @@
</label>
</div>
</div>
<!---
<label class="col-sm-3 control-label"></label>
<div class="col-sm-9">
<div class="checkbox">
@@ -73,114 +89,130 @@
SSL Certificates
</label>
</div>
</div> -->
</div>
<!---- if Back up is running ----->
<div ng-hide="runningBackup" class="form-group">
<div class="col-sm-12">
<div class="col-sm-12">
<textarea ng-model="status" class="form-control" rows="10"></textarea>
</div>
</div>
</div>
<!---- if Back up is running ----->
<!---- if Back up is running------>
<div ng-hide="runningBackup" class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th></th>
<th>{% trans "File Name" %}</th>
<th>{% trans "Status" %} <img ng-hide="backupLoadingBottom" src="{% static 'images/loading.gif' %}"></th>
</tr>
</thead>
<tbody>
<tr>
<td>{% trans "Running" %}</td>
<td>{$ fileName $}</td>
<td style="color: red"><strong>{$ status $}</strong></td>
</tr>
</tbody>
</table>
</div>
</div>
<!---- if Back up is running------>
<div ng-hide="backupButton" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="createBackup()" class="btn btn-primary btn-lg btn-block">{% trans "Create Back up" %}</button>
</div>
</div>
<div ng-hide="cancelButton" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="cancelBackup()" class="btn btn-primary btn-lg btn-block">{% trans "Cancel Backup" %}</button>
</div>
</div>
<!------ List of records --------------->
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "File" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "Size" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.id"></td>
<td ng-bind="record.file"></td>
<td ng-bind="record.date"></td>
<td ng-bind="record.size"></td>
<td ng-bind="record.status"></td>
<a href=""><td ng-click="deleteBackup(record.id)"><img src="{% static 'images/delete.png' %}"></td></a>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<div id="websiteDeleteFailure" class="alert alert-danger">
<p>{% trans "Cannot delete website, Error message: " %}{$ errorMessage $}</p>
<div ng-hide="backupButton" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="createBackup()"
class="btn btn-primary btn-lg btn-block">{% trans "Create Back up" %}</button>
</div>
</div>
<div id="websiteDeleteSuccess" class="alert alert-success">
<p>Website <strong>{$ deletedWebsite $}</strong> {% trans "Successfully Deleted" %}</p>
<!------ List of records --------------->
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "Restore" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.id"></td>
<td ng-bind="record.date"></td>
<td>
<a ng-click="restore(record.id)" data-toggle="modal" data-target="#settings"
ng-click='deleteCLPackage()'
class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Restore Points</span></a>
<div id="settings" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
&times;
</button>
<h4 class="modal-title">Restore Points
<img id="cyberpanelLoading"
src="/static/images/loading.gif"
style="display: none;">
</h4>
</div>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th>{% trans "Job ID" %}</th>
<th>{% trans "Snapshot ID" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Destination" %}</th>
<th>{% trans "Action" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="job in jobs track by $index">
<td ng-bind="job.id"></td>
<td ng-bind="job.snapshotid"></td>
<td ng-bind="job.type"></td>
<td ng-bind="job.destination"></td>
<td>
<a class="btn btn-border btn-alt border-green btn-link font-green"
title=""><span>Restore</span></a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" ng-disabled="savingSettings"
class="btn btn-default" data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
</td>
<a href="">
<td ng-click="deleteBackup(record.id)"><img
src="{% static 'images/delete.png' %}"></td>
</a>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!------ List of records --------------->
</form>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -7,5 +7,9 @@ urlpatterns = [
url(r'^addDestination$', views.addDestination, name='addDestinationInc'),
url(r'^populateCurrentRecords$', views.populateCurrentRecords, name='populateCurrentRecordsInc'),
url(r'^removeDestination$', views.removeDestination, name='removeDestinationInc'),
url(r'^fetchCurrentBackups$', views.fetchCurrentBackups, name='fetchCurrentBackupsInc'),
url(r'^submitBackupCreation$', views.submitBackupCreation, name='submitBackupCreationInc'),
url(r'^getBackupStatus$', views.getBackupStatus, name='getBackupStatusInc'),
url(r'^deleteBackup$', views.deleteBackup, name='deleteBackupInc'),
url(r'^fetchRestorePoints$', views.fetchRestorePoints, name='fetchRestorePointsInc'),
]

View File

@@ -8,6 +8,13 @@ from plogical.processUtilities import ProcessUtilities
from plogical.virtualHostUtilities import virtualHostUtilities
import json
import os
from loginSystem.models import Administrator
from websiteFunctions.models import Websites
from .models import IncJob, JobSnapshots
from .IncBackups import IncJobs
from random import randint
import time
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
# Create your views here.
@@ -23,7 +30,19 @@ def createBackup(request):
return ACLManager.loadError()
websitesName = ACLManager.findAllSites(currentACL, userID)
return defRenderer(request, 'IncBackups/createBackup.html', {'websiteList': websitesName})
destinations = []
destinations.append('local')
path = '/home/cyberpanel/sftp'
for items in os.listdir(path):
destinations.append('sftp:%s' % (items))
for items in os.listdir(path):
destinations.append('s3:s3.amazonaws.com/%s' % (items))
return defRenderer(request, 'IncBackups/createBackup.html', {'websiteList': websitesName, 'destinations': destinations})
except BaseException, msg:
return HttpResponse(str(msg))
@@ -242,4 +261,236 @@ def removeDestination(request):
except BaseException, msg:
final_dic = {'destStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def fetchCurrentBackups(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('fetchStatus', 0)
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson()
website = Websites.objects.get(domain=backupDomain)
backups = website.incjob_set.all().reverse()
json_data = "["
checker = 0
for items in backups:
includes = ""
jobs = items.jobsnapshots_set.all()
for job in jobs:
includes = '%s,%s:%s' % (includes, job.type, job.snapshotid)
dic = {'id': items.id,
'date': str(items.date),
'includes': includes
}
if checker == 0:
json_data = json_data + json.dumps(dic)
checker = 1
else:
json_data = json_data + ',' + json.dumps(dic)
json_data = json_data + ']'
final_json = json.dumps({'status': 1, 'error_message': "None", "data": json_data})
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'status': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def submitBackupCreation(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
backupDomain = data['websiteToBeBacked']
backupDestinations = data['backupDestinations']
if ACLManager.checkOwnership(backupDomain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('metaStatus', 0)
tempPath = "/home/cyberpanel/" + str(randint(1000, 9999))
try:
websiteData = data['websiteData']
except:
websiteData = False
try:
websiteEmails = data['websiteEmails']
except:
websiteEmails = False
try:
websiteSSLs = data['websiteSSLs']
except:
websiteSSLs = False
try:
websiteDatabases = data['websiteDatabases']
except:
websiteDatabases = False
extraArgs = {}
extraArgs['website'] = backupDomain
extraArgs['tempPath'] = tempPath
extraArgs['backupDestinations'] = backupDestinations
extraArgs['websiteData'] = websiteData
extraArgs['websiteEmails'] = websiteEmails
extraArgs['websiteSSLs'] = websiteSSLs
extraArgs['websiteDatabases'] = websiteDatabases
startJob = IncJobs('createBackup', extraArgs)
startJob.start()
time.sleep(2)
final_json = json.dumps({'status': 1, 'error_message': "None", 'tempPath': tempPath})
return HttpResponse(final_json)
except BaseException, msg:
logging.writeToFile(str(msg))
final_dic = {'status': 0, 'metaStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def getBackupStatus(request):
try:
userID = request.session['userID']
data = json.loads(request.body)
status = data['tempPath']
backupDomain = data['websiteToBeBacked']
domain = Websites.objects.get(domain=backupDomain)
## file name read ends
if os.path.exists(status):
command = "sudo cat " + status
status = ProcessUtilities.outputExecutioner(command, 'cyberpanel')
if status.find("Completed") > -1:
### Removing Files
command = 'sudo rm -f ' + status
ProcessUtilities.executioner(command, 'cyberpanel')
final_json = json.dumps(
{'backupStatus': 1, 'error_message': "None", "status": status, "abort": 1})
return HttpResponse(final_json)
elif status.find("[5009]") > -1:
## removing status file, so that backup can re-run
try:
command = 'sudo rm -f ' + status
ProcessUtilities.executioner(command, 'cyberpanel')
except:
pass
final_json = json.dumps(
{'backupStatus': 1, 'error_message': "None", "status": status,
"abort": 1})
return HttpResponse(final_json)
else:
final_json = json.dumps(
{'backupStatus': 1, 'error_message': "None", "status": status,
"abort": 0})
return HttpResponse(final_json)
else:
final_json = json.dumps({'backupStatus': 1, 'error_message': "None", "status": 1, "abort": 0})
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'backupStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
logging.writeToFile(str(msg) + " [backupStatus]")
return HttpResponse(final_json)
def deleteBackup(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('destStatus', 0)
data = json.loads(request.body)
id = data['backupID']
IncJob.objects.get(id=id).delete()
final_dic = {'status': 1, 'error_message': 'None'}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'destStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
def fetchRestorePoints(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
data = json.loads(request.body)
id = data['id']
incJob = IncJob.objects.get(id=id)
backups = incJob.jobsnapshots_set.all()
json_data = "["
checker = 0
for items in backups:
dic = {'id': items.id,
'snapshotid': items.snapshotid,
'type': items.type,
'destination': items.destination,
}
if checker == 0:
json_data = json_data + json.dumps(dic)
checker = 1
else:
json_data = json_data + ',' + json.dumps(dic)
json_data = json_data + ']'
final_json = json.dumps({'status': 1, 'error_message': "None", "data": json_data})
return HttpResponse(final_json)
except BaseException, msg:
final_dic = {'status': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)

View File

@@ -117,7 +117,7 @@
</extension>
<extension>
<extensionName>lsphp70-pecl-imagick</extensionName>
<extensionName>lsphp70-imagick</extensionName>
<extensionDescription>Extension to create and modify images using ImageMagick</extensionDescription>
<status>0</status>
</extension>

View File

@@ -117,7 +117,7 @@
</extension>
<extension>
<extensionName>lsphp71-pecl-imagick</extensionName>
<extensionName>lsphp71-imagick</extensionName>
<extensionDescription>Extension to create and modify images using ImageMagick</extensionDescription>
<status>0</status>
</extension>

View File

@@ -117,7 +117,7 @@
</extension>
<extension>
<extensionName>lsphp72-pecl-imagick</extensionName>
<extensionName>lsphp72-imagick</extensionName>
<extensionDescription>Extension to create and modify images using ImageMagick</extensionDescription>
<status>0</status>
</extension>

View File

@@ -117,7 +117,7 @@
</extension>
<extension>
<extensionName>lsphp73-pecl-imagick</extensionName>
<extensionName>lsphp73-imagick</extensionName>
<extensionDescription>Extension to create and modify images using ImageMagick</extensionDescription>
<status>0</status>
</extension>

View File

@@ -7,7 +7,6 @@ django.setup()
import threading as multi
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
import subprocess
import shlex
from vhost import vhost
from websiteFunctions.models import ChildDomains, Websites
import randomPassword

View File

@@ -189,11 +189,13 @@ class ProcessUtilities(multi.Thread):
# for items in CommandArgs:
# finalCommand = '%s %s' % (finalCommand, items)
#logging.writeToFile(command)
if user == None:
logging.writeToFile(ProcessUtilities.token + command)
sock.sendall(ProcessUtilities.token + command)
else:
command = '%s-u %s %s' % (ProcessUtilities.token, user, command)
logging.writeToFile(command)
command = command.replace('sudo', '')
sock.sendall(command)