| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- package api
- import (
- "strings"
- "github.com/grafana/grafana/pkg/api/dtos"
- m "github.com/grafana/grafana/pkg/models"
- "github.com/grafana/grafana/pkg/services/annotations"
- "github.com/grafana/grafana/pkg/services/guardian"
- "github.com/grafana/grafana/pkg/util"
- )
- func GetAnnotations(c *m.ReqContext) Response {
- query := &annotations.ItemQuery{
- From: c.QueryInt64("from"),
- To: c.QueryInt64("to"),
- OrgId: c.OrgId,
- UserId: c.QueryInt64("userId"),
- AlertId: c.QueryInt64("alertId"),
- DashboardId: c.QueryInt64("dashboardId"),
- PanelId: c.QueryInt64("panelId"),
- Limit: c.QueryInt64("limit"),
- Tags: c.QueryStrings("tags"),
- Type: c.Query("type"),
- MatchAny: c.QueryBool("matchAny"),
- }
- repo := annotations.GetRepository()
- items, err := repo.Find(query)
- if err != nil {
- return Error(500, "Failed to get annotations", err)
- }
- for _, item := range items {
- if item.Email != "" {
- item.AvatarUrl = dtos.GetGravatarUrl(item.Email)
- }
- }
- return JSON(200, items)
- }
- type CreateAnnotationError struct {
- message string
- }
- func (e *CreateAnnotationError) Error() string {
- return e.message
- }
- func PostAnnotation(c *m.ReqContext, cmd dtos.PostAnnotationsCmd) Response {
- if canSave, err := canSaveByDashboardID(c, cmd.DashboardId); err != nil || !canSave {
- return dashboardGuardianResponse(err)
- }
- repo := annotations.GetRepository()
- if cmd.Text == "" {
- err := &CreateAnnotationError{"text field should not be empty"}
- return Error(500, "Failed to save annotation", err)
- }
- item := annotations.Item{
- OrgId: c.OrgId,
- UserId: c.UserId,
- DashboardId: cmd.DashboardId,
- PanelId: cmd.PanelId,
- Epoch: cmd.Time,
- EpochEnd: cmd.TimeEnd,
- Text: cmd.Text,
- Data: cmd.Data,
- Tags: cmd.Tags,
- }
- if err := repo.Save(&item); err != nil {
- return Error(500, "Failed to save annotation", err)
- }
- startID := item.Id
- return JSON(200, util.DynMap{
- "message": "Annotation added",
- "id": startID,
- })
- }
- func formatGraphiteAnnotation(what string, data string) string {
- text := what
- if data != "" {
- text = text + "\n" + data
- }
- return text
- }
- func PostGraphiteAnnotation(c *m.ReqContext, cmd dtos.PostGraphiteAnnotationsCmd) Response {
- repo := annotations.GetRepository()
- if cmd.What == "" {
- err := &CreateAnnotationError{"what field should not be empty"}
- return Error(500, "Failed to save Graphite annotation", err)
- }
- text := formatGraphiteAnnotation(cmd.What, cmd.Data)
- // Support tags in prior to Graphite 0.10.0 format (string of tags separated by space)
- var tagsArray []string
- switch tags := cmd.Tags.(type) {
- case string:
- if tags != "" {
- tagsArray = strings.Split(tags, " ")
- } else {
- tagsArray = []string{}
- }
- case []interface{}:
- for _, t := range tags {
- if tagStr, ok := t.(string); ok {
- tagsArray = append(tagsArray, tagStr)
- } else {
- err := &CreateAnnotationError{"tag should be a string"}
- return Error(500, "Failed to save Graphite annotation", err)
- }
- }
- default:
- err := &CreateAnnotationError{"unsupported tags format"}
- return Error(500, "Failed to save Graphite annotation", err)
- }
- item := annotations.Item{
- OrgId: c.OrgId,
- UserId: c.UserId,
- Epoch: cmd.When * 1000,
- Text: text,
- Tags: tagsArray,
- }
- if err := repo.Save(&item); err != nil {
- return Error(500, "Failed to save Graphite annotation", err)
- }
- return JSON(200, util.DynMap{
- "message": "Graphite annotation added",
- "id": item.Id,
- })
- }
- func UpdateAnnotation(c *m.ReqContext, cmd dtos.UpdateAnnotationsCmd) Response {
- annotationID := c.ParamsInt64(":annotationId")
- repo := annotations.GetRepository()
- if resp := canSave(c, repo, annotationID); resp != nil {
- return resp
- }
- item := annotations.Item{
- OrgId: c.OrgId,
- UserId: c.UserId,
- Id: annotationID,
- Epoch: cmd.Time,
- EpochEnd: cmd.TimeEnd,
- Text: cmd.Text,
- Tags: cmd.Tags,
- }
- if err := repo.Update(&item); err != nil {
- return Error(500, "Failed to update annotation", err)
- }
- return Success("Annotation updated")
- }
- func PatchAnnotation(c *m.ReqContext, cmd dtos.PatchAnnotationsCmd) Response {
- annotationID := c.ParamsInt64(":annotationId")
- repo := annotations.GetRepository()
- if resp := canSave(c, repo, annotationID); resp != nil {
- return resp
- }
- items, err := repo.Find(&annotations.ItemQuery{AnnotationId: annotationID, OrgId: c.OrgId})
- if err != nil || len(items) == 0 {
- return Error(404, "Could not find annotation to update", err)
- }
- existing := annotations.Item{
- OrgId: c.OrgId,
- UserId: c.UserId,
- Id: annotationID,
- Epoch: items[0].Time,
- EpochEnd: items[0].TimeEnd,
- Text: items[0].Text,
- Tags: items[0].Tags,
- }
- if cmd.Tags != nil {
- existing.Tags = cmd.Tags
- }
- if cmd.Text != "" && cmd.Text != existing.Text {
- existing.Text = cmd.Text
- }
- if cmd.Time > 0 && cmd.Time != existing.Epoch {
- existing.Epoch = cmd.Time
- }
- if cmd.TimeEnd > 0 && cmd.TimeEnd != existing.EpochEnd {
- existing.EpochEnd = cmd.TimeEnd
- }
- if err := repo.Update(&existing); err != nil {
- return Error(500, "Failed to update annotation", err)
- }
- return Success("Annotation patched")
- }
- func DeleteAnnotations(c *m.ReqContext, cmd dtos.DeleteAnnotationsCmd) Response {
- repo := annotations.GetRepository()
- err := repo.Delete(&annotations.DeleteParams{
- OrgId: c.OrgId,
- Id: cmd.AnnotationId,
- DashboardId: cmd.DashboardId,
- PanelId: cmd.PanelId,
- })
- if err != nil {
- return Error(500, "Failed to delete annotations", err)
- }
- return Success("Annotations deleted")
- }
- func DeleteAnnotationByID(c *m.ReqContext) Response {
- repo := annotations.GetRepository()
- annotationID := c.ParamsInt64(":annotationId")
- if resp := canSave(c, repo, annotationID); resp != nil {
- return resp
- }
- err := repo.Delete(&annotations.DeleteParams{
- OrgId: c.OrgId,
- Id: annotationID,
- })
- if err != nil {
- return Error(500, "Failed to delete annotation", err)
- }
- return Success("Annotation deleted")
- }
- func canSaveByDashboardID(c *m.ReqContext, dashboardID int64) (bool, error) {
- if dashboardID == 0 && !c.SignedInUser.HasRole(m.ROLE_EDITOR) {
- return false, nil
- }
- if dashboardID != 0 {
- guard := guardian.New(dashboardID, c.OrgId, c.SignedInUser)
- if canEdit, err := guard.CanEdit(); err != nil || !canEdit {
- return false, err
- }
- }
- return true, nil
- }
- func canSave(c *m.ReqContext, repo annotations.Repository, annotationID int64) Response {
- items, err := repo.Find(&annotations.ItemQuery{AnnotationId: annotationID, OrgId: c.OrgId})
- if err != nil || len(items) == 0 {
- return Error(500, "Could not find annotation to update", err)
- }
- dashboardID := items[0].DashboardId
- if canSave, err := canSaveByDashboardID(c, dashboardID); err != nil || !canSave {
- return dashboardGuardianResponse(err)
- }
- return nil
- }
|