summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
Diffstat (limited to 'store')
-rw-r--r--store/sql_channel_store.go74
-rw-r--r--store/sql_post_store.go24
-rw-r--r--store/sql_preference_store.go27
-rw-r--r--store/sql_preference_store_test.go27
-rw-r--r--store/sql_team_store.go2
-rw-r--r--store/sql_user_store.go116
-rw-r--r--store/store.go5
7 files changed, 174 insertions, 101 deletions
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index e5e0aa8ba..463bc0678 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -856,6 +856,58 @@ func (s SqlChannelStore) CheckOpenChannelPermissions(teamId string, channelId st
return storeChannel
}
+func (s SqlChannelStore) SetLastViewedAt(channelId string, userId string, newLastViewedAt int64) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ var query string
+
+ if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
+ query = `UPDATE
+ ChannelMembers
+ SET
+ MentionCount = 0,
+ MsgCount = Channels.TotalMsgCount - (SELECT COUNT(*)
+ FROM Posts
+ WHERE ChannelId = :ChannelId
+ AND CreateAt > :NewLastViewedAt),
+ LastViewedAt = :NewLastViewedAt
+ FROM
+ Channels
+ WHERE
+ Channels.Id = ChannelMembers.ChannelId
+ AND UserId = :UserId
+ AND ChannelId = :ChannelId`
+ } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
+ query = `UPDATE
+ ChannelMembers, Channels
+ SET
+ ChannelMembers.MentionCount = 0,
+ ChannelMembers.MsgCount = Channels.TotalMsgCount - (SELECT COUNT(*)
+ FROM Posts
+ WHERE ChannelId = :ChannelId
+ AND CreateAt > :NewLastViewedAt),
+ ChannelMembers.LastViewedAt = :NewLastViewedAt
+ WHERE
+ Channels.Id = ChannelMembers.ChannelId
+ AND UserId = :UserId
+ AND ChannelId = :ChannelId`
+ }
+
+ _, err := s.GetMaster().Exec(query, map[string]interface{}{"ChannelId": channelId, "UserId": userId, "NewLastViewedAt": newLastViewedAt})
+ if err != nil {
+ result.Err = model.NewLocAppError("SqlChannelStore.SetLastViewedAt", "store.sql_channel.set_last_viewed_at.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (s SqlChannelStore) UpdateLastViewedAt(channelId string, userId string) StoreChannel {
storeChannel := make(StoreChannel)
@@ -930,28 +982,6 @@ func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string)
return storeChannel
}
-func (s SqlChannelStore) GetForExport(teamId string) StoreChannel {
- storeChannel := make(StoreChannel)
-
- go func() {
- result := StoreResult{}
-
- var data []*model.Channel
- _, err := s.GetReplica().Select(&data, "SELECT * FROM Channels WHERE TeamId = :TeamId AND DeleteAt = 0 AND Type = 'O'", map[string]interface{}{"TeamId": teamId})
-
- if err != nil {
- result.Err = model.NewLocAppError("SqlChannelStore.GetAllChannels", "store.sql_channel.get_for_export.app_error", nil, "teamId="+teamId+", err="+err.Error())
- } else {
- result.Data = data
- }
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
-
func (s SqlChannelStore) GetAll(teamId string) StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/sql_post_store.go b/store/sql_post_store.go
index e6291687e..57bb2a512 100644
--- a/store/sql_post_store.go
+++ b/store/sql_post_store.go
@@ -784,30 +784,6 @@ func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchP
return storeChannel
}
-func (s SqlPostStore) GetForExport(channelId string) StoreChannel {
- storeChannel := make(StoreChannel)
-
- go func() {
- result := StoreResult{}
-
- var posts []*model.Post
- _, err := s.GetReplica().Select(
- &posts,
- "SELECT * FROM Posts WHERE ChannelId = :ChannelId AND DeleteAt = 0",
- map[string]interface{}{"ChannelId": channelId})
- if err != nil {
- result.Err = model.NewLocAppError("SqlPostStore.GetForExport", "store.sql_post.get_for_export.app_error", nil, "channelId="+channelId+err.Error())
- } else {
- result.Data = posts
- }
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
-
func (s SqlPostStore) AnalyticsUserCountsWithPostsByDay(teamId string) StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/sql_preference_store.go b/store/sql_preference_store.go
index 83bf92ead..a701c3cb8 100644
--- a/store/sql_preference_store.go
+++ b/store/sql_preference_store.go
@@ -26,7 +26,7 @@ func NewSqlPreferenceStore(sqlStore *SqlStore) PreferenceStore {
table.ColMap("UserId").SetMaxSize(26)
table.ColMap("Category").SetMaxSize(32)
table.ColMap("Name").SetMaxSize(32)
- table.ColMap("Value").SetMaxSize(128)
+ table.ColMap("Value").SetMaxSize(2000)
}
return s
@@ -100,6 +100,8 @@ func (s SqlPreferenceStore) Save(preferences *model.Preferences) StoreChannel {
func (s SqlPreferenceStore) save(transaction *gorp.Transaction, preference *model.Preference) StoreResult {
result := StoreResult{}
+ preference.PreUpdate()
+
if result.Err = preference.IsValid(); result.Err != nil {
return result
}
@@ -304,3 +306,26 @@ func (s SqlPreferenceStore) IsFeatureEnabled(feature, userId string) StoreChanne
return storeChannel
}
+
+func (s SqlPreferenceStore) Delete(userId, category, name string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec(
+ `DELETE FROM
+ Preferences
+ WHERE
+ UserId = :UserId
+ AND Category = :Category
+ AND Name = :Name`, map[string]interface{}{"UserId": userId, "Category": category, "Name": name}); err != nil {
+ result.Err = model.NewLocAppError("SqlPreferenceStore.Delete", "store.sql_preference.delete.app_error", nil, err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_preference_store_test.go b/store/sql_preference_store_test.go
index ec9d1df6c..8c6a2b6af 100644
--- a/store/sql_preference_store_test.go
+++ b/store/sql_preference_store_test.go
@@ -193,7 +193,7 @@ func TestPreferenceGetAll(t *testing.T) {
}
}
-func TestPreferenceDelete(t *testing.T) {
+func TestPreferenceDeleteByUser(t *testing.T) {
Setup()
userId := model.NewId()
@@ -367,3 +367,28 @@ func TestDeleteUnusedFeatures(t *testing.T) {
t.Fatalf("Found %d features with value 'true', expected to find at least %d features", val, 2)
}
}
+
+func TestPreferenceDelete(t *testing.T) {
+ Setup()
+
+ preference := model.Preference{
+ UserId: model.NewId(),
+ Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
+ Name: model.NewId(),
+ Value: "value1a",
+ }
+
+ Must(store.Preference().Save(&model.Preferences{preference}))
+
+ if prefs := Must(store.Preference().GetAll(preference.UserId)).(model.Preferences); len([]model.Preference(prefs)) != 1 {
+ t.Fatal("should've returned 1 preference")
+ }
+
+ if result := <-store.Preference().Delete(preference.UserId, preference.Category, preference.Name); result.Err != nil {
+ t.Fatal(result.Err)
+ }
+
+ if prefs := Must(store.Preference().GetAll(preference.UserId)).(model.Preferences); len([]model.Preference(prefs)) != 0 {
+ t.Fatal("should've returned no preferences")
+ }
+}
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index ddcaa7896..002d2a3ea 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -265,7 +265,7 @@ func (s SqlTeamStore) GetTeamsByUserId(userId string) StoreChannel {
result := StoreResult{}
var data []*model.Team
- if _, err := s.GetReplica().Select(&data, "SELECT Teams.* FROM Teams, TeamMembers WHERE TeamMembers.TeamId = Teams.Id AND TeamMembers.UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
+ if _, err := s.GetReplica().Select(&data, "SELECT Teams.* FROM Teams, TeamMembers WHERE TeamMembers.TeamId = Teams.Id AND TeamMembers.UserId = :UserId AND TeamMembers.DeleteAt = 0 AND Teams.DeleteAt = 0", map[string]interface{}{"UserId": userId}); err != nil {
result.Err = model.NewLocAppError("SqlTeamStore.GetTeamsByUserId", "store.sql_team.get_all.app_error", nil, err.Error())
}
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index df132ab42..325008670 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -4,11 +4,14 @@
package store
import (
+ "crypto/md5"
"database/sql"
"fmt"
"strconv"
"strings"
+ "time"
+ l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -39,7 +42,6 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore {
table.ColMap("Roles").SetMaxSize(64)
table.ColMap("Props").SetMaxSize(4000)
table.ColMap("NotifyProps").SetMaxSize(2000)
- table.ColMap("ThemeProps").SetMaxSize(2000)
table.ColMap("Locale").SetMaxSize(5)
table.ColMap("MfaSecret").SetMaxSize(128)
}
@@ -52,27 +54,68 @@ func (us SqlUserStore) UpgradeSchemaIfNeeded() {
us.CreateColumnIfNotExists("Users", "Locale", "varchar(5)", "character varying(5)", model.DEFAULT_LOCALE)
// ADDED for 3.2 REMOVE for 3.6
- var data []*model.User
- if _, err := us.GetReplica().Select(&data, "SELECT * FROM Users WHERE ThemeProps LIKE '%solarized%'"); err == nil {
- for _, user := range data {
- shouldUpdate := false
- if user.ThemeProps["codeTheme"] == "solarized_dark" {
- user.ThemeProps["codeTheme"] = "solarized-dark"
- shouldUpdate = true
- } else if user.ThemeProps["codeTheme"] == "solarized_light" {
- user.ThemeProps["codeTheme"] = "solarized-light"
- shouldUpdate = true
+ if us.DoesColumnExist("Users", "ThemeProps") {
+ params := map[string]interface{}{
+ "Category": model.PREFERENCE_CATEGORY_THEME,
+ "Name": "",
+ }
+
+ transaction, err := us.GetMaster().Begin()
+ if err != nil {
+ themeMigrationFailed(err)
+ }
+
+ // increase size of Value column of Preferences table to match the size of the ThemeProps column
+ if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
+ if _, err := transaction.Exec("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil {
+ themeMigrationFailed(err)
+ }
+ } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
+ if _, err := transaction.Exec("ALTER TABLE Preferences MODIFY Value text"); err != nil {
+ themeMigrationFailed(err)
}
+ }
- if shouldUpdate {
- if result := <-us.Update(user, true); result.Err != nil {
- return
- }
+ // copy data across
+ if _, err := transaction.Exec(
+ `INSERT INTO
+ Preferences(UserId, Category, Name, Value)
+ SELECT
+ Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps
+ FROM
+ Users
+ WHERE
+ Users.ThemeProps != 'null'`, params); err != nil {
+ themeMigrationFailed(err)
+ }
+
+ // delete old data
+ if _, err := transaction.Exec("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil {
+ themeMigrationFailed(err)
+ }
+
+ if err := transaction.Commit(); err != nil {
+ themeMigrationFailed(err)
+ }
+
+ // rename solarized_* code themes to solarized-* to match client changes in 3.0
+ var data model.Preferences
+ if _, err := us.GetReplica().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil {
+ for i := range data {
+ data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1)
}
+
+ us.Preference().Save(&data)
}
}
}
+func themeMigrationFailed(err error) {
+ l4g.Critical(utils.T("store.sql_user.migrate_theme.critical"), err)
+ time.Sleep(time.Second)
+ panic(fmt.Sprintf(utils.T("store.sql_user.migrate_theme.critical"), err.Error()))
+}
+
func (us SqlUserStore) CreateIndexesIfNotExists() {
us.CreateIndexIfNotExists("idx_users_email", "Users", "Email")
}
@@ -480,9 +523,10 @@ func (s SqlUserStore) GetEtagForDirectProfiles(userId string) StoreChannel {
go func() {
result := StoreResult{}
- updateAt, err := s.GetReplica().SelectInt(`
+ var ids []string
+ _, err := s.GetReplica().Select(ids, `
SELECT
- UpdateAt
+ Id
FROM
Users
WHERE
@@ -508,12 +552,14 @@ func (s SqlUserStore) GetEtagForDirectProfiles(userId string) StoreChannel {
WHERE
UserId = :UserId
AND Category = 'direct_channel_show')
- ORDER BY UpdateAt DESC LIMIT 1
+ ORDER BY UpdateAt DESC
`, map[string]interface{}{"UserId": userId})
- if err != nil {
- result.Data = fmt.Sprintf("%v.%v.%v.%v", model.CurrentVersion, model.GetMillis(), utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress)
+
+ if err != nil || len(ids) == 0 {
+ result.Data = fmt.Sprintf("%v.%v.0.%v.%v", model.CurrentVersion, model.GetMillis(), utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress)
} else {
- result.Data = fmt.Sprintf("%v.%v.%v.%v", model.CurrentVersion, updateAt, utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress)
+ allIds := strings.Join(ids, "")
+ result.Data = fmt.Sprintf("%v.%v.%v.%v.%v", model.CurrentVersion, md5.Sum([]byte(allIds)), len(ids), utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress)
}
storeChannel <- result
@@ -923,34 +969,6 @@ func (us SqlUserStore) VerifyEmail(userId string) StoreChannel {
return storeChannel
}
-func (us SqlUserStore) GetForExport(teamId string) StoreChannel {
-
- storeChannel := make(StoreChannel)
-
- go func() {
- result := StoreResult{}
-
- var users []*model.User
-
- if _, err := us.GetReplica().Select(&users, "SELECT Users.* FROM Users, TeamMembers WHERE TeamMembers.TeamId = :TeamId AND Users.Id = TeamMembers.UserId", map[string]interface{}{"TeamId": teamId}); err != nil {
- result.Err = model.NewLocAppError("SqlUserStore.GetForExport", "store.sql_user.get_for_export.app_error", nil, err.Error())
- } else {
- for _, u := range users {
- u.Password = ""
- u.AuthData = new(string)
- *u.AuthData = ""
- }
-
- result.Data = users
- }
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
-
func (us SqlUserStore) GetTotalUsersCount() StoreChannel {
storeChannel := make(StoreChannel)
diff --git a/store/store.go b/store/store.go
index f576cc2ab..4b5c0e8cd 100644
--- a/store/store.go
+++ b/store/store.go
@@ -83,7 +83,6 @@ type ChannelStore interface {
GetChannels(teamId string, userId string) StoreChannel
GetMoreChannels(teamId string, userId string) StoreChannel
GetChannelCounts(teamId string, userId string) StoreChannel
- GetForExport(teamId string) StoreChannel
GetAll(teamId string) StoreChannel
SaveMember(member *model.ChannelMember) StoreChannel
@@ -99,6 +98,7 @@ type ChannelStore interface {
CheckOpenChannelPermissions(teamId string, channelId string) StoreChannel
CheckPermissionsToByName(teamId string, channelName string, userId string) StoreChannel
UpdateLastViewedAt(channelId string, userId string) StoreChannel
+ SetLastViewedAt(channelId string, userId string, newLastViewedAt int64) StoreChannel
IncrementMentionCount(channelId string, userId string) StoreChannel
AnalyticsTypeCount(teamId string, channelType string) StoreChannel
ExtraUpdateByUser(userId string, time int64) StoreChannel
@@ -116,7 +116,6 @@ type PostStore interface {
GetPostsSince(channelId string, time int64) StoreChannel
GetEtag(channelId string) StoreChannel
Search(teamId string, userId string, params *model.SearchParams) StoreChannel
- GetForExport(channelId string) StoreChannel
AnalyticsUserCountsWithPostsByDay(teamId string) StoreChannel
AnalyticsPostCountsByDay(teamId string) StoreChannel
AnalyticsPostCount(teamId string, mustHaveFile bool, mustHaveHashtag bool) StoreChannel
@@ -150,7 +149,6 @@ type UserStore interface {
GetEtagForProfiles(teamId string) StoreChannel
GetEtagForDirectProfiles(userId string) StoreChannel
UpdateFailedPasswordAttempts(userId string, attempts int) StoreChannel
- GetForExport(teamId string) StoreChannel
GetTotalUsersCount() StoreChannel
GetTotalActiveUsersCount() StoreChannel
GetSystemAdminProfiles() StoreChannel
@@ -242,6 +240,7 @@ type PreferenceStore interface {
Get(userId string, category string, name string) StoreChannel
GetCategory(userId string, category string) StoreChannel
GetAll(userId string) StoreChannel
+ Delete(userId, category, name string) StoreChannel
PermanentDeleteByUser(userId string) StoreChannel
IsFeatureEnabled(feature, userId string) StoreChannel
}