PageRenderTime 1589ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/store/sql_store.go

https://gitlab.com/Realtyka/platform
Go | 761 lines | 610 code | 131 blank | 20 comment | 160 complexity | 9d29ce7dfbebf059f9c2bfb8dfdf0f08 MD5 | raw file
  1. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
  2. // See License.txt for license information.
  3. package store
  4. import (
  5. "crypto/aes"
  6. "crypto/cipher"
  7. "crypto/hmac"
  8. crand "crypto/rand"
  9. "crypto/sha256"
  10. "crypto/sha512"
  11. dbsql "database/sql"
  12. "encoding/base64"
  13. "encoding/json"
  14. "errors"
  15. "fmt"
  16. l4g "github.com/alecthomas/log4go"
  17. "io"
  18. sqltrace "log"
  19. "math/rand"
  20. "os"
  21. "strings"
  22. "time"
  23. "github.com/go-gorp/gorp"
  24. _ "github.com/go-sql-driver/mysql"
  25. _ "github.com/lib/pq"
  26. "github.com/mattermost/platform/model"
  27. "github.com/mattermost/platform/utils"
  28. )
  29. const (
  30. INDEX_TYPE_FULL_TEXT = "full_text"
  31. INDEX_TYPE_DEFAULT = "default"
  32. )
  33. type SqlStore struct {
  34. master *gorp.DbMap
  35. replicas []*gorp.DbMap
  36. team TeamStore
  37. channel ChannelStore
  38. post PostStore
  39. user UserStore
  40. audit AuditStore
  41. session SessionStore
  42. oauth OAuthStore
  43. system SystemStore
  44. webhook WebhookStore
  45. command CommandStore
  46. preference PreferenceStore
  47. license LicenseStore
  48. }
  49. func NewSqlStore() Store {
  50. sqlStore := &SqlStore{}
  51. sqlStore.master = setupConnection("master", utils.Cfg.SqlSettings.DriverName,
  52. utils.Cfg.SqlSettings.DataSource, utils.Cfg.SqlSettings.MaxIdleConns,
  53. utils.Cfg.SqlSettings.MaxOpenConns, utils.Cfg.SqlSettings.Trace)
  54. if len(utils.Cfg.SqlSettings.DataSourceReplicas) == 0 {
  55. sqlStore.replicas = make([]*gorp.DbMap, 1)
  56. sqlStore.replicas[0] = setupConnection(fmt.Sprintf("replica-%v", 0), utils.Cfg.SqlSettings.DriverName, utils.Cfg.SqlSettings.DataSource,
  57. utils.Cfg.SqlSettings.MaxIdleConns, utils.Cfg.SqlSettings.MaxOpenConns,
  58. utils.Cfg.SqlSettings.Trace)
  59. } else {
  60. sqlStore.replicas = make([]*gorp.DbMap, len(utils.Cfg.SqlSettings.DataSourceReplicas))
  61. for i, replica := range utils.Cfg.SqlSettings.DataSourceReplicas {
  62. sqlStore.replicas[i] = setupConnection(fmt.Sprintf("replica-%v", i), utils.Cfg.SqlSettings.DriverName, replica,
  63. utils.Cfg.SqlSettings.MaxIdleConns, utils.Cfg.SqlSettings.MaxOpenConns,
  64. utils.Cfg.SqlSettings.Trace)
  65. }
  66. }
  67. schemaVersion := sqlStore.GetCurrentSchemaVersion()
  68. // If the version is already set then we are potentially in an 'upgrade needed' state
  69. if schemaVersion != "" {
  70. // Check to see if it's the most current database schema version
  71. if !model.IsCurrentVersion(schemaVersion) {
  72. // If we are upgrading from the previous version then print a warning and continue
  73. if model.IsPreviousVersionsSupported(schemaVersion) {
  74. l4g.Warn(utils.T("store.sql.schema_out_of_date.warn"), schemaVersion)
  75. l4g.Warn(utils.T("store.sql.schema_upgrade_attempt.warn"), model.CurrentVersion)
  76. } else {
  77. // If this is an 'upgrade needed' state but the user is attempting to skip a version then halt the world
  78. l4g.Critical(utils.T("store.sql.schema_version.critical"), schemaVersion)
  79. time.Sleep(time.Second)
  80. panic(fmt.Sprintf(utils.T("store.sql.schema_version.critical"), schemaVersion))
  81. }
  82. }
  83. }
  84. sqlStore.team = NewSqlTeamStore(sqlStore)
  85. sqlStore.channel = NewSqlChannelStore(sqlStore)
  86. sqlStore.post = NewSqlPostStore(sqlStore)
  87. sqlStore.user = NewSqlUserStore(sqlStore)
  88. sqlStore.audit = NewSqlAuditStore(sqlStore)
  89. sqlStore.session = NewSqlSessionStore(sqlStore)
  90. sqlStore.oauth = NewSqlOAuthStore(sqlStore)
  91. sqlStore.system = NewSqlSystemStore(sqlStore)
  92. sqlStore.webhook = NewSqlWebhookStore(sqlStore)
  93. sqlStore.command = NewSqlCommandStore(sqlStore)
  94. sqlStore.preference = NewSqlPreferenceStore(sqlStore)
  95. sqlStore.license = NewSqlLicenseStore(sqlStore)
  96. err := sqlStore.master.CreateTablesIfNotExists()
  97. if err != nil {
  98. l4g.Critical(utils.T("store.sql.creating_tables.critical"), err)
  99. }
  100. sqlStore.team.(*SqlTeamStore).UpgradeSchemaIfNeeded()
  101. sqlStore.channel.(*SqlChannelStore).UpgradeSchemaIfNeeded()
  102. sqlStore.post.(*SqlPostStore).UpgradeSchemaIfNeeded()
  103. sqlStore.user.(*SqlUserStore).UpgradeSchemaIfNeeded()
  104. sqlStore.audit.(*SqlAuditStore).UpgradeSchemaIfNeeded()
  105. sqlStore.session.(*SqlSessionStore).UpgradeSchemaIfNeeded()
  106. sqlStore.oauth.(*SqlOAuthStore).UpgradeSchemaIfNeeded()
  107. sqlStore.system.(*SqlSystemStore).UpgradeSchemaIfNeeded()
  108. sqlStore.webhook.(*SqlWebhookStore).UpgradeSchemaIfNeeded()
  109. sqlStore.command.(*SqlCommandStore).UpgradeSchemaIfNeeded()
  110. sqlStore.preference.(*SqlPreferenceStore).UpgradeSchemaIfNeeded()
  111. sqlStore.license.(*SqlLicenseStore).UpgradeSchemaIfNeeded()
  112. sqlStore.team.(*SqlTeamStore).CreateIndexesIfNotExists()
  113. sqlStore.channel.(*SqlChannelStore).CreateIndexesIfNotExists()
  114. sqlStore.post.(*SqlPostStore).CreateIndexesIfNotExists()
  115. sqlStore.user.(*SqlUserStore).CreateIndexesIfNotExists()
  116. sqlStore.audit.(*SqlAuditStore).CreateIndexesIfNotExists()
  117. sqlStore.session.(*SqlSessionStore).CreateIndexesIfNotExists()
  118. sqlStore.oauth.(*SqlOAuthStore).CreateIndexesIfNotExists()
  119. sqlStore.system.(*SqlSystemStore).CreateIndexesIfNotExists()
  120. sqlStore.webhook.(*SqlWebhookStore).CreateIndexesIfNotExists()
  121. sqlStore.command.(*SqlCommandStore).CreateIndexesIfNotExists()
  122. sqlStore.preference.(*SqlPreferenceStore).CreateIndexesIfNotExists()
  123. sqlStore.license.(*SqlLicenseStore).CreateIndexesIfNotExists()
  124. sqlStore.preference.(*SqlPreferenceStore).DeleteUnusedFeatures()
  125. if model.IsPreviousVersionsSupported(schemaVersion) && !model.IsCurrentVersion(schemaVersion) {
  126. sqlStore.system.Update(&model.System{Name: "Version", Value: model.CurrentVersion})
  127. l4g.Warn(utils.T("store.sql.upgraded.warn"), model.CurrentVersion)
  128. }
  129. if schemaVersion == "" {
  130. sqlStore.system.Save(&model.System{Name: "Version", Value: model.CurrentVersion})
  131. l4g.Info(utils.T("store.sql.schema_set.info"), model.CurrentVersion)
  132. }
  133. return sqlStore
  134. }
  135. func setupConnection(con_type string, driver string, dataSource string, maxIdle int, maxOpen int, trace bool) *gorp.DbMap {
  136. db, err := dbsql.Open(driver, dataSource)
  137. if err != nil {
  138. l4g.Critical(utils.T("store.sql.open_conn.critical"), err)
  139. time.Sleep(time.Second)
  140. panic(fmt.Sprintf(utils.T("store.sql.open_conn.critical"), err.Error()))
  141. }
  142. l4g.Info(utils.T("store.sql.pinging.info"), con_type)
  143. err = db.Ping()
  144. if err != nil {
  145. l4g.Critical(utils.T("store.sql.ping.critical"), err)
  146. time.Sleep(time.Second)
  147. panic(fmt.Sprintf(utils.T("store.sql.open_conn.panic"), err.Error()))
  148. }
  149. db.SetMaxIdleConns(maxIdle)
  150. db.SetMaxOpenConns(maxOpen)
  151. var dbmap *gorp.DbMap
  152. if driver == "sqlite3" {
  153. dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}}
  154. } else if driver == model.DATABASE_DRIVER_MYSQL {
  155. dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}}
  156. } else if driver == model.DATABASE_DRIVER_POSTGRES {
  157. dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.PostgresDialect{}}
  158. } else {
  159. l4g.Critical(utils.T("store.sql.dialect_driver.critical"))
  160. time.Sleep(time.Second)
  161. panic(fmt.Sprintf(utils.T("store.sql.dialect_driver.panic"), err.Error()))
  162. }
  163. if trace {
  164. dbmap.TraceOn("", sqltrace.New(os.Stdout, "sql-trace:", sqltrace.Lmicroseconds))
  165. }
  166. return dbmap
  167. }
  168. func (ss SqlStore) GetCurrentSchemaVersion() string {
  169. version, _ := ss.GetMaster().SelectStr("SELECT Value FROM Systems WHERE Name='Version'")
  170. return version
  171. }
  172. func (ss SqlStore) MarkSystemRanUnitTests() {
  173. if result := <-ss.System().Get(); result.Err == nil {
  174. props := result.Data.(model.StringMap)
  175. unitTests := props[model.SYSTEM_RAN_UNIT_TESTS]
  176. if len(unitTests) == 0 {
  177. systemTests := &model.System{Name: model.SYSTEM_RAN_UNIT_TESTS, Value: "1"}
  178. <-ss.System().Save(systemTests)
  179. }
  180. }
  181. }
  182. func (ss SqlStore) DoesTableExist(tableName string) bool {
  183. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  184. count, err := ss.GetMaster().SelectInt(
  185. `SELECT count(relname) FROM pg_class WHERE relname=$1`,
  186. strings.ToLower(tableName),
  187. )
  188. if err != nil {
  189. l4g.Critical(utils.T("store.sql.table_exists.critical"), err)
  190. time.Sleep(time.Second)
  191. panic(fmt.Sprintf(utils.T("store.sql.table_exists.critical"), err.Error()))
  192. }
  193. return count > 0
  194. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  195. count, err := ss.GetMaster().SelectInt(
  196. `SELECT
  197. COUNT(0) AS table_exists
  198. FROM
  199. information_schema.TABLES
  200. WHERE
  201. TABLE_SCHEMA = DATABASE()
  202. AND TABLE_NAME = ?
  203. `,
  204. tableName,
  205. )
  206. if err != nil {
  207. l4g.Critical(utils.T("store.sql.table_exists.critical"), err)
  208. time.Sleep(time.Second)
  209. panic(fmt.Sprintf(utils.T("store.sql.table_exists.critical"), err.Error()))
  210. }
  211. return count > 0
  212. } else {
  213. l4g.Critical(utils.T("store.sql.column_exists_missing_driver.critical"))
  214. time.Sleep(time.Second)
  215. panic(utils.T("store.sql.column_exists_missing_driver.critical"))
  216. }
  217. }
  218. func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool {
  219. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  220. count, err := ss.GetMaster().SelectInt(
  221. `SELECT COUNT(0)
  222. FROM pg_attribute
  223. WHERE attrelid = $1::regclass
  224. AND attname = $2
  225. AND NOT attisdropped`,
  226. strings.ToLower(tableName),
  227. strings.ToLower(columnName),
  228. )
  229. if err != nil {
  230. if err.Error() == "pq: relation \""+strings.ToLower(tableName)+"\" does not exist" {
  231. return false
  232. }
  233. l4g.Critical(utils.T("store.sql.column_exists.critical"), err)
  234. time.Sleep(time.Second)
  235. panic(fmt.Sprintf(utils.T("store.sql.column_exists.critical"), err.Error()))
  236. }
  237. return count > 0
  238. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  239. count, err := ss.GetMaster().SelectInt(
  240. `SELECT
  241. COUNT(0) AS column_exists
  242. FROM
  243. information_schema.COLUMNS
  244. WHERE
  245. TABLE_SCHEMA = DATABASE()
  246. AND TABLE_NAME = ?
  247. AND COLUMN_NAME = ?`,
  248. tableName,
  249. columnName,
  250. )
  251. if err != nil {
  252. l4g.Critical(utils.T("store.sql.column_exists.critical"), err)
  253. time.Sleep(time.Second)
  254. panic(fmt.Sprintf(utils.T("store.sql.column_exists.critical"), err.Error()))
  255. }
  256. return count > 0
  257. } else {
  258. l4g.Critical(utils.T("store.sql.column_exists_missing_driver.critical"))
  259. time.Sleep(time.Second)
  260. panic(utils.T("store.sql.column_exists_missing_driver.critical"))
  261. }
  262. }
  263. func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, mySqlColType string, postgresColType string, defaultValue string) bool {
  264. if ss.DoesColumnExist(tableName, columnName) {
  265. return false
  266. }
  267. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  268. _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + postgresColType + " DEFAULT '" + defaultValue + "'")
  269. if err != nil {
  270. l4g.Critical(utils.T("store.sql.create_column.critical"), err)
  271. time.Sleep(time.Second)
  272. panic(fmt.Sprintf(utils.T("store.sql.create_column.critical"), err.Error()))
  273. }
  274. return true
  275. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  276. _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + mySqlColType + " DEFAULT '" + defaultValue + "'")
  277. if err != nil {
  278. l4g.Critical(utils.T("store.sql.create_column.critical"), err)
  279. time.Sleep(time.Second)
  280. panic(fmt.Sprintf(utils.T("store.sql.create_column.critical"), err.Error()))
  281. }
  282. return true
  283. } else {
  284. l4g.Critical(utils.T("store.sql.create_column_missing_driver.critical"))
  285. time.Sleep(time.Second)
  286. panic(utils.T("store.sql.create_column_missing_driver.critical"))
  287. }
  288. }
  289. func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
  290. if !ss.DoesColumnExist(tableName, columnName) {
  291. return false
  292. }
  293. _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
  294. if err != nil {
  295. l4g.Critical(utils.T("store.sql.drop_column.critical"), err)
  296. time.Sleep(time.Second)
  297. panic(fmt.Sprintf(utils.T("store.sql.drop_column.critical"), err.Error()))
  298. }
  299. return true
  300. }
  301. func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
  302. if !ss.DoesColumnExist(tableName, oldColumnName) {
  303. return false
  304. }
  305. var err error
  306. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  307. _, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType)
  308. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  309. _, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " RENAME COLUMN " + oldColumnName + " TO " + newColumnName)
  310. }
  311. if err != nil {
  312. l4g.Critical(utils.T("store.sql.rename_column.critical"), err)
  313. time.Sleep(time.Second)
  314. panic(fmt.Sprintf(utils.T("store.sql.rename_column.critical"), err.Error()))
  315. }
  316. return true
  317. }
  318. func (ss SqlStore) GetMaxLengthOfColumnIfExists(tableName string, columnName string) string {
  319. if !ss.DoesColumnExist(tableName, columnName) {
  320. return ""
  321. }
  322. var result string
  323. var err error
  324. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  325. result, err = ss.GetMaster().SelectStr("SELECT CHARACTER_MAXIMUM_LENGTH FROM information_schema.columns WHERE table_name = '" + tableName + "' AND COLUMN_NAME = '" + columnName + "'")
  326. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  327. result, err = ss.GetMaster().SelectStr("SELECT character_maximum_length FROM information_schema.columns WHERE table_name = '" + strings.ToLower(tableName) + "' AND column_name = '" + strings.ToLower(columnName) + "'")
  328. }
  329. if err != nil {
  330. l4g.Critical(utils.T("store.sql.maxlength_column.critical"), err)
  331. time.Sleep(time.Second)
  332. panic(fmt.Sprintf(utils.T("store.sql.maxlength_column.critical"), err.Error()))
  333. }
  334. return result
  335. }
  336. func (ss SqlStore) AlterColumnTypeIfExists(tableName string, columnName string, mySqlColType string, postgresColType string) bool {
  337. if !ss.DoesColumnExist(tableName, columnName) {
  338. return false
  339. }
  340. var err error
  341. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  342. _, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " MODIFY " + columnName + " " + mySqlColType)
  343. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  344. _, err = ss.GetMaster().Exec("ALTER TABLE " + strings.ToLower(tableName) + " ALTER COLUMN " + strings.ToLower(columnName) + " TYPE " + postgresColType)
  345. }
  346. if err != nil {
  347. l4g.Critical(utils.T("store.sql.alter_column_type.critical"), err)
  348. time.Sleep(time.Second)
  349. panic(fmt.Sprintf(utils.T("store.sql.alter_column_type.critical"), err.Error()))
  350. }
  351. return true
  352. }
  353. func (ss SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) {
  354. ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT)
  355. }
  356. func (ss SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName string, columnName string) {
  357. ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_FULL_TEXT)
  358. }
  359. func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, columnName string, indexType string) {
  360. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  361. _, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
  362. // It should fail if the index does not exist
  363. if err == nil {
  364. return
  365. }
  366. query := ""
  367. if indexType == INDEX_TYPE_FULL_TEXT {
  368. query = "CREATE INDEX " + indexName + " ON " + tableName + " USING gin(to_tsvector('english', " + columnName + "))"
  369. } else {
  370. query = "CREATE INDEX " + indexName + " ON " + tableName + " (" + columnName + ")"
  371. }
  372. _, err = ss.GetMaster().Exec(query)
  373. if err != nil {
  374. l4g.Critical(utils.T("store.sql.create_index.critical"), err)
  375. time.Sleep(time.Second)
  376. panic(fmt.Sprintf(utils.T("store.sql.create_index.critical"), err.Error()))
  377. }
  378. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  379. count, err := ss.GetMaster().SelectInt("SELECT COUNT(0) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = ? AND index_name = ?", tableName, indexName)
  380. if err != nil {
  381. l4g.Critical(utils.T("store.sql.check_index.critical"), err)
  382. time.Sleep(time.Second)
  383. panic(fmt.Sprintf(utils.T("store.sql.check_index.critical"), err.Error()))
  384. }
  385. if count > 0 {
  386. return
  387. }
  388. fullTextIndex := ""
  389. if indexType == INDEX_TYPE_FULL_TEXT {
  390. fullTextIndex = " FULLTEXT "
  391. }
  392. _, err = ss.GetMaster().Exec("CREATE " + fullTextIndex + " INDEX " + indexName + " ON " + tableName + " (" + columnName + ")")
  393. if err != nil {
  394. l4g.Critical(utils.T("store.sql.create_index.critical"), err)
  395. time.Sleep(time.Second)
  396. panic(fmt.Sprintf(utils.T("store.sql.create_index.critical"), err.Error()))
  397. }
  398. } else {
  399. l4g.Critical(utils.T("store.sql.create_index_missing_driver.critical"))
  400. time.Sleep(time.Second)
  401. panic(utils.T("store.sql.create_index_missing_driver.critical"))
  402. }
  403. }
  404. func (ss SqlStore) RemoveIndexIfExists(indexName string, tableName string) {
  405. if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
  406. _, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
  407. // It should fail if the index does not exist
  408. if err == nil {
  409. return
  410. }
  411. _, err = ss.GetMaster().Exec("DROP INDEX " + indexName)
  412. if err != nil {
  413. l4g.Critical(utils.T("store.sql.remove_index.critical"), err)
  414. time.Sleep(time.Second)
  415. panic(fmt.Sprintf(utils.T("store.sql.remove_index.critical"), err.Error()))
  416. }
  417. } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
  418. count, err := ss.GetMaster().SelectInt("SELECT COUNT(0) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = ? AND index_name = ?", tableName, indexName)
  419. if err != nil {
  420. l4g.Critical(utils.T("store.sql.check_index.critical"), err)
  421. time.Sleep(time.Second)
  422. panic(fmt.Sprintf(utils.T("store.sql.check_index.critical"), err.Error()))
  423. }
  424. if count > 0 {
  425. return
  426. }
  427. _, err = ss.GetMaster().Exec("DROP INDEX " + indexName + " ON " + tableName)
  428. if err != nil {
  429. l4g.Critical(utils.T("store.sql.remove_index.critical"), err)
  430. time.Sleep(time.Second)
  431. panic(fmt.Sprintf(utils.T("store.sql.remove_index.critical"), err.Error()))
  432. }
  433. } else {
  434. l4g.Critical(utils.T("store.sql.create_index_missing_driver.critical"))
  435. time.Sleep(time.Second)
  436. panic(utils.T("store.sql.create_index_missing_driver.critical"))
  437. }
  438. }
  439. func IsUniqueConstraintError(err string, mysql string, postgres string) bool {
  440. unique := strings.Contains(err, "unique constraint") || strings.Contains(err, "Duplicate entry")
  441. field := strings.Contains(err, mysql) || strings.Contains(err, postgres)
  442. return unique && field
  443. }
  444. // func (ss SqlStore) GetColumnDataType(tableName, columnName string) string {
  445. // dataType, err := ss.GetMaster().SelectStr("SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS where table_name = :Tablename AND column_name = :Columnname", map[string]interface{}{
  446. // "Tablename": tableName,
  447. // "Columnname": columnName,
  448. // })
  449. // if err != nil {
  450. // l4g.Critical(utils.T("store.sql.table_column_type.critical"), columnName, tableName, err.Error())
  451. // time.Sleep(time.Second)
  452. // panic(fmt.Sprintf(utils.T("store.sql.table_column_type.critical"), columnName, tableName, err.Error()))
  453. // }
  454. // return dataType
  455. // }
  456. func (ss SqlStore) GetMaster() *gorp.DbMap {
  457. return ss.master
  458. }
  459. func (ss SqlStore) GetReplica() *gorp.DbMap {
  460. return ss.replicas[rand.Intn(len(ss.replicas))]
  461. }
  462. func (ss SqlStore) GetAllConns() []*gorp.DbMap {
  463. all := make([]*gorp.DbMap, len(ss.replicas)+1)
  464. copy(all, ss.replicas)
  465. all[len(ss.replicas)] = ss.master
  466. return all
  467. }
  468. func (ss SqlStore) Close() {
  469. l4g.Info(utils.T("store.sql.closing.info"))
  470. ss.master.Db.Close()
  471. for _, replica := range ss.replicas {
  472. replica.Db.Close()
  473. }
  474. }
  475. func (ss SqlStore) Team() TeamStore {
  476. return ss.team
  477. }
  478. func (ss SqlStore) Channel() ChannelStore {
  479. return ss.channel
  480. }
  481. func (ss SqlStore) Post() PostStore {
  482. return ss.post
  483. }
  484. func (ss SqlStore) User() UserStore {
  485. return ss.user
  486. }
  487. func (ss SqlStore) Session() SessionStore {
  488. return ss.session
  489. }
  490. func (ss SqlStore) Audit() AuditStore {
  491. return ss.audit
  492. }
  493. func (ss SqlStore) OAuth() OAuthStore {
  494. return ss.oauth
  495. }
  496. func (ss SqlStore) System() SystemStore {
  497. return ss.system
  498. }
  499. func (ss SqlStore) Webhook() WebhookStore {
  500. return ss.webhook
  501. }
  502. func (ss SqlStore) Command() CommandStore {
  503. return ss.command
  504. }
  505. func (ss SqlStore) Preference() PreferenceStore {
  506. return ss.preference
  507. }
  508. func (ss SqlStore) License() LicenseStore {
  509. return ss.license
  510. }
  511. type mattermConverter struct{}
  512. func (me mattermConverter) ToDb(val interface{}) (interface{}, error) {
  513. switch t := val.(type) {
  514. case model.StringMap:
  515. return model.MapToJson(t), nil
  516. case model.StringArray:
  517. return model.ArrayToJson(t), nil
  518. case model.EncryptStringMap:
  519. return encrypt([]byte(utils.Cfg.SqlSettings.AtRestEncryptKey), model.MapToJson(t))
  520. case model.StringInterface:
  521. return model.StringInterfaceToJson(t), nil
  522. }
  523. return val, nil
  524. }
  525. func (me mattermConverter) FromDb(target interface{}) (gorp.CustomScanner, bool) {
  526. switch target.(type) {
  527. case *model.StringMap:
  528. binder := func(holder, target interface{}) error {
  529. s, ok := holder.(*string)
  530. if !ok {
  531. return errors.New(utils.T("store.sql.convert_string_map"))
  532. }
  533. b := []byte(*s)
  534. return json.Unmarshal(b, target)
  535. }
  536. return gorp.CustomScanner{new(string), target, binder}, true
  537. case *model.StringArray:
  538. binder := func(holder, target interface{}) error {
  539. s, ok := holder.(*string)
  540. if !ok {
  541. return errors.New(utils.T("store.sql.convert_string_array"))
  542. }
  543. b := []byte(*s)
  544. return json.Unmarshal(b, target)
  545. }
  546. return gorp.CustomScanner{new(string), target, binder}, true
  547. case *model.EncryptStringMap:
  548. binder := func(holder, target interface{}) error {
  549. s, ok := holder.(*string)
  550. if !ok {
  551. return errors.New(utils.T("store.sql.convert_encrypt_string_map"))
  552. }
  553. ue, err := decrypt([]byte(utils.Cfg.SqlSettings.AtRestEncryptKey), *s)
  554. if err != nil {
  555. return err
  556. }
  557. b := []byte(ue)
  558. return json.Unmarshal(b, target)
  559. }
  560. return gorp.CustomScanner{new(string), target, binder}, true
  561. case *model.StringInterface:
  562. binder := func(holder, target interface{}) error {
  563. s, ok := holder.(*string)
  564. if !ok {
  565. return errors.New(utils.T("store.sql.convert_string_interface"))
  566. }
  567. b := []byte(*s)
  568. return json.Unmarshal(b, target)
  569. }
  570. return gorp.CustomScanner{new(string), target, binder}, true
  571. }
  572. return gorp.CustomScanner{}, false
  573. }
  574. func encrypt(key []byte, text string) (string, error) {
  575. if text == "" || text == "{}" {
  576. return "", nil
  577. }
  578. plaintext := []byte(text)
  579. skey := sha512.Sum512(key)
  580. ekey, akey := skey[:32], skey[32:]
  581. block, err := aes.NewCipher(ekey)
  582. if err != nil {
  583. return "", err
  584. }
  585. macfn := hmac.New(sha256.New, akey)
  586. ciphertext := make([]byte, aes.BlockSize+macfn.Size()+len(plaintext))
  587. iv := ciphertext[:aes.BlockSize]
  588. if _, err := io.ReadFull(crand.Reader, iv); err != nil {
  589. return "", err
  590. }
  591. stream := cipher.NewCFBEncrypter(block, iv)
  592. stream.XORKeyStream(ciphertext[aes.BlockSize+macfn.Size():], plaintext)
  593. macfn.Write(ciphertext[aes.BlockSize+macfn.Size():])
  594. mac := macfn.Sum(nil)
  595. copy(ciphertext[aes.BlockSize:aes.BlockSize+macfn.Size()], mac)
  596. return base64.URLEncoding.EncodeToString(ciphertext), nil
  597. }
  598. func decrypt(key []byte, cryptoText string) (string, error) {
  599. if cryptoText == "" || cryptoText == "{}" {
  600. return "{}", nil
  601. }
  602. ciphertext, err := base64.URLEncoding.DecodeString(cryptoText)
  603. if err != nil {
  604. return "", err
  605. }
  606. skey := sha512.Sum512(key)
  607. ekey, akey := skey[:32], skey[32:]
  608. macfn := hmac.New(sha256.New, akey)
  609. if len(ciphertext) < aes.BlockSize+macfn.Size() {
  610. return "", errors.New(utils.T("store.sql.short_ciphertext"))
  611. }
  612. macfn.Write(ciphertext[aes.BlockSize+macfn.Size():])
  613. expectedMac := macfn.Sum(nil)
  614. mac := ciphertext[aes.BlockSize : aes.BlockSize+macfn.Size()]
  615. if hmac.Equal(expectedMac, mac) != true {
  616. return "", errors.New(utils.T("store.sql.incorrect_mac"))
  617. }
  618. block, err := aes.NewCipher(ekey)
  619. if err != nil {
  620. return "", err
  621. }
  622. if len(ciphertext) < aes.BlockSize {
  623. return "", errors.New(utils.T("store.sql.too_short_ciphertext"))
  624. }
  625. iv := ciphertext[:aes.BlockSize]
  626. ciphertext = ciphertext[aes.BlockSize+macfn.Size():]
  627. stream := cipher.NewCFBDecrypter(block, iv)
  628. stream.XORKeyStream(ciphertext, ciphertext)
  629. return fmt.Sprintf("%s", ciphertext), nil
  630. }