diff options
Diffstat (limited to 'store')
-rw-r--r-- | store/redis.go | 75 | ||||
-rw-r--r-- | store/redis_test.go | 59 | ||||
-rw-r--r-- | store/sql_channel_store.go | 2 | ||||
-rw-r--r-- | store/sql_channel_store_test.go | 4 | ||||
-rw-r--r-- | store/sql_post_store.go | 5 | ||||
-rw-r--r-- | store/sql_store.go | 148 | ||||
-rw-r--r-- | store/sql_team_store.go | 27 | ||||
-rw-r--r-- | store/sql_team_store_test.go | 40 | ||||
-rw-r--r-- | store/sql_user_store.go | 48 | ||||
-rw-r--r-- | store/store.go | 5 |
10 files changed, 151 insertions, 262 deletions
diff --git a/store/redis.go b/store/redis.go deleted file mode 100644 index 262040d43..000000000 --- a/store/redis.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. -// See License.txt for license information. - -package store - -import ( - l4g "code.google.com/p/log4go" - "github.com/mattermost/platform/model" - "github.com/mattermost/platform/utils" - "gopkg.in/redis.v2" - "strings" - "time" -) - -var client *redis.Client - -func RedisClient() *redis.Client { - - if client == nil { - - addr := utils.Cfg.RedisSettings.DataSource - - client = redis.NewTCPClient(&redis.Options{ - Addr: addr, - Password: "", - DB: 0, - PoolSize: utils.Cfg.RedisSettings.MaxOpenConns, - }) - - l4g.Info("Pinging redis at '%v'", addr) - pong, err := client.Ping().Result() - - if err != nil { - l4g.Critical("Failed to open redis connection to '%v' err:%v", addr, err) - time.Sleep(time.Second) - panic("Failed to open redis connection " + err.Error()) - } - - if pong != "PONG" { - l4g.Critical("Failed to ping redis connection to '%v' err:%v", addr, err) - time.Sleep(time.Second) - panic("Failed to open ping connection " + err.Error()) - } - } - - return client -} - -func RedisClose() { - l4g.Info("Closing redis") - - if client != nil { - client.Close() - client = nil - } -} - -func PublishAndForget(message *model.Message) { - - go func() { - c := RedisClient() - result := c.Publish(message.TeamId, message.ToJson()) - if result.Err() != nil { - l4g.Error("Failed to publish message err=%v, payload=%v", result.Err(), message.ToJson()) - } - }() -} - -func GetMessageFromPayload(m interface{}) *model.Message { - if msg, found := m.(*redis.Message); found { - return model.MessageFromJson(strings.NewReader(msg.Payload)) - } else { - return nil - } -} diff --git a/store/redis_test.go b/store/redis_test.go deleted file mode 100644 index 11bd9ca6a..000000000 --- a/store/redis_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. -// See License.txt for license information. - -package store - -import ( - "fmt" - "github.com/mattermost/platform/model" - "github.com/mattermost/platform/utils" - "testing" -) - -func TestRedis(t *testing.T) { - utils.LoadConfig("config.json") - - c := RedisClient() - - if c == nil { - t.Fatal("should have a valid redis connection") - } - - pubsub := c.PubSub() - defer pubsub.Close() - - m := model.NewMessage(model.NewId(), model.NewId(), model.NewId(), model.ACTION_TYPING) - m.Add("RootId", model.NewId()) - - err := pubsub.Subscribe(m.TeamId) - if err != nil { - t.Fatal(err) - } - - // should be the subscribe success message - // lets gobble that up - if _, err := pubsub.Receive(); err != nil { - t.Fatal(err) - } - - PublishAndForget(m) - - fmt.Println("here1") - - if msg, err := pubsub.Receive(); err != nil { - t.Fatal(err) - } else { - - rmsg := GetMessageFromPayload(msg) - - if m.TeamId != rmsg.TeamId { - t.Fatal("Ids do not match") - } - - if m.Props["RootId"] != rmsg.Props["RootId"] { - t.Fatal("Ids do not match") - } - } - - RedisClose() -} diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index 5aa7f21f9..dbdfc16b1 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -360,7 +360,7 @@ func (s SqlChannelStore) GetExtraMembers(channelId string, limit int) StoreChann result := StoreResult{} var members []model.ExtraMember - _, err := s.GetReplica().Select(&members, "SELECT Id, FullName, Email, ChannelMembers.Roles, Username FROM ChannelMembers, Users WHERE ChannelMembers.UserId = Users.Id AND ChannelId = :ChannelId LIMIT :Limit", map[string]interface{}{"ChannelId": channelId, "Limit": limit}) + _, err := s.GetReplica().Select(&members, "SELECT Id, Nickname, Email, ChannelMembers.Roles, Username FROM ChannelMembers, Users WHERE ChannelMembers.UserId = Users.Id AND ChannelId = :ChannelId LIMIT :Limit", map[string]interface{}{"ChannelId": channelId, "Limit": limit}) if err != nil { result.Err = model.NewAppError("SqlChannelStore.GetExtraMembers", "We couldn't get the extra info for channel members", "channel_id="+channelId+", "+err.Error()) } else { diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go index 3cb249b39..ae29bc2b3 100644 --- a/store/sql_channel_store_test.go +++ b/store/sql_channel_store_test.go @@ -200,13 +200,13 @@ func TestChannelMemberStore(t *testing.T) { u1 := model.User{} u1.TeamId = model.NewId() u1.Email = model.NewId() - u1.FullName = model.NewId() + u1.Nickname = model.NewId() Must(store.User().Save(&u1)) u2 := model.User{} u2.TeamId = model.NewId() u2.Email = model.NewId() - u2.FullName = model.NewId() + u2.Nickname = model.NewId() Must(store.User().Save(&u2)) o1 := model.ChannelMember{} diff --git a/store/sql_post_store.go b/store/sql_post_store.go index 13e7b891d..56c174e4c 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -36,6 +36,11 @@ func NewSqlPostStore(sqlStore *SqlStore) PostStore { } func (s SqlPostStore) UpgradeSchemaIfNeeded() { + + // These execs are for upgrading currently created databases to full utf8mb4 compliance + // Will be removed as seen fit for upgrading + s.GetMaster().Exec("ALTER TABLE Posts charset=utf8mb4") + s.GetMaster().Exec("ALTER TABLE Posts MODIFY COLUMN Message varchar(4000) CHARACTER SET utf8mb4") } func (s SqlPostStore) CreateIndexesIfNotExists() { diff --git a/store/sql_store.go b/store/sql_store.go index 543945605..216060dba 100644 --- a/store/sql_store.go +++ b/store/sql_store.go @@ -83,7 +83,14 @@ func NewSqlStore() Store { func setupConnection(con_type string, driver string, dataSource string, maxIdle int, maxOpen int, trace bool) *gorp.DbMap { - db, err := dbsql.Open(driver, dataSource) + charset := "" + if strings.Index(dataSource, "?") > -1 { + charset = "&charset=utf8mb4,utf8" + } else { + charset = "?charset=utf8mb4,utf8" + } + + db, err := dbsql.Open(driver, dataSource+charset) if err != nil { l4g.Critical("Failed to open sql connection to '%v' err:%v", dataSource, err) time.Sleep(time.Second) @@ -106,7 +113,7 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle if driver == "sqlite3" { dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}} } else if driver == "mysql" { - dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"}} + dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}} } else if driver == "postgres" { dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.PostgresDialect{}} } else { @@ -122,27 +129,9 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle return dbmap } -func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, colType string, defaultValue string) bool { - - var count int64 - var err error - - if utils.Cfg.SqlSettings.DriverName == "postgres" { - - count, err = ss.GetMaster().SelectInt( - `SELECT - COUNT(0) AS column_exists - FROM - information_schema.COLUMNS - WHERE - TABLE_NAME = $1 - AND COLUMN_NAME = $2`, - tableName, - columnName, - ) - } else if utils.Cfg.SqlSettings.DriverName == "mysql" { - count, err = ss.GetMaster().SelectInt( - `SELECT +func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { + count, err := ss.GetMaster().SelectInt( + `SELECT COUNT(0) AS column_exists FROM information_schema.COLUMNS @@ -150,22 +139,24 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`, - tableName, - columnName, - ) - } - + tableName, + columnName, + ) if err != nil { l4g.Critical("Failed to check if column exists %v", err) time.Sleep(time.Second) panic("Failed to check if column exists " + err.Error()) } - if count > 0 { + return count > 0 +} + +func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, afterName string, colType string, defaultValue string) bool { + if ss.DoesColumnExist(tableName, columnName) { return false } - _, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + colType + " DEFAULT '" + defaultValue + "'") + _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + colType + " DEFAULT '" + defaultValue + "'" + " AFTER " + afterName) if err != nil { l4g.Critical("Failed to create column %v", err) time.Sleep(time.Second) @@ -176,31 +167,32 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, } func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool { - count, err := ss.GetMaster().SelectInt( - `SELECT - COUNT(0) AS column_exists - FROM - information_schema.COLUMNS - WHERE - TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = ? - AND COLUMN_NAME = ?`, - tableName, - columnName, - ) + if !ss.DoesColumnExist(tableName, columnName) { + return false + } + + _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName) if err != nil { - l4g.Critical("Failed to check if column exists %v", err) + l4g.Critical("Failed to drop column %v", err) time.Sleep(time.Second) - panic("Failed to check if column exists " + err.Error()) + panic("Failed to drop column " + err.Error()) } - if count == 0 { + return true +} + +func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool { + if !ss.DoesColumnExist(tableName, oldColumnName) { return false } - _, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName) + _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType) + + // when we eventually support PostgreSQL, we can use the following instead + //_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " RENAME COLUMN " + oldColumnName + " TO " + newColumnName) + if err != nil { - l4g.Critical("Failed to drop column %v", err) + l4g.Critical("Failed to rename column %v", err) time.Sleep(time.Second) panic("Failed to drop column " + err.Error()) } @@ -217,55 +209,27 @@ func (ss SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName st } func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, columnName string, fullText bool) { + 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) + if err != nil { + l4g.Critical("Failed to check index", err) + time.Sleep(time.Second) + panic("Failed to check index" + err.Error()) + } - if utils.Cfg.SqlSettings.DriverName == "postgres" { - _, err := ss.GetMaster().SelectStr("SELECT to_regclass($1)", indexName) - // It should fail if the index does not exist - if err == nil { - return - } - - query := "" - if fullText { - query = "CREATE INDEX " + indexName + " ON " + tableName + " USING gin(to_tsvector('english', " + columnName + "))" - } else { - query = "CREATE INDEX " + indexName + " ON " + tableName + " (" + columnName + ")" - } - - _, err = ss.GetMaster().Exec(query) - if err != nil { - l4g.Critical("Failed to create index %v", err) - time.Sleep(time.Second) - panic("Failed to create index " + err.Error()) - } - } else if utils.Cfg.SqlSettings.DriverName == "mysql" { - - 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) - if err != nil { - l4g.Critical("Failed to check index %v", err) - time.Sleep(time.Second) - panic("Failed to check index " + err.Error()) - } - - if count > 0 { - return - } + if count > 0 { + return + } - fullTextIndex := "" - if fullText { - fullTextIndex = " FULLTEXT " - } + fullTextIndex := "" + if fullText { + fullTextIndex = " FULLTEXT " + } - _, err = ss.GetMaster().Exec("CREATE " + fullTextIndex + " INDEX " + indexName + " ON " + tableName + " (" + columnName + ")") - if err != nil { - l4g.Critical("Failed to create index %v", err) - time.Sleep(time.Second) - panic("Failed to create index " + err.Error()) - } - } else { - l4g.Critical("Failed to create index because of missing driver") + _, err = ss.GetMaster().Exec("CREATE " + fullTextIndex + " INDEX " + indexName + " ON " + tableName + " (" + columnName + ")") + if err != nil { + l4g.Critical("Failed to create index", err) time.Sleep(time.Second) - panic("Failed to create index because of missing driver") + panic("Failed to create index " + err.Error()) } } diff --git a/store/sql_team_store.go b/store/sql_team_store.go index 193d0a62c..73d603151 100644 --- a/store/sql_team_store.go +++ b/store/sql_team_store.go @@ -17,8 +17,8 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore { for _, db := range sqlStore.GetAllConns() { table := db.AddTableWithName(model.Team{}, "Teams").SetKeys(false, "Id") table.ColMap("Id").SetMaxSize(26) - table.ColMap("Name").SetMaxSize(64) - table.ColMap("Domain").SetMaxSize(64).SetUnique(true) + table.ColMap("DisplayName").SetMaxSize(64) + table.ColMap("Name").SetMaxSize(64).SetUnique(true) table.ColMap("Email").SetMaxSize(128) table.ColMap("CompanyName").SetMaxSize(64) table.ColMap("AllowedDomains").SetMaxSize(500) @@ -28,6 +28,15 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore { } func (s SqlTeamStore) UpgradeSchemaIfNeeded() { + defaultValue := "0" + if utils.Cfg.TeamSettings.AllowValetDefault { + defaultValue = "1" + } + s.CreateColumnIfNotExists("Teams", "AllowValet", "AllowedDomains", "tinyint(1)", defaultValue) + if !s.DoesColumnExist("Teams", "DisplayName") { + s.RenameColumnIfExists("Teams", "Name", "DisplayName", "varchar(64)") + s.RenameColumnIfExists("Teams", "Domain", "Name", "varchar(64)") + } } func (s SqlTeamStore) CreateIndexesIfNotExists() { @@ -56,7 +65,7 @@ func (s SqlTeamStore) Save(team *model.Team) StoreChannel { } if err := s.GetMaster().Insert(team); err != nil { - if IsUniqueConstraintError(err.Error(), "Domain", "teams_domain_key") { + if IsUniqueConstraintError(err.Error(), "Name", "teams_domain_key") { result.Err = model.NewAppError("SqlTeamStore.Save", "A team with that domain already exists", "id="+team.Id+", "+err.Error()) } else { result.Err = model.NewAppError("SqlTeamStore.Save", "We couldn't save the team", "id="+team.Id+", "+err.Error()) @@ -94,7 +103,7 @@ func (s SqlTeamStore) Update(team *model.Team) StoreChannel { } else { oldTeam := oldResult.(*model.Team) team.CreateAt = oldTeam.CreateAt - team.Domain = oldTeam.Domain + team.Name = oldTeam.Name if count, err := s.GetMaster().Update(team); err != nil { result.Err = model.NewAppError("SqlTeamStore.Update", "We encounted an error updating the team", "id="+team.Id+", "+err.Error()) @@ -112,14 +121,14 @@ func (s SqlTeamStore) Update(team *model.Team) StoreChannel { return storeChannel } -func (s SqlTeamStore) UpdateName(name string, teamId string) StoreChannel { +func (s SqlTeamStore) UpdateDisplayName(name string, teamId string) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} - if _, err := s.GetMaster().Exec("UPDATE Teams SET Name = :Name WHERE Id = :Id", map[string]interface{}{"Name": name, "Id": teamId}); err != nil { + if _, err := s.GetMaster().Exec("UPDATE Teams SET DisplayName = :Name WHERE Id = :Id", map[string]interface{}{"Name": name, "Id": teamId}); err != nil { result.Err = model.NewAppError("SqlTeamStore.UpdateName", "We couldn't update the team name", "team_id="+teamId) } else { result.Data = teamId @@ -153,7 +162,7 @@ func (s SqlTeamStore) Get(id string) StoreChannel { return storeChannel } -func (s SqlTeamStore) GetByDomain(domain string) StoreChannel { +func (s SqlTeamStore) GetByName(name string) StoreChannel { storeChannel := make(StoreChannel) go func() { @@ -161,8 +170,8 @@ func (s SqlTeamStore) GetByDomain(domain string) StoreChannel { team := model.Team{} - if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Domain = :Domain", map[string]interface{}{"Domain": domain}); err != nil { - result.Err = model.NewAppError("SqlTeamStore.GetByDomain", "We couldn't find the existing team", "domain="+domain+", "+err.Error()) + if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil { + result.Err = model.NewAppError("SqlTeamStore.GetByName", "We couldn't find the existing team", "name="+name+", "+err.Error()) } result.Data = &team diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go index bd1a7de2e..1f13e466c 100644 --- a/store/sql_team_store_test.go +++ b/store/sql_team_store_test.go @@ -13,8 +13,8 @@ func TestTeamStoreSave(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN @@ -36,8 +36,8 @@ func TestTeamStoreUpdate(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN if err := (<-store.Team().Save(&o1)).Err; err != nil { @@ -61,25 +61,25 @@ func TestTeamStoreUpdate(t *testing.T) { } } -func TestTeamStoreUpdateName(t *testing.T) { +func TestTeamStoreUpdateDisplayName(t *testing.T) { Setup() o1 := &model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "Display Name" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN o1 = (<-store.Team().Save(o1)).Data.(*model.Team) - newName := "NewName" + newDisplayName := "NewDisplayName" - if err := (<-store.Team().UpdateName(newName, o1.Id)).Err; err != nil { + if err := (<-store.Team().UpdateDisplayName(newDisplayName, o1.Id)).Err; err != nil { t.Fatal(err) } ro1 := (<-store.Team().Get(o1.Id)).Data.(*model.Team) - if ro1.Name != newName { - t.Fatal("Name not updated") + if ro1.DisplayName != newDisplayName { + t.Fatal("DisplayName not updated") } } @@ -87,8 +87,8 @@ func TestTeamStoreGet(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN Must(store.Team().Save(&o1)) @@ -106,12 +106,12 @@ func TestTeamStoreGet(t *testing.T) { } } -func TestTeamStoreGetByDomain(t *testing.T) { +func TestTeamStoreGetByName(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN @@ -119,7 +119,7 @@ func TestTeamStoreGetByDomain(t *testing.T) { t.Fatal(err) } - if r1 := <-store.Team().GetByDomain(o1.Domain); r1.Err != nil { + if r1 := <-store.Team().GetByName(o1.Name); r1.Err != nil { t.Fatal(r1.Err) } else { if r1.Data.(*model.Team).ToJson() != o1.ToJson() { @@ -127,7 +127,7 @@ func TestTeamStoreGetByDomain(t *testing.T) { } } - if err := (<-store.Team().GetByDomain("")).Err; err == nil { + if err := (<-store.Team().GetByName("")).Err; err == nil { t.Fatal("Missing id should have failed") } } @@ -136,8 +136,8 @@ func TestTeamStoreGetForEmail(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN Must(store.Team().Save(&o1)) diff --git a/store/sql_user_store.go b/store/sql_user_store.go index 1eb20734b..5feef5e69 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -24,7 +24,9 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore { table.ColMap("Password").SetMaxSize(128) table.ColMap("AuthData").SetMaxSize(128) table.ColMap("Email").SetMaxSize(128) - table.ColMap("FullName").SetMaxSize(64) + table.ColMap("Nickname").SetMaxSize(64) + table.ColMap("FirstName").SetMaxSize(64) + table.ColMap("LastName").SetMaxSize(64) table.ColMap("Roles").SetMaxSize(64) table.ColMap("Props").SetMaxSize(4000) table.ColMap("NotifyProps").SetMaxSize(2000) @@ -35,9 +37,29 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore { return us } -func (s SqlUserStore) UpgradeSchemaIfNeeded() { +func (us SqlUserStore) UpgradeSchemaIfNeeded() { + us.CreateColumnIfNotExists("Users", "LastPictureUpdate", "LastPasswordUpdate", "bigint(20)", "0") + + // migrating the FullName column to Nickname and adding the FirstName and LastName columns for MM-825 + if us.RenameColumnIfExists("Users", "FullName", "Nickname", "varchar(64)") { + us.CreateColumnIfNotExists("Users", "FirstName", "Nickname", "varchar(64)", "") + us.CreateColumnIfNotExists("Users", "LastName", "FirstName", "varchar(64)", "") + + // infer values of first and last name by splitting the previous full name + if _, err := us.GetMaster().Exec("UPDATE Users SET FirstName = SUBSTRING_INDEX(SUBSTRING_INDEX(Nickname, ' ', 1), ' ', -1)"); err != nil { + panic("Failed to set first name from nickname " + err.Error()) + } + + // only set the last name from full names that are comprised of multiple words (ie that have at least one space in them) + if _, err := us.GetMaster().Exec("Update Users SET LastName = SUBSTRING(Nickname, INSTR(Nickname, ' ') + 1) " + + "WHERE CHAR_LENGTH(REPLACE(Nickname, ' ', '')) < CHAR_LENGTH(Nickname)"); err != nil { + panic("Failed to set last name from nickname " + err.Error()) + } + } } +//func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, afterName string, colType string, defaultValue string) bool { + func (us SqlUserStore) CreateIndexesIfNotExists() { us.CreateIndexIfNotExists("idx_users_team_id", "Users", "TeamId") us.CreateIndexIfNotExists("idx_users_email", "Users", "Email") @@ -120,6 +142,7 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha user.AuthData = oldUser.AuthData user.Password = oldUser.Password user.LastPasswordUpdate = oldUser.LastPasswordUpdate + user.LastPictureUpdate = oldUser.LastPictureUpdate user.TeamId = oldUser.TeamId user.LastActivityAt = oldUser.LastActivityAt user.LastPingAt = oldUser.LastPingAt @@ -150,6 +173,27 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha return storeChannel } +func (us SqlUserStore) UpdateLastPictureUpdate(userId string) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + curTime := model.GetMillis() + + if _, err := us.GetMaster().Exec("UPDATE Users SET LastPictureUpdate = ?, UpdateAt = ? WHERE Id = ?", curTime, curTime, userId); err != nil { + result.Err = model.NewAppError("SqlUserStore.UpdateUpdateAt", "We couldn't update the update_at", "user_id="+userId) + } else { + result.Data = userId + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (us SqlUserStore) UpdateLastPingAt(userId string, time int64) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/store.go b/store/store.go index 070ee0562..5b0e13fce 100644 --- a/store/store.go +++ b/store/store.go @@ -36,9 +36,9 @@ type Store interface { type TeamStore interface { Save(team *model.Team) StoreChannel Update(team *model.Team) StoreChannel - UpdateName(name string, teamId string) StoreChannel + UpdateDisplayName(name string, teamId string) StoreChannel Get(id string) StoreChannel - GetByDomain(domain string) StoreChannel + GetByName(name string) StoreChannel GetTeamsForEmail(domain string) StoreChannel } @@ -77,6 +77,7 @@ type PostStore interface { type UserStore interface { Save(user *model.User) StoreChannel Update(user *model.User, allowRoleUpdate bool) StoreChannel + UpdateLastPictureUpdate(userId string) StoreChannel UpdateLastPingAt(userId string, time int64) StoreChannel UpdateLastActivityAt(userId string, time int64) StoreChannel UpdateUserAndSessionActivity(userId string, sessionId string, time int64) StoreChannel |