mirror of https://github.com/gophish/gophish
Added campaign summary routes:
/api/campaigns/summary /api/campaigns/:id/summary This is part of #505pull/446/merge
parent
9982769d0f
commit
8738ebbb35
|
@ -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
|
// API_Campaigns_Id returns details about the requested campaign. If the campaign is not
|
||||||
// valid, API_Campaigns_Id returns null.
|
// valid, API_Campaigns_Id returns null.
|
||||||
func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
|
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.
|
// API_Campaigns_Id_Complete effectively "ends" a campaign.
|
||||||
// Future phishing emails clicked will return a simple "404" page.
|
// Future phishing emails clicked will return a simple "404" page.
|
||||||
func API_Campaigns_Id_Complete(w http.ResponseWriter, r *http.Request) {
|
func API_Campaigns_Id_Complete(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -48,8 +48,10 @@ func CreateAdminRouter() http.Handler {
|
||||||
api.HandleFunc("/", Use(API, mid.RequireLogin))
|
api.HandleFunc("/", Use(API, mid.RequireLogin))
|
||||||
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
|
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
|
||||||
api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey))
|
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]+}", 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]+}/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("/campaigns/{id:[0-9]+}/complete", Use(API_Campaigns_Id_Complete, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
|
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))
|
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))
|
||||||
|
|
|
@ -37,6 +37,33 @@ type CampaignResults struct {
|
||||||
Events []Event `json:"timeline,omitempty"`
|
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
|
// ErrCampaignNameNotSpecified indicates there was no template given by the user
|
||||||
var ErrCampaignNameNotSpecified = errors.New("Campaign name not specified")
|
var ErrCampaignNameNotSpecified = errors.New("Campaign name not specified")
|
||||||
|
|
||||||
|
@ -165,6 +192,34 @@ func (c *Campaign) getDetails() error {
|
||||||
return nil
|
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
|
// Event contains the fields for an event
|
||||||
// that occurs during the campaign
|
// that occurs during the campaign
|
||||||
type Event struct {
|
type Event struct {
|
||||||
|
@ -192,6 +247,51 @@ func GetCampaigns(uid int64) ([]Campaign, error) {
|
||||||
return cs, err
|
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.
|
// GetCampaign returns the campaign, if it exists, specified by the given id and user_id.
|
||||||
func GetCampaign(id int64, uid int64) (Campaign, error) {
|
func GetCampaign(id int64, uid int64) (Campaign, error) {
|
||||||
c := Campaign{}
|
c := Campaign{}
|
||||||
|
|
Loading…
Reference in New Issue