summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api4/command.go26
-rw-r--r--api4/command_test.go96
-rw-r--r--app/import.go77
-rw-r--r--app/import_test.go80
-rw-r--r--app/post.go5
-rw-r--r--i18n/en.json16
-rw-r--r--model/emoji.go8
-rw-r--r--model/emoji_test.go5
-rw-r--r--model/user.go1
-rw-r--r--model/user_test.go1
-rw-r--r--store/sqlstore/upgrade.go10
11 files changed, 276 insertions, 49 deletions
diff --git a/api4/command.go b/api4/command.go
index 3ab2839ba..69efee010 100644
--- a/api4/command.go
+++ b/api4/command.go
@@ -4,7 +4,6 @@
package api4
import (
- "io/ioutil"
"net/http"
"strconv"
"strings"
@@ -22,9 +21,6 @@ func (api *API) InitCommand() {
api.BaseRoutes.Team.Handle("/commands/autocomplete", api.ApiSessionRequired(listAutocompleteCommands)).Methods("GET")
api.BaseRoutes.Command.Handle("/regen_token", api.ApiSessionRequired(regenCommandToken)).Methods("PUT")
-
- api.BaseRoutes.Teams.Handle("/command_test", api.ApiHandler(testCommand)).Methods("POST")
- api.BaseRoutes.Teams.Handle("/command_test", api.ApiHandler(testCommand)).Methods("GET")
}
func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -291,25 +287,3 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(resp)))
}
-
-func testCommand(c *Context, w http.ResponseWriter, r *http.Request) {
- r.ParseForm()
-
- msg := ""
- if r.Method == "POST" {
- msg = msg + "\ntoken=" + r.FormValue("token")
- msg = msg + "\nteam_domain=" + r.FormValue("team_domain")
- } else {
- body, _ := ioutil.ReadAll(r.Body)
- msg = string(body)
- }
-
- rc := &model.CommandResponse{
- Text: "test command response " + msg,
- ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL,
- Type: "custom_test",
- Props: map[string]interface{}{"someprop": "somevalue"},
- }
-
- w.Write([]byte(rc.ToJson()))
-}
diff --git a/api4/command_test.go b/api4/command_test.go
index 0d37d7440..96025c063 100644
--- a/api4/command_test.go
+++ b/api4/command_test.go
@@ -4,7 +4,6 @@
package api4
import (
- "fmt"
"net/http"
"net/http/httptest"
"net/url"
@@ -423,7 +422,7 @@ func TestExecuteInvalidCommand(t *testing.T) {
getCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: th.BasicTeam.Id,
- URL: fmt.Sprintf("%s/%s/teams/command_test", ts.URL, model.API_URL_SUFFIX_V4),
+ URL: ts.URL,
Method: model.COMMAND_METHOD_GET,
Trigger: "getcommand",
}
@@ -501,7 +500,7 @@ func TestExecuteGetCommand(t *testing.T) {
getCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: th.BasicTeam.Id,
- URL: fmt.Sprintf("%s/%s/teams/command_test", ts.URL, model.API_URL_SUFFIX_V4),
+ URL: ts.URL,
Method: model.COMMAND_METHOD_GET,
Trigger: "getcommand",
Token: token,
@@ -556,16 +555,16 @@ func TestExecutePostCommand(t *testing.T) {
}))
defer ts.Close()
- getCmd := &model.Command{
+ postCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: th.BasicTeam.Id,
- URL: fmt.Sprintf("%s/%s/teams/command_test", ts.URL, model.API_URL_SUFFIX_V4),
+ URL: ts.URL,
Method: model.COMMAND_METHOD_POST,
Trigger: "postcommand",
Token: token,
}
- if _, err := th.App.CreateCommand(getCmd); err != nil {
+ if _, err := th.App.CreateCommand(postCmd); err != nil {
t.Fatal("failed to create get command")
}
@@ -592,14 +591,29 @@ func TestExecuteCommandAgainstChannelOnAnotherTeam(t *testing.T) {
})
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
+ th.App.UpdateConfig(func(cfg *model.Config) {
+ *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
+ })
+
+ expectedCommandResponse := &model.CommandResponse{
+ Text: "test post command response",
+ ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL,
+ Type: "custom_test",
+ Props: map[string]interface{}{"someprop": "somevalue"},
+ }
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(expectedCommandResponse.ToJson()))
+ }))
+ defer ts.Close()
// create a slash command on some other team where we have permission to do so
team2 := th.CreateTeam()
postCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: team2.Id,
- URL: fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
+ URL: ts.URL,
Method: model.COMMAND_METHOD_POST,
Trigger: "postcommand",
}
@@ -627,14 +641,29 @@ func TestExecuteCommandAgainstChannelUserIsNotIn(t *testing.T) {
})
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
+ th.App.UpdateConfig(func(cfg *model.Config) {
+ *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
+ })
+
+ expectedCommandResponse := &model.CommandResponse{
+ Text: "test post command response",
+ ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL,
+ Type: "custom_test",
+ Props: map[string]interface{}{"someprop": "somevalue"},
+ }
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(expectedCommandResponse.ToJson()))
+ }))
+ defer ts.Close()
// create a slash command on some other team where we have permission to do so
team2 := th.CreateTeam()
postCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: team2.Id,
- URL: fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
+ URL: ts.URL,
Method: model.COMMAND_METHOD_POST,
Trigger: "postcommand",
}
@@ -667,14 +696,32 @@ func TestExecuteCommandInDirectMessageChannel(t *testing.T) {
})
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
+ th.App.UpdateConfig(func(cfg *model.Config) {
+ *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
+ })
- // create a slash command on some other team where we have permission to do so
+ // create a team that the user isn't a part of
team2 := th.CreateTeam()
+
+ expectedCommandResponse := &model.CommandResponse{
+ Text: "test post command response",
+ ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL,
+ Type: "custom_test",
+ Props: map[string]interface{}{"someprop": "somevalue"},
+ }
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ require.Equal(t, http.MethodPost, r.Method)
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(expectedCommandResponse.ToJson()))
+ }))
+ defer ts.Close()
+
+ // create a slash command on some other team where we have permission to do so
postCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: team2.Id,
- URL: fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
+ URL: ts.URL,
Method: model.COMMAND_METHOD_POST,
Trigger: "postcommand",
}
@@ -709,16 +756,35 @@ func TestExecuteCommandInTeamUserIsNotOn(t *testing.T) {
})
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
+ th.App.UpdateConfig(func(cfg *model.Config) {
+ *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
+ })
// create a team that the user isn't a part of
team2 := th.CreateTeam()
+ expectedCommandResponse := &model.CommandResponse{
+ Text: "test post command response",
+ ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL,
+ Type: "custom_test",
+ Props: map[string]interface{}{"someprop": "somevalue"},
+ }
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ require.Equal(t, http.MethodPost, r.Method)
+ r.ParseForm()
+ require.Equal(t, team2.Name, r.FormValue("team_domain"))
+
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(expectedCommandResponse.ToJson()))
+ }))
+ defer ts.Close()
+
// create a slash command on that team
postCmd := &model.Command{
CreatorId: th.BasicUser.Id,
TeamId: team2.Id,
- URL: fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
+ URL: ts.URL,
Method: model.COMMAND_METHOD_POST,
Trigger: "postcommand",
}
diff --git a/app/import.go b/app/import.go
index baf936567..12353d562 100644
--- a/app/import.go
+++ b/app/import.go
@@ -33,6 +33,7 @@ type LineImportData struct {
Post *PostImportData `json:"post"`
DirectChannel *DirectChannelImportData `json:"direct_channel"`
DirectPost *DirectPostImportData `json:"direct_post"`
+ Emoji *EmojiImportData `json:"emoji"`
Version *int `json:"version"`
}
@@ -114,6 +115,11 @@ type UserChannelNotifyPropsImportData struct {
MarkUnread *string `json:"mark_unread"`
}
+type EmojiImportData struct {
+ Name *string `json:"name"`
+ Image *string `json:"image"`
+}
+
type ReactionImportData struct {
User *string `json:"user"`
CreateAt *int64 `json:"create_at"`
@@ -337,6 +343,12 @@ func (a *App) ImportLine(line LineImportData, dryRun bool) *model.AppError {
} else {
return a.ImportDirectPost(line.DirectPost, dryRun)
}
+ case line.Type == "emoji":
+ if line.Emoji == nil {
+ return model.NewAppError("BulkImport", "app.import.import_line.null_emoji.error", nil, "", http.StatusBadRequest)
+ } else {
+ return a.ImportEmoji(line.Emoji, dryRun)
+ }
default:
return model.NewAppError("BulkImport", "app.import.import_line.unknown_line_type.error", map[string]interface{}{"Type": line.Type}, "", http.StatusBadRequest)
}
@@ -1925,6 +1937,71 @@ func validateDirectPostImportData(data *DirectPostImportData, maxPostSize int) *
return nil
}
+func (a *App) ImportEmoji(data *EmojiImportData, dryRun bool) *model.AppError {
+ if err := validateEmojiImportData(data); err != nil {
+ return err
+ }
+
+ // If this is a Dry Run, do not continue any further.
+ if dryRun {
+ return nil
+ }
+
+ var emoji *model.Emoji
+ var err *model.AppError
+
+ emoji, err = a.GetEmojiByName(*data.Name)
+ if err != nil && err.StatusCode != http.StatusNotFound {
+ return err
+ }
+
+ alreadyExists := emoji != nil
+
+ if !alreadyExists {
+ emoji = &model.Emoji{
+ Name: *data.Name,
+ }
+ emoji.PreSave()
+ }
+
+ file, fileErr := os.Open(*data.Image)
+ if fileErr != nil {
+ return model.NewAppError("BulkImport", "app.import.emoji.bad_file.error", map[string]interface{}{"EmojiName": *data.Name}, "", http.StatusBadRequest)
+ }
+
+ if _, err := a.WriteFile(file, getEmojiImagePath(emoji.Id)); err != nil {
+ return err
+ }
+
+ if !alreadyExists {
+ if result := <-a.Srv.Store.Emoji().Save(emoji); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ return nil
+}
+
+func validateEmojiImportData(data *EmojiImportData) *model.AppError {
+ if data == nil {
+ return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.empty.error", nil, "", http.StatusBadRequest)
+ }
+
+ if data.Name == nil || len(*data.Name) == 0 {
+ return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.name_missing.error", nil, "", http.StatusBadRequest)
+ }
+
+ if err := model.IsValidEmojiName(*data.Name); err != nil {
+ return err
+ }
+
+ if data.Image == nil || len(*data.Image) == 0 {
+ return model.NewAppError("BulkImport", "app.import.validate_emoji_import_data.image_missing.error", nil, "", http.StatusBadRequest)
+ }
+
+ return nil
+}
+
//
// -- Old SlackImport Functions --
// Import functions are sutible for entering posts and users into the database without
diff --git a/app/import_test.go b/app/import_test.go
index e7bc055a4..8a88937f9 100644
--- a/app/import_test.go
+++ b/app/import_test.go
@@ -3774,11 +3774,16 @@ func TestImportBulkImport(t *testing.T) {
th := Setup()
defer th.TearDown()
+ th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
+
teamName := model.NewId()
channelName := model.NewId()
username := model.NewId()
username2 := model.NewId()
username3 := model.NewId()
+ emojiName := model.NewId()
+ testsDir, _ := utils.FindDir("tests")
+ testImage := filepath.Join(testsDir, "test.png")
// Run bulk import with a valid 1 of everything.
data1 := `{"type": "version", "version": 1}
@@ -3791,7 +3796,8 @@ func TestImportBulkImport(t *testing.T) {
{"type": "direct_channel", "direct_channel": {"members": ["` + username + `", "` + username2 + `"]}}
{"type": "direct_channel", "direct_channel": {"members": ["` + username + `", "` + username2 + `", "` + username3 + `"]}}
{"type": "direct_post", "direct_post": {"channel_members": ["` + username + `", "` + username2 + `"], "user": "` + username + `", "message": "Hello Direct Channel", "create_at": 123456789013}}
-{"type": "direct_post", "direct_post": {"channel_members": ["` + username + `", "` + username2 + `", "` + username3 + `"], "user": "` + username + `", "message": "Hello Group Channel", "create_at": 123456789014}}`
+{"type": "direct_post", "direct_post": {"channel_members": ["` + username + `", "` + username2 + `", "` + username3 + `"], "user": "` + username + `", "message": "Hello Group Channel", "create_at": 123456789014}}
+{"type": "emoji", "emoji": {"name": "` + emojiName + `", "image": "` + testImage + `"}}`
if err, line := th.App.BulkImport(strings.NewReader(data1), false, 2); err != nil || line != 0 {
t.Fatalf("BulkImport should have succeeded: %v, %v", err.Error(), line)
@@ -3833,3 +3839,75 @@ func TestImportProcessImportDataFileVersionLine(t *testing.T) {
t.Fatalf("Expected error on invalid version line.")
}
}
+
+func TestImportValidateEmojiImportData(t *testing.T) {
+ data := EmojiImportData{
+ Name: ptrStr("parrot"),
+ Image: ptrStr("/path/to/image"),
+ }
+
+ err := validateEmojiImportData(&data)
+ assert.Nil(t, err, "Validation should succeed")
+
+ *data.Name = "smiley"
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ *data.Name = ""
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ *data.Name = ""
+ *data.Image = ""
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ *data.Image = "/path/to/image"
+ data.Name = nil
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+
+ data.Name = ptrStr("parrot")
+ data.Image = nil
+ err = validateEmojiImportData(&data)
+ assert.NotNil(t, err)
+}
+
+func TestImportImportEmoji(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
+
+ testsDir, _ := utils.FindDir("tests")
+ testImage := filepath.Join(testsDir, "test.png")
+
+ data := EmojiImportData{Name: ptrStr(model.NewId())}
+ err := th.App.ImportEmoji(&data, true)
+ assert.NotNil(t, err, "Invalid emoji should have failed dry run")
+
+ result := <-th.App.Srv.Store.Emoji().GetByName(*data.Name)
+ assert.Nil(t, result.Data, "Emoji should not have been imported")
+
+ data.Image = ptrStr(testImage)
+ err = th.App.ImportEmoji(&data, true)
+ assert.Nil(t, err, "Valid emoji should have passed dry run")
+
+ data = EmojiImportData{Name: ptrStr(model.NewId())}
+ err = th.App.ImportEmoji(&data, false)
+ assert.NotNil(t, err, "Invalid emoji should have failed apply mode")
+
+ data.Image = ptrStr("non-existent-file")
+ err = th.App.ImportEmoji(&data, false)
+ assert.NotNil(t, err, "Emoji with bad image file should have failed apply mode")
+
+ data.Image = ptrStr(testImage)
+ err = th.App.ImportEmoji(&data, false)
+ assert.Nil(t, err, "Valid emoji should have succeeded apply mode")
+
+ result = <-th.App.Srv.Store.Emoji().GetByName(*data.Name)
+ assert.NotNil(t, result.Data, "Emoji should have been imported")
+
+ err = th.App.ImportEmoji(&data, false)
+ assert.Nil(t, err, "Second run should have succeeded apply mode")
+}
diff --git a/app/post.go b/app/post.go
index e24018995..806263f5f 100644
--- a/app/post.go
+++ b/app/post.go
@@ -765,6 +765,11 @@ func (a *App) GetOpenGraphMetadata(requestURL string) *opengraph.OpenGraph {
makeOpenGraphURLsAbsolute(og, requestURL)
+ // The URL should be the link the user provided in their message, not a redirected one.
+ if og.URL != "" {
+ og.URL = requestURL
+ }
+
return og
}
diff --git a/i18n/en.json b/i18n/en.json
index 80693edbf..fc6d1c55b 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -2391,6 +2391,22 @@
"translation": "Cluster API endpoint not found."
},
{
+ "id": "app.import.emoji.bad_file.error",
+ "translation": "Error reading import emoji image file. Emoji with name: \"{{.EmojiName}}\""
+ },
+ {
+ "id": "app.import.validate_emoji_import_data.empty.error",
+ "translation": "Import emoji data empty."
+ },
+ {
+ "id": "app.import.validate_emoji_import_data.name_missing.error",
+ "translation": "Import emoji name field missing or blank."
+ },
+ {
+ "id": "app.import.validate_emoji_import_data.image_missing.error",
+ "translation": "Import emoji image field missing or blank."
+ },
+ {
"id": "app.import.bulk_import.file_scan.error",
"translation": "Error reading import data file."
},
diff --git a/model/emoji.go b/model/emoji.go
index 78a266386..f14af89df 100644
--- a/model/emoji.go
+++ b/model/emoji.go
@@ -41,11 +41,15 @@ func (emoji *Emoji) IsValid() *AppError {
return NewAppError("Emoji.IsValid", "model.emoji.update_at.app_error", nil, "id="+emoji.Id, http.StatusBadRequest)
}
- if len(emoji.CreatorId) != 26 {
+ if len(emoji.CreatorId) > 26 {
return NewAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "", http.StatusBadRequest)
}
- if len(emoji.Name) == 0 || len(emoji.Name) > EMOJI_NAME_MAX_LENGTH || !IsValidAlphaNumHyphenUnderscore(emoji.Name, false) || inSystemEmoji(emoji.Name) {
+ return IsValidEmojiName(emoji.Name)
+}
+
+func IsValidEmojiName(name string) *AppError {
+ if len(name) == 0 || len(name) > EMOJI_NAME_MAX_LENGTH || !IsValidAlphaNumHyphenUnderscore(name, false) || inSystemEmoji(name) {
return NewAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "", http.StatusBadRequest)
}
diff --git a/model/emoji_test.go b/model/emoji_test.go
index 95abe37c6..50d741214 100644
--- a/model/emoji_test.go
+++ b/model/emoji_test.go
@@ -40,11 +40,6 @@ func TestEmojiIsValid(t *testing.T) {
}
emoji.UpdateAt = 1234
- emoji.CreatorId = strings.Repeat("1", 25)
- if err := emoji.IsValid(); err == nil {
- t.Fatal()
- }
-
emoji.CreatorId = strings.Repeat("1", 27)
if err := emoji.IsValid(); err == nil {
t.Fatal()
diff --git a/model/user.go b/model/user.go
index c5d6c13b6..e56f3aaed 100644
--- a/model/user.go
+++ b/model/user.go
@@ -565,6 +565,7 @@ var restrictedUsernames = []string{
"all",
"channel",
"matterbot",
+ "system",
}
func IsValidUsername(s string) bool {
diff --git a/model/user_test.go b/model/user_test.go
index 645eaadff..a1953a40d 100644
--- a/model/user_test.go
+++ b/model/user_test.go
@@ -272,6 +272,7 @@ var usernames = []struct {
{"spin'punch", false},
{"spin*punch", false},
{"all", false},
+ {"system", false},
}
func TestValidUsername(t *testing.T) {
diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go
index 868575522..8ea44371c 100644
--- a/store/sqlstore/upgrade.go
+++ b/store/sqlstore/upgrade.go
@@ -15,6 +15,7 @@ import (
)
const (
+ VERSION_5_2_0 = "5.2.0"
VERSION_5_1_0 = "5.1.0"
VERSION_5_0_0 = "5.0.0"
VERSION_4_10_0 = "4.10.0"
@@ -80,6 +81,7 @@ func UpgradeDatabase(sqlStore SqlStore) {
UpgradeDatabaseToVersion410(sqlStore)
UpgradeDatabaseToVersion50(sqlStore)
UpgradeDatabaseToVersion51(sqlStore)
+ UpgradeDatabaseToVersion52(sqlStore)
// If the SchemaVersion is empty this this is the first time it has ran
// so lets set it to the current version.
@@ -470,3 +472,11 @@ func UpgradeDatabaseToVersion51(sqlStore SqlStore) {
saveSchemaVersion(sqlStore, VERSION_5_1_0)
}
}
+
+func UpgradeDatabaseToVersion52(sqlStore SqlStore) {
+ // TODO: Uncomment following condition when version 5.2.0 is released
+ // if shouldPerformUpgrade(sqlStore, VERSION_5_1_0, VERSION_5_2_0) {
+
+ // saveSchemaVersion(sqlStore, VERSION_5_2_0)
+ // }
+}