Added campaign summary routes:

/api/campaigns/summary
/api/campaigns/:id/summary

This is part of #505
pull/446/merge
Jordan Wright 2017-01-05 21:48:54 -06:00
parent 9982769d0f
commit 8738ebbb35
3 changed files with 136 additions and 0 deletions

View File

@ -87,6 +87,20 @@ func API_Campaigns(w http.ResponseWriter, r *http.Request) {
}
}
// API_Campaigns_Summary returns the summary for the current user's campaigns
func API_Campaigns_Summary(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == "GET":
cs, err := models.GetCampaignSummaries(ctx.Get(r, "user_id").(int64))
if err != nil {
Logger.Println(err)
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
return
}
JSONResponse(w, cs, http.StatusOK)
}
}
// API_Campaigns_Id returns details about the requested campaign. If the campaign is not
// valid, API_Campaigns_Id returns null.
func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
@ -128,6 +142,26 @@ func API_Campaigns_Id_Results(w http.ResponseWriter, r *http.Request) {
}
}
// API_Campaigns_Id_Summary returns just the summary for a given campaign.
func API_Campaign_Id_Summary(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.ParseInt(vars["id"], 0, 64)
switch {
case r.Method == "GET":
cs, err := models.GetCampaignSummary(id, ctx.Get(r, "user_id").(int64))
if err != nil {
if err == gorm.ErrRecordNotFound {
JSONResponse(w, models.Response{Success: false, Message: "Campaign not found"}, http.StatusNotFound)
} else {
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
}
Logger.Println(err)
return
}
JSONResponse(w, cs, http.StatusOK)
}
}
// API_Campaigns_Id_Complete effectively "ends" a campaign.
// Future phishing emails clicked will return a simple "404" page.
func API_Campaigns_Id_Complete(w http.ResponseWriter, r *http.Request) {

View File

@ -48,8 +48,10 @@ func CreateAdminRouter() http.Handler {
api.HandleFunc("/", Use(API, mid.RequireLogin))
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey))
api.HandleFunc("/campaigns/summary", Use(API_Campaigns_Summary, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}/results", Use(API_Campaigns_Id_Results, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}/summary", Use(API_Campaign_Id_Summary, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}/complete", Use(API_Campaigns_Id_Complete, mid.RequireAPIKey))
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))

View File

@ -37,6 +37,33 @@ type CampaignResults struct {
Events []Event `json:"timeline,omitempty"`
}
// CampaignsSummary is a struct representing the overview of campaigns
type CampaignSummaries struct {
Total int64 `json:"total"`
Campaigns []CampaignSummary `json:"campaigns"`
}
// CampaignSummary is a struct representing the overview of a single camaign
type CampaignSummary struct {
Id int64 `json:"id"`
CreatedDate time.Time `json:"created_date"`
LaunchDate time.Time `json:"launch_date"`
CompletedDate time.Time `json:"completed_date"`
Status string `json:"status"`
Name string `json:"name"`
Stats CampaignStats `json:"stats"`
}
// CampaignStats is a struct representing the statistics for a single campaign
type CampaignStats struct {
Total int64 `json:"total"`
EmailsSent int64 `json:"sent"`
OpenedEmail int64 `json:"opened"`
ClickedLink int64 `json:"clicked"`
SubmittedData int64 `json:"submitted_data"`
Error int64 `json:"error"`
}
// ErrCampaignNameNotSpecified indicates there was no template given by the user
var ErrCampaignNameNotSpecified = errors.New("Campaign name not specified")
@ -165,6 +192,34 @@ func (c *Campaign) getDetails() error {
return nil
}
// getCampaignStats returns a CampaignStats object for the campaign with the given campaign ID.
func getCampaignStats(cid int64) (CampaignStats, error) {
s := CampaignStats{}
query := db.Table("results").Where("campaign_id = ?", cid)
err := query.Count(&s.Total).Error
if err != nil {
return s, err
}
err = query.Where("status=?", EVENT_SENT).Count(&s.EmailsSent).Error
if err != nil {
return s, err
}
err = query.Where("status=?", EVENT_OPENED).Count(&s.OpenedEmail).Error
if err != nil {
return s, err
}
query.Where("status=?", EVENT_CLICKED).Count(&s.ClickedLink)
if err != nil {
return s, err
}
query.Where("status=?", EVENT_DATA_SUBMIT).Count(&s.SubmittedData)
if err != nil {
return s, err
}
err = query.Where("status=?", ERROR).Count(&s.Error).Error
return s, err
}
// Event contains the fields for an event
// that occurs during the campaign
type Event struct {
@ -192,6 +247,51 @@ func GetCampaigns(uid int64) ([]Campaign, error) {
return cs, err
}
// GetCampaignSummaries gets the summary objects for all the campaigns
// owned by the current user
func GetCampaignSummaries(uid int64) (CampaignSummaries, error) {
overview := CampaignSummaries{}
cs := []CampaignSummary{}
// Get the basic campaign information
query := db.Table("campaigns").Where("user_id = ?", uid)
query = query.Select("id, name, created_date, launch_date, completed_date, status")
err := query.Scan(&cs).Error
if err != nil {
Logger.Println(err)
return overview, err
}
for i := range cs {
s, err := getCampaignStats(cs[i].Id)
if err != nil {
Logger.Println(err)
return overview, err
}
cs[i].Stats = s
}
overview.Total = int64(len(cs))
overview.Campaigns = cs
return overview, nil
}
// GetCampaignSummary gets the summary object for a campaign specified by the campaign ID
func GetCampaignSummary(id int64, uid int64) (CampaignSummary, error) {
cs := CampaignSummary{}
query := db.Table("campaigns").Where("user_id = ? AND id = ?", uid, id)
query = query.Select("id, name, created_date, launch_date, completed_date, status")
err := query.Scan(&cs).Error
if err != nil {
Logger.Println(err)
return cs, err
}
s, err := getCampaignStats(cs.Id)
if err != nil {
Logger.Println(err)
return cs, err
}
cs.Stats = s
return cs, nil
}
// GetCampaign returns the campaign, if it exists, specified by the given id and user_id.
func GetCampaign(id int64, uid int64) (Campaign, error) {
c := Campaign{}