From a83492d7ab2b37f01a482ad9152f7fe3f01d1780 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 4 Jul 2023 10:18:36 +0200 Subject: [PATCH] allow deleting global evs Signed-off-by: jkoberg --- services/userlog/pkg/service/conversion.go | 4 +- services/userlog/pkg/service/globalevents.go | 2 + services/userlog/pkg/service/http.go | 52 ++++++++++---------- services/userlog/pkg/service/service.go | 41 ++++++++++----- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/services/userlog/pkg/service/conversion.go b/services/userlog/pkg/service/conversion.go index 266e65e0b1..df472094a8 100644 --- a/services/userlog/pkg/service/conversion.go +++ b/services/userlog/pkg/service/conversion.go @@ -129,7 +129,7 @@ func (c *Converter) ConvertGlobalEvent(typ string, data json.RawMessage) (OC10No return OC10Notification{}, err } - return c.deprovisionMessage(PlatformDeprovision, dd.DeprovisionDate) + return c.deprovisionMessage(PlatformDeprovision, dd.DeprovisionDate.Format(dd.DeprovisionFormat)) } } @@ -305,7 +305,7 @@ func (c *Converter) policiesMessage(eventid string, nt NotificationTemplate, exe }, nil } -func (c *Converter) deprovisionMessage(nt NotificationTemplate, deproDate time.Time) (OC10Notification, error) { +func (c *Converter) deprovisionMessage(nt NotificationTemplate, deproDate string) (OC10Notification, error) { subj, subjraw, msg, msgraw, err := composeMessage(nt, c.locale, c.translationPath, map[string]interface{}{ "date": deproDate, }) diff --git a/services/userlog/pkg/service/globalevents.go b/services/userlog/pkg/service/globalevents.go index 2f7369d1b4..b1ba5e568b 100644 --- a/services/userlog/pkg/service/globalevents.go +++ b/services/userlog/pkg/service/globalevents.go @@ -10,6 +10,8 @@ var ( type DeprovisionData struct { // The deprovision date DeprovisionDate time.Time `json:"deprovision_date"` + // The Format of the deprvision date + DeprovisionFormat string // The user who stored the deprovision message Deprovisioner string } diff --git a/services/userlog/pkg/service/http.go b/services/userlog/pkg/service/http.go index 2cc4e6cb60..6d42bab474 100644 --- a/services/userlog/pkg/service/http.go +++ b/services/userlog/pkg/service/http.go @@ -110,22 +110,8 @@ func (ul *UserlogService) HandleSSE(w http.ResponseWriter, r *http.Request) { ul.sse.ServeHTTP(w, r) } -// HandlePostEvent is the POST handler for events -func (ul *UserlogService) HandlePostEvent(w http.ResponseWriter, r *http.Request) { - u, ok := ctx.ContextGetUser(r.Context()) - if !ok { - ul.log.Error().Msg("post: no user in context") - w.WriteHeader(http.StatusInternalServerError) - return - } - - uid := u.GetId().GetOpaqueId() - if uid == "" { - ul.log.Error().Msg("post: user in context is broken") - w.WriteHeader(http.StatusInternalServerError) - return - } - +// HandlePostGlobaelEvent is the POST handler for global events +func (ul *UserlogService) HandlePostGlobalEvent(w http.ResponseWriter, r *http.Request) { var req PostEventsRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { ul.log.Error().Err(err).Int("returned statuscode", http.StatusBadRequest).Msg("request body is malformed") @@ -142,6 +128,24 @@ func (ul *UserlogService) HandlePostEvent(w http.ResponseWriter, r *http.Request w.WriteHeader(http.StatusOK) } +// HandleDeleteGlobalEvent is the DELETE handler for global events +func (ul *UserlogService) HandleDeleteGlobalEvent(w http.ResponseWriter, r *http.Request) { + var req DeleteEventsRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + ul.log.Error().Err(err).Int("returned statuscode", http.StatusBadRequest).Msg("request body is malformed") + w.WriteHeader(http.StatusBadRequest) + return + } + + if err := ul.DeleteGlobalEvents(req.IDs); err != nil { + ul.log.Error().Err(err).Int("returned statuscode", http.StatusInternalServerError).Msg("delete events failed") + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} + // HandleDeleteEvents is the DELETE handler for events func (ul *UserlogService) HandleDeleteEvents(w http.ResponseWriter, r *http.Request) { u, ok := revactx.ContextGetUser(r.Context()) @@ -197,12 +201,9 @@ func RequireAdmin(rm *roles.Manager, logger log.Logger) func(next http.HandlerFu return func(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { u, ok := revactx.ContextGetUser(r.Context()) - if !ok { - errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized") - return - } - if u.Id == nil || u.Id.OpaqueId == "" { - errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "user is missing an id") + if !ok || u.GetId().GetOpaqueId() == "" { + logger.Error().Str("userid", u.Id.OpaqueId).Msg("user not in context") + errorcode.AccessDenied.Render(w, r, http.StatusInternalServerError, "") return } // get roles from context @@ -213,11 +214,12 @@ func RequireAdmin(rm *roles.Manager, logger log.Logger) func(next http.HandlerFu roleIDs, err = rm.FindRoleIDsForUser(r.Context(), u.Id.OpaqueId) if err != nil { logger.Err(err).Str("userid", u.Id.OpaqueId).Msg("failed to get roles for user") - errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized") + errorcode.AccessDenied.Render(w, r, http.StatusInternalServerError, "") return } if len(roleIDs) == 0 { - errorcode.AccessDenied.Render(w, r, http.StatusUnauthorized, "Unauthorized") + logger.Err(err).Str("userid", u.Id.OpaqueId).Msg("user has no roles") + errorcode.AccessDenied.Render(w, r, http.StatusInternalServerError, "") return } } @@ -228,7 +230,7 @@ func RequireAdmin(rm *roles.Manager, logger log.Logger) func(next http.HandlerFu return } - errorcode.AccessDenied.Render(w, r, http.StatusForbidden, "Forbidden") + errorcode.AccessDenied.Render(w, r, http.StatusNotFound, "Forbidden") } } } diff --git a/services/userlog/pkg/service/service.go b/services/userlog/pkg/service/service.go index 2ab8396371..cb97beef53 100644 --- a/services/userlog/pkg/service/service.go +++ b/services/userlog/pkg/service/service.go @@ -90,8 +90,9 @@ func NewUserlogService(opts ...Option) (*UserlogService, error) { ul.m.Route("/ocs/v2.php/apps/notifications/api/v1/notifications", func(r chi.Router) { r.Get("/", ul.HandleGetEvents) - r.Post("/", RequireAdmin(&m, ul.log)(ul.HandlePostEvent)) r.Delete("/", ul.HandleDeleteEvents) + r.Post("/global", RequireAdmin(&m, ul.log)(ul.HandlePostGlobalEvent)) + r.Delete("/global", RequireAdmin(&m, ul.log)(ul.HandleDeleteGlobalEvent)) if !ul.cfg.DisableSSE { r.Get("/sse", ul.HandleSSE) @@ -266,11 +267,22 @@ func (ul *UserlogService) StoreGlobalEvent(typ string, data map[string]string) e return fmt.Errorf("cannot parse time to format. time: '%s' format: '%s'", dps, format) } - return ul.storeGlobalEvent(typ, DeprovisionData{ - DeprovisionDate: date, - }) + ev := DeprovisionData{ + DeprovisionDate: date, + DeprovisionFormat: format, + } + b, err := json.Marshal(ev) + if err != nil { + return err + } + + return ul.alterGlobalEvents(func(evs map[string]json.RawMessage) error { + evs[typ] = b + return nil + }) } + } // GetGlobalEvents will return all global events @@ -291,6 +303,16 @@ func (ul *UserlogService) GetGlobalEvents() (map[string]json.RawMessage, error) return out, nil } +// DeleteGlobalEvents will delete the specified event +func (ul *UserlogService) DeleteGlobalEvents(evnames []string) error { + return ul.alterGlobalEvents(func(evs map[string]json.RawMessage) error { + for _, name := range evnames { + delete(evs, name) + } + return nil + }) +} + func (ul *UserlogService) addEventToUser(userid string, event events.Event) error { if !ul.cfg.DisableSSE { if err := ul.sendSSE(userid, event); err != nil { @@ -368,18 +390,15 @@ func (ul *UserlogService) alterUserEventList(userid string, alter func([]string) }) } -func (ul *UserlogService) storeGlobalEvent(typ string, ev interface{}) error { - b, err := json.Marshal(ev) - if err != nil { - return err - } - +func (ul *UserlogService) alterGlobalEvents(alter func(map[string]json.RawMessage) error) error { evs, err := ul.GetGlobalEvents() if err != nil && err != store.ErrNotFound { return err } - evs[typ] = b + if err := alter(evs); err != nil { + return err + } val, err := json.Marshal(evs) if err != nil {