mirror of https://github.com/gophish/gophish
Fixing SSRF by requiring an API key for all import endpoints. Fixes #1026
parent
9ba3f04d1e
commit
2131c17c33
|
@ -102,6 +102,13 @@ func (s *ControllersSuite) SetupTest() {
|
||||||
c.UpdateStatus(models.CAMPAIGN_EMAILS_SENT)
|
c.UpdateStatus(models.CAMPAIGN_EMAILS_SENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ControllersSuite) TestRequireAPIKey() {
|
||||||
|
resp, err := http.Post(fmt.Sprintf("%s/api/import/site", as.URL), "application/json", nil)
|
||||||
|
s.Nil(err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
s.Equal(resp.StatusCode, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ControllersSuite) TestSiteImportBaseHref() {
|
func (s *ControllersSuite) TestSiteImportBaseHref() {
|
||||||
h := "<html><head></head><body><img src=\"/test.png\"/></body></html>"
|
h := "<html><head></head><body><img src=\"/test.png\"/></body></html>"
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -59,9 +59,9 @@ func CreateAdminRouter() http.Handler {
|
||||||
api.HandleFunc("/smtp/", Use(API_SMTP, mid.RequireAPIKey))
|
api.HandleFunc("/smtp/", Use(API_SMTP, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/smtp/{id:[0-9]+}", Use(API_SMTP_Id, mid.RequireAPIKey))
|
api.HandleFunc("/smtp/{id:[0-9]+}", Use(API_SMTP_Id, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/util/send_test_email", Use(API_Send_Test_Email, mid.RequireAPIKey))
|
api.HandleFunc("/util/send_test_email", Use(API_Send_Test_Email, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/import/group", API_Import_Group)
|
api.HandleFunc("/import/group", Use(API_Import_Group, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/import/email", API_Import_Email)
|
api.HandleFunc("/import/email", Use(API_Import_Email, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/import/site", API_Import_Site)
|
api.HandleFunc("/import/site", Use(API_Import_Site, mid.RequireAPIKey))
|
||||||
|
|
||||||
// Setup static file serving
|
// Setup static file serving
|
||||||
router.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))
|
router.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
function errorFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function successFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-success"> <i class="fa fa-check-circle"></i> '+e+"</div>")}function modalError(e){$("#modal\\.flashes").empty().append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function query(e,t,n,r){return $.ajax({url:"/api"+e+"?api_key="+user.api_key,async:r,method:t,data:JSON.stringify(n),dataType:"json",contentType:"application/json"})}function escapeHtml(e){return $("<div/>").text(e).html()}function unescapeHtml(e){return $("<div/>").html(e).text()}var capitalize=function(e){return e.charAt(0).toUpperCase()+e.slice(1)},api={campaigns:{get:function(){return query("/campaigns/","GET",{},!1)},post:function(e){return query("/campaigns/","POST",e,!1)},summary:function(){return query("/campaigns/summary","GET",{},!1)}},campaignId:{get:function(e){return query("/campaigns/"+e,"GET",{},!0)},delete:function(e){return query("/campaigns/"+e,"DELETE",{},!1)},results:function(e){return query("/campaigns/"+e+"/results","GET",{},!0)},complete:function(e){return query("/campaigns/"+e+"/complete","GET",{},!0)},summary:function(e){return query("/campaigns/"+e+"/summary","GET",{},!0)}},groups:{get:function(){return query("/groups/","GET",{},!1)},post:function(e){return query("/groups/","POST",e,!1)},summary:function(){return query("/groups/summary","GET",{},!0)}},groupId:{get:function(e){return query("/groups/"+e,"GET",{},!1)},put:function(e){return query("/groups/"+e.id,"PUT",e,!1)},delete:function(e){return query("/groups/"+e,"DELETE",{},!1)}},templates:{get:function(){return query("/templates/","GET",{},!1)},post:function(e){return query("/templates/","POST",e,!1)}},templateId:{get:function(e){return query("/templates/"+e,"GET",{},!1)},put:function(e){return query("/templates/"+e.id,"PUT",e,!1)},delete:function(e){return query("/templates/"+e,"DELETE",{},!1)}},pages:{get:function(){return query("/pages/","GET",{},!1)},post:function(e){return query("/pages/","POST",e,!1)}},pageId:{get:function(e){return query("/pages/"+e,"GET",{},!1)},put:function(e){return query("/pages/"+e.id,"PUT",e,!1)},delete:function(e){return query("/pages/"+e,"DELETE",{},!1)}},SMTP:{get:function(){return query("/smtp/","GET",{},!1)},post:function(e){return query("/smtp/","POST",e,!1)}},SMTPId:{get:function(e){return query("/smtp/"+e,"GET",{},!1)},put:function(e){return query("/smtp/"+e.id,"PUT",e,!1)},delete:function(e){return query("/smtp/"+e,"DELETE",{},!1)}},import_email:function(e){return query("/import/email","POST",{},!1)},clone_site:function(e){return query("/import/site","POST",e,!1)},send_test_email:function(e){return query("/util/send_test_email","POST",e,!0)}};$(document).ready(function(){$.fn.dataTable.moment("MMMM Do YYYY, h:mm:ss a"),$('[data-toggle="tooltip"]').tooltip()});
|
function errorFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function successFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-success"> <i class="fa fa-check-circle"></i> '+e+"</div>")}function modalError(e){$("#modal\\.flashes").empty().append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function query(e,t,n,r){return $.ajax({url:"/api"+e+"?api_key="+user.api_key,async:r,method:t,data:JSON.stringify(n),dataType:"json",contentType:"application/json"})}function escapeHtml(e){return $("<div/>").text(e).html()}function unescapeHtml(e){return $("<div/>").html(e).text()}var capitalize=function(e){return e.charAt(0).toUpperCase()+e.slice(1)},api={campaigns:{get:function(){return query("/campaigns/","GET",{},!1)},post:function(e){return query("/campaigns/","POST",e,!1)},summary:function(){return query("/campaigns/summary","GET",{},!1)}},campaignId:{get:function(e){return query("/campaigns/"+e,"GET",{},!0)},delete:function(e){return query("/campaigns/"+e,"DELETE",{},!1)},results:function(e){return query("/campaigns/"+e+"/results","GET",{},!0)},complete:function(e){return query("/campaigns/"+e+"/complete","GET",{},!0)},summary:function(e){return query("/campaigns/"+e+"/summary","GET",{},!0)}},groups:{get:function(){return query("/groups/","GET",{},!1)},post:function(e){return query("/groups/","POST",e,!1)},summary:function(){return query("/groups/summary","GET",{},!0)}},groupId:{get:function(e){return query("/groups/"+e,"GET",{},!1)},put:function(e){return query("/groups/"+e.id,"PUT",e,!1)},delete:function(e){return query("/groups/"+e,"DELETE",{},!1)}},templates:{get:function(){return query("/templates/","GET",{},!1)},post:function(e){return query("/templates/","POST",e,!1)}},templateId:{get:function(e){return query("/templates/"+e,"GET",{},!1)},put:function(e){return query("/templates/"+e.id,"PUT",e,!1)},delete:function(e){return query("/templates/"+e,"DELETE",{},!1)}},pages:{get:function(){return query("/pages/","GET",{},!1)},post:function(e){return query("/pages/","POST",e,!1)}},pageId:{get:function(e){return query("/pages/"+e,"GET",{},!1)},put:function(e){return query("/pages/"+e.id,"PUT",e,!1)},delete:function(e){return query("/pages/"+e,"DELETE",{},!1)}},SMTP:{get:function(){return query("/smtp/","GET",{},!1)},post:function(e){return query("/smtp/","POST",e,!1)}},SMTPId:{get:function(e){return query("/smtp/"+e,"GET",{},!1)},put:function(e){return query("/smtp/"+e.id,"PUT",e,!1)},delete:function(e){return query("/smtp/"+e,"DELETE",{},!1)}},import_email:function(e){return query("/import/email","POST",e,!1)},clone_site:function(e){return query("/import/site","POST",e,!1)},send_test_email:function(e){return query("/util/send_test_email","POST",e,!0)}};$(document).ready(function(){$.fn.dataTable.moment("MMMM Do YYYY, h:mm:ss a"),$('[data-toggle="tooltip"]').tooltip()});
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
function save(a){var e=[];$.each($("#targetsTable").DataTable().rows().data(),function(a,s){e.push({first_name:unescapeHtml(s[0]),last_name:unescapeHtml(s[1]),email:unescapeHtml(s[2]),position:unescapeHtml(s[3])})});var s={name:$("#name").val(),targets:e};a!=-1?(s.id=a,api.groupId.put(s).success(function(a){successFlash("Group updated successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})):api.groups.post(s).success(function(a){successFlash("Group added successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})}function dismiss(){$("#targetsTable").dataTable().DataTable().clear().draw(),$("#name").val(""),$("#modal\\.flashes").empty()}function edit(a){if(targets=$("#targetsTable").dataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]}),$("#modalSubmit").unbind("click").click(function(){save(a)}),a==-1);else api.groupId.get(a).success(function(a){$("#name").val(a.name),$.each(a.targets,function(a,e){targets.DataTable().row.add([escapeHtml(e.first_name),escapeHtml(e.last_name),escapeHtml(e.email),escapeHtml(e.position),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>']).draw()})}).error(function(){errorFlash("Error fetching group")});$("#csvupload").fileupload({dataType:"json",add:function(a,e){$("#modal\\.flashes").empty();var s=/(csv|txt)$/i,t=e.originalFiles[0].name;return t&&!s.test(t.split(".").pop())?(modalError("Unsupported file extension (use .csv or .txt)"),!1):void e.submit()},done:function(a,e){$.each(e.result,function(a,e){addTarget(e.first_name,e.last_name,e.email,e.position)}),targets.DataTable().draw()}})}function deleteGroup(a){var e=groups.find(function(e){return e.id===a});return e?void(confirm("Delete "+e.name+"?")&&api.groupId.delete(a).success(function(a){successFlash(a.message),load()})):void console.log("wat")}function addTarget(a,e,s,t){var o=escapeHtml(s).toLowerCase(),r=[escapeHtml(a),escapeHtml(e),o,escapeHtml(t),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'],n=targets.DataTable(),i=n.column(2,{order:"index"}).data().indexOf(o);i>=0?n.row(i,{order:"index"}).data(r):n.row.add(r)}function load(){$("#groupTable").hide(),$("#emptyMessage").hide(),$("#loading").show(),api.groups.summary().success(function(a){if($("#loading").hide(),a.total>0){groups=a.groups,$("#emptyMessage").hide(),$("#groupTable").show();var e=$("#groupTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]});e.clear(),$.each(groups,function(a,s){e.row.add([escapeHtml(s.name),escapeHtml(s.num_targets),moment(s.modified_date).format("MMMM Do YYYY, h:mm:ss a"),"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit("+s.id+")'> <i class='fa fa-pencil'></i> </button> <button class='btn btn-danger' onclick='deleteGroup("+s.id+")'> <i class='fa fa-trash-o'></i> </button></div>"]).draw()})}else $("#emptyMessage").show()}).error(function(){errorFlash("Error fetching groups")})}var groups=[];$(document).ready(function(){load(),$("#targetForm").submit(function(){return addTarget($("#firstName").val(),$("#lastName").val(),$("#email").val(),$("#position").val()),targets.DataTable().draw(),$("#targetForm>div>input").val(""),$("#firstName").focus(),!1}),$("#targetsTable").on("click","span>i.fa-trash-o",function(){targets.DataTable().row($(this).parents("tr")).remove().draw()}),$("#modal").on("hide.bs.modal",function(){dismiss()})});
|
function save(a){var e=[];$.each($("#targetsTable").DataTable().rows().data(),function(a,s){e.push({first_name:unescapeHtml(s[0]),last_name:unescapeHtml(s[1]),email:unescapeHtml(s[2]),position:unescapeHtml(s[3])})});var s={name:$("#name").val(),targets:e};a!=-1?(s.id=a,api.groupId.put(s).success(function(a){successFlash("Group updated successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})):api.groups.post(s).success(function(a){successFlash("Group added successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})}function dismiss(){$("#targetsTable").dataTable().DataTable().clear().draw(),$("#name").val(""),$("#modal\\.flashes").empty()}function edit(a){if(targets=$("#targetsTable").dataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]}),$("#modalSubmit").unbind("click").click(function(){save(a)}),a==-1);else api.groupId.get(a).success(function(a){$("#name").val(a.name),$.each(a.targets,function(a,e){targets.DataTable().row.add([escapeHtml(e.first_name),escapeHtml(e.last_name),escapeHtml(e.email),escapeHtml(e.position),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>']).draw()})}).error(function(){errorFlash("Error fetching group")});$("#csvupload").fileupload({url:"/api/import/group?api_key="+user.api_key,dataType:"json",add:function(a,e){$("#modal\\.flashes").empty();var s=/(csv|txt)$/i,t=e.originalFiles[0].name;return t&&!s.test(t.split(".").pop())?(modalError("Unsupported file extension (use .csv or .txt)"),!1):void e.submit()},done:function(a,e){$.each(e.result,function(a,e){addTarget(e.first_name,e.last_name,e.email,e.position)}),targets.DataTable().draw()}})}function deleteGroup(a){var e=groups.find(function(e){return e.id===a});return e?void(confirm("Delete "+e.name+"?")&&api.groupId.delete(a).success(function(a){successFlash(a.message),load()})):void console.log("wat")}function addTarget(a,e,s,t){var o=escapeHtml(s).toLowerCase(),r=[escapeHtml(a),escapeHtml(e),o,escapeHtml(t),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'],n=targets.DataTable(),i=n.column(2,{order:"index"}).data().indexOf(o);i>=0?n.row(i,{order:"index"}).data(r):n.row.add(r)}function load(){$("#groupTable").hide(),$("#emptyMessage").hide(),$("#loading").show(),api.groups.summary().success(function(a){if($("#loading").hide(),a.total>0){groups=a.groups,$("#emptyMessage").hide(),$("#groupTable").show();var e=$("#groupTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]});e.clear(),$.each(groups,function(a,s){e.row.add([escapeHtml(s.name),escapeHtml(s.num_targets),moment(s.modified_date).format("MMMM Do YYYY, h:mm:ss a"),"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit("+s.id+")'> <i class='fa fa-pencil'></i> </button> <button class='btn btn-danger' onclick='deleteGroup("+s.id+")'> <i class='fa fa-trash-o'></i> </button></div>"]).draw()})}else $("#emptyMessage").show()}).error(function(){errorFlash("Error fetching groups")})}var groups=[];$(document).ready(function(){load(),$("#targetForm").submit(function(){return addTarget($("#firstName").val(),$("#lastName").val(),$("#email").val(),$("#position").val()),targets.DataTable().draw(),$("#targetForm>div>input").val(""),$("#firstName").focus(),!1}),$("#targetsTable").on("click","span>i.fa-trash-o",function(){targets.DataTable().row($(this).parents("tr")).remove().draw()}),$("#modal").on("hide.bs.modal",function(){dismiss()})});
|
|
@ -194,8 +194,8 @@ var api = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// import handles all of the "import" functions in the api
|
// import handles all of the "import" functions in the api
|
||||||
import_email: function (raw) {
|
import_email: function (req) {
|
||||||
return query("/import/email", "POST", {}, false)
|
return query("/import/email", "POST", req, false)
|
||||||
},
|
},
|
||||||
// clone_site handles importing a site by url
|
// clone_site handles importing a site by url
|
||||||
clone_site: function (req) {
|
clone_site: function (req) {
|
||||||
|
|
|
@ -240,16 +240,10 @@ function importEmail() {
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
modalError("No Content Specified!")
|
modalError("No Content Specified!")
|
||||||
} else {
|
} else {
|
||||||
$.ajax({
|
api.import_email({
|
||||||
method: "POST",
|
|
||||||
url: "/api/import/email",
|
|
||||||
data: JSON.stringify({
|
|
||||||
content: raw,
|
content: raw,
|
||||||
convert_links: convert_links
|
convert_links: convert_links
|
||||||
}),
|
})
|
||||||
dataType: "json",
|
|
||||||
contentType: "application/json"
|
|
||||||
})
|
|
||||||
.success(function (data) {
|
.success(function (data) {
|
||||||
$("#text_editor").val(data.text)
|
$("#text_editor").val(data.text)
|
||||||
$("#html_editor").val(data.html)
|
$("#html_editor").val(data.html)
|
||||||
|
@ -337,7 +331,8 @@ $(document).ready(function () {
|
||||||
if (
|
if (
|
||||||
this.$element[0] !== e.target && !this.$element.has(e.target).length
|
this.$element[0] !== e.target && !this.$element.has(e.target).length
|
||||||
// CKEditor compatibility fix start.
|
// CKEditor compatibility fix start.
|
||||||
&& !$(e.target).closest('.cke_dialog, .cke').length
|
&&
|
||||||
|
!$(e.target).closest('.cke_dialog, .cke').length
|
||||||
// CKEditor compatibility fix end.
|
// CKEditor compatibility fix end.
|
||||||
) {
|
) {
|
||||||
this.$element.trigger('focus');
|
this.$element.trigger('focus');
|
||||||
|
@ -356,4 +351,4 @@ $(document).ready(function () {
|
||||||
})
|
})
|
||||||
load()
|
load()
|
||||||
|
|
||||||
})
|
})
|
|
@ -3,7 +3,7 @@ var groups = []
|
||||||
// Save attempts to POST or PUT to /groups/
|
// Save attempts to POST or PUT to /groups/
|
||||||
function save(id) {
|
function save(id) {
|
||||||
var targets = []
|
var targets = []
|
||||||
$.each($("#targetsTable").DataTable().rows().data(), function(i, target) {
|
$.each($("#targetsTable").DataTable().rows().data(), function (i, target) {
|
||||||
targets.push({
|
targets.push({
|
||||||
first_name: unescapeHtml(target[0]),
|
first_name: unescapeHtml(target[0]),
|
||||||
last_name: unescapeHtml(target[1]),
|
last_name: unescapeHtml(target[1]),
|
||||||
|
@ -12,35 +12,35 @@ function save(id) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
var group = {
|
var group = {
|
||||||
name: $("#name").val(),
|
name: $("#name").val(),
|
||||||
targets: targets
|
targets: targets
|
||||||
}
|
}
|
||||||
// Submit the group
|
// Submit the group
|
||||||
if (id != -1) {
|
if (id != -1) {
|
||||||
// If we're just editing an existing group,
|
// If we're just editing an existing group,
|
||||||
// we need to PUT /groups/:id
|
// we need to PUT /groups/:id
|
||||||
group.id = id
|
group.id = id
|
||||||
api.groupId.put(group)
|
api.groupId.put(group)
|
||||||
.success(function(data) {
|
.success(function (data) {
|
||||||
successFlash("Group updated successfully!")
|
successFlash("Group updated successfully!")
|
||||||
load()
|
load()
|
||||||
dismiss()
|
dismiss()
|
||||||
$("#modal").modal('hide')
|
$("#modal").modal('hide')
|
||||||
})
|
})
|
||||||
.error(function(data) {
|
.error(function (data) {
|
||||||
modalError(data.responseJSON.message)
|
modalError(data.responseJSON.message)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Else, if this is a new group, POST it
|
// Else, if this is a new group, POST it
|
||||||
// to /groups
|
// to /groups
|
||||||
api.groups.post(group)
|
api.groups.post(group)
|
||||||
.success(function(data) {
|
.success(function (data) {
|
||||||
successFlash("Group added successfully!")
|
successFlash("Group added successfully!")
|
||||||
load()
|
load()
|
||||||
dismiss()
|
dismiss()
|
||||||
$("#modal").modal('hide')
|
$("#modal").modal('hide')
|
||||||
})
|
})
|
||||||
.error(function(data) {
|
.error(function (data) {
|
||||||
modalError(data.responseJSON.message)
|
modalError(data.responseJSON.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -60,16 +60,16 @@ function edit(id) {
|
||||||
targets: "no-sort"
|
targets: "no-sort"
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
$("#modalSubmit").unbind('click').click(function() {
|
$("#modalSubmit").unbind('click').click(function () {
|
||||||
save(id)
|
save(id)
|
||||||
})
|
})
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
var group = {}
|
var group = {}
|
||||||
} else {
|
} else {
|
||||||
api.groupId.get(id)
|
api.groupId.get(id)
|
||||||
.success(function(group) {
|
.success(function (group) {
|
||||||
$("#name").val(group.name)
|
$("#name").val(group.name)
|
||||||
$.each(group.targets, function(i, record) {
|
$.each(group.targets, function (i, record) {
|
||||||
targets.DataTable()
|
targets.DataTable()
|
||||||
.row.add([
|
.row.add([
|
||||||
escapeHtml(record.first_name),
|
escapeHtml(record.first_name),
|
||||||
|
@ -81,14 +81,15 @@ function edit(id) {
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.error(function() {
|
.error(function () {
|
||||||
errorFlash("Error fetching group")
|
errorFlash("Error fetching group")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Handle file uploads
|
// Handle file uploads
|
||||||
$("#csvupload").fileupload({
|
$("#csvupload").fileupload({
|
||||||
|
url: "/api/import/group?api_key=" + user.api_key,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
add: function(e, data) {
|
add: function (e, data) {
|
||||||
$("#modal\\.flashes").empty()
|
$("#modal\\.flashes").empty()
|
||||||
var acceptFileTypes = /(csv|txt)$/i;
|
var acceptFileTypes = /(csv|txt)$/i;
|
||||||
var filename = data.originalFiles[0]['name']
|
var filename = data.originalFiles[0]['name']
|
||||||
|
@ -98,8 +99,8 @@ function edit(id) {
|
||||||
}
|
}
|
||||||
data.submit();
|
data.submit();
|
||||||
},
|
},
|
||||||
done: function(e, data) {
|
done: function (e, data) {
|
||||||
$.each(data.result, function(i, record) {
|
$.each(data.result, function (i, record) {
|
||||||
addTarget(
|
addTarget(
|
||||||
record.first_name,
|
record.first_name,
|
||||||
record.last_name,
|
record.last_name,
|
||||||
|
@ -112,14 +113,16 @@ function edit(id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteGroup(id) {
|
function deleteGroup(id) {
|
||||||
var group = groups.find(function(x){return x.id === id})
|
var group = groups.find(function (x) {
|
||||||
|
return x.id === id
|
||||||
|
})
|
||||||
if (!group) {
|
if (!group) {
|
||||||
console.log('wat');
|
console.log('wat');
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (confirm("Delete " + group.name + "?")) {
|
if (confirm("Delete " + group.name + "?")) {
|
||||||
api.groupId.delete(id)
|
api.groupId.delete(id)
|
||||||
.success(function(data) {
|
.success(function (data) {
|
||||||
successFlash(data.message)
|
successFlash(data.message)
|
||||||
load()
|
load()
|
||||||
})
|
})
|
||||||
|
@ -162,7 +165,7 @@ function load() {
|
||||||
$("#emptyMessage").hide()
|
$("#emptyMessage").hide()
|
||||||
$("#loading").show()
|
$("#loading").show()
|
||||||
api.groups.summary()
|
api.groups.summary()
|
||||||
.success(function(response) {
|
.success(function (response) {
|
||||||
$("#loading").hide()
|
$("#loading").hide()
|
||||||
if (response.total > 0) {
|
if (response.total > 0) {
|
||||||
groups = response.groups
|
groups = response.groups
|
||||||
|
@ -176,7 +179,7 @@ function load() {
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
groupTable.clear();
|
groupTable.clear();
|
||||||
$.each(groups, function(i, group) {
|
$.each(groups, function (i, group) {
|
||||||
groupTable.row.add([
|
groupTable.row.add([
|
||||||
escapeHtml(group.name),
|
escapeHtml(group.name),
|
||||||
escapeHtml(group.num_targets),
|
escapeHtml(group.num_targets),
|
||||||
|
@ -193,16 +196,16 @@ function load() {
|
||||||
$("#emptyMessage").show()
|
$("#emptyMessage").show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.error(function() {
|
.error(function () {
|
||||||
errorFlash("Error fetching groups")
|
errorFlash("Error fetching groups")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function () {
|
||||||
load()
|
load()
|
||||||
// Setup the event listeners
|
// Setup the event listeners
|
||||||
// Handle manual additions
|
// Handle manual additions
|
||||||
$("#targetForm").submit(function() {
|
$("#targetForm").submit(function () {
|
||||||
addTarget(
|
addTarget(
|
||||||
$("#firstName").val(),
|
$("#firstName").val(),
|
||||||
$("#lastName").val(),
|
$("#lastName").val(),
|
||||||
|
@ -216,13 +219,13 @@ $(document).ready(function() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
// Handle Deletion
|
// Handle Deletion
|
||||||
$("#targetsTable").on("click", "span>i.fa-trash-o", function() {
|
$("#targetsTable").on("click", "span>i.fa-trash-o", function () {
|
||||||
targets.DataTable()
|
targets.DataTable()
|
||||||
.row($(this).parents('tr'))
|
.row($(this).parents('tr'))
|
||||||
.remove()
|
.remove()
|
||||||
.draw();
|
.draw();
|
||||||
});
|
});
|
||||||
$("#modal").on("hide.bs.modal", function() {
|
$("#modal").on("hide.bs.modal", function () {
|
||||||
dismiss();
|
dismiss();
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -3,24 +3,35 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 col-md-2 sidebar">
|
<div class="col-sm-3 col-md-2 sidebar">
|
||||||
<ul class="nav nav-sidebar">
|
<ul class="nav nav-sidebar">
|
||||||
<li><a href="/">Dashboard</a>
|
<li>
|
||||||
|
<a href="/">Dashboard</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/campaigns">Campaigns</a>
|
<li>
|
||||||
|
<a href="/campaigns">Campaigns</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="active"><a href="/users">Users & Groups</a>
|
<li class="active">
|
||||||
|
<a href="/users">Users & Groups</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/templates">Email Templates</a>
|
<li>
|
||||||
|
<a href="/templates">Email Templates</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/landing_pages">Landing Pages</a>
|
<li>
|
||||||
|
<a href="/landing_pages">Landing Pages</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/sending_profiles">Sending Profiles</a>
|
<li>
|
||||||
|
<a href="/sending_profiles">Sending Profiles</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/settings">Settings</a>
|
<li>
|
||||||
|
<a href="/settings">Settings</a>
|
||||||
</li>
|
</li>
|
||||||
<li><hr></li>
|
<li>
|
||||||
<li><a href="https://gophish.gitbooks.io/user-guide/content/">User Guide</a>
|
<hr>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/api/">API Documentation</a>
|
<li>
|
||||||
|
<a href="https://gophish.gitbooks.io/user-guide/content/">User Guide</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/api/">API Documentation</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +45,8 @@
|
||||||
</div>
|
</div>
|
||||||
<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="#modal"><i class="fa fa-plus"></i> New Group</button>
|
<button type="button" class="btn btn-primary" onclick="edit(-1)" data-toggle="modal" data-target="#modal">
|
||||||
|
<i class="fa fa-plus"></i> New Group</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="loading">
|
<div id="loading">
|
||||||
|
@ -62,63 +74,66 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel">
|
<div class="modal fade" id="modal" 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">
|
||||||
<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">
|
||||||
<h4 class="modal-title" id="groupModalLabel">New Group</h4>
|
<span aria-hidden="true">×</span>
|
||||||
</div>
|
</button>
|
||||||
<div class="modal-body">
|
<h4 class="modal-title" id="groupModalLabel">New Group</h4>
|
||||||
<div class="row" id="modal.flashes"></div>
|
</div>
|
||||||
<label class="control-label" for="name">Name:</label>
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="row" id="modal.flashes"></div>
|
||||||
<input type="text" class="form-control" ng-model="group.name" placeholder="Group name" id="name" autofocus/>
|
<label class="control-label" for="name">Name:</label>
|
||||||
</div>
|
<div class="form-group">
|
||||||
<div class="form-group">
|
<input type="text" class="form-control" ng-model="group.name" placeholder="Group name" id="name" autofocus/>
|
||||||
<span class="btn btn-danger btn-file" data-toggle="tooltip" data-placement="right" title="Supports CSV files" id="fileUpload"><i class="fa fa-plus"></i> Bulk Import Users
|
</div>
|
||||||
<input type="file" id="csvupload" data-url="/api/import/group" multiple>
|
<div class="form-group">
|
||||||
</span>
|
<span class="btn btn-danger btn-file" data-toggle="tooltip" data-placement="right" title="Supports CSV files" id="fileUpload">
|
||||||
</div>
|
<i class="fa fa-plus"></i> Bulk Import Users
|
||||||
<div class="row">
|
<input type="file" id="csvupload" multiple>
|
||||||
<form id="targetForm">
|
</span>
|
||||||
<div class="col-sm-2">
|
</div>
|
||||||
<input type="text" class="form-control" placeholder="First Name" id="firstName">
|
<div class="row">
|
||||||
</div>
|
<form id="targetForm">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<input type="text" class="form-control" placeholder="Last Name" id="lastName">
|
<input type="text" class="form-control" placeholder="First Name" id="firstName">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-2">
|
||||||
<input type="email" class="form-control" placeholder="Email" id="email" required>
|
<input type="text" class="form-control" placeholder="Last Name" id="lastName">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<input type="text" class="form-control" placeholder="Position" id="position">
|
<input type="email" class="form-control" placeholder="Email" id="email" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-1">
|
<div class="col-sm-3">
|
||||||
<button type="submit" class="btn btn-danger btn-lg"><i class="fa fa-plus"></i> Add</button>
|
<input type="text" class="form-control" placeholder="Position" id="position">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="col-sm-1">
|
||||||
</div>
|
<button type="submit" class="btn btn-danger btn-lg">
|
||||||
<br />
|
<i class="fa fa-plus"></i> Add</button>
|
||||||
<table id="targetsTable" class="table table-hover table-striped table-condensed">
|
</div>
|
||||||
<thead>
|
</form>
|
||||||
<tr>
|
</div>
|
||||||
<th>First Name</th>
|
<br />
|
||||||
<th>Last Name</th>
|
<table id="targetsTable" class="table table-hover table-striped table-condensed">
|
||||||
<th>Email</th>
|
<thead>
|
||||||
<th>Position</th>
|
<tr>
|
||||||
<th class="no-sort"></th>
|
<th>First Name</th>
|
||||||
<tbody>
|
<th>Last Name</th>
|
||||||
</tbody>
|
<th>Email</th>
|
||||||
</table>
|
<th>Position</th>
|
||||||
</div>
|
<th class="no-sort"></th>
|
||||||
<div class="modal-footer">
|
<tbody>
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
</tbody>
|
||||||
<button type="button" class="btn btn-primary" id="modalSubmit">Save changes</button>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="modalSubmit">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}} {{define "scripts"}}
|
||||||
{{define "scripts"}}
|
|
||||||
<script src="/js/dist/app/users.min.js"></script>
|
<script src="/js/dist/app/users.min.js"></script>
|
||||||
{{end}}
|
{{end}}
|
Loading…
Reference in New Issue