oc backups

This commit is contained in:
usmannasir
2024-05-27 20:28:32 +04:00
parent 5233759134
commit f354687cb4
15 changed files with 2147 additions and 246 deletions

View File

@@ -1,5 +1,6 @@
from django.db import models
from websiteFunctions.models import Websites
from loginSystem.models import Administrator
from datetime import datetime
@@ -27,3 +28,19 @@ class BackupJob(models.Model):
class JobSites(models.Model):
job = models.ForeignKey(BackupJob, on_delete=models.CASCADE)
website = models.CharField(max_length=300)
class OneClickBackups(models.Model):
owner = models.ForeignKey(Administrator, on_delete=models.PROTECT)
planName = models.CharField(max_length=100)
months = models.CharField(max_length=100)
price = models.CharField(max_length=100)
customer = models.CharField(max_length=300)
subscription = models.CharField(max_length=300, unique=True)
sftpUser = models.CharField(max_length=100)
config = models.TextField(default='{}')
date = models.DateTimeField(default=datetime.now, blank=True)
state = models.IntegerField(default=0)

View File

@@ -2,8 +2,12 @@
import os
import os.path
import sys
import django
from io import StringIO
import django
import paramiko
from plogical.applicationInstaller import ApplicationInstaller
from plogical.httpProc import httpProc
sys.path.append('/usr/local/CyberCP')
@@ -1912,4 +1916,405 @@ class BackupManager:
except BaseException as msg:
data_ret = {'abort': 0, 'installStatus': 0, 'installationProgress': "0", 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
return HttpResponse(json_data)
def OneClickBackups(self, request=None, userID=None, data=None):
user = Administrator.objects.get(pk=userID)
data = {}
import requests
try:
if request.GET.get('status', 'none') == 'success':
plan_name = request.GET.get('planName')
months = request.GET.get('months')
monthly_price = request.GET.get('monthlyPrice')
yearly_price = request.GET.get('yearlyPrice')
customer = request.GET.get('customer')
subscription = request.GET.get('subscription')
from IncBackups.models import OneClickBackups
if months == '1':
price = monthly_price
else:
price = yearly_price
try:
backup_plan = OneClickBackups(
owner=user,
planName=plan_name,
months=months,
price=price,
customer=customer,
subscription=subscription,
sftpUser=f'{user.userName}{str(randint(1000, 9999))}',
)
backup_plan.save()
####
import requests
import json
# Define the URL of the endpoint
url = 'http://platform.cyberpersons.com/Billing/CreateSFTPAccount' # Replace with your actual endpoint URL
# Define the payload to send in the POST request
payload = {
'sub': subscription,
'key': ProcessUtilities.outputExecutioner(f'cat /root/.ssh/cyberpanel.pub'), # Replace with the actual SSH public key
'sftpUser': backup_plan.sftpUser,
'serverIP': ACLManager.fetchIP(), # Replace with the actual server IP,
'planName': plan_name
}
# Convert the payload to JSON format
headers = {'Content-Type': 'application/json'}
dataRet = json.dumps(payload)
# Make the POST request
response = requests.post(url, headers=headers, data=dataRet)
# Handle the response
if response.status_code == 200:
response_data = response.json()
if response_data.get('status') == 1:
ocbkup = OneClickBackups.objects.get(owner=user,subscription=subscription)
ocbkup.state = 1
ocbkup.save()
finalDic = {}
finalDic['IPAddress'] = response_data.get('ipAddress')
finalDic['password'] = 'NOT-NEEDED'
finalDic['backupSSHPort'] = '22'
finalDic['userName'] = backup_plan.sftpUser
finalDic['type'] = 'SFTP'
finalDic['path'] = 'cpbackups'
finalDic['name'] = backup_plan.sftpUser
wm = BackupManager()
response_inner = wm.submitDestinationCreation(userID, finalDic)
response_data_inner = json.loads(response_inner.content.decode('utf-8'))
# Extract the value of 'status'
if response_data_inner.get('status') == 0:
data['status'] = 0
data[
'message'] = f"[2109] Failed to create sftp account {response_data_inner.get('error_message')}"
print("Failed to create SFTP account:", response_data_inner.get('error_message'))
else:
data['status'] = 1
else:
data['status'] = 0
data['message'] = f"[1985] Failed to create sftp account {response_data.get('error_message')}"
print("Failed to create SFTP account:", response_data.get('error_message'))
else:
print("Failed to connect to the server. Status code:", response.status_code)
print("Response:", response.text)
data['status'] = 0
data['message'] = f"[1991] Failed to create sftp account {response.text}"
####
except BaseException as msg:
data['status'] = 4
data['message'] = str(msg)
elif request.GET.get('status', 'none') == 'cancelled':
data['status'] = 0
else:
data['status'] = 2
except BaseException as msg:
data['status'] = 0
data['message'] = f"[2038] Unkown error occured in purchase process. Error message: {str(msg)}"
url = 'https://platform.cyberpersons.com/Billing/FetchBackupPlans'
try:
response = requests.get(url)
response.raise_for_status() # Check if the request was successful
data['plans'] = response.json() # Convert the response to a Python dictionary
except requests.exceptions.HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
except Exception as err:
print(f'Other error occurred: {err}')
data['bPlans'] = user.oneclickbackups_set.all()
proc = httpProc(request, 'backup/oneClickBackups.html', data, 'addDeleteDestinations')
return proc.render()
def ManageOCBackups(self, request=None, userID=None, data=None):
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
from IncBackups.models import OneClickBackups
ocb = OneClickBackups.objects.get(pk = request.GET.get('id'), owner=admin)
destinations = [NormalBackupDests.objects.get(name=ocb.sftpUser)]
dests = []
for dest in destinations:
dests.append(dest.name)
websitesName = ACLManager.findAllSites(currentACL, userID)
proc = httpProc(request, 'backup/OneClickBackupSchedule.html', {'destination': NormalBackupDests.objects.get(name=ocb.sftpUser).name, 'websites': websitesName},
'scheduleBackups')
return proc.render()
def RestoreOCBackups(self, request=None, userID=None, data=None):
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
from IncBackups.models import OneClickBackups
ocb = OneClickBackups.objects.get(pk = request.GET.get('id'), owner=admin)
# Load the private key
nbd = NormalBackupDests.objects.get(name=ocb.sftpUser)
ip = json.loads(nbd.config)['ip']
# Connect to the remote server using the private key
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Read the private key content
private_key_path = '/root/.ssh/cyberpanel'
key_content = ProcessUtilities.outputExecutioner(f'cat {private_key_path}').rstrip('\n')
# Load the private key from the content
key_file = StringIO(key_content)
key = paramiko.RSAKey.from_private_key(key_file)
# Connect to the server using the private key
ssh.connect(ip, username=ocb.sftpUser, pkey=key)
# Command to list directories under the specified path
command = f"ls -d cpbackups/*/"
# Execute the command
stdin, stdout, stderr = ssh.exec_command(command)
# Read the results
directories = stdout.read().decode().splitlines()
finalDirs = []
# Print directories
for directory in directories:
finalDirs.append(directory.split('/')[1])
proc = httpProc(request, 'backup/restoreOCBackups.html', {'directories': finalDirs},
'scheduleBackups')
return proc.render()
def fetchOCSites(self, request=None, userID=None, data=None):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
data = json.loads(request.body)
id = data['idValue']
folder = data['folder']
admin = Administrator.objects.get(pk=userID)
from IncBackups.models import OneClickBackups
ocb = OneClickBackups.objects.get(pk = id, owner=admin)
# Load the private key
nbd = NormalBackupDests.objects.get(name=ocb.sftpUser)
ip = json.loads(nbd.config)['ip']
# Connect to the remote server using the private key
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Read the private key content
private_key_path = '/root/.ssh/cyberpanel'
key_content = ProcessUtilities.outputExecutioner(f'cat {private_key_path}').rstrip('\n')
# Load the private key from the content
key_file = StringIO(key_content)
key = paramiko.RSAKey.from_private_key(key_file)
# Connect to the server using the private key
ssh.connect(ip, username=ocb.sftpUser, pkey=key)
# Command to list directories under the specified path
command = f"ls -d cpbackups/{folder}/*"
# Execute the command
stdin, stdout, stderr = ssh.exec_command(command)
# Read the results
directories = stdout.read().decode().splitlines()
finalDirs = []
# Print directories
for directory in directories:
finalDirs.append(directory.split('/')[2])
data_ret = {'status': 1, 'finalDirs': finalDirs}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException as msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def StartOCRestore(self, request=None, userID=None, data=None):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
data = json.loads(request.body)
id = data['idValue']
folder = data['folder']
backupfile = data['backupfile']
extraArgs = {}
extraArgs['id'] = id
extraArgs['folder'] = folder
extraArgs['backupfile'] = backupfile
extraArgs['userID'] = userID
extraArgs['tempStatusPath'] = "/home/cyberpanel/" + str(randint(1000, 9999))
statusFile = open(extraArgs['tempStatusPath'], 'w')
statusFile.writelines("Restore started..")
statusFile.close()
background = ApplicationInstaller('StartOCRestore', extraArgs)
background.start()
data_ret = {'status': 1, 'installStatus': 1, 'error_message': 'None',
'tempStatusPath': extraArgs['tempStatusPath']}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except BaseException as msg:
data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
def DeployAccount(self, request=None, userID=None, data=None):
user = Administrator.objects.get(pk=userID)
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
import json
data = json.loads(request.body)
id = data['id']
from IncBackups.models import OneClickBackups
ocb = OneClickBackups.objects.get(pk=id, owner=user)
data = {}
####
import requests
import json
# Define the URL of the endpoint
url = 'http://platform.cyberpersons.com/Billing/CreateSFTPAccount' # Replace with your actual endpoint URL
# Define the payload to send in the POST request
payload = {
'sub': ocb.subscription,
'key': ProcessUtilities.outputExecutioner(f'cat /root/.ssh/cyberpanel.pub'),
# Replace with the actual SSH public key
'sftpUser': ocb.sftpUser,
'serverIP': ACLManager.fetchIP(), # Replace with the actual server IP
'planName': ocb.planName
}
# Convert the payload to JSON format
headers = {'Content-Type': 'application/json'}
dataRet = json.dumps(payload)
# Make the POST request
response = requests.post(url, headers=headers, data=dataRet)
# Handle the response
# Handle the response
if response.status_code == 200:
response_data = response.json()
if response_data.get('status') == 1:
ocb.state = 1
ocb.save()
print("SFTP account created successfully.")
finalDic = {}
finalDic['IPAddress'] = response_data.get('ipAddress')
finalDic['password'] = 'NOT-NEEDED'
finalDic['backupSSHPort'] = '22'
finalDic['userName'] = ocb.sftpUser
finalDic['type'] = 'SFTP'
finalDic['path'] = 'cpbackups'
finalDic['name'] = ocb.sftpUser
wm = BackupManager()
response_inner = wm.submitDestinationCreation(userID, finalDic)
response_data_inner = json.loads(response_inner.content.decode('utf-8'))
# Extract the value of 'status'
if response_data_inner.get('status') == 0:
data_ret = {'status': 1, 'error_message': response_data_inner.get('error_message')}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
data_ret = {'status': 1,}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
if response_data.get('error_message') == "Already deployed.":
ocb.state = 1
ocb.save()
print("SFTP account created successfully.")
finalDic = {}
finalDic['IPAddress'] = response_data.get('ipAddress')
finalDic['password'] = 'NOT-NEEDED'
finalDic['backupSSHPort'] = '22'
finalDic['userName'] = ocb.sftpUser
finalDic['type'] = 'SFTP'
finalDic['path'] = 'cpbackups'
finalDic['name'] = ocb.sftpUser
wm = BackupManager()
response_inner = wm.submitDestinationCreation(userID, finalDic)
response_data_inner = json.loads(response_inner.content.decode('utf-8'))
# Extract the value of 'status'
if response_data_inner.get('status') == 0:
data_ret = {'status': 1, 'error_message': response_data_inner.get('error_message')}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
data_ret = {'status': 1, }
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
data_ret = {'status': 0, 'error_message': response_data.get('error_message')}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
else:
data['message'] = f"[1991] Failed to create sftp account {response.text}"
data_ret = {'status': 0, 'error_message': response.text}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)

View File

@@ -97,8 +97,7 @@ app.controller('backupWebsiteControl', function ($scope, $http, $timeout) {
$scope.status = response.data.status;
populateCurrentRecords();
return;
}
else {
} else {
$scope.destination = true;
$scope.backupButton = true;
$scope.runningBackup = false;
@@ -109,8 +108,7 @@ app.controller('backupWebsiteControl', function ($scope, $http, $timeout) {
$timeout(getBackupStatus, 2000);
}
}
else {
} else {
$timeout.cancel();
$scope.backupLoadingBottom = true;
$scope.backupLoading = true;
@@ -230,8 +228,7 @@ app.controller('backupWebsiteControl', function ($scope, $http, $timeout) {
populateCurrentRecords();
}
else {
} else {
}
@@ -308,8 +305,7 @@ app.controller('restoreWebsiteControl', function ($scope, $http, $timeout) {
$scope.restoreFinished = true;
$timeout.cancel();
return;
}
else {
} else {
$scope.running = response.data.running;
$scope.fileName = $scope.backupFile;
$scope.restoreLoading = false;
@@ -364,18 +360,17 @@ app.controller('restoreWebsiteControl', function ($scope, $http, $timeout) {
getRestoreStatus();
restoreBackupButton.disabled = false;
}
else {
} else {
$scope.backupError = false;
$scope.errorMessage = response.data.error_message;
restoreBackupButton.disabled = false;
restoreBackupButton.disabled = false;
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
restoreBackupButton.disabled = false;
restoreBackupButton.disabled = false;
}
};
@@ -404,14 +399,12 @@ app.controller('restoreWebsiteControl', function ($scope, $http, $timeout) {
if (response.data.createWebSiteStatus == 1) {
getRestoreStatus();
}
else if (response.data.existsStatus == 1) {
} else if (response.data.existsStatus == 1) {
$scope.backupError = false;
$scope.errorMessage = response.data.error_message;
$scope.restoreButton = true;
$scope.runningRestore = true;
}
else {
} else {
$scope.websiteDomain = domainName;
$scope.backupError = false;
$scope.errorMessage = response.data.error_message;
@@ -484,8 +477,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
websitesToBeBacked.push(website);
}
}
else {
} else {
var tempArray = [];
@@ -504,8 +496,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
websitesToBeBacked = websitesToBeBackedTemp;
$scope.webSiteStatus = true;
}
else {
} else {
websitesToBeBacked = [];
$scope.webSiteStatus = false;
}
@@ -568,8 +559,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
$scope.backupCancelled = true;
}
else {
} else {
$scope.error_message = response.data.error_message;
$scope.backupLoading = true;
@@ -667,8 +657,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
getBackupStatus();
}
else {
} else {
$scope.error_message = response.data.error_message;
$scope.backupLoading = true;
@@ -730,8 +719,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
$scope.backupStatus = false;
$scope.requestData = response.data.status;
$timeout(getBackupStatus, 2000);
}
else {
} else {
$scope.requestData = response.data.status;
$timeout.cancel();
@@ -739,8 +727,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
remoteBackupRestore();
}
}
else {
} else {
$scope.error_message = response.data.error_message;
$scope.backupLoading = true;
@@ -832,15 +819,13 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
$scope.backupStatus = false;
$scope.restoreData = response.data.status;
$timeout(localRestoreStatus, 2000);
}
else {
} else {
$scope.restoreData = response.data.status;
$timeout.cancel();
$scope.backupLoading = true;
$scope.startTransferbtn = false;
}
}
else {
} else {
$scope.error_message = response.data.error_message;
$scope.backupLoading = true;
@@ -895,8 +880,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
$scope.backupStatus = false;
$scope.requestData = response.data.status;
$timeout(getBackupStatus, 2000);
}
else {
} else {
$timeout.cancel();
}
}
@@ -980,8 +964,7 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
$scope.fetchAccountsBtn = false;
}
else {
} else {
$scope.error_message = response.data.error_message;
$scope.backupLoading = true;
@@ -1067,6 +1050,7 @@ app.controller('backupLogsScheduled', function ($scope, $http, $timeout) {
});
}
}
function cantLoadInitialData(response) {
$scope.cyberpanelLoading = true;
new PNotify({
@@ -1085,15 +1069,12 @@ app.controller('backupLogsScheduled', function ($scope, $http, $timeout) {
///** Backup site ends **///
app.controller('googleDrive', function ($scope, $http) {
$scope.cyberPanelLoading = true;
$scope.driveHidden = true;
$scope.setupAccount = function(){
$scope.setupAccount = function () {
window.open("https://platform.cyberpersons.com/gDrive?name=" + $scope.accountName + '&server=' + window.location.href + 'Setup');
};
@@ -1252,7 +1233,7 @@ app.controller('googleDrive', function ($scope, $http) {
$scope.changeRetention = function () {
$scope.cyberPanelLoading = false;
var config = {
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
@@ -1268,24 +1249,25 @@ app.controller('googleDrive', function ($scope, $http) {
$http.post(dataurl, data, config).then(fileretention, cantLoadInitialData);
function fileretention(response) {
$scope.cyberPanelLoading = true;
if (response.data.status === 1) {
new PNotify({
title: 'Success',
text: 'Changes successfully applied',
type: 'success'
});
$scope.fetchWebsites();
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
function fileretention(response) {
$scope.cyberPanelLoading = true;
if (response.data.status === 1) {
new PNotify({
title: 'Success',
text: 'Changes successfully applied',
type: 'success'
});
$scope.fetchWebsites();
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
function cantLoadInitialData(response) {
}
function cantLoadInitialData(response) {
$scope.cyberPanelLoading = true;
new PNotify({
title: 'Operation Failed!',
@@ -2062,3 +2044,654 @@ app.controller('scheduleBackup', function ($scope, $http, $window) {
};
});
app.controller('backupPlanNowOneClick', function ($scope, $http, $window) {
$scope.cyberpanelLoading = true;
$scope.sftpHide = true;
$scope.localHide = true;
$scope.BuyNowBackupP = function (planName, monthlyPrice, yearlyPrice, months) {
const baseURL = 'https://platform.cyberpersons.com/Billing/CreateOrderforBackupPlans';
// Get the current URL
var currentURL = window.location.href;
// Find the position of the question mark
const queryStringIndex = currentURL.indexOf('?');
// Check if there is a query string
currentURL = queryStringIndex !== -1 ? currentURL.substring(0, queryStringIndex) : currentURL;
// Encode parameters to make them URL-safe
const params = new URLSearchParams({
planName: planName,
monthlyPrice: monthlyPrice,
yearlyPrice: yearlyPrice,
returnURL: currentURL, // Add the current URL as a query parameter
months: months
});
// Build the complete URL with query string
const fullURL = `${baseURL}?${params.toString()}`;
// Redirect to the constructed URL
window.location.href = fullURL;
}
$scope.fetchDetails = function () {
if ($scope.destinationType === 'SFTP') {
$scope.sftpHide = false;
$scope.localHide = true;
$scope.populateCurrentRecords();
} else {
$scope.sftpHide = true;
$scope.localHide = false;
$scope.populateCurrentRecords();
}
};
$scope.populateCurrentRecords = function () {
$scope.cyberpanelLoading = false;
url = "/backup/getCurrentBackupDestinations";
var type = 'SFTP';
if ($scope.destinationType === 'SFTP') {
type = 'SFTP';
} else {
type = 'local';
}
var data = {
type: type
};
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.records = 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'
});
}
};
$scope.addDestination = function (type) {
$scope.cyberpanelLoading = false;
url = "/backup/submitDestinationCreation";
if (type === 'SFTP') {
var data = {
type: type,
name: $scope.name,
IPAddress: $scope.IPAddress,
userName: $scope.userName,
password: $scope.password,
backupSSHPort: $scope.backupSSHPort,
path: $scope.path
};
} else {
var data = {
type: type,
path: $scope.localPath,
name: $scope.name
};
}
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
$scope.populateCurrentRecords();
if (response.data.status === 1) {
new PNotify({
title: 'Success!',
text: 'Destination successfully added.',
type: 'success'
});
} 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'
});
}
};
$scope.removeDestination = function (type, nameOrPath) {
$scope.cyberpanelLoading = false;
url = "/backup/deleteDestination";
var data = {
type: type,
nameOrPath: nameOrPath,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
$scope.populateCurrentRecords();
if (response.data.status === 1) {
new PNotify({
title: 'Success!',
text: 'Destination successfully removed.',
type: 'success'
});
} 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'
});
}
};
$scope.DeployAccount = function (id) {
$scope.cyberpanelLoading = false;
url = "/backup/DeployAccount";
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) {
new PNotify({
title: 'Success',
text: 'Successfully deployed.',
type: 'success'
});
$window.location.reload();
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
restoreBackupButton.disabled = false;
}
};
});
app.controller('OneClickrestoreWebsiteControl', function ($scope, $http, $timeout) {
$scope.restoreLoading = true;
$scope.runningRestore = true;
$scope.restoreButton = true;
$scope.restoreFinished = false;
$scope.couldNotConnect = true;
$scope.backupError = true;
$scope.siteExists = true;
$scope.installationProgress = true;
// check to start time of status function
var check = 1;
$scope.fetchDetails = function () {
$scope.restoreLoading = false;
getRestoreStatus();
};
function getRestoreStatus() {
var backupFile = $scope.backupFile;
url = "/backup/restoreStatus";
var data = {
backupFile: backupFile,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.restoreStatus === 1) {
if (response.data.abort === 1) {
$scope.running = response.data.running;
$scope.fileName = $scope.backupFile;
$scope.restoreLoading = true;
$scope.status = response.data.status;
$scope.runningRestore = false;
$scope.restoreButton = false;
$scope.restoreFinished = true;
$timeout.cancel();
return;
} else {
$scope.running = response.data.running;
$scope.fileName = $scope.backupFile;
$scope.restoreLoading = false;
$scope.status = response.data.status;
$scope.runningRestore = false;
$scope.restoreButton = true;
$timeout(getRestoreStatus, 2000);
}
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
}
};
$scope.restoreBackup = function () {
var restoreBackupButton = document.getElementById("restoreBackup");
restoreBackupButton.disabled = true;
var backupFile = $scope.backupFile;
$scope.running = "Lets start.."
url = "/backup/submitRestore";
var data = {
backupFile: backupFile,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.restoreLoading = true;
if (response.data.restoreStatus == 1) {
$scope.runningRestore = false;
$scope.running = "Running";
$scope.fileName = $scope.backupFile;
$scope.status = "Just Started..";
getRestoreStatus();
restoreBackupButton.disabled = false;
} else {
$scope.backupError = false;
$scope.errorMessage = response.data.error_message;
restoreBackupButton.disabled = false;
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
restoreBackupButton.disabled = false;
}
};
function createWebsite() {
var backupFile = $scope.backupFile;
url = "/websites/CreateWebsiteFromBackup";
var data = {
backupFile: backupFile,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.createWebSiteStatus == 1) {
getRestoreStatus();
} else if (response.data.existsStatus == 1) {
$scope.backupError = false;
$scope.errorMessage = response.data.error_message;
$scope.restoreButton = true;
$scope.runningRestore = true;
} else {
$scope.websiteDomain = domainName;
$scope.backupError = false;
$scope.errorMessage = response.data.error_message;
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
}
};
$scope.FetchOCSites = function () {
$scope.restoreLoading = false;
// Current URL
const currentURL = window.location.href;
// Create a URL object
const urlN = new URL(currentURL);
// Get the value of the 'id' parameter
const idValue = urlN.searchParams.get('id');
url = "/backup/fetchOCSites";
var data = {
idValue: idValue,
folder: $scope.ocFolder
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.restoreLoading = true;
if (response.data.status === 1) {
$scope.backups = response.data.finalDirs;
} else {
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
restoreBackupButton.disabled = false;
}
};
$scope.StartOCRestore = function () {
$scope.restoreLoading = false;
$scope.installationDetailsForm = true;
$scope.installationProgress = false;
$scope.errorMessageBox = true;
$scope.success = true;
$scope.couldNotConnect = true;
$scope.goBackDisable = true;
$scope.restoreLoading = false;
$scope.currentStatus = "Starting creation..";
// Current URL
const currentURL = window.location.href;
// Create a URL object
const urlN = new URL(currentURL);
// Get the value of the 'id' parameter
const idValue = urlN.searchParams.get('id');
//alert(domainNameCreate);
var data = {
idValue: idValue,
folder: $scope.ocFolder,
backupfile: $scope.ocFile
}
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var url = "/backup/StartOCRestore";
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.restoreLoading = true;
if (response.data.status === 1) {
statusFile = response.data.tempStatusPath;
getCreationStatus();
} else {
$scope.goBackDisable = false;
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
alert("Error..." + response)
}
};
$scope.goBack = function () {
$scope.webSiteCreationLoading = true;
$scope.installationDetailsForm = false;
$scope.installationProgress = true;
$scope.errorMessageBox = true;
$scope.success = true;
$scope.couldNotConnect = true;
$scope.goBackDisable = true;
$("#installProgress").css("width", "0%");
};
function getCreationStatus() {
url = "/websites/installWordpressStatus";
var data = {
statusFile: statusFile
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.abort === 1) {
if (response.data.installStatus === 1) {
$scope.restoreLoading = true;
$scope.installationDetailsForm = true;
$scope.installationProgress = false;
$scope.errorMessageBox = true;
$scope.success = false;
$scope.couldNotConnect = true;
$scope.goBackDisable = false;
$("#installProgress").css("width", "100%");
$scope.installPercentage = "100";
$scope.currentStatus = response.data.currentStatus ;
$timeout.cancel();
} else {
$scope.restoreLoading = true;
$scope.installationDetailsForm = true;
$scope.installationProgress = false;
$scope.errorMessageBox = false;
$scope.success = true;
$scope.couldNotConnect = true;
$scope.goBackDisable = false;
$scope.errorMessage = response.data.error_message;
$("#installProgress").css("width", "0%");
$scope.installPercentage = "0";
$scope.goBackDisable = false;
}
} else {
$scope.restoreLoading = false;
$("#installProgress").css("width", response.data.installationProgress + "%");
$scope.installPercentage = response.data.installationProgress;
$scope.currentStatus = response.data.currentStatus;
$timeout(getCreationStatus, 1000);
}
}
function cantLoadInitialDatas(response) {
$scope.restoreLoading = true;
$scope.installationDetailsForm = true;
$scope.installationProgress = false;
$scope.errorMessageBox = true;
$scope.success = true;
$scope.couldNotConnect = false;
$scope.goBackDisable = false;
}
}
});

View File

@@ -0,0 +1,309 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Schedule Backup - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div ng-controller="scheduleBackup" class="container">
<div id="page-title">
<h2>{% trans "Schedule Backup" %} - <a target="_blank"
href="https://cyberpanel.net/KnowledgeBase/home/schedule-backups-local-or-sftp/"
style="height: 23px;line-height: 21px; text-decoration: underline"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a>
</h2>
<p>{% trans "On this page you can schedule Backups to localhost or remote server (If you have added one)" %}</p>
</div>
<div class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Create New Backup Schedule" %} <img ng-hide="cyberPanelLoading"
src="{% static 'images/loading.gif' %}"
alt="cyberPanelLoading">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group" style="display: none">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="selectedAccountAdd"
ng-init="selectedAccountAdd='{{ destination }}'" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="name" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Backup Frequency" %}</label>
<div class="col-sm-6">
<select ng-model="backupFrequency" class="form-control">
<option>Never</option>
<option>Daily</option>
<option>Weekly</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Backup Retention. Leave 0 for no limit" %}</label>
<div class="col-sm-9">
<div class="number">
<label>
<input ng-model="backupRetention" type="number" value="0">
</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addSchedule()"
class="btn btn-primary btn-lg btn-block">{% trans "Add Schedule" %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Manage Existing Backup Schedules" %} <img ng-hide="cyberPanelLoading"
src="{% static 'images/loading.gif' %}"
alt="cyberPanelLoading">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Destination" %}</label>
<div class="col-sm-6">
<select ng-change="fetchJobs()" ng-model="selectedAccount" class="form-control">
<option>{{ destination }}</option>
</select>
</div>
</div>
<div ng-hide="jobsHidden" class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Job" %}</label>
<div class="col-sm-6">
<select ng-change="fetchWebsites()" ng-model="selectedJob" class="form-control">
<option ng-repeat="job in jobs track by $index">{$ job $}</option>
</select>
</div>
<button ng-hide="driveHidden" type="button" ng-click="deleteAccount()"
class="btn btn-danger">{% trans "Delete" %}</button>
</div>
<div ng-hide="driveHidden" class="form-group">
<label class="col-sm-3 control-label">{% trans "Add Sites for Backup" %}</label>
<div class="col-sm-6">
<select ng-model="selectedWebsite" class="form-control">
{% for items in websites %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
<button type="button" ng-click="addSite('one')"
class="btn btn-primary">{% trans "Add Site" %}</button>
<button type="button" ng-click="addSite('all')"
class="btn btn-primary">{% trans "Add All" %}</button>
</div>
<div ng-hide="driveHidden" class="form-group">
<div style="border: 1px solid green;" class="col-sm-12">
<table style="margin-top: 2%" class="table">
<thead>
<tr>
<th>Last Run</th>
<th>All Sites</th>
<th>Frequency ({$ currently $})</th>
<th>Retention ({$ currently $})</th>
<th>Current Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>{$ lastRun $}</td>
<td>{$ allSites $}</td>
<td>
<select ng-change="changeFrequency()" ng-model="backupFrequency"
class="form-control">
<option>Never</option>
<option>Daily</option>
<option>Weekly</option>
</select>
</td>
<td>{$ currentStatus $}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div style="border: 1px solid green;" ng-hide="driveHidden" class="form-group">
<div class="row">
<div style="margin-left: 2%" class="col-sm-3">
<button data-toggle="modal" data-target="#backupLogs" ng-hide="driveHidden"
type="button" ng-click="fetchLogs()"
class="btn btn-gray">{% trans "View Logs" %}</button>
<div id="backupLogs" class="modal fade" role="dialog">
<div class="modal-dialog modal-lg">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;
</button>
<h4 class="modal-title">{% trans "Backup logs" %} <img
ng-hide="cyberPanelLoading"
src="{% static 'images/loading.gif' %}">
</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-sm-9">
</div>
<div class="col-sm-2">
<div class="form-group">
<select ng-model="recordsToShowLogs"
ng-change="fetchLogs()"
class="form-control" id="example-select">
<option>10</option>
<option>50</option>
<option>100</option>
</select>
</div>
</div>
</div>
<table style="margin: 0px; padding-bottom: 2%" class="table">
<thead>
<tr>
<th>Type</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="log in logs track by $index">
<td ng-bind="log.type"></td>
<td ng-bind="log.message"></td>
</tr>
</tbody>
</table>
<div style="margin-top: 2%" class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-8">
</div>
<div class="col-md-3">
<div class="form-group">
<select ng-model="currentPageLogs"
class="form-control"
ng-change="fetchLogs()">
<option ng-repeat="page in paginationLogs">
{$
$index + 1
$}
</option>
</select>
</div>
</div>
</div> <!-- end row -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
</div>
<div class="col-sm-2">
<div class="form-group">
<select ng-model="recordsToShow"
ng-change="fetchWebsites()"
class="form-control" id="example-select">
<option>10</option>
<option>50</option>
<option>100</option>
</select>
</div>
</div>
</div>
<table style="margin-top: 2%" class="table">
<thead>
<tr>
<th>Sites</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="website in websites track by $index">
<td ng-bind="website.name"></td>
<td>
<button type="button" ng-click="deleteSite(website.name)"
class="btn btn-danger">{% trans "Delete" %}</button>
</td>
</tr>
</tbody>
</table>
<div style="margin-top: 2%" class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-8">
</div>
<div class="col-md-3">
<div class="form-group">
<select ng-model="currentPage" class="form-control"
ng-change="fetchWebsites()">
<option ng-repeat="page in pagination">{$ $index + 1
$}
</option>
</select>
</div>
</div>
</div> <!-- end row -->
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,155 +1,167 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Backup Website" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Backup 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 Backup your websites" %}</p>
</div>
<div ng-controller="backupWebsiteControl" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Backup Website" %} <img ng-hide="backupLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<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 id="create-backup-select" ng-model="websiteToBeBacked" class="form-control">
{% for items in websiteList %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group destinationHide">
<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 "Home" %}</option>
</select>
</div>
</div>
<!---- if Backup 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 Backup is running------>
<div class="form-group destinationHide">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="createBackup()" id="createBackup" class="btn btn-primary btn-lg btn-block">{% trans "Create Backup" %}</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>
<div id="websiteDeleteSuccess" class="alert alert-success">
<p>Website <strong>{$ deletedWebsite $}</strong> {% trans "Successfully Deleted" %}</p>
</div>
</div>
</div>
</form>
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Backup 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 Backup your websites" %}</p>
</div>
<div ng-controller="backupWebsiteControl" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Backup Website" %} <img ng-hide="backupLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="alert alert-warning">
<p>Configure automatic backups to our secure servers in 60 seconds. <a
href="/backup/OneClickBackups">Set-up now.</a></p>
</div>
<div class="example-box-wrapper">
<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 id="create-backup-select" ng-model="websiteToBeBacked" class="form-control">
{% for items in websiteList %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group destinationHide">
<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 "Home" %}</option>
</select>
</div>
</div>
<!---- if Backup 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 Backup is running------>
<div class="form-group destinationHide">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="createBackup()" id="createBackup"
class="btn btn-primary btn-lg btn-block">{% trans "Create Backup" %}</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>
<div id="websiteDeleteSuccess" class="alert alert-success">
<p>Website <strong>{$ deletedWebsite $}</strong> {% trans "Successfully Deleted" %}
</p>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -12,10 +12,10 @@
<div class="container">
<div id="page-title">
<h2>{% trans "Set up Backup Destinations" %} - <a target="_blank"
href="https://cyberpanel.net/KnowledgeBase/home/add-destination-scheduled-local-sftp-remote-backups/"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a>
href="https://cyberpanel.net/KnowledgeBase/home/add-destination-scheduled-local-sftp-remote-backups/"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a>
</h2>
<p>{% trans "On this page you can set up your Backup destinations. (SFTP)" %}</p>
</div>
@@ -24,8 +24,12 @@
<div class="panel-body">
<h3 class="title-hero">
{% trans "Set up Backup Destinations." %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
src="{% static 'images/loading.gif' %}">
</h3>
<div class="alert alert-warning">
<p>Configure automatic backups to our secure servers in 60 seconds. <a
href="/backup/OneClickBackups">Set-up now.</a></p>
</div>
<div class="example-box-wrapper">
@@ -82,7 +86,8 @@
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Path" %}</label>
<div class="col-sm-6">
<input placeholder="Path on remote server to store backups." type="text" class="form-control" ng-model="path" required>
<input placeholder="Path on remote server to store backups." type="text"
class="form-control" ng-model="path" required>
</div>
</div>
@@ -122,7 +127,8 @@
<td ng-bind="record.username"></td>
<td ng-bind="record.path"></td>
<td ng-bind="record.port"></td>
<td ng-click="removeDestination('SFTP', record.name)"><img src="{% static 'images/delete.png' %}">
<td ng-click="removeDestination('SFTP', record.name)"><img
src="{% static 'images/delete.png' %}">
</td>
</tr>
@@ -164,8 +170,6 @@
<!--- SFTP --->
<!------ List of Destinations --------------->
<div ng-hide="localHide" class="form-group">
@@ -184,7 +188,8 @@
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.name"></td>
<td ng-bind="record.path"></td>
<td ng-click="removeDestination('local', record.name)"><img src="{% static 'images/delete.png' %}">
<td ng-click="removeDestination('local', record.name)"><img
src="{% static 'images/delete.png' %}">
</td>
</tr>

View File

@@ -0,0 +1,172 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "One-click Backups" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "One-click Backups" %} - <a target="_blank"
href="https://cyberpanel.net/KnowledgeBase/home/add-destination-scheduled-local-sftp-remote-backups/"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a>
</h2>
<p>{% trans "On this page you purchase and manage one-click backups." %}</p>
</div>
<div ng-controller="backupPlanNowOneClick" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Set up Backup Destinations." %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
{% if status == 1 %}
<div class="alert alert-info">
<p>You have successfully purchased a backup plan.</p>
</div>
{% elif status == 0 %}
<div class="alert alert-danger">
<p>Your purchase was not successful.</p> {{ message }}
</div>
{% elif status == 4 %}
<div class="alert alert-danger">
{{ message }}
</div>
{% endif %}
<form action="/" class="form-horizontal bordered-row">
<p style="font-size: 15px;margin: 1%;">With CyberPanel's one-click backups, you can easily back up your website to our secure
servers in just 60 seconds. It's simple, fast, and reliable.</p>
<!------ List of Purchased backup plans --------------->
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "Account" %}</th>
<th>{% trans "Plan Name" %}</th>
<th>{% trans "Subscription" %}</th>
<th>{% trans "Billing Cycle" %}</th>
<th>{% trans "Purchase Date" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for plan in bPlans %}
<tr>
<td>{{ plan.sftpUser }}</td>
<td>{{ plan.planName }}</td>
<td>{{ plan.subscription }}</td>
{% if plan.months == '1' %}
<td>${{ plan.price }}/month</td>
{% else %}
<td>${{ plan.price }}/year</td>
{% endif %}
<td>{{ plan.date }}</td>
<td>
{% if plan.state == 1 %}
<a
href="{% url 'ManageOCBackups' %}?id={{ plan.id }}">
<button style="margin-bottom: 1%" type="button"
class="btn btn-primary btn-lg btn-block">{% trans "Schedule Backups" %}</button>
</a>
<a href="{% url 'RestoreOCBackups' %}?id={{ plan.id }}">
<button type="button"
class="btn btn-primary btn-lg btn-block">{% trans "Restore Backups" %}</button>
</a>
{% else %}
<button type="button"
ng-click="DeployAccount('{{ plan.id }}')"
class="btn btn-primary btn-lg btn-block">{% trans "Deploy Account" %}</button>
{% endif %}
</td>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!------ List of Purchased backup plans --------------->
<!------ List of Backup plans --------------->
<h3 class="title-hero">
{% trans "Subscribe to one-click backup plans." %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "Plan Name" %}</th>
<th>{% trans "Monthly Price" %}</th>
<th>{% trans "Yearly Price" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for plan in plans %}
<tr>
<td>{{ plan.name }}</td>
<td>${{ plan.monthlyPrice }}</td>
<td>${{ plan.yearlyPrice }}</td>
<td>
<button type="button"
ng-click="BuyNowBackupP('{{ plan.name }}', '{{ plan.monthlyPrice }}', '{{ plan.yearlyPrice }}', 1)"
class="btn btn-primary btn-lg btn-block">{% trans "Buy Monthly" %}</button>
<button type="button"
ng-click="BuyNowBackupP('{{ plan.name }}', '{{ plan.monthlyPrice }}', '{{ plan.yearlyPrice }}', 12)"
class="btn btn-primary btn-lg btn-block">{% trans "Buy Yearly" %}</button>
</td>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!------ List of backup plans --------------->
<!--- AWS End --->
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,114 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Restore Website - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Restore 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 restore your websites, Backup should be generated from CyberPanel Backup generation tool, it will detect all Backups under <strong>/home/backup</strong>." %}</p>
</div>
<div ng-controller="OneClickrestoreWebsiteControl" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Restore Website" %} <img ng-hide="restoreLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Folder" %}</label>
<div class="col-sm-6">
<select ng-change="FetchOCSites()" ng-model="ocFolder" class="form-control">
{% for items in directories %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Backup" %}</label>
<div class="col-sm-6">
<select ng-model="ocFile" class="form-control">
<option ng-repeat="item in backups">{$ item $}</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="StartOCRestore()"
class="btn btn-primary btn-lg">{% trans "Restore Backup" %}</button>
</div>
</div>
<div ng-hide="installationProgress" class="form-group">
<label class="col-sm-2 control-label"></label>
<div class="col-sm-7">
<div class="alert alert-success text-center">
<h2>{$ currentStatus $}</h2>
</div>
<div class="progress">
<div id="installProgress" class="progress-bar" role="progressbar" aria-valuenow="70"
aria-valuemin="0" aria-valuemax="100" style="width:0%">
<span class="sr-only">70% Complete</span>
</div>
</div>
<div ng-hide="errorMessageBox" class="alert alert-danger">
<p>{% trans "Error message:" %} {$ errorMessage $}</p>
</div>
<div ng-hide="success" class="alert alert-success">
<p>{% trans "Backup restored successfully." %}</p>
</div>
<div ng-hide="couldNotConnect" class="alert alert-danger">
<p>{% trans "Could not connect to server. Please refresh this page." %}</p>
</div>
</div>
</div>
<div ng-hide="installationProgress" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-disabled="goBackDisable" ng-click="goBack()"
class="btn btn-primary btn-lg">{% trans "Go Back" %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -4,6 +4,13 @@ from . import views
urlpatterns = [
url(r'^$', views.loadBackupHome, name='loadBackupHome'),
url(r'^getCurrentBackups', views.getCurrentBackups, name='getCurrentBackups'),
url(r'^OneClickBackups', views.OneClickBackups, name='OneClickBackups'),
url(r'^ManageOCBackups', views.ManageOCBackups, name='ManageOCBackups'),
url(r'^RestoreOCBackups', views.RestoreOCBackups, name='RestoreOCBackups'),
url(r'^fetchOCSites', views.fetchOCSites, name='fetchOCSites'),
url(r'^StartOCRestore', views.StartOCRestore, name='StartOCRestore'),
url(r'^DeployAccount', views.DeployAccount, name='DeployAccount'),
url(r'^backupSite', views.backupSite, name='backupSite'),
url(r'^restoreSite', views.restoreSite, name='restoreSite'),
url(r'^gDrive$', views.gDrive, name='gDrive'),
@@ -16,7 +23,6 @@ urlpatterns = [
url(r'^deleteSitegDrive$', views.deleteSitegDrive, name='deleteSitegDrive'),
url(r'^fetchDriveLogs$', views.fetchDriveLogs, name='fetchDriveLogs'),
url(r'^submitBackupCreation', views.submitBackupCreation, name='submitBackupCreation'),
url(r'^cancelBackupCreation', views.cancelBackupCreation, name='cancelBackupCreation'),
url(r'^backupStatus', views.backupStatus, name='backupStatus'),
@@ -42,10 +48,8 @@ urlpatterns = [
url(r'^submitBackupSchedule', views.submitBackupSchedule, name='submitBackupSchedule'),
url(r'^scheduleDelete', views.scheduleDelete, name='scheduleDelete'),
url(r'^remoteBackups', views.remoteBackups, name='remoteBackups'),
url(r'^submitRemoteBackups', views.submitRemoteBackups, name='submitRemoteBackups'),
url(r'^getRemoteTransferStatus', views.getRemoteTransferStatus, name='getRemoteTransferStatus'),
@@ -67,4 +71,4 @@ urlpatterns = [
url(r'^deleteAccountNormal$', views.deleteAccountNormal, name='deleteAccountNormal'),
url(r'^fetchNormalLogs$', views.fetchNormalLogs, name='fetchNormalLogs'),
]
]

View File

@@ -481,5 +481,56 @@ def fetchNormalLogs(request):
userID = request.session['userID']
wm = BackupManager()
return wm.fetchNormalLogs(request, userID)
except KeyError:
return redirect(loadLoginPage)
def OneClickBackups(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.OneClickBackups(request, userID)
except KeyError:
return redirect(loadLoginPage)
def ManageOCBackups(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.ManageOCBackups(request, userID)
except KeyError:
return redirect(loadLoginPage)
def RestoreOCBackups(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.RestoreOCBackups(request, userID)
except KeyError:
return redirect(loadLoginPage)
def fetchOCSites(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.fetchOCSites(request, userID)
except KeyError:
return redirect(loadLoginPage)
def StartOCRestore(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.StartOCRestore(request, userID)
except KeyError:
return redirect(loadLoginPage)
def DeployAccount(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.DeployAccount(request, userID)
except KeyError:
return redirect(loadLoginPage)

View File

@@ -77,7 +77,7 @@
<!-- HELPERS -->
{% with version="2.3.5.4" %}
{% with version="2.3.5.6" %}
<link rel="stylesheet" type="text/css" href="{% static 'baseTemplate/assets/finalBase/finalBase.css' %}">
@@ -690,6 +690,11 @@
<div class="sidebar-submenu">
<ul>
{% if admin or createBackup %}
<li><a href="{% url 'OneClickBackups' %}"
title="{% trans 'One-Click Backups' %}"><span>{% trans "One-Click Backups" %}</span></a>
</li>
{% endif %}
{% if admin or createBackup %}
<li><a href="{% url 'backupSite' %}"
title="{% trans 'Create Backup' %}"><span>{% trans "Create Backup" %}</span></a>
@@ -947,9 +952,9 @@
<li><a href="{% url 'packageManager' %}"
title="{% trans 'Package Manager' %}"><span>{% trans "Package Manager" %}</span></a>
</li>
{# <li><a href="{% url 'Switchoffsecurity' %}"#}
{# title="{% trans 'Switch off security' %}"><span>{% trans "Switch off security" %}</span></a>#}
{# </li>#}
{# <li><a href="{% url 'Switchoffsecurity' %}"#}
{# title="{% trans 'Switch off security' %}"><span>{% trans "Switch off security" %}</span></a>#}
{# </li>#}
</ul>
</div><!-- .sidebar-submenu -->
@@ -1149,6 +1154,12 @@
href="/base/onboarding">Setup Wizard.</a></p>
</div>
{% endif %}
{% if backupDisplay == 1 %}
<div class="alert alert-warning">
<p>Looks like your websites are not secured with automatic backups. <a
href="/backup/OneClickBackups">Configure now.</a></p>
</div>
{% endif %}
{% block content %}
{% endblock %}

View File

@@ -652,8 +652,18 @@ Automatic backup failed for %s on %s.
except BaseException as msg:
NormalBackupJobLogs(owner=backupjob, status=backupSchedule.INFO,
message=f'Failed to make sftp connection {str(msg)}').save()
print(str(msg))
continue
try:
command = f'find cpbackups -type f -mtime +{destinationConfig["retention"]} -exec rm -f {{}} \\;'
ssh.exec_command(command)
logging.writeToFile(command)
except:
pass
# Execute the command to create the remote directory
command = f'mkdir -p {finalPath}'
stdin, stdout, stderr = ssh.exec_command(command)

View File

@@ -1,8 +1,12 @@
#!/usr/local/CyberCP/bin/python
import argparse
import json
import os, sys
import shutil
import time
from io import StringIO
import paramiko
from ApachController.ApacheVhosts import ApacheVhost
from loginSystem.models import Administrator
@@ -18,7 +22,7 @@ import threading as multi
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
import subprocess
from websiteFunctions.models import ChildDomains, Websites, WPSites, WPStaging, wpplugins, WPSitesBackup, \
RemoteBackupConfig
RemoteBackupConfig, NormalBackupDests
from plogical import randomPassword
from plogical.mysqlUtilities import mysqlUtilities
from databases.models import Databases
@@ -86,6 +90,8 @@ class ApplicationInstaller(multi.Thread):
self.RestoreWPbackupNow()
elif self.installApp == 'UpgradeCP':
self.UpgradeCP()
elif self.installApp == 'StartOCRestore':
self.StartOCRestore()
except BaseException as msg:
logging.writeToFile(str(msg) + ' [ApplicationInstaller.run]')
@@ -6358,6 +6364,99 @@ class ApplicationInstaller(multi.Thread):
logging.statusWriter(self.tempStatusPath, str(msg))
return 0, str(msg)
def StartOCRestore(self):
try:
id = self.extraArgs['id']
folder = self.extraArgs['folder']
backupfile = self.extraArgs['backupfile']
tempStatusPath = self.extraArgs['tempStatusPath']
userID = self.extraArgs['userID']
self.tempStatusPath = tempStatusPath
statusFile = open(tempStatusPath, 'w')
statusFile.writelines("Download started..,30")
statusFile.close()
from IncBackups.models import OneClickBackups
ocb = OneClickBackups.objects.get(pk=id)
# Load the private key
nbd = NormalBackupDests.objects.get(name=ocb.sftpUser)
ip = json.loads(nbd.config)['ip']
# Connect to the remote server using the private key
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Read the private key content
private_key_path = '/root/.ssh/cyberpanel'
key_content = ProcessUtilities.outputExecutioner(f'cat {private_key_path}').rstrip('\n')
# Load the private key from the content
key_file = StringIO(key_content)
key = paramiko.RSAKey.from_private_key(key_file)
# Connect to the server using the private key
ssh.connect(ip, username=ocb.sftpUser, pkey=key)
sftp = ssh.open_sftp()
sftp.get(f'cpbackups/{folder}/{backupfile}', f'/home/cyberpanel/{backupfile}')
if not os.path.exists('/home/backup'):
command = 'mkdir /home/backup'
ProcessUtilities.executioner(command)
command = f'mv /home/cyberpanel/{backupfile} /home/backup/{backupfile}'
ProcessUtilities.executioner(command)
from backup.backupManager import BackupManager
wm = BackupManager()
resp = wm.submitRestore({'backupFile': backupfile}, userID)
if json.loads(resp.content)['restoreStatus'] == 0:
statusFile = open(tempStatusPath, 'w')
statusFile.writelines(f"Failed to restore backup. Error {json.loads(resp.content)['error_message']}. [404]")
statusFile.close()
command = f'rm -f /home/backup/{backupfile}'
ProcessUtilities.executioner(command)
return 0
while True:
resp = wm.restoreStatus({'backupFile': backupfile})
resp = json.loads(resp.content)
if resp['abort'] == 1 and resp['running'] == 'Completed':
statusFile = open(tempStatusPath, 'w')
statusFile.writelines("Successfully Installed. [200]")
statusFile.close()
command = f'rm -f /home/backup/{backupfile}'
ProcessUtilities.executioner(command)
return 0
elif resp['abort'] == 1 and resp['running'] == 'Error':
statusFile = open(tempStatusPath, 'w')
statusFile.writelines(
f"Failed to restore backup. Error {resp['status']}. [404]")
statusFile.close()
command = f'rm -f /home/backup/{backupfile}'
ProcessUtilities.executioner(command)
break
else:
statusFile = open(tempStatusPath, 'w')
statusFile.writelines(f"{resp['status']},60")
statusFile.close()
command = f'rm -f /home/backup/{backupfile}'
ProcessUtilities.executioner(command)
time.sleep(3)
except BaseException as msg:
statusFile = open(self.tempStatusPath, 'w')
statusFile.writelines(str(msg) + " [404]")
statusFile.close()
return 0
def main():
parser = argparse.ArgumentParser(description='CyberPanel Application Installer')

View File

@@ -1,3 +1,4 @@
import json
import os
import sys
@@ -41,7 +42,7 @@ from random import randint
from plogical.processUtilities import ProcessUtilities
try:
from websiteFunctions.models import Websites, ChildDomains, Backups
from websiteFunctions.models import Websites, ChildDomains, Backups, NormalBackupDests
from databases.models import Databases
from loginSystem.models import Administrator
from plogical.dnsUtilities import DNS
@@ -1329,35 +1330,48 @@ class backupUtilities:
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, port=int(port), username=user, password=password)
if password != 'NOT-NEEDED':
commands = [
"mkdir -p .ssh",
"rm -f .ssh/temp",
"rm -f .ssh/authorized_temp",
"cp .ssh/authorized_keys .ssh/temp",
"chmod 700 .ssh",
"chmod g-w ~",
]
ssh.connect(IPAddress, port=int(port), username=user, password=password)
commands = [
"mkdir -p .ssh",
"rm -f .ssh/temp",
"rm -f .ssh/authorized_temp",
"cp .ssh/authorized_keys .ssh/temp",
"chmod 700 .ssh",
"chmod g-w ~",
]
for command in commands:
try:
ssh.exec_command(command)
except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(f'Error executing remote command {command}. Error {str(msg)}')
for command in commands:
try:
ssh.exec_command(command)
except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(
f'Error executing remote command {command}. Error {str(msg)}')
ssh.close()
ssh.close()
sendKey = backupUtilities.sendKey(IPAddress, password, port, user)
sendKey = backupUtilities.sendKey(IPAddress, password, port, user)
if sendKey[0] == 1:
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
ProcessUtilities.executioner(command)
return [1, "None"]
if sendKey[0] == 1:
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
ProcessUtilities.executioner(command)
return [1, "None"]
else:
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
ProcessUtilities.executioner(command)
return [0, sendKey[1]]
else:
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
ProcessUtilities.executioner(command)
return [0, sendKey[1]]
# Load the private key
private_key_path = '/root/.ssh/cyberpanel'
keyPrivate = paramiko.RSAKey(filename=private_key_path)
# Connect to the remote server using the private key
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, username=user, pkey=keyPrivate)
return [1, "None"]
except paramiko.AuthenticationException:
return [0, 'Authentication failed. [setupSSHKeys]']
@@ -2345,6 +2359,37 @@ def getConnectionStatus(ipAddress):
except BaseException as msg:
print(str(msg))
def FetchOCBackupsFolders(id, owner):
# Load the private key
private_key_path = '/root/.ssh/cyberpanel'
keyPrivate = paramiko.RSAKey(filename=private_key_path)
from IncBackups.models import OneClickBackups
admin = Administrator.objects.get(userName=owner)
ocb = OneClickBackups.objects.get(pk=id, owner=admin)
nbd = NormalBackupDests.objects.get(name=ocb.sftpUser)
ip = json.loads(nbd.config)['ip']
# Connect to the remote server using the private key
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, username=ocb.sftpUser, pkey=keyPrivate)
# Command to list directories under the specified path
command = f"ls -d cpbackups/*/"
# Execute the command
stdin, stdout, stderr = ssh.exec_command(command)
# Read the results
directories = stdout.read().decode().splitlines()
# Print directories
for directory in directories:
print(directory)
def main():
parser = argparse.ArgumentParser(description='CyberPanel Backup Generator')
@@ -2391,6 +2436,10 @@ def main():
parser.add_argument('--CPHomeStorage', help='')
### id
parser.add_argument('--id', help='')
args = parser.parse_args()
@@ -2439,5 +2488,8 @@ def main():
bu = backupUtilities(extraArgs)
bu.SubmitS3BackupRestore()
elif args.function == 'FetchOCBackupsFolders':
FetchOCBackupsFolders(args.id, args.user)
if __name__ == "__main__":
main()

View File

@@ -77,6 +77,13 @@ Please launch the <a href="/base/onboarding">set-up wizard</a> to get maximum ou
except:
pass
from IncBackups.models import OneClickBackups
if OneClickBackups.objects.filter(owner=admin).count() == 0:
self.data['backupDisplay'] = 1
else:
self.data['backupDisplay'] = 0
ACLManager.GetServiceStatus(self.data)
self.data.update(currentACL)