install.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "strings"
  8. "time"
  9. "github.com/jmoiron/sqlx"
  10. "github.com/knadh/goyesql"
  11. "github.com/knadh/listmonk/models"
  12. "github.com/lib/pq"
  13. uuid "github.com/satori/go.uuid"
  14. )
  15. // install runs the first time setup of creating and
  16. // migrating the database and creating the super user.
  17. func install(app *App, qMap goyesql.Queries) {
  18. fmt.Println("")
  19. fmt.Println("** First time installation **")
  20. fmt.Printf("** IMPORTANT: This will wipe existing listmonk tables and types in the DB '%s' **",
  21. ko.String("db.database"))
  22. fmt.Println("")
  23. var ok string
  24. fmt.Print("Continue (y/n)? ")
  25. if _, err := fmt.Scanf("%s", &ok); err != nil {
  26. logger.Fatalf("Error reading value from terminal: %v", err)
  27. }
  28. if strings.ToLower(ok) != "y" {
  29. fmt.Println("Installation cancelled.")
  30. return
  31. }
  32. // Migrate the tables.
  33. err := installMigrate(app.DB, app)
  34. if err != nil {
  35. logger.Fatalf("Error migrating DB schema: %v", err)
  36. }
  37. // Load the queries.
  38. var q Queries
  39. if err := scanQueriesToStruct(&q, qMap, app.DB.Unsafe()); err != nil {
  40. logger.Fatalf("error loading SQL queries: %v", err)
  41. }
  42. // Sample list.
  43. var listID int
  44. if err := q.CreateList.Get(&listID,
  45. uuid.NewV4().String(),
  46. "Default list",
  47. models.ListTypePublic,
  48. pq.StringArray{"test"},
  49. ); err != nil {
  50. logger.Fatalf("Error creating superadmin user: %v", err)
  51. }
  52. // Sample subscriber.
  53. if _, err := q.UpsertSubscriber.Exec(
  54. uuid.NewV4(),
  55. "john@example.com",
  56. "John Doe",
  57. `{"type": "known", "good": true, "city": "Bengaluru"}`,
  58. pq.Int64Array{int64(listID)},
  59. ); err != nil {
  60. logger.Fatalf("Error creating subscriber: %v", err)
  61. }
  62. // Default template.
  63. tplBody, err := ioutil.ReadFile("email-templates/default.tpl")
  64. if err != nil {
  65. tplBody = []byte(tplTag)
  66. }
  67. var tplID int
  68. if err := q.CreateTemplate.Get(&tplID,
  69. "Default template",
  70. string(tplBody),
  71. ); err != nil {
  72. logger.Fatalf("error creating default template: %v", err)
  73. }
  74. if _, err := q.SetDefaultTemplate.Exec(tplID); err != nil {
  75. logger.Fatalf("error setting default template: %v", err)
  76. }
  77. // Sample campaign.
  78. sendAt := time.Now()
  79. sendAt.Add(time.Minute * 43200)
  80. if _, err := q.CreateCampaign.Exec(uuid.NewV4(),
  81. "Test campaign",
  82. "Welcome to listmonk",
  83. "noreply@yoursite.com",
  84. `<h3>Hi {{ .Subscriber.FirstName }}!</h3>
  85. This is a test e-mail campaign. Your second name is {{ .Subscriber.LastName }} and you are from {{ .Subscriber.Attribs.city }}.`,
  86. "richtext",
  87. sendAt,
  88. pq.StringArray{"test-campaign"},
  89. "email",
  90. 1,
  91. pq.Int64Array{1},
  92. ); err != nil {
  93. logger.Fatalf("error creating sample campaign: %v", err)
  94. }
  95. logger.Printf("Setup complete")
  96. logger.Printf(`Run the program view it at %s`, ko.String("app.address"))
  97. }
  98. // installMigrate executes the SQL schema and creates the necessary tables and types.
  99. func installMigrate(db *sqlx.DB, app *App) error {
  100. q, err := app.FS.Read("/schema.sql")
  101. if err != nil {
  102. return err
  103. }
  104. _, err = db.Query(string(q))
  105. if err != nil {
  106. return err
  107. }
  108. return nil
  109. }
  110. func newConfigFile() error {
  111. if _, err := os.Stat("config.toml"); !os.IsNotExist(err) {
  112. return errors.New("config.toml exists. Remove it to generate a new one")
  113. }
  114. // Initialize the static file system into which all
  115. // required static assets (.sql, .js files etc.) are loaded.
  116. fs, err := initFileSystem(os.Args[0])
  117. if err != nil {
  118. return err
  119. }
  120. b, err := fs.Read("config.toml.sample")
  121. if err != nil {
  122. return fmt.Errorf("error reading sample config (is binary stuffed?): %v", err)
  123. }
  124. ioutil.WriteFile("config.toml", b, 0644)
  125. return nil
  126. }