v2.0.0.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package migrations
  2. import (
  3. "github.com/jmoiron/sqlx"
  4. "github.com/knadh/koanf"
  5. "github.com/knadh/stuffbin"
  6. )
  7. // V2_0_0 performs the DB migrations for v.1.0.0.
  8. func V2_0_0(db *sqlx.DB, fs stuffbin.FileSystem, ko *koanf.Koanf) error {
  9. if _, err := db.Exec(`
  10. DO $$
  11. BEGIN
  12. IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'bounce_type') THEN
  13. CREATE TYPE bounce_type AS ENUM ('soft', 'hard', 'complaint');
  14. END IF;
  15. END$$;
  16. `); err != nil {
  17. return err
  18. }
  19. if _, err := db.Exec(`
  20. CREATE TABLE IF NOT EXISTS bounces (
  21. id SERIAL PRIMARY KEY,
  22. subscriber_id INTEGER NOT NULL REFERENCES subscribers(id) ON DELETE CASCADE ON UPDATE CASCADE,
  23. campaign_id INTEGER NULL REFERENCES campaigns(id) ON DELETE SET NULL ON UPDATE CASCADE,
  24. type bounce_type NOT NULL DEFAULT 'hard',
  25. source TEXT NOT NULL DEFAULT '',
  26. meta JSONB NOT NULL DEFAULT '{}',
  27. created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
  28. );
  29. CREATE INDEX IF NOT EXISTS idx_bounces_sub_id ON bounces(subscriber_id);
  30. CREATE INDEX IF NOT EXISTS idx_bounces_camp_id ON bounces(campaign_id);
  31. CREATE INDEX IF NOT EXISTS idx_bounces_source ON bounces(source);
  32. `); err != nil {
  33. return err
  34. }
  35. if _, err := db.Exec(`
  36. INSERT INTO settings (key, value) VALUES
  37. ('bounce.enabled', 'false'),
  38. ('bounce.webhooks_enabled', 'false'),
  39. ('bounce.count', '2'),
  40. ('bounce.action', '"blocklist"'),
  41. ('bounce.ses_enabled', 'false'),
  42. ('bounce.sendgrid_enabled', 'false'),
  43. ('bounce.sendgrid_key', '""'),
  44. ('bounce.mailboxes', '[{"enabled":false, "type": "pop", "host":"pop.yoursite.com","port":995,"auth_protocol":"userpass","username":"username","password":"password","return_path": "bounce@listmonk.yoursite.com","scan_interval":"15m","tls_enabled":true,"tls_skip_verify":false}]')
  45. ON CONFLICT DO NOTHING;`); err != nil {
  46. return err
  47. }
  48. if _, err := db.Exec(`ALTER TABLE subscribers DROP COLUMN IF EXISTS campaigns`); err != nil {
  49. return err
  50. }
  51. if _, err := db.Exec(`
  52. DO $$
  53. BEGIN
  54. IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'campaign_views_pkey') THEN
  55. ALTER TABLE campaign_views ADD COLUMN IF NOT EXISTS id BIGSERIAL PRIMARY KEY;
  56. END IF;
  57. IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'link_clicks_pkey') THEN
  58. ALTER TABLE link_clicks ADD COLUMN IF NOT EXISTS id BIGSERIAL PRIMARY KEY;
  59. END IF;
  60. IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'campaign_lists_pkey') THEN
  61. ALTER TABLE campaign_lists ADD COLUMN IF NOT EXISTS id BIGSERIAL PRIMARY KEY;
  62. END IF;
  63. END$$;
  64. CREATE INDEX IF NOT EXISTS idx_views_date ON campaign_views((TIMEZONE('UTC', created_at)::DATE));
  65. CREATE INDEX IF NOT EXISTS idx_clicks_date ON link_clicks((TIMEZONE('UTC', created_at)::DATE));
  66. `); err != nil {
  67. return err
  68. }
  69. // S3 URL i snow a settings field. Prepare S3 URL based on region and bucket.
  70. if _, err := db.Exec(`
  71. WITH region AS (
  72. SELECT value#>>'{}' AS value FROM settings WHERE key='upload.s3.aws_default_region'
  73. ), s3url AS (
  74. SELECT FORMAT('https://s3.%s.amazonaws.com', (SELECT value FROM region)) AS value
  75. )
  76. INSERT INTO settings (key, value) VALUES ('upload.s3.url', TO_JSON((SELECT * FROM s3url))) ON CONFLICT DO NOTHING;`); err != nil {
  77. return err
  78. }
  79. return nil
  80. }