A More Secure Internet Connection for Your Home https://fen.gg
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

191 lines
4.7 KiB

  1. package model
  2. //
  3. // Fengg Security Gateway Server Application
  4. // Copyright (C) 2020 Lukas Matt <support@fen.gg>
  5. //
  6. // This program is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. //
  18. import (
  19. "time"
  20. "fmt"
  21. "tea.fen.gg/fengg/server/types"
  22. "github.com/jmoiron/sqlx"
  23. _ "github.com/lib/pq"
  24. )
  25. const (
  26. NotificationQueryTmpl = `SELECT a.* FROM notifications as a %s;`
  27. NotificationQuerySumCountTmpl = `
  28. SELECT
  29. CASE
  30. WHEN SUM(trigger_count) > 0
  31. THEN SUM(trigger_count)
  32. ELSE 0
  33. END
  34. FROM notifications %s;`
  35. NotificationNamedInsertTmpl = `
  36. INSERT INTO notifications (
  37. created_at, updated_at, trigger_count, type, reviewed, pattern_id
  38. ) VALUES (
  39. now(), now(), 1, :type, :reviewed, :pattern_id
  40. ) RETURNING id;`
  41. NotificationNamedUpdateTmpl = `
  42. UPDATE notifications
  43. SET updated_at=now(), reviewed=:reviewed, trigger_count=:trigger_count
  44. WHERE %s;`
  45. )
  46. type Notification struct {
  47. ID uint `db:"id" json:"id"`
  48. CreatedAt time.Time `db:"created_at" json:"createdAt"`
  49. UpdatedAt time.Time `db:"updated_at" json:"updatedAt"`
  50. TriggerCount uint `db:"trigger_count" json:"triggerCount"`
  51. Type types.NFQActionType `db:"type" json:"type"`
  52. Reviewed bool `db:"reviewed" json:"reviewed"`
  53. PatternID uint `db:"pattern_id" json:"patternId"`
  54. // can be loaded with PreLoad function
  55. Pattern *Pattern `db:"-" json:"-"`
  56. }
  57. type Notifications []*Notification
  58. func NewNotification() *Notification {
  59. return &Notification{
  60. CreatedAt: time.Now(),
  61. UpdatedAt: time.Now(),
  62. TriggerCount: 1,
  63. Reviewed: false,
  64. }
  65. }
  66. func NotificationCount(count *int) error {
  67. db, err := sqlx.Connect(dbDriver, dbConnect)
  68. if err != nil {
  69. return err
  70. }
  71. defer db.Close()
  72. return db.Get(count, fmt.Sprintf(NotificationQuerySumCountTmpl, ""))
  73. }
  74. func (notifications Notifications) PreLoad() error {
  75. for _, notification := range notifications {
  76. err := notification.PreLoad()
  77. if err != nil {
  78. return err
  79. }
  80. }
  81. return nil
  82. }
  83. func (notification *Notification) PreLoad() error {
  84. var pattern Pattern
  85. err := pattern.FindByID(notification.PatternID)
  86. notification.Pattern = &pattern
  87. return err
  88. }
  89. func (notification *Notification) FindByID() error {
  90. db, err := sqlx.Connect(dbDriver, dbConnect)
  91. if err != nil {
  92. return err
  93. }
  94. defer db.Close()
  95. err = db.Get(notification,
  96. fmt.Sprintf(NotificationQueryTmpl, "WHERE a.id=$1"), notification.ID)
  97. if err != nil {
  98. return err
  99. }
  100. return notification.PreLoad()
  101. }
  102. func (notifications *Notifications) FindOutOfSync(migration PortalMigration) error {
  103. db, err := sqlx.Connect(dbDriver, dbConnect)
  104. if err != nil {
  105. return err
  106. }
  107. defer db.Close()
  108. err = db.Select(notifications,
  109. fmt.Sprintf(NotificationQueryTmpl, "WHERE a.updated_at > $1"),
  110. migration.Version,
  111. ); if err != nil {
  112. return err
  113. }
  114. return notifications.PreLoad()
  115. }
  116. // Exists directly updates the struct with the findings
  117. func (notification *Notification) Exists() bool {
  118. db, err := sqlx.Connect(dbDriver, dbConnect)
  119. if err != nil {
  120. logger.Error().Err(err).Msg("cannot open database")
  121. return false
  122. }
  123. defer db.Close()
  124. // NOTE only overwrite if found
  125. dbNotification := Notification{}
  126. err = db.Get(&dbNotification, fmt.Sprintf(NotificationQueryTmpl,
  127. "WHERE a.pattern_id=$1 OR a.id=$2"), notification.PatternID, notification.ID)
  128. if err == nil {
  129. *notification = dbNotification
  130. err = notification.PreLoad()
  131. if err != nil {
  132. logger.Warn().Err(err).Msg("cannot preload notification struct")
  133. }
  134. return true
  135. }
  136. return false
  137. }
  138. func (notification *Notification) Update() error {
  139. db, err := sqlx.Connect(dbDriver, dbConnect)
  140. if err != nil {
  141. return err
  142. }
  143. defer db.Close()
  144. _, err = db.NamedExec(fmt.Sprintf(NotificationNamedUpdateTmpl,
  145. "id=:id OR pattern_id=:pattern_id"), notification)
  146. return err
  147. }
  148. func (notification *Notification) Create() error {
  149. db, err := sqlx.Connect(dbDriver, dbConnect)
  150. if err != nil {
  151. return err
  152. }
  153. defer db.Close()
  154. rows, err := db.NamedQuery(NotificationNamedInsertTmpl, notification)
  155. if err != nil {
  156. return err
  157. }
  158. defer rows.Close()
  159. for rows.Next() {
  160. err = rows.Scan(&notification.ID)
  161. if err != nil {
  162. return err
  163. }
  164. }
  165. return nil
  166. }