diff options
Diffstat (limited to 'store')
-rw-r--r-- | store/sql_channel_store.go | 71 | ||||
-rw-r--r-- | store/sql_channel_store_test.go | 34 | ||||
-rw-r--r-- | store/sql_post_store.go | 2 | ||||
-rw-r--r-- | store/sql_post_store_test.go | 5 | ||||
-rw-r--r-- | store/sql_user_store.go | 24 | ||||
-rw-r--r-- | store/sql_user_store_test.go | 22 | ||||
-rw-r--r-- | store/store.go | 1 |
7 files changed, 141 insertions, 18 deletions
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index ce1a8c6fa..cac5c681b 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -36,6 +36,7 @@ func NewSqlChannelStore(sqlStore *SqlStore) ChannelStore { } func (s SqlChannelStore) UpgradeSchemaIfNeeded() { + s.CreateColumnIfNotExists("Channels", "ExtraUpdateAt", "TotalMsgCount", "bigint(20)", "0") } func (s SqlChannelStore) CreateIndexesIfNotExists() { @@ -142,6 +143,25 @@ func (s SqlChannelStore) Update(channel *model.Channel) StoreChannel { return storeChannel } +func (s SqlChannelStore) extraUpdated(channel *model.Channel) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + channel.ExtraUpdated() + + if count, err := s.GetMaster().Update(channel); err != nil || count != 1 { + result.Err = model.NewAppError("SqlChannelStore.extraUpdated", "Problem updating members last updated time", "id="+channel.Id+", "+err.Error()) + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (s SqlChannelStore) Get(id string) StoreChannel { storeChannel := make(StoreChannel) @@ -288,20 +308,31 @@ func (s SqlChannelStore) SaveMember(member *model.ChannelMember) StoreChannel { go func() { result := StoreResult{} - member.PreSave() - if result.Err = member.IsValid(); result.Err != nil { - storeChannel <- result - return - } + // Grab the channel we are saving this member to + if cr := <-s.Get(member.ChannelId); cr.Err != nil { + result.Err = cr.Err + } else { + channel := cr.Data.(*model.Channel) + + member.PreSave() + if result.Err = member.IsValid(); result.Err != nil { + storeChannel <- result + return + } - if err := s.GetMaster().Insert(member); err != nil { - if IsUniqueConstraintError(err.Error(), "ChannelId", "channelmembers_pkey") { - result.Err = model.NewAppError("SqlChannelStore.SaveMember", "A channel member with that id already exists", "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error()) + if err := s.GetMaster().Insert(member); err != nil { + if IsUniqueConstraintError(err.Error(), "ChannelId", "channelmembers_pkey") { + result.Err = model.NewAppError("SqlChannelStore.SaveMember", "A channel member with that id already exists", "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error()) + } else { + result.Err = model.NewAppError("SqlChannelStore.SaveMember", "We couldn't save the channel member", "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error()) + } } else { - result.Err = model.NewAppError("SqlChannelStore.SaveMember", "We couldn't save the channel member", "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error()) + result.Data = member + // If sucessfull record members have changed in channel + if mu := <-s.extraUpdated(channel); mu.Err != nil { + result.Err = mu.Err + } } - } else { - result.Data = member } storeChannel <- result @@ -383,9 +414,21 @@ func (s SqlChannelStore) RemoveMember(channelId string, userId string) StoreChan go func() { result := StoreResult{} - _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}) - if err != nil { - result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "We couldn't remove the channel member", "channel_id="+channelId+", user_id="+userId+", "+err.Error()) + // Grab the channel we are saving this member to + if cr := <-s.Get(channelId); cr.Err != nil { + result.Err = cr.Err + } else { + channel := cr.Data.(*model.Channel) + + _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}) + if err != nil { + result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "We couldn't remove the channel member", "channel_id="+channelId+", user_id="+userId+", "+err.Error()) + } else { + // If sucessfull record members have changed in channel + if mu := <-s.extraUpdated(channel); mu.Err != nil { + result.Err = mu.Err + } + } } storeChannel <- result diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go index ae29bc2b3..b14883843 100644 --- a/store/sql_channel_store_test.go +++ b/store/sql_channel_store_test.go @@ -197,6 +197,16 @@ func TestChannelStoreGetByName(t *testing.T) { func TestChannelMemberStore(t *testing.T) { Setup() + c1 := model.Channel{} + c1.TeamId = model.NewId() + c1.DisplayName = "NameName" + c1.Name = "a" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = *Must(store.Channel().Save(&c1)).(*model.Channel) + + c1t1 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel) + t1 := c1t1.ExtraUpdateAt + u1 := model.User{} u1.TeamId = model.NewId() u1.Email = model.NewId() @@ -210,17 +220,24 @@ func TestChannelMemberStore(t *testing.T) { Must(store.User().Save(&u2)) o1 := model.ChannelMember{} - o1.ChannelId = model.NewId() + o1.ChannelId = c1.Id o1.UserId = u1.Id o1.NotifyLevel = model.CHANNEL_NOTIFY_ALL Must(store.Channel().SaveMember(&o1)) o2 := model.ChannelMember{} - o2.ChannelId = o1.ChannelId + o2.ChannelId = c1.Id o2.UserId = u2.Id o2.NotifyLevel = model.CHANNEL_NOTIFY_ALL Must(store.Channel().SaveMember(&o2)) + c1t2 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel) + t2 := c1t2.ExtraUpdateAt + + if t2 <= t1 { + t.Fatal("Member update time incorrect") + } + members := (<-store.Channel().GetMembers(o1.ChannelId)).Data.([]model.ChannelMember) if len(members) != 2 { t.Fatal("should have saved 2 members") @@ -233,6 +250,13 @@ func TestChannelMemberStore(t *testing.T) { t.Fatal("should have removed 1 member") } + c1t3 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel) + t3 := c1t3.ExtraUpdateAt + + if t3 <= t2 || t3 <= t1 { + t.Fatal("Member update time incorrect on delete") + } + member := (<-store.Channel().GetMember(o1.ChannelId, o1.UserId)).Data.(model.ChannelMember) if member.ChannelId != o1.ChannelId { t.Fatal("should have go member") @@ -246,6 +270,12 @@ func TestChannelMemberStore(t *testing.T) { if err := (<-store.Channel().SaveMember(&o1)).Err; err == nil { t.Fatal("Should have been a duplicate") } + + c1t4 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel) + t4 := c1t4.ExtraUpdateAt + if t4 != t3 { + t.Fatal("Should not update time upon failure") + } } func TestChannelStorePermissionsTo(t *testing.T) { diff --git a/store/sql_post_store.go b/store/sql_post_store.go index ede69d125..479caf838 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -401,7 +401,7 @@ func (s SqlPostStore) Search(teamId string, userId string, terms string, isHasht Id = ChannelId AND TeamId = $1 AND UserId = $2 AND DeleteAt = 0) - AND %s @@ plainto_tsquery($3) + AND %s @@ to_tsquery($3) ORDER BY CreateAt DESC LIMIT 100`, searchType) diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go index d1639aa03..336a20d98 100644 --- a/store/sql_post_store_test.go +++ b/store/sql_post_store_test.go @@ -483,4 +483,9 @@ func TestPostStoreSearch(t *testing.T) { if len(r8.Order) != 0 { t.Fatal("returned wrong serach result") } + + r9 := (<-store.Post().Search(teamId, userId, "mattermost jersey", false)).Data.(*model.PostList) + if len(r9.Order) != 2 { + t.Fatal("returned wrong search result") + } } diff --git a/store/sql_user_store.go b/store/sql_user_store.go index 552d12843..cd25b488b 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -59,6 +59,8 @@ func (us SqlUserStore) UpgradeSchemaIfNeeded() { } us.CreateColumnIfNotExists("Users", "AuthService", "AuthData", "varchar(32)", "") // for OAuth Client + + us.CreateColumnIfNotExists("Users", "FailedAttempts", "LastPictureUpdate", "int(11)", "0") } //func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, afterName string, colType string, defaultValue string) bool { @@ -150,6 +152,7 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha user.LastActivityAt = oldUser.LastActivityAt user.LastPingAt = oldUser.LastPingAt user.EmailVerified = oldUser.EmailVerified + user.FailedAttempts = oldUser.FailedAttempts if !allowActiveUpdate { user.Roles = oldUser.Roles @@ -271,7 +274,7 @@ func (us SqlUserStore) UpdatePassword(userId, hashedPassword string) StoreChanne updateAt := model.GetMillis() - if _, err := us.GetMaster().Exec("UPDATE Users SET Password = :Password, LastPasswordUpdate = :LastPasswordUpdate, UpdateAt = :UpdateAt WHERE Id = :UserId", map[string]interface{}{"Password": hashedPassword, "LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId}); err != nil { + if _, err := us.GetMaster().Exec("UPDATE Users SET Password = :Password, LastPasswordUpdate = :LastPasswordUpdate, UpdateAt = :UpdateAt, FailedAttempts = 0 WHERE Id = :UserId", map[string]interface{}{"Password": hashedPassword, "LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId}); err != nil { result.Err = model.NewAppError("SqlUserStore.UpdatePassword", "We couldn't update the user password", "id="+userId+", "+err.Error()) } else { result.Data = userId @@ -284,6 +287,25 @@ func (us SqlUserStore) UpdatePassword(userId, hashedPassword string) StoreChanne return storeChannel } +func (us SqlUserStore) UpdateFailedPasswordAttempts(userId string, attempts int) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + if _, err := us.GetMaster().Exec("UPDATE Users SET FailedAttempts = :FailedAttempts WHERE Id = :UserId", map[string]interface{}{"FailedAttempts": attempts, "UserId": userId}); err != nil { + result.Err = model.NewAppError("SqlUserStore.UpdateFailedPasswordAttempts", "We couldn't update the failed_attempts", "user_id="+userId) + } else { + result.Data = userId + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (us SqlUserStore) Get(id string) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go index 1f94021b2..ddd7e5bb8 100644 --- a/store/sql_user_store_test.go +++ b/store/sql_user_store_test.go @@ -128,6 +128,28 @@ func TestUserStoreUpdateLastActivityAt(t *testing.T) { } +func TestUserStoreUpdateFailedPasswordAttempts(t *testing.T) { + Setup() + + u1 := model.User{} + u1.TeamId = model.NewId() + u1.Email = model.NewId() + Must(store.User().Save(&u1)) + + if err := (<-store.User().UpdateFailedPasswordAttempts(u1.Id, 3)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-store.User().Get(u1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.User).FailedAttempts != 3 { + t.Fatal("LastActivityAt not updated correctly") + } + } + +} + func TestUserStoreUpdateUserAndSessionActivity(t *testing.T) { Setup() diff --git a/store/store.go b/store/store.go index fac3a5bdb..0934fe84b 100644 --- a/store/store.go +++ b/store/store.go @@ -89,6 +89,7 @@ type UserStore interface { GetByUsername(teamId string, username string) StoreChannel VerifyEmail(userId string) StoreChannel GetEtagForProfiles(teamId string) StoreChannel + UpdateFailedPasswordAttempts(userId string, attempts int) StoreChannel } type SessionStore interface { |