diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go index d59c6d97583..d697fa3a2aa 100644 --- a/pkg/api/annotations.go +++ b/pkg/api/annotations.go @@ -351,6 +351,26 @@ func (hs *HTTPServer) MassDeleteAnnotations(c *models.ReqContext) response.Respo return response.Success("Annotations deleted") } +func (hs *HTTPServer) GetAnnotationByID(c *models.ReqContext) response.Response { + annotationID, err := strconv.ParseInt(web.Params(c.Req)[":annotationId"], 10, 64) + if err != nil { + return response.Error(http.StatusBadRequest, "annotationId is invalid", err) + } + + repo := annotations.GetRepository() + + annotation, resp := findAnnotationByID(c.Req.Context(), repo, annotationID, c.SignedInUser) + if resp != nil { + return resp + } + + if annotation.Email != "" { + annotation.AvatarUrl = dtos.GetGravatarUrl(annotation.Email) + } + + return response.JSON(200, annotation) +} + func (hs *HTTPServer) DeleteAnnotationByID(c *models.ReqContext) response.Response { annotationID, err := strconv.ParseInt(web.Params(c.Req)[":annotationId"], 10, 64) if err != nil { diff --git a/pkg/api/annotations_test.go b/pkg/api/annotations_test.go index 32e1e817e6e..74f4659c616 100644 --- a/pkg/api/annotations_test.go +++ b/pkg/api/annotations_test.go @@ -512,6 +512,24 @@ func TestAPI_Annotations_AccessControl(t *testing.T) { }, want: http.StatusForbidden, }, + { + name: "AccessControl getting annotation by ID with correct permissions is allowed", + args: args{ + permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionAnnotationsRead, Scope: accesscontrol.ScopeAnnotationsAll}}, + url: "/api/annotations/1", + method: http.MethodGet, + }, + want: http.StatusOK, + }, + { + name: "AccessControl getting annotation by ID without permissions is forbidden", + args: args{ + permissions: []*accesscontrol.Permission{}, + url: "/api/annotations", + method: http.MethodGet, + }, + want: http.StatusForbidden, + }, { name: "AccessControl getting tags for annotations with correct permissions is allowed", args: args{ diff --git a/pkg/api/api.go b/pkg/api/api.go index 2931c9027de..18f25c9d479 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -475,6 +475,7 @@ func (hs *HTTPServer) registerRoutes() { apiRoute.Group("/annotations", func(annotationsRoute routing.RouteRegister) { annotationsRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsCreate)), routing.Wrap(hs.PostAnnotation)) + annotationsRoute.Get("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsRead, ac.ScopeAnnotationsID)), routing.Wrap(hs.GetAnnotationByID)) annotationsRoute.Delete("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsDelete, ac.ScopeAnnotationsID)), routing.Wrap(hs.DeleteAnnotationByID)) annotationsRoute.Put("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsWrite, ac.ScopeAnnotationsID)), routing.Wrap(hs.UpdateAnnotation)) annotationsRoute.Patch("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsWrite, ac.ScopeAnnotationsID)), routing.Wrap(hs.PatchAnnotation)) diff --git a/pkg/api/docs/definitions/annotations.go b/pkg/api/docs/definitions/annotations.go index 6493a77e8ee..019a02acd52 100644 --- a/pkg/api/docs/definitions/annotations.go +++ b/pkg/api/docs/definitions/annotations.go @@ -16,6 +16,15 @@ import ( // 401: unauthorisedError // 500: internalServerError +// swagger:route GET /annotations/{annotation_id} annotations getAnnotation +// +// Get Annotation by Id. +// +// Responses: +// 200: getAnnotationResponse +// 401: unauthorisedError +// 500: internalServerError + // swagger:route POST /annotations/mass-delete annotations massDeleteAnnotations // // Delete multiple annotations. @@ -216,6 +225,13 @@ type GetAnnotationsResponse struct { Body []*annotations.ItemDTO `json:"body"` } +// swagger:response getAnnotationResponse +type GetAnnotationResponse struct { + // The response message + // in: body + Body *annotations.ItemDTO `json:"body"` +} + // swagger:response createAnnotationResponse type CreateAnnotationResponse struct { // The response message