summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
Diffstat (limited to 'store')
-rw-r--r--store/sql_channel_store.go71
-rw-r--r--store/sql_channel_store_test.go34
-rw-r--r--store/sql_post_store.go2
-rw-r--r--store/sql_post_store_test.go5
-rw-r--r--store/sql_user_store.go24
-rw-r--r--store/sql_user_store_test.go22
-rw-r--r--store/store.go1
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 {