mirror of https://github.com/gophish/gophish
Added Sending Profiles page and sending_profiles.js for interacting with /smtp/ API endpoint
parent
1dd1851ce7
commit
2d503ff215
|
@ -0,0 +1,171 @@
|
||||||
|
var profiles = []
|
||||||
|
|
||||||
|
// Save attempts to POST to /smtp/
|
||||||
|
function save(idx) {
|
||||||
|
var profile = {}
|
||||||
|
profile.name = $("#name").val()
|
||||||
|
profile.interface_type = $("#interface_type").val()
|
||||||
|
profile.from_address = $("#from").val()
|
||||||
|
profile.host = $("#host").val()
|
||||||
|
profile.username = $("#username").val()
|
||||||
|
profile.password = $("#password").val()
|
||||||
|
profile.ignore_cert_errors = $("#ignore_cert_errors").prop("checked")
|
||||||
|
if (idx != -1) {
|
||||||
|
profile.id = profiles[idx].id
|
||||||
|
api.SMTPId.put(profile)
|
||||||
|
.success(function(data) {
|
||||||
|
successFlash("Profile edited successfully!")
|
||||||
|
load()
|
||||||
|
dismiss()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Submit the profile
|
||||||
|
api.SMTP.post(profile)
|
||||||
|
.success(function(data) {
|
||||||
|
successFlash("Profile added successfully!")
|
||||||
|
load()
|
||||||
|
dismiss()
|
||||||
|
})
|
||||||
|
.error(function(data) {
|
||||||
|
modalError(data.responseJSON.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismiss() {
|
||||||
|
$("#modal\\.flashes").empty()
|
||||||
|
$("#name").val("")
|
||||||
|
$("#from").val("")
|
||||||
|
$("#host").val("")
|
||||||
|
$("#username").val("")
|
||||||
|
$("#password").val("")
|
||||||
|
$("#modal").modal('hide')
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteProfile(idx) {
|
||||||
|
if (confirm("Delete " + profiles[idx].name + "?")) {
|
||||||
|
api.SMTPId.delete(profiles[idx].id)
|
||||||
|
.success(function(data) {
|
||||||
|
successFlash(data.message)
|
||||||
|
load()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function edit(idx) {
|
||||||
|
$("#modalSubmit").unbind('click').click(function() {
|
||||||
|
save(idx)
|
||||||
|
})
|
||||||
|
var profile = {}
|
||||||
|
if (idx != -1) {
|
||||||
|
profile = profiles[idx]
|
||||||
|
$("#name").val(profile.name)
|
||||||
|
$("#interface_type").val(profile.interface_type)
|
||||||
|
$("#from").val(profile.from_address)
|
||||||
|
$("#host").val(profile.host)
|
||||||
|
$("#username").val(profile.username)
|
||||||
|
$("#password").val(profile.password)
|
||||||
|
$("#ignore_cert_errors").prop("checked", profile.ignore_cert_errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copy(idx) {
|
||||||
|
$("#modalSubmit").unbind('click').click(function() {
|
||||||
|
save(-1)
|
||||||
|
})
|
||||||
|
var profile = {}
|
||||||
|
profile = profiles[idx]
|
||||||
|
$("#name").val("Copy of " + profile.name)
|
||||||
|
$("#interface_type").val(profile.interface_type)
|
||||||
|
$("#from").val(profile.from_address)
|
||||||
|
$("#host").val(profile.host)
|
||||||
|
$("#username").val(profile.username)
|
||||||
|
$("#password").val(profile.password)
|
||||||
|
$("#ignore_cert_errors").prop("checked", profile.ignore_cert_errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
$("#profileTable").hide()
|
||||||
|
$("#emptyMessage").hide()
|
||||||
|
$("#loading").show()
|
||||||
|
api.SMTP.get()
|
||||||
|
.success(function(ss) {
|
||||||
|
profiles = ss
|
||||||
|
$("#loading").hide()
|
||||||
|
if (profiles.length > 0) {
|
||||||
|
$("#profileTable").show()
|
||||||
|
profileTable = $("#profileTable").DataTable({
|
||||||
|
destroy: true,
|
||||||
|
columnDefs: [{
|
||||||
|
orderable: false,
|
||||||
|
targets: "no-sort"
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
profileTable.clear()
|
||||||
|
$.each(profiles, function(i, profile) {
|
||||||
|
profileTable.row.add([
|
||||||
|
profile.name,
|
||||||
|
profile.interface_type,
|
||||||
|
moment(profile.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
|
||||||
|
"<div class='pull-right'><span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Edit Profile' onclick='edit(" + i + ")'>\
|
||||||
|
<i class='fa fa-pencil'></i>\
|
||||||
|
</button></span>\
|
||||||
|
<span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Profile' onclick='copy(" + i + ")'>\
|
||||||
|
<i class='fa fa-copy'></i>\
|
||||||
|
</button></span>\
|
||||||
|
<button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Profile' onclick='deleteProfile(" + i + ")'>\
|
||||||
|
<i class='fa fa-trash-o'></i>\
|
||||||
|
</button></div>"
|
||||||
|
]).draw()
|
||||||
|
})
|
||||||
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
} else {
|
||||||
|
$("#emptyMessage").show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.error(function() {
|
||||||
|
$("#loading").hide()
|
||||||
|
errorFlash("Error fetching profiles")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Setup multiple modals
|
||||||
|
// Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html
|
||||||
|
$('.modal').on('hidden.bs.modal', function(event) {
|
||||||
|
$(this).removeClass('fv-modal-stack');
|
||||||
|
$('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1);
|
||||||
|
});
|
||||||
|
$('.modal').on('shown.bs.modal', function(event) {
|
||||||
|
// Keep track of the number of open modals
|
||||||
|
if (typeof($('body').data('fv_open_modals')) == 'undefined') {
|
||||||
|
$('body').data('fv_open_modals', 0);
|
||||||
|
}
|
||||||
|
// if the z-index of this modal has been set, ignore.
|
||||||
|
if ($(this).hasClass('fv-modal-stack')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$(this).addClass('fv-modal-stack');
|
||||||
|
// Increment the number of open modals
|
||||||
|
$('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1);
|
||||||
|
// Setup the appropriate z-index
|
||||||
|
$(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals')));
|
||||||
|
$('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals')));
|
||||||
|
$('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack');
|
||||||
|
});
|
||||||
|
$.fn.modal.Constructor.prototype.enforceFocus = function() {
|
||||||
|
$(document)
|
||||||
|
.off('focusin.bs.modal') // guard against infinite focus loop
|
||||||
|
.on('focusin.bs.modal', $.proxy(function(e) {
|
||||||
|
if (
|
||||||
|
this.$element[0] !== e.target && !this.$element.has(e.target).length
|
||||||
|
// CKEditor compatibility fix start.
|
||||||
|
&& !$(e.target).closest('.cke_dialog, .cke').length
|
||||||
|
// CKEditor compatibility fix end.
|
||||||
|
) {
|
||||||
|
this.$element.trigger('focus');
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
|
};
|
||||||
|
load()
|
||||||
|
})
|
|
@ -32,7 +32,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
<div id="flashes" class="row"></div>
|
<div id="flashes" class="row"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<button type="button" class="btn btn-primary" onclick="edit(-1)" data-toggle="modal" data-target="#newLandingPageModal"><i class="fa fa-plus"></i> New Page</button>
|
<button type="button" class="btn btn-primary" onclick="edit(-1)" data-toggle="modal" data-target="#newProfileModal"><i class="fa fa-plus"></i> New Profile</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="loading">
|
<div id="loading">
|
||||||
|
@ -40,14 +40,15 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="emptyMessage" class="row" style="display:none;">
|
<div id="emptyMessage" class="row" style="display:none;">
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
No pages created yet. Let's create one!
|
No profiles created yet. Let's create one!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<table id="pagesTable" class="table" style="display:none;">
|
<table id="profileTable" class="table" style="display:none;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
<th>Interface Type</th>
|
||||||
<th>Last Modified Date</th>
|
<th>Last Modified Date</th>
|
||||||
<th class="col-md-2 no-sort"></th>
|
<th class="col-md-2 no-sort"></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -58,60 +59,48 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="newLandingPageModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel">
|
<div class="modal fade" id="newProfileModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<!-- New Template Modal -->
|
<!-- New Template Modal -->
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
<h4 class="modal-title" id="pageModalLabel">New Landing Page</h4>
|
<h4 class="modal-title" id="profileModalLabel">New Sending Profile</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="row" id="modal.flashes"></div>
|
<div class="row" id="modal.flashes"></div>
|
||||||
<label class="control-label" for="name">Name:</label>
|
<label class="control-label" for="name">Name:</label>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" class="form-control" placeholder="Page name" id="name" autofocus/>
|
<input type="text" class="form-control" placeholder="Profile name" id="name" autofocus/>
|
||||||
</div>
|
</div>
|
||||||
|
<label class="control-label" for="name">Interface Type:</label>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button class="btn btn-danger" data-toggle="modal" data-target="#importSiteModal"><i class="fa fa-globe"></i> Import Site</button>
|
<input type="text" class="form-control" value="SMTP" id="interface_type" disabled/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Nav tabs -->
|
<label class="control-label" for="name">From:</label>
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<div class="form-group">
|
||||||
<li class="active" role="html"><a href="#html" aria-controls="html" role="tab" data-toggle="tab">HTML</a></li>
|
<input type="text" class="form-control" placeholder="First Last <test@example.com>" id="from" autofocus/>
|
||||||
</ul>
|
</div>
|
||||||
<!-- Tab panes -->
|
<label class="control-label" for="name">Host:</label>
|
||||||
<div class="tab-content">
|
<div class="form-group">
|
||||||
<div role="tabpanel" class="tab-pane active" id="html">
|
<input type="text" class="form-control" placeholder="smtp.example.com:25" id="host" autofocus/>
|
||||||
<textarea id="html_editor"></textarea>
|
</div>
|
||||||
</div>
|
<label class="control-label" for="name">Username:</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" placeholder="Username" id="username" autofocus/>
|
||||||
|
</div>
|
||||||
|
<label class="control-label" for="name">Password:</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" placeholder="Password" id="password" autofocus/>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox checkbox-primary">
|
||||||
|
<input id="ignore_cert_errors" type="checkbox" checked>
|
||||||
|
<label for="ignore_cert_errors">Ignore Certificate Errors <i class="fa fa-question-circle" data-toggle="tooltip" data-placement="right" title="Ignore common certificate errors such as self-signed certs (exposes you to MiTM attacks - use carefully!)"></i></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" data-dismiss="modal" class="btn btn-default" onclick="dismiss()">Cancel</button>
|
<button type="button" data-dismiss="modal" class="btn btn-default" onclick="dismiss()">Cancel</button>
|
||||||
<button type="button" class="btn btn-primary" id="modalSubmit">Save Page</button>
|
<button type="button" class="btn btn-primary" id="modalSubmit">Save Profile</button>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Modal -->
|
|
||||||
<div class="modal fade" id="importSiteModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<!-- New Template Modal -->
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
||||||
<h4 class="modal-title" id="importSiteModalLabel">Import Site</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="row" id="modal.flashes"></div>
|
|
||||||
<label class="control-label" for="url">URL:</label>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control" placeholder="http://google.com" id="url" autofocus/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" data-dismiss="modal" class="btn btn-default">Cancel</button>
|
|
||||||
<button type="button" class="btn btn-primary" id="modalSubmit" onclick="importSite()">Import</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -120,6 +109,5 @@
|
||||||
{{define "scripts"}}
|
{{define "scripts"}}
|
||||||
<script src="/js/ckeditor/ckeditor.js"></script>
|
<script src="/js/ckeditor/ckeditor.js"></script>
|
||||||
<script src="/js/ckeditor/adapters/jquery.js"></script>
|
<script src="/js/ckeditor/adapters/jquery.js"></script>
|
||||||
<script src="/js/app/landing_pages.js"></script>
|
|
||||||
<script src="/js/app/sending_profiles.js"></script>
|
<script src="/js/app/sending_profiles.js"></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Reference in New Issue