From bafa1832874433187b9dafc45327056ebed34bf2 Mon Sep 17 00:00:00 2001 From: Usman Nasir Date: Mon, 21 Sep 2020 22:19:52 +0500 Subject: [PATCH] scheduled backups improvement --- backup/backupManager.py | 262 +++++++++++++------- backup/static/backup/backup.js | 113 ++++++++- backup/templates/backup/backupSchedule.html | 80 +++++- backup/urls.py | 4 + backup/views.py | 32 +++ websiteFunctions/models.py | 9 + 6 files changed, 386 insertions(+), 114 deletions(-) diff --git a/backup/backupManager.py b/backup/backupManager.py index 95b05e574..03838e7c6 100755 --- a/backup/backupManager.py +++ b/backup/backupManager.py @@ -26,7 +26,7 @@ import requests import google.oauth2.credentials import googleapiclient.discovery from googleapiclient.discovery import build -from websiteFunctions.models import NormalBackupDests +from websiteFunctions.models import NormalBackupDests, NormalBackupJobs, NormalBackupSites class BackupManager: @@ -880,7 +880,9 @@ class BackupManager: for dest in destinations: dests.append(dest.name) - return render(request, 'backup/backupSchedule.html', {'destinations': dests}) + websitesName = ACLManager.findAllSites(currentACL, userID) + + return render(request, 'backup/backupSchedule.html', {'destinations': dests, 'websites': websitesName}) except BaseException as msg: return HttpResponse(str(msg)) @@ -920,111 +922,27 @@ class BackupManager: def submitBackupSchedule(self, userID=None, data=None): try: - backupDest = data['backupDest'] - backupFreq = data['backupFreq'] + selectedAccount = data['selectedAccount'] + name = data['name'] + backupFrequency = data['backupFrequency'] currentACL = ACLManager.loadedACL(userID) if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0: return ACLManager.loadErrorJson('scheduleStatus', 0) - path = "/etc/crontab" + nbd = NormalBackupDests.objects.get(name=selectedAccount) - ## check if already exists - try: - schedule = backupSchedules.objects.get(frequency=backupFreq) + config = {'frequency': backupFrequency} - if schedule.dest.destLoc == backupDest: - final_json = json.dumps( - {'scheduleStatus': 0, 'error_message': "This schedule already exists"}) - return HttpResponse(final_json) - else: - if backupDest == "Home" and backupFreq == "Daily": - cronJob = "0 3 * * * root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupScheduleLocal.py" - elif backupDest == "Home" and backupFreq == "Weekly": - cronJob = "0 0 * * 0 root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupScheduleLocal.py " - elif backupDest != "Home" and backupFreq == "Daily": - cronJob = "0 3 * * * root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupSchedule.py" - elif backupDest != "Home" and backupFreq == "Weekly": - cronJob = "0 0 * * 0 root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupSchedule.py " + nbj = NormalBackupJobs(owner=nbd, name=name, config=config) + nbj.save() - command = "cat " + path - output = ProcessUtilities.outputExecutioner(command) - - finalCronJob = output + cronJob - tempCronPath = "/home/cyberpanel/" + str(randint(1000, 9999)) - - writeToFile = open(tempCronPath, 'a') - writeToFile.writelines(finalCronJob + "\n") - writeToFile.close() - - command = "mv " + tempCronPath + " " + path - ProcessUtilities.executioner(command) - - command = 'chown root:root %s' % (path) - ProcessUtilities.executioner(command) - - command = "systemctl restart crond" - ProcessUtilities.executioner(command) - - ## Set local path for backup - - if backupDest == "Home": - writeToFile = open(BackupManager.localBackupPath, 'w') - writeToFile.write(data['localPath']) - writeToFile.close() - - destination = dest.objects.get(destLoc=backupDest) - newSchedule = backupSchedules(dest=destination, frequency=backupFreq) - newSchedule.save() - - final_json = json.dumps({'scheduleStatus': 1, 'error_message': "None"}) - return HttpResponse(final_json) - except: - if backupDest == "Home" and backupFreq == "Daily": - cronJob = "0 3 * * * root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupScheduleLocal.py" - elif backupDest == "Home" and backupFreq == "Weekly": - cronJob = "0 0 * * 0 root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupScheduleLocal.py " - elif backupDest != "Home" and backupFreq == "Daily": - cronJob = "0 3 * * * root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupSchedule.py" - elif backupDest != "Home" and backupFreq == "Weekly": - cronJob = "0 0 * * 0 root /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/backupSchedule.py " - - command = "cat " + path - output = ProcessUtilities.outputExecutioner(command) - - finalCronJob = output + cronJob - tempCronPath = "/home/cyberpanel/" + str(randint(1000, 9999)) - - writeToFile = open(tempCronPath, 'a') - writeToFile.writelines(finalCronJob + "\n") - writeToFile.close() - - command = "sudo mv " + tempCronPath + " " + path - ProcessUtilities.executioner(command) - - command = 'chown root:root %s' % (path) - ProcessUtilities.executioner(command) - - command = "sudo systemctl restart crond" - ProcessUtilities.executioner(command) - - destination = dest.objects.get(destLoc=backupDest) - newSchedule = backupSchedules(dest=destination, frequency=backupFreq) - newSchedule.save() - - ## Set local path for backup - - if backupDest == "Home": - writeToFile = open(BackupManager.localBackupPath, 'w') - writeToFile.write(data['localPath']) - writeToFile.close() - - final_json = json.dumps({'scheduleStatus': 1, 'error_message': "None"}) - return HttpResponse(final_json) + final_json = json.dumps({'status': 1, 'scheduleStatus': 0}) + return HttpResponse(final_json) except BaseException as msg: - final_json = json.dumps({'scheduleStatus': 0, 'error_message': str(msg)}) + final_json = json.dumps({'status': 0, 'scheduleStatus': 0, 'error_message': str(msg)}) return HttpResponse(final_json) def scheduleDelete(self, userID=None, data=None): @@ -1541,3 +1459,155 @@ class BackupManager: data = {'remoteRestoreStatus': 0, 'error_message': str(msg)} json_data = json.dumps(data) return HttpResponse(json_data) + + def fetchgNormalSites(self, request=None, userID=None, data=None): + try: + + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + data = json.loads(request.body) + + selectedAccount = data['selectedAccount'] + recordsToShow = int(data['recordsToShow']) + page = int(str(data['page']).strip('\n')) + + nbd = NormalBackupJobs.objects.get(name=selectedAccount) + + if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0: + return ACLManager.loadErrorJson('scheduleStatus', 0) + + websites = nbd.normalbackupsites_set.all() + + from s3Backups.s3Backups import S3Backups + + pagination = S3Backups.getPagination(len(websites), recordsToShow) + endPageNumber, finalPageNumber = S3Backups.recordsPointer(page, recordsToShow) + finalWebsites = websites[finalPageNumber:endPageNumber] + + json_data = "[" + checker = 0 + counter = 0 + + from plogical.backupSchedule import backupSchedule + + for website in finalWebsites: + + dic = { + 'name': website.domain.domain + } + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + counter = counter + 1 + + json_data = json_data + ']' + + + data_ret = {'status': 1, 'websites': json_data, 'pagination': pagination} + 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 fetchNormalJobs(self, request=None, userID=None, data=None): + try: + + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + data = json.loads(request.body) + + selectedAccount = data['selectedAccount'] + + nbd = NormalBackupDests.objects.get(name=selectedAccount) + + if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0: + return ACLManager.loadErrorJson('scheduleStatus', 0) + + allJobs = nbd.normalbackupjobs_set.all() + + alljbs = [] + + for items in allJobs: + alljbs.append(items.name) + + data_ret = {'status': 1, 'jobs': alljbs} + 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 addSiteNormal(self, request=None, userID=None, data=None): + try: + + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + data = json.loads(request.body) + + selectedJob = data['selectedJob'] + selectedWebsite = data['selectedWebsite'] + + nbj = NormalBackupJobs.objects.get(name=selectedJob) + website = Websites.objects.get(domain=selectedWebsite) + + if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0: + return ACLManager.loadErrorJson('scheduleStatus', 0) + + try: + NormalBackupSites.objects.get(owner=nbj, domain=website) + except: + NormalBackupSites(owner=nbj, domain=website).save() + + data_ret = {'status': 1} + 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 deleteSiteNormal(self, request=None, userID=None, data=None): + try: + + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + data = json.loads(request.body) + + selectedJob = data['selectedJob'] + selectedWebsite = data['website'] + + nbj = NormalBackupJobs.objects.get(name=selectedJob) + website = Websites.objects.get(domain=selectedWebsite) + + if ACLManager.currentContextPermission(currentACL, 'scheDuleBackups') == 0: + return ACLManager.loadErrorJson('scheduleStatus', 0) + + try: + NormalBackupSites.objects.get(owner=nbj, domain=website).delete() + except: + pass + + data_ret = {'status': 1} + 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) diff --git a/backup/static/backup/backup.js b/backup/static/backup/backup.js index 9d2d49516..07f504662 100755 --- a/backup/static/backup/backup.js +++ b/backup/static/backup/backup.js @@ -1577,10 +1577,111 @@ app.controller('scheduleBackup', function ($scope, $http) { $scope.cyberPanelLoading = true; $scope.driveHidden = true; + $scope.jobsHidden = true; $scope.currentPage = 1; $scope.recordsToShow = 10; + $scope.fetchJobs = function () { + + $scope.cyberPanelLoading = false; + + var config = { + headers: { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + var data = { + selectedAccount: $scope.selectedAccount, + }; + + + dataurl = "/backup/fetchNormalJobs"; + + $http.post(dataurl, data, config).then(ListInitialDatas, cantLoadInitialDatas); + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + if (response.data.status === 1) { + $scope.jobsHidden = false; + new PNotify({ + title: 'Success', + text: 'Successfully fetched.', + type: 'success' + }); + $scope.jobs = response.data.jobs; + } 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.addSchedule = function () { + $scope.cyberPanelLoading = false; + + var config = { + headers: { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + var data = { + selectedAccount: $scope.selectedAccount, + name: $scope.name, + backupFrequency: $scope.backupFrequency + }; + + dataurl = "/backup/submitBackupSchedule"; + + $http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData); + + + function ListInitialData(response) { + $scope.cyberPanelLoading = true; + if (response.data.status === 1) { + new PNotify({ + title: 'Success', + text: 'Schedule successfully added.', + type: 'success' + }); + $scope.fetchWebsites(); + } else { + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type: 'error' + }); + } + } + + function cantLoadInitialData(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type: 'error' + }); + } + + + }; + $scope.fetchWebsites = function () { $scope.cyberPanelLoading = false; @@ -1592,13 +1693,13 @@ app.controller('scheduleBackup', function ($scope, $http) { }; var data = { - selectedAccount: $scope.selectedAccount, + selectedAccount: $scope.selectedJob, page: $scope.currentPage, recordsToShow: $scope.recordsToShow }; - dataurl = "/backup/fetchgDriveSites"; + dataurl = "/backup/fetchgNormalSites"; $http.post(dataurl, data, config).then(ListInitialDatas, cantLoadInitialDatas); @@ -1646,10 +1747,10 @@ app.controller('scheduleBackup', function ($scope, $http) { }; var data = { selectedWebsite: $scope.selectedWebsite, - selectedAccount: $scope.selectedAccount + selectedJob: $scope.selectedJob }; - dataurl = "/backup/addSitegDrive"; + dataurl = "/backup/addSiteNormal"; $http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData); @@ -1787,11 +1888,11 @@ app.controller('scheduleBackup', function ($scope, $http) { } }; var data = { - selectedAccount: $scope.selectedAccount, + selectedJob: $scope.selectedJob, website: website }; - dataurl = "/backup/deleteSitegDrive"; + dataurl = "/backup/deleteSiteNormal"; $http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData); diff --git a/backup/templates/backup/backupSchedule.html b/backup/templates/backup/backupSchedule.html index e8b1fbf74..ad0246e73 100755 --- a/backup/templates/backup/backupSchedule.html +++ b/backup/templates/backup/backupSchedule.html @@ -9,7 +9,7 @@ {% get_current_language as LANGUAGE_CODE %} -
+
-
+

- {% trans "Schedule Back up" %} + {% trans "Create New Backup Schedule" %}

@@ -34,7 +34,64 @@
- + {% for items in destinations %} + + {% endfor %} + +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ +
+ +
+ + +
+
+ + + + +
+
+
+ +
+
+

+ {% trans "Manage Existing Back up Schedules" %} +

+
+ + +
+ +
+ +
+ - - - +
- Currently: {$ currently $} +
diff --git a/backup/urls.py b/backup/urls.py index a4b9df825..ec955eb65 100755 --- a/backup/urls.py +++ b/backup/urls.py @@ -58,5 +58,9 @@ urlpatterns = [ url(r'^backupLogs$', views.backupLogs, name='backupLogs'), url(r'^fetchLogs$', views.fetchLogs, name='fetchLogs'), + url(r'^fetchgNormalSites$', views.fetchgNormalSites, name='fetchgNormalSites'), + url(r'^fetchNormalJobs$', views.fetchNormalJobs, name='fetchNormalJobs'), + url(r'^addSiteNormal$', views.addSiteNormal, name='addSiteNormal'), + url(r'^deleteSiteNormal$', views.deleteSiteNormal, name='deleteSiteNormal'), ] \ No newline at end of file diff --git a/backup/views.py b/backup/views.py index 18c0c626a..17d100799 100755 --- a/backup/views.py +++ b/backup/views.py @@ -419,3 +419,35 @@ def localInitiate(request): return wm.submitBackupCreation(1, json.loads(request.body)) except BaseException as msg: logging.writeToFile(str(msg)) + +def fetchgNormalSites(request): + try: + userID = request.session['userID'] + wm = BackupManager() + return wm.fetchgNormalSites(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def fetchNormalJobs(request): + try: + userID = request.session['userID'] + wm = BackupManager() + return wm.fetchNormalJobs(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def addSiteNormal(request): + try: + userID = request.session['userID'] + wm = BackupManager() + return wm.addSiteNormal(request, userID) + except KeyError: + return redirect(loadLoginPage) + +def deleteSiteNormal(request): + try: + userID = request.session['userID'] + wm = BackupManager() + return wm.deleteSiteNormal(request, userID) + except KeyError: + return redirect(loadLoginPage) diff --git a/websiteFunctions/models.py b/websiteFunctions/models.py index bf1231638..78a20d5ee 100755 --- a/websiteFunctions/models.py +++ b/websiteFunctions/models.py @@ -83,3 +83,12 @@ class GDriveJobLogs(models.Model): class NormalBackupDests(models.Model): name = models.CharField(max_length=25) config = models.TextField() + +class NormalBackupJobs(models.Model): + owner = models.ForeignKey(NormalBackupDests, on_delete=models.CASCADE) + name = models.CharField(max_length=25) + config = models.TextField() + +class NormalBackupSites(models.Model): + owner = models.ForeignKey(NormalBackupJobs, on_delete=models.CASCADE) + domain = models.ForeignKey(Websites, on_delete=models.CASCADE)