feature: configure server mailer for CyberPanel notifications

This commit is contained in:
Usman Nasir
2020-03-17 20:51:45 +05:00
parent bae625a2d2
commit 88aee551c1
17 changed files with 2192 additions and 1625 deletions

View File

@@ -797,6 +797,8 @@
<div class="sidebar-submenu"> <div class="sidebar-submenu">
<ul> <ul>
<li><a href="{% url 'serverMail' %}"
title="{% trans 'Server Mail' %}"><span>{% trans "Server Mail" %}</span></a></li>
<li><a href="{% url 'accessLogs' %}" <li><a href="{% url 'accessLogs' %}"
title="{% trans 'Access Log' %}"><span>{% trans "Access Log" %}</span></a></li> title="{% trans 'Access Log' %}"><span>{% trans "Access Log" %}</span></a></li>
<li><a href="{% url 'errorLogs' %}" <li><a href="{% url 'errorLogs' %}"

View File

@@ -8,11 +8,32 @@ class CyberCPLogFileWriter:
fileName = "/home/cyberpanel/error-logs.txt" fileName = "/home/cyberpanel/error-logs.txt"
@staticmethod @staticmethod
def SendEmail(sender, receivers, message): def SendEmail(sender, receivers, message, subject=None, type=None):
try: try:
smtpObj = smtplib.SMTP('localhost') smtpPath = '/home/cyberpanel/smtpDetails'
smtpObj.sendmail(sender, receivers, message)
print("Successfully sent email") if os.path.exists(smtpPath):
import json
mailSettings = json.loads(open(smtpPath, 'r').read())
smtpHost = mailSettings['smtpHost']
smtpPort = mailSettings['smtpPort']
smtpUserName = mailSettings['smtpUserName']
smtpPassword = mailSettings['smtpPassword']
smtpServer = smtplib.SMTP(str(smtpHost), int(smtpPort))
smtpServer.login(smtpUserName, smtpPassword)
##
if subject != None:
message = 'Subject: {}\n\n{}'.format(subject, message)
smtpServer.sendmail(smtpUserName, receivers, message)
else:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print("Successfully sent email")
except BaseException as msg: except BaseException as msg:
CyberCPLogFileWriter.writeToFile(str(msg)) CyberCPLogFileWriter.writeToFile(str(msg))

View File

@@ -9,6 +9,11 @@ from IncBackups.IncBackupsControl import IncJobs
from IncBackups.models import BackupJob from IncBackups.models import BackupJob
from random import randint from random import randint
import argparse import argparse
import json
from websiteFunctions.models import GitLogs, Websites
from websiteFunctions.website import WebsiteManager
import time
try: try:
from plogical.virtualHostUtilities import virtualHostUtilities from plogical.virtualHostUtilities import virtualHostUtilities
from plogical.mailUtilities import mailUtilities from plogical.mailUtilities import mailUtilities
@@ -18,6 +23,7 @@ except:
class IncScheduler(): class IncScheduler():
logPath = '/home/cyberpanel/incbackuplogs' logPath = '/home/cyberpanel/incbackuplogs'
gitFolder = '/home/cyberpanel/git'
@staticmethod @staticmethod
def startBackup(type): def startBackup(type):
@@ -82,6 +88,76 @@ class IncScheduler():
except BaseException as msg: except BaseException as msg:
logging.writeToFile(str(msg)) logging.writeToFile(str(msg))
@staticmethod
def git(type):
try:
for website in os.listdir(IncScheduler.gitFolder):
finalText = ''
web = Websites.objects.get(domain=website)
message = '[%s Cron] Checking if %s has any pending commits on %s.' % (type, website, time.strftime("%m.%d.%Y_%H-%M-%S"))
finalText = '%s\n' % (message)
GitLogs(owner=web, type='INFO', message = message).save()
finalPathInside = '%s/%s' % (IncScheduler.gitFolder, website)
for file in os.listdir(finalPathInside):
if file.find('public_html') > -1:
finalPath = '/home/%s/public_html' % (website)
finalPathConf = '%s/%s' % (finalPathInside, file)
elif file.find('vmail') > -1:
finalPath = '/home/vmail/%s' % (website)
finalPathConf = '%s/%s' % (finalPathInside, file)
else:
finalPath = '/var/lib/mysql/%s' % (file)
finalPathConf = '%s/%s' % (finalPathInside, file)
gitConf = json.loads(open(finalPathConf, 'r').read())
data = {}
data['domain'] = website
data['folder'] = finalPath
data['commitMessage'] = 'Auto commit by CyberPanel %s cron on %s.' % (type, time.strftime('%m.%d.%Y_%H-%M-%S'))
if gitConf['autoCommit'] == type:
wm = WebsiteManager()
resp = wm.commitChanges(1, data)
logging.writeToFile(resp.content)
resp = json.loads(resp.content)
message = 'Folder: %s, Status: %s' % (finalPath, resp['commandStatus'])
finalText = '%s\n%s' % (finalText, message)
if resp['status'] == 1:
GitLogs(owner=web, type='INFO', message=message).save()
else:
GitLogs(owner=web, type='ERROR', message=message).save()
if gitConf['autoPush'] == type:
wm = WebsiteManager()
resp = wm.gitPush(1, data)
resp = json.loads(resp.content)
if resp['status'] == 1:
GitLogs(owner=web, type='INFO', message=resp['commandStatus']).save()
finalText = '%s\n%s' % (finalText, resp['commandStatus'])
else:
GitLogs(owner=web, type='ERROR', message=resp['commandStatus']).save()
finalText = '%s\n%s' % (finalText, resp['commandStatus'])
message = '[%s Cron] Finished checking for %s on %s.' % (type, website, time.strftime("%m.%d.%Y_%H-%M-%S"))
finalText = '%s\n%s' % (finalText, message)
logging.SendEmail(web.adminEmail, web.adminEmail, finalText, 'Git report for %s.' % (web.domain))
GitLogs(owner=web, type='INFO', message=message).save()
except BaseException as msg:
logging.writeToFile('%s. [IncScheduler.git:90]' % (str(msg)))
def main(): def main():
@@ -90,6 +166,7 @@ def main():
args = parser.parse_args() args = parser.parse_args()
IncScheduler.startBackup(args.function) IncScheduler.startBackup(args.function)
IncScheduler.git(args.function)
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -0,0 +1,4 @@
import subprocess
command = 'git -C /home/usman/Backup/CyberCP commit -m "Auto commit by CyberPanel Daily cron on"'
print(subprocess.check_output(command, shell=True).decode("utf-8"))

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Server Mail - 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 "Manage Server Mail" %}</h2>
<p>{% trans "On this page you can configure how CyberPanel send mails. (Notifications or Errors from CyberPanel)" %}</p>
</div>
<div ng-controller="serverMail" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Manage SMTP Hosts" %} <img ng-hide="cyberPanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<!---- Create SMTP Host --->
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Mailer" %}</label>
<div class="col-sm-6">
<select ng-change="mailerSettings()" ng-model="mailer" class="form-control">
<option>Default</option>
<option>SMTP</option>
</select>
</div>
</div>
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "SMTP Host" %}</label>
<div ng-init="smtpHost='{{ smtpHost }}'" class="col-sm-6">
<input type="text" class="form-control" ng-model="smtpHost" required>
</div>
</div>
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "Port" %}</label>
<div ng-init="smtpPort='{{ smtpPort }}'" class="col-sm-6">
<input type="text" class="form-control" ng-model="smtpPort" required>
</div>
</div>
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "Username" %}</label>
<div ng-init="smtpUserName='{{ smtpUserName }}'" class="col-sm-6">
<input type="text" class="form-control" ng-model="smtpUserName" required>
</div>
</div>
<div ng-hide="installationDetailsForm" class="form-group">
<label class="col-sm-3 control-label">{% trans "Password" %}</label>
<div ng-init="smtpPassword='{{ smtpPassword }}'" class="col-sm-6">
<input type="password" class="form-control" ng-model="smtpPassword" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="saveSMTPSettings()"
class="btn btn-primary btn-lg btn-block">{% trans "Save" %}</button>
</div>
</div>
<!---- Create SMTP Host --->
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -10,5 +10,6 @@ urlpatterns = [
url(r'^modSecAuditLogs', views.modSecAuditLogs, name='modSecAuditLogs'), url(r'^modSecAuditLogs', views.modSecAuditLogs, name='modSecAuditLogs'),
url(r'^getLogsFromFile',views.getLogsFromFile, name="getLogsFromFile"), url(r'^getLogsFromFile',views.getLogsFromFile, name="getLogsFromFile"),
url(r'^clearLogFile',views.clearLogFile, name="clearLogFile"), url(r'^clearLogFile',views.clearLogFile, name="clearLogFile"),
url(r'^serverMail$', views.serverMail, name="serverMail"),
url(r'^saveSMTPSettings$', views.saveSMTPSettings, name="saveSMTPSettings"),
] ]

View File

@@ -203,3 +203,90 @@ def clearLogFile(request):
data_ret = {'cleanStatus': 0, 'error_message': str(msg)} data_ret = {'cleanStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret) json_data = json.dumps(data_ret)
return HttpResponse(json_data) return HttpResponse(json_data)
def serverMail(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadError()
smtpPath = '/home/cyberpanel/smtpDetails'
data = {}
if os.path.exists(smtpPath):
mailSettings = json.loads(open(smtpPath, 'r').read())
data['smtpHost'] = mailSettings['smtpHost']
data['smtpPort'] = mailSettings['smtpPort']
data['smtpUserName'] = mailSettings['smtpUserName']
data['smtpPassword'] = mailSettings['smtpPassword']
return render(request,'serverLogs/serverMail.html', data)
except KeyError as msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[accessLogs]")
return redirect(loadLoginPage)
def saveSMTPSettings(request):
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadErrorJson('logstatus', 0)
data = json.loads(request.body)
mailer = data['mailer']
smtpPath = '/home/cyberpanel/smtpDetails'
if mailer != 'SMTP':
if os.path.exists(smtpPath):
os.remove(smtpPath)
else:
import smtplib
smtpHost = data['smtpHost']
smtpPort = data['smtpPort']
smtpUserName = data['smtpUserName']
smtpPassword = data['smtpPassword']
try:
verifyLogin = smtplib.SMTP(str(smtpHost), int(smtpPort))
verifyLogin.login(str(smtpUserName), str(smtpPassword))
writeToFile = open(smtpPath, 'w')
writeToFile.write(json.dumps(data))
writeToFile.close()
command = 'chmod 600 %s' % (smtpPath)
ProcessUtilities.executioner(command)
except smtplib.SMTPHeloError:
data_ret = {"status": 0, 'error_message': 'The server did not reply properly to the HELO greeting.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except smtplib.SMTPAuthenticationError:
data_ret = {"status": 0, 'error_message': 'Username and password combination not accepted.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except smtplib.SMTPException:
data_ret = {"status": 0, 'error_message': 'No suitable authentication method was found.'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
status = {"status": 1}
final_json = json.dumps(status)
return HttpResponse(final_json)
except BaseException as msg:
status = {"status": 0, 'error_message': str(msg)}
final_json = json.dumps(status)
return HttpResponse(final_json)

1499
static/serverLogs/serverLogs.js Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6714,5 +6714,62 @@ app.controller('manageGIT', function ($scope, $http, $timeout, $window) {
} }
}; };
$scope.currentPage = 1;
$scope.recordsToShow = 10;
$scope.fetchGitLogs = function () {
$scope.cyberpanelLoading = false;
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var data = {
domain: $("#domain").text(),
folder: $scope.folder,
page: $scope.currentPage,
recordsToShow: $scope.recordsToShow
};
dataurl = "/websites/fetchGitLogs";
$http.post(dataurl, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
new PNotify({
title: 'Success',
text: 'Successfully fetched.',
type: 'success'
});
$scope.logs = JSON.parse(response.data.logs);
$scope.pagination = response.data.pagination;
} 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'
});
}
};
}); });
/* Java script code to git tracking ends here */ /* Java script code to git tracking ends here */

View File

@@ -4,6 +4,7 @@
from django.db import models from django.db import models
from packages.models import Package from packages.models import Package
from loginSystem.models import Administrator from loginSystem.models import Administrator
from datetime import datetime
# Create your models here. # Create your models here.
@@ -47,3 +48,10 @@ class aliasDomains(models.Model):
master = models.ForeignKey(Websites, on_delete=models.CASCADE) master = models.ForeignKey(Websites, on_delete=models.CASCADE)
aliasDomain = models.CharField(max_length=75) aliasDomain = models.CharField(max_length=75)
class GitLogs(models.Model):
owner = models.ForeignKey(Websites, on_delete=models.CASCADE)
date = models.DateTimeField(default=datetime.now, blank=True)
type = models.CharField(max_length=5)
message = models.TextField(max_length=65532)

View File

@@ -6714,5 +6714,62 @@ app.controller('manageGIT', function ($scope, $http, $timeout, $window) {
} }
}; };
$scope.currentPage = 1;
$scope.recordsToShow = 10;
$scope.fetchGitLogs = function () {
$scope.cyberpanelLoading = false;
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var data = {
domain: $("#domain").text(),
folder: $scope.folder,
page: $scope.currentPage,
recordsToShow: $scope.recordsToShow
};
dataurl = "/websites/fetchGitLogs";
$http.post(dataurl, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
new PNotify({
title: 'Success',
text: 'Successfully fetched.',
type: 'success'
});
$scope.logs = JSON.parse(response.data.logs);
$scope.pagination = response.data.pagination;
} 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'
});
}
};
}); });
/* Java script code to git tracking ends here */ /* Java script code to git tracking ends here */

View File

@@ -15,140 +15,144 @@
<div ng-controller="listWebsites" class="container"> <div ng-controller="listWebsites" class="container">
<div id="page-title"> <div id="page-title">
<h2 id="domainNamePage">{% trans "List Websites" %}</h2> <img ng-hide="cyberPanelLoading" <h2 id="domainNamePage">{% trans "List Websites" %}</h2> <img ng-hide="cyberPanelLoading"
src="{% static 'images/loading.gif' %}"> src="{% static 'images/loading.gif' %}">
<p>{% trans "On this page you can launch, list, modify and delete websites from your server." %}</p> <p>{% trans "On this page you can launch, list, modify and delete websites from your server." %}</p>
</div>
<div class="col-sm-10" style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888; margin-bottom: 2%">
<input ng-change="searchWebsites()" placeholder="Search..." ng-model="patternAdded" name="dom" type="text"
class="form-control" required>
</div>
<div class="col-sm-2">
<div class="form-group">
<select ng-model="recordsToShow" ng-change="getFurtherWebsitesFromDB()"
class="form-control" id="example-select">
<option>10</option>
<option>50</option>
<option>100</option>
</select>
</div> </div>
</div>
<div ng-repeat="web in WebSitesList track by $index" class="panel col-md-12" <div class="col-sm-10" style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888; margin-bottom: 2%">
style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888;"> <input ng-change="searchWebsites()" placeholder="Search..." ng-model="patternAdded" name="dom" type="text"
<div class=""> class="form-control" required>
<div class="table-responsive no-gutter text-nowrap" style="overflow-x: hidden;"> </div>
<div
style="background-image: url({% static 'images/not-available-preview.png' %}); <div class="col-sm-2">
height: 160px; <div class="form-group">
width: 200px; <select ng-model="recordsToShow" ng-change="getFurtherWebsitesFromDB()"
background-position: top; class="form-control" id="example-select">
background-repeat: no-repeat; <option>10</option>
background-size: cover; <option>50</option>
position: relative;" <option>100</option>
class="col-lg-3 col-md-12" </select>
> </div>
</div> </div>
<div class="col-lg-9" style="text-transform: none">
<div style="border-bottom: 1px solid #888888" class="col-md-12"> <div ng-repeat="web in WebSitesList track by $index" class="panel col-md-12"
<div class="col-lg-10 content-box-header" style="text-transform: none;"> style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888;">
<a href="http://{$ web.domain $}" target="_blank" title="Visit Site"> <div class="">
<h2 style="display: inline; color: #414C59;" ng-bind="web.domain"></h2> <div class="table-responsive no-gutter text-nowrap" style="overflow-x: hidden;">
</a> <div
<a target="_blank" href="/filemanager/{$ web.domain $}" title="Open File Manager"> -- style="background-image: url({% static 'images/not-available-preview.png' %});
/home/{$ web.domain $}/public_html</a> height: 160px;
</div> width: 200px;
<div class="col-md-2 content-box-header" style="text-transform: none;"> background-position: top;
<a href="/websites/{$ web.domain $}" target="_blank" title="Manage Website"> background-repeat: no-repeat;
<i class="p fa fa-external-link btn-icon">&emsp;</i> background-size: cover;
<span>Manage</span> position: relative;"
</a> class="col-lg-3 col-md-12"
</div> >
</div> </div>
<div class="col-md-12"> <div class="col-lg-9" style="text-transform: none">
<div class="col-md-4 content-box-header"> <div style="border-bottom: 1px solid #888888" class="col-md-12">
<i class="p fa fa-sticky-note btn-icon text-muted" data-toggle="tooltip" <div class="col-lg-10 content-box-header" style="text-transform: none;">
data-placement="right" title="State">&emsp;</i> <a href="http://{$ web.domain $}" target="_blank" title="Visit Site">
<span ng-bind="web.state" style="text-transform: none"></span> <h2 style="display: inline; color: #414C59;" ng-bind="web.domain"></h2>
</a>
<a target="_blank" href="/filemanager/{$ web.domain $}" title="Open File Manager"> --
/home/{$ web.domain $}/public_html</a>
</div>
<div class="col-md-2 content-box-header" style="text-transform: none;">
<a href="/websites/{$ web.domain $}" target="_blank" title="Manage Website">
<i class="p fa fa-external-link btn-icon">&emsp;</i>
<span>Manage</span>
</a>
</div>
</div> </div>
<div class="col-md-4 content-box-header"> <div class="col-md-12">
<i class="p fa fa-map-marker btn-icon text-muted" data-toggle="tooltip" <div class="col-md-4 content-box-header">
data-placement="right" title="IP Address">&emsp;</i> <i class="p fa fa-sticky-note btn-icon text-muted" data-toggle="tooltip"
<span ng-bind="web.ipAddress"></span> data-placement="right" title="State">&emsp;</i>
<span ng-bind="web.state" style="text-transform: none"></span>
</div>
<div class="col-md-4 content-box-header">
<i class="p fa fa-map-marker btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="IP Address">&emsp;</i>
<span ng-bind="web.ipAddress"></span>
</div>
<div class="col-md-4 content-box-header">
<i class="p fa fa-lock btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="SSL">&emsp;</i>
<span><a ng-click="issueSSL(web.domain)" href=""
style="text-transform: none">Issue SSL</a></span>
</div>
</div> </div>
<div class="col-md-4 content-box-header"> <div class="col-md-12">
<i class="p fa fa-lock btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="SSL">&emsp;</i>
<span><a ng-click="issueSSL(web.domain)" href="" style="text-transform: none">Issue SSL</a></span>
</div>
</div>
<div class="col-md-12">
<div class="col-md-4 content-box-header"> <div class="col-md-4 content-box-header">
<i class="p fa fa-hdd-o btn-icon text-muted" data-toggle="tooltip" data-placement="right" <i class="p fa fa-hdd-o btn-icon text-muted" data-toggle="tooltip"
title="Disk Usage">&emsp;</i> data-placement="right"
<span ng-bind="web.diskUsed" style="text-transform: none"></span> title="Disk Usage">&emsp;</i>
</div> <span ng-bind="web.diskUsed" style="text-transform: none"></span>
</div>
<div class="col-md-4 content-box-header">
<i class="p fa fa-cubes btn-icon text-muted" data-toggle="tooltip"
data-placement="right"
title="Packages">&emsp;</i>
<span ng-bind="web.package" style="text-transform: none"></span>
</div>
<div class="col-md-4 content-box-header">
<i class="p fa fa-user btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="Owner">&emsp;</i>
<span ng-bind="web.admin" style="text-transform: none"></span>
</div>
<div class="col-md-4 content-box-header">
<i class="p fa fa-cubes btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="Packages">&emsp;</i>
<span ng-bind="web.package" style="text-transform: none"></span>
</div>
<div class="col-md-4 content-box-header">
<i class="p fa fa-user btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="Owner">&emsp;</i>
<span ng-bind="web.admin" style="text-transform: none"></span>
</div> </div>
<!--table cellpadding="0" cellspacing="0" border="0" class="table" style="margin:0px 0px; id="datatable-example">
<thead>
<tr>
<th>IP Address</th>
<th>Package</th>
<th>Owner</th>
<th>State</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-bind="web.ipAddress"></td>
<td ng-bind="web.package"></td>
<td ng-bind="web.admin"></td>
<td ng-bind="web.state"></td>
<td ng-bind="web.adminEmail"></td>
</tr>
</tbody>
</table-->
</div> </div>
<!--table cellpadding="0" cellspacing="0" border="0" class="table" style="margin:0px 0px; id="datatable-example">
<thead>
<tr>
<th>IP Address</th>
<th>Package</th>
<th>Owner</th>
<th>State</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-bind="web.ipAddress"></td>
<td ng-bind="web.package"></td>
<td ng-bind="web.admin"></td>
<td ng-bind="web.state"></td>
<td ng-bind="web.adminEmail"></td>
</tr>
</tbody> <div id="listFail" class="alert alert-danger">
</table--> <p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
</div>
</div>
<div id="listFail" class="alert alert-danger">
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
</div> </div>
</div> </div>
</div> </div>
</div> <div style="margin-top: 2%" class="row">
<div style="margin-top: 2%" class="row"> <div class="col-md-12">
<div class="col-md-12"> <div class="row">
<div class="row"> <div class="col-md-9">
<div class="col-md-9">
</div>
<div class="col-md-3">
<div class="form-group">
<select ng-model="currentPage" class="form-control"
ng-change="getFurtherWebsitesFromDB()">
<option ng-repeat="page in pagination">{$ $index + 1 $}</option>
</select>
</div> </div>
</div> <div class="col-md-3">
</div> <!-- end row --> <div class="form-group">
<select ng-model="currentPage" class="form-control"
ng-change="getFurtherWebsitesFromDB()">
<option ng-repeat="page in pagination">{$ $index + 1 $}</option>
</select>
</div>
</div>
</div> <!-- end row -->
</div>
</div> </div>
</div> </div>

View File

@@ -185,19 +185,23 @@
<option>Weekly</option> <option>Weekly</option>
</select> </select>
</div> </div>
<div class="current-pack ng-binding">Currently: {$ autoCommitCurrent $}</div> <div class="current-pack ng-binding">Currently: {$ autoCommitCurrent
$}
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">{% trans "Auto Push" %}</label> <label class="col-sm-3 control-label">{% trans "Auto Push" %}</label>
<div class="col-sm-6"> <div class="col-sm-6">
<select ng-disabled="remote==0" ng-model="$parent.autoPush" class="form-control"> <select ng-disabled="remote==0" ng-model="$parent.autoPush"
class="form-control">
<option>Never</option> <option>Never</option>
<option>Daily</option> <option>Daily</option>
<option>Weekly</option> <option>Weekly</option>
</select> </select>
</div> </div>
<div class="current-pack ng-binding">Currently: {$ autoPushCurrent $}</div> <div class="current-pack ng-binding">Currently: {$ autoPushCurrent $}
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
@@ -211,7 +215,8 @@
</label> </label>
</div> </div>
</div> </div>
<div class="current-pack ng-binding">Currently: {$ emailLogsCurrent $}</div> <div class="current-pack ng-binding">Currently: {$ emailLogsCurrent $}
</div>
</div> </div>
<div ng-hide="installationDetailsForm" class="form-group"> <div ng-hide="installationDetailsForm" class="form-group">
@@ -462,6 +467,7 @@
<input name="radio-toggle-1" type="radio"> <input name="radio-toggle-1" type="radio">
Push Push
</a> </a>
<a ng-click="fetchGitignore()" data-toggle="modal" data-target="#gitignore" href="#" <a ng-click="fetchGitignore()" data-toggle="modal" data-target="#gitignore" href="#"
class="btn btn-info"> class="btn btn-info">
<input name="radio-toggle-1" type="radio"> <input name="radio-toggle-1" type="radio">
@@ -514,6 +520,81 @@
</div> </div>
</div> </div>
<a ng-click="fetchGitLogs()" data-toggle="modal" data-target="#gitLogs" href="#"
class="btn btn-info">
<input name="radio-toggle-1" type="radio">
Git Logs
</a>
<div id="gitLogs" 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 "Git Logs" %} <img
ng-hide="cyberpanelLoading" src="{% static 'images/loading.gif' %}"></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-sm-10">
</div>
<div class="col-sm-2">
<div class="form-group">
<select ng-model="recordsToShow"
ng-change="fetchGitLogs()"
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>Type</th>
<th>Date</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.date"></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-9">
</div>
<div class="col-md-3">
<div class="form-group">
<select ng-model="currentPage" class="form-control"
ng-change="fetchGitLogs()">
<option ng-repeat="page in pagination">{$ $index + 1
$}
</option>
</select>
</div>
</div>
</div> <!-- end row -->
</div>
</div>
</div>
</div>
</div>
</div>
<a data-toggle="modal" data-target="#removeGit" href="#" class="btn btn-info"> <a data-toggle="modal" data-target="#removeGit" href="#" class="btn btn-info">
<input name="radio-toggle-1" type="radio"> <input name="radio-toggle-1" type="radio">
Remove Remove

View File

@@ -136,6 +136,7 @@ urlpatterns = [
url(r'^fetchFiles$', views.fetchFiles, name='fetchFiles'), url(r'^fetchFiles$', views.fetchFiles, name='fetchFiles'),
url(r'^fetchChangesInFile$', views.fetchChangesInFile, name='fetchChangesInFile'), url(r'^fetchChangesInFile$', views.fetchChangesInFile, name='fetchChangesInFile'),
url(r'^saveGitConfigurations$', views.saveGitConfigurations, name='saveGitConfigurations'), url(r'^saveGitConfigurations$', views.saveGitConfigurations, name='saveGitConfigurations'),
url(r'^fetchGitLogs$', views.fetchGitLogs, name='fetchGitLogs'),
## Catch all for domains ## Catch all for domains

View File

@@ -853,3 +853,11 @@ def saveGitConfigurations(request):
return wm.saveGitConfigurations(userID, json.loads(request.body)) return wm.saveGitConfigurations(userID, json.loads(request.body))
except KeyError: except KeyError:
return redirect(loadLoginPage) return redirect(loadLoginPage)
def fetchGitLogs(request):
try:
userID = request.session['userID']
wm = WebsiteManager()
return wm.fetchGitLogs(userID, json.loads(request.body))
except KeyError:
return redirect(loadLoginPage)

View File

@@ -3284,8 +3284,8 @@ StrictHostKeyChecking no
command = 'git -C %s add -A' % (self.folder) command = 'git -C %s add -A' % (self.folder)
ProcessUtilities.outputExecutioner(command ) ProcessUtilities.outputExecutioner(command )
command = 'git -C %s commit -m "%s"' % (self.folder, self.commitMessage) command = 'git -C %s commit -m "%s"' % (self.folder, self.commitMessage.replace('"', ''))
commandStatus = ProcessUtilities.outputExecutioner(command ) commandStatus = ProcessUtilities.outputExecutioner(command)
if commandStatus.find('nothing to commit') == -1: if commandStatus.find('nothing to commit') == -1:
data_ret = {'status': 1, 'commandStatus': commandStatus} data_ret = {'status': 1, 'commandStatus': commandStatus}
@@ -3297,7 +3297,7 @@ StrictHostKeyChecking no
return HttpResponse(json_data) return HttpResponse(json_data)
except BaseException as msg: except BaseException as msg:
data_ret = {'status': 0, 'error_message': str(msg)} data_ret = {'status': 0, 'error_message': str(msg), 'commandStatus': str(msg)}
json_data = json.dumps(data_ret) json_data = json.dumps(data_ret)
return HttpResponse(json_data) return HttpResponse(json_data)
@@ -3403,7 +3403,7 @@ StrictHostKeyChecking no
return HttpResponse(json_data) return HttpResponse(json_data)
except BaseException as msg: except BaseException as msg:
data_ret = {'status': 0, 'error_message': str(msg)} data_ret = {'status': 0, 'error_message': str(msg), 'commandStatus': str(msg)}
json_data = json.dumps(data_ret) json_data = json.dumps(data_ret)
return HttpResponse(json_data) return HttpResponse(json_data)
@@ -3802,7 +3802,7 @@ StrictHostKeyChecking no
try: try:
dic['autoPush'] = data['autoPush'] dic['autoPush'] = data['autoPush']
except: except:
dic['autoCommit'] = 'Never' dic['autoPush'] = 'Never'
try: try:
dic['emailLogs'] = data['emailLogs'] dic['emailLogs'] = data['emailLogs']
@@ -3845,3 +3845,64 @@ StrictHostKeyChecking no
data_ret = {'status': 0, 'error_message': str(msg)} data_ret = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(data_ret) json_data = json.dumps(data_ret)
return HttpResponse(json_data) return HttpResponse(json_data)
def getLogsInJson(self, logs):
json_data = "["
checker = 0
counter = 1
for items in logs:
dic = {'type': items.type, 'date': items.date.strftime('%m.%d.%Y_%H-%M-%S'), 'message': items.message}
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 + ']'
return json_data
def fetchGitLogs(self, userID=None, data=None):
try:
currentACL = ACLManager.loadedACL(userID)
admin = Administrator.objects.get(pk=userID)
self.domain = data['domain']
self.folder = data['folder']
recordsToShow = int(data['recordsToShow'])
page = int(data['page'])
if ACLManager.checkOwnership(self.domain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadErrorJson('status', 0)
if self.folderCheck():
pass
else:
return ACLManager.loadErrorJson()
website = Websites.objects.get(domain=self.domain)
logs = website.gitlogs_set.all().order_by('-id')
from s3Backups.s3Backups import S3Backups
pagination = S3Backups.getPagination(len(logs), recordsToShow)
endPageNumber, finalPageNumber = S3Backups.recordsPointer(page, recordsToShow)
jsonData = self.getLogsInJson(logs[finalPageNumber:endPageNumber])
data_ret = {'status': 1, 'logs': jsonData, 'pagination': pagination}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
except IndexError:
data_ret = {'status': 0, 'error_message': 'Not a text file.'}
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)