mirror of
https://github.com/gophish/gophish
synced 2024-11-14 00:07:19 +00:00
General code cleanup as part of an effort to integrate staticcheck into our CI pipeline.
This commit is contained in:
parent
0961e22126
commit
ec8b17238e
25 changed files with 58 additions and 75 deletions
|
@ -68,7 +68,7 @@ func TestLoadConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load an invalid config
|
// Load an invalid config
|
||||||
conf, err = LoadConfig("bogusfile")
|
_, err = LoadConfig("bogusfile")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected error when loading invalid config, but got %v", err)
|
t.Fatalf("expected error when loading invalid config, but got %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,4 @@ func Set(r *http.Request, key, val interface{}) *http.Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear is a null operation, since this is handled automatically in Go > 1.7
|
// Clear is a null operation, since this is handled automatically in Go > 1.7
|
||||||
func Clear(r *http.Request) {
|
func Clear(r *http.Request) {}
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
|
@ -42,18 +42,6 @@ func setupTest(t *testing.T) *testContext {
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func tearDown(t *testing.T, ctx *testContext) {
|
|
||||||
// Cleanup all users except the original admin
|
|
||||||
// users, _ := models.GetUsers()
|
|
||||||
// for _, user := range users {
|
|
||||||
// if user.Id == 1 {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// err := models.DeleteUser(user.Id)
|
|
||||||
// s.Nil(err)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestData(t *testing.T) {
|
func createTestData(t *testing.T) {
|
||||||
// Add a group
|
// Add a group
|
||||||
group := models.Group{Name: "Test Group"}
|
group := models.Group{Name: "Test Group"}
|
||||||
|
|
|
@ -87,6 +87,11 @@ func (as *Server) Group(w http.ResponseWriter, r *http.Request) {
|
||||||
// Change this to get from URL and uid (don't bother with id in r.Body)
|
// Change this to get from URL and uid (don't bother with id in r.Body)
|
||||||
g = models.Group{}
|
g = models.Group{}
|
||||||
err = json.NewDecoder(r.Body).Decode(&g)
|
err = json.NewDecoder(r.Body).Decode(&g)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error decoding group: %v", err)
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
if g.Id != id {
|
if g.Id != id {
|
||||||
JSONResponse(w, models.Response{Success: false, Message: "Error: /:id and group_id mismatch"}, http.StatusInternalServerError)
|
JSONResponse(w, models.Response{Success: false, Message: "Error: /:id and group_id mismatch"}, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
|
@ -46,7 +46,6 @@ func (as *Server) ImportGroup(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
JSONResponse(w, ts, http.StatusOK)
|
JSONResponse(w, ts, http.StatusOK)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportEmail allows for the importing of email.
|
// ImportEmail allows for the importing of email.
|
||||||
|
@ -94,7 +93,6 @@ func (as *Server) ImportEmail(w http.ResponseWriter, r *http.Request) {
|
||||||
HTML: string(e.HTML),
|
HTML: string(e.HTML),
|
||||||
}
|
}
|
||||||
JSONResponse(w, er, http.StatusOK)
|
JSONResponse(w, er, http.StatusOK)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportSite allows for the importing of HTML from a website
|
// ImportSite allows for the importing of HTML from a website
|
||||||
|
@ -153,5 +151,4 @@ func (as *Server) ImportSite(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
cs := cloneResponse{HTML: h}
|
cs := cloneResponse{HTML: h}
|
||||||
JSONResponse(w, cs, http.StatusOK)
|
JSONResponse(w, cs, http.StatusOK)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,5 +118,4 @@ func (as *Server) SendTestEmail(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
JSONResponse(w, models.Response{Success: true, Message: "Email Sent"}, http.StatusOK)
|
JSONResponse(w, models.Response{Success: true, Message: "Email Sent"}, http.StatusOK)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,15 +62,20 @@ func (as *Server) Webhook(w http.ResponseWriter, r *http.Request) {
|
||||||
JSONResponse(w, models.Response{Success: true, Message: "Webhook deleted Successfully!"}, http.StatusOK)
|
JSONResponse(w, models.Response{Success: true, Message: "Webhook deleted Successfully!"}, http.StatusOK)
|
||||||
|
|
||||||
case r.Method == "PUT":
|
case r.Method == "PUT":
|
||||||
wh2 := models.Webhook{}
|
wh = models.Webhook{}
|
||||||
err = json.NewDecoder(r.Body).Decode(&wh2)
|
err = json.NewDecoder(r.Body).Decode(&wh)
|
||||||
wh2.Id = id
|
if err != nil {
|
||||||
err = models.PutWebhook(&wh2)
|
log.Errorf("error decoding webhook: %v", err)
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wh.Id = id
|
||||||
|
err = models.PutWebhook(&wh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest)
|
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
JSONResponse(w, wh2, http.StatusOK)
|
JSONResponse(w, wh, http.StatusOK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,7 @@ func (as *AdminServer) Impersonate(w http.ResponseWriter, r *http.Request) {
|
||||||
session.Values["id"] = u.Id
|
session.Values["id"] = u.Id
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/", 302)
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login handles the authentication flow for a user. If credentials are valid,
|
// Login handles the authentication flow for a user. If credentials are valid,
|
||||||
|
@ -326,7 +326,7 @@ func (as *AdminServer) Login(w http.ResponseWriter, r *http.Request) {
|
||||||
next = path
|
next = path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, next, 302)
|
http.Redirect(w, r, next, http.StatusFound)
|
||||||
} else {
|
} else {
|
||||||
Flash(w, r, "danger", "Invalid Username/Password")
|
Flash(w, r, "danger", "Invalid Username/Password")
|
||||||
params.Flashes = session.Flashes()
|
params.Flashes = session.Flashes()
|
||||||
|
@ -349,7 +349,7 @@ func (as *AdminServer) Logout(w http.ResponseWriter, r *http.Request) {
|
||||||
delete(session.Values, "id")
|
delete(session.Values, "id")
|
||||||
Flash(w, r, "success", "You have successfully logged out")
|
Flash(w, r, "success", "You have successfully logged out")
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
http.Redirect(w, r, "/login", 302)
|
http.Redirect(w, r, "/login", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTemplate(w http.ResponseWriter, tmpl string) *template.Template {
|
func getTemplate(w http.ResponseWriter, tmpl string) *template.Template {
|
||||||
|
|
|
@ -305,7 +305,6 @@ func getEmails(client Client, cmd *imap.Command, markAsRead, delete bool, respon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteEmail(client Client, UID uint32) error {
|
func deleteEmail(client Client, UID uint32) error {
|
||||||
|
|
|
@ -162,7 +162,7 @@ func checkForNewEmails(im models.IMAP) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error updating GoPhish email with rid ", rid, ": ", err.Error())
|
log.Error("Error updating GoPhish email with rid ", rid, ": ", err.Error())
|
||||||
} else {
|
} else {
|
||||||
if im.DeleteReportedCampaignEmail == true {
|
if im.DeleteReportedCampaignEmail {
|
||||||
campaignEmails = append(campaignEmails, m.UID)
|
campaignEmails = append(campaignEmails, m.UID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func checkForNewEmails(im models.IMAP) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the DeleteReportedCampaignEmail flag is set, delete reported Gophish campaign emails
|
// If the DeleteReportedCampaignEmail flag is set, delete reported Gophish campaign emails
|
||||||
if im.DeleteReportedCampaignEmail == true && len(campaignEmails) > 0 {
|
if im.DeleteReportedCampaignEmail && len(campaignEmails) > 0 {
|
||||||
log.Debugf("Deleting %d campaign emails\n", len(campaignEmails))
|
log.Debugf("Deleting %d campaign emails\n", len(campaignEmails))
|
||||||
err := mailServer.DeleteEmails(campaignEmails) // Delete GoPhish campaign emails.
|
err := mailServer.DeleteEmails(campaignEmails) // Delete GoPhish campaign emails.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,11 +13,6 @@ import (
|
||||||
// being unreachable
|
// being unreachable
|
||||||
var errHostUnreachable = errors.New("host unreachable")
|
var errHostUnreachable = errors.New("host unreachable")
|
||||||
|
|
||||||
// errDialerUnavailable is a mock error to represent a dialer
|
|
||||||
// being unavailable (perhaps an error getting the dialer config
|
|
||||||
// or a database error)
|
|
||||||
var errDialerUnavailable = errors.New("dialer unavailable")
|
|
||||||
|
|
||||||
// mockDialer keeps track of calls to Dial
|
// mockDialer keeps track of calls to Dial
|
||||||
type mockDialer struct {
|
type mockDialer struct {
|
||||||
dialCount int
|
dialCount int
|
||||||
|
@ -137,10 +132,6 @@ func (mm *mockMessage) defaultDialer() (Dialer, error) {
|
||||||
return newMockDialer(), nil
|
return newMockDialer(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mm *mockMessage) errorDialer() (Dialer, error) {
|
|
||||||
return nil, errDialerUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mm *mockMessage) GetDialer() (Dialer, error) {
|
func (mm *mockMessage) GetDialer() (Dialer, error) {
|
||||||
return mm.getdialer()
|
return mm.getdialer()
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,6 @@ func RequireLogin(handler http.Handler) http.HandlerFunc {
|
||||||
q := r.URL.Query()
|
q := r.URL.Query()
|
||||||
q.Set("next", r.URL.Path)
|
q.Set("next", r.URL.Path)
|
||||||
http.Redirect(w, r, fmt.Sprintf("/login?%s", q.Encode()), http.StatusTemporaryRedirect)
|
http.Redirect(w, r, fmt.Sprintf("/login?%s", q.Encode()), http.StatusTemporaryRedirect)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ type Campaign struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Results []Result `json:"results,omitempty"`
|
Results []Result `json:"results,omitempty"`
|
||||||
Groups []Group `json:"groups,omitempty"`
|
Groups []Group `json:"groups,omitempty"`
|
||||||
Events []Event `json:"timeline,omitemtpy"`
|
Events []Event `json:"timeline,omitempty"`
|
||||||
SMTPId int64 `json:"-"`
|
SMTPId int64 `json:"-"`
|
||||||
SMTP SMTP `json:"smtp"`
|
SMTP SMTP `json:"smtp"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
|
|
|
@ -103,10 +103,6 @@ func (s *EmailRequest) Generate(msg *gomail.Message) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fn := f.Name
|
|
||||||
if fn == "" {
|
|
||||||
fn = f.Address
|
|
||||||
}
|
|
||||||
msg.SetAddressHeader("From", f.Address, f.Name)
|
msg.SetAddressHeader("From", f.Address, f.Name)
|
||||||
|
|
||||||
ptx, err := NewPhishingTemplateContext(s, s.BaseRecipient, s.RId)
|
ptx, err := NewPhishingTemplateContext(s, s.BaseRecipient, s.RId)
|
||||||
|
|
|
@ -226,7 +226,6 @@ func PutGroup(g *Group) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Fetch group's existing targets from database.
|
// Fetch group's existing targets from database.
|
||||||
ts := []Target{}
|
|
||||||
ts, err := GetTargets(g.Id)
|
ts, err := GetTargets(g.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
|
|
|
@ -53,7 +53,7 @@ var ErrIMAPPasswordNotSpecified = errors.New("No Password specified")
|
||||||
|
|
||||||
// ErrInvalidIMAPFreq is thrown when the frequency for polling the
|
// ErrInvalidIMAPFreq is thrown when the frequency for polling the
|
||||||
// IMAP server is invalid
|
// IMAP server is invalid
|
||||||
var ErrInvalidIMAPFreq = errors.New("Invalid polling frequency.")
|
var ErrInvalidIMAPFreq = errors.New("Invalid polling frequency")
|
||||||
|
|
||||||
// TableName specifies the database tablename for Gorm to use
|
// TableName specifies the database tablename for Gorm to use
|
||||||
func (im IMAP) TableName() string {
|
func (im IMAP) TableName() string {
|
||||||
|
|
|
@ -125,7 +125,7 @@ func (m *MailLog) Success() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = db.Delete(m).Error
|
err = db.Delete(m).Error
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDialer returns a dialer based on the maillog campaign's SMTP configuration
|
// GetDialer returns a dialer based on the maillog campaign's SMTP configuration
|
||||||
|
|
|
@ -138,6 +138,9 @@ func PostPage(p *Page) error {
|
||||||
// Per the PUT Method RFC, it presumes all data for a page is provided.
|
// Per the PUT Method RFC, it presumes all data for a page is provided.
|
||||||
func PutPage(p *Page) error {
|
func PutPage(p *Page) error {
|
||||||
err := p.Validate()
|
err := p.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = db.Where("id=?", p.Id).Save(p).Error
|
err = db.Where("id=?", p.Id).Save(p).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
|
|
@ -27,7 +27,9 @@ func (s *ModelsSuite) TestGetUserByAPIKeyWithExistingAPIKey(c *check.C) {
|
||||||
u, err := GetUser(1)
|
u, err := GetUser(1)
|
||||||
c.Assert(err, check.Equals, nil)
|
c.Assert(err, check.Equals, nil)
|
||||||
|
|
||||||
u, err = GetUserByAPIKey(u.ApiKey)
|
got, err := GetUserByAPIKey(u.ApiKey)
|
||||||
|
c.Assert(err, check.Equals, nil)
|
||||||
|
c.Assert(got.Id, check.Equals, u.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ModelsSuite) TestGetUserByAPIKeyWithNotExistingAPIKey(c *check.C) {
|
func (s *ModelsSuite) TestGetUserByAPIKeyWithNotExistingAPIKey(c *check.C) {
|
||||||
|
@ -46,11 +48,12 @@ func (s *ModelsSuite) TestGetUserByUsernameWithNotExistingUser(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ModelsSuite) TestPutUser(c *check.C) {
|
func (s *ModelsSuite) TestPutUser(c *check.C) {
|
||||||
u, err := GetUser(1)
|
u, _ := GetUser(1)
|
||||||
u.Username = "admin_changed"
|
u.Username = "admin_changed"
|
||||||
err = PutUser(&u)
|
err := PutUser(&u)
|
||||||
c.Assert(err, check.Equals, nil)
|
c.Assert(err, check.Equals, nil)
|
||||||
u, err = GetUser(1)
|
u, err = GetUser(1)
|
||||||
|
c.Assert(err, check.Equals, nil)
|
||||||
c.Assert(u.Username, check.Equals, "admin_changed")
|
c.Assert(u.Username, check.Equals, "admin_changed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
static/js/dist/app/webhooks.min.js
vendored
2
static/js/dist/app/webhooks.min.js
vendored
|
@ -1 +1 @@
|
||||||
!function(e){var o={};function n(t){if(o[t])return o[t].exports;var a=o[t]={i:t,l:!1,exports:{}};return e[t].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=o,n.d=function(e,o,t){n.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:t})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,o){if(1&o&&(e=n(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(n.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var a in e)n.d(t,a,function(o){return e[o]}.bind(null,a));return t},n.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(o,"a",o),o},n.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},n.p="",n(n.s=1)}([,function(e,o){var n=[],t=function(){$("#name").val(""),$("#url").val(""),$("#secret").val(""),$("#is_active").prop("checked",!1),$("#flashes").empty()},a=function(){$("#webhookTable").hide(),$("#loading").show(),api.webhooks.get().success(function(e){n=e,$("#loading").hide(),$("#webhookTable").show();var o=$("#webhookTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]});o.clear(),$.each(n,function(e,n){o.row.add([escapeHtml(n.name),escapeHtml(n.url),escapeHtml(n.is_active),'\n <div class="pull-right">\n <button class="btn btn-primary ping_button" data-webhook-id="'.concat(n.id,'">\n Ping\n </button>\n <button class="btn btn-primary edit_button" data-toggle="modal" data-backdrop="static" data-target="#modal" data-webhook-id="').concat(n.id,'">\n <i class="fa fa-pencil"></i>\n </button>\n <button class="btn btn-danger delete_button" data-webhook-id="').concat(n.id,'">\n <i class="fa fa-trash-o"></i>\n </button>\n </div>\n ')]).draw()})}).error(function(){errorFlash("Error fetching webhooks")})},c=function(e){$("#modalSubmit").unbind("click").click(function(){!function(e){var o={name:$("#name").val(),url:$("#url").val(),secret:$("#secret").val(),is_active:$("#is_active").is(":checked")};-1!=e?(o.id=e,api.webhookId.put(o).success(function(e){t(),a(),$("#modal").modal("hide"),successFlash('Webhook "'.concat(escape(o.name),'" has been updated successfully!'))}).error(function(e){modalError(e.responseJSON.message)})):api.webhooks.post(o).success(function(e){a(),t(),$("#modal").modal("hide"),successFlash('Webhook "'.concat(escape(o.name),'" has been created successfully!'))}).error(function(e){modalError(e.responseJSON.message)})}(e)}),-1!==e&&api.webhookId.get(e).success(function(e){$("#name").val(e.name),$("#url").val(e.url),$("#secret").val(e.secret),$("#is_active").prop("checked",e.is_active)}).error(function(){errorFlash("Error fetching webhook")})};$(document).ready(function(){a(),$("#modal").on("hide.bs.modal",function(){t()}),$("#new_button").on("click",function(){c(-1)}),$("#webhookTable").on("click",".edit_button",function(e){c($(this).attr("data-webhook-id"))}),$("#webhookTable").on("click",".delete_button",function(e){var o,t;o=$(this).attr("data-webhook-id"),(t=n.find(function(e){return e.id==o}))&&Swal.fire({title:"Are you sure?",text:"This will delete the webhook '".concat(escape(t.name),"'"),type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Delete",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1,preConfirm:function(){return new Promise(function(e,n){api.webhookId.delete(o).success(function(o){e()}).error(function(e){n(e.responseJSON.message)})}).catch(function(e){Swal.showValidationMessage(e)})}}).then(function(e){e.value&&Swal.fire("Webhook Deleted!","The webhook has been deleted!","success"),$("button:contains('OK')").on("click",function(){location.reload()})})}),$("#webhookTable").on("click",".ping_button",function(e){var o,a;o=e.currentTarget,a=e.currentTarget.dataset.webhookId,t(),o.disabled=!0,api.webhookId.ping(a).success(function(e){o.disabled=!1,successFlash('Ping of "'.concat(escape(e.name),'" webhook succeeded.'))}).error(function(e){o.disabled=!1;var t=n.find(function(e){return e.id==a});t&&errorFlash('Ping of "'.concat(escape(t.name),'" webhook failed: "').concat(e.responseJSON.message,'"'))})})})}]);
|
!function(e){var t={};function n(o){if(t[o])return t[o].exports;var a=t[o]={i:o,l:!1,exports:{}};return e[o].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(o,a,function(t){return e[t]}.bind(null,a));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([,function(e,t){var n=[],o=function(){$("#name").val(""),$("#url").val(""),$("#secret").val(""),$("#is_active").prop("checked",!1),$("#flashes").empty()},a=function(){$("#webhookTable").hide(),$("#loading").show(),api.webhooks.get().success(function(e){n=e,$("#loading").hide(),$("#webhookTable").show();var t=$("#webhookTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]});t.clear(),$.each(n,function(e,n){t.row.add([escapeHtml(n.name),escapeHtml(n.url),escapeHtml(n.is_active),'\n <div class="pull-right">\n <button class="btn btn-primary ping_button" data-webhook-id="'.concat(n.id,'">\n Ping\n </button>\n <button class="btn btn-primary edit_button" data-toggle="modal" data-backdrop="static" data-target="#modal" data-webhook-id="').concat(n.id,'">\n <i class="fa fa-pencil"></i>\n </button>\n <button class="btn btn-danger delete_button" data-webhook-id="').concat(n.id,'">\n <i class="fa fa-trash-o"></i>\n </button>\n </div>\n ')]).draw()})}).error(function(){errorFlash("Error fetching webhooks")})},c=function(e){$("#modalSubmit").unbind("click").click(function(){!function(e){var t={name:$("#name").val(),url:$("#url").val(),secret:$("#secret").val(),is_active:$("#is_active").is(":checked")};-1!=e?(t.id=parseInt(e),api.webhookId.put(t).success(function(e){o(),a(),$("#modal").modal("hide"),successFlash('Webhook "'.concat(escapeHtml(t.name),'" has been updated successfully!'))}).error(function(e){modalError(e.responseJSON.message)})):api.webhooks.post(t).success(function(e){a(),o(),$("#modal").modal("hide"),successFlash('Webhook "'.concat(escapeHtml(t.name),'" has been created successfully!'))}).error(function(e){modalError(e.responseJSON.message)})}(e)}),-1!==e&&api.webhookId.get(e).success(function(e){$("#name").val(e.name),$("#url").val(e.url),$("#secret").val(e.secret),$("#is_active").prop("checked",e.is_active)}).error(function(){errorFlash("Error fetching webhook")})};$(document).ready(function(){a(),$("#modal").on("hide.bs.modal",function(){o()}),$("#new_button").on("click",function(){c(-1)}),$("#webhookTable").on("click",".edit_button",function(e){c($(this).attr("data-webhook-id"))}),$("#webhookTable").on("click",".delete_button",function(e){var t,o;t=$(this).attr("data-webhook-id"),(o=n.find(function(e){return e.id==t}))&&Swal.fire({title:"Are you sure?",text:"This will delete the webhook '".concat(escapeHtml(o.name),"'"),type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Delete",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1,preConfirm:function(){return new Promise(function(e,n){api.webhookId.delete(t).success(function(t){e()}).error(function(e){n(e.responseJSON.message)})}).catch(function(e){Swal.showValidationMessage(e)})}}).then(function(e){e.value&&Swal.fire("Webhook Deleted!","The webhook has been deleted!","success"),$("button:contains('OK')").on("click",function(){location.reload()})})}),$("#webhookTable").on("click",".ping_button",function(e){var t,a;t=e.currentTarget,a=e.currentTarget.dataset.webhookId,o(),t.disabled=!0,api.webhookId.ping(a).success(function(e){t.disabled=!1,successFlash('Ping of "'.concat(escapeHtml(e.name),'" webhook succeeded.'))}).error(function(e){t.disabled=!1;var o=n.find(function(e){return e.id==a});o&&errorFlash('Ping of "'.concat(escapeHtml(o.name),'" webhook failed: "').concat(e.responseJSON.message,'"'))})})})}]);
|
|
@ -16,13 +16,13 @@ const saveWebhook = (id) => {
|
||||||
is_active: $("#is_active").is(":checked"),
|
is_active: $("#is_active").is(":checked"),
|
||||||
};
|
};
|
||||||
if (id != -1) {
|
if (id != -1) {
|
||||||
wh.id = id;
|
wh.id = parseInt(id);
|
||||||
api.webhookId.put(wh)
|
api.webhookId.put(wh)
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
dismiss();
|
dismiss();
|
||||||
load();
|
load();
|
||||||
$("#modal").modal("hide");
|
$("#modal").modal("hide");
|
||||||
successFlash(`Webhook "${escape(wh.name)}" has been updated successfully!`);
|
successFlash(`Webhook "${escapeHtml(wh.name)}" has been updated successfully!`);
|
||||||
})
|
})
|
||||||
.error(function(data) {
|
.error(function(data) {
|
||||||
modalError(data.responseJSON.message)
|
modalError(data.responseJSON.message)
|
||||||
|
@ -33,7 +33,7 @@ const saveWebhook = (id) => {
|
||||||
load();
|
load();
|
||||||
dismiss();
|
dismiss();
|
||||||
$("#modal").modal("hide");
|
$("#modal").modal("hide");
|
||||||
successFlash(`Webhook "${escape(wh.name)}" has been created successfully!`);
|
successFlash(`Webhook "${escapeHtml(wh.name)}" has been created successfully!`);
|
||||||
})
|
})
|
||||||
.error(function(data) {
|
.error(function(data) {
|
||||||
modalError(data.responseJSON.message)
|
modalError(data.responseJSON.message)
|
||||||
|
@ -108,7 +108,7 @@ const deleteWebhook = (id) => {
|
||||||
}
|
}
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: "Are you sure?",
|
title: "Are you sure?",
|
||||||
text: `This will delete the webhook '${escape(wh.name)}'`,
|
text: `This will delete the webhook '${escapeHtml(wh.name)}'`,
|
||||||
type: "warning",
|
type: "warning",
|
||||||
animation: false,
|
animation: false,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
|
@ -150,7 +150,7 @@ const pingUrl = (btn, whId) => {
|
||||||
api.webhookId.ping(whId)
|
api.webhookId.ping(whId)
|
||||||
.success(function(wh) {
|
.success(function(wh) {
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
successFlash(`Ping of "${escape(wh.name)}" webhook succeeded.`);
|
successFlash(`Ping of "${escapeHtml(wh.name)}" webhook succeeded.`);
|
||||||
})
|
})
|
||||||
.error(function(data) {
|
.error(function(data) {
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
|
@ -158,7 +158,7 @@ const pingUrl = (btn, whId) => {
|
||||||
if (!wh) {
|
if (!wh) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
errorFlash(`Ping of "${escape(wh.name)}" webhook failed: "${data.responseJSON.message}"`)
|
errorFlash(`Ping of "${escapeHtml(wh.name)}" webhook failed: "${data.responseJSON.message}"`)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
13
util/util.go
13
util/util.go
|
@ -138,6 +138,9 @@ func CheckAndCreateSSL(cp string, kp string) error {
|
||||||
log.Infof("Creating new self-signed certificates for administration interface")
|
log.Infof("Creating new self-signed certificates for administration interface")
|
||||||
|
|
||||||
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error generating tls private key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
notBefore := time.Now()
|
notBefore := time.Now()
|
||||||
// Generate a certificate that lasts for 10 years
|
// Generate a certificate that lasts for 10 years
|
||||||
|
@ -147,7 +150,7 @@ func CheckAndCreateSSL(cp string, kp string) error {
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("TLS Certificate Generation: Failed to generate a random serial number: %s", err)
|
return fmt.Errorf("tls certificate generation: failed to generate a random serial number: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
template := x509.Certificate{
|
template := x509.Certificate{
|
||||||
|
@ -165,24 +168,24 @@ func CheckAndCreateSSL(cp string, kp string) error {
|
||||||
|
|
||||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("TLS Certificate Generation: Failed to create certificate: %s", err)
|
return fmt.Errorf("tls certificate generation: failed to create certificate: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
certOut, err := os.Create(cp)
|
certOut, err := os.Create(cp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("TLS Certificate Generation: Failed to open %s for writing: %s", cp, err)
|
return fmt.Errorf("tls certificate generation: failed to open %s for writing: %s", cp, err)
|
||||||
}
|
}
|
||||||
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||||
certOut.Close()
|
certOut.Close()
|
||||||
|
|
||||||
keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("TLS Certificate Generation: Failed to open %s for writing", kp)
|
return fmt.Errorf("tls certificate generation: failed to open %s for writing", kp)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := x509.MarshalECPrivateKey(priv)
|
b, err := x509.MarshalECPrivateKey(priv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("TLS Certificate Generation: Unable to marshal ECDSA private key: %v", err)
|
return fmt.Errorf("tls certificate generation: unable to marshal ECDSA private key: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
|
pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
|
||||||
|
|
|
@ -76,7 +76,15 @@ func (ds defaultSender) Send(endPoint EndPoint, data interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", endPoint.URL, bytes.NewBuffer(jsonData))
|
req, err := http.NewRequest("POST", endPoint.URL, bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
signat, err := sign(endPoint.Secret, jsonData)
|
signat, err := sign(endPoint.Secret, jsonData)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
req.Header.Set(SignatureHeader, fmt.Sprintf("%s=%s", Sha256Prefix, signat))
|
req.Header.Set(SignatureHeader, fmt.Sprintf("%s=%s", Sha256Prefix, signat))
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
resp, err := ds.client.Do(req)
|
resp, err := ds.client.Do(req)
|
||||||
|
|
|
@ -155,11 +155,3 @@ func (w *DefaultWorker) SendTestEmail(s *models.EmailRequest) error {
|
||||||
}()
|
}()
|
||||||
return <-s.ErrorChan
|
return <-s.ErrorChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// errorMail is a helper to handle erroring out a slice of Mail instances
|
|
||||||
// in the case that an unrecoverable error occurs.
|
|
||||||
func errorMail(err error, ms []mailer.Mail) {
|
|
||||||
for _, m := range ms {
|
|
||||||
m.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,9 +15,7 @@ type logMailer struct {
|
||||||
queue chan []mailer.Mail
|
queue chan []mailer.Mail
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *logMailer) Start(ctx context.Context) {
|
func (m *logMailer) Start(ctx context.Context) {}
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *logMailer) Queue(ms []mailer.Mail) {
|
func (m *logMailer) Queue(ms []mailer.Mail) {
|
||||||
m.queue <- ms
|
m.queue <- ms
|
||||||
|
|
Loading…
Reference in a new issue