alert_notification.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package sqlstore
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "github.com/grafana/grafana/pkg/bus"
  9. m "github.com/grafana/grafana/pkg/models"
  10. )
  11. func init() {
  12. bus.AddHandler("sql", GetAlertNotifications)
  13. bus.AddHandler("sql", CreateAlertNotificationCommand)
  14. bus.AddHandler("sql", UpdateAlertNotification)
  15. bus.AddHandler("sql", DeleteAlertNotification)
  16. bus.AddHandler("sql", GetAlertNotificationsToSend)
  17. bus.AddHandler("sql", GetAllAlertNotifications)
  18. bus.AddHandlerCtx("sql", RecordNotificationJournal)
  19. bus.AddHandlerCtx("sql", GetLatestNotification)
  20. bus.AddHandlerCtx("sql", CleanNotificationJournal)
  21. }
  22. func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error {
  23. return inTransaction(func(sess *DBSession) error {
  24. sql := "DELETE FROM alert_notification WHERE alert_notification.org_id = ? AND alert_notification.id = ?"
  25. _, err := sess.Exec(sql, cmd.OrgId, cmd.Id)
  26. return err
  27. })
  28. }
  29. func GetAlertNotifications(query *m.GetAlertNotificationsQuery) error {
  30. return getAlertNotificationInternal(query, newSession())
  31. }
  32. func GetAllAlertNotifications(query *m.GetAllAlertNotificationsQuery) error {
  33. results := make([]*m.AlertNotification, 0)
  34. if err := x.Where("org_id = ?", query.OrgId).Find(&results); err != nil {
  35. return err
  36. }
  37. query.Result = results
  38. return nil
  39. }
  40. func GetAlertNotificationsToSend(query *m.GetAlertNotificationsToSendQuery) error {
  41. var sql bytes.Buffer
  42. params := make([]interface{}, 0)
  43. sql.WriteString(`SELECT
  44. alert_notification.id,
  45. alert_notification.org_id,
  46. alert_notification.name,
  47. alert_notification.type,
  48. alert_notification.created,
  49. alert_notification.updated,
  50. alert_notification.settings,
  51. alert_notification.is_default,
  52. alert_notification.send_reminder,
  53. alert_notification.frequency
  54. FROM alert_notification
  55. `)
  56. sql.WriteString(` WHERE alert_notification.org_id = ?`)
  57. params = append(params, query.OrgId)
  58. sql.WriteString(` AND ((alert_notification.is_default = ?)`)
  59. params = append(params, dialect.BooleanStr(true))
  60. if len(query.Ids) > 0 {
  61. sql.WriteString(` OR alert_notification.id IN (?` + strings.Repeat(",?", len(query.Ids)-1) + ")")
  62. for _, v := range query.Ids {
  63. params = append(params, v)
  64. }
  65. }
  66. sql.WriteString(`)`)
  67. results := make([]*m.AlertNotification, 0)
  68. if err := x.SQL(sql.String(), params...).Find(&results); err != nil {
  69. return err
  70. }
  71. query.Result = results
  72. return nil
  73. }
  74. func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *DBSession) error {
  75. var sql bytes.Buffer
  76. params := make([]interface{}, 0)
  77. sql.WriteString(`SELECT
  78. alert_notification.id,
  79. alert_notification.org_id,
  80. alert_notification.name,
  81. alert_notification.type,
  82. alert_notification.created,
  83. alert_notification.updated,
  84. alert_notification.settings,
  85. alert_notification.is_default,
  86. alert_notification.send_reminder,
  87. alert_notification.frequency
  88. FROM alert_notification
  89. `)
  90. sql.WriteString(` WHERE alert_notification.org_id = ?`)
  91. params = append(params, query.OrgId)
  92. if query.Name != "" || query.Id != 0 {
  93. if query.Name != "" {
  94. sql.WriteString(` AND alert_notification.name = ?`)
  95. params = append(params, query.Name)
  96. }
  97. if query.Id != 0 {
  98. sql.WriteString(` AND alert_notification.id = ?`)
  99. params = append(params, query.Id)
  100. }
  101. }
  102. results := make([]*m.AlertNotification, 0)
  103. if err := sess.Sql(sql.String(), params...).Find(&results); err != nil {
  104. return err
  105. }
  106. if len(results) == 0 {
  107. query.Result = nil
  108. } else {
  109. query.Result = results[0]
  110. }
  111. return nil
  112. }
  113. func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error {
  114. return inTransaction(func(sess *DBSession) error {
  115. existingQuery := &m.GetAlertNotificationsQuery{OrgId: cmd.OrgId, Name: cmd.Name}
  116. err := getAlertNotificationInternal(existingQuery, sess)
  117. if err != nil {
  118. return err
  119. }
  120. if existingQuery.Result != nil {
  121. return fmt.Errorf("Alert notification name %s already exists", cmd.Name)
  122. }
  123. var frequency time.Duration
  124. if cmd.SendReminder {
  125. if cmd.Frequency == "" {
  126. return m.ErrNotificationFrequencyNotFound
  127. }
  128. frequency, err = time.ParseDuration(cmd.Frequency)
  129. if err != nil {
  130. return err
  131. }
  132. }
  133. alertNotification := &m.AlertNotification{
  134. OrgId: cmd.OrgId,
  135. Name: cmd.Name,
  136. Type: cmd.Type,
  137. Settings: cmd.Settings,
  138. SendReminder: cmd.SendReminder,
  139. Frequency: frequency,
  140. Created: time.Now(),
  141. Updated: time.Now(),
  142. IsDefault: cmd.IsDefault,
  143. }
  144. if _, err = sess.MustCols("send_reminder").Insert(alertNotification); err != nil {
  145. return err
  146. }
  147. cmd.Result = alertNotification
  148. return nil
  149. })
  150. }
  151. func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
  152. return inTransaction(func(sess *DBSession) (err error) {
  153. current := m.AlertNotification{}
  154. if _, err = sess.ID(cmd.Id).Get(&current); err != nil {
  155. return err
  156. }
  157. // check if name exists
  158. sameNameQuery := &m.GetAlertNotificationsQuery{OrgId: cmd.OrgId, Name: cmd.Name}
  159. if err := getAlertNotificationInternal(sameNameQuery, sess); err != nil {
  160. return err
  161. }
  162. if sameNameQuery.Result != nil && sameNameQuery.Result.Id != current.Id {
  163. return fmt.Errorf("Alert notification name %s already exists", cmd.Name)
  164. }
  165. current.Updated = time.Now()
  166. current.Settings = cmd.Settings
  167. current.Name = cmd.Name
  168. current.Type = cmd.Type
  169. current.IsDefault = cmd.IsDefault
  170. current.SendReminder = cmd.SendReminder
  171. if current.SendReminder {
  172. if cmd.Frequency == "" {
  173. return m.ErrNotificationFrequencyNotFound
  174. }
  175. frequency, err := time.ParseDuration(cmd.Frequency)
  176. if err != nil {
  177. return err
  178. }
  179. current.Frequency = frequency
  180. }
  181. sess.UseBool("is_default", "send_reminder")
  182. if affected, err := sess.ID(cmd.Id).Update(current); err != nil {
  183. return err
  184. } else if affected == 0 {
  185. return fmt.Errorf("Could not update alert notification")
  186. }
  187. cmd.Result = &current
  188. return nil
  189. })
  190. }
  191. func RecordNotificationJournal(ctx context.Context, cmd *m.RecordNotificationJournalCommand) error {
  192. return inTransactionCtx(ctx, func(sess *DBSession) error {
  193. journalEntry := &m.AlertNotificationJournal{
  194. OrgId: cmd.OrgId,
  195. AlertId: cmd.AlertId,
  196. NotifierId: cmd.NotifierId,
  197. SentAt: cmd.SentAt,
  198. Success: cmd.Success,
  199. }
  200. if _, err := sess.Insert(journalEntry); err != nil {
  201. return err
  202. }
  203. return nil
  204. })
  205. }
  206. func GetLatestNotification(ctx context.Context, cmd *m.GetLatestNotificationQuery) error {
  207. return inTransactionCtx(ctx, func(sess *DBSession) error {
  208. nj := &m.AlertNotificationJournal{}
  209. _, err := sess.Desc("alert_notification_journal.sent_at").
  210. Limit(1).
  211. Where("alert_notification_journal.org_id = ? AND alert_notification_journal.alert_id = ? AND alert_notification_journal.notifier_id = ?", cmd.OrgId, cmd.AlertId, cmd.NotifierId).Get(nj)
  212. if err != nil {
  213. return err
  214. }
  215. if nj.AlertId == 0 && nj.Id == 0 && nj.NotifierId == 0 && nj.OrgId == 0 {
  216. return m.ErrJournalingNotFound
  217. }
  218. cmd.Result = nj
  219. return nil
  220. })
  221. }
  222. func CleanNotificationJournal(ctx context.Context, cmd *m.CleanNotificationJournalCommand) error {
  223. return inTransactionCtx(ctx, func(sess *DBSession) error {
  224. sql := "DELETE FROM alert_notification_journal WHERE alert_notification_journal.org_id = ? AND alert_notification_journal.alert_id = ? AND alert_notification_journal.notifier_id = ?"
  225. _, err := sess.Exec(sql, cmd.OrgId, cmd.AlertId, cmd.NotifierId)
  226. return err
  227. })
  228. }