summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-04-27 10:55:03 -0400
committerJoram Wilander <jwawilander@gmail.com>2017-04-27 10:55:03 -0400
commit9a87bb3af68216b53ee8f89d6604c715c7b85b2d (patch)
tree8c06aed890f388b228f3aefb8e398309bc73c0b9 /store
parent0e007e344bf10993529711f14c4168365c3504c3 (diff)
downloadchat-9a87bb3af68216b53ee8f89d6604c715c7b85b2d.tar.gz
chat-9a87bb3af68216b53ee8f89d6604c715c7b85b2d.tar.bz2
chat-9a87bb3af68216b53ee8f89d6604c715c7b85b2d.zip
Creating common token store and moving email invites and verification to it (#6213)
Diffstat (limited to 'store')
-rw-r--r--store/sql_recovery_store.go128
-rw-r--r--store/sql_recovery_store_test.go54
-rw-r--r--store/sql_store.go28
-rw-r--r--store/sql_tokens_store.go108
-rw-r--r--store/sql_upgrade.go1
-rw-r--r--store/store.go12
6 files changed, 137 insertions, 194 deletions
diff --git a/store/sql_recovery_store.go b/store/sql_recovery_store.go
deleted file mode 100644
index 6c073a548..000000000
--- a/store/sql_recovery_store.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-package store
-
-import (
- "database/sql"
- "net/http"
-
- "github.com/mattermost/platform/model"
-)
-
-type SqlPasswordRecoveryStore struct {
- *SqlStore
-}
-
-func NewSqlPasswordRecoveryStore(sqlStore *SqlStore) PasswordRecoveryStore {
- s := &SqlPasswordRecoveryStore{sqlStore}
-
- for _, db := range sqlStore.GetAllConns() {
- table := db.AddTableWithName(model.PasswordRecovery{}, "PasswordRecovery").SetKeys(false, "UserId")
- table.ColMap("UserId").SetMaxSize(26)
- table.ColMap("Code").SetMaxSize(128)
- }
-
- return s
-}
-
-func (s SqlPasswordRecoveryStore) CreateIndexesIfNotExists() {
- s.CreateIndexIfNotExists("idx_password_recovery_code", "PasswordRecovery", "Code")
-}
-
-func (s SqlPasswordRecoveryStore) SaveOrUpdate(recovery *model.PasswordRecovery) StoreChannel {
-
- storeChannel := make(StoreChannel, 1)
-
- go func() {
- result := StoreResult{}
-
- recovery.PreSave()
- if result.Err = recovery.IsValid(); result.Err != nil {
- storeChannel <- result
- close(storeChannel)
- return
- }
-
- if err := s.GetReplica().SelectOne(&model.PasswordRecovery{}, "SELECT * FROM PasswordRecovery WHERE UserId = :UserId", map[string]interface{}{"UserId": recovery.UserId}); err == nil {
- if _, err := s.GetMaster().Update(recovery); err != nil {
- result.Err = model.NewLocAppError("SqlPasswordRecoveryStore.SaveOrUpdate", "store.sql_recover.update.app_error", nil, "")
- }
- } else {
- if err := s.GetMaster().Insert(recovery); err != nil {
- result.Err = model.NewLocAppError("SqlPasswordRecoveryStore.SaveOrUpdate", "store.sql_recover.save.app_error", nil, "")
- }
- }
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
-
-func (s SqlPasswordRecoveryStore) Delete(userId string) StoreChannel {
-
- storeChannel := make(StoreChannel, 1)
-
- go func() {
- result := StoreResult{}
-
- if _, err := s.GetMaster().Exec("DELETE FROM PasswordRecovery WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
- result.Err = model.NewLocAppError("SqlPasswordRecoveryStore.Delete", "store.sql_recover.delete.app_error", nil, "")
- }
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
-
-func (s SqlPasswordRecoveryStore) Get(userId string) StoreChannel {
-
- storeChannel := make(StoreChannel, 1)
-
- go func() {
- result := StoreResult{}
-
- recovery := model.PasswordRecovery{}
-
- if err := s.GetReplica().SelectOne(&recovery, "SELECT * FROM PasswordRecovery WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
- result.Err = model.NewLocAppError("SqlPasswordRecoveryStore.Get", "store.sql_recover.get.app_error", nil, "")
- }
-
- result.Data = &recovery
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
-
-func (s SqlPasswordRecoveryStore) GetByCode(code string) StoreChannel {
-
- storeChannel := make(StoreChannel, 1)
-
- go func() {
- result := StoreResult{}
-
- recovery := model.PasswordRecovery{}
-
- if err := s.GetReplica().SelectOne(&recovery, "SELECT * FROM PasswordRecovery WHERE Code = :Code", map[string]interface{}{"Code": code}); err != nil {
- if err == sql.ErrNoRows {
- result.Err = model.NewAppError("SqlPasswordRecoveryStore.GetByCode", "store.sql_recover.get_by_code.app_error", nil, "", http.StatusBadRequest)
- } else {
- result.Err = model.NewAppError("SqlPasswordRecoveryStore.GetByCode", "store.sql_recover.get_by_code.app_error", nil, "", http.StatusInternalServerError)
- }
- }
-
- result.Data = &recovery
-
- storeChannel <- result
- close(storeChannel)
- }()
-
- return storeChannel
-}
diff --git a/store/sql_recovery_store_test.go b/store/sql_recovery_store_test.go
deleted file mode 100644
index 39f5c068b..000000000
--- a/store/sql_recovery_store_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-package store
-
-import (
- "github.com/mattermost/platform/model"
- "testing"
-)
-
-func TestSqlPasswordRecoveryGet(t *testing.T) {
- Setup()
-
- recovery := &model.PasswordRecovery{UserId: "12345678901234567890123456"}
- Must(store.PasswordRecovery().SaveOrUpdate(recovery))
-
- result := <-store.PasswordRecovery().Get(recovery.UserId)
- rrecovery := result.Data.(*model.PasswordRecovery)
- if rrecovery.Code != recovery.Code {
- t.Fatal("codes didn't match")
- }
-
- result2 := <-store.PasswordRecovery().GetByCode(recovery.Code)
- rrecovery2 := result2.Data.(*model.PasswordRecovery)
- if rrecovery2.Code != recovery.Code {
- t.Fatal("codes didn't match")
- }
-}
-
-func TestSqlPasswordRecoverySaveOrUpdate(t *testing.T) {
- Setup()
-
- recovery := &model.PasswordRecovery{UserId: "12345678901234567890123456"}
-
- if err := (<-store.PasswordRecovery().SaveOrUpdate(recovery)).Err; err != nil {
- t.Fatal(err)
- }
-
- // not duplicate, testing update
- if err := (<-store.PasswordRecovery().SaveOrUpdate(recovery)).Err; err != nil {
- t.Fatal(err)
- }
-}
-
-func TestSqlPasswordRecoveryDelete(t *testing.T) {
- Setup()
-
- recovery := &model.PasswordRecovery{UserId: "12345678901234567890123456"}
- Must(store.PasswordRecovery().SaveOrUpdate(recovery))
-
- if err := (<-store.PasswordRecovery().Delete(recovery.UserId)).Err; err != nil {
- t.Fatal(err)
- }
-}
diff --git a/store/sql_store.go b/store/sql_store.go
index 466042ca2..0d921d07d 100644
--- a/store/sql_store.go
+++ b/store/sql_store.go
@@ -62,6 +62,7 @@ const (
EXIT_REMOVE_INDEX_POSTGRES = 121
EXIT_REMOVE_INDEX_MYSQL = 122
EXIT_REMOVE_INDEX_MISSING = 123
+ EXIT_REMOVE_TABLE = 134
)
type SqlStore struct {
@@ -80,7 +81,7 @@ type SqlStore struct {
command CommandStore
preference PreferenceStore
license LicenseStore
- recovery PasswordRecoveryStore
+ token TokenStore
emoji EmojiStore
status StatusStore
fileInfo FileInfoStore
@@ -131,7 +132,7 @@ func NewSqlStore() Store {
sqlStore.command = NewSqlCommandStore(sqlStore)
sqlStore.preference = NewSqlPreferenceStore(sqlStore)
sqlStore.license = NewSqlLicenseStore(sqlStore)
- sqlStore.recovery = NewSqlPasswordRecoveryStore(sqlStore)
+ sqlStore.token = NewSqlTokenStore(sqlStore)
sqlStore.emoji = NewSqlEmojiStore(sqlStore)
sqlStore.status = NewSqlStatusStore(sqlStore)
sqlStore.fileInfo = NewSqlFileInfoStore(sqlStore)
@@ -159,7 +160,7 @@ func NewSqlStore() Store {
sqlStore.command.(*SqlCommandStore).CreateIndexesIfNotExists()
sqlStore.preference.(*SqlPreferenceStore).CreateIndexesIfNotExists()
sqlStore.license.(*SqlLicenseStore).CreateIndexesIfNotExists()
- sqlStore.recovery.(*SqlPasswordRecoveryStore).CreateIndexesIfNotExists()
+ sqlStore.token.(*SqlTokenStore).CreateIndexesIfNotExists()
sqlStore.emoji.(*SqlEmojiStore).CreateIndexesIfNotExists()
sqlStore.status.(*SqlStatusStore).CreateIndexesIfNotExists()
sqlStore.fileInfo.(*SqlFileInfoStore).CreateIndexesIfNotExists()
@@ -388,7 +389,7 @@ func (ss *SqlStore) RemoveColumnIfExists(tableName string, columnName string) bo
_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
if err != nil {
- l4g.Critical(utils.T("store.sql.drop_column.critical"), err)
+ l4g.Critical("Failed to drop column %v", err)
time.Sleep(time.Second)
os.Exit(EXIT_REMOVE_COLUMN)
}
@@ -396,6 +397,21 @@ func (ss *SqlStore) RemoveColumnIfExists(tableName string, columnName string) bo
return true
}
+func (ss *SqlStore) RemoveTableIfExists(tableName string) bool {
+ if !ss.DoesTableExist(tableName) {
+ return false
+ }
+
+ _, err := ss.GetMaster().Exec("DROP TABLE " + tableName)
+ if err != nil {
+ l4g.Critical("Failed to drop table %v", err)
+ time.Sleep(time.Second)
+ os.Exit(EXIT_REMOVE_TABLE)
+ }
+
+ return true
+}
+
func (ss *SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
if !ss.DoesColumnExist(tableName, oldColumnName) {
return false
@@ -667,8 +683,8 @@ func (ss *SqlStore) License() LicenseStore {
return ss.license
}
-func (ss *SqlStore) PasswordRecovery() PasswordRecoveryStore {
- return ss.recovery
+func (ss *SqlStore) Token() TokenStore {
+ return ss.token
}
func (ss *SqlStore) Emoji() EmojiStore {
diff --git a/store/sql_tokens_store.go b/store/sql_tokens_store.go
new file mode 100644
index 000000000..3ee03b549
--- /dev/null
+++ b/store/sql_tokens_store.go
@@ -0,0 +1,108 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package store
+
+import (
+ "database/sql"
+ "net/http"
+
+ l4g "github.com/alecthomas/log4go"
+
+ "github.com/mattermost/platform/model"
+)
+
+type SqlTokenStore struct {
+ *SqlStore
+}
+
+func NewSqlTokenStore(sqlStore *SqlStore) TokenStore {
+ s := &SqlTokenStore{sqlStore}
+
+ for _, db := range sqlStore.GetAllConns() {
+ table := db.AddTableWithName(model.Token{}, "Tokens").SetKeys(false, "Token")
+ table.ColMap("Type").SetMaxSize(64)
+ table.ColMap("Extra").SetMaxSize(128)
+ }
+
+ return s
+}
+
+func (s SqlTokenStore) CreateIndexesIfNotExists() {
+}
+
+func (s SqlTokenStore) Save(token *model.Token) StoreChannel {
+
+ storeChannel := make(StoreChannel, 1)
+
+ go func() {
+ result := StoreResult{}
+
+ if result.Err = token.IsValid(); result.Err != nil {
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+
+ if err := s.GetMaster().Insert(token); err != nil {
+ result.Err = model.NewLocAppError("SqlTokenStore.Save", "store.sql_recover.save.app_error", nil, "")
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlTokenStore) Delete(token string) StoreChannel {
+
+ storeChannel := make(StoreChannel, 1)
+
+ go func() {
+ result := StoreResult{}
+
+ if _, err := s.GetMaster().Exec("DELETE FROM Tokens WHERE Token = :Token", map[string]interface{}{"Token": token}); err != nil {
+ result.Err = model.NewLocAppError("SqlTokenStore.Delete", "store.sql_recover.delete.app_error", nil, "")
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlTokenStore) GetByToken(tokenString string) StoreChannel {
+
+ storeChannel := make(StoreChannel, 1)
+
+ go func() {
+ result := StoreResult{}
+
+ token := model.Token{}
+
+ if err := s.GetReplica().SelectOne(&token, "SELECT * FROM Tokens WHERE Token = :Token", map[string]interface{}{"Token": tokenString}); err != nil {
+ if err == sql.ErrNoRows {
+ result.Err = model.NewAppError("SqlTokenStore.GetByToken", "store.sql_recover.get_by_code.app_error", nil, err.Error(), http.StatusBadRequest)
+ } else {
+ result.Err = model.NewAppError("SqlTokenStore.GetByToken", "store.sql_recover.get_by_code.app_error", nil, err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ result.Data = &token
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlTokenStore) Cleanup() {
+ l4g.Debug("Cleaning up token store.")
+ deltime := model.GetMillis() - model.MAX_TOKEN_EXIPRY_TIME
+ if _, err := s.GetMaster().Exec("DELETE FROM Tokens WHERE CreateAt < :DelTime", map[string]interface{}{"DelTime": deltime}); err != nil {
+ l4g.Error("Unable to cleanup token store.")
+ }
+}
diff --git a/store/sql_upgrade.go b/store/sql_upgrade.go
index b25e7e73d..f708f15c5 100644
--- a/store/sql_upgrade.go
+++ b/store/sql_upgrade.go
@@ -258,6 +258,7 @@ func UpgradeDatabaseToVersion39(sqlStore *SqlStore) {
// TODO: Uncomment following condition when version 3.9.0 is released
//if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) {
sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
+ sqlStore.RemoveTableIfExists("PasswordRecovery")
// saveSchemaVersion(sqlStore, VERSION_3_9_0)
//}
diff --git a/store/store.go b/store/store.go
index 18f7374dc..570695bfe 100644
--- a/store/store.go
+++ b/store/store.go
@@ -42,7 +42,7 @@ type Store interface {
Command() CommandStore
Preference() PreferenceStore
License() LicenseStore
- PasswordRecovery() PasswordRecoveryStore
+ Token() TokenStore
Emoji() EmojiStore
Status() StatusStore
FileInfo() FileInfoStore
@@ -322,11 +322,11 @@ type LicenseStore interface {
Get(id string) StoreChannel
}
-type PasswordRecoveryStore interface {
- SaveOrUpdate(recovery *model.PasswordRecovery) StoreChannel
- Delete(userId string) StoreChannel
- Get(userId string) StoreChannel
- GetByCode(code string) StoreChannel
+type TokenStore interface {
+ Save(recovery *model.Token) StoreChannel
+ Delete(token string) StoreChannel
+ GetByToken(token string) StoreChannel
+ Cleanup()
}
type EmojiStore interface {