Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

import.go 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "encoding/json"
  6. "fmt"
  7. "io/ioutil"
  8. "log"
  9. "strconv"
  10. "strings"
  11. "github.com/tidwall/buntdb"
  12. "github.com/oragono/oragono/irc/utils"
  13. )
  14. type userImport struct {
  15. Name string
  16. Hash string
  17. Email string
  18. RegisteredAt int64 `json:"registeredAt"`
  19. Vhost string
  20. AdditionalNicks []string `json:"additionalNicks"`
  21. RegisteredChannels []string
  22. }
  23. type channelImport struct {
  24. Name string
  25. Founder string
  26. RegisteredAt int64 `json:"registeredAt"`
  27. Topic string
  28. TopicSetBy string `json:"topicSetBy"`
  29. TopicSetAt int64 `json:"topicSetAt"`
  30. Amode map[string]int
  31. }
  32. type databaseImport struct {
  33. Version int
  34. Source string
  35. Users map[string]userImport
  36. Channels map[string]channelImport
  37. }
  38. func doImportAthemeDB(config *Config, dbImport databaseImport, tx *buntdb.Tx) (err error) {
  39. requiredVersion := 1
  40. if dbImport.Version != requiredVersion {
  41. return fmt.Errorf("unsupported version of the db for import: version %d is required", requiredVersion)
  42. }
  43. // produce a hardcoded version of the database schema
  44. // XXX instead of referencing, e.g., keyAccountExists, we should write in the string literal
  45. // (to ensure that no matter what code changes happen elsewhere, we're still producing a
  46. // version 14 db)
  47. tx.Set(keySchemaVersion, "14", nil)
  48. tx.Set(keyCloakSecret, utils.GenerateSecretKey(), nil)
  49. for username, userInfo := range dbImport.Users {
  50. cfUsername, err := CasefoldName(username)
  51. if err != nil {
  52. log.Printf("invalid username %s: %v", username, err)
  53. continue
  54. }
  55. credentials := AccountCredentials{
  56. Version: CredentialsAtheme,
  57. PassphraseHash: []byte(userInfo.Hash),
  58. }
  59. marshaledCredentials, err := json.Marshal(&credentials)
  60. if err != nil {
  61. log.Printf("invalid credentials for %s: %v", username, err)
  62. continue
  63. }
  64. tx.Set(fmt.Sprintf(keyAccountExists, cfUsername), "1", nil)
  65. tx.Set(fmt.Sprintf(keyAccountVerified, cfUsername), "1", nil)
  66. tx.Set(fmt.Sprintf(keyAccountName, cfUsername), userInfo.Name, nil)
  67. tx.Set(fmt.Sprintf(keyAccountCallback, cfUsername), "mailto:"+userInfo.Email, nil)
  68. tx.Set(fmt.Sprintf(keyAccountCredentials, cfUsername), string(marshaledCredentials), nil)
  69. tx.Set(fmt.Sprintf(keyAccountRegTime, cfUsername), strconv.FormatInt(userInfo.RegisteredAt, 10), nil)
  70. if userInfo.Vhost != "" {
  71. tx.Set(fmt.Sprintf(keyAccountVHost, cfUsername), userInfo.Vhost, nil)
  72. }
  73. if len(userInfo.AdditionalNicks) != 0 {
  74. tx.Set(fmt.Sprintf(keyAccountAdditionalNicks, cfUsername), marshalReservedNicks(userInfo.AdditionalNicks), nil)
  75. }
  76. if len(userInfo.RegisteredChannels) != 0 {
  77. tx.Set(fmt.Sprintf(keyAccountChannels, cfUsername), strings.Join(userInfo.RegisteredChannels, ","), nil)
  78. }
  79. }
  80. for chname, chInfo := range dbImport.Channels {
  81. cfchname, err := CasefoldChannel(chname)
  82. if err != nil {
  83. log.Printf("invalid channel name %s: %v", chname, err)
  84. continue
  85. }
  86. tx.Set(fmt.Sprintf(keyChannelExists, cfchname), "1", nil)
  87. tx.Set(fmt.Sprintf(keyChannelName, cfchname), chname, nil)
  88. tx.Set(fmt.Sprintf(keyChannelRegTime, cfchname), strconv.FormatInt(chInfo.RegisteredAt, 10), nil)
  89. tx.Set(fmt.Sprintf(keyChannelFounder, cfchname), chInfo.Founder, nil)
  90. if chInfo.Topic != "" {
  91. tx.Set(fmt.Sprintf(keyChannelTopic, cfchname), chInfo.Topic, nil)
  92. tx.Set(fmt.Sprintf(keyChannelTopicSetTime, cfchname), strconv.FormatInt(chInfo.TopicSetAt, 10), nil)
  93. tx.Set(fmt.Sprintf(keyChannelTopicSetBy, cfchname), chInfo.TopicSetBy, nil)
  94. }
  95. if len(chInfo.Amode) != 0 {
  96. m, err := json.Marshal(chInfo.Amode)
  97. if err == nil {
  98. tx.Set(fmt.Sprintf(keyChannelAccountToUMode, cfchname), string(m), nil)
  99. } else {
  100. log.Printf("couldn't serialize amodes for %s: %v", chname, err)
  101. }
  102. }
  103. }
  104. return nil
  105. }
  106. func doImportDB(config *Config, dbImport databaseImport, tx *buntdb.Tx) (err error) {
  107. switch dbImport.Source {
  108. case "atheme":
  109. return doImportAthemeDB(config, dbImport, tx)
  110. default:
  111. return fmt.Errorf("only imports from atheme are currently supported")
  112. }
  113. }
  114. func ImportDB(config *Config, infile string) (err error) {
  115. data, err := ioutil.ReadFile(infile)
  116. if err != nil {
  117. return
  118. }
  119. var dbImport databaseImport
  120. err = json.Unmarshal(data, &dbImport)
  121. if err != nil {
  122. return err
  123. }
  124. err = checkDBReadyForInit(config.Datastore.Path)
  125. if err != nil {
  126. return err
  127. }
  128. db, err := buntdb.Open(config.Datastore.Path)
  129. if err != nil {
  130. return err
  131. }
  132. performImport := func(tx *buntdb.Tx) (err error) {
  133. return doImportDB(config, dbImport, tx)
  134. }
  135. return db.Update(performImport)
  136. }