mirror of https://github.com/gophish/gophish
Add button to campaign result view, to update users.
ToDo: Prevent duplicate user entries.pull/3047/head
parent
a28dcc5df8
commit
3e6e87a19e
|
@ -100,6 +100,32 @@ func (as *Server) CampaignResults(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CampaignUpdateUsers updates the users assigned to this campaign
|
||||||
|
func (as *Server) CampaignUpdateUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id, _ := strconv.ParseInt(vars["id"], 0, 64)
|
||||||
|
c, err := models.GetCampaign(id, ctx.Get(r, "user_id").(int64))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err);
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: "Campaign not found"}, http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.UpdateCampaignUsersFromGroups(&c);
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err);
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: "Unable to update campaign users"}, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Method == "GET" {
|
||||||
|
JSONResponse(w, models.Response{Success: true, Message: "Campaign user assignment updated successfully!"}, http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CampaignSummary returns the summary for a given campaign.
|
// CampaignSummary returns the summary for a given campaign.
|
||||||
func (as *Server) CampaignSummary(w http.ResponseWriter, r *http.Request) {
|
func (as *Server) CampaignSummary(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
|
@ -67,6 +67,7 @@ func (as *Server) registerRoutes() {
|
||||||
router.HandleFunc("/campaigns/{id:[0-9]+}/results", as.CampaignResults)
|
router.HandleFunc("/campaigns/{id:[0-9]+}/results", as.CampaignResults)
|
||||||
router.HandleFunc("/campaigns/{id:[0-9]+}/summary", as.CampaignSummary)
|
router.HandleFunc("/campaigns/{id:[0-9]+}/summary", as.CampaignSummary)
|
||||||
router.HandleFunc("/campaigns/{id:[0-9]+}/complete", as.CampaignComplete)
|
router.HandleFunc("/campaigns/{id:[0-9]+}/complete", as.CampaignComplete)
|
||||||
|
router.HandleFunc("/campaigns/{id:[0-9]+}/update_users", as.CampaignUpdateUsers)
|
||||||
router.HandleFunc("/groups/", as.Groups)
|
router.HandleFunc("/groups/", as.Groups)
|
||||||
router.HandleFunc("/groups/summary", as.GroupsSummary)
|
router.HandleFunc("/groups/summary", as.GroupsSummary)
|
||||||
router.HandleFunc("/groups/{id:[0-9]+}", as.Group)
|
router.HandleFunc("/groups/{id:[0-9]+}", as.Group)
|
||||||
|
|
|
@ -713,4 +713,113 @@ func InsertGroupIntoCampaign(tx *gorm.DB, gid int64, c *Campaign) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCampaignGroups returns the groups for a campaign
|
||||||
|
func GetCampaignGroups(cid int64) ([]Group, error) {
|
||||||
|
gids := []int64{}
|
||||||
|
err := db.Table("campaign_groups").Where("campaign_id=?", cid).Pluck("group_id", &gids).Error
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gs := make([]Group, len(gids))
|
||||||
|
for i, gid := range gids {
|
||||||
|
gs[i], err = GetGroupById(gid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCampaignUsersFromGroups creates maillogs and result entries for all group members assigned to the specified campaign
|
||||||
|
func UpdateCampaignUsersFromGroups(c *Campaign) (error) {
|
||||||
|
// ToDo: Prevent duplicates
|
||||||
|
gs, err := GetCampaignGroups(c.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.Groups = gs
|
||||||
|
|
||||||
|
totalRecipients := 0
|
||||||
|
for i, _ := range c.Groups {
|
||||||
|
totalRecipients += len(c.Groups[i].Targets)
|
||||||
|
}
|
||||||
|
|
||||||
|
resultMap := make(map[string]bool)
|
||||||
|
recipientIndex := 0
|
||||||
|
tx := db.Begin()
|
||||||
|
for _, g := range c.Groups {
|
||||||
|
// Insert a result for each target in the group
|
||||||
|
for _, t := range g.Targets {
|
||||||
|
// Remove duplicate results - we should only
|
||||||
|
// send emails to unique email addresses.
|
||||||
|
if _, ok := resultMap[t.Email]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
resultMap[t.Email] = true
|
||||||
|
sendDate := c.generateSendDate(recipientIndex, totalRecipients)
|
||||||
|
r := &Result{
|
||||||
|
BaseRecipient: BaseRecipient{
|
||||||
|
Email: t.Email,
|
||||||
|
Position: t.Position,
|
||||||
|
FirstName: t.FirstName,
|
||||||
|
LastName: t.LastName,
|
||||||
|
},
|
||||||
|
Status: StatusScheduled,
|
||||||
|
CampaignId: c.Id,
|
||||||
|
UserId: c.UserId,
|
||||||
|
SendDate: sendDate,
|
||||||
|
Reported: false,
|
||||||
|
ModifiedDate: c.CreatedDate,
|
||||||
|
}
|
||||||
|
err := r.GenerateId(tx)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
processing := false
|
||||||
|
if r.SendDate.Before(c.CreatedDate) || r.SendDate.Equal(c.CreatedDate) {
|
||||||
|
r.Status = StatusSending
|
||||||
|
processing = true
|
||||||
|
}
|
||||||
|
err = tx.Save(r).Error
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"email": t.Email,
|
||||||
|
}).Errorf("error creating result: %v", err)
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.Results = append(c.Results, *r)
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"email": r.Email,
|
||||||
|
"send_date": sendDate,
|
||||||
|
}).Debug("creating maillog")
|
||||||
|
m := &MailLog{
|
||||||
|
UserId: c.UserId,
|
||||||
|
CampaignId: c.Id,
|
||||||
|
RId: r.RId,
|
||||||
|
SendDate: sendDate,
|
||||||
|
Processing: processing,
|
||||||
|
}
|
||||||
|
err = tx.Save(m).Error
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"email": t.Email,
|
||||||
|
}).Errorf("error creating maillog entry: %v", err)
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
recipientIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit().Error
|
||||||
}
|
}
|
|
@ -122,6 +122,22 @@ func GetGroups(uid int64) ([]Group, error) {
|
||||||
return gs, nil
|
return gs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetGroupById(gid int64) (Group, error) {
|
||||||
|
g := Group{}
|
||||||
|
err := db.Where("id=?", gid).Find(&g).Error
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return g, err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.Targets, err = GetTargets(g.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetGroupSummaries returns the summaries for the groups
|
// GetGroupSummaries returns the summaries for the groups
|
||||||
// created by the given uid.
|
// created by the given uid.
|
||||||
func GetGroupSummaries(uid int64) (GroupSummaries, error) {
|
func GetGroupSummaries(uid int64) (GroupSummaries, error) {
|
||||||
|
|
|
@ -199,6 +199,44 @@ function completeCampaign() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updates a campaign's user assignments after prompting the user
|
||||||
|
function updateCampaignUserAssignment() {
|
||||||
|
Swal.fire({
|
||||||
|
title: "Are you sure?",
|
||||||
|
text: "This will update the campaign's user assignments.",
|
||||||
|
type: "warning",
|
||||||
|
animation: false,
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: "Update user assignments",
|
||||||
|
confirmButtonColor: "#428bca",
|
||||||
|
reverseButtons: true,
|
||||||
|
allowOutsideClick: false,
|
||||||
|
showLoaderOnConfirm: true,
|
||||||
|
preConfirm: function () {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
api.campaignId.updateUsers(campaign.id)
|
||||||
|
.success(function (msg) {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
reject(data.responseJSON.message)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).then(function (result) {
|
||||||
|
if(result.value){
|
||||||
|
Swal.fire(
|
||||||
|
'Campaign User assignment Updated!',
|
||||||
|
'This campaign\'s user assignment has been updated!',
|
||||||
|
'success'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$('button:contains("OK")').on('click', function () {
|
||||||
|
location.href = '/campaigns/' + campaign.id;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Exports campaign results as a CSV file
|
// Exports campaign results as a CSV file
|
||||||
function exportAsCSV(scope) {
|
function exportAsCSV(scope) {
|
||||||
exportHTML = $("#exportButton").html()
|
exportHTML = $("#exportButton").html()
|
||||||
|
|
|
@ -104,6 +104,10 @@ var api = {
|
||||||
complete: function (id) {
|
complete: function (id) {
|
||||||
return query("/campaigns/" + id + "/complete", "GET", {}, true)
|
return query("/campaigns/" + id + "/complete", "GET", {}, true)
|
||||||
},
|
},
|
||||||
|
// updateUsers() - Upates a campaign's user assignments at POST /campaigns/:id/update_users
|
||||||
|
updateUsers: function(id) {
|
||||||
|
return query("/campaigns/" + id + "/update_users", "GET", {}, true);
|
||||||
|
},
|
||||||
// summary() - Queries the API for GET /campaigns/summary
|
// summary() - Queries the API for GET /campaigns/summary
|
||||||
summary: function (id) {
|
summary: function (id) {
|
||||||
return query("/campaigns/" + id + "/summary", "GET", {}, true)
|
return query("/campaigns/" + id + "/summary", "GET", {}, true)
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
<button id="complete_button" type="button" class="btn btn-blue" data-toggle="tooltip" onclick="completeCampaign()">
|
<button id="complete_button" type="button" class="btn btn-blue" data-toggle="tooltip" onclick="completeCampaign()">
|
||||||
<i class="fa fa-flag-checkered"></i> Complete
|
<i class="fa fa-flag-checkered"></i> Complete
|
||||||
</button>
|
</button>
|
||||||
|
<button id="complete_button" type="button" class="btn btn-blue" data-toggle="tooltip" onclick="updateCampaignUserAssignment()">
|
||||||
|
<i class="fa fa-users"></i> Update users
|
||||||
|
</button>
|
||||||
<button type="button" class="btn btn-danger" data-toggle="tooltip" onclick="deleteCampaign()">
|
<button type="button" class="btn btn-danger" data-toggle="tooltip" onclick="deleteCampaign()">
|
||||||
<i class="fa fa-trash-o fa-lg"></i> Delete
|
<i class="fa fa-trash-o fa-lg"></i> Delete
|
||||||
</button>
|
</button>
|
||||||
|
|
Loading…
Reference in New Issue