diff --git a/server/api/notification.go b/server/api/notification.go index 6a347a6e..5e9ebe86 100644 --- a/server/api/notification.go +++ b/server/api/notification.go @@ -3,20 +3,69 @@ package api import ( "encoding/json" "net/http" + "unicode/utf8" "github.com/smarthome-go/smarthome/core/database" "github.com/smarthome-go/smarthome/core/homescript" "github.com/smarthome-go/smarthome/server/middleware" ) +type NotifyRequest struct { + Priority uint8 `json:"priority"` // Includes 1: info, 2: warning, 3: alert + Name string `json:"name"` + Description string `json:"description"` +} + type NotificationCountResponse struct { NotificationCount uint16 `json:"count"` } -type DeleteNotificationByIdRequest struct { +type NotificationIdBody struct { Id uint `json:"id"` } +func NotifyUser(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + username, err := middleware.GetUserFromCurrentSession(w, r) + if err != nil { + return + } + + var request NotifyRequest + + decoder := json.NewDecoder(r.Body) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&request); err != nil { + w.WriteHeader(http.StatusBadRequest) + Res(w, Response{Success: false, Message: "bad request", Error: "invalid request body"}) + return + } + + if request.Priority < 1 || request.Priority > 3 { + w.WriteHeader(http.StatusUnprocessableEntity) + Res(w, Response{Success: false, Message: "illegal request body", Error: "priority must be 1 <= p <= 3"}) + return + } + + if utf8.RuneCountInString(request.Name) > 100 { + w.WriteHeader(http.StatusUnprocessableEntity) + Res(w, Response{Success: false, Message: "illegal request body", Error: "name must no be longer than 100 characters"}) + return + } + + newId, err := homescript.Notify( + username, + request.Name, + request.Description, + homescript.NotificationLevel(request.Priority), + true, + ) + + if err := json.NewEncoder(w).Encode(NotificationIdBody{Id: newId}); err != nil { + Res(w, Response{Success: false, Message: "failed to add notification", Error: "could not encode response"}) + } +} + // Returns a uin16 that indicates the number of notifications the current user has, no authentication required func GetNotificationCount(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -31,7 +80,6 @@ func GetNotificationCount(w http.ResponseWriter, r *http.Request) { return } if err := json.NewEncoder(w).Encode(NotificationCountResponse{NotificationCount: notificationCount}); err != nil { - log.Error(err.Error()) Res(w, Response{Success: false, Message: "failed to get notification count", Error: "could not encode response"}) } } @@ -60,7 +108,7 @@ func DeleteUserNotificationById(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") decoder := json.NewDecoder(r.Body) decoder.DisallowUnknownFields() - var request DeleteNotificationByIdRequest + var request NotificationIdBody if err := decoder.Decode(&request); err != nil { w.WriteHeader(http.StatusBadRequest) Res(w, Response{Success: false, Message: "bad request", Error: "invalid request body"}) diff --git a/server/routes/routes.go b/server/routes/routes.go index 1ab9e91e..2b08b7b0 100644 --- a/server/routes/routes.go +++ b/server/routes/routes.go @@ -145,6 +145,7 @@ func NewRouter() *mux.Router { r.HandleFunc("/api/user/token/list/personal", mdl.ApiAuth(api.ListUserTokens)).Methods("GET") // Notifications + r.HandleFunc("/api/user/notification/notify", mdl.ApiAuth(api.NotifyUser)).Methods("POST") r.HandleFunc("/api/user/notification/count", mdl.ApiAuth(api.GetNotificationCount)).Methods("GET") r.HandleFunc("/api/user/notification/delete", mdl.ApiAuth(api.DeleteUserNotificationById)).Methods("DELETE") r.HandleFunc("/api/user/notification/delete/all", mdl.ApiAuth(api.DeleteAllUserNotifications)).Methods("DELETE")