diff --git a/services/graph/pkg/service/v0/teamwork.go b/services/graph/pkg/service/v0/teamwork.go index 36d22a3fbf..de0590ccde 100644 --- a/services/graph/pkg/service/v0/teamwork.go +++ b/services/graph/pkg/service/v0/teamwork.go @@ -116,8 +116,11 @@ func (g Graph) SendActivityNotification(w http.ResponseWriter, r *http.Request) errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, "item not found") return case statResponse.GetStatus().GetCode() != rpc.Code_CODE_OK: - g.logger.Error().Str("code", statResponse.GetStatus().GetCode().String()).Msg("could not stat item") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not stat item") + g.logger.Error(). + Str("code", statResponse.GetStatus().GetCode().String()). + Str("message", statResponse.GetStatus().GetMessage()). + Msg("could not stat item") + errorcode.RenderError(w, r, errorcode.FromCS3Status(statResponse.GetStatus(), nil)) return } @@ -136,8 +139,12 @@ func (g Graph) SendActivityNotification(w http.ResponseWriter, r *http.Request) errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, "recipient not found") return case authResponse.GetStatus().GetCode() != rpc.Code_CODE_OK: - g.logger.Error().Str("userID", userID).Str("code", authResponse.GetStatus().GetCode().String()).Msg("could not authenticate the recipient") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not authenticate the recipient") + g.logger.Error(). + Str("userID", userID). + Str("code", authResponse.GetStatus().GetCode().String()). + Str("message", authResponse.GetStatus().GetMessage()). + Msg("could not authenticate the recipient") + errorcode.RenderError(w, r, errorcode.FromCS3Status(authResponse.GetStatus(), nil)) return } @@ -156,8 +163,12 @@ func (g Graph) SendActivityNotification(w http.ResponseWriter, r *http.Request) w.WriteHeader(http.StatusAccepted) return case recipientStat.GetStatus().GetCode() != rpc.Code_CODE_OK: - g.logger.Error().Str("userID", userID).Str("code", recipientStat.GetStatus().GetCode().String()).Msg("could not stat the item as the recipient") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not stat item") + g.logger.Error(). + Str("userID", userID). + Str("code", recipientStat.GetStatus().GetCode().String()). + Str("message", recipientStat.GetStatus().GetMessage()). + Msg("could not stat the item as the recipient") + errorcode.RenderError(w, r, errorcode.FromCS3Status(recipientStat.GetStatus(), nil)) return } diff --git a/services/graph/pkg/service/v0/teamwork_test.go b/services/graph/pkg/service/v0/teamwork_test.go index 5d5b80f2fa..6dc9e4f133 100644 --- a/services/graph/pkg/service/v0/teamwork_test.go +++ b/services/graph/pkg/service/v0/teamwork_test.go @@ -134,6 +134,8 @@ var _ = Describe("SendActivityNotification", func() { return &gateway.AuthenticateResponse{Status: status.NewNotFound(context.Background(), "not found")} case "broken": return &gateway.AuthenticateResponse{Status: status.NewInternal(context.Background(), "auth failed")} + case "denied": + return &gateway.AuthenticateResponse{Status: status.NewPermissionDenied(context.Background(), nil, "permission denied")} } return &gateway.AuthenticateResponse{ @@ -232,6 +234,19 @@ var _ = Describe("SendActivityNotification", func() { Expect(mentions()).To(BeEmpty()) }) + // anything the caller stat answers beyond that is whatever the cs3 status maps to + It("carries the cs3 status of a failed caller stat", func() { + statWith(func(ctx context.Context, _ string) *rpc.Status { + return status.NewInvalidArg(ctx, "invalid reference") + }) + + rr := httptest.NewRecorder() + svc.SendActivityNotification(rr, request("alice", mention)) + + Expect(rr.Code).To(Equal(http.StatusBadRequest)) + Expect(mentions()).To(BeEmpty()) + }) + // a recipient without access looks like success, so the sender cannot probe who has it It("silently drops a mention for a recipient who cannot see the item", func() { statAs("") @@ -276,6 +291,22 @@ var _ = Describe("SendActivityNotification", func() { Expect(mentions()).To(BeEmpty()) }) + It("carries the cs3 status of a failed recipient stat", func() { + statWith(func(ctx context.Context, token string) *rpc.Status { + if token == "alice-token" { + return status.NewLocked(ctx, "locked") + } + + return status.NewOK(ctx) + }) + + rr := httptest.NewRecorder() + svc.SendActivityNotification(rr, request("alice", mention)) + + Expect(rr.Code).To(Equal(http.StatusLocked)) + Expect(mentions()).To(BeEmpty()) + }) + // a user id is no secret, other endpoints look users up as well It("refuses a recipient that does not exist", func() { statAs("", "alice-token") @@ -297,6 +328,17 @@ var _ = Describe("SendActivityNotification", func() { Expect(mentions()).To(BeEmpty()) }) + // a rejected machine auth is a server side misconfiguration, the status decides what it looks like + It("carries the cs3 status of a rejected machine auth", func() { + statAs("") + + rr := httptest.NewRecorder() + svc.SendActivityNotification(rr, request("denied", mention)) + + Expect(rr.Code).To(Equal(http.StatusForbidden)) + Expect(mentions()).To(BeEmpty()) + }) + DescribeTable("rejects a malformed body", func(body string) { statAs("", "alice-token")