mirror of
https://github.com/pushbits/server.git
synced 2025-05-14 17:37:01 +02:00
rearange code
This commit is contained in:
parent
6a0c7dc7c9
commit
101db63649
7 changed files with 91 additions and 104 deletions
|
@ -4,13 +4,11 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pushbits/server/internal/api"
|
"github.com/pushbits/server/internal/api"
|
||||||
"github.com/pushbits/server/internal/authentication"
|
"github.com/pushbits/server/internal/authentication"
|
||||||
"github.com/pushbits/server/internal/model"
|
"github.com/pushbits/server/internal/model"
|
||||||
"github.com/pushbits/server/internal/pberrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlertmanagerHandler struct {
|
type AlertmanagerHandler struct {
|
||||||
|
@ -23,25 +21,6 @@ type AlertmanagerHandlerSettings struct {
|
||||||
MessageAnnotation string
|
MessageAnnotation string
|
||||||
}
|
}
|
||||||
|
|
||||||
type hookMessage struct {
|
|
||||||
Version string `json:"version"`
|
|
||||||
GroupKey string `json:"groupKey"`
|
|
||||||
Receiver string `json:"receiver"`
|
|
||||||
GroupLabels map[string]string `json:"groupLabels"`
|
|
||||||
CommonLabels map[string]string `json:"commonLabels"`
|
|
||||||
CommonAnnotations map[string]string `json:"commonAnnotiations"`
|
|
||||||
ExternalURL string `json:"externalURL"`
|
|
||||||
Alerts []alert `json:"alerts"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type alert struct {
|
|
||||||
Labels map[string]string `json:"labels"`
|
|
||||||
Annotiations map[string]string `json:"annotiations"`
|
|
||||||
StartsAt string `json:"startsAt"`
|
|
||||||
EndsAt string `json:"endsAt"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateAlert godoc
|
// CreateAlert godoc
|
||||||
// @Summary Create an Alert
|
// @Summary Create an Alert
|
||||||
// @Description Creates an alert that is send to the channel as a notification. This endpoint is compatible with alertmanager webhooks.
|
// @Description Creates an alert that is send to the channel as a notification. This endpoint is compatible with alertmanager webhooks.
|
||||||
|
@ -50,7 +29,7 @@ type alert struct {
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param token query string true "Channels token, can also be provieded in the header"
|
// @Param token query string true "Channels token, can also be provieded in the header"
|
||||||
// @Param data body hookMessage true "alertmanager webhook call"
|
// @Param data body model.AlertmanagerWebhook true "alertmanager webhook call"
|
||||||
// @Success 200 {object} []model.Notification
|
// @Success 200 {object} []model.Notification
|
||||||
// @Failure 500,404,403 ""
|
// @Failure 500,404,403 ""
|
||||||
// @Router /alert [post]
|
// @Router /alert [post]
|
||||||
|
@ -58,7 +37,7 @@ func (h *AlertmanagerHandler) CreateAlert(ctx *gin.Context) {
|
||||||
application := authentication.GetApplication(ctx)
|
application := authentication.GetApplication(ctx)
|
||||||
log.Printf("Sending alert notification for application %s.", application.Name)
|
log.Printf("Sending alert notification for application %s.", application.Name)
|
||||||
|
|
||||||
var hook hookMessage
|
var hook model.AlertmanagerWebhook
|
||||||
if err := ctx.Bind(&hook); err != nil {
|
if err := ctx.Bind(&hook); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -68,7 +47,7 @@ func (h *AlertmanagerHandler) CreateAlert(ctx *gin.Context) {
|
||||||
notification := alert.ToNotification(h.Settings.TitleAnnotation, h.Settings.MessageAnnotation)
|
notification := alert.ToNotification(h.Settings.TitleAnnotation, h.Settings.MessageAnnotation)
|
||||||
notification.Sanitize(application)
|
notification.Sanitize(application)
|
||||||
messageID, err := h.DP.SendNotification(application, ¬ification)
|
messageID, err := h.DP.SendNotification(application, ¬ification)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := api.SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,62 +57,3 @@ func (h *AlertmanagerHandler) CreateAlert(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusOK, ¬ifications)
|
ctx.JSON(http.StatusOK, ¬ifications)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (alert *alert) ToNotification(titleAnnotation, messageAnnotation string) model.Notification {
|
|
||||||
title := strings.Builder{}
|
|
||||||
message := strings.Builder{}
|
|
||||||
|
|
||||||
switch alert.Status {
|
|
||||||
case "firing":
|
|
||||||
title.WriteString("[FIR] ")
|
|
||||||
case "resolved":
|
|
||||||
title.WriteString("[RES] ")
|
|
||||||
}
|
|
||||||
message.WriteString("STATUS: ")
|
|
||||||
message.WriteString(alert.Status)
|
|
||||||
message.WriteString("\n\n")
|
|
||||||
|
|
||||||
if titleString, ok := alert.Annotiations[titleAnnotation]; ok {
|
|
||||||
title.WriteString(titleString)
|
|
||||||
} else if titleString, ok := alert.Labels[titleAnnotation]; ok {
|
|
||||||
title.WriteString(titleString)
|
|
||||||
} else {
|
|
||||||
title.WriteString("Unknown Title")
|
|
||||||
}
|
|
||||||
|
|
||||||
if messageString, ok := alert.Annotiations[messageAnnotation]; ok {
|
|
||||||
message.WriteString(messageString)
|
|
||||||
} else if messageString, ok := alert.Labels[messageAnnotation]; ok {
|
|
||||||
message.WriteString(messageString)
|
|
||||||
} else {
|
|
||||||
message.WriteString("Unknown Message")
|
|
||||||
}
|
|
||||||
|
|
||||||
message.WriteString("\n")
|
|
||||||
|
|
||||||
for labelName, labelValue := range alert.Labels {
|
|
||||||
message.WriteString("\n")
|
|
||||||
message.WriteString(labelName)
|
|
||||||
message.WriteString(": ")
|
|
||||||
message.WriteString(labelValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
return model.Notification{
|
|
||||||
Message: message.String(),
|
|
||||||
Title: title.String(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func successOrAbort(ctx *gin.Context, code int, err error) bool {
|
|
||||||
if err != nil {
|
|
||||||
// If we know the error force error code
|
|
||||||
switch err {
|
|
||||||
case pberrors.ErrorMessageNotFound:
|
|
||||||
ctx.AbortWithError(http.StatusNotFound, err)
|
|
||||||
default:
|
|
||||||
ctx.AbortWithError(code, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,14 +30,14 @@ func (h *ApplicationHandler) registerApplication(ctx *gin.Context, a *model.Appl
|
||||||
log.L.Printf("Registering application %s.", a.Name)
|
log.L.Printf("Registering application %s.", a.Name)
|
||||||
|
|
||||||
channelID, err := h.DP.RegisterApplication(a.ID, a.Name, a.Token, u.MatrixID)
|
channelID, err := h.DP.RegisterApplication(a.ID, a.Name, a.Token, u.MatrixID)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.MatrixID = channelID
|
a.MatrixID = channelID
|
||||||
|
|
||||||
err = h.DB.UpdateApplication(a)
|
err = h.DB.UpdateApplication(a)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ func (h *ApplicationHandler) createApplication(ctx *gin.Context, u *model.User,
|
||||||
application.UserID = u.ID
|
application.UserID = u.ID
|
||||||
|
|
||||||
err := h.DB.CreateApplication(&application)
|
err := h.DB.CreateApplication(&application)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.registerApplication(ctx, &application, u); err != nil {
|
if err := h.registerApplication(ctx, &application, u); err != nil {
|
||||||
err := h.DB.DeleteApplication(&application)
|
err := h.DB.DeleteApplication(&application)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
log.L.Printf("Cannot delete application with ID %d.", application.ID)
|
log.L.Printf("Cannot delete application with ID %d.", application.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,12 +73,12 @@ func (h *ApplicationHandler) deleteApplication(ctx *gin.Context, a *model.Applic
|
||||||
log.L.Printf("Deleting application %s (ID %d).", a.Name, a.ID)
|
log.L.Printf("Deleting application %s (ID %d).", a.Name, a.ID)
|
||||||
|
|
||||||
err := h.DP.DeregisterApplication(a, u)
|
err := h.DP.DeregisterApplication(a, u)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.DB.DeleteApplication(a)
|
err = h.DB.DeleteApplication(a)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,12 +100,12 @@ func (h *ApplicationHandler) updateApplication(ctx *gin.Context, a *model.Applic
|
||||||
}
|
}
|
||||||
|
|
||||||
err := h.DB.UpdateApplication(a)
|
err := h.DB.UpdateApplication(a)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.DP.UpdateApplication(a)
|
err = h.DP.UpdateApplication(a)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ func (h *ApplicationHandler) GetApplications(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
applications, err := h.DB.GetApplications(user)
|
applications, err := h.DB.GetApplications(user)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ func getApplication(ctx *gin.Context, db Database) (*model.Application, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
application, err := db.GetApplicationByID(id)
|
application, err := db.GetApplicationByID(id)
|
||||||
if success := successOrAbort(ctx, http.StatusNotFound, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusNotFound, err); !success {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ func getUser(ctx *gin.Context, db Database) (*model.User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := db.GetUserByID(id)
|
user, err := db.GetUserByID(id)
|
||||||
if success := successOrAbort(ctx, http.StatusNotFound, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusNotFound, err); !success {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ func (h *UserHandler) requireMultipleAdmins(ctx *gin.Context) error {
|
||||||
|
|
||||||
func (h *UserHandler) deleteApplications(ctx *gin.Context, u *model.User) error {
|
func (h *UserHandler) deleteApplications(ctx *gin.Context, u *model.User) error {
|
||||||
applications, err := h.DB.GetApplications(u)
|
applications, err := h.DB.GetApplications(u)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ func (h *UserHandler) deleteApplications(ctx *gin.Context, u *model.User) error
|
||||||
|
|
||||||
func (h *UserHandler) updateChannels(ctx *gin.Context, u *model.User, matrixID string) error {
|
func (h *UserHandler) updateChannels(ctx *gin.Context, u *model.User, matrixID string) error {
|
||||||
applications, err := h.DB.GetApplications(u)
|
applications, err := h.DB.GetApplications(u)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ func (h *UserHandler) updateChannels(ctx *gin.Context, u *model.User, matrixID s
|
||||||
application := application // See https://stackoverflow.com/a/68247837
|
application := application // See https://stackoverflow.com/a/68247837
|
||||||
|
|
||||||
err := h.DP.DeregisterApplication(&application, u)
|
err := h.DP.DeregisterApplication(&application, u)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ func (h *UserHandler) updateUser(ctx *gin.Context, u *model.User, updateUser mod
|
||||||
}
|
}
|
||||||
if updateUser.Password != nil {
|
if updateUser.Password != nil {
|
||||||
hash, err := h.CM.CreatePasswordHash(*updateUser.Password)
|
hash, err := h.CM.CreatePasswordHash(*updateUser.Password)
|
||||||
if success := successOrAbort(ctx, http.StatusBadRequest, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusBadRequest, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ func (h *UserHandler) updateUser(ctx *gin.Context, u *model.User, updateUser mod
|
||||||
}
|
}
|
||||||
|
|
||||||
err := h.DB.UpdateUser(u)
|
err := h.DB.UpdateUser(u)
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ func (h *UserHandler) CreateUser(ctx *gin.Context) {
|
||||||
|
|
||||||
user, err := h.DB.CreateUser(createUser)
|
user, err := h.DB.CreateUser(createUser)
|
||||||
|
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ func (h *UserHandler) CreateUser(ctx *gin.Context) {
|
||||||
// @Router /user [get]
|
// @Router /user [get]
|
||||||
func (h *UserHandler) GetUsers(ctx *gin.Context) {
|
func (h *UserHandler) GetUsers(ctx *gin.Context) {
|
||||||
users, err := h.DB.GetUsers()
|
users, err := h.DB.GetUsers()
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ func (h *UserHandler) DeleteUser(ctx *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if success := successOrAbort(ctx, http.StatusInternalServerError, h.DB.DeleteUser(user)); !success {
|
if success := SuccessOrAbort(ctx, http.StatusInternalServerError, h.DB.DeleteUser(user)); !success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func successOrAbort(ctx *gin.Context, code int, err error) bool {
|
func SuccessOrAbort(ctx *gin.Context, code int, err error) bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If we know the error force error code
|
// If we know the error force error code
|
||||||
switch err {
|
switch err {
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestApi_SuccessOrAbort(t *testing.T) {
|
||||||
w, c, err := testCase.GetRequest()
|
w, c, err := testCase.GetRequest()
|
||||||
require.NoErrorf(err, "(Test case %s) Could not make request", testCase.Name)
|
require.NoErrorf(err, "(Test case %s) Could not make request", testCase.Name)
|
||||||
|
|
||||||
aborted := successOrAbort(c, testCase.ShouldStatus, forcedErr)
|
aborted := SuccessOrAbort(c, testCase.ShouldStatus, forcedErr)
|
||||||
|
|
||||||
if forcedErr != nil {
|
if forcedErr != nil {
|
||||||
assert.Equalf(testCase.ShouldStatus, w.Code, "(Test case %s) Expected status code %d but have %d", testCase.Name, testCase.ShouldStatus, w.Code)
|
assert.Equalf(testCase.ShouldStatus, w.Code, "(Test case %s) Expected status code %d but have %d", testCase.Name, testCase.ShouldStatus, w.Code)
|
||||||
|
|
67
internal/model/alertmanager.go
Normal file
67
internal/model/alertmanager.go
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type AlertmanagerWebhook struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
GroupKey string `json:"groupKey"`
|
||||||
|
Receiver string `json:"receiver"`
|
||||||
|
GroupLabels map[string]string `json:"groupLabels"`
|
||||||
|
CommonLabels map[string]string `json:"commonLabels"`
|
||||||
|
CommonAnnotations map[string]string `json:"commonAnnotiations"`
|
||||||
|
ExternalURL string `json:"externalURL"`
|
||||||
|
Alerts []AlertmanagerAlert `json:"alerts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlertmanagerAlert struct {
|
||||||
|
Labels map[string]string `json:"labels"`
|
||||||
|
Annotiations map[string]string `json:"annotiations"`
|
||||||
|
StartsAt string `json:"startsAt"`
|
||||||
|
EndsAt string `json:"endsAt"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alert *AlertmanagerAlert) ToNotification(titleAnnotation, messageAnnotation string) Notification {
|
||||||
|
title := strings.Builder{}
|
||||||
|
message := strings.Builder{}
|
||||||
|
|
||||||
|
switch alert.Status {
|
||||||
|
case "firing":
|
||||||
|
title.WriteString("[FIR] ")
|
||||||
|
case "resolved":
|
||||||
|
title.WriteString("[RES] ")
|
||||||
|
}
|
||||||
|
message.WriteString("STATUS: ")
|
||||||
|
message.WriteString(alert.Status)
|
||||||
|
message.WriteString("\n\n")
|
||||||
|
|
||||||
|
if titleString, ok := alert.Annotiations[titleAnnotation]; ok {
|
||||||
|
title.WriteString(titleString)
|
||||||
|
} else if titleString, ok := alert.Labels[titleAnnotation]; ok {
|
||||||
|
title.WriteString(titleString)
|
||||||
|
} else {
|
||||||
|
title.WriteString("Unknown Title")
|
||||||
|
}
|
||||||
|
|
||||||
|
if messageString, ok := alert.Annotiations[messageAnnotation]; ok {
|
||||||
|
message.WriteString(messageString)
|
||||||
|
} else if messageString, ok := alert.Labels[messageAnnotation]; ok {
|
||||||
|
message.WriteString(messageString)
|
||||||
|
} else {
|
||||||
|
message.WriteString("Unknown Message")
|
||||||
|
}
|
||||||
|
|
||||||
|
message.WriteString("\n")
|
||||||
|
|
||||||
|
for labelName, labelValue := range alert.Labels {
|
||||||
|
message.WriteString("\n")
|
||||||
|
message.WriteString(labelName)
|
||||||
|
message.WriteString(": ")
|
||||||
|
message.WriteString(labelValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Notification{
|
||||||
|
Message: message.String(),
|
||||||
|
Title: title.String(),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue