From a73ac4ab7c181afae8ee49fd3d4c08cb2fed1211 Mon Sep 17 00:00:00 2001 From: Jordan Wright Date: Sat, 15 Dec 2018 21:38:51 -0600 Subject: [PATCH] Fixed various minor linting issues --- auth/auth.go | 2 + context/context.go | 3 ++ controllers/api.go | 94 +++++++++++++++++++-------------------- controllers/api_test.go | 10 ++--- controllers/phish.go | 28 ++++++------ controllers/phish_test.go | 22 ++++----- controllers/route.go | 42 ++++++++--------- logger/logger.go | 12 +++++ middleware/middleware.go | 3 ++ models/campaign.go | 26 +++++------ models/maillog.go | 2 +- models/maillog_test.go | 10 ++--- models/models.go | 38 ++++++++-------- models/result.go | 30 ++++++------- models/result_test.go | 8 ++-- models/template.go | 2 +- worker/worker.go | 4 +- worker/worker_test.go | 2 +- 18 files changed, 179 insertions(+), 159 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index 0514d14e..595ed732 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -109,6 +109,8 @@ func GenerateSecureKey() string { return fmt.Sprintf("%x", k) } +// ChangePassword verifies the current password provided in the request and, +// if it's valid, changes the password for the authenticated user. func ChangePassword(r *http.Request) error { u := ctx.Get(r, "user").(models.User) currentPw := r.FormValue("current_password") diff --git a/context/context.go b/context/context.go index 705a0a81..998f4939 100644 --- a/context/context.go +++ b/context/context.go @@ -8,10 +8,12 @@ import ( "context" ) +// Get retrieves a value from the request context func Get(r *http.Request, key interface{}) interface{} { return r.Context().Value(key) } +// Set stores a value on the request context func Set(r *http.Request, key, val interface{}) *http.Request { if val == nil { return r @@ -20,6 +22,7 @@ func Set(r *http.Request, key, val interface{}) *http.Request { return r.WithContext(context.WithValue(r.Context(), key, val)) } +// Clear is a null operation, since this is handled automatically in Go > 1.7 func Clear(r *http.Request) { return } diff --git a/controllers/api.go b/controllers/api.go index bd6d3938..153c514f 100644 --- a/controllers/api.go +++ b/controllers/api.go @@ -23,8 +23,8 @@ import ( "github.com/sirupsen/logrus" ) -// API (/api/reset) resets a user's API key -func (as *AdminServer) API_Reset(w http.ResponseWriter, r *http.Request) { +// APIReset (/api/reset) resets a user's API key +func (as *AdminServer) APIReset(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "POST": u := ctx.Get(r, "user").(models.User) @@ -38,9 +38,9 @@ func (as *AdminServer) API_Reset(w http.ResponseWriter, r *http.Request) { } } -// API_Campaigns returns a list of campaigns if requested via GET. -// If requested via POST, API_Campaigns creates a new campaign and returns a reference to it. -func (as *AdminServer) API_Campaigns(w http.ResponseWriter, r *http.Request) { +// APICampaigns returns a list of campaigns if requested via GET. +// If requested via POST, APICampaigns creates a new campaign and returns a reference to it. +func (as *AdminServer) APICampaigns(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": cs, err := models.GetCampaigns(ctx.Get(r, "user_id").(int64)) @@ -64,15 +64,15 @@ func (as *AdminServer) API_Campaigns(w http.ResponseWriter, r *http.Request) { } // If the campaign is scheduled to launch immediately, send it to the worker. // Otherwise, the worker will pick it up at the scheduled time - if c.Status == models.CAMPAIGN_IN_PROGRESS { + if c.Status == models.CampaignInProgress { go as.worker.LaunchCampaign(c) } JSONResponse(w, c, http.StatusCreated) } } -// API_Campaigns_Summary returns the summary for the current user's campaigns -func (as *AdminServer) API_Campaigns_Summary(w http.ResponseWriter, r *http.Request) { +// APICampaignsSummary returns the summary for the current user's campaigns +func (as *AdminServer) APICampaignsSummary(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": cs, err := models.GetCampaignSummaries(ctx.Get(r, "user_id").(int64)) @@ -85,9 +85,9 @@ func (as *AdminServer) API_Campaigns_Summary(w http.ResponseWriter, r *http.Requ } } -// API_Campaigns_Id returns details about the requested campaign. If the campaign is not -// valid, API_Campaigns_Id returns null. -func (as *AdminServer) API_Campaigns_Id(w http.ResponseWriter, r *http.Request) { +// APICampaign returns details about the requested campaign. If the campaign is not +// valid, APICampaign returns null. +func (as *AdminServer) APICampaign(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)) @@ -109,9 +109,9 @@ func (as *AdminServer) API_Campaigns_Id(w http.ResponseWriter, r *http.Request) } } -// API_Campaigns_Id_Results returns just the results for a given campaign to +// APICampaignResults returns just the results for a given campaign to // significantly reduce the information returned. -func (as *AdminServer) API_Campaigns_Id_Results(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APICampaignResults(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) cr, err := models.GetCampaignResults(id, ctx.Get(r, "user_id").(int64)) @@ -126,8 +126,8 @@ func (as *AdminServer) API_Campaigns_Id_Results(w http.ResponseWriter, r *http.R } } -// API_Campaigns_Id_Summary returns just the summary for a given campaign. -func (as *AdminServer) API_Campaign_Id_Summary(w http.ResponseWriter, r *http.Request) { +// APICampaignSummary returns the summary for a given campaign. +func (as *AdminServer) APICampaignSummary(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) switch { @@ -146,9 +146,9 @@ func (as *AdminServer) API_Campaign_Id_Summary(w http.ResponseWriter, r *http.Re } } -// API_Campaigns_Id_Complete effectively "ends" a campaign. +// APICampaignComplete effectively "ends" a campaign. // Future phishing emails clicked will return a simple "404" page. -func (as *AdminServer) API_Campaigns_Id_Complete(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APICampaignComplete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) switch { @@ -162,9 +162,9 @@ func (as *AdminServer) API_Campaigns_Id_Complete(w http.ResponseWriter, r *http. } } -// API_Groups returns a list of groups if requested via GET. -// If requested via POST, API_Groups creates a new group and returns a reference to it. -func (as *AdminServer) API_Groups(w http.ResponseWriter, r *http.Request) { +// APIGroups returns a list of groups if requested via GET. +// If requested via POST, APIGroups creates a new group and returns a reference to it. +func (as *AdminServer) APIGroups(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": gs, err := models.GetGroups(ctx.Get(r, "user_id").(int64)) @@ -198,8 +198,8 @@ func (as *AdminServer) API_Groups(w http.ResponseWriter, r *http.Request) { } } -// API_Groups_Summary returns a summary of the groups owned by the current user. -func (as *AdminServer) API_Groups_Summary(w http.ResponseWriter, r *http.Request) { +// APIGroupsSummary returns a summary of the groups owned by the current user. +func (as *AdminServer) APIGroupsSummary(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": gs, err := models.GetGroupSummaries(ctx.Get(r, "user_id").(int64)) @@ -212,9 +212,9 @@ func (as *AdminServer) API_Groups_Summary(w http.ResponseWriter, r *http.Request } } -// API_Groups_Id returns details about the requested group. -// If the group is not valid, API_Groups_Id returns null. -func (as *AdminServer) API_Groups_Id(w http.ResponseWriter, r *http.Request) { +// APIGroup returns details about the requested group. +// If the group is not valid, APIGroup returns null. +func (as *AdminServer) APIGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) g, err := models.GetGroup(id, ctx.Get(r, "user_id").(int64)) @@ -251,8 +251,8 @@ func (as *AdminServer) API_Groups_Id(w http.ResponseWriter, r *http.Request) { } } -// API_Groups_Id_Summary returns a summary of the groups owned by the current user. -func (as *AdminServer) API_Groups_Id_Summary(w http.ResponseWriter, r *http.Request) { +// APIGroupSummary returns a summary of the groups owned by the current user. +func (as *AdminServer) APIGroupSummary(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": vars := mux.Vars(r) @@ -266,8 +266,8 @@ func (as *AdminServer) API_Groups_Id_Summary(w http.ResponseWriter, r *http.Requ } } -// API_Templates handles the functionality for the /api/templates endpoint -func (as *AdminServer) API_Templates(w http.ResponseWriter, r *http.Request) { +// APITemplates handles the functionality for the /api/templates endpoint +func (as *AdminServer) APITemplates(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": ts, err := models.GetTemplates(ctx.Get(r, "user_id").(int64)) @@ -309,8 +309,8 @@ func (as *AdminServer) API_Templates(w http.ResponseWriter, r *http.Request) { } } -// API_Templates_Id handles the functions for the /api/templates/:id endpoint -func (as *AdminServer) API_Templates_Id(w http.ResponseWriter, r *http.Request) { +// APITemplate handles the functions for the /api/templates/:id endpoint +func (as *AdminServer) APITemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) t, err := models.GetTemplate(id, ctx.Get(r, "user_id").(int64)) @@ -349,8 +349,8 @@ func (as *AdminServer) API_Templates_Id(w http.ResponseWriter, r *http.Request) } } -// API_Pages handles requests for the /api/pages/ endpoint -func (as *AdminServer) API_Pages(w http.ResponseWriter, r *http.Request) { +// APIPages handles requests for the /api/pages/ endpoint +func (as *AdminServer) APIPages(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": ps, err := models.GetPages(ctx.Get(r, "user_id").(int64)) @@ -385,9 +385,9 @@ func (as *AdminServer) API_Pages(w http.ResponseWriter, r *http.Request) { } } -// API_Pages_Id contains functions to handle the GET'ing, DELETE'ing, and PUT'ing +// APIPage contains functions to handle the GET'ing, DELETE'ing, and PUT'ing // of a Page object -func (as *AdminServer) API_Pages_Id(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APIPage(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) p, err := models.GetPage(id, ctx.Get(r, "user_id").(int64)) @@ -426,8 +426,8 @@ func (as *AdminServer) API_Pages_Id(w http.ResponseWriter, r *http.Request) { } } -// API_SMTP handles requests for the /api/smtp/ endpoint -func (as *AdminServer) API_SMTP(w http.ResponseWriter, r *http.Request) { +// APISendingProfiles handles requests for the /api/smtp/ endpoint +func (as *AdminServer) APISendingProfiles(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "GET": ss, err := models.GetSMTPs(ctx.Get(r, "user_id").(int64)) @@ -462,9 +462,9 @@ func (as *AdminServer) API_SMTP(w http.ResponseWriter, r *http.Request) { } } -// API_SMTP_Id contains functions to handle the GET'ing, DELETE'ing, and PUT'ing +// APISendingProfile contains functions to handle the GET'ing, DELETE'ing, and PUT'ing // of a SMTP object -func (as *AdminServer) API_SMTP_Id(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APISendingProfile(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.ParseInt(vars["id"], 0, 64) s, err := models.GetSMTP(id, ctx.Get(r, "user_id").(int64)) @@ -508,8 +508,8 @@ func (as *AdminServer) API_SMTP_Id(w http.ResponseWriter, r *http.Request) { } } -// API_Import_Group imports a CSV of group members -func (as *AdminServer) API_Import_Group(w http.ResponseWriter, r *http.Request) { +// APIImportGroup imports a CSV of group members +func (as *AdminServer) APIImportGroup(w http.ResponseWriter, r *http.Request) { ts, err := util.ParseCSV(r) if err != nil { JSONResponse(w, models.Response{Success: false, Message: "Error parsing CSV"}, http.StatusInternalServerError) @@ -519,9 +519,9 @@ func (as *AdminServer) API_Import_Group(w http.ResponseWriter, r *http.Request) return } -// API_Import_Email allows for the importing of email. +// APIImportEmail allows for the importing of email. // Returns a Message object -func (as *AdminServer) API_Import_Email(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APIImportEmail(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { JSONResponse(w, models.Response{Success: false, Message: "Method not allowed"}, http.StatusBadRequest) return @@ -567,10 +567,10 @@ func (as *AdminServer) API_Import_Email(w http.ResponseWriter, r *http.Request) return } -// API_Import_Site allows for the importing of HTML from a website +// APIImportSite allows for the importing of HTML from a website // Without "include_resources" set, it will merely place a "base" tag // so that all resources can be loaded relative to the given URL. -func (as *AdminServer) API_Import_Site(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APIImportSite(w http.ResponseWriter, r *http.Request) { cr := cloneRequest{} if r.Method != "POST" { JSONResponse(w, models.Response{Success: false, Message: "Method not allowed"}, http.StatusBadRequest) @@ -626,9 +626,9 @@ func (as *AdminServer) API_Import_Site(w http.ResponseWriter, r *http.Request) { return } -// API_Send_Test_Email sends a test email using the template name +// APISendTestEmail sends a test email using the template name // and Target given. -func (as *AdminServer) API_Send_Test_Email(w http.ResponseWriter, r *http.Request) { +func (as *AdminServer) APISendTestEmail(w http.ResponseWriter, r *http.Request) { s := &models.EmailRequest{ ErrorChan: make(chan error), UserId: ctx.Get(r, "user_id").(int64), diff --git a/controllers/api_test.go b/controllers/api_test.go index cc0684c7..9f9e26d9 100644 --- a/controllers/api_test.go +++ b/controllers/api_test.go @@ -17,7 +17,7 @@ import ( // ControllersSuite is a suite of tests to cover API related functions type ControllersSuite struct { suite.Suite - ApiKey string + apiKey string config *config.Config adminServer *httptest.Server phishServer *httptest.Server @@ -42,7 +42,7 @@ func (s *ControllersSuite) SetupSuite() { // Get the API key to use for these tests u, err := models.GetUser(1) s.Nil(err) - s.ApiKey = u.ApiKey + s.apiKey = u.ApiKey // Start the phishing server s.phishServer = httptest.NewUnstartedServer(NewPhishingServer(s.config.PhishConf).server.Handler) s.phishServer.Config.Addr = s.config.PhishConf.ListenURL @@ -100,7 +100,7 @@ func (s *ControllersSuite) SetupTest() { c.SMTP = smtp c.Groups = []models.Group{group} models.PostCampaign(&c, c.UserId) - c.UpdateStatus(models.CAMPAIGN_EMAILS_SENT) + c.UpdateStatus(models.CampaignEmailsSent) } func (s *ControllersSuite) TestRequireAPIKey() { @@ -120,7 +120,7 @@ func (s *ControllersSuite) TestInvalidAPIKey() { func (s *ControllersSuite) TestBearerToken() { req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/groups/", s.adminServer.URL), nil) s.Nil(err) - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", s.ApiKey)) + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", s.apiKey)) resp, err := http.DefaultClient.Do(req) s.Nil(err) defer resp.Body.Close() @@ -134,7 +134,7 @@ func (s *ControllersSuite) TestSiteImportBaseHref() { })) hr := fmt.Sprintf("\n", ts.URL) defer ts.Close() - resp, err := http.Post(fmt.Sprintf("%s/api/import/site?api_key=%s", s.adminServer.URL, s.ApiKey), "application/json", + resp, err := http.Post(fmt.Sprintf("%s/api/import/site?api_key=%s", s.adminServer.URL, s.apiKey), "application/json", bytes.NewBuffer([]byte(fmt.Sprintf(` { "url" : "%s", diff --git a/controllers/phish.go b/controllers/phish.go index e1996d3d..4fbc47ca 100644 --- a/controllers/phish.go +++ b/controllers/phish.go @@ -126,7 +126,7 @@ func (ps *PhishingServer) registerRoutes() { // TrackHandler tracks emails as they are opened, updating the status for the given Result func (ps *PhishingServer) TrackHandler(w http.ResponseWriter, r *http.Request) { - err, r := setupContext(r) + r, err := setupContext(r) if err != nil { // Log the error if it wasn't something we can safely ignore if err != ErrInvalidRequest && err != ErrCampaignComplete { @@ -159,7 +159,7 @@ func (ps *PhishingServer) TrackHandler(w http.ResponseWriter, r *http.Request) { // ReportHandler tracks emails as they are reported, updating the status for the given Result func (ps *PhishingServer) ReportHandler(w http.ResponseWriter, r *http.Request) { - err, r := setupContext(r) + r, err := setupContext(r) if err != nil { // Log the error if it wasn't something we can safely ignore if err != ErrInvalidRequest && err != ErrCampaignComplete { @@ -193,7 +193,7 @@ func (ps *PhishingServer) ReportHandler(w http.ResponseWriter, r *http.Request) // PhishHandler handles incoming client connections and registers the associated actions performed // (such as clicked link, etc.) func (ps *PhishingServer) PhishHandler(w http.ResponseWriter, r *http.Request) { - err, r := setupContext(r) + r, err := setupContext(r) if err != nil { // Log the error if it wasn't something we can safely ignore if err != ErrInvalidRequest && err != ErrCampaignComplete { @@ -304,15 +304,15 @@ func (ps *PhishingServer) TransparencyHandler(w http.ResponseWriter, r *http.Req // setupContext handles some of the administrative work around receiving a new // request, such as checking the result ID, the campaign, etc. -func setupContext(r *http.Request) (error, *http.Request) { +func setupContext(r *http.Request) (*http.Request, error) { err := r.ParseForm() if err != nil { log.Error(err) - return err, r + return r, err } rid := r.Form.Get(models.RecipientParameter) if rid == "" { - return ErrInvalidRequest, r + return r, ErrInvalidRequest } // Since we want to support the common case of adding a "+" to indicate a // transparency request, we need to take care to handle the case where the @@ -332,28 +332,28 @@ func setupContext(r *http.Request) (error, *http.Request) { if strings.HasPrefix(id, models.PreviewPrefix) { rs, err := models.GetEmailRequestByResultId(id) if err != nil { - return err, r + return r, err } r = ctx.Set(r, "result", rs) - return nil, r + return r, nil } rs, err := models.GetResult(id) if err != nil { - return err, r + return r, err } c, err := models.GetCampaign(rs.CampaignId, rs.UserId) if err != nil { log.Error(err) - return err, r + return r, err } // Don't process events for completed campaigns - if c.Status == models.CAMPAIGN_COMPLETE { - return ErrCampaignComplete, r + if c.Status == models.CampaignComplete { + return r, ErrCampaignComplete } ip, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { log.Error(err) - return err, r + return r, err } // Respect X-Forwarded headers if fips := r.Header.Get("X-Forwarded-For"); fips != "" { @@ -375,5 +375,5 @@ func setupContext(r *http.Request) (error, *http.Request) { r = ctx.Set(r, "result", rs) r = ctx.Set(r, "campaign", c) r = ctx.Set(r, "details", d) - return nil, r + return r, nil } diff --git a/controllers/phish_test.go b/controllers/phish_test.go index dca961a6..c1b53c54 100644 --- a/controllers/phish_test.go +++ b/controllers/phish_test.go @@ -102,22 +102,22 @@ func (s *ControllersSuite) transparencyRequest(r models.Result, rid, path string func (s *ControllersSuite) TestOpenedPhishingEmail() { campaign := s.getFirstCampaign() result := campaign.Results[0] - s.Equal(result.Status, models.STATUS_SENDING) + s.Equal(result.Status, models.StatusSending) s.openEmail(result.RId) campaign = s.getFirstCampaign() result = campaign.Results[0] lastEvent := campaign.Events[len(campaign.Events)-1] - s.Equal(result.Status, models.EVENT_OPENED) - s.Equal(lastEvent.Message, models.EVENT_OPENED) + s.Equal(result.Status, models.EventOpened) + s.Equal(lastEvent.Message, models.EventOpened) s.Equal(result.ModifiedDate, lastEvent.Time) } func (s *ControllersSuite) TestReportedPhishingEmail() { campaign := s.getFirstCampaign() result := campaign.Results[0] - s.Equal(result.Status, models.STATUS_SENDING) + s.Equal(result.Status, models.StatusSending) s.reportedEmail(result.RId) @@ -125,14 +125,14 @@ func (s *ControllersSuite) TestReportedPhishingEmail() { result = campaign.Results[0] lastEvent := campaign.Events[len(campaign.Events)-1] s.Equal(result.Reported, true) - s.Equal(lastEvent.Message, models.EVENT_REPORTED) + s.Equal(lastEvent.Message, models.EventReported) s.Equal(result.ModifiedDate, lastEvent.Time) } func (s *ControllersSuite) TestClickedPhishingLinkAfterOpen() { campaign := s.getFirstCampaign() result := campaign.Results[0] - s.Equal(result.Status, models.STATUS_SENDING) + s.Equal(result.Status, models.StatusSending) s.openEmail(result.RId) s.clickLink(result.RId, campaign.Page.HTML) @@ -140,8 +140,8 @@ func (s *ControllersSuite) TestClickedPhishingLinkAfterOpen() { campaign = s.getFirstCampaign() result = campaign.Results[0] lastEvent := campaign.Events[len(campaign.Events)-1] - s.Equal(result.Status, models.EVENT_CLICKED) - s.Equal(lastEvent.Message, models.EVENT_CLICKED) + s.Equal(result.Status, models.EventClicked) + s.Equal(lastEvent.Message, models.EventClicked) s.Equal(result.ModifiedDate, lastEvent.Time) } @@ -165,12 +165,12 @@ func (s *ControllersSuite) TestInvalidRecipientID() { func (s *ControllersSuite) TestCompletedCampaignClick() { campaign := s.getFirstCampaign() result := campaign.Results[0] - s.Equal(result.Status, models.STATUS_SENDING) + s.Equal(result.Status, models.StatusSending) s.openEmail(result.RId) campaign = s.getFirstCampaign() result = campaign.Results[0] - s.Equal(result.Status, models.EVENT_OPENED) + s.Equal(result.Status, models.EventOpened) models.CompleteCampaign(campaign.Id, 1) s.openEmail404(result.RId) @@ -178,7 +178,7 @@ func (s *ControllersSuite) TestCompletedCampaignClick() { campaign = s.getFirstCampaign() result = campaign.Results[0] - s.Equal(result.Status, models.EVENT_OPENED) + s.Equal(result.Status, models.EventOpened) } func (s *ControllersSuite) TestRobotsHandler() { diff --git a/controllers/route.go b/controllers/route.go index c27499d8..b71f4e0d 100644 --- a/controllers/route.go +++ b/controllers/route.go @@ -109,27 +109,27 @@ func (as *AdminServer) registerRoutes() { api := router.PathPrefix("/api").Subrouter() api = api.StrictSlash(true) api.Use(mid.RequireAPIKey) - api.HandleFunc("/reset", as.API_Reset) - api.HandleFunc("/campaigns/", as.API_Campaigns) - api.HandleFunc("/campaigns/summary", as.API_Campaigns_Summary) - api.HandleFunc("/campaigns/{id:[0-9]+}", as.API_Campaigns_Id) - api.HandleFunc("/campaigns/{id:[0-9]+}/results", as.API_Campaigns_Id_Results) - api.HandleFunc("/campaigns/{id:[0-9]+}/summary", as.API_Campaign_Id_Summary) - api.HandleFunc("/campaigns/{id:[0-9]+}/complete", as.API_Campaigns_Id_Complete) - api.HandleFunc("/groups/", as.API_Groups) - api.HandleFunc("/groups/summary", as.API_Groups_Summary) - api.HandleFunc("/groups/{id:[0-9]+}", as.API_Groups_Id) - api.HandleFunc("/groups/{id:[0-9]+}/summary", as.API_Groups_Id_Summary) - api.HandleFunc("/templates/", as.API_Templates) - api.HandleFunc("/templates/{id:[0-9]+}", as.API_Templates_Id) - api.HandleFunc("/pages/", as.API_Pages) - api.HandleFunc("/pages/{id:[0-9]+}", as.API_Pages_Id) - api.HandleFunc("/smtp/", as.API_SMTP) - api.HandleFunc("/smtp/{id:[0-9]+}", as.API_SMTP_Id) - api.HandleFunc("/util/send_test_email", as.API_Send_Test_Email) - api.HandleFunc("/import/group", as.API_Import_Group) - api.HandleFunc("/import/email", as.API_Import_Email) - api.HandleFunc("/import/site", as.API_Import_Site) + api.HandleFunc("/reset", as.APIReset) + api.HandleFunc("/campaigns/", as.APICampaigns) + api.HandleFunc("/campaigns/summary", as.APICampaignsSummary) + api.HandleFunc("/campaigns/{id:[0-9]+}", as.APICampaign) + api.HandleFunc("/campaigns/{id:[0-9]+}/results", as.APICampaignResults) + api.HandleFunc("/campaigns/{id:[0-9]+}/summary", as.APICampaignSummary) + api.HandleFunc("/campaigns/{id:[0-9]+}/complete", as.APICampaignComplete) + api.HandleFunc("/groups/", as.APIGroups) + api.HandleFunc("/groups/summary", as.APIGroupsSummary) + api.HandleFunc("/groups/{id:[0-9]+}", as.APIGroup) + api.HandleFunc("/groups/{id:[0-9]+}/summary", as.APIGroupSummary) + api.HandleFunc("/templates/", as.APITemplates) + api.HandleFunc("/templates/{id:[0-9]+}", as.APITemplate) + api.HandleFunc("/pages/", as.APIPages) + api.HandleFunc("/pages/{id:[0-9]+}", as.APIPage) + api.HandleFunc("/smtp/", as.APISendingProfiles) + api.HandleFunc("/smtp/{id:[0-9]+}", as.APISendingProfile) + api.HandleFunc("/util/send_test_email", as.APISendTestEmail) + api.HandleFunc("/import/group", as.APIImportGroup) + api.HandleFunc("/import/email", as.APIImportEmail) + api.HandleFunc("/import/site", as.APIImportSite) // Setup static file serving router.PathPrefix("/").Handler(http.FileServer(unindexed.Dir("./static/"))) diff --git a/logger/logger.go b/logger/logger.go index 1e107258..e697f5f3 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -33,50 +33,62 @@ func Setup(conf *config.Config) error { return nil } +// Debug logs a debug message func Debug(args ...interface{}) { Logger.Debug(args...) } +// Debugf logs a formatted debug messsage func Debugf(format string, args ...interface{}) { Logger.Debugf(format, args...) } +// Info logs an informational message func Info(args ...interface{}) { Logger.Info(args...) } +// Infof logs a formatted informational message func Infof(format string, args ...interface{}) { Logger.Infof(format, args...) } +// Error logs an error message func Error(args ...interface{}) { Logger.Error(args...) } +// Errorf logs a formatted error message func Errorf(format string, args ...interface{}) { Logger.Errorf(format, args...) } +// Warn logs a warning message func Warn(args ...interface{}) { Logger.Warn(args...) } +// Warnf logs a formatted warning message func Warnf(format string, args ...interface{}) { Logger.Warnf(format, args...) } +// Fatal logs a fatal error message func Fatal(args ...interface{}) { Logger.Fatal(args...) } +// Fatalf logs a formatted fatal error message func Fatalf(format string, args ...interface{}) { Logger.Fatalf(format, args...) } +// WithFields returns a new log enty with the provided fields func WithFields(fields logrus.Fields) *logrus.Entry { return Logger.WithFields(fields) } +// Writer returns the current logging writer func Writer() *io.PipeWriter { return Logger.Writer() } diff --git a/middleware/middleware.go b/middleware/middleware.go index 25e0c4b8..1e5455b1 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -12,10 +12,13 @@ import ( "github.com/gorilla/csrf" ) +// CSRFExemptPrefixes are a list of routes that are exempt from CSRF protection var CSRFExemptPrefixes = []string{ "/api", } +// CSRFExceptions is a middleware that prevents CSRF checks on routes listed in +// CSRFExemptPrefixes. func CSRFExceptions(handler http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { for _, prefix := range CSRFExemptPrefixes { diff --git a/models/campaign.go b/models/campaign.go index 9017f787..c1e1af9b 100644 --- a/models/campaign.go +++ b/models/campaign.go @@ -37,7 +37,7 @@ type CampaignResults struct { Id int64 `json:"id"` Name string `json:"name"` Status string `json:"status"` - Results []Result `json:"results, omitempty"` + Results []Result `json:"results,omitempty"` Events []Event `json:"timeline,omitempty"` } @@ -255,11 +255,11 @@ func getCampaignStats(cid int64) (CampaignStats, error) { if err != nil { return s, err } - query.Where("status=?", EVENT_DATA_SUBMIT).Count(&s.SubmittedData) + query.Where("status=?", EventDataSubmit).Count(&s.SubmittedData) if err != nil { return s, err } - query.Where("status=?", EVENT_CLICKED).Count(&s.ClickedLink) + query.Where("status=?", EventClicked).Count(&s.ClickedLink) if err != nil { return s, err } @@ -269,19 +269,19 @@ func getCampaignStats(cid int64) (CampaignStats, error) { } // Every submitted data event implies they clicked the link s.ClickedLink += s.SubmittedData - err = query.Where("status=?", EVENT_OPENED).Count(&s.OpenedEmail).Error + err = query.Where("status=?", EventOpened).Count(&s.OpenedEmail).Error if err != nil { return s, err } // Every clicked link event implies they opened the email s.OpenedEmail += s.ClickedLink - err = query.Where("status=?", EVENT_SENT).Count(&s.EmailsSent).Error + err = query.Where("status=?", EventSent).Count(&s.EmailsSent).Error if err != nil { return s, err } // Every opened email event implies the email was sent s.EmailsSent += s.OpenedEmail - err = query.Where("status=?", ERROR).Count(&s.Error).Error + err = query.Where("status=?", Error).Count(&s.Error).Error return s, err } @@ -386,7 +386,7 @@ func GetCampaignResults(id int64, uid int64) (CampaignResults, error) { func GetQueuedCampaigns(t time.Time) ([]Campaign, error) { cs := []Campaign{} err := db.Where("launch_date <= ?", t). - Where("status = ?", CAMPAIGN_QUEUED).Find(&cs).Error + Where("status = ?", CampaignQueued).Find(&cs).Error if err != nil { log.Error(err) } @@ -410,7 +410,7 @@ func PostCampaign(c *Campaign, uid int64) error { c.UserId = uid c.CreatedDate = time.Now().UTC() c.CompletedDate = time.Time{} - c.Status = CAMPAIGN_QUEUED + c.Status = CampaignQueued if c.LaunchDate.IsZero() { c.LaunchDate = c.CreatedDate } else { @@ -420,7 +420,7 @@ func PostCampaign(c *Campaign, uid int64) error { c.SendByDate = c.SendByDate.UTC() } if c.LaunchDate.Before(c.CreatedDate) || c.LaunchDate.Equal(c.CreatedDate) { - c.Status = CAMPAIGN_IN_PROGRESS + c.Status = CampaignInProgress } // Check to make sure all the groups already exist // Also, later we'll need to know the total number of recipients (counting @@ -508,7 +508,7 @@ func PostCampaign(c *Campaign, uid int64) error { FirstName: t.FirstName, LastName: t.LastName, }, - Status: STATUS_SCHEDULED, + Status: StatusScheduled, CampaignId: c.Id, UserId: c.UserId, SendDate: sendDate, @@ -522,7 +522,7 @@ func PostCampaign(c *Campaign, uid int64) error { } processing := false if r.SendDate.Before(c.CreatedDate) || r.SendDate.Equal(c.CreatedDate) { - r.Status = STATUS_SENDING + r.Status = StatusSending processing = true } err = db.Save(r).Error @@ -587,12 +587,12 @@ func CompleteCampaign(id int64, uid int64) error { return err } // Don't overwrite original completed time - if c.Status == CAMPAIGN_COMPLETE { + if c.Status == CampaignComplete { return nil } // Mark the campaign as complete c.CompletedDate = time.Now().UTC() - c.Status = CAMPAIGN_COMPLETE + c.Status = CampaignComplete err = db.Where("id=? and user_id=?", id, uid).Save(&c).Error if err != nil { log.Error(err) diff --git a/models/maillog.go b/models/maillog.go index bbcc7a25..98e4a904 100644 --- a/models/maillog.go +++ b/models/maillog.go @@ -20,7 +20,7 @@ import ( // attempt. This will give us a maximum send delay of 256 minutes, or about 4.2 hours. var MaxSendAttempts = 8 -// ErrMaxSendAttempts is thrown when the maximum number of sending attemps for a given +// ErrMaxSendAttempts is thrown when the maximum number of sending attempts for a given // MailLog is exceeded. var ErrMaxSendAttempts = errors.New("max send attempts exceeded") diff --git a/models/maillog_test.go b/models/maillog_test.go index 5011030f..5bce9ce0 100644 --- a/models/maillog_test.go +++ b/models/maillog_test.go @@ -90,7 +90,7 @@ func (s *ModelsSuite) TestMailLogBackoff(ch *check.C) { result, err := GetResult(m.RId) ch.Assert(err, check.Equals, nil) ch.Assert(result.SendDate, check.Equals, expectedSendDate) - ch.Assert(result.Status, check.Equals, STATUS_RETRY) + ch.Assert(result.Status, check.Equals, StatusRetry) } // Get our updated campaign and check for the added event campaign, err = GetCampaign(campaign.Id, int64(1)) @@ -123,7 +123,7 @@ func (s *ModelsSuite) TestMailLogError(ch *check.C) { // Get our result and make sure the status is set correctly result, err = GetResult(result.RId) ch.Assert(err, check.Equals, nil) - ch.Assert(result.Status, check.Equals, ERROR) + ch.Assert(result.Status, check.Equals, Error) // Get our updated campaign and check for the added event campaign, err = GetCampaign(campaign.Id, int64(1)) @@ -138,7 +138,7 @@ func (s *ModelsSuite) TestMailLogError(ch *check.C) { expectedEvent := Event{ Id: gotEvent.Id, Email: result.Email, - Message: EVENT_SENDING_ERROR, + Message: EventSendingError, CampaignId: campaign.Id, Details: string(ej), Time: gotEvent.Time, @@ -165,7 +165,7 @@ func (s *ModelsSuite) TestMailLogSuccess(ch *check.C) { // Get our result and make sure the status is set correctly result, err = GetResult(result.RId) ch.Assert(err, check.Equals, nil) - ch.Assert(result.Status, check.Equals, EVENT_SENT) + ch.Assert(result.Status, check.Equals, EventSent) // Get our updated campaign and check for the added event campaign, err = GetCampaign(campaign.Id, int64(1)) @@ -178,7 +178,7 @@ func (s *ModelsSuite) TestMailLogSuccess(ch *check.C) { expectedEvent := Event{ Id: gotEvent.Id, Email: result.Email, - Message: EVENT_SENT, + Message: EventSent, CampaignId: campaign.Id, Time: gotEvent.Time, } diff --git a/models/models.go b/models/models.go index 52f930a5..d3b7fbfc 100644 --- a/models/models.go +++ b/models/models.go @@ -18,25 +18,25 @@ var db *gorm.DB var conf *config.Config const ( - CAMPAIGN_IN_PROGRESS string = "In progress" - CAMPAIGN_QUEUED string = "Queued" - CAMPAIGN_CREATED string = "Created" - CAMPAIGN_EMAILS_SENT string = "Emails Sent" - CAMPAIGN_COMPLETE string = "Completed" - EVENT_SENT string = "Email Sent" - EVENT_SENDING_ERROR string = "Error Sending Email" - EVENT_OPENED string = "Email Opened" - EVENT_CLICKED string = "Clicked Link" - EVENT_DATA_SUBMIT string = "Submitted Data" - EVENT_REPORTED string = "Email Reported" - EVENT_PROXY_REQUEST string = "Proxied request" - STATUS_SUCCESS string = "Success" - STATUS_QUEUED string = "Queued" - STATUS_SENDING string = "Sending" - STATUS_UNKNOWN string = "Unknown" - STATUS_SCHEDULED string = "Scheduled" - STATUS_RETRY string = "Retrying" - ERROR string = "Error" + CampaignInProgress string = "In progress" + CampaignQueued string = "Queued" + CampaignCreated string = "Created" + CampaignEmailsSent string = "Emails Sent" + CampaignComplete string = "Completed" + EventSent string = "Email Sent" + EventSendingError string = "Error Sending Email" + EventOpened string = "Email Opened" + EventClicked string = "Clicked Link" + EventDataSubmit string = "Submitted Data" + EventReported string = "Email Reported" + EventProxyRequest string = "Proxied request" + StatusSuccess string = "Success" + StatusQueued string = "Queued" + StatusSending string = "Sending" + StatusUnknown string = "Unknown" + StatusScheduled string = "Scheduled" + StatusRetry string = "Retrying" + Error string = "Error" ) // Flash is used to hold flash information for use in templates. diff --git a/models/result.go b/models/result.go index 988ddffd..5b74dc83 100644 --- a/models/result.go +++ b/models/result.go @@ -58,12 +58,12 @@ func (r *Result) createEvent(status string, details interface{}) (*Event, error) // HandleEmailSent updates a Result to indicate that the email has been // successfully sent to the remote SMTP server func (r *Result) HandleEmailSent() error { - event, err := r.createEvent(EVENT_SENT, nil) + event, err := r.createEvent(EventSent, nil) if err != nil { return err } r.SendDate = event.Time - r.Status = EVENT_SENT + r.Status = EventSent r.ModifiedDate = event.Time return db.Save(r).Error } @@ -71,11 +71,11 @@ func (r *Result) HandleEmailSent() error { // HandleEmailError updates a Result to indicate that there was an error when // attempting to send the email to the remote SMTP server. func (r *Result) HandleEmailError(err error) error { - event, err := r.createEvent(EVENT_SENDING_ERROR, EventError{Error: err.Error()}) + event, err := r.createEvent(EventSendingError, EventError{Error: err.Error()}) if err != nil { return err } - r.Status = ERROR + r.Status = Error r.ModifiedDate = event.Time return db.Save(r).Error } @@ -83,11 +83,11 @@ func (r *Result) HandleEmailError(err error) error { // HandleEmailBackoff updates a Result to indicate that the email received a // temporary error and needs to be retried func (r *Result) HandleEmailBackoff(err error, sendDate time.Time) error { - event, err := r.createEvent(EVENT_SENDING_ERROR, EventError{Error: err.Error()}) + event, err := r.createEvent(EventSendingError, EventError{Error: err.Error()}) if err != nil { return err } - r.Status = STATUS_RETRY + r.Status = StatusRetry r.SendDate = sendDate r.ModifiedDate = event.Time return db.Save(r).Error @@ -96,16 +96,16 @@ func (r *Result) HandleEmailBackoff(err error, sendDate time.Time) error { // HandleEmailOpened updates a Result in the case where the recipient opened the // email. func (r *Result) HandleEmailOpened(details EventDetails) error { - event, err := r.createEvent(EVENT_OPENED, details) + event, err := r.createEvent(EventOpened, details) if err != nil { return err } // Don't update the status if the user already clicked the link // or submitted data to the campaign - if r.Status == EVENT_CLICKED || r.Status == EVENT_DATA_SUBMIT { + if r.Status == EventClicked || r.Status == EventDataSubmit { return nil } - r.Status = EVENT_OPENED + r.Status = EventOpened r.ModifiedDate = event.Time return db.Save(r).Error } @@ -113,16 +113,16 @@ func (r *Result) HandleEmailOpened(details EventDetails) error { // HandleClickedLink updates a Result in the case where the recipient clicked // the link in an email. func (r *Result) HandleClickedLink(details EventDetails) error { - event, err := r.createEvent(EVENT_CLICKED, details) + event, err := r.createEvent(EventClicked, details) if err != nil { return err } // Don't update the status if the user has already submitted data via the // landing page form. - if r.Status == EVENT_DATA_SUBMIT { + if r.Status == EventDataSubmit { return nil } - r.Status = EVENT_CLICKED + r.Status = EventClicked r.ModifiedDate = event.Time return db.Save(r).Error } @@ -130,11 +130,11 @@ func (r *Result) HandleClickedLink(details EventDetails) error { // HandleFormSubmit updates a Result in the case where the recipient submitted // credentials to the form on a Landing Page. func (r *Result) HandleFormSubmit(details EventDetails) error { - event, err := r.createEvent(EVENT_DATA_SUBMIT, details) + event, err := r.createEvent(EventDataSubmit, details) if err != nil { return err } - r.Status = EVENT_DATA_SUBMIT + r.Status = EventDataSubmit r.ModifiedDate = event.Time return db.Save(r).Error } @@ -142,7 +142,7 @@ func (r *Result) HandleFormSubmit(details EventDetails) error { // HandleEmailReport updates a Result in the case where they report a simulated // phishing email using the HTTP handler. func (r *Result) HandleEmailReport(details EventDetails) error { - event, err := r.createEvent(EVENT_REPORTED, details) + event, err := r.createEvent(EventReported, details) if err != nil { return err } diff --git a/models/result_test.go b/models/result_test.go index 3b7f3394..c41f2615 100644 --- a/models/result_test.go +++ b/models/result_test.go @@ -42,7 +42,7 @@ func (s *ModelsSuite) TestResultSendingStatus(ch *check.C) { // This campaign wasn't scheduled, so we expect the status to // be sending for _, r := range c.Results { - ch.Assert(r.Status, check.Equals, STATUS_SENDING) + ch.Assert(r.Status, check.Equals, StatusSending) ch.Assert(r.ModifiedDate, check.Equals, c.CreatedDate) } } @@ -53,7 +53,7 @@ func (s *ModelsSuite) TestResultScheduledStatus(ch *check.C) { // This campaign wasn't scheduled, so we expect the status to // be sending for _, r := range c.Results { - ch.Assert(r.Status, check.Equals, STATUS_SCHEDULED) + ch.Assert(r.Status, check.Equals, StatusScheduled) ch.Assert(r.ModifiedDate, check.Equals, c.CreatedDate) } } @@ -68,9 +68,9 @@ func (s *ModelsSuite) TestResultVariableStatus(ch *check.C) { // emails to be sent immediately, while others will be scheduled for _, r := range c.Results { if r.SendDate.Before(c.CreatedDate) || r.SendDate.Equal(c.CreatedDate) { - ch.Assert(r.Status, check.Equals, STATUS_SENDING) + ch.Assert(r.Status, check.Equals, StatusSending) } else { - ch.Assert(r.Status, check.Equals, STATUS_SCHEDULED) + ch.Assert(r.Status, check.Equals, StatusScheduled) } } } diff --git a/models/template.go b/models/template.go index 8f0637e9..05d4a64c 100644 --- a/models/template.go +++ b/models/template.go @@ -51,7 +51,7 @@ func GetTemplates(uid int64) ([]Template, error) { log.Error(err) return ts, err } - for i, _ := range ts { + for i := range ts { // Get Attachments err = db.Where("template_id=?", ts[i].Id).Find(&ts[i].Attachments).Error if err == nil && len(ts[i].Attachments) == 0 { diff --git a/worker/worker.go b/worker/worker.go index 7161ec4b..1a93128e 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -81,8 +81,8 @@ func (w *DefaultWorker) Start() { errorMail(err, msc) return } - if c.Status == models.CAMPAIGN_QUEUED { - err := c.UpdateStatus(models.CAMPAIGN_IN_PROGRESS) + if c.Status == models.CampaignQueued { + err := c.UpdateStatus(models.CampaignInProgress) if err != nil { log.Error(err) return diff --git a/worker/worker_test.go b/worker/worker_test.go index a0252604..eecd59ec 100644 --- a/worker/worker_test.go +++ b/worker/worker_test.go @@ -74,5 +74,5 @@ func (s *WorkerSuite) SetupTest() { c.SMTP = smtp c.Groups = []models.Group{group} models.PostCampaign(&c, c.UserId) - c.UpdateStatus(models.CAMPAIGN_EMAILS_SENT) + c.UpdateStatus(models.CampaignEmailsSent) }