diff --git a/internal/api/context.go b/internal/api/context.go index c408515..90a5ec8 100644 --- a/internal/api/context.go +++ b/internal/api/context.go @@ -20,6 +20,17 @@ func getID(ctx *gin.Context) (uint, error) { return id, nil } +func getMessageID(ctx *gin.Context) (string, error) { + id, ok := ctx.MustGet("messageid").(string) + if !ok { + err := errors.New("an error occured while retrieving messageID from context") + ctx.AbortWithError(http.StatusInternalServerError, err) + return "", err + } + + return id, nil +} + func getApplication(ctx *gin.Context, db Database) (*model.Application, error) { id, err := getID(ctx) if err != nil { diff --git a/internal/api/middleware.go b/internal/api/middleware.go index a6507e1..3d84840 100644 --- a/internal/api/middleware.go +++ b/internal/api/middleware.go @@ -8,6 +8,10 @@ type idInURI struct { ID uint `uri:"id" binding:"required"` } +type messageIdInURI struct { + MessageID string `uri:"messageid" binding:"required"` +} + // RequireIDInURI returns a Gin middleware which requires an ID to be supplied in the URI of the request. func RequireIDInURI() gin.HandlerFunc { return func(ctx *gin.Context) { @@ -20,3 +24,16 @@ func RequireIDInURI() gin.HandlerFunc { ctx.Set("id", requestModel.ID) } } + +// RequireMessageIDInURI returns a Gin middleware which requires an messageID to be supplied in the URI of the request. +func RequireMessageIDInURI() gin.HandlerFunc { + return func(ctx *gin.Context) { + var requestModel messageIdInURI + + if err := ctx.BindUri(&requestModel); err != nil { + return + } + + ctx.Set("messageid", requestModel.MessageID) + } +} diff --git a/internal/api/notification.go b/internal/api/notification.go index b4a2100..9cd51d0 100644 --- a/internal/api/notification.go +++ b/internal/api/notification.go @@ -18,8 +18,8 @@ type NotificationDatabase interface { // The NotificationDispatcher interface for relaying notifications. type NotificationDispatcher interface { - SendNotification(a *model.Application, n *model.Notification) error - SendDeleteNotification(a *model.Application, n *model.DeleteNotification) error + SendNotification(a *model.Application, n *model.Notification) (id string, err error) + DeleteNotification(a *model.Application, n *model.DeleteNotification) error } // NotificationHandler holds information for processing requests about notifications. @@ -39,24 +39,36 @@ func (h *NotificationHandler) CreateNotification(ctx *gin.Context) { application := authentication.GetApplication(ctx) log.Printf("Sending notification for application %s.", application.Name) - notification.ID = 0 notification.ApplicationID = application.ID if strings.TrimSpace(notification.Title) == "" { notification.Title = application.Name } notification.Date = time.Now() - if success := successOrAbort(ctx, http.StatusInternalServerError, h.DP.SendNotification(application, ¬ification)); !success { + messageID, err := h.DP.SendNotification(application, ¬ification) + + if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success { return } + notification.ID = messageID + ctx.JSON(http.StatusOK, ¬ification) } +// DeleteNotification is used to delete (or mark as deleted) a notification for a user func (h *NotificationHandler) DeleteNotification(ctx *gin.Context) { application := authentication.GetApplication(ctx) + id, err := getMessageID(ctx) - n := model.DeleteNotification{} + if success := successOrAbort(ctx, http.StatusUnprocessableEntity, err); !success { + return + } - h.DP.SendDeleteNotification(application, &n) + n := model.DeleteNotification{ + ID: id, + Date: time.Now(), + } + + h.DP.DeleteNotification(application, &n) } diff --git a/internal/dispatcher/notification.go b/internal/dispatcher/notification.go index 0eb15c3..edc9c97 100644 --- a/internal/dispatcher/notification.go +++ b/internal/dispatcher/notification.go @@ -1,7 +1,6 @@ package dispatcher import ( - "encoding/json" "fmt" "html" "log" @@ -11,7 +10,7 @@ import ( "github.com/pushbits/server/internal/model" ) -type ExampleEvent struct { +type ReplyEvent struct { Body string `json:"body"` Msgtype string `json:"msgtype"` RelatesTo RelatesTo `json:"m.relates_to,omitempty"` @@ -22,7 +21,7 @@ type RelatesTo struct { } // SendNotification sends a notification to the specified user. -func (d *Dispatcher) SendNotification(a *model.Application, n *model.Notification) error { +func (d *Dispatcher) SendNotification(a *model.Application, n *model.Notification) (id string, err error) { log.Printf("Sending notification to room %s.", a.MatrixID) plainMessage := strings.TrimSpace(n.Message) @@ -33,41 +32,37 @@ func (d *Dispatcher) SendNotification(a *model.Application, n *model.Notificatio text := fmt.Sprintf("%s\n\n%s", plainTitle, plainMessage) formattedText := fmt.Sprintf("%s %s", title, message) - _, err := d.client.SendFormattedText(a.MatrixID, text, formattedText) + respSendEvent, err := d.client.SendFormattedText(a.MatrixID, text, formattedText) - return err + return respSendEvent.EventID, err } -func (d *Dispatcher) SendDeleteNotification(a *model.Application, n *model.DeleteNotification) error { +// DeleteNotification sends a notification to the specified user that another notificaion is deleted +func (d *Dispatcher) DeleteNotification(a *model.Application, n *model.DeleteNotification) error { log.Printf("Sending delete notification to room %s", a.MatrixID) - event := ExampleEvent{ - Body: "Testmessage", + event := ReplyEvent{ + Body: "This message got deleted.", Msgtype: "m.text", } irt := make(map[string]string) - - irt["event_id"] = "$uf5OLKPaefHTZhc2lxSIY7If7pLFcNHcMZLbMfS-7qw" - + irt["event_id"] = n.ID rt := RelatesTo{ InReplyTo: irt, } - event.RelatesTo = rt _, err := d.client.SendMessageEvent(a.MatrixID, "m.room.message", event) - if err != nil { - log.Println(err) - } + return err - messages, _ := d.client.Messages(a.MatrixID, "", "", 'b', 10) + /* + messages, _ := d.client.Messages(a.MatrixID, "", "", 'b', 10) - js, _ := json.Marshal(messages) + js, _ := json.Marshal(messages) - log.Println(string(js)) - - return nil + log.Println(string(js)) + */ } // HTML-formats the title diff --git a/internal/model/notification.go b/internal/model/notification.go index 0b229cf..7bb64b7 100644 --- a/internal/model/notification.go +++ b/internal/model/notification.go @@ -6,7 +6,7 @@ import ( // Notification holds information like the message, the title, and the priority of a notification. type Notification struct { - ID uint `json:"id"` + ID string `json:"id"` ApplicationID uint `json:"appid"` Message string `json:"message" form:"message" query:"message" binding:"required"` Title string `json:"title" form:"title" query:"title"` @@ -17,11 +17,6 @@ type Notification struct { // DeleteNotification holds information like the message, the reply to message id and the priority of a deletion notification. type DeleteNotification struct { - ID uint `json:"id"` - DeleteID uint `json:"deleteid"` - ApplicationID uint `json:"appid"` - Message string `json:"message" form:"message" query:"message" binding:"required"` - Priority int `json:"priority" form:"priority" query:"priority"` - Extras map[string]interface{} `json:"extras,omitempty" form:"-" query:"-"` - Date time.Time `json:"date"` + ID string `json:"id" form:"id"` + Date time.Time `json:"date"` } diff --git a/internal/router/router.go b/internal/router/router.go index 9dd5e87..1debc4a 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -46,6 +46,7 @@ func Create(debug bool, cm *credentials.Manager, db *database.Database, dp *disp r.GET("/health", healthHandler.Health) r.POST("/message", auth.RequireApplicationToken(), notificationHandler.CreateNotification) + r.DELETE("/message/:messageid", api.RequireIDInURI(), auth.RequireApplicationToken(), notificationHandler.DeleteNotification) r.GET("/test", auth.RequireApplicationToken(), notificationHandler.DeleteNotification)