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.
|
||||
func (as *Server) CampaignSummary(w http.ResponseWriter, r *http.Request) {
|
||||
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]+}/summary", as.CampaignSummary)
|
||||
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/summary", as.GroupsSummary)
|
||||
router.HandleFunc("/groups/{id:[0-9]+}", as.Group)
|
||||
|
|
|
@ -713,4 +713,113 @@ func InsertGroupIntoCampaign(tx *gorm.DB, gid int64, c *Campaign) error {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
// created by the given uid.
|
||||
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
|
||||
function exportAsCSV(scope) {
|
||||
exportHTML = $("#exportButton").html()
|
||||
|
|
|
@ -104,6 +104,10 @@ var api = {
|
|||
complete: function (id) {
|
||||
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: function (id) {
|
||||
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()">
|
||||
<i class="fa fa-flag-checkered"></i> Complete
|
||||
</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()">
|
||||
<i class="fa fa-trash-o fa-lg"></i> Delete
|
||||
</button>
|
||||
|
|
Loading…
Reference in New Issue