web_push.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package server
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "github.com/SherClockHolmes/webpush-go"
  6. _ "github.com/mattn/go-sqlite3" // SQLite driver
  7. )
  8. const (
  9. createWebPushSubscriptionsTableQuery = `
  10. BEGIN;
  11. CREATE TABLE IF NOT EXISTS subscriptions (
  12. id INTEGER PRIMARY KEY AUTOINCREMENT,
  13. topic TEXT NOT NULL,
  14. user_id TEXT,
  15. endpoint TEXT NOT NULL,
  16. key_auth TEXT NOT NULL,
  17. key_p256dh TEXT NOT NULL,
  18. updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
  19. );
  20. CREATE INDEX IF NOT EXISTS idx_topic ON subscriptions (topic);
  21. CREATE INDEX IF NOT EXISTS idx_endpoint ON subscriptions (endpoint);
  22. CREATE UNIQUE INDEX IF NOT EXISTS idx_topic_endpoint ON subscriptions (topic, endpoint);
  23. COMMIT;
  24. `
  25. insertWebPushSubscriptionQuery = `
  26. INSERT OR REPLACE INTO subscriptions (topic, user_id, endpoint, key_auth, key_p256dh)
  27. VALUES (?, ?, ?, ?, ?)
  28. `
  29. deleteWebPushSubscriptionByEndpointQuery = `DELETE FROM subscriptions WHERE endpoint = ?`
  30. deleteWebPushSubscriptionByUserIDQuery = `DELETE FROM subscriptions WHERE user_id = ?`
  31. deleteWebPushSubscriptionByTopicAndEndpointQuery = `DELETE FROM subscriptions WHERE topic = ? AND endpoint = ?`
  32. selectWebPushSubscriptionsForTopicQuery = `SELECT endpoint, key_auth, key_p256dh, user_id FROM subscriptions WHERE topic = ?`
  33. selectWebPushSubscriptionsCountQuery = `SELECT COUNT(*) FROM subscriptions`
  34. )
  35. type webPushStore struct {
  36. db *sql.DB
  37. }
  38. func newWebPushStore(filename string) (*webPushStore, error) {
  39. db, err := sql.Open("sqlite3", filename)
  40. if err != nil {
  41. return nil, err
  42. }
  43. if err := setupSubscriptionsDB(db); err != nil {
  44. return nil, err
  45. }
  46. return &webPushStore{
  47. db: db,
  48. }, nil
  49. }
  50. func setupSubscriptionsDB(db *sql.DB) error {
  51. // If 'subscriptions' table does not exist, this must be a new database
  52. rowsMC, err := db.Query(selectWebPushSubscriptionsCountQuery)
  53. if err != nil {
  54. return setupNewSubscriptionsDB(db)
  55. }
  56. return rowsMC.Close()
  57. }
  58. func setupNewSubscriptionsDB(db *sql.DB) error {
  59. if _, err := db.Exec(createWebPushSubscriptionsTableQuery); err != nil {
  60. return err
  61. }
  62. return nil
  63. }
  64. func (c *webPushStore) UpdateSubscriptions(topics []string, userID string, subscription webpush.Subscription) error {
  65. fmt.Printf("AAA")
  66. tx, err := c.db.Begin()
  67. if err != nil {
  68. return err
  69. }
  70. defer tx.Rollback()
  71. if err = c.RemoveByEndpoint(subscription.Endpoint); err != nil {
  72. return err
  73. }
  74. for _, topic := range topics {
  75. if err := c.AddSubscription(topic, userID, subscription); err != nil {
  76. return err
  77. }
  78. }
  79. return tx.Commit()
  80. }
  81. func (c *webPushStore) AddSubscription(topic string, userID string, subscription webpush.Subscription) error {
  82. _, err := c.db.Exec(
  83. insertWebPushSubscriptionQuery,
  84. topic,
  85. userID,
  86. subscription.Endpoint,
  87. subscription.Keys.Auth,
  88. subscription.Keys.P256dh,
  89. )
  90. return err
  91. }
  92. func (c *webPushStore) SubscriptionsForTopic(topic string) (subscriptions []webPushSubscription, err error) {
  93. rows, err := c.db.Query(selectWebPushSubscriptionsForTopicQuery, topic)
  94. if err != nil {
  95. return nil, err
  96. }
  97. defer rows.Close()
  98. var data []webPushSubscription
  99. for rows.Next() {
  100. i := webPushSubscription{}
  101. err = rows.Scan(&i.BrowserSubscription.Endpoint, &i.BrowserSubscription.Keys.Auth, &i.BrowserSubscription.Keys.P256dh, &i.UserID)
  102. if err != nil {
  103. return nil, err
  104. }
  105. data = append(data, i)
  106. }
  107. return data, nil
  108. }
  109. func (c *webPushStore) RemoveByEndpoint(endpoint string) error {
  110. _, err := c.db.Exec(
  111. deleteWebPushSubscriptionByEndpointQuery,
  112. endpoint,
  113. )
  114. return err
  115. }
  116. func (c *webPushStore) RemoveByUserID(userID string) error {
  117. _, err := c.db.Exec(
  118. deleteWebPushSubscriptionByUserIDQuery,
  119. userID,
  120. )
  121. return err
  122. }
  123. func (c *webPushStore) Close() error {
  124. return c.db.Close()
  125. }