2022-08-03 10:17:26 -05:00
package alerting
2016-06-13 09:39:00 -05:00
import (
"bytes"
2018-06-15 08:30:17 -05:00
"context"
2018-09-28 04:17:03 -05:00
"errors"
2016-06-14 01:33:50 -05:00
"fmt"
2016-07-26 05:29:52 -05:00
"strings"
2016-06-14 01:33:50 -05:00
"time"
2016-06-13 09:39:00 -05:00
2022-10-19 08:02:15 -05:00
"github.com/grafana/grafana/pkg/infra/db"
2023-01-23 07:19:25 -06:00
"github.com/grafana/grafana/pkg/services/alerting/models"
2018-12-14 03:53:50 -06:00
"github.com/grafana/grafana/pkg/util"
2016-06-13 09:39:00 -05:00
)
2022-02-03 06:26:05 -06:00
type AlertNotificationStore interface {
DeleteAlertNotification ( ctx context . Context , cmd * models . DeleteAlertNotificationCommand ) error
DeleteAlertNotificationWithUid ( ctx context . Context , cmd * models . DeleteAlertNotificationWithUidCommand ) error
2023-02-02 02:41:05 -06:00
GetAlertNotifications ( ctx context . Context , query * models . GetAlertNotificationsQuery ) ( * models . AlertNotification , error )
GetAlertNotificationUidWithId ( ctx context . Context , query * models . GetAlertNotificationUidQuery ) ( string , error )
GetAlertNotificationsWithUid ( ctx context . Context , query * models . GetAlertNotificationsWithUidQuery ) ( * models . AlertNotification , error )
GetAllAlertNotifications ( ctx context . Context , query * models . GetAllAlertNotificationsQuery ) ( [ ] * models . AlertNotification , error )
GetAlertNotificationsWithUidToSend ( ctx context . Context , query * models . GetAlertNotificationsWithUidToSendQuery ) ( [ ] * models . AlertNotification , error )
CreateAlertNotificationCommand ( ctx context . Context , cmd * models . CreateAlertNotificationCommand ) ( * models . AlertNotification , error )
UpdateAlertNotification ( ctx context . Context , cmd * models . UpdateAlertNotificationCommand ) ( * models . AlertNotification , error )
UpdateAlertNotificationWithUid ( ctx context . Context , cmd * models . UpdateAlertNotificationWithUidCommand ) ( * models . AlertNotification , error )
2022-02-03 06:26:05 -06:00
SetAlertNotificationStateToCompleteCommand ( ctx context . Context , cmd * models . SetAlertNotificationStateToCompleteCommand ) error
SetAlertNotificationStateToPendingCommand ( ctx context . Context , cmd * models . SetAlertNotificationStateToPendingCommand ) error
2023-02-02 02:41:05 -06:00
GetOrCreateAlertNotificationState ( ctx context . Context , cmd * models . GetOrCreateNotificationStateQuery ) ( * models . AlertNotificationState , error )
2022-02-03 06:26:05 -06:00
}
2022-08-03 10:17:26 -05:00
// timeNow makes it possible to test usage of time
var timeNow = time . Now
func ( ss * sqlStore ) DeleteAlertNotification ( ctx context . Context , cmd * models . DeleteAlertNotificationCommand ) error {
2022-10-19 08:02:15 -05:00
return ss . db . WithTransactionalDbSession ( ctx , func ( sess * db . Session ) error {
2016-06-16 08:21:44 -05:00
sql := "DELETE FROM alert_notification WHERE alert_notification.org_id = ? AND alert_notification.id = ?"
2023-02-03 08:46:55 -06:00
res , err := sess . Exec ( sql , cmd . OrgID , cmd . ID )
2020-09-11 11:04:43 -05:00
if err != nil {
return err
}
rowsAffected , err := res . RowsAffected ( )
if err != nil {
2018-09-30 14:57:15 -05:00
return err
}
2020-09-11 11:04:43 -05:00
if rowsAffected == 0 {
return models . ErrAlertNotificationNotFound
}
2023-02-03 08:46:55 -06:00
if _ , err := sess . Exec ( "DELETE FROM alert_notification_state WHERE alert_notification_state.org_id = ? AND alert_notification_state.notifier_id = ?" , cmd . OrgID , cmd . ID ) ; err != nil {
2018-09-30 14:57:15 -05:00
return err
}
return nil
2016-06-16 08:21:44 -05:00
} )
2016-06-13 09:39:00 -05:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) DeleteAlertNotificationWithUid ( ctx context . Context , cmd * models . DeleteAlertNotificationWithUidCommand ) ( err error ) {
var res * models . AlertNotification
if err = ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
2023-02-03 08:46:55 -06:00
existingNotification := & models . GetAlertNotificationsWithUidQuery { OrgID : cmd . OrgID , UID : cmd . UID }
2023-02-02 02:41:05 -06:00
res , err = getAlertNotificationWithUidInternal ( ctx , existingNotification , sess )
return err
2022-09-29 07:55:47 -05:00
} ) ; err != nil {
2018-12-20 04:45:18 -06:00
return err
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
if res == nil {
2020-09-11 11:04:43 -05:00
return models . ErrAlertNotificationNotFound
}
2023-02-03 08:46:55 -06:00
cmd . DeletedAlertNotificationID = res . ID
2020-09-11 11:04:43 -05:00
deleteCommand := & models . DeleteAlertNotificationCommand {
2023-02-03 08:46:55 -06:00
ID : res . ID ,
OrgID : res . OrgID ,
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
return ss . DeleteAlertNotification ( ctx , deleteCommand )
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) GetAlertNotifications ( ctx context . Context , query * models . GetAlertNotificationsQuery ) ( res * models . AlertNotification , err error ) {
err = ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
res , err = getAlertNotificationInternal ( ctx , query , sess )
return err
2022-09-29 07:55:47 -05:00
} )
2023-02-02 02:41:05 -06:00
return res , err
2016-06-14 01:33:50 -05:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) GetAlertNotificationUidWithId ( ctx context . Context , query * models . GetAlertNotificationUidQuery ) ( res string , err error ) {
2023-02-03 08:46:55 -06:00
cacheKey := newAlertNotificationUidCacheKey ( query . OrgID , query . ID )
2020-03-18 08:00:56 -05:00
2022-08-03 10:17:26 -05:00
if cached , found := ss . cache . Get ( cacheKey ) ; found {
2023-02-02 02:41:05 -06:00
return cached . ( string ) , nil
2020-03-18 08:00:56 -05:00
}
2022-10-19 08:02:15 -05:00
if err := ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
2023-02-02 02:41:05 -06:00
res , err = getAlertNotificationUidInternal ( ctx , query , sess )
2020-03-18 08:00:56 -05:00
return err
2023-02-02 02:41:05 -06:00
} ) ; err != nil {
return "" , err
2020-03-18 08:00:56 -05:00
}
2023-02-02 02:41:05 -06:00
ss . cache . Set ( cacheKey , res , - 1 ) // Infinite, never changes
return res , nil
2020-03-18 08:00:56 -05:00
}
func newAlertNotificationUidCacheKey ( orgID , notificationId int64 ) string {
return fmt . Sprintf ( "notification-uid-by-org-%d-and-id-%d" , orgID , notificationId )
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) GetAlertNotificationsWithUid ( ctx context . Context , query * models . GetAlertNotificationsWithUidQuery ) ( res * models . AlertNotification , err error ) {
err = ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
res , err = getAlertNotificationWithUidInternal ( ctx , query , sess )
return err
2022-09-29 07:55:47 -05:00
} )
2023-02-02 02:41:05 -06:00
return res , err
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) GetAllAlertNotifications ( ctx context . Context , query * models . GetAllAlertNotificationsQuery ) ( res [ ] * models . AlertNotification , err error ) {
res = make ( [ ] * models . AlertNotification , 0 )
err = ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
2023-02-03 08:46:55 -06:00
if err := sess . Where ( "org_id = ?" , query . OrgID ) . Asc ( "name" ) . Find ( & res ) ; err != nil {
2022-01-06 11:21:39 -06:00
return err
}
return nil
} )
2023-02-02 02:41:05 -06:00
return res , err
2016-09-06 01:42:35 -05:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) GetAlertNotificationsWithUidToSend ( ctx context . Context , query * models . GetAlertNotificationsWithUidToSendQuery ) ( res [ ] * models . AlertNotification , err error ) {
res = make ( [ ] * models . AlertNotification , 0 )
err = ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
2022-01-06 11:21:39 -06:00
var sql bytes . Buffer
params := make ( [ ] interface { } , 0 )
2016-09-06 01:42:35 -05:00
2022-01-06 11:21:39 -06:00
sql . WriteString ( ` SELECT
2016-09-06 01:42:35 -05:00
alert_notification . id ,
2018-12-14 03:53:50 -06:00
alert_notification . uid ,
2016-09-06 01:42:35 -05:00
alert_notification . org_id ,
alert_notification . name ,
alert_notification . type ,
alert_notification . created ,
alert_notification . updated ,
alert_notification . settings ,
2020-07-08 03:17:05 -05:00
alert_notification . secure_settings ,
2018-05-20 11:12:10 -05:00
alert_notification . is_default ,
2018-10-17 03:41:18 -05:00
alert_notification . disable_resolve_message ,
2018-06-05 03:27:29 -05:00
alert_notification . send_reminder ,
2018-05-20 11:12:10 -05:00
alert_notification . frequency
2016-09-06 01:42:35 -05:00
FROM alert_notification
` )
2022-01-06 11:21:39 -06:00
sql . WriteString ( ` WHERE alert_notification.org_id = ? ` )
2023-02-03 08:46:55 -06:00
params = append ( params , query . OrgID )
2016-09-06 01:42:35 -05:00
2022-01-06 11:21:39 -06:00
sql . WriteString ( ` AND ((alert_notification.is_default = ?) ` )
2022-08-03 10:17:26 -05:00
params = append ( params , ss . db . GetDialect ( ) . BooleanStr ( true ) )
2018-12-14 03:53:50 -06:00
2023-02-03 08:46:55 -06:00
if len ( query . UIDs ) > 0 {
sql . WriteString ( ` OR alert_notification.uid IN (? ` + strings . Repeat ( ",?" , len ( query . UIDs ) - 1 ) + ")" )
for _ , v := range query . UIDs {
2022-01-06 11:21:39 -06:00
params = append ( params , v )
}
2016-09-06 01:42:35 -05:00
}
2022-01-06 11:21:39 -06:00
sql . WriteString ( ` ) ` )
2016-09-06 01:42:35 -05:00
2023-02-02 02:41:05 -06:00
return sess . SQL ( sql . String ( ) , params ... ) . Find ( & res )
2022-01-06 11:21:39 -06:00
} )
2023-02-02 02:41:05 -06:00
return res , err
2016-09-06 01:42:35 -05:00
}
2023-02-02 02:41:05 -06:00
func getAlertNotificationUidInternal ( ctx context . Context , query * models . GetAlertNotificationUidQuery , sess * db . Session ) ( res string , err error ) {
2020-03-18 08:00:56 -05:00
var sql bytes . Buffer
params := make ( [ ] interface { } , 0 )
sql . WriteString ( ` SELECT
alert_notification . uid
FROM alert_notification
` )
sql . WriteString ( ` WHERE alert_notification.org_id = ? ` )
2023-02-03 08:46:55 -06:00
params = append ( params , query . OrgID )
2020-03-18 08:00:56 -05:00
sql . WriteString ( ` AND alert_notification.id = ? ` )
2023-02-03 08:46:55 -06:00
params = append ( params , query . ID )
2020-03-18 08:00:56 -05:00
results := make ( [ ] string , 0 )
if err := sess . SQL ( sql . String ( ) , params ... ) . Find ( & results ) ; err != nil {
2023-02-02 02:41:05 -06:00
return "" , err
2020-03-18 08:00:56 -05:00
}
if len ( results ) == 0 {
2023-02-02 02:41:05 -06:00
return "" , models . ErrAlertNotificationFailedTranslateUniqueID
2020-03-18 08:00:56 -05:00
}
2023-02-02 02:41:05 -06:00
res = results [ 0 ]
return res , nil
2020-03-18 08:00:56 -05:00
}
2023-02-02 02:41:05 -06:00
func getAlertNotificationInternal ( ctx context . Context , query * models . GetAlertNotificationsQuery , sess * db . Session ) ( res * models . AlertNotification , err error ) {
2016-06-13 09:39:00 -05:00
var sql bytes . Buffer
params := make ( [ ] interface { } , 0 )
sql . WriteString ( ` SELECT
2016-09-05 14:33:05 -05:00
alert_notification . id ,
2019-03-26 06:37:02 -05:00
alert_notification . uid ,
2016-09-05 14:33:05 -05:00
alert_notification . org_id ,
alert_notification . name ,
alert_notification . type ,
alert_notification . created ,
alert_notification . updated ,
alert_notification . settings ,
2020-07-08 03:17:05 -05:00
alert_notification . secure_settings ,
2018-05-20 11:12:10 -05:00
alert_notification . is_default ,
2018-10-17 03:41:18 -05:00
alert_notification . disable_resolve_message ,
2018-06-05 03:27:29 -05:00
alert_notification . send_reminder ,
2018-05-20 11:12:10 -05:00
alert_notification . frequency
2016-09-05 14:33:05 -05:00
FROM alert_notification
` )
2016-06-13 09:39:00 -05:00
sql . WriteString ( ` WHERE alert_notification.org_id = ? ` )
2023-02-03 08:46:55 -06:00
params = append ( params , query . OrgID )
2016-06-13 09:39:00 -05:00
2023-02-03 08:46:55 -06:00
if query . Name != "" || query . ID != 0 {
2016-09-05 14:33:05 -05:00
if query . Name != "" {
sql . WriteString ( ` AND alert_notification.name = ? ` )
params = append ( params , query . Name )
}
2016-06-13 09:39:00 -05:00
2023-02-03 08:46:55 -06:00
if query . ID != 0 {
2016-09-05 14:33:05 -05:00
sql . WriteString ( ` AND alert_notification.id = ? ` )
2023-02-03 08:46:55 -06:00
params = append ( params , query . ID )
2016-09-05 14:33:05 -05:00
}
2016-06-14 09:56:14 -05:00
}
2020-02-29 06:35:15 -06:00
results := make ( [ ] * models . AlertNotification , 0 )
2018-09-16 05:26:05 -05:00
if err := sess . SQL ( sql . String ( ) , params ... ) . Find ( & results ) ; err != nil {
2023-02-02 02:41:05 -06:00
return nil , err
2016-06-13 09:39:00 -05:00
}
2016-09-06 01:42:35 -05:00
if len ( results ) == 0 {
2023-02-02 02:41:05 -06:00
return nil , nil
2016-09-06 01:42:35 -05:00
}
2023-02-02 02:41:05 -06:00
return results [ 0 ] , nil
2016-06-13 09:39:00 -05:00
}
2023-02-02 02:41:05 -06:00
func getAlertNotificationWithUidInternal ( ctx context . Context , query * models . GetAlertNotificationsWithUidQuery , sess * db . Session ) ( res * models . AlertNotification , err error ) {
2018-12-14 03:53:50 -06:00
var sql bytes . Buffer
params := make ( [ ] interface { } , 0 )
sql . WriteString ( ` SELECT
alert_notification . id ,
alert_notification . uid ,
alert_notification . org_id ,
alert_notification . name ,
alert_notification . type ,
alert_notification . created ,
alert_notification . updated ,
alert_notification . settings ,
2020-07-08 03:17:05 -05:00
alert_notification . secure_settings ,
2018-12-14 03:53:50 -06:00
alert_notification . is_default ,
alert_notification . disable_resolve_message ,
alert_notification . send_reminder ,
alert_notification . frequency
FROM alert_notification
` )
sql . WriteString ( ` WHERE alert_notification.org_id = ? AND alert_notification.uid = ? ` )
2023-02-03 08:46:55 -06:00
params = append ( params , query . OrgID , query . UID )
2018-12-14 03:53:50 -06:00
2020-02-29 06:35:15 -06:00
results := make ( [ ] * models . AlertNotification , 0 )
2018-12-14 03:53:50 -06:00
if err := sess . SQL ( sql . String ( ) , params ... ) . Find ( & results ) ; err != nil {
2023-02-02 02:41:05 -06:00
return nil , err
2018-12-14 03:53:50 -06:00
}
if len ( results ) == 0 {
2023-02-02 02:41:05 -06:00
return nil , nil
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
return results [ 0 ] , nil
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) CreateAlertNotificationCommand ( ctx context . Context , cmd * models . CreateAlertNotificationCommand ) ( res * models . AlertNotification , err error ) {
err = ss . db . WithTransactionalDbSession ( ctx , func ( sess * db . Session ) error {
2023-02-03 08:46:55 -06:00
if cmd . UID == "" {
uid , uidGenerationErr := generateNewAlertNotificationUid ( ctx , sess , cmd . OrgID )
2019-04-23 03:24:47 -05:00
if uidGenerationErr != nil {
2018-12-14 03:53:50 -06:00
return uidGenerationErr
}
2019-04-23 03:24:47 -05:00
2023-02-03 08:46:55 -06:00
cmd . UID = uid
2018-12-14 03:53:50 -06:00
}
2023-02-03 08:46:55 -06:00
existingQuery := & models . GetAlertNotificationsWithUidQuery { OrgID : cmd . OrgID , UID : cmd . UID }
2023-02-02 02:41:05 -06:00
if notification , err := getAlertNotificationWithUidInternal ( ctx , existingQuery , sess ) ; err != nil {
2016-06-14 01:33:50 -05:00
return err
2023-02-02 02:41:05 -06:00
} else if notification != nil {
2020-10-20 06:53:48 -05:00
return models . ErrAlertNotificationWithSameUIDExists
2018-12-14 03:53:50 -06:00
}
// check if name exists
2023-02-03 08:46:55 -06:00
sameNameQuery := & models . GetAlertNotificationsQuery { OrgID : cmd . OrgID , Name : cmd . Name }
2023-02-02 02:41:05 -06:00
if notification , err := getAlertNotificationInternal ( ctx , sameNameQuery , sess ) ; err != nil {
2018-12-14 03:53:50 -06:00
return err
2023-02-02 02:41:05 -06:00
} else if notification != nil {
2020-10-20 06:53:48 -05:00
return models . ErrAlertNotificationWithSameNameExists
2016-06-14 01:33:50 -05:00
}
2016-06-13 09:39:00 -05:00
2018-05-25 13:14:33 -05:00
var frequency time . Duration
2018-06-05 03:27:29 -05:00
if cmd . SendReminder {
2018-06-04 15:19:27 -05:00
if cmd . Frequency == "" {
2020-02-29 06:35:15 -06:00
return models . ErrNotificationFrequencyNotFound
2018-06-04 15:19:27 -05:00
}
frequency , err = time . ParseDuration ( cmd . Frequency )
if err != nil {
return err
}
2018-05-20 11:12:10 -05:00
}
2020-07-08 03:17:05 -05:00
// delete empty keys
for k , v := range cmd . SecureSettings {
if v == "" {
delete ( cmd . SecureSettings , k )
}
}
2020-02-29 06:35:15 -06:00
alertNotification := & models . AlertNotification {
2023-02-03 08:46:55 -06:00
UID : cmd . UID ,
OrgID : cmd . OrgID ,
2018-10-17 03:41:18 -05:00
Name : cmd . Name ,
Type : cmd . Type ,
Settings : cmd . Settings ,
2021-10-07 09:33:50 -05:00
SecureSettings : cmd . EncryptedSecureSettings ,
2018-10-17 03:41:18 -05:00
SendReminder : cmd . SendReminder ,
DisableResolveMessage : cmd . DisableResolveMessage ,
Frequency : frequency ,
Created : time . Now ( ) ,
Updated : time . Now ( ) ,
IsDefault : cmd . IsDefault ,
2016-06-14 01:33:50 -05:00
}
2016-06-13 09:39:00 -05:00
2018-06-05 03:27:29 -05:00
if _ , err = sess . MustCols ( "send_reminder" ) . Insert ( alertNotification ) ; err != nil {
2016-06-14 01:33:50 -05:00
return err
}
2023-02-02 02:41:05 -06:00
res = alertNotification
2016-06-14 01:33:50 -05:00
return nil
2016-06-13 09:39:00 -05:00
} )
2023-02-02 02:41:05 -06:00
return res , err
2016-06-13 09:39:00 -05:00
}
2022-10-19 08:02:15 -05:00
func generateNewAlertNotificationUid ( ctx context . Context , sess * db . Session , orgId int64 ) ( string , error ) {
2018-12-14 03:53:50 -06:00
for i := 0 ; i < 3 ; i ++ {
2019-01-29 14:17:56 -06:00
uid := util . GenerateShortUID ( )
2020-02-29 06:35:15 -06:00
exists , err := sess . Where ( "org_id=? AND uid=?" , orgId , uid ) . Get ( & models . AlertNotification { } )
2018-12-14 03:53:50 -06:00
if err != nil {
return "" , err
}
2019-01-28 15:03:16 -06:00
2018-12-14 03:53:50 -06:00
if ! exists {
return uid , nil
}
}
2019-01-28 15:03:16 -06:00
2020-02-29 06:35:15 -06:00
return "" , models . ErrAlertNotificationFailedGenerateUniqueUid
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) UpdateAlertNotification ( ctx context . Context , cmd * models . UpdateAlertNotificationCommand ) ( res * models . AlertNotification , err error ) {
err = ss . db . WithTransactionalDbSession ( ctx , func ( sess * db . Session ) ( err error ) {
2020-02-29 06:35:15 -06:00
current := models . AlertNotification { }
2016-06-13 09:39:00 -05:00
2023-02-03 08:46:55 -06:00
if _ , err = sess . ID ( cmd . ID ) . Get ( & current ) ; err != nil {
2016-06-14 01:33:50 -05:00
return err
}
2023-02-03 08:46:55 -06:00
if current . ID == 0 {
2020-09-11 11:04:43 -05:00
return models . ErrAlertNotificationNotFound
}
2016-07-22 09:45:17 -05:00
// check if name exists
2023-02-03 08:46:55 -06:00
sameNameQuery := & models . GetAlertNotificationsQuery { OrgID : cmd . OrgID , Name : cmd . Name }
2023-02-02 02:41:05 -06:00
notification , err := getAlertNotificationInternal ( ctx , sameNameQuery , sess )
if err != nil {
2016-07-22 09:45:17 -05:00
return err
2016-06-20 09:19:15 -05:00
}
2023-02-03 08:46:55 -06:00
if notification != nil && notification . ID != current . ID {
2020-11-05 04:57:20 -06:00
return fmt . Errorf ( "alert notification name %q already exists" , cmd . Name )
2016-07-22 09:45:17 -05:00
}
2016-06-14 01:33:50 -05:00
2020-07-08 03:17:05 -05:00
// delete empty keys
for k , v := range cmd . SecureSettings {
if v == "" {
delete ( cmd . SecureSettings , k )
}
}
2016-07-22 09:45:17 -05:00
current . Updated = time . Now ( )
current . Settings = cmd . Settings
2021-10-07 09:33:50 -05:00
current . SecureSettings = cmd . EncryptedSecureSettings
2016-07-22 09:45:17 -05:00
current . Name = cmd . Name
current . Type = cmd . Type
2016-09-05 14:33:05 -05:00
current . IsDefault = cmd . IsDefault
2018-06-05 03:27:29 -05:00
current . SendReminder = cmd . SendReminder
2018-10-17 03:41:18 -05:00
current . DisableResolveMessage = cmd . DisableResolveMessage
2018-05-20 11:12:10 -05:00
2023-02-03 08:46:55 -06:00
if cmd . UID != "" {
current . UID = cmd . UID
2019-03-29 03:42:38 -05:00
}
2018-06-05 03:27:29 -05:00
if current . SendReminder {
2018-06-04 15:19:27 -05:00
if cmd . Frequency == "" {
2020-02-29 06:35:15 -06:00
return models . ErrNotificationFrequencyNotFound
2018-06-04 15:19:27 -05:00
}
2018-05-20 15:08:42 -05:00
2018-06-04 15:19:27 -05:00
frequency , err := time . ParseDuration ( cmd . Frequency )
if err != nil {
return err
}
current . Frequency = frequency
2018-05-20 11:12:10 -05:00
}
2016-09-05 14:33:05 -05:00
2018-10-17 03:41:18 -05:00
sess . UseBool ( "is_default" , "send_reminder" , "disable_resolve_message" )
2016-06-14 01:33:50 -05:00
2023-02-03 08:46:55 -06:00
if affected , err := sess . ID ( cmd . ID ) . Update ( current ) ; err != nil {
2016-06-14 01:33:50 -05:00
return err
2016-07-22 09:45:17 -05:00
} else if affected == 0 {
2020-11-05 04:57:20 -06:00
return fmt . Errorf ( "could not update alert notification" )
2016-06-14 09:56:14 -05:00
}
2023-02-02 02:41:05 -06:00
res = & current
2016-06-14 01:33:50 -05:00
return nil
} )
2023-02-02 02:41:05 -06:00
return res , err
2016-06-14 01:33:50 -05:00
}
2018-05-19 15:21:00 -05:00
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) UpdateAlertNotificationWithUid ( ctx context . Context , cmd * models . UpdateAlertNotificationWithUidCommand ) ( res * models . AlertNotification , err error ) {
2023-02-03 08:46:55 -06:00
getAlertNotificationWithUidQuery := & models . GetAlertNotificationsWithUidQuery { OrgID : cmd . OrgID , UID : cmd . UID }
2018-12-14 03:53:50 -06:00
2022-10-19 08:02:15 -05:00
if err := ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
2023-02-02 02:41:05 -06:00
res , err = getAlertNotificationWithUidInternal ( ctx , getAlertNotificationWithUidQuery , sess )
2018-12-20 04:45:18 -06:00
return err
2023-02-02 02:41:05 -06:00
} ) ; err != nil {
return nil , err
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
current := res
2018-12-14 03:53:50 -06:00
if current == nil {
2023-02-02 02:41:05 -06:00
return nil , models . ErrAlertNotificationNotFound
2018-12-14 03:53:50 -06:00
}
2023-02-03 08:46:55 -06:00
if cmd . NewUID == "" {
cmd . NewUID = cmd . UID
2019-03-29 03:42:38 -05:00
}
2020-02-29 06:35:15 -06:00
updateNotification := & models . UpdateAlertNotificationCommand {
2023-02-03 08:46:55 -06:00
ID : current . ID ,
UID : cmd . NewUID ,
2018-12-14 03:53:50 -06:00
Name : cmd . Name ,
Type : cmd . Type ,
SendReminder : cmd . SendReminder ,
DisableResolveMessage : cmd . DisableResolveMessage ,
Frequency : cmd . Frequency ,
IsDefault : cmd . IsDefault ,
Settings : cmd . Settings ,
2020-07-08 03:17:05 -05:00
SecureSettings : cmd . SecureSettings ,
2018-12-14 03:53:50 -06:00
2023-02-03 08:46:55 -06:00
OrgID : cmd . OrgID ,
2018-12-14 03:53:50 -06:00
}
2023-02-02 02:41:05 -06:00
return ss . UpdateAlertNotification ( ctx , updateNotification )
2018-12-14 03:53:50 -06:00
}
2022-08-03 10:17:26 -05:00
func ( ss * sqlStore ) SetAlertNotificationStateToCompleteCommand ( ctx context . Context , cmd * models . SetAlertNotificationStateToCompleteCommand ) error {
2022-10-19 08:02:15 -05:00
return ss . db . WithTransactionalDbSession ( ctx , func ( sess * db . Session ) error {
2018-10-02 06:57:41 -05:00
version := cmd . Version
2020-02-29 06:35:15 -06:00
var current models . AlertNotificationState
2023-02-03 08:46:55 -06:00
if _ , err := sess . ID ( cmd . ID ) . Get ( & current ) ; err != nil {
2019-10-22 07:08:18 -05:00
return err
}
2018-09-28 07:12:26 -05:00
2018-10-02 06:57:41 -05:00
newVersion := cmd . Version + 1
2018-09-27 05:07:43 -05:00
sql := ` UPDATE alert_notification_state SET
2018-09-28 04:17:03 -05:00
state = ? ,
2018-09-28 08:11:03 -05:00
version = ? ,
2018-09-30 14:52:50 -05:00
updated_at = ?
2018-09-27 04:33:13 -05:00
WHERE
id = ? `
2023-02-03 08:46:55 -06:00
_ , err := sess . Exec ( sql , models . AlertNotificationStateCompleted , newVersion , timeNow ( ) . Unix ( ) , cmd . ID )
2018-09-27 04:33:13 -05:00
if err != nil {
return err
}
2018-09-28 07:12:26 -05:00
if current . Version != version {
2023-02-03 08:46:55 -06:00
ss . log . Error ( "notification state out of sync. the notification is marked as complete but has been modified between set as pending and completion." , "notifierId" , current . NotifierID )
2018-09-27 04:33:13 -05:00
}
return nil
} )
}
2022-08-03 10:17:26 -05:00
func ( ss * sqlStore ) SetAlertNotificationStateToPendingCommand ( ctx context . Context , cmd * models . SetAlertNotificationStateToPendingCommand ) error {
2022-10-19 08:02:15 -05:00
return ss . db . WithDbSession ( ctx , func ( sess * db . Session ) error {
2018-10-02 06:57:41 -05:00
newVersion := cmd . Version + 1
2018-09-27 05:07:43 -05:00
sql := ` UPDATE alert_notification_state SET
2018-09-28 04:17:03 -05:00
state = ? ,
2018-09-30 14:52:50 -05:00
version = ? ,
2018-10-01 07:13:03 -05:00
updated_at = ? ,
alert_rule_state_updated_version = ?
2018-09-27 04:14:44 -05:00
WHERE
id = ? AND
2018-10-01 07:13:03 -05:00
( version = ? OR alert_rule_state_updated_version < ? ) `
2018-09-27 04:14:44 -05:00
2018-10-01 07:13:03 -05:00
res , err := sess . Exec ( sql ,
2020-02-29 06:35:15 -06:00
models . AlertNotificationStatePending ,
2018-10-02 06:57:41 -05:00
newVersion ,
2018-10-01 07:13:03 -05:00
timeNow ( ) . Unix ( ) ,
cmd . AlertRuleStateUpdatedVersion ,
2023-02-03 08:46:55 -06:00
cmd . ID ,
2018-10-02 06:57:41 -05:00
cmd . Version ,
2018-10-01 07:13:03 -05:00
cmd . AlertRuleStateUpdatedVersion )
2018-09-28 07:12:26 -05:00
2018-09-27 04:14:44 -05:00
if err != nil {
return err
}
affected , _ := res . RowsAffected ( )
if affected == 0 {
2020-02-29 06:35:15 -06:00
return models . ErrAlertNotificationStateVersionConflict
2018-09-27 04:14:44 -05:00
}
2018-10-02 06:57:41 -05:00
cmd . ResultVersion = newVersion
2018-09-27 04:14:44 -05:00
return nil
} )
}
2023-02-02 02:41:05 -06:00
func ( ss * sqlStore ) GetOrCreateAlertNotificationState ( ctx context . Context , cmd * models . GetOrCreateNotificationStateQuery ) ( res * models . AlertNotificationState , err error ) {
err = ss . db . WithTransactionalDbSession ( ctx , func ( sess * db . Session ) error {
2020-02-29 06:35:15 -06:00
nj := & models . AlertNotificationState { }
2018-06-29 08:15:31 -05:00
2021-11-05 03:41:24 -05:00
exist , err := getAlertNotificationState ( ctx , sess , cmd , nj )
2018-06-16 04:27:04 -05:00
2018-09-27 07:32:54 -05:00
// if exists, return it, otherwise create it with default values
2018-05-19 15:21:00 -05:00
if err != nil {
return err
}
2018-09-28 03:48:08 -05:00
if exist {
2023-02-02 02:41:05 -06:00
res = nj
2018-09-28 03:48:08 -05:00
return nil
}
2020-02-29 06:35:15 -06:00
notificationState := & models . AlertNotificationState {
2023-02-03 08:46:55 -06:00
OrgID : cmd . OrgID ,
AlertID : cmd . AlertID ,
NotifierID : cmd . NotifierID ,
2020-02-29 06:35:15 -06:00
State : models . AlertNotificationStateUnknown ,
2018-09-30 14:52:50 -05:00
UpdatedAt : timeNow ( ) . Unix ( ) ,
2018-09-28 04:17:03 -05:00
}
2018-09-27 07:32:54 -05:00
2018-09-28 04:17:03 -05:00
if _ , err := sess . Insert ( notificationState ) ; err != nil {
2022-08-03 10:17:26 -05:00
if ss . db . GetDialect ( ) . IsUniqueConstraintViolation ( err ) {
2021-11-05 03:41:24 -05:00
exist , err = getAlertNotificationState ( ctx , sess , cmd , nj )
2018-09-27 07:32:54 -05:00
2018-09-28 04:17:03 -05:00
if err != nil {
return err
}
2018-09-28 03:48:08 -05:00
2018-09-28 04:17:03 -05:00
if ! exist {
2020-11-05 04:57:20 -06:00
return errors . New ( "should not happen" )
2018-09-27 07:32:54 -05:00
}
2023-02-02 02:41:05 -06:00
res = nj
2018-09-28 04:17:03 -05:00
return nil
2018-09-28 03:48:08 -05:00
}
2018-09-28 04:17:03 -05:00
return err
2018-09-27 04:14:44 -05:00
}
2023-02-02 02:41:05 -06:00
res = notificationState
2018-05-19 15:21:00 -05:00
return nil
} )
2023-02-02 02:41:05 -06:00
return res , err
2018-05-19 15:21:00 -05:00
}
2018-09-28 03:48:08 -05:00
2022-10-19 08:02:15 -05:00
func getAlertNotificationState ( ctx context . Context , sess * db . Session , cmd * models . GetOrCreateNotificationStateQuery , nj * models . AlertNotificationState ) ( bool , error ) {
2018-10-02 04:19:09 -05:00
return sess .
2023-02-03 08:46:55 -06:00
Where ( "alert_notification_state.org_id = ?" , cmd . OrgID ) .
Where ( "alert_notification_state.alert_id = ?" , cmd . AlertID ) .
Where ( "alert_notification_state.notifier_id = ?" , cmd . NotifierID ) .
2018-09-28 03:48:08 -05:00
Get ( nj )
}