summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-01-13 13:53:37 -0500
committerGitHub <noreply@github.com>2017-01-13 13:53:37 -0500
commit97558f6a6ec4c53fa69035fb430ead209d9c222d (patch)
tree6fc57f5b75b15a025348c6e295cea6aedb9e69ae
parent07bad4d6d518a9012a20fec8309cd625f57c7a8c (diff)
downloadchat-97558f6a6ec4c53fa69035fb430ead209d9c222d.tar.gz
chat-97558f6a6ec4c53fa69035fb430ead209d9c222d.tar.bz2
chat-97558f6a6ec4c53fa69035fb430ead209d9c222d.zip
PLT-4938 Add app package and move logic over from api package (#4931)
* Add app package and move logic over from api package * Change app package functions to return errors * Move non-api tests into app package * Fix merge
-rw-r--r--Makefile4
-rw-r--r--api/admin.go63
-rw-r--r--api/admin_test.go9
-rw-r--r--api/api.go19
-rw-r--r--api/apitestlib.go39
-rw-r--r--api/authentication.go5
-rw-r--r--api/authorization.go9
-rw-r--r--api/auto_users.go9
-rw-r--r--api/channel.go333
-rw-r--r--api/channel_test.go7
-rw-r--r--api/cli_test.go7
-rw-r--r--api/command.go34
-rw-r--r--api/command_away.go3
-rw-r--r--api/command_echo.go3
-rw-r--r--api/command_expand_collapse.go5
-rw-r--r--api/command_invite_people.go5
-rw-r--r--api/command_join.go3
-rw-r--r--api/command_loadtest.go13
-rw-r--r--api/command_msg.go9
-rw-r--r--api/command_offline.go3
-rw-r--r--api/command_online.go3
-rw-r--r--api/context.go149
-rw-r--r--api/context_test.go23
-rw-r--r--api/deprecated.go19
-rw-r--r--api/emoji.go15
-rw-r--r--api/emoji_test.go11
-rw-r--r--api/file.go19
-rw-r--r--api/file_test.go45
-rw-r--r--api/general.go3
-rw-r--r--api/import.go13
-rw-r--r--api/license.go13
-rw-r--r--api/oauth.go135
-rw-r--r--api/post.go1176
-rw-r--r--api/post_test.go347
-rw-r--r--api/preference.go11
-rw-r--r--api/reaction.go19
-rw-r--r--api/slackimport.go17
-rw-r--r--api/status.go257
-rw-r--r--api/status_test.go11
-rw-r--r--api/team.go181
-rw-r--r--api/team_test.go27
-rw-r--r--api/user.go271
-rw-r--r--api/user_test.go79
-rw-r--r--api/webhook.go45
-rw-r--r--api/webrtc.go12
-rw-r--r--api/websocket.go22
-rw-r--r--api/websocket_handler.go20
-rw-r--r--api/websocket_test.go5
-rw-r--r--app/apptestlib.go191
-rw-r--r--app/channel.go216
-rw-r--r--app/command.go31
-rw-r--r--app/email_batching.go (renamed from api/email_batching.go)4
-rw-r--r--app/email_batching_test.go (renamed from api/email_batching_test.go)2
-rw-r--r--app/notification.go732
-rw-r--r--app/notification_test.go312
-rw-r--r--app/post.go196
-rw-r--r--app/server.go (renamed from api/server.go)52
-rw-r--r--app/session.go94
-rw-r--r--app/session_test.go31
-rw-r--r--app/status.go255
-rw-r--r--app/team.go82
-rw-r--r--app/user.go60
-rw-r--r--app/web_conn.go (renamed from api/web_conn.go)42
-rw-r--r--app/web_hub.go (renamed from api/web_hub.go)4
-rw-r--r--app/webhook.go155
-rw-r--r--app/websocket_router.go (renamed from api/websocket_router.go)30
-rw-r--r--cmd/platform/channel.go15
-rw-r--r--cmd/platform/channelargs.go6
-rw-r--r--cmd/platform/init.go5
-rw-r--r--cmd/platform/mattermost.go4
-rw-r--r--cmd/platform/oldcommands.go86
-rw-r--r--cmd/platform/server.go37
-rw-r--r--cmd/platform/team.go9
-rw-r--r--cmd/platform/teamargs.go6
-rw-r--r--cmd/platform/test.go5
-rw-r--r--cmd/platform/user.go7
-rw-r--r--cmd/platform/userargs.go8
-rw-r--r--cmd/platform/version.go4
-rw-r--r--i18n/en.json54
-rw-r--r--manualtesting/manual_testing.go22
-rw-r--r--model/websocket_client.go4
-rw-r--r--utils/config.go10
-rw-r--r--utils/utils.go18
-rw-r--r--web/web.go3
-rw-r--r--web/web_test.go43
85 files changed, 3368 insertions, 2997 deletions
diff --git a/Makefile b/Makefile
index 5d5cae1e8..b4d243fdf 100644
--- a/Makefile
+++ b/Makefile
@@ -184,17 +184,19 @@ test-server: start-docker prepare-enterprise
echo "mode: count" > cover.out
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=650s -covermode=count -coverprofile=capi.out ./api || exit 1
+ $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=60s -covermode=count -coverprofile=capp.out ./app || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=60s -covermode=count -coverprofile=cmodel.out ./model || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s -covermode=count -coverprofile=cstore.out ./store || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s -covermode=count -coverprofile=cutils.out ./utils || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s -covermode=count -coverprofile=cweb.out ./web || exit 1
tail -n +2 capi.out >> cover.out
+ tail -n +2 capp.out >> cover.out
tail -n +2 cmodel.out >> cover.out
tail -n +2 cstore.out >> cover.out
tail -n +2 cutils.out >> cover.out
tail -n +2 cweb.out >> cover.out
- rm -f capi.out cmodel.out cstore.out cutils.out cweb.out
+ rm -f capi.out capp.out cmodel.out cstore.out cutils.out cweb.out
ifeq ($(BUILD_ENTERPRISE_READY),true)
@echo Running Enterprise tests
diff --git a/api/admin.go b/api/admin.go
index 6ec76caae..2b5afc47a 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -17,6 +17,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
@@ -106,7 +107,7 @@ func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getAllAudits(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-Srv.Store.Audit().Get("", 200); result.Err != nil {
+ if result := <-app.Srv.Store.Audit().Get("", 200); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -141,7 +142,7 @@ func reloadConfig(c *Context, w http.ResponseWriter, r *http.Request) {
utils.LoadConfig(utils.CfgFileName)
// start/restart email batching job if necessary
- InitEmailBatching()
+ app.InitEmailBatching()
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
ReturnStatusOK(w)
@@ -150,7 +151,7 @@ func reloadConfig(c *Context, w http.ResponseWriter, r *http.Request) {
func invalidateAllCaches(c *Context, w http.ResponseWriter, r *http.Request) {
debug.FreeOSMemory()
- InvalidateAllCaches()
+ app.InvalidateAllCaches()
if einterfaces.GetClusterInterface() != nil {
err := einterfaces.GetClusterInterface().InvalidateAllCaches()
@@ -214,7 +215,7 @@ func saveConfig(c *Context, w http.ResponseWriter, r *http.Request) {
// }
// start/restart email batching job if necessary
- InitEmailBatching()
+ app.InitEmailBatching()
rdata := map[string]string{}
rdata["status"] = "OK"
@@ -222,10 +223,10 @@ func saveConfig(c *Context, w http.ResponseWriter, r *http.Request) {
}
func recycleDatabaseConnection(c *Context, w http.ResponseWriter, r *http.Request) {
- oldStore := Srv.Store
+ oldStore := app.Srv.Store
l4g.Warn(utils.T("api.admin.recycle_db_start.warn"))
- Srv.Store = store.NewSqlStore()
+ app.Srv.Store = store.NewSqlStore()
time.Sleep(20 * time.Second)
oldStore.Close()
@@ -261,7 +262,7 @@ func testEmail(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -282,7 +283,7 @@ func getComplianceReports(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Compliance().GetAll(); result.Err != nil {
+ if result := <-app.Srv.Store.Compliance().GetAll(); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -306,7 +307,7 @@ func saveComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
job.UserId = c.Session.UserId
job.Type = model.COMPLIANCE_TYPE_ADHOC
- if result := <-Srv.Store.Compliance().Save(job); result.Err != nil {
+ if result := <-app.Srv.Store.Compliance().Save(job); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -331,7 +332,7 @@ func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request
return
}
- if result := <-Srv.Store.Compliance().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.Compliance().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -369,7 +370,7 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
skipIntensiveQueries := false
var systemUserCount int64
- if r := <-Srv.Store.User().AnalyticsUniqueUserCount(""); r.Err != nil {
+ if r := <-app.Srv.Store.User().AnalyticsUniqueUserCount(""); r.Err != nil {
c.Err = r.Err
return
} else {
@@ -391,18 +392,18 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
rows[6] = &model.AnalyticsRow{"total_master_db_connections", 0}
rows[7] = &model.AnalyticsRow{"total_read_db_connections", 0}
- openChan := Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_OPEN)
- privateChan := Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_PRIVATE)
- teamChan := Srv.Store.Team().AnalyticsTeamCount()
+ openChan := app.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_OPEN)
+ privateChan := app.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_PRIVATE)
+ teamChan := app.Srv.Store.Team().AnalyticsTeamCount()
var userChan store.StoreChannel
if teamId != "" {
- userChan = Srv.Store.User().AnalyticsUniqueUserCount(teamId)
+ userChan = app.Srv.Store.User().AnalyticsUniqueUserCount(teamId)
}
var postChan store.StoreChannel
if !skipIntensiveQueries {
- postChan = Srv.Store.Post().AnalyticsPostCount(teamId, false, false)
+ postChan = app.Srv.Store.Post().AnalyticsPostCount(teamId, false, false)
}
if r := <-openChan; r.Err != nil {
@@ -456,9 +457,9 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- totalSockets := TotalWebsocketConnections()
- totalMasterDb := Srv.Store.TotalMasterDbConnections()
- totalReadDb := Srv.Store.TotalReadDbConnections()
+ totalSockets := app.TotalWebsocketConnections()
+ totalMasterDb := app.Srv.Store.TotalMasterDbConnections()
+ totalReadDb := app.Srv.Store.TotalReadDbConnections()
for _, stat := range stats {
totalSockets = totalSockets + stat.TotalWebsocketConnections
@@ -471,9 +472,9 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
rows[7].Value = float64(totalReadDb)
} else {
- rows[5].Value = float64(TotalWebsocketConnections())
- rows[6].Value = float64(Srv.Store.TotalMasterDbConnections())
- rows[7].Value = float64(Srv.Store.TotalReadDbConnections())
+ rows[5].Value = float64(app.TotalWebsocketConnections())
+ rows[6].Value = float64(app.Srv.Store.TotalMasterDbConnections())
+ rows[7].Value = float64(app.Srv.Store.TotalReadDbConnections())
}
w.Write([]byte(rows.ToJson()))
@@ -484,7 +485,7 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if r := <-Srv.Store.Post().AnalyticsPostCountsByDay(teamId); r.Err != nil {
+ if r := <-app.Srv.Store.Post().AnalyticsPostCountsByDay(teamId); r.Err != nil {
c.Err = r.Err
return
} else {
@@ -497,7 +498,7 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if r := <-Srv.Store.Post().AnalyticsUserCountsWithPostsByDay(teamId); r.Err != nil {
+ if r := <-app.Srv.Store.Post().AnalyticsUserCountsWithPostsByDay(teamId); r.Err != nil {
c.Err = r.Err
return
} else {
@@ -512,16 +513,16 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
rows[4] = &model.AnalyticsRow{"command_count", 0}
rows[5] = &model.AnalyticsRow{"session_count", 0}
- iHookChan := Srv.Store.Webhook().AnalyticsIncomingCount(teamId)
- oHookChan := Srv.Store.Webhook().AnalyticsOutgoingCount(teamId)
- commandChan := Srv.Store.Command().AnalyticsCommandCount(teamId)
- sessionChan := Srv.Store.Session().AnalyticsSessionCount()
+ iHookChan := app.Srv.Store.Webhook().AnalyticsIncomingCount(teamId)
+ oHookChan := app.Srv.Store.Webhook().AnalyticsOutgoingCount(teamId)
+ commandChan := app.Srv.Store.Command().AnalyticsCommandCount(teamId)
+ sessionChan := app.Srv.Store.Session().AnalyticsSessionCount()
var fileChan store.StoreChannel
var hashtagChan store.StoreChannel
if !skipIntensiveQueries {
- fileChan = Srv.Store.Post().AnalyticsPostCount(teamId, true, false)
- hashtagChan = Srv.Store.Post().AnalyticsPostCount(teamId, false, true)
+ fileChan = app.Srv.Store.Post().AnalyticsPostCount(teamId, true, false)
+ hashtagChan = app.Srv.Store.Post().AnalyticsPostCount(teamId, false, true)
}
if fileChan == nil {
@@ -821,7 +822,7 @@ func samlCertificateStatus(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getRecentlyActiveUsers(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-Srv.Store.User().GetRecentlyActiveUsersForTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetRecentlyActiveUsersForTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
diff --git a/api/admin_test.go b/api/admin_test.go
index 3af45892d..f97d76855 100644
--- a/api/admin_test.go
+++ b/api/admin_test.go
@@ -7,6 +7,7 @@ import (
"strings"
"testing"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -333,7 +334,7 @@ func TestGetPostCount(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
// manually update creation time, since it's always set to 0 upon saving and we only retrieve posts < today
- Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
+ app.Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
map[string]interface{}{"ChannelId": th.BasicChannel.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())})
if _, err := th.BasicClient.GetTeamAnalytics(th.BasicTeam.Id, "post_counts_day"); err == nil {
@@ -375,7 +376,7 @@ func TestUserCountsWithPostsByDay(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
// manually update creation time, since it's always set to 0 upon saving and we only retrieve posts < today
- Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
+ app.Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
map[string]interface{}{"ChannelId": th.BasicChannel.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())})
if _, err := th.BasicClient.GetTeamAnalytics(th.BasicTeam.Id, "user_counts_with_posts_day"); err == nil {
@@ -579,7 +580,7 @@ func TestAdminResetPassword(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.AdminResetPassword("", "newpwd1"); err == nil {
t.Fatal("Should have errored - empty user id")
@@ -601,7 +602,7 @@ func TestAdminResetPassword(t *testing.T) {
user2 := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", AuthData: &authData, AuthService: "random"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.AdminResetPassword(user.Id, "newpwd1"); err != nil {
t.Fatal(err)
diff --git a/api/api.go b/api/api.go
index 122a6b933..59c547b8c 100644
--- a/api/api.go
+++ b/api/api.go
@@ -7,6 +7,7 @@ import (
"net/http"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
@@ -53,16 +54,20 @@ type Routes struct {
Emoji *mux.Router // 'api/v3/emoji'
Webrtc *mux.Router // 'api/v3/webrtc'
-
- WebSocket *WebSocketRouter // websocket api
}
var BaseRoutes *Routes
+func InitRouter() {
+ app.Srv.Router = mux.NewRouter()
+ app.Srv.Router.NotFoundHandler = http.HandlerFunc(Handle404)
+ app.Srv.WebSocketRouter = app.NewWebSocketRouter()
+}
+
func InitApi() {
BaseRoutes = &Routes{}
- BaseRoutes.Root = Srv.Router
- BaseRoutes.ApiRoot = Srv.Router.PathPrefix(model.API_URL_SUFFIX).Subrouter()
+ BaseRoutes.Root = app.Srv.Router
+ BaseRoutes.ApiRoot = app.Srv.Router.PathPrefix(model.API_URL_SUFFIX).Subrouter()
BaseRoutes.Users = BaseRoutes.ApiRoot.PathPrefix("/users").Subrouter()
BaseRoutes.NeedUser = BaseRoutes.Users.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()
BaseRoutes.Teams = BaseRoutes.ApiRoot.PathPrefix("/teams").Subrouter()
@@ -86,8 +91,6 @@ func InitApi() {
BaseRoutes.Emoji = BaseRoutes.ApiRoot.PathPrefix("/emoji").Subrouter()
BaseRoutes.Webrtc = BaseRoutes.ApiRoot.PathPrefix("/webrtc").Subrouter()
- BaseRoutes.WebSocket = NewWebSocketRouter()
-
InitUser()
InitTeam()
InitChannel()
@@ -108,11 +111,11 @@ func InitApi() {
InitDeprecated()
// 404 on any api route before web.go has a chance to serve it
- Srv.Router.Handle("/api/{anything:.*}", http.HandlerFunc(Handle404))
+ app.Srv.Router.Handle("/api/{anything:.*}", http.HandlerFunc(Handle404))
utils.InitHTML()
- InitEmailBatching()
+ app.InitEmailBatching()
}
func HandleEtag(etag string, routeName string, w http.ResponseWriter, r *http.Request) bool {
diff --git a/api/apitestlib.go b/api/apitestlib.go
index 8fb030488..cd54c8e2a 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -6,6 +6,7 @@ package api
import (
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -28,7 +29,7 @@ type TestHelper struct {
}
func SetupEnterprise() *TestHelper {
- if Srv == nil {
+ if app.Srv == nil {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
@@ -36,14 +37,14 @@ func SetupEnterprise() *TestHelper {
*utils.Cfg.RateLimitSettings.Enable = false
utils.DisableDebugLogForTest()
utils.License.Features.SetDefaults()
- NewServer()
- InitStores()
+ app.NewServer()
+ app.InitStores()
InitRouter()
- StartServer()
+ app.StartServer()
utils.InitHTML()
InitApi()
utils.EnableDebugLogForTest()
- Srv.Store.MarkSystemRanUnitTests()
+ app.Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true
}
@@ -52,20 +53,20 @@ func SetupEnterprise() *TestHelper {
}
func Setup() *TestHelper {
- if Srv == nil {
+ if app.Srv == nil {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
*utils.Cfg.RateLimitSettings.Enable = false
utils.DisableDebugLogForTest()
- NewServer()
- InitStores()
+ app.NewServer()
+ app.InitStores()
InitRouter()
- StartServer()
+ app.StartServer()
InitApi()
utils.EnableDebugLogForTest()
- Srv.Store.MarkSystemRanUnitTests()
+ app.Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true
}
@@ -138,7 +139,7 @@ func (me *TestHelper) CreateUser(client *model.Client) *model.User {
utils.DisableDebugLogForTest()
ruser := client.Must(client.CreateUser(user, "")).Data.(*model.User)
ruser.Password = "Password1"
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
utils.EnableDebugLogForTest()
return ruser
}
@@ -146,7 +147,7 @@ func (me *TestHelper) CreateUser(client *model.Client) *model.User {
func LinkUserToTeam(user *model.User, team *model.Team) {
utils.DisableDebugLogForTest()
- err := JoinUserToTeam(team, user)
+ err := app.JoinUserToTeam(team, user)
if err != nil {
l4g.Error(err.Error())
l4g.Close()
@@ -161,7 +162,7 @@ func UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
utils.DisableDebugLogForTest()
tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id}
- if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
+ if tmr := <-app.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
utils.EnableDebugLogForTest()
l4g.Error(tmr.Err.Error())
l4g.Close()
@@ -174,10 +175,10 @@ func UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
func MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
utils.DisableDebugLogForTest()
- if cmr := <-Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
+ if cmr := <-app.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
cm := cmr.Data.(model.ChannelMember)
cm.Roles = "channel_admin channel_user"
- if sr := <-Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
+ if sr := <-app.Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
utils.EnableDebugLogForTest()
panic(sr.Err)
}
@@ -192,10 +193,10 @@ func MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
func MakeUserChannelUser(user *model.User, channel *model.Channel) {
utils.DisableDebugLogForTest()
- if cmr := <-Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
+ if cmr := <-app.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
cm := cmr.Data.(model.ChannelMember)
cm.Roles = "channel_user"
- if sr := <-Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
+ if sr := <-app.Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
utils.EnableDebugLogForTest()
panic(sr.Err)
}
@@ -264,7 +265,7 @@ func (me *TestHelper) LoginSystemAdmin() {
}
func TearDown() {
- if Srv != nil {
- StopServer()
+ if app.Srv != nil {
+ app.StopServer()
}
}
diff --git a/api/authentication.go b/api/authentication.go
index fbfdb2cf4..ab649ee10 100644
--- a/api/authentication.go
+++ b/api/authentication.go
@@ -4,6 +4,7 @@
package api
import (
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
@@ -39,13 +40,13 @@ func doubleCheckPassword(user *model.User, password string) *model.AppError {
func checkUserPassword(user *model.User, password string) *model.AppError {
if !model.ComparePassword(user.Password, password) {
- if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, user.FailedAttempts+1); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, user.FailedAttempts+1); result.Err != nil {
return result.Err
}
return model.NewLocAppError("checkUserPassword", "api.user.check_user_password.invalid.app_error", nil, "user_id="+user.Id)
} else {
- if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, 0); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, 0); result.Err != nil {
return result.Err
}
diff --git a/api/authorization.go b/api/authorization.go
index e931c4b33..ac50d45ff 100644
--- a/api/authorization.go
+++ b/api/authorization.go
@@ -8,6 +8,7 @@ import (
"strings"
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -66,7 +67,7 @@ func HasPermissionToTeam(user *model.User, teamMember *model.TeamMember, permiss
}
func HasPermissionToChannelContext(c *Context, channelId string, permission *model.Permission) bool {
- cmc := Srv.Store.Channel().GetAllChannelMembersForUser(c.Session.UserId, true)
+ cmc := app.Srv.Store.Channel().GetAllChannelMembersForUser(c.Session.UserId, true)
var channelRoles []string
if cmcresult := <-cmc; cmcresult.Err == nil {
@@ -79,7 +80,7 @@ func HasPermissionToChannelContext(c *Context, channelId string, permission *mod
}
}
- cc := Srv.Store.Channel().Get(channelId, true)
+ cc := app.Srv.Store.Channel().Get(channelId, true)
if ccresult := <-cc; ccresult.Err == nil {
channel := ccresult.Data.(*model.Channel)
@@ -117,7 +118,7 @@ func HasPermissionToChannel(user *model.User, teamMember *model.TeamMember, chan
}
func HasPermissionToChannelByPostContext(c *Context, postId string, permission *model.Permission) bool {
- cmc := Srv.Store.Channel().GetMemberForPost(postId, c.Session.UserId)
+ cmc := app.Srv.Store.Channel().GetMemberForPost(postId, c.Session.UserId)
var channelRoles []string
if cmcresult := <-cmc; cmcresult.Err == nil {
@@ -129,7 +130,7 @@ func HasPermissionToChannelByPostContext(c *Context, postId string, permission *
}
}
- cc := Srv.Store.Channel().GetForPost(postId)
+ cc := app.Srv.Store.Channel().GetForPost(postId)
if ccresult := <-cc; ccresult.Err == nil {
channel := ccresult.Data.(*model.Channel)
diff --git a/api/auto_users.go b/api/auto_users.go
index 7439de96e..f1f7b483c 100644
--- a/api/auto_users.go
+++ b/api/auto_users.go
@@ -4,6 +4,7 @@
package api
import (
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -49,8 +50,8 @@ func CreateBasicUser(client *model.Client) *model.AppError {
return err
}
ruser := result.Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
- store.Must(Srv.Store.Team().SaveMember(&model.TeamMember{TeamId: basicteam.Id, UserId: ruser.Id}))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.Team().SaveMember(&model.TeamMember{TeamId: basicteam.Id, UserId: ruser.Id}))
}
return nil
}
@@ -81,14 +82,14 @@ func (cfg *AutoUserCreator) createRandomUser() (*model.User, bool) {
ruser := result.Data.(*model.User)
status := &model.Status{ruser.Id, model.STATUS_ONLINE, false, model.GetMillis(), ""}
- if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil {
+ if result := <-app.Srv.Store.Status().SaveOrUpdate(status); result.Err != nil {
result.Err.Translate(utils.T)
l4g.Error(result.Err.Error())
return nil, false
}
// We need to cheat to verify the user's email
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
return result.Data.(*model.User), true
}
diff --git a/api/channel.go b/api/channel.go
index cc63edd07..f0d520b4e 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -11,6 +11,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -82,7 +83,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
if channel.TeamId == c.TeamId {
// Get total number of channels on current team
- if result := <-Srv.Store.Channel().GetTeamChannels(channel.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetTeamChannels(channel.TeamId); result.Err != nil {
c.Err = model.NewLocAppError("createChannel", "api.channel.get_channels.error", nil, result.Err.Message)
return
} else {
@@ -96,38 +97,12 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel.CreatorId = c.Session.UserId
- if sc, err := CreateChannel(c, channel, true); err != nil {
+ if sc, err := app.CreateChannel(channel, true); err != nil {
c.Err = err
return
} else {
- w.Write([]byte(sc.ToJson()))
- }
-}
-
-func CreateChannel(c *Context, channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) {
- if result := <-Srv.Store.Channel().Save(channel); result.Err != nil {
- return nil, result.Err
- } else {
- sc := result.Data.(*model.Channel)
-
- if addMember {
- cm := &model.ChannelMember{
- ChannelId: sc.Id,
- UserId: c.Session.UserId,
- Roles: model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id,
- NotifyProps: model.GetDefaultChannelNotifyProps(),
- }
-
- if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
- return nil, cmresult.Err
- }
-
- InvalidateCacheForUser(c.Session.UserId)
- }
-
c.LogAudit("name=" + channel.Name)
-
- return sc, nil
+ w.Write([]byte(sc.ToJson()))
}
}
@@ -153,13 +128,13 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) {
- uc := Srv.Store.User().Get(otherUserId)
+ uc := app.Srv.Store.User().Get(otherUserId)
if uresult := <-uc; uresult.Err != nil {
return nil, model.NewLocAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId)
}
- if result := <-Srv.Store.Channel().CreateDirectChannel(userId, otherUserId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().CreateDirectChannel(userId, otherUserId); result.Err != nil {
if result.Err.Id == store.CHANNEL_EXISTS_ERROR {
return result.Data.(*model.Channel), nil
} else {
@@ -168,34 +143,17 @@ func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *mo
} else {
channel := result.Data.(*model.Channel)
- InvalidateCacheForUser(userId)
- InvalidateCacheForUser(otherUserId)
+ app.InvalidateCacheForUser(userId)
+ app.InvalidateCacheForUser(otherUserId)
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil)
message.Add("teammate_id", otherUserId)
- go Publish(message)
+ go app.Publish(message)
return channel, nil
}
}
-func CreateDefaultChannels(c *Context, teamId string) ([]*model.Channel, *model.AppError) {
- townSquare := &model.Channel{DisplayName: c.T("api.channel.create_default_channels.town_square"), Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: teamId}
-
- if _, err := CreateChannel(c, townSquare, false); err != nil {
- return nil, err
- }
-
- offTopic := &model.Channel{DisplayName: c.T("api.channel.create_default_channels.off_topic"), Name: "off-topic", Type: model.CHANNEL_OPEN, TeamId: teamId}
-
- if _, err := CreateChannel(c, offTopic, false); err != nil {
- return nil, err
- }
-
- channels := []*model.Channel{townSquare, offTopic}
- return channels, nil
-}
-
func CanManageChannel(c *Context, channel *model.Channel) bool {
if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) {
return false
@@ -217,8 +175,8 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := Srv.Store.Channel().Get(channel.Id, true)
- cmc := Srv.Store.Channel().GetMember(channel.Id, c.Session.UserId)
+ sc := app.Srv.Store.Channel().Get(channel.Id, true)
+ cmc := app.Srv.Store.Channel().GetMember(channel.Id, c.Session.UserId)
if cresult := <-sc; cresult.Err != nil {
c.Err = cresult.Err
@@ -265,8 +223,8 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
oldChannel.Type = channel.Type
}
- InvalidateCacheForChannel(oldChannel.Id)
- if ucresult := <-Srv.Store.Channel().Update(oldChannel); ucresult.Err != nil {
+ app.InvalidateCacheForChannel(oldChannel.Id)
+ if ucresult := <-app.Srv.Store.Channel().Update(oldChannel); ucresult.Err != nil {
c.Err = ucresult.Err
return
} else {
@@ -294,8 +252,8 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := Srv.Store.Channel().Get(channelId, true)
- cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
+ sc := app.Srv.Store.Channel().Get(channelId, true)
+ cmc := app.Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
if cresult := <-sc; cresult.Err != nil {
c.Err = cresult.Err
@@ -314,8 +272,8 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
oldChannelHeader := channel.Header
channel.Header = channelHeader
- InvalidateCacheForChannel(channel.Id)
- if ucresult := <-Srv.Store.Channel().Update(channel); ucresult.Err != nil {
+ app.InvalidateCacheForChannel(channel.Id)
+ if ucresult := <-app.Srv.Store.Channel().Update(channel); ucresult.Err != nil {
c.Err = ucresult.Err
return
} else {
@@ -327,7 +285,7 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
}
func PostUpdateChannelHeaderMessage(c *Context, channelId string, oldChannelHeader, newChannelHeader string) {
- uc := Srv.Store.User().Get(c.Session.UserId)
+ uc := app.Srv.Store.User().Get(c.Session.UserId)
if uresult := <-uc; uresult.Err != nil {
l4g.Error(utils.T("api.channel.post_update_channel_header_message_and_forget.retrieve_user.error"), uresult.Err)
@@ -355,14 +313,14 @@ func PostUpdateChannelHeaderMessage(c *Context, channelId string, oldChannelHead
},
}
- if _, err := CreatePost(c, post, false); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
l4g.Error(utils.T("api.channel.post_update_channel_header_message_and_forget.join_leave.error"), err)
}
}
}
func PostUpdateChannelDisplayNameMessage(c *Context, channelId string, oldChannelDisplayName, newChannelDisplayName string) {
- uc := Srv.Store.User().Get(c.Session.UserId)
+ uc := app.Srv.Store.User().Get(c.Session.UserId)
if uresult := <-uc; uresult.Err != nil {
l4g.Error(utils.T("api.channel.post_update_channel_displayname_message_and_forget.retrieve_user.error"), uresult.Err)
@@ -383,7 +341,7 @@ func PostUpdateChannelDisplayNameMessage(c *Context, channelId string, oldChanne
},
}
- if _, err := CreatePost(c, post, false); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
l4g.Error(utils.T("api.channel.post_update_channel_displayname_message_and_forget.create_post.error"), err)
}
}
@@ -403,8 +361,8 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := Srv.Store.Channel().Get(channelId, true)
- cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
+ sc := app.Srv.Store.Channel().Get(channelId, true)
+ cmc := app.Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
if cresult := <-sc; cresult.Err != nil {
c.Err = cresult.Err
@@ -422,8 +380,8 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
channel.Purpose = channelPurpose
- InvalidateCacheForChannel(channel.Id)
- if ucresult := <-Srv.Store.Channel().Update(channel); ucresult.Err != nil {
+ app.InvalidateCacheForChannel(channel.Id)
+ if ucresult := <-app.Srv.Store.Channel().Update(channel); ucresult.Err != nil {
c.Err = ucresult.Err
return
} else {
@@ -441,10 +399,11 @@ func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
}
// user is already in the team
// Get's all channels the user is a member of
- if result := <-Srv.Store.Channel().GetChannels(c.TeamId, c.Session.UserId); result.Err != nil {
+
+ if result := <-app.Srv.Store.Channel().GetChannels(c.TeamId, c.Session.UserId); result.Err != nil {
if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
// lets make sure the user is valid
- if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
c.Err = result.Err
c.RemoveSessionCookie(w, r)
l4g.Error(utils.T("api.channel.get_channels.error"), c.Session.UserId)
@@ -482,7 +441,7 @@ func getMoreChannelsPage(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -496,7 +455,7 @@ func getChannelCounts(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team
- if result := <-Srv.Store.Channel().GetChannelCounts(c.TeamId, c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetChannelCounts(c.TeamId, c.Session.UserId); result.Err != nil {
c.Err = model.NewLocAppError("getChannelCounts", "api.channel.get_channel_counts.app_error", nil, result.Err.Message)
return
} else if HandleEtag(result.Data.(*model.ChannelCounts).Etag(), "Get Channel Counts", w, r) {
@@ -539,15 +498,15 @@ func join(c *Context, w http.ResponseWriter, r *http.Request) {
}
func JoinChannelByName(c *Context, userId string, teamId string, channelName string) (*model.AppError, *model.Channel) {
- channelChannel := Srv.Store.Channel().GetByName(teamId, channelName)
- userChannel := Srv.Store.User().Get(userId)
+ channelChannel := app.Srv.Store.Channel().GetByName(teamId, channelName)
+ userChannel := app.Srv.Store.User().Get(userId)
return joinChannel(c, channelChannel, userChannel)
}
func JoinChannelById(c *Context, userId string, channelId string) (*model.AppError, *model.Channel) {
- channelChannel := Srv.Store.Channel().Get(channelId, true)
- userChannel := Srv.Store.User().Get(userId)
+ channelChannel := app.Srv.Store.Channel().Get(channelId, true)
+ userChannel := app.Srv.Store.User().Get(userId)
return joinChannel(c, channelChannel, userChannel)
}
@@ -561,7 +520,7 @@ func joinChannel(c *Context, channelChannel store.StoreChannel, userChannel stor
channel := cresult.Data.(*model.Channel)
user := uresult.Data.(*model.User)
- if mresult := <-Srv.Store.Channel().GetMember(channel.Id, user.Id); mresult.Err == nil && mresult.Data != nil {
+ if mresult := <-app.Srv.Store.Channel().GetMember(channel.Id, user.Id); mresult.Err == nil && mresult.Data != nil {
// the user is already in the channel so just return successful
return nil, channel
}
@@ -571,7 +530,7 @@ func joinChannel(c *Context, channelChannel store.StoreChannel, userChannel stor
}
if channel.Type == model.CHANNEL_OPEN {
- if _, err := AddUserToChannel(user, channel); err != nil {
+ if _, err := app.AddUserToChannel(user, channel); err != nil {
return err, nil
}
go PostUserAddRemoveMessage(c, channel.Id, fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username), model.POST_JOIN_LEAVE)
@@ -589,135 +548,19 @@ func PostUserAddRemoveMessage(c *Context, channelId string, message, postType st
Type: postType,
UserId: c.Session.UserId,
}
- if _, err := CreatePost(c, post, false); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
}
}
-func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) {
- if channel.DeleteAt > 0 {
- return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user_to_channel.deleted.app_error", nil, "")
- }
-
- if channel.Type != model.CHANNEL_OPEN && channel.Type != model.CHANNEL_PRIVATE {
- return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "")
- }
-
- tmchan := Srv.Store.Team().GetMember(channel.TeamId, user.Id)
- cmchan := Srv.Store.Channel().GetMember(channel.Id, user.Id)
-
- if result := <-tmchan; result.Err != nil {
- return nil, result.Err
- } else {
- teamMember := result.Data.(model.TeamMember)
- if teamMember.DeleteAt > 0 {
- return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.deleted.app_error", nil, "")
- }
- }
-
- if result := <-cmchan; result.Err != nil {
- if result.Err.Id != store.MISSING_CHANNEL_MEMBER_ERROR {
- return nil, result.Err
- }
- } else {
- channelMember := result.Data.(model.ChannelMember)
- return &channelMember, nil
- }
-
- newMember := &model.ChannelMember{
- ChannelId: channel.Id,
- UserId: user.Id,
- NotifyProps: model.GetDefaultChannelNotifyProps(),
- Roles: model.ROLE_CHANNEL_USER.Id,
- }
- if result := <-Srv.Store.Channel().SaveMember(newMember); result.Err != nil {
- l4g.Error("Failed to add member user_id=%v channel_id=%v err=%v", user.Id, channel.Id, result.Err)
- return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "")
- }
-
- InvalidateCacheForUser(user.Id)
- InvalidateCacheForChannel(channel.Id)
-
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil)
- message.Add("user_id", user.Id)
- message.Add("team_id", channel.TeamId)
- go Publish(message)
-
- return newMember, nil
-}
-
-func JoinDefaultChannels(teamId string, user *model.User, channelRole string) *model.AppError {
- // We don't call JoinChannel here since c.Session is not populated on user creation
-
- var err *model.AppError = nil
-
- fakeContext := &Context{
- Session: model.Session{
- UserId: user.Id,
- },
- TeamId: teamId,
- T: utils.TfuncWithFallback(user.Locale),
- }
-
- if result := <-Srv.Store.Channel().GetByName(teamId, "town-square"); result.Err != nil {
- err = result.Err
- } else {
- cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id,
- Roles: channelRole, NotifyProps: model.GetDefaultChannelNotifyProps()}
-
- if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
- err = cmResult.Err
- }
-
- post := &model.Post{
- ChannelId: result.Data.(*model.Channel).Id,
- Message: fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username),
- Type: model.POST_JOIN_LEAVE,
- UserId: user.Id,
- }
-
- InvalidateCacheForChannel(result.Data.(*model.Channel).Id)
-
- if _, err := CreatePost(fakeContext, post, false); err != nil {
- l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
- }
- }
-
- if result := <-Srv.Store.Channel().GetByName(teamId, "off-topic"); result.Err != nil {
- err = result.Err
- } else {
- cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id,
- Roles: channelRole, NotifyProps: model.GetDefaultChannelNotifyProps()}
-
- if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
- err = cmResult.Err
- }
-
- post := &model.Post{
- ChannelId: result.Data.(*model.Channel).Id,
- Message: fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username),
- Type: model.POST_JOIN_LEAVE,
- UserId: user.Id,
- }
-
- InvalidateCacheForChannel(result.Data.(*model.Channel).Id)
-
- if _, err := CreatePost(fakeContext, post, false); err != nil {
- l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
- }
- }
-
- return err
-}
-
func leave(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- sc := Srv.Store.Channel().Get(id, true)
- uc := Srv.Store.User().Get(c.Session.UserId)
- ccm := Srv.Store.Channel().GetMemberCount(id, false)
+ sc := app.Srv.Store.Channel().Get(id, true)
+ uc := app.Srv.Store.User().Get(c.Session.UserId)
+ ccm := app.Srv.Store.Channel().GetMemberCount(id, false)
if cresult := <-sc; cresult.Err != nil {
c.Err = cresult.Err
@@ -751,7 +594,7 @@ func leave(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if cmresult := <-Srv.Store.Channel().RemoveMember(channel.Id, c.Session.UserId); cmresult.Err != nil {
+ if cmresult := <-app.Srv.Store.Channel().RemoveMember(channel.Id, c.Session.UserId); cmresult.Err != nil {
c.Err = cmresult.Err
return
}
@@ -771,12 +614,12 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- sc := Srv.Store.Channel().Get(id, true)
- scm := Srv.Store.Channel().GetMember(id, c.Session.UserId)
- cmc := Srv.Store.Channel().GetMemberCount(id, false)
- uc := Srv.Store.User().Get(c.Session.UserId)
- ihc := Srv.Store.Webhook().GetIncomingByChannel(id)
- ohc := Srv.Store.Webhook().GetOutgoingByChannel(id)
+ sc := app.Srv.Store.Channel().Get(id, true)
+ scm := app.Srv.Store.Channel().GetMember(id, c.Session.UserId)
+ cmc := app.Srv.Store.Channel().GetMemberCount(id, false)
+ uc := app.Srv.Store.User().Get(c.Session.UserId)
+ ihc := app.Srv.Store.Webhook().GetIncomingByChannel(id)
+ ohc := app.Srv.Store.Webhook().GetOutgoingByChannel(id)
if cresult := <-sc; cresult.Err != nil {
c.Err = cresult.Err
@@ -834,35 +677,35 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
UserId: c.Session.UserId,
}
- if _, err := CreatePost(c, post, false); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
l4g.Error(utils.T("api.channel.delete_channel.failed_post.error"), err)
}
now := model.GetMillis()
for _, hook := range incomingHooks {
- if result := <-Srv.Store.Webhook().DeleteIncoming(hook.Id, now); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().DeleteIncoming(hook.Id, now); result.Err != nil {
l4g.Error(utils.T("api.channel.delete_channel.incoming_webhook.error"), hook.Id)
}
}
for _, hook := range outgoingHooks {
- if result := <-Srv.Store.Webhook().DeleteOutgoing(hook.Id, now); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().DeleteOutgoing(hook.Id, now); result.Err != nil {
l4g.Error(utils.T("api.channel.delete_channel.outgoing_webhook.error"), hook.Id)
}
}
- if dresult := <-Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); dresult.Err != nil {
+ if dresult := <-app.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); dresult.Err != nil {
c.Err = dresult.Err
return
}
- InvalidateCacheForChannel(channel.Id)
+ app.InvalidateCacheForChannel(channel.Id)
c.LogAudit("name=" + channel.Name)
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, c.TeamId, "", "", nil)
message.Add("channel_id", channel.Id)
- Publish(message)
+ app.Publish(message)
result := make(map[string]string)
result["id"] = channel.Id
@@ -874,8 +717,8 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- cchan := Srv.Store.Channel().Get(id, true)
- cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId)
+ cchan := app.Srv.Store.Channel().Get(id, true)
+ cmchan := app.Srv.Store.Channel().GetMember(id, c.Session.UserId)
if cresult := <-cchan; cresult.Err != nil {
c.Err = cresult.Err
@@ -904,7 +747,7 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
func SetActiveChannel(userId string, channelId string) *model.AppError {
- status, err := GetStatus(userId)
+ status, err := app.GetStatus(userId)
if err != nil {
status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), channelId}
} else {
@@ -915,7 +758,7 @@ func SetActiveChannel(userId string, channelId string) *model.AppError {
status.LastActivityAt = model.GetMillis()
}
- AddStatusCache(status)
+ app.AddStatusCache(status)
return nil
}
@@ -924,7 +767,7 @@ func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
channelName := params["channel_name"]
- cchan := Srv.Store.Channel().GetByName(c.TeamId, channelName)
+ cchan := app.Srv.Store.Channel().GetByName(c.TeamId, channelName)
if cresult := <-cchan; cresult.Err != nil {
c.Err = cresult.Err
@@ -954,7 +797,7 @@ func getChannelStats(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- sc := Srv.Store.Channel().Get(id, true)
+ sc := app.Srv.Store.Channel().Get(id, true)
var channel *model.Channel
if result := <-sc; result.Err != nil {
c.Err = result.Err
@@ -963,7 +806,7 @@ func getChannelStats(c *Context, w http.ResponseWriter, r *http.Request) {
channel = result.Data.(*model.Channel)
}
- if result := <-Srv.Store.Channel().GetMemberCount(id, true); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetMemberCount(id, true); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -993,7 +836,7 @@ func getChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Channel().GetMember(channelId, userId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetMember(channelId, userId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1003,7 +846,7 @@ func getChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getMyChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-Srv.Store.Channel().GetMembersForUser(c.TeamId, c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetMembersForUser(c.TeamId, c.Session.UserId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1024,9 +867,9 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := Srv.Store.Channel().Get(id, true)
- ouc := Srv.Store.User().Get(c.Session.UserId)
- nuc := Srv.Store.User().Get(userId)
+ sc := app.Srv.Store.Channel().Get(id, true)
+ ouc := app.Srv.Store.User().Get(c.Session.UserId)
+ nuc := app.Srv.Store.User().Get(userId)
if nresult := <-nuc; nresult.Err != nil {
c.Err = model.NewLocAppError("addMember", "api.channel.add_member.find_user.app_error", nil, "")
return
@@ -1051,7 +894,7 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
oUser := oresult.Data.(*model.User)
- cm, err := AddUserToChannel(nUser, channel)
+ cm, err := app.AddUserToChannel(nUser, channel)
if err != nil {
c.Err = err
return
@@ -1061,7 +904,7 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
go PostUserAddRemoveMessage(c, channel.Id, fmt.Sprintf(utils.T("api.channel.add_member.added"), nUser.Username, oUser.Username), model.POST_ADD_REMOVE)
- <-Srv.Store.Channel().UpdateLastViewedAt([]string{id}, oUser.Id)
+ <-app.Srv.Store.Channel().UpdateLastViewedAt([]string{id}, oUser.Id)
w.Write([]byte(cm.ToJson()))
}
}
@@ -1079,9 +922,9 @@ func removeMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := Srv.Store.Channel().Get(channelId, true)
- cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
- ouc := Srv.Store.User().Get(userIdToRemove)
+ sc := app.Srv.Store.Channel().Get(channelId, true)
+ cmc := app.Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
+ ouc := app.Srv.Store.User().Get(userIdToRemove)
if oresult := <-ouc; oresult.Err != nil {
c.Err = model.NewLocAppError("removeMember", "api.channel.remove_member.user.app_error", nil, "")
@@ -1132,23 +975,23 @@ func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel
return model.NewLocAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
}
- if cmresult := <-Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil {
+ if cmresult := <-app.Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil {
return cmresult.Err
}
- InvalidateCacheForUser(userIdToRemove)
- InvalidateCacheForChannel(channel.Id)
+ app.InvalidateCacheForUser(userIdToRemove)
+ app.InvalidateCacheForChannel(channel.Id)
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil)
message.Add("user_id", userIdToRemove)
message.Add("remover_id", removerUserId)
- go Publish(message)
+ go app.Publish(message)
// because the removed user no longer belongs to the channel we need to send a separate websocket event
userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIdToRemove, nil)
userMsg.Add("channel_id", channel.Id)
userMsg.Add("remover_id", removerUserId)
- go Publish(userMsg)
+ go app.Publish(userMsg)
return nil
}
@@ -1172,7 +1015,7 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- result := <-Srv.Store.Channel().GetMember(channelId, userId)
+ result := <-app.Srv.Store.Channel().GetMember(channelId, userId)
if result.Err != nil {
c.Err = result.Err
return
@@ -1189,11 +1032,11 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
member.NotifyProps["desktop"] = desktop
}
- if result := <-Srv.Store.Channel().UpdateMember(&member); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().UpdateMember(&member); result.Err != nil {
c.Err = result.Err
return
} else {
- InvalidateCacheForUser(userId)
+ app.InvalidateCacheForUser(userId)
// return the updated notify properties including any unchanged ones
w.Write([]byte(model.MapToJson(member.NotifyProps)))
@@ -1219,7 +1062,7 @@ func searchMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Channel().SearchMore(c.Session.UserId, c.TeamId, props.Term); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().SearchMore(c.Session.UserId, c.TeamId, props.Term); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1239,7 +1082,7 @@ func autocompleteChannels(c *Context, w http.ResponseWriter, r *http.Request) {
var channels *model.ChannelList
- if result := <-Srv.Store.Channel().SearchInTeam(c.TeamId, term); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().SearchInTeam(c.TeamId, term); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1269,11 +1112,11 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channelIds = append(channelIds, view.PrevChannelId)
if *utils.Cfg.EmailSettings.SendPushNotifications && !c.Session.IsMobileApp() {
- pchan = Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, view.ChannelId)
+ pchan = app.Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, view.ChannelId)
}
}
- uchan := Srv.Store.Channel().UpdateLastViewedAt(channelIds, c.Session.UserId)
+ uchan := app.Srv.Store.Channel().UpdateLastViewedAt(channelIds, c.Session.UserId)
if pchan != nil {
if result := <-pchan; result.Err != nil {
@@ -1281,7 +1124,7 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
if result.Data.(int64) > 0 {
- clearPushNotification(c.Session.UserId, view.ChannelId)
+ app.ClearPushNotification(c.Session.UserId, view.ChannelId)
}
}
}
@@ -1293,7 +1136,7 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, c.TeamId, "", c.Session.UserId, nil)
message.Add("channel_id", view.ChannelId)
- go Publish(message)
+ go app.Publish(message)
ReturnStatusOK(w)
}
@@ -1312,7 +1155,7 @@ func getChannelMembersByIds(c *Context, w http.ResponseWriter, r *http.Request)
return
}
- if result := <-Srv.Store.Channel().GetMembersByIds(channelId, userIds); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetMembersByIds(channelId, userIds); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1334,7 +1177,7 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request
return
}
- mchan := Srv.Store.Channel().GetMember(channelId, userId)
+ mchan := app.Srv.Store.Channel().GetMember(channelId, userId)
newRoles := props["new_roles"]
if !(model.IsValidUserRoles(newRoles)) {
@@ -1356,12 +1199,12 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request
member.Roles = newRoles
- if result := <-Srv.Store.Channel().UpdateMember(&member); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().UpdateMember(&member); result.Err != nil {
c.Err = result.Err
return
}
- InvalidateCacheForUser(userId)
+ app.InvalidateCacheForUser(userId)
rdata := map[string]string{}
rdata["status"] = "ok"
diff --git a/api/channel_test.go b/api/channel_test.go
index 8bfa0e896..1bce8b9fd 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -9,6 +9,7 @@ import (
"testing"
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -1067,7 +1068,7 @@ func TestJoinChannelByNameDisabledUser(t *testing.T) {
Client.Must(th.BasicClient.RemoveUserFromTeam(th.BasicTeam.Id, th.BasicUser.Id))
- if _, err := AddUserToChannel(th.BasicUser, channel1); err == nil {
+ if _, err := app.AddUserToChannel(th.BasicUser, channel1); err == nil {
t.Fatal("shoudn't be able to join channel")
} else {
if err.Id != "api.channel.add_user.to.channel.failed.deleted.app_error" {
@@ -1832,7 +1833,7 @@ func TestGetChannelByName(t *testing.T) {
user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Jabba the Hutt", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
Client.SetTeamId(th.BasicTeam.Id)
@@ -1887,7 +1888,7 @@ func TestViewChannel(t *testing.T) {
func TestGetChannelMembersByIds(t *testing.T) {
th := Setup().InitBasic()
- if _, err := AddUserToChannel(th.BasicUser2, th.BasicChannel); err != nil {
+ if _, err := app.AddUserToChannel(th.BasicUser2, th.BasicChannel); err != nil {
t.Fatal("Could not add second user to channel")
}
diff --git a/api/cli_test.go b/api/cli_test.go
index ed8f764a3..1f60b02cd 100644
--- a/api/cli_test.go
+++ b/api/cli_test.go
@@ -7,6 +7,7 @@ import (
"os/exec"
"testing"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -108,7 +109,7 @@ func TestCliCreateUserWithoutTeam(t *testing.T) {
t.Fatal(err)
}
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
t.Fatal()
} else {
user := result.Data.(*model.User)
@@ -132,7 +133,7 @@ func TestCliAssignRole(t *testing.T) {
t.Fatal(err)
}
- if result := <-Srv.Store.User().GetByEmail(th.BasicUser.Email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(th.BasicUser.Email); result.Err != nil {
t.Fatal()
} else {
user := result.Data.(*model.User)
@@ -370,7 +371,7 @@ func TestCliLeaveTeam(t *testing.T) {
t.Fatal("profile should not be on team")
}
- if result := <-Srv.Store.Team().GetTeamsByUserId(th.BasicUser.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetTeamsByUserId(th.BasicUser.Id); result.Err != nil {
teamMembers := result.Data.([]*model.TeamMember)
if len(teamMembers) > 0 {
t.Fatal("Shouldn't be in team")
diff --git a/api/command.go b/api/command.go
index 9c8f60be5..8a1126bf3 100644
--- a/api/command.go
+++ b/api/command.go
@@ -13,6 +13,7 @@ import (
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -69,7 +70,7 @@ func listCommands(c *Context, w http.ResponseWriter, r *http.Request) {
}
if *utils.Cfg.ServiceSettings.EnableCommands {
- if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -119,11 +120,11 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- chanChan := Srv.Store.Channel().Get(commandArgs.ChannelId, true)
- teamChan := Srv.Store.Team().Get(c.TeamId)
- userChan := Srv.Store.User().Get(c.Session.UserId)
+ chanChan := app.Srv.Store.Channel().Get(commandArgs.ChannelId, true)
+ teamChan := app.Srv.Store.Team().Get(c.TeamId)
+ userChan := app.Srv.Store.User().Get(c.Session.UserId)
- if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -221,6 +222,7 @@ func handleResponse(c *Context, w http.ResponseWriter, response *model.CommandRe
post.ChannelId = commandArgs.ChannelId
post.RootId = commandArgs.RootId
post.ParentId = commandArgs.ParentId
+ post.UserId = c.Session.UserId
if !builtIn {
post.AddProp("from_webhook", "true")
@@ -246,7 +248,9 @@ func handleResponse(c *Context, w http.ResponseWriter, response *model.CommandRe
}
}
- CreateCommandPost(c, post, response)
+ if _, err := app.CreateCommandPost(post, c.TeamId, response); err != nil {
+ l4g.Error(err.Error())
+ }
w.Write([]byte(response.ToJson()))
}
@@ -277,7 +281,7 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
cmd.CreatorId = c.Session.UserId
cmd.TeamId = c.TeamId
- if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -297,7 +301,7 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.Command().Save(cmd); result.Err != nil {
+ if result := <-app.Srv.Store.Command().Save(cmd); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -332,7 +336,7 @@ func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) {
cmd.Trigger = strings.ToLower(cmd.Trigger)
var oldCmd *model.Command
- if result := <-Srv.Store.Command().Get(cmd.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Command().Get(cmd.Id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -358,7 +362,7 @@ func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) {
cmd.TeamId = oldCmd.TeamId
}
- if result := <-Srv.Store.Command().Update(cmd); result.Err != nil {
+ if result := <-app.Srv.Store.Command().Update(cmd); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -379,7 +383,7 @@ func listTeamCommands(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -412,7 +416,7 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
}
var cmd *model.Command
- if result := <-Srv.Store.Command().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.Command().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -427,7 +431,7 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
cmd.Token = model.NewId()
- if result := <-Srv.Store.Command().Update(cmd); result.Err != nil {
+ if result := <-app.Srv.Store.Command().Update(cmd); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -458,7 +462,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Command().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.Command().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -469,7 +473,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if err := (<-Srv.Store.Command().Delete(id, model.GetMillis())).Err; err != nil {
+ if err := (<-app.Srv.Store.Command().Delete(id, model.GetMillis())).Err; err != nil {
c.Err = err
return
}
diff --git a/api/command_away.go b/api/command_away.go
index 6d6540320..6a488c081 100644
--- a/api/command_away.go
+++ b/api/command_away.go
@@ -4,6 +4,7 @@
package api
import (
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -36,7 +37,7 @@ func (me *AwayProvider) DoCommand(c *Context, args *model.CommandArgs, message s
if len(message) > 0 {
rmsg = message + " " + rmsg
}
- SetStatusAwayIfNeeded(c.Session.UserId, true)
+ app.SetStatusAwayIfNeeded(c.Session.UserId, true)
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: rmsg}
}
diff --git a/api/command_echo.go b/api/command_echo.go
index c219945c7..2e931e414 100644
--- a/api/command_echo.go
+++ b/api/command_echo.go
@@ -9,6 +9,7 @@ import (
"time"
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -87,7 +88,7 @@ func (me *EchoProvider) DoCommand(c *Context, args *model.CommandArgs, message s
time.Sleep(time.Duration(delay) * time.Second)
- if _, err := CreatePost(c, post, true); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, true); err != nil {
l4g.Error(c.T("api.command_echo.create.app_error"), err)
}
}()
diff --git a/api/command_expand_collapse.go b/api/command_expand_collapse.go
index d36893cb0..5adbf4bab 100644
--- a/api/command_expand_collapse.go
+++ b/api/command_expand_collapse.go
@@ -6,6 +6,7 @@ package api
import (
"strconv"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -67,13 +68,13 @@ func setCollapsePreference(c *Context, isCollapse bool) *model.CommandResponse {
Value: strconv.FormatBool(isCollapse),
}
- if result := <-Srv.Store.Preference().Save(&model.Preferences{pref}); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Save(&model.Preferences{pref}); result.Err != nil {
return &model.CommandResponse{Text: c.T("api.command_expand_collapse.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
socketMessage := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", c.Session.UserId, nil)
socketMessage.Add("preference", pref.ToJson())
- go Publish(socketMessage)
+ go app.Publish(socketMessage)
var rmsg string
diff --git a/api/command_invite_people.go b/api/command_invite_people.go
index e6ad252f6..f3818628f 100644
--- a/api/command_invite_people.go
+++ b/api/command_invite_people.go
@@ -6,6 +6,7 @@ package api
import (
"strings"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -40,8 +41,8 @@ func (me *InvitePeopleProvider) DoCommand(c *Context, args *model.CommandArgs, m
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: c.T("api.command.invite_people.email_off")}
}
- tchan := Srv.Store.Team().Get(c.TeamId)
- uchan := Srv.Store.User().Get(c.Session.UserId)
+ tchan := app.Srv.Store.Team().Get(c.TeamId)
+ uchan := app.Srv.Store.User().Get(c.Session.UserId)
emailList := strings.Fields(message)
diff --git a/api/command_join.go b/api/command_join.go
index 3c997dffd..2210d2857 100644
--- a/api/command_join.go
+++ b/api/command_join.go
@@ -4,6 +4,7 @@
package api
import (
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -33,7 +34,7 @@ func (me *JoinProvider) GetCommand(c *Context) *model.Command {
}
func (me *JoinProvider) DoCommand(c *Context, args *model.CommandArgs, message string) *model.CommandResponse {
- if result := <-Srv.Store.Channel().GetByName(c.TeamId, message); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetByName(c.TeamId, message); result.Err != nil {
return &model.CommandResponse{Text: c.T("api.command_join.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
channel := result.Data.(*model.Channel)
diff --git a/api/command_loadtest.go b/api/command_loadtest.go
index ed3fc37ba..5ad2736a0 100644
--- a/api/command_loadtest.go
+++ b/api/command_loadtest.go
@@ -11,6 +11,7 @@ import (
"strings"
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -185,7 +186,7 @@ func (me *LoadTestProvider) SetupCommand(c *Context, channelId string, message s
} else {
var team *model.Team
- if tr := <-Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
+ if tr := <-app.Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
team = tr.Data.(*model.Team)
@@ -220,7 +221,7 @@ func (me *LoadTestProvider) UsersCommand(c *Context, channelId string, message s
}
var team *model.Team
- if tr := <-Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
+ if tr := <-app.Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
team = tr.Data.(*model.Team)
@@ -250,7 +251,7 @@ func (me *LoadTestProvider) ChannelsCommand(c *Context, channelId string, messag
}
var team *model.Team
- if tr := <-Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
+ if tr := <-app.Srv.Store.Team().Get(c.TeamId); tr.Err != nil {
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
team = tr.Data.(*model.Team)
@@ -289,7 +290,7 @@ func (me *LoadTestProvider) PostsCommand(c *Context, channelId string, message s
}
var usernames []string
- if result := <-Srv.Store.User().GetProfiles(c.TeamId, 0, 1000); result.Err == nil {
+ if result := <-app.Srv.Store.User().GetProfiles(c.TeamId, 0, 1000); result.Err == nil {
profileUsers := result.Data.(map[string]*model.User)
usernames = make([]string, len(profileUsers))
i := 0
@@ -358,7 +359,7 @@ func (me *LoadTestProvider) UrlCommand(c *Context, channelId string, message str
post.ChannelId = channelId
post.UserId = c.Session.UserId
- if _, err := CreatePost(c, post, false); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
}
@@ -397,7 +398,7 @@ func (me *LoadTestProvider) JsonCommand(c *Context, channelId string, message st
post.Message = message
}
- if _, err := CreatePost(c, post, false); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
return &model.CommandResponse{Text: "Loaded data", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
diff --git a/api/command_msg.go b/api/command_msg.go
index f2d06824d..36a9344ea 100644
--- a/api/command_msg.go
+++ b/api/command_msg.go
@@ -6,6 +6,7 @@ package api
import (
"strings"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -48,7 +49,7 @@ func (me *msgProvider) DoCommand(c *Context, args *model.CommandArgs, message st
targetUsername = strings.TrimPrefix(targetUsername, "@")
var userProfile *model.User
- if result := <-Srv.Store.User().GetByUsername(targetUsername); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByUsername(targetUsername); result.Err != nil {
c.Err = result.Err
return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
} else {
@@ -63,7 +64,7 @@ func (me *msgProvider) DoCommand(c *Context, args *model.CommandArgs, message st
channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id)
targetChannelId := ""
- if channel := <-Srv.Store.Channel().GetByName(c.TeamId, channelName); channel.Err != nil {
+ if channel := <-app.Srv.Store.Channel().GetByName(c.TeamId, channelName); channel.Err != nil {
if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" {
if directChannel, err := CreateDirectChannel(c.Session.UserId, userProfile.Id); err != nil {
c.Err = err
@@ -79,13 +80,13 @@ func (me *msgProvider) DoCommand(c *Context, args *model.CommandArgs, message st
targetChannelId = channel.Data.(*model.Channel).Id
}
- makeDirectChannelVisible(targetChannelId)
+ app.MakeDirectChannelVisible(targetChannelId)
if len(parsedMessage) > 0 {
post := &model.Post{}
post.Message = parsedMessage
post.ChannelId = targetChannelId
post.UserId = c.Session.UserId
- if _, err := CreatePost(c, post, true); err != nil {
+ if _, err := app.CreatePost(post, c.TeamId, true); err != nil {
return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
}
diff --git a/api/command_offline.go b/api/command_offline.go
index 1349ac18f..a4bcdf8a5 100644
--- a/api/command_offline.go
+++ b/api/command_offline.go
@@ -4,6 +4,7 @@
package api
import (
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -36,7 +37,7 @@ func (me *OfflineProvider) DoCommand(c *Context, args *model.CommandArgs, messag
if len(message) > 0 {
rmsg = message + " " + rmsg
}
- SetStatusOffline(c.Session.UserId, true)
+ app.SetStatusOffline(c.Session.UserId, true)
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: rmsg}
}
diff --git a/api/command_online.go b/api/command_online.go
index 887aa2c47..81d3e1fd6 100644
--- a/api/command_online.go
+++ b/api/command_online.go
@@ -4,6 +4,7 @@
package api
import (
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -36,7 +37,7 @@ func (me *OnlineProvider) DoCommand(c *Context, args *model.CommandArgs, message
if len(message) > 0 {
rmsg = message + " " + rmsg
}
- SetStatusOnline(c.Session.UserId, c.Session.Id, true)
+ app.SetStatusOnline(c.Session.UserId, c.Session.Id, true)
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: rmsg}
}
diff --git a/api/context.go b/api/context.go
index 7f95fdfbc..c2036ed81 100644
--- a/api/context.go
+++ b/api/context.go
@@ -5,7 +5,6 @@ package api
import (
"fmt"
- "net"
"net/http"
"net/url"
"strings"
@@ -15,23 +14,12 @@ import (
"github.com/gorilla/mux"
goi18n "github.com/nicksnyder/go-i18n/i18n"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
-var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE)
-
-var allowedMethods []string = []string{
- "POST",
- "GET",
- "OPTIONS",
- "PUT",
- "PATCH",
- "DELETE",
-}
-
type Context struct {
Session model.Session
RequestId string
@@ -116,7 +104,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := &Context{}
c.T, c.Locale = utils.GetTranslationsAndLocale(w, r)
c.RequestId = model.NewId()
- c.IpAddress = GetIpAddress(r)
+ c.IpAddress = utils.GetIpAddress(r)
c.TeamId = mux.Vars(r)["team_id"]
token := ""
@@ -153,9 +141,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
isTokenFromQueryString = true
}
- if *utils.Cfg.ServiceSettings.SiteURL != "" {
- c.SetSiteURL(*utils.Cfg.ServiceSettings.SiteURL)
- } else {
+ if utils.GetSiteURL() == "" {
protocol := GetProtocol(r)
c.SetSiteURL(protocol + "://" + r.Host)
}
@@ -180,9 +166,10 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if len(token) != 0 {
- session := GetSession(token)
+ session, err := app.GetSession(token)
- if session == nil || session.IsExpired() {
+ if err != nil {
+ l4g.Error(utils.T("api.context.invalid_session.error"), err.Error())
c.RemoveSessionCookie(w, r)
if h.requireUser || h.requireSystemAdmin {
c.Err = model.NewLocAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token)
@@ -218,7 +205,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if c.Err == nil && h.isUserActivity && token != "" && len(c.Session.UserId) > 0 {
- SetStatusOnline(c.Session.UserId, c.Session.Id, false)
+ app.SetStatusOnline(c.Session.UserId, c.Session.Id, false)
}
if c.Err == nil && (h.requireUser || h.requireSystemAdmin) {
@@ -269,31 +256,6 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
-func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if len(*utils.Cfg.ServiceSettings.AllowCorsFrom) > 0 {
- origin := r.Header.Get("Origin")
- if *utils.Cfg.ServiceSettings.AllowCorsFrom == "*" || strings.Contains(*utils.Cfg.ServiceSettings.AllowCorsFrom, origin) {
- w.Header().Set("Access-Control-Allow-Origin", origin)
-
- if r.Method == "OPTIONS" {
- w.Header().Set(
- "Access-Control-Allow-Methods",
- strings.Join(allowedMethods, ", "))
-
- w.Header().Set(
- "Access-Control-Allow-Headers",
- r.Header.Get("Access-Control-Request-Headers"))
- }
- }
- }
-
- if r.Method == "OPTIONS" {
- return
- }
-
- cw.router.ServeHTTP(w, r)
-}
-
func GetProtocol(r *http.Request) string {
if r.Header.Get(model.HEADER_FORWARDED_PROTO) == "https" {
return "https"
@@ -304,7 +266,7 @@ func GetProtocol(r *http.Request) string {
func (c *Context) LogAudit(extraInfo string) {
audit := &model.Audit{UserId: c.Session.UserId, IpAddress: c.IpAddress, Action: c.Path, ExtraInfo: extraInfo, SessionId: c.Session.Id}
- if r := <-Srv.Store.Audit().Save(audit); r.Err != nil {
+ if r := <-app.Srv.Store.Audit().Save(audit); r.Err != nil {
c.LogError(r.Err)
}
}
@@ -316,7 +278,7 @@ func (c *Context) LogAuditWithUserId(userId, extraInfo string) {
}
audit := &model.Audit{UserId: userId, IpAddress: c.IpAddress, Action: c.Path, ExtraInfo: extraInfo, SessionId: c.Session.Id}
- if r := <-Srv.Store.Audit().Save(audit); r.Err != nil {
+ if r := <-app.Srv.Store.Audit().Save(audit); r.Err != nil {
c.LogError(r.Err)
}
}
@@ -356,7 +318,7 @@ func (c *Context) MfaRequired() {
return
}
- if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
c.Err = model.NewLocAppError("", "api.context.session_expired.app_error", nil, "MfaRequired")
c.Err.StatusCode = http.StatusUnauthorized
return
@@ -422,7 +384,7 @@ func (c *Context) setTeamURL(url string, valid bool) {
}
func (c *Context) SetTeamURLFromSession() {
- if result := <-Srv.Store.Team().Get(c.TeamId); result.Err == nil {
+ if result := <-app.Srv.Store.Team().Get(c.TeamId); result.Err == nil {
c.setTeamURL(c.GetSiteURL()+"/"+result.Data.(*model.Team).Name, true)
}
}
@@ -457,20 +419,6 @@ func IsApiCall(r *http.Request) bool {
return strings.Index(r.URL.Path, "/api/") == 0
}
-func GetIpAddress(r *http.Request) string {
- address := r.Header.Get(model.HEADER_FORWARDED)
-
- if len(address) == 0 {
- address = r.Header.Get(model.HEADER_REAL_IP)
- }
-
- if len(address) == 0 {
- address, _, _ = net.SplitHostPort(r.RemoteAddr)
- }
-
- return address
-}
-
func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request) {
T, _ := utils.GetTranslationsAndLocale(w, r)
@@ -501,7 +449,7 @@ func Handle404(w http.ResponseWriter, r *http.Request) {
err.Translate(utils.T)
err.StatusCode = http.StatusNotFound
- l4g.Debug("%v: code=404 ip=%v", r.URL.Path, GetIpAddress(r))
+ l4g.Debug("%v: code=404 ip=%v", r.URL.Path, utils.GetIpAddress(r))
if IsApiCall(r) {
w.WriteHeader(err.StatusCode)
@@ -512,81 +460,10 @@ func Handle404(w http.ResponseWriter, r *http.Request) {
}
}
-func GetSession(token string) *model.Session {
- metrics := einterfaces.GetMetricsInterface()
-
- var session *model.Session
- if ts, ok := sessionCache.Get(token); ok {
- session = ts.(*model.Session)
- if metrics != nil {
- metrics.IncrementMemCacheHitCounter("Session")
- }
- } else {
- if metrics != nil {
- metrics.IncrementMemCacheMissCounter("Session")
- }
- }
-
- if session == nil {
- if sessionResult := <-Srv.Store.Session().Get(token); sessionResult.Err != nil {
- l4g.Error(utils.T("api.context.invalid_token.error"), token, sessionResult.Err.DetailedError)
- } else {
- session = sessionResult.Data.(*model.Session)
-
- if session.IsExpired() || session.Token != token {
- return nil
- } else {
- AddSessionToCache(session)
- return session
- }
- }
- }
-
- return session
-}
-
-func RemoveAllSessionsForUserId(userId string) {
-
- RemoveAllSessionsForUserIdSkipClusterSend(userId)
-
- if einterfaces.GetClusterInterface() != nil {
- einterfaces.GetClusterInterface().RemoveAllSessionsForUserId(userId)
- }
-}
-
-func RemoveAllSessionsForUserIdSkipClusterSend(userId string) {
- keys := sessionCache.Keys()
-
- for _, key := range keys {
- if ts, ok := sessionCache.Get(key); ok {
- session := ts.(*model.Session)
- if session.UserId == userId {
- sessionCache.Remove(key)
- }
- }
- }
-
- InvalidateWebConnSessionCacheForUser(userId)
-
-}
-
-func AddSessionToCache(session *model.Session) {
- sessionCache.AddWithExpiresInSecs(session.Token, session, int64(*utils.Cfg.ServiceSettings.SessionCacheInMinutes*60))
-}
-
-func InvalidateAllCaches() {
- l4g.Info(utils.T("api.context.invalidate_all_caches"))
- sessionCache.Purge()
- ClearStatusCache()
- store.ClearChannelCaches()
- store.ClearUserCaches()
- store.ClearPostCaches()
-}
-
func (c *Context) CheckTeamId() {
if c.TeamId != "" && c.Session.GetTeamByTeamId(c.TeamId) == nil {
if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- if result := <-Srv.Store.Team().Get(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(c.TeamId); result.Err != nil {
c.Err = result.Err
c.Err.StatusCode = http.StatusBadRequest
return
diff --git a/api/context_test.go b/api/context_test.go
index 2227b7f65..cd6ca01aa 100644
--- a/api/context_test.go
+++ b/api/context_test.go
@@ -4,32 +4,9 @@
package api
import (
- "github.com/mattermost/platform/model"
"testing"
)
-func TestCache(t *testing.T) {
- session := &model.Session{
- Id: model.NewId(),
- Token: model.NewId(),
- UserId: model.NewId(),
- }
-
- sessionCache.AddWithExpiresInSecs(session.Token, session, 5*60)
-
- keys := sessionCache.Keys()
- if len(keys) <= 0 {
- t.Fatal("should have items")
- }
-
- RemoveAllSessionsForUserId(session.UserId)
-
- rkeys := sessionCache.Keys()
- if len(rkeys) != len(keys)-1 {
- t.Fatal("should have one less")
- }
-}
-
func TestSiteURL(t *testing.T) {
c := &Context{}
diff --git a/api/deprecated.go b/api/deprecated.go
index 4865ab5e0..bbaafdf15 100644
--- a/api/deprecated.go
+++ b/api/deprecated.go
@@ -8,6 +8,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -35,7 +36,7 @@ func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, 0, 100000); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, 0, 100000); result.Err != nil {
c.Err = result.Err
return
} else if HandleEtag(result.Data.(*model.ChannelList).Etag(), "Get More Channels (deprecated)", w, r) {
@@ -61,7 +62,7 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
doClearPush := false
if *utils.Cfg.EmailSettings.SendPushNotifications && !c.Session.IsMobileApp() && active {
- if result := <-Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, id); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, id); result.Err != nil {
l4g.Error(utils.T("api.channel.update_last_viewed_at.get_unread_count_for_channel.error"), c.Session.UserId, id, result.Err.Error())
} else {
if result.Data.(int64) > 0 {
@@ -76,11 +77,11 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
}
}()
- Srv.Store.Channel().UpdateLastViewedAt([]string{id}, c.Session.UserId)
+ app.Srv.Store.Channel().UpdateLastViewedAt([]string{id}, c.Session.UserId)
// Must be after update so that unread count is correct
if doClearPush {
- go clearPushNotification(c.Session.UserId, id)
+ go app.ClearPushNotification(c.Session.UserId, id)
}
chanPref := model.Preference{
@@ -97,12 +98,12 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
Value: c.TeamId,
}
- Srv.Store.Preference().Save(&model.Preferences{teamPref, chanPref})
+ app.Srv.Store.Preference().Save(&model.Preferences{teamPref, chanPref})
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, c.TeamId, "", c.Session.UserId, nil)
message.Add("channel_id", id)
- go Publish(message)
+ go app.Publish(message)
result := make(map[string]string)
result["id"] = id
@@ -116,7 +117,7 @@ func setLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
data := model.StringInterfaceFromJson(r.Body)
newLastViewedAt := int64(data["last_viewed_at"].(float64))
- Srv.Store.Channel().SetLastViewedAt(id, c.Session.UserId, newLastViewedAt)
+ app.Srv.Store.Channel().SetLastViewedAt(id, c.Session.UserId, newLastViewedAt)
chanPref := model.Preference{
UserId: c.Session.UserId,
@@ -132,12 +133,12 @@ func setLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
Value: c.TeamId,
}
- Srv.Store.Preference().Save(&model.Preferences{teamPref, chanPref})
+ app.Srv.Store.Preference().Save(&model.Preferences{teamPref, chanPref})
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, c.TeamId, "", c.Session.UserId, nil)
message.Add("channel_id", id)
- go Publish(message)
+ go app.Publish(message)
result := make(map[string]string)
result["id"] = id
diff --git a/api/emoji.go b/api/emoji.go
index 37adace49..fd78d5bd6 100644
--- a/api/emoji.go
+++ b/api/emoji.go
@@ -18,6 +18,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/disintegration/imaging"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
@@ -46,7 +47,7 @@ func getEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Emoji().GetAll(); result.Err != nil {
+ if result := <-app.Srv.Store.Emoji().GetAll(); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -114,7 +115,7 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Emoji().GetByName(emoji.Name); result.Err == nil && result.Data != nil {
+ if result := <-app.Srv.Store.Emoji().GetByName(emoji.Name); result.Err == nil && result.Data != nil {
c.Err = model.NewLocAppError("createEmoji", "api.emoji.create.duplicate.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
@@ -128,7 +129,7 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Emoji().Save(emoji); result.Err != nil {
+ if result := <-app.Srv.Store.Emoji().Save(emoji); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -210,7 +211,7 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
}
var emoji *model.Emoji
- if result := <-Srv.Store.Emoji().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.Emoji().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -223,7 +224,7 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if err := (<-Srv.Store.Emoji().Delete(id, model.GetMillis())).Err; err != nil {
+ if err := (<-app.Srv.Store.Emoji().Delete(id, model.GetMillis())).Err; err != nil {
c.Err = err
return
}
@@ -241,7 +242,7 @@ func deleteEmojiImage(id string) {
}
func deleteReactionsForEmoji(emojiName string) {
- if result := <-Srv.Store.Reaction().DeleteAllWithEmojiName(emojiName); result.Err != nil {
+ if result := <-app.Srv.Store.Reaction().DeleteAllWithEmojiName(emojiName); result.Err != nil {
l4g.Warn(utils.T("api.emoji.delete.delete_reactions.app_error"), emojiName)
l4g.Warn(result.Err)
}
@@ -268,7 +269,7 @@ func getEmojiImage(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Emoji().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.Emoji().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
diff --git a/api/emoji_test.go b/api/emoji_test.go
index efe4fd363..243703193 100644
--- a/api/emoji_test.go
+++ b/api/emoji_test.go
@@ -13,6 +13,7 @@ import (
"testing"
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -44,11 +45,11 @@ func TestGetEmoji(t *testing.T) {
}
for i, emoji := range emojis {
- emojis[i] = store.Must(Srv.Store.Emoji().Save(emoji)).(*model.Emoji)
+ emojis[i] = store.Must(app.Srv.Store.Emoji().Save(emoji)).(*model.Emoji)
}
defer func() {
for _, emoji := range emojis {
- store.Must(Srv.Store.Emoji().Delete(emoji.Id, time.Now().Unix()))
+ store.Must(app.Srv.Store.Emoji().Delete(emoji.Id, time.Now().Unix()))
}
}()
@@ -76,7 +77,7 @@ func TestGetEmoji(t *testing.T) {
Name: model.NewId(),
DeleteAt: 1,
}
- deleted = store.Must(Srv.Store.Emoji().Save(deleted)).(*model.Emoji)
+ deleted = store.Must(app.Srv.Store.Emoji().Save(deleted)).(*model.Emoji)
if returnedEmojis, err := Client.ListEmoji(); err != nil {
t.Fatal(err)
@@ -314,10 +315,10 @@ func createTestPng(t *testing.T, width int, height int) []byte {
}
func createTestEmoji(t *testing.T, emoji *model.Emoji, imageData []byte) *model.Emoji {
- emoji = store.Must(Srv.Store.Emoji().Save(emoji)).(*model.Emoji)
+ emoji = store.Must(app.Srv.Store.Emoji().Save(emoji)).(*model.Emoji)
if err := WriteFile(imageData, "emoji/"+emoji.Id+"/image"); err != nil {
- store.Must(Srv.Store.Emoji().Delete(emoji.Id, time.Now().Unix()))
+ store.Must(app.Srv.Store.Emoji().Delete(emoji.Id, time.Now().Unix()))
t.Fatalf("failed to write image: %v", err.Error())
}
diff --git a/api/file.go b/api/file.go
index 0774a78b8..179c658cd 100644
--- a/api/file.go
+++ b/api/file.go
@@ -27,6 +27,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/disintegration/imaging"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"github.com/rwcarlsen/goexif/exif"
@@ -185,7 +186,7 @@ func doUploadFile(teamId string, channelId string, userId string, rawFilename st
return nil, err
}
- if result := <-Srv.Store.FileInfo().Save(info); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().Save(info); result.Err != nil {
return nil, result.Err
}
@@ -436,7 +437,7 @@ func getFileInfoForRequest(c *Context, r *http.Request, requireFileVisible bool)
}
var info *model.FileInfo
- if result := <-Srv.Store.FileInfo().Get(fileId); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().Get(fileId); result.Err != nil {
return nil, result.Err
} else {
info = result.Data.(*model.FileInfo)
@@ -497,7 +498,7 @@ func getPublicFileOld(c *Context, w http.ResponseWriter, r *http.Request) {
path := "teams/" + teamId + "/channels/" + channelId + "/users/" + userId + "/" + filename
var info *model.FileInfo
- if result := <-Srv.Store.FileInfo().GetByPath(path); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().GetByPath(path); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -584,7 +585,7 @@ func migrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
return []*model.FileInfo{}
}
- cchan := Srv.Store.Channel().Get(post.ChannelId, true)
+ cchan := app.Srv.Store.Channel().Get(post.ChannelId, true)
// There's a weird bug that rarely happens where a post ends up with duplicate Filenames so remove those
filenames := utils.RemoveDuplicatesFromStringArray(post.Filenames)
@@ -625,12 +626,12 @@ func migrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
fileMigrationLock.Lock()
defer fileMigrationLock.Unlock()
- if result := <-Srv.Store.Post().Get(post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Get(post.Id); result.Err != nil {
l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.get_post_again.app_error"), post.Id, result.Err)
return []*model.FileInfo{}
} else if newPost := result.Data.(*model.PostList).Posts[post.Id]; len(newPost.Filenames) != len(post.Filenames) {
// Another thread has already created FileInfos for this post, so just return those
- if result := <-Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil {
l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.get_post_file_infos_again.app_error"), post.Id, result.Err)
return []*model.FileInfo{}
} else {
@@ -644,7 +645,7 @@ func migrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
savedInfos := make([]*model.FileInfo, 0, len(infos))
fileIds := make([]string, 0, len(filenames))
for _, info := range infos {
- if result := <-Srv.Store.FileInfo().Save(info); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().Save(info); result.Err != nil {
l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.save_file_info.app_error"), post.Id, info.Id, info.Path, result.Err)
continue
}
@@ -661,7 +662,7 @@ func migrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
newPost.FileIds = fileIds
// Update Posts to clear Filenames and set FileIds
- if result := <-Srv.Store.Post().Update(newPost, post); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Update(newPost, post); result.Err != nil {
l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.save_post.app_error"), post.Id, newPost.FileIds, post.Filenames, result.Err)
return []*model.FileInfo{}
} else {
@@ -675,7 +676,7 @@ func findTeamIdForFilename(post *model.Post, filename string) string {
name, _ := url.QueryUnescape(split[4])
// This post is in a direct channel so we need to figure out what team the files are stored under.
- if result := <-Srv.Store.Team().GetTeamsByUserId(post.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetTeamsByUserId(post.UserId); result.Err != nil {
l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.teams.app_error"), post.Id, result.Err)
} else if teams := result.Data.([]*model.Team); len(teams) == 1 {
// The user has only one team so the post must've been sent from it
diff --git a/api/file_test.go b/api/file_test.go
index 5d440f112..56e604fea 100644
--- a/api/file_test.go
+++ b/api/file_test.go
@@ -14,6 +14,7 @@ import (
"testing"
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -59,7 +60,7 @@ func TestUploadFile(t *testing.T) {
}
var info *model.FileInfo
- if result := <-Srv.Store.FileInfo().Get(uploadInfo.Id); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().Get(uploadInfo.Id); result.Err != nil {
t.Fatal(result.Err)
} else {
info = result.Data.(*model.FileInfo)
@@ -154,7 +155,7 @@ func TestGetFileInfo(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
// Other user shouldn't be able to get file info for this file if they're not in the channel for it
if _, err := Client.GetFileInfo(fileId); err == nil {
@@ -170,7 +171,7 @@ func TestGetFileInfo(t *testing.T) {
t.Fatal("other user got incorrect file")
}
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -223,7 +224,7 @@ func TestGetFile(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
// Other user shouldn't be able to get file for this file if they're not in the channel for it
if _, err := Client.GetFile(fileId); err == nil {
@@ -252,7 +253,7 @@ func TestGetFile(t *testing.T) {
body.Close()
}
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -292,7 +293,7 @@ func TestGetFileThumbnail(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
// Other user shouldn't be able to get thumbnail for this file if they're not in the channel for it
if _, err := Client.GetFileThumbnail(fileId); err == nil {
@@ -308,7 +309,7 @@ func TestGetFileThumbnail(t *testing.T) {
body.Close()
}
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -348,7 +349,7 @@ func TestGetFilePreview(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
// Other user shouldn't be able to get preview for this file if they're not in the channel for it
if _, err := Client.GetFilePreview(fileId); err == nil {
@@ -364,7 +365,7 @@ func TestGetFilePreview(t *testing.T) {
body.Close()
}
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -397,7 +398,7 @@ func TestGetPublicFile(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
link := Client.MustGeneric(Client.GetPublicLink(fileId)).(string)
@@ -430,7 +431,7 @@ func TestGetPublicFile(t *testing.T) {
t.Fatal("should've failed to get image with public link after salt changed")
}
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -463,7 +464,7 @@ func TestGetPublicFileOld(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
// reconstruct old style of link
siteURL := *utils.Cfg.ServiceSettings.SiteURL
@@ -501,7 +502,7 @@ func TestGetPublicFileOld(t *testing.T) {
t.Fatal("should've failed to get image with public link after salt changed")
}
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -540,7 +541,7 @@ func TestGetPublicLink(t *testing.T) {
}
// Hacky way to assign file to a post (usually would be done by CreatePost call)
- store.Must(Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
utils.Cfg.FileSettings.EnablePublicLink = false
@@ -575,7 +576,7 @@ func TestGetPublicLink(t *testing.T) {
// Wait a bit for files to ready
time.Sleep(2 * time.Second)
- if err := cleanupTestFile(store.Must(Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
+ if err := cleanupTestFile(store.Must(app.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
t.Fatal(err)
}
}
@@ -631,7 +632,7 @@ func TestMigrateFilenamesToFileInfos(t *testing.T) {
}
// Bypass the Client whenever possible since we're trying to simulate a pre-3.5 post
- post1 := store.Must(Srv.Store.Post().Save(&model.Post{
+ post1 := store.Must(app.Srv.Store.Post().Save(&model.Post{
UserId: user1.Id,
ChannelId: channel1.Id,
Message: "test",
@@ -732,7 +733,7 @@ func TestFindTeamIdForFilename(t *testing.T) {
}
// Bypass the Client whenever possible since we're trying to simulate a pre-3.5 post
- post1 := store.Must(Srv.Store.Post().Save(&model.Post{
+ post1 := store.Must(app.Srv.Store.Post().Save(&model.Post{
UserId: user1.Id,
ChannelId: channel1.Id,
Message: "test",
@@ -744,7 +745,7 @@ func TestFindTeamIdForFilename(t *testing.T) {
}
Client.SetTeamId(team2.Id)
- post2 := store.Must(Srv.Store.Post().Save(&model.Post{
+ post2 := store.Must(app.Srv.Store.Post().Save(&model.Post{
UserId: user1.Id,
ChannelId: channel2.Id,
Message: "test",
@@ -781,13 +782,13 @@ func TestGetInfoForFilename(t *testing.T) {
t.Fatal(err)
} else {
fileId1 = Client.MustGeneric(Client.UploadPostAttachment(data, channel1.Id, "test.png")).(*model.FileUploadResponse).FileInfos[0].Id
- path = store.Must(Srv.Store.FileInfo().Get(fileId1)).(*model.FileInfo).Path
- thumbnailPath = store.Must(Srv.Store.FileInfo().Get(fileId1)).(*model.FileInfo).ThumbnailPath
- previewPath = store.Must(Srv.Store.FileInfo().Get(fileId1)).(*model.FileInfo).PreviewPath
+ path = store.Must(app.Srv.Store.FileInfo().Get(fileId1)).(*model.FileInfo).Path
+ thumbnailPath = store.Must(app.Srv.Store.FileInfo().Get(fileId1)).(*model.FileInfo).ThumbnailPath
+ previewPath = store.Must(app.Srv.Store.FileInfo().Get(fileId1)).(*model.FileInfo).PreviewPath
}
// Bypass the Client whenever possible since we're trying to simulate a pre-3.5 post
- post1 := store.Must(Srv.Store.Post().Save(&model.Post{
+ post1 := store.Must(app.Srv.Store.Post().Save(&model.Post{
UserId: user1.Id,
ChannelId: channel1.Id,
Message: "test",
diff --git a/api/general.go b/api/general.go
index 24855b821..5c8e45082 100644
--- a/api/general.go
+++ b/api/general.go
@@ -10,6 +10,7 @@ import (
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -21,7 +22,7 @@ func InitGeneral() {
BaseRoutes.General.Handle("/log_client", ApiAppHandler(logClient)).Methods("POST")
BaseRoutes.General.Handle("/ping", ApiAppHandler(ping)).Methods("GET")
- BaseRoutes.WebSocket.Handle("ping", ApiWebSocketHandler(webSocketPing))
+ app.Srv.WebSocketRouter.Handle("ping", ApiWebSocketHandler(webSocketPing))
}
func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) {
diff --git a/api/import.go b/api/import.go
index a6db73126..b93a061fe 100644
--- a/api/import.go
+++ b/api/import.go
@@ -10,6 +10,7 @@ import (
"unicode/utf8"
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -34,12 +35,12 @@ func ImportPost(post *model.Post) {
post.Hashtags, _ = model.ParseHashtags(post.Message)
- if result := <-Srv.Store.Post().Save(post); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Save(post); result.Err != nil {
l4g.Debug(utils.T("api.import.import_post.saving.debug"), post.UserId, post.Message)
}
for _, fileId := range post.FileIds {
- if result := <-Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
l4g.Error(utils.T("api.import.import_post.attach_files.error"), post.Id, post.FileIds, result.Err)
}
}
@@ -55,17 +56,17 @@ func ImportUser(team *model.Team, user *model.User) *model.User {
user.Roles = model.ROLE_SYSTEM_USER.Id
- if result := <-Srv.Store.User().Save(user); result.Err != nil {
+ if result := <-app.Srv.Store.User().Save(user); result.Err != nil {
l4g.Error(utils.T("api.import.import_user.saving.error"), result.Err)
return nil
} else {
ruser := result.Data.(*model.User)
- if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
+ if cresult := <-app.Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
l4g.Error(utils.T("api.import.import_user.set_email.error"), cresult.Err)
}
- if err := JoinUserToTeam(team, user); err != nil {
+ if err := app.JoinUserToTeam(team, user); err != nil {
l4g.Error(utils.T("api.import.import_user.join_team.error"), err)
}
@@ -74,7 +75,7 @@ func ImportUser(team *model.Team, user *model.User) *model.User {
}
func ImportChannel(channel *model.Channel) *model.Channel {
- if result := <-Srv.Store.Channel().Save(channel); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().Save(channel); result.Err != nil {
return nil
} else {
sc := result.Data.(*model.Channel)
diff --git a/api/license.go b/api/license.go
index 65ca90943..8a6ee7385 100644
--- a/api/license.go
+++ b/api/license.go
@@ -10,6 +10,7 @@ import (
"strings"
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -29,7 +30,7 @@ func InitLicense() {
func LoadLicense() {
licenseId := ""
- if result := <-Srv.Store.System().Get(); result.Err == nil {
+ if result := <-app.Srv.Store.System().Get(); result.Err == nil {
props := result.Data.(model.StringMap)
licenseId = props[model.SYSTEM_ACTIVE_LICENSE_ID]
}
@@ -39,7 +40,7 @@ func LoadLicense() {
return
}
- if result := <-Srv.Store.License().Get(licenseId); result.Err == nil {
+ if result := <-app.Srv.Store.License().Get(licenseId); result.Err == nil {
record := result.Data.(*model.LicenseRecord)
utils.LoadLicense([]byte(record.Bytes))
} else {
@@ -104,7 +105,7 @@ func SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
if success, licenseStr := utils.ValidateLicense(licenseBytes); success {
license = model.LicenseFromJson(strings.NewReader(licenseStr))
- if result := <-Srv.Store.User().AnalyticsUniqueUserCount(""); result.Err != nil {
+ if result := <-app.Srv.Store.User().AnalyticsUniqueUserCount(""); result.Err != nil {
return nil, model.NewLocAppError("addLicense", "api.license.add_license.invalid_count.app_error", nil, result.Err.Error())
} else {
uniqueUserCount := result.Data.(int64)
@@ -121,12 +122,12 @@ func SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
record := &model.LicenseRecord{}
record.Id = license.Id
record.Bytes = string(licenseBytes)
- rchan := Srv.Store.License().Save(record)
+ rchan := app.Srv.Store.License().Save(record)
sysVar := &model.System{}
sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
sysVar.Value = license.Id
- schan := Srv.Store.System().SaveOrUpdate(sysVar)
+ schan := app.Srv.Store.System().SaveOrUpdate(sysVar)
if result := <-rchan; result.Err != nil {
RemoveLicense()
@@ -164,7 +165,7 @@ func RemoveLicense() *model.AppError {
sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
sysVar.Value = ""
- if result := <-Srv.Store.System().SaveOrUpdate(sysVar); result.Err != nil {
+ if result := <-app.Srv.Store.System().SaveOrUpdate(sysVar); result.Err != nil {
utils.RemoveLicense()
return result.Err
}
diff --git a/api/oauth.go b/api/oauth.go
index 268cf1aed..80daf7415 100644
--- a/api/oauth.go
+++ b/api/oauth.go
@@ -16,6 +16,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
@@ -59,27 +60,27 @@ func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- app := model.OAuthAppFromJson(r.Body)
+ oauthApp := model.OAuthAppFromJson(r.Body)
- if app == nil {
+ if oauthApp == nil {
c.SetInvalidParam("registerOAuthApp", "app")
return
}
secret := model.NewId()
- app.ClientSecret = secret
- app.CreatorId = c.Session.UserId
+ oauthApp.ClientSecret = secret
+ oauthApp.CreatorId = c.Session.UserId
- if result := <-Srv.Store.OAuth().SaveApp(app); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().SaveApp(oauthApp); result.Err != nil {
c.Err = result.Err
return
} else {
- app = result.Data.(*model.OAuthApp)
+ oauthApp = result.Data.(*model.OAuthApp)
- c.LogAudit("client_id=" + app.Id)
+ c.LogAudit("client_id=" + oauthApp.Id)
- w.Write([]byte(app.ToJson()))
+ w.Write([]byte(oauthApp.ToJson()))
return
}
@@ -100,10 +101,10 @@ func getOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) {
var ochan store.StoreChannel
if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
- ochan = Srv.Store.OAuth().GetApps()
+ ochan = app.Srv.Store.OAuth().GetApps()
} else {
c.Err = nil
- ochan = Srv.Store.OAuth().GetAppByUser(c.Session.UserId)
+ ochan = app.Srv.Store.OAuth().GetAppByUser(c.Session.UserId)
}
if result := <-ochan; result.Err != nil {
@@ -126,16 +127,16 @@ func getOAuthAppInfo(c *Context, w http.ResponseWriter, r *http.Request) {
clientId := params["client_id"]
- var app *model.OAuthApp
- if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
+ var oauthApp *model.OAuthApp
+ if result := <-app.Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
c.Err = model.NewLocAppError("getOAuthAppInfo", "api.oauth.allow_oauth.database.app_error", nil, "")
return
} else {
- app = result.Data.(*model.OAuthApp)
+ oauthApp = result.Data.(*model.OAuthApp)
}
- app.Sanitize()
- w.Write([]byte(app.ToJson()))
+ oauthApp.Sanitize()
+ w.Write([]byte(oauthApp.ToJson()))
}
func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -177,15 +178,15 @@ func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
scope = model.DEFAULT_SCOPE
}
- var app *model.OAuthApp
- if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
+ var oauthApp *model.OAuthApp
+ if result := <-app.Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.database.app_error", nil, "")
return
} else {
- app = result.Data.(*model.OAuthApp)
+ oauthApp = result.Data.(*model.OAuthApp)
}
- if !app.IsValidRedirectURL(redirectUri) {
+ if !oauthApp.IsValidRedirectURL(redirectUri) {
c.LogAudit("fail - redirect_uri did not match registered callback")
c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.redirect_callback.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
@@ -209,13 +210,13 @@ func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
Value: scope,
}
- if result := <-Srv.Store.Preference().Save(&model.Preferences{authorizedApp}); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Save(&model.Preferences{authorizedApp}); result.Err != nil {
responseData["redirect"] = redirectUri + "?error=server_error&state=" + state
w.Write([]byte(model.MapToJson(responseData)))
return
}
- if result := <-Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil {
responseData["redirect"] = redirectUri + "?error=server_error&state=" + state
w.Write([]byte(model.MapToJson(responseData)))
return
@@ -234,7 +235,7 @@ func getAuthorizedApps(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- ochan := Srv.Store.OAuth().GetAuthorizedApps(c.Session.UserId)
+ ochan := app.Srv.Store.OAuth().GetAuthorizedApps(c.Session.UserId)
if result := <-ochan; result.Err != nil {
c.Err = result.Err
return
@@ -251,14 +252,14 @@ func getAuthorizedApps(c *Context, w http.ResponseWriter, r *http.Request) {
func RevokeAccessToken(token string) *model.AppError {
- session := GetSession(token)
- schan := Srv.Store.Session().Remove(token)
+ session, _ := app.GetSession(token)
+ schan := app.Srv.Store.Session().Remove(token)
- if result := <-Srv.Store.OAuth().GetAccessData(token); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().GetAccessData(token); result.Err != nil {
return model.NewLocAppError("RevokeAccessToken", "api.oauth.revoke_access_token.get.app_error", nil, "")
}
- tchan := Srv.Store.OAuth().RemoveAccessData(token)
+ tchan := app.Srv.Store.OAuth().RemoveAccessData(token)
if result := <-tchan; result.Err != nil {
return model.NewLocAppError("RevokeAccessToken", "api.oauth.revoke_access_token.del_token.app_error", nil, "")
@@ -269,14 +270,14 @@ func RevokeAccessToken(token string) *model.AppError {
}
if session != nil {
- RemoveAllSessionsForUserId(session.UserId)
+ app.RemoveAllSessionsForUserId(session.UserId)
}
return nil
}
func GetAuthData(code string) *model.AuthData {
- if result := <-Srv.Store.OAuth().GetAuthData(code); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().GetAuthData(code); result.Err != nil {
l4g.Error(utils.T("api.oauth.get_auth_data.find.error"), code)
return nil
} else {
@@ -318,7 +319,7 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
case model.OAUTH_ACTION_LOGIN:
user := LoginByOAuth(c, w, r, service, body)
if len(teamId) > 0 {
- c.Err = JoinUserToTeamById(teamId, user)
+ c.Err = app.JoinUserToTeamById(teamId, user)
}
if c.Err == nil {
if val, ok := props["redirect_to"]; ok {
@@ -372,12 +373,12 @@ func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var app *model.OAuthApp
- if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
+ var oauthApp *model.OAuthApp
+ if result := <-app.Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
c.Err = result.Err
return
} else {
- app = result.Data.(*model.OAuthApp)
+ oauthApp = result.Data.(*model.OAuthApp)
}
// here we should check if the user is logged in
@@ -387,13 +388,13 @@ func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
}
isAuthorized := false
- if result := <-Srv.Store.Preference().Get(c.Session.UserId, model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, clientId); result.Err == nil {
+ if result := <-app.Srv.Store.Preference().Get(c.Session.UserId, model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, clientId); result.Err == nil {
// when we support scopes we should check if the scopes match
isAuthorized = true
}
// Automatically allow if the app is trusted
- if app.IsTrusted || isAuthorized {
+ if oauthApp.IsTrusted || isAuthorized {
closeBody := func(r *http.Response) {
if r.Body != nil {
ioutil.ReadAll(r.Body)
@@ -481,16 +482,16 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var app *model.OAuthApp
- achan := Srv.Store.OAuth().GetApp(clientId)
+ var oauthApp *model.OAuthApp
+ achan := app.Srv.Store.OAuth().GetApp(clientId)
if result := <-achan; result.Err != nil {
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "")
return
} else {
- app = result.Data.(*model.OAuthApp)
+ oauthApp = result.Data.(*model.OAuthApp)
}
- if app.ClientSecret != secret {
+ if oauthApp.ClientSecret != secret {
c.LogAudit("fail - invalid client credentials")
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "")
return
@@ -510,7 +511,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
}
if authData.IsExpired() {
- <-Srv.Store.OAuth().RemoveAuthData(authData.Code)
+ <-app.Srv.Store.OAuth().RemoveAuthData(authData.Code)
c.LogAudit("fail - auth code expired")
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "")
return
@@ -528,7 +529,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- uchan := Srv.Store.User().Get(authData.UserId)
+ uchan := app.Srv.Store.User().Get(authData.UserId)
if result := <-uchan; result.Err != nil {
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "")
return
@@ -536,14 +537,14 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User)
}
- tchan := Srv.Store.OAuth().GetPreviousAccessData(user.Id, clientId)
+ tchan := app.Srv.Store.OAuth().GetPreviousAccessData(user.Id, clientId)
if result := <-tchan; result.Err != nil {
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal.app_error", nil, "")
return
} else if result.Data != nil {
accessData := result.Data.(*model.AccessData)
if accessData.IsExpired() {
- if access, err := newSessionUpdateToken(app.Name, accessData, user); err != nil {
+ if access, err := newSessionUpdateToken(oauthApp.Name, accessData, user); err != nil {
c.Err = err
return
} else {
@@ -560,7 +561,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
// create a new session and return new access token
var session *model.Session
- if result, err := newSession(app.Name, user); err != nil {
+ if result, err := newSession(oauthApp.Name, user); err != nil {
c.Err = err
return
} else {
@@ -569,7 +570,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
accessData = &model.AccessData{ClientId: clientId, UserId: user.Id, Token: session.Token, RefreshToken: model.NewId(), RedirectUri: redirectUri, ExpiresAt: session.ExpiresAt}
- if result := <-Srv.Store.OAuth().SaveAccessData(accessData); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().SaveAccessData(accessData); result.Err != nil {
l4g.Error(result.Err)
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_saving.app_error", nil, "")
return
@@ -583,10 +584,10 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- <-Srv.Store.OAuth().RemoveAuthData(authData.Code)
+ <-app.Srv.Store.OAuth().RemoveAuthData(authData.Code)
} else {
// when grantType is refresh_token
- if result := <-Srv.Store.OAuth().GetAccessDataByRefreshToken(refreshToken); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().GetAccessDataByRefreshToken(refreshToken); result.Err != nil {
c.LogAudit("fail - refresh token is invalid")
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.refresh_token.app_error", nil, "")
return
@@ -594,7 +595,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
accessData = result.Data.(*model.AccessData)
}
- uchan := Srv.Store.User().Get(accessData.UserId)
+ uchan := app.Srv.Store.User().Get(accessData.UserId)
if result := <-uchan; result.Err != nil {
c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "")
return
@@ -602,7 +603,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User)
}
- if access, err := newSessionUpdateToken(app.Name, accessData, user); err != nil {
+ if access, err := newSessionUpdateToken(oauthApp.Name, accessData, user); err != nil {
c.Err = err
return
} else {
@@ -668,7 +669,7 @@ func getTeamIdFromQuery(query url.Values) (string, *model.AppError) {
return props["id"], nil
} else if len(inviteId) > 0 {
- if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
// soft fail, so we still create user but don't auto-join team
l4g.Error("%v", result.Err)
} else {
@@ -844,7 +845,7 @@ func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request,
}
var user *model.User
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -856,7 +857,7 @@ func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request,
return
}
- if result := <-Srv.Store.User().UpdateAuthData(user.Id, service, &authData, ssoEmail, true); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdateAuthData(user.Id, service, &authData, ssoEmail, true); result.Err != nil {
c.Err = result.Err
return
}
@@ -887,7 +888,7 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.OAuth().GetApp(id); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().GetApp(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -898,7 +899,7 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if err := (<-Srv.Store.OAuth().DeleteApp(id)).Err; err != nil {
+ if err := (<-app.Srv.Store.OAuth().DeleteApp(id)).Err; err != nil {
c.Err = err
return
}
@@ -923,7 +924,7 @@ func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
// revoke app sessions
- if result := <-Srv.Store.OAuth().GetAccessDataByUserForApp(c.Session.UserId, id); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().GetAccessDataByUserForApp(c.Session.UserId, id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -935,7 +936,7 @@ func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if rad := <-Srv.Store.OAuth().RemoveAccessData(a.Token); rad.Err != nil {
+ if rad := <-app.Srv.Store.OAuth().RemoveAccessData(a.Token); rad.Err != nil {
c.Err = rad.Err
return
}
@@ -943,7 +944,7 @@ func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
// Deauthorize the app
- if err := (<-Srv.Store.Preference().Delete(c.Session.UserId, model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, id)).Err; err != nil {
+ if err := (<-app.Srv.Store.Preference().Delete(c.Session.UserId, model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, id)).Err; err != nil {
c.Err = err
return
}
@@ -967,26 +968,26 @@ func regenerateOAuthSecret(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var app *model.OAuthApp
- if result := <-Srv.Store.OAuth().GetApp(id); result.Err != nil {
+ var oauthApp *model.OAuthApp
+ if result := <-app.Srv.Store.OAuth().GetApp(id); result.Err != nil {
c.Err = model.NewLocAppError("regenerateOAuthSecret", "api.oauth.allow_oauth.database.app_error", nil, "")
return
} else {
- app = result.Data.(*model.OAuthApp)
+ oauthApp = result.Data.(*model.OAuthApp)
- if app.CreatorId != c.Session.UserId && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
+ if oauthApp.CreatorId != c.Session.UserId && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
- app.ClientSecret = model.NewId()
- if update := <-Srv.Store.OAuth().UpdateApp(app); update.Err != nil {
+ oauthApp.ClientSecret = model.NewId()
+ if update := <-app.Srv.Store.OAuth().UpdateApp(oauthApp); update.Err != nil {
c.Err = update.Err
return
}
- w.Write([]byte(app.ToJson()))
+ w.Write([]byte(oauthApp.ToJson()))
return
}
}
@@ -999,11 +1000,11 @@ func newSession(appName string, user *model.User) (*model.Session, *model.AppErr
session.AddProp(model.SESSION_PROP_OS, "OAuth2")
session.AddProp(model.SESSION_PROP_BROWSER, "OAuth2")
- if result := <-Srv.Store.Session().Save(session); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Save(session); result.Err != nil {
return nil, model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_session.app_error", nil, "")
} else {
session = result.Data.(*model.Session)
- AddSessionToCache(session)
+ app.AddSessionToCache(session)
}
return session, nil
@@ -1011,7 +1012,7 @@ func newSession(appName string, user *model.User) (*model.Session, *model.AppErr
func newSessionUpdateToken(appName string, accessData *model.AccessData, user *model.User) (*model.AccessResponse, *model.AppError) {
var session *model.Session
- <-Srv.Store.Session().Remove(accessData.Token) //remove the previous session
+ <-app.Srv.Store.Session().Remove(accessData.Token) //remove the previous session
if result, err := newSession(appName, user); err != nil {
return nil, err
@@ -1021,7 +1022,7 @@ func newSessionUpdateToken(appName string, accessData *model.AccessData, user *m
accessData.Token = session.Token
accessData.ExpiresAt = session.ExpiresAt
- if result := <-Srv.Store.OAuth().UpdateAccessData(accessData); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().UpdateAccessData(accessData); result.Err != nil {
l4g.Error(result.Err)
return nil, model.NewLocAppError("getAccessToken", "web.get_access_token.internal_saving.app_error", nil, "")
}
diff --git a/api/post.go b/api/post.go
index 8d255649e..270ab72ca 100644
--- a/api/post.go
+++ b/api/post.go
@@ -4,33 +4,15 @@
package api
import (
- "crypto/tls"
- "fmt"
- "html"
- "html/template"
- "io"
- "io/ioutil"
"net/http"
- "net/url"
- "path/filepath"
- "regexp"
- "sort"
"strconv"
- "strings"
- "time"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
- "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
- "github.com/nicksnyder/go-i18n/i18n"
-)
-
-const (
- TRIGGERWORDS_FULL = 0
- TRIGGERWORDS_STARTSWITH = 1
)
func InitPost() {
@@ -61,7 +43,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
post.UserId = c.Session.UserId
- cchan := Srv.Store.Channel().Get(post.ChannelId, true)
+ cchan := app.Srv.Store.Channel().Get(post.ChannelId, true)
if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_CREATE_POST) {
return
@@ -82,7 +64,11 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if rp, err := CreatePost(c, post, true); err != nil {
+ if post.CreateAt != 0 && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
+ post.CreateAt = 0
+ }
+
+ if rp, err := app.CreatePost(post, c.TeamId, true); err != nil {
c.Err = err
if c.Err.Id == "api.post.create_post.root_id.app_error" ||
@@ -95,7 +81,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
// Update the LastViewAt only if the post does not have from_webhook prop set (eg. Zapier app)
if _, ok := post.Props["from_webhook"]; !ok {
- if result := <-Srv.Store.Channel().UpdateLastViewedAt([]string{post.ChannelId}, c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().UpdateLastViewedAt([]string{post.ChannelId}, c.Session.UserId); result.Err != nil {
l4g.Error(utils.T("api.post.create_post.last_viewed.error"), post.ChannelId, c.Session.UserId, result.Err)
}
}
@@ -104,1106 +90,6 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func CreatePost(c *Context, post *model.Post, triggerWebhooks bool) (*model.Post, *model.AppError) {
- var pchan store.StoreChannel
- if len(post.RootId) > 0 {
- pchan = Srv.Store.Post().Get(post.RootId)
- }
-
- // Verify the parent/child relationships are correct
- if pchan != nil {
- if presult := <-pchan; presult.Err != nil {
- return nil, model.NewLocAppError("createPost", "api.post.create_post.root_id.app_error", nil, "")
- } else {
- list := presult.Data.(*model.PostList)
- if len(list.Posts) == 0 || !list.IsChannelId(post.ChannelId) {
- return nil, model.NewLocAppError("createPost", "api.post.create_post.channel_root_id.app_error", nil, "")
- }
-
- if post.ParentId == "" {
- post.ParentId = post.RootId
- }
-
- if post.RootId != post.ParentId {
- parent := list.Posts[post.ParentId]
- if parent == nil {
- return nil, model.NewLocAppError("createPost", "api.post.create_post.parent_id.app_error", nil, "")
- }
- }
- }
- }
-
- if post.CreateAt != 0 && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- post.CreateAt = 0
- c.Err = nil
- }
-
- post.Hashtags, _ = model.ParseHashtags(post.Message)
-
- var rpost *model.Post
- if result := <-Srv.Store.Post().Save(post); result.Err != nil {
- return nil, result.Err
- } else {
- rpost = result.Data.(*model.Post)
- }
-
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostCreate()
- }
-
- if len(post.FileIds) > 0 {
- // There's a rare bug where the client sends up duplicate FileIds so protect against that
- post.FileIds = utils.RemoveDuplicatesFromStringArray(post.FileIds)
-
- for _, fileId := range post.FileIds {
- if result := <-Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
- l4g.Error(utils.T("api.post.create_post.attach_files.error"), post.Id, post.FileIds, c.Session.UserId, result.Err)
- }
- }
-
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostFileAttachment(len(post.FileIds))
- }
- }
-
- InvalidateCacheForChannel(rpost.ChannelId)
- InvalidateCacheForChannelPosts(rpost.ChannelId)
-
- handlePostEvents(c, rpost, triggerWebhooks)
-
- return rpost, nil
-}
-
-var linkWithTextRegex *regexp.Regexp = regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
-
-func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIconUrl string, props model.StringInterface, postType string) (*model.Post, *model.AppError) {
- post := &model.Post{UserId: c.Session.UserId, ChannelId: channelId, Message: text, Type: postType}
- post.AddProp("from_webhook", "true")
-
- if utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
- if len(overrideUsername) != 0 {
- post.AddProp("override_username", overrideUsername)
- } else {
- post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
- }
- }
-
- if utils.Cfg.ServiceSettings.EnablePostIconOverride {
- if len(overrideIconUrl) != 0 {
- post.AddProp("override_icon_url", overrideIconUrl)
- }
- }
-
- post.Message = parseSlackLinksToMarkdown(post.Message)
-
- if len(props) > 0 {
- for key, val := range props {
- if key == "attachments" {
- parseSlackAttachment(post, val)
- } else if key != "override_icon_url" && key != "override_username" && key != "from_webhook" {
- post.AddProp(key, val)
- }
- }
- }
-
- if _, err := CreatePost(c, post, false); err != nil {
- return nil, model.NewLocAppError("CreateWebhookPost", "api.post.create_webhook_post.creating.app_error", nil, "err="+err.Message)
- }
-
- return post, nil
-}
-
-func CreateCommandPost(c *Context, post *model.Post, response *model.CommandResponse) {
- post.Message = parseSlackLinksToMarkdown(response.Text)
- post.UserId = c.Session.UserId
- post.CreateAt = model.GetMillis()
-
- if response.Attachments != nil {
- parseSlackAttachment(post, response.Attachments)
- }
-
- switch response.ResponseType {
- case model.COMMAND_RESPONSE_TYPE_IN_CHANNEL:
- if _, err := CreatePost(c, post, true); err != nil {
- c.Err = model.NewLocAppError("command", "api.command.execute_command.save.app_error", nil, "")
- }
- case model.COMMAND_RESPONSE_TYPE_EPHEMERAL:
- if response.Text == "" {
- return
- }
-
- post.ParentId = ""
- SendEphemeralPost(c.TeamId, c.Session.UserId, post)
- }
-}
-
-// This method only parses and processes the attachments,
-// all else should be set in the post which is passed
-func parseSlackAttachment(post *model.Post, attachments interface{}) {
- post.Type = model.POST_SLACK_ATTACHMENT
-
- if list, success := attachments.([]interface{}); success {
- for i, aInt := range list {
- attachment := aInt.(map[string]interface{})
- if aText, ok := attachment["text"].(string); ok {
- aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
- attachment["text"] = aText
- list[i] = attachment
- }
- if aText, ok := attachment["pretext"].(string); ok {
- aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
- attachment["pretext"] = aText
- list[i] = attachment
- }
- if fVal, ok := attachment["fields"]; ok {
- if fields, ok := fVal.([]interface{}); ok {
- // parse attachment field links into Markdown format
- for j, fInt := range fields {
- field := fInt.(map[string]interface{})
- if fValue, ok := field["value"].(string); ok {
- fValue = linkWithTextRegex.ReplaceAllString(fValue, "[${2}](${1})")
- field["value"] = fValue
- fields[j] = field
- }
- }
- attachment["fields"] = fields
- list[i] = attachment
- }
- }
- }
- post.AddProp("attachments", list)
- }
-}
-
-func parseSlackLinksToMarkdown(text string) string {
- return linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})")
-}
-
-func handlePostEvents(c *Context, post *model.Post, triggerWebhooks bool) {
- tchan := Srv.Store.Team().Get(c.TeamId)
- cchan := Srv.Store.Channel().Get(post.ChannelId, true)
- uchan := Srv.Store.User().Get(post.UserId)
-
- var team *model.Team
- if result := <-tchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.team.error"), c.TeamId, result.Err)
- return
- } else {
- team = result.Data.(*model.Team)
- }
-
- var channel *model.Channel
- if result := <-cchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.channel.error"), post.ChannelId, result.Err)
- return
- } else {
- channel = result.Data.(*model.Channel)
- }
-
- sendNotifications(c, post, team, channel)
-
- var user *model.User
- if result := <-uchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.user.error"), post.UserId, result.Err)
- return
- } else {
- user = result.Data.(*model.User)
- }
-
- if triggerWebhooks {
- go handleWebhookEvents(c, post, team, channel, user)
- }
-
- if channel.Type == model.CHANNEL_DIRECT {
- go makeDirectChannelVisible(post.ChannelId)
- }
-}
-
-func makeDirectChannelVisible(channelId string) {
- var members []model.ChannelMember
- if result := <-Srv.Store.Channel().GetMembers(channelId); result.Err != nil {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.get_members.error"), channelId, result.Err.Message)
- return
- } else {
- members = result.Data.([]model.ChannelMember)
- }
-
- if len(members) != 2 {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.get_2_members.error"), channelId)
- return
- }
-
- // make sure the channel is visible to both members
- for i, member := range members {
- otherUserId := members[1-i].UserId
-
- if result := <-Srv.Store.Preference().Get(member.UserId, model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, otherUserId); result.Err != nil {
- // create a new preference since one doesn't exist yet
- preference := &model.Preference{
- UserId: member.UserId,
- Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
- Name: otherUserId,
- Value: "true",
- }
-
- if saveResult := <-Srv.Store.Preference().Save(&model.Preferences{*preference}); saveResult.Err != nil {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.save_pref.error"), member.UserId, otherUserId, saveResult.Err.Message)
- } else {
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil)
- message.Add("preference", preference.ToJson())
-
- go Publish(message)
- }
- } else {
- preference := result.Data.(model.Preference)
-
- if preference.Value != "true" {
- // update the existing preference to make the channel visible
- preference.Value = "true"
-
- if updateResult := <-Srv.Store.Preference().Save(&model.Preferences{preference}); updateResult.Err != nil {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.update_pref.error"), member.UserId, otherUserId, updateResult.Err.Message)
- } else {
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil)
- message.Add("preference", preference.ToJson())
-
- go Publish(message)
- }
- }
- }
- }
-}
-
-func handleWebhookEvents(c *Context, post *model.Post, team *model.Team, channel *model.Channel, user *model.User) {
- if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
- return
- }
-
- if channel.Type != model.CHANNEL_OPEN {
- return
- }
-
- hchan := Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId)
- result := <-hchan
- if result.Err != nil {
- l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.getting.error"), result.Err)
- return
- }
-
- hooks := result.Data.([]*model.OutgoingWebhook)
- if len(hooks) == 0 {
- return
- }
-
- splitWords := strings.Fields(post.Message)
- if len(splitWords) == 0 {
- return
- }
- firstWord := splitWords[0]
-
- relevantHooks := []*model.OutgoingWebhook{}
- for _, hook := range hooks {
- if hook.ChannelId == post.ChannelId || len(hook.ChannelId) == 0 {
- if hook.ChannelId == post.ChannelId && len(hook.TriggerWords) == 0 {
- relevantHooks = append(relevantHooks, hook)
- } else if hook.TriggerWhen == TRIGGERWORDS_FULL && hook.HasTriggerWord(firstWord) {
- relevantHooks = append(relevantHooks, hook)
- } else if hook.TriggerWhen == TRIGGERWORDS_STARTSWITH && hook.TriggerWordStartsWith(firstWord) {
- relevantHooks = append(relevantHooks, hook)
- }
- }
- }
-
- for _, hook := range relevantHooks {
- go func(hook *model.OutgoingWebhook) {
- payload := &model.OutgoingWebhookPayload{
- Token: hook.Token,
- TeamId: hook.TeamId,
- TeamDomain: team.Name,
- ChannelId: post.ChannelId,
- ChannelName: channel.Name,
- Timestamp: post.CreateAt,
- UserId: post.UserId,
- UserName: user.Username,
- PostId: post.Id,
- Text: post.Message,
- TriggerWord: firstWord,
- }
- var body io.Reader
- var contentType string
- if hook.ContentType == "application/json" {
- body = strings.NewReader(payload.ToJSON())
- contentType = "application/json"
- } else {
- body = strings.NewReader(payload.ToFormValues())
- contentType = "application/x-www-form-urlencoded"
- }
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- client := &http.Client{Transport: tr}
-
- for _, url := range hook.CallbackURLs {
- go func(url string) {
- req, _ := http.NewRequest("POST", url, body)
- req.Header.Set("Content-Type", contentType)
- req.Header.Set("Accept", "application/json")
- if resp, err := client.Do(req); err != nil {
- l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.event_post.error"), err.Error())
- } else {
- defer func() {
- ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- }()
- respProps := model.MapFromJson(resp.Body)
-
- // copy the context and create a mock session for posting the message
- mockSession := model.Session{
- UserId: hook.CreatorId,
- TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.CreatorId}},
- IsOAuth: false,
- }
-
- newContext := &Context{
- Session: mockSession,
- RequestId: model.NewId(),
- IpAddress: "",
- Path: c.Path,
- Err: nil,
- teamURLValid: c.teamURLValid,
- teamURL: c.teamURL,
- siteURL: c.siteURL,
- T: c.T,
- Locale: c.Locale,
- TeamId: hook.TeamId,
- }
-
- if text, ok := respProps["text"]; ok {
- if _, err := CreateWebhookPost(newContext, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil {
- l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.create_post.error"), err)
- }
- }
- }
- }(url)
- }
-
- }(hook)
- }
-}
-
-// Given a map of user IDs to profiles, returns a list of mention
-// keywords for all users in the channel.
-func getMentionKeywordsInChannel(profiles map[string]*model.User) map[string][]string {
- keywords := make(map[string][]string)
-
- for id, profile := range profiles {
- userMention := "@" + strings.ToLower(profile.Username)
- keywords[userMention] = append(keywords[userMention], id)
-
- if len(profile.NotifyProps["mention_keys"]) > 0 {
- // Add all the user's mention keys
- splitKeys := strings.Split(profile.NotifyProps["mention_keys"], ",")
- for _, k := range splitKeys {
- // note that these are made lower case so that we can do a case insensitive check for them
- key := strings.ToLower(k)
- keywords[key] = append(keywords[key], id)
- }
- }
-
- // If turned on, add the user's case sensitive first name
- if profile.NotifyProps["first_name"] == "true" {
- keywords[profile.FirstName] = append(keywords[profile.FirstName], profile.Id)
- }
-
- // Add @channel and @all to keywords if user has them turned on
- if int64(len(profiles)) < *utils.Cfg.TeamSettings.MaxNotificationsPerChannel && profile.NotifyProps["channel"] == "true" {
- keywords["@channel"] = append(keywords["@channel"], profile.Id)
- keywords["@all"] = append(keywords["@all"], profile.Id)
- }
- }
-
- return keywords
-}
-
-// Given a message and a map mapping mention keywords to the users who use them, returns a map of mentioned
-// users and a slice of potencial mention users not in the channel and whether or not @here was mentioned.
-func getExplicitMentions(message string, keywords map[string][]string) (map[string]bool, []string, bool, bool, bool) {
- mentioned := make(map[string]bool)
- potentialOthersMentioned := make([]string, 0)
- systemMentions := map[string]bool{"@here": true, "@channel": true, "@all": true}
- hereMentioned := false
- allMentioned := false
- channelMentioned := false
-
- addMentionedUsers := func(ids []string) {
- for _, id := range ids {
- mentioned[id] = true
- }
- }
-
- for _, word := range strings.Fields(message) {
- isMention := false
-
- if word == "@here" {
- hereMentioned = true
- }
-
- if word == "@channel" {
- channelMentioned = true
- }
-
- if word == "@all" {
- allMentioned = true
- }
-
- // Non-case-sensitive check for regular keys
- if ids, match := keywords[strings.ToLower(word)]; match {
- addMentionedUsers(ids)
- isMention = true
- }
-
- // Case-sensitive check for first name
- if ids, match := keywords[word]; match {
- addMentionedUsers(ids)
- isMention = true
- }
-
- if !isMention {
- // No matches were found with the string split just on whitespace so try further splitting
- // the message on punctuation
- splitWords := strings.FieldsFunc(word, func(c rune) bool {
- return model.SplitRunes[c]
- })
-
- for _, splitWord := range splitWords {
- if splitWord == "@here" {
- hereMentioned = true
- }
-
- if splitWord == "@all" {
- allMentioned = true
- }
-
- if splitWord == "@channel" {
- channelMentioned = true
- }
-
- // Non-case-sensitive check for regular keys
- if ids, match := keywords[strings.ToLower(splitWord)]; match {
- addMentionedUsers(ids)
- }
-
- // Case-sensitive check for first name
- if ids, match := keywords[splitWord]; match {
- addMentionedUsers(ids)
- } else if _, ok := systemMentions[word]; !ok && strings.HasPrefix(word, "@") {
- username := word[1:len(splitWord)]
- potentialOthersMentioned = append(potentialOthersMentioned, username)
- }
- }
- }
- }
-
- return mentioned, potentialOthersMentioned, hereMentioned, channelMentioned, allMentioned
-}
-
-func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *model.Channel) []string {
- mentionedUsersList := make([]string, 0)
- var fchan store.StoreChannel
- var senderUsername string
-
- if post.IsSystemMessage() {
- senderUsername = c.T("system.message.name")
- } else {
- pchan := Srv.Store.User().GetProfilesInChannel(channel.Id, -1, -1, true)
- fchan = Srv.Store.FileInfo().GetForPost(post.Id)
-
- var profileMap map[string]*model.User
- if result := <-pchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.profiles.error"), c.TeamId, result.Err)
- return nil
- } else {
- profileMap = result.Data.(map[string]*model.User)
- }
-
- // If the user who made the post is mention don't send a notification
- if _, ok := profileMap[post.UserId]; !ok {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.user_id.error"), post.UserId)
- return nil
- }
-
- mentionedUserIds := make(map[string]bool)
- allActivityPushUserIds := []string{}
- hereNotification := false
- channelNotification := false
- allNotification := false
- updateMentionChans := []store.StoreChannel{}
-
- if channel.Type == model.CHANNEL_DIRECT {
- var otherUserId string
- if userIds := strings.Split(channel.Name, "__"); userIds[0] == post.UserId {
- otherUserId = userIds[1]
- } else {
- otherUserId = userIds[0]
- }
-
- mentionedUserIds[otherUserId] = true
- if post.Props["from_webhook"] == "true" {
- mentionedUserIds[post.UserId] = true
- }
- } else {
- keywords := getMentionKeywordsInChannel(profileMap)
-
- var potentialOtherMentions []string
- mentionedUserIds, potentialOtherMentions, hereNotification, channelNotification, allNotification = getExplicitMentions(post.Message, keywords)
-
- // get users that have comment thread mentions enabled
- if len(post.RootId) > 0 {
- if result := <-Srv.Store.Post().Get(post.RootId); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.comment_thread.error"), post.RootId, result.Err)
- return nil
- } else {
- list := result.Data.(*model.PostList)
-
- for _, threadPost := range list.Posts {
- if profile, ok := profileMap[threadPost.UserId]; ok {
- if profile.NotifyProps["comments"] == "any" || (profile.NotifyProps["comments"] == "root" && threadPost.Id == list.Order[0]) {
- mentionedUserIds[threadPost.UserId] = true
- }
- }
- }
- }
- }
-
- // prevent the user from mentioning themselves
- if post.Props["from_webhook"] != "true" {
- delete(mentionedUserIds, post.UserId)
- }
-
- if len(potentialOtherMentions) > 0 {
- if result := <-Srv.Store.User().GetProfilesByUsernames(potentialOtherMentions, team.Id); result.Err == nil {
- outOfChannelMentions := result.Data.(map[string]*model.User)
- go sendOutOfChannelMentions(c, post, outOfChannelMentions)
- }
- }
-
- // find which users in the channel are set up to always receive mobile notifications
- for _, profile := range profileMap {
- if profile.NotifyProps["push"] == model.USER_NOTIFY_ALL &&
- (post.UserId != profile.Id || post.Props["from_webhook"] == "true") {
- allActivityPushUserIds = append(allActivityPushUserIds, profile.Id)
- }
- }
- }
-
- mentionedUsersList = make([]string, 0, len(mentionedUserIds))
- for id := range mentionedUserIds {
- mentionedUsersList = append(mentionedUsersList, id)
- updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, id))
- }
-
- var sender *model.User
- senderName := make(map[string]string)
- for _, id := range mentionedUsersList {
- senderName[id] = ""
- if profile, ok := profileMap[post.UserId]; ok {
- if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" {
- senderName[id] = value.(string)
- } else {
- //Get the Display name preference from the receiver
- if result := <-Srv.Store.Preference().Get(id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "name_format"); result.Err != nil {
- // Show default sender's name if user doesn't set display settings.
- senderName[id] = profile.Username
- } else {
- senderName[id] = profile.GetDisplayNameForPreference(result.Data.(model.Preference).Value)
- }
- }
- sender = profile
- }
- }
-
- if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" {
- senderUsername = value.(string)
- } else {
- senderUsername = profileMap[post.UserId].Username
- }
-
- if utils.Cfg.EmailSettings.SendEmailNotifications {
- for _, id := range mentionedUsersList {
- userAllowsEmails := profileMap[id].NotifyProps["email"] != "false"
-
- var status *model.Status
- var err *model.AppError
- if status, err = GetStatus(id); err != nil {
- status = &model.Status{
- UserId: id,
- Status: model.STATUS_OFFLINE,
- Manual: false,
- LastActivityAt: 0,
- ActiveChannel: "",
- }
- }
-
- if userAllowsEmails && status.Status != model.STATUS_ONLINE {
- sendNotificationEmail(c, post, profileMap[id], channel, team, senderName[id], sender)
- }
- }
- }
-
- // If the channel has more than 1K users then @here is disabled
- if hereNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
- hereNotification = false
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: c.T("api.post.disabled_here", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
- CreateAt: post.CreateAt + 1,
- },
- )
- }
-
- // If the channel has more than 1K users then @channel is disabled
- if channelNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: c.T("api.post.disabled_channel", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
- CreateAt: post.CreateAt + 1,
- },
- )
- }
-
- // If the channel has more than 1K users then @all is disabled
- if allNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: c.T("api.post.disabled_all", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
- CreateAt: post.CreateAt + 1,
- },
- )
- }
-
- if hereNotification {
- statuses := GetAllStatuses()
- for _, status := range statuses {
- if status.UserId == post.UserId {
- continue
- }
-
- _, profileFound := profileMap[status.UserId]
- _, alreadyMentioned := mentionedUserIds[status.UserId]
-
- if status.Status == model.STATUS_ONLINE && profileFound && !alreadyMentioned {
- mentionedUsersList = append(mentionedUsersList, status.UserId)
- updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, status.UserId))
- }
- }
- }
-
- // Make sure all mention updates are complete to prevent race
- // Probably better to batch these DB updates in the future
- // MUST be completed before push notifications send
- for _, uchan := range updateMentionChans {
- if result := <-uchan; result.Err != nil {
- l4g.Warn(utils.T("api.post.update_mention_count_and_forget.update_error"), post.Id, post.ChannelId, result.Err)
- }
- }
-
- sendPushNotifications := false
- if *utils.Cfg.EmailSettings.SendPushNotifications {
- pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
- if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) {
- l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn"))
- sendPushNotifications = false
- } else {
- sendPushNotifications = true
- }
- }
-
- if sendPushNotifications {
- for _, id := range mentionedUsersList {
- var status *model.Status
- var err *model.AppError
- if status, err = GetStatus(id); err != nil {
- status = &model.Status{id, model.STATUS_OFFLINE, false, 0, ""}
- }
-
- if DoesStatusAllowPushNotification(profileMap[id], status, post.ChannelId) {
- sendPushNotification(post, profileMap[id], channel, senderName[id], true)
- }
- }
-
- for _, id := range allActivityPushUserIds {
- if _, ok := mentionedUserIds[id]; !ok {
- var status *model.Status
- var err *model.AppError
- if status, err = GetStatus(id); err != nil {
- status = &model.Status{id, model.STATUS_OFFLINE, false, 0, ""}
- }
-
- if DoesStatusAllowPushNotification(profileMap[id], status, post.ChannelId) {
- sendPushNotification(post, profileMap[id], channel, senderName[id], false)
- }
- }
- }
- }
- }
-
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POSTED, "", post.ChannelId, "", nil)
- message.Add("post", post.ToJson())
- message.Add("channel_type", channel.Type)
- message.Add("channel_display_name", channel.DisplayName)
- message.Add("channel_name", channel.Name)
- message.Add("sender_name", senderUsername)
- message.Add("team_id", team.Id)
-
- if len(post.FileIds) != 0 && fchan != nil {
- message.Add("otherFile", "true")
-
- var infos []*model.FileInfo
- if result := <-fchan; result.Err != nil {
- l4g.Warn(utils.T("api.post.send_notifications.files.error"), post.Id, result.Err)
- } else {
- infos = result.Data.([]*model.FileInfo)
- }
-
- for _, info := range infos {
- if info.IsImage() {
- message.Add("image", "true")
- break
- }
- }
- }
-
- if len(mentionedUsersList) != 0 {
- message.Add("mentions", model.ArrayToJson(mentionedUsersList))
- }
-
- Publish(message)
- return mentionedUsersList
-}
-
-func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string, sender *model.User) {
- // skip if inactive
- if user.DeleteAt > 0 {
- return
- }
-
- if channel.Type == model.CHANNEL_DIRECT && channel.TeamId != team.Id {
- // this message is a cross-team DM so it we need to find a team that the recipient is on to use in the link
- if result := <-Srv.Store.Team().GetTeamsByUserId(user.Id); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.get_teams.error"), user.Id, result.Err)
- return
- } else {
- // if the recipient isn't in the current user's team, just pick one
- teams := result.Data.([]*model.Team)
- found := false
-
- for i := range teams {
- if teams[i].Id == team.Id {
- found = true
- team = teams[i]
- break
- }
- }
-
- if !found {
- if len(teams) > 0 {
- team = teams[0]
- } else {
- // in case the user hasn't joined any teams we send them to the select_team page
- team = &model.Team{Name: "select_team", DisplayName: utils.Cfg.TeamSettings.SiteName}
- }
- }
- }
- }
-
- if *utils.Cfg.EmailSettings.EnableEmailBatching {
- var sendBatched bool
-
- if result := <-Srv.Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_NOTIFICATIONS, model.PREFERENCE_NAME_EMAIL_INTERVAL); result.Err != nil {
- // if the call fails, assume it hasn't been set and use the default
- sendBatched = false
- } else {
- // default to not using batching if the setting is set to immediate
- sendBatched = result.Data.(model.Preference).Value != model.PREFERENCE_DEFAULT_EMAIL_INTERVAL
- }
-
- if sendBatched {
- if err := AddNotificationEmailToBatch(user, post, team); err == nil {
- return
- }
- }
-
- // fall back to sending a single email if we can't batch it for some reason
- }
-
- var channelName string
- var bodyText string
- var subjectText string
- var mailTemplate string
- var mailParameters map[string]interface{}
-
- teamURL := c.GetSiteURL() + "/" + team.Name
- tm := time.Unix(post.CreateAt/1000, 0)
-
- userLocale := utils.GetUserTranslations(user.Locale)
- month := userLocale(tm.Month().String())
- day := fmt.Sprintf("%d", tm.Day())
- year := fmt.Sprintf("%d", tm.Year())
- zone, _ := tm.Zone()
-
- if channel.Type == model.CHANNEL_DIRECT {
- bodyText = userLocale("api.post.send_notifications_and_forget.message_body")
- subjectText = userLocale("api.post.send_notifications_and_forget.message_subject")
-
- senderDisplayName := senderName
-
- mailTemplate = "api.templates.post_subject_in_direct_message"
- mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
- "SenderDisplayName": senderDisplayName, "Month": month, "Day": day, "Year": year}
- } else {
- bodyText = userLocale("api.post.send_notifications_and_forget.mention_body")
- subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject")
- channelName = channel.DisplayName
- mailTemplate = "api.templates.post_subject_in_channel"
- mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
- "ChannelName": channelName, "Month": month, "Day": day, "Year": year}
- }
-
- subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, userLocale(mailTemplate, mailParameters))
-
- bodyPage := utils.NewHTMLTemplate("post_body", user.Locale)
- bodyPage.Props["SiteURL"] = c.GetSiteURL()
- bodyPage.Props["PostMessage"] = getMessageForNotification(post, userLocale)
- if team.Name != "select_team" {
- bodyPage.Props["TeamLink"] = teamURL + "/pl/" + post.Id
- } else {
- bodyPage.Props["TeamLink"] = teamURL
- }
-
- bodyPage.Props["BodyText"] = bodyText
- bodyPage.Props["Button"] = userLocale("api.templates.post_body.button")
- bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info",
- map[string]interface{}{"ChannelName": channelName, "SenderName": senderName,
- "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()),
- "TimeZone": zone, "Month": month, "Day": day}))
-
- if err := utils.SendMail(user.Email, html.UnescapeString(subject), bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err)
- }
-
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostSentEmail()
- }
-}
-
-func getMessageForNotification(post *model.Post, translateFunc i18n.TranslateFunc) string {
- if len(strings.TrimSpace(post.Message)) != 0 || len(post.FileIds) == 0 {
- return post.Message
- }
-
- // extract the filenames from their paths and determine what type of files are attached
- var infos []*model.FileInfo
- if result := <-Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil {
- l4g.Warn(utils.T("api.post.get_message_for_notification.get_files.error"), post.Id, result.Err)
- } else {
- infos = result.Data.([]*model.FileInfo)
- }
-
- filenames := make([]string, len(infos))
- onlyImages := true
- for i, info := range infos {
- if escaped, err := url.QueryUnescape(filepath.Base(info.Name)); err != nil {
- // this should never error since filepath was escaped using url.QueryEscape
- filenames[i] = escaped
- } else {
- filenames[i] = info.Name
- }
-
- onlyImages = onlyImages && info.IsImage()
- }
-
- props := map[string]interface{}{"Filenames": strings.Join(filenames, ", ")}
-
- if onlyImages {
- return translateFunc("api.post.get_message_for_notification.images_sent", len(filenames), props)
- } else {
- return translateFunc("api.post.get_message_for_notification.files_sent", len(filenames), props)
- }
-}
-
-func sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, senderName string, wasMentioned bool) {
- sessions := getMobileAppSessions(user.Id)
-
- if sessions == nil {
- return
- }
-
- var channelName string
-
- if channel.Type == model.CHANNEL_DIRECT {
- channelName = senderName
- } else {
- channelName = channel.DisplayName
- }
-
- userLocale := utils.GetUserTranslations(user.Locale)
-
- msg := model.PushNotification{}
- if badge := <-Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil {
- msg.Badge = 1
- l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), user.Id, badge.Err)
- } else {
- msg.Badge = int(badge.Data.(int64))
- }
- msg.Type = model.PUSH_TYPE_MESSAGE
- msg.TeamId = channel.TeamId
- msg.ChannelId = channel.Id
- msg.ChannelName = channel.Name
-
- if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
- } else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message)
- }
- } else {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
- } else if wasMentioned {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
- } else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName
- }
- }
-
- l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
-
- for _, session := range sessions {
- tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson()))
- tmpMessage.SetDeviceIdAndPlatform(session.DeviceId)
- sendToPushProxy(tmpMessage)
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostSentPush()
- }
- }
-}
-
-func clearPushNotification(userId string, channelId string) {
- sessions := getMobileAppSessions(userId)
- if sessions == nil {
- return
- }
-
- msg := model.PushNotification{}
- msg.Type = model.PUSH_TYPE_CLEAR
- msg.ChannelId = channelId
- msg.ContentAvailable = 0
- if badge := <-Srv.Store.User().GetUnreadCount(userId); badge.Err != nil {
- msg.Badge = 0
- l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), userId, badge.Err)
- } else {
- msg.Badge = int(badge.Data.(int64))
- }
-
- l4g.Debug(utils.T("api.post.send_notifications_and_forget.clear_push_notification.debug"), msg.DeviceId, msg.ChannelId)
- for _, session := range sessions {
- tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson()))
- tmpMessage.SetDeviceIdAndPlatform(session.DeviceId)
- sendToPushProxy(tmpMessage)
- }
-}
-
-func sendToPushProxy(msg model.PushNotification) {
- msg.ServerId = utils.CfgDiagnosticId
-
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- httpClient := &http.Client{Transport: tr}
- request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
-
- if resp, err := httpClient.Do(request); err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), msg.DeviceId, err)
- } else {
- ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- }
-}
-
-func getMobileAppSessions(userId string) []*model.Session {
- if result := <-Srv.Store.Session().GetSessionsWithActiveDeviceIds(userId); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), userId, result.Err)
- return nil
- } else {
- return result.Data.([]*model.Session)
- }
-}
-
-func sendOutOfChannelMentions(c *Context, post *model.Post, profiles map[string]*model.User) {
- if len(profiles) == 0 {
- return
- }
-
- var usernames []string
- for _, user := range profiles {
- usernames = append(usernames, user.Username)
- }
- sort.Strings(usernames)
-
- var message string
- if len(usernames) == 1 {
- message = c.T("api.post.check_for_out_of_channel_mentions.message.one", map[string]interface{}{
- "Username": usernames[0],
- })
- } else {
- message = c.T("api.post.check_for_out_of_channel_mentions.message.multiple", map[string]interface{}{
- "Usernames": strings.Join(usernames[:len(usernames)-1], ", "),
- "LastUsername": usernames[len(usernames)-1],
- })
- }
-
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: message,
- CreateAt: post.CreateAt + 1,
- },
- )
-}
-
-func SendEphemeralPost(teamId, userId string, post *model.Post) {
- post.Type = model.POST_EPHEMERAL
-
- // fill in fields which haven't been specified which have sensible defaults
- if post.Id == "" {
- post.Id = model.NewId()
- }
- if post.CreateAt == 0 {
- post.CreateAt = model.GetMillis()
- }
- if post.Props == nil {
- post.Props = model.StringInterface{}
- }
-
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE, "", post.ChannelId, userId, nil)
- message.Add("post", post.ToJson())
-
- go Publish(message)
-}
-
func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
post := model.PostFromJson(r.Body)
@@ -1212,7 +98,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(post.Id)
+ pchan := app.Srv.Store.Post().Get(post.Id)
if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_EDIT_POST) {
return
@@ -1258,7 +144,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
newPost.EditAt = model.GetMillis()
newPost.Hashtags, _ = model.ParseHashtags(post.Message)
- if result := <-Srv.Store.Post().Update(newPost, oldPost); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Update(newPost, oldPost); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1267,9 +153,9 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_EDITED, "", rpost.ChannelId, "", nil)
message.Add("post", rpost.ToJson())
- go Publish(message)
+ go app.Publish(message)
- InvalidateCacheForChannelPosts(rpost.ChannelId)
+ app.InvalidateCacheForChannelPosts(rpost.ChannelId)
w.Write([]byte(rpost.ToJson()))
}
@@ -1292,7 +178,7 @@ func getFlaggedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
posts := &model.PostList{}
- if result := <-Srv.Store.Post().GetFlaggedPosts(c.Session.UserId, offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.Post().GetFlaggedPosts(c.Session.UserId, offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1323,7 +209,7 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- etagChan := Srv.Store.Post().GetEtag(id, true)
+ etagChan := app.Srv.Store.Post().GetEtag(id, true)
if !HasPermissionToChannelContext(c, id, model.PERMISSION_CREATE_POST) {
return
@@ -1335,7 +221,7 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().GetPosts(id, offset, limit, true)
+ pchan := app.Srv.Store.Post().GetPosts(id, offset, limit, true)
if result := <-pchan; result.Err != nil {
c.Err = result.Err
@@ -1364,7 +250,7 @@ func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().GetPostsSince(id, time, true)
+ pchan := app.Srv.Store.Post().GetPostsSince(id, time, true)
if !HasPermissionToChannelContext(c, id, model.PERMISSION_READ_CHANNEL) {
return
@@ -1396,7 +282,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
@@ -1430,7 +316,7 @@ func getPostById(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Post().Get(postId); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Get(postId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1464,7 +350,7 @@ func getPermalinkTmp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Post().Get(postId); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Get(postId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1515,7 +401,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
if result := <-pchan; result.Err != nil {
c.Err = result.Err
@@ -1541,7 +427,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if dresult := <-Srv.Store.Post().Delete(postId, model.GetMillis()); dresult.Err != nil {
+ if dresult := <-app.Srv.Store.Post().Delete(postId, model.GetMillis()); dresult.Err != nil {
c.Err = dresult.Err
return
}
@@ -1549,11 +435,11 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_DELETED, "", post.ChannelId, "", nil)
message.Add("post", post.ToJson())
- go Publish(message)
+ go app.Publish(message)
go DeletePostFiles(post)
go DeleteFlaggedPost(c.Session.UserId, post)
- InvalidateCacheForChannelPosts(post.ChannelId)
+ app.InvalidateCacheForChannelPosts(post.ChannelId)
result := make(map[string]string)
result["id"] = postId
@@ -1562,7 +448,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
}
func DeleteFlaggedPost(userId string, post *model.Post) {
- if result := <-Srv.Store.Preference().Delete(userId, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Delete(userId, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id); result.Err != nil {
l4g.Warn(utils.T("api.post.delete_flagged_post.app_error.warn"), result.Err)
return
}
@@ -1573,7 +459,7 @@ func DeletePostFiles(post *model.Post) {
return
}
- if result := <-Srv.Store.FileInfo().DeleteForPost(post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().DeleteForPost(post.Id); result.Err != nil {
l4g.Warn(utils.T("api.post.delete_post_files.app_error.warn"), post.Id, result.Err)
}
}
@@ -1614,7 +500,7 @@ func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, b
}
// We can do better than this etag in this situation
- etagChan := Srv.Store.Post().GetEtag(id, true)
+ etagChan := app.Srv.Store.Post().GetEtag(id, true)
if !HasPermissionToChannelContext(c, id, model.PERMISSION_READ_CHANNEL) {
return
@@ -1627,9 +513,9 @@ func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, b
var pchan store.StoreChannel
if before {
- pchan = Srv.Store.Post().GetPostsBefore(id, postId, numPosts, offset)
+ pchan = app.Srv.Store.Post().GetPostsBefore(id, postId, numPosts, offset)
} else {
- pchan = Srv.Store.Post().GetPostsAfter(id, postId, numPosts, offset)
+ pchan = app.Srv.Store.Post().GetPostsAfter(id, postId, numPosts, offset)
}
if result := <-pchan; result.Err != nil {
@@ -1664,7 +550,7 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) {
params.OrTerms = isOrSearch
// don't allow users to search for everything
if params.Terms != "*" {
- channels = append(channels, Srv.Store.Post().Search(c.TeamId, c.Session.UserId, params))
+ channels = append(channels, app.Srv.Store.Post().Search(c.TeamId, c.Session.UserId, params))
}
}
@@ -1698,8 +584,8 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
- fchan := Srv.Store.FileInfo().GetForPost(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
+ fchan := app.Srv.Store.FileInfo().GetForPost(postId)
if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
diff --git a/api/post_test.go b/api/post_test.go
index 6101d2c8d..95f753da7 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -14,6 +14,7 @@ import (
"testing"
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -134,7 +135,7 @@ func TestCreatePost(t *testing.T) {
} else if rpost9 := resp.Data.(*model.Post); len(rpost9.FileIds) != 3 {
t.Fatal("post should have 3 files")
} else {
- infos := store.Must(Srv.Store.FileInfo().GetForPost(rpost9.Id)).([]*model.FileInfo)
+ infos := store.Must(app.Srv.Store.FileInfo().GetForPost(rpost9.Id)).([]*model.FileInfo)
if len(infos) != 3 {
t.Fatal("should've attached all 3 files to post")
@@ -904,7 +905,9 @@ func TestMakeDirectChannelVisible(t *testing.T) {
channel := Client.Must(Client.CreateDirectChannel(user2.Id)).Data.(*model.Channel)
- makeDirectChannelVisible(channel.Id)
+ if err := app.MakeDirectChannelVisible(channel.Id); err != nil {
+ t.Fatal(err)
+ }
if result, err := Client.GetPreference(model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, user2.Id); err != nil {
t.Fatal("Errored trying to set direct channel to be visible for user1")
@@ -913,281 +916,6 @@ func TestMakeDirectChannelVisible(t *testing.T) {
}
}
-func TestGetMentionKeywords(t *testing.T) {
- // user with username or custom mentions enabled
- user1 := &model.User{
- Id: model.NewId(),
- FirstName: "First",
- Username: "User",
- NotifyProps: map[string]string{
- "mention_keys": "User,@User,MENTION",
- },
- }
-
- profiles := map[string]*model.User{user1.Id: user1}
- mentions := getMentionKeywordsInChannel(profiles)
- if len(mentions) != 3 {
- t.Fatal("should've returned three mention keywords")
- } else if ids, ok := mentions["user"]; !ok || ids[0] != user1.Id {
- t.Fatal("should've returned mention key of user")
- } else if ids, ok := mentions["@user"]; !ok || ids[0] != user1.Id {
- t.Fatal("should've returned mention key of @user")
- } else if ids, ok := mentions["mention"]; !ok || ids[0] != user1.Id {
- t.Fatal("should've returned mention key of mention")
- }
-
- // user with first name mention enabled
- user2 := &model.User{
- Id: model.NewId(),
- FirstName: "First",
- Username: "User",
- NotifyProps: map[string]string{
- "first_name": "true",
- },
- }
-
- profiles = map[string]*model.User{user2.Id: user2}
- mentions = getMentionKeywordsInChannel(profiles)
- if len(mentions) != 2 {
- t.Fatal("should've returned two mention keyword")
- } else if ids, ok := mentions["First"]; !ok || ids[0] != user2.Id {
- t.Fatal("should've returned mention key of First")
- }
-
- // user with @channel/@all mentions enabled
- user3 := &model.User{
- Id: model.NewId(),
- FirstName: "First",
- Username: "User",
- NotifyProps: map[string]string{
- "channel": "true",
- },
- }
-
- profiles = map[string]*model.User{user3.Id: user3}
- mentions = getMentionKeywordsInChannel(profiles)
- if len(mentions) != 3 {
- t.Fatal("should've returned three mention keywords")
- } else if ids, ok := mentions["@channel"]; !ok || ids[0] != user3.Id {
- t.Fatal("should've returned mention key of @channel")
- } else if ids, ok := mentions["@all"]; !ok || ids[0] != user3.Id {
- t.Fatal("should've returned mention key of @all")
- }
-
- // user with all types of mentions enabled
- user4 := &model.User{
- Id: model.NewId(),
- FirstName: "First",
- Username: "User",
- NotifyProps: map[string]string{
- "mention_keys": "User,@User,MENTION",
- "first_name": "true",
- "channel": "true",
- },
- }
-
- profiles = map[string]*model.User{user4.Id: user4}
- mentions = getMentionKeywordsInChannel(profiles)
- if len(mentions) != 6 {
- t.Fatal("should've returned six mention keywords")
- } else if ids, ok := mentions["user"]; !ok || ids[0] != user4.Id {
- t.Fatal("should've returned mention key of user")
- } else if ids, ok := mentions["@user"]; !ok || ids[0] != user4.Id {
- t.Fatal("should've returned mention key of @user")
- } else if ids, ok := mentions["mention"]; !ok || ids[0] != user4.Id {
- t.Fatal("should've returned mention key of mention")
- } else if ids, ok := mentions["First"]; !ok || ids[0] != user4.Id {
- t.Fatal("should've returned mention key of First")
- } else if ids, ok := mentions["@channel"]; !ok || ids[0] != user4.Id {
- t.Fatal("should've returned mention key of @channel")
- } else if ids, ok := mentions["@all"]; !ok || ids[0] != user4.Id {
- t.Fatal("should've returned mention key of @all")
- }
-
- dup_count := func(list []string) map[string]int {
-
- duplicate_frequency := make(map[string]int)
-
- for _, item := range list {
- // check if the item/element exist in the duplicate_frequency map
-
- _, exist := duplicate_frequency[item]
-
- if exist {
- duplicate_frequency[item] += 1 // increase counter by 1 if already in the map
- } else {
- duplicate_frequency[item] = 1 // else start counting from 1
- }
- }
- return duplicate_frequency
- }
-
- // multiple users
- profiles = map[string]*model.User{
- user1.Id: user1,
- user2.Id: user2,
- user3.Id: user3,
- user4.Id: user4,
- }
- mentions = getMentionKeywordsInChannel(profiles)
- if len(mentions) != 6 {
- t.Fatal("should've returned six mention keywords")
- } else if ids, ok := mentions["user"]; !ok || len(ids) != 2 || (ids[0] != user1.Id && ids[1] != user1.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
- t.Fatal("should've mentioned user1 and user4 with user")
- } else if ids := dup_count(mentions["@user"]); len(ids) != 4 || (ids[user1.Id] != 2) || (ids[user4.Id] != 2) {
- t.Fatal("should've mentioned user1 and user4 with @user")
- } else if ids, ok := mentions["mention"]; !ok || len(ids) != 2 || (ids[0] != user1.Id && ids[1] != user1.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
- t.Fatal("should've mentioned user1 and user4 with mention")
- } else if ids, ok := mentions["First"]; !ok || len(ids) != 2 || (ids[0] != user2.Id && ids[1] != user2.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
- t.Fatal("should've mentioned user2 and user4 with mention")
- } else if ids, ok := mentions["@channel"]; !ok || len(ids) != 2 || (ids[0] != user3.Id && ids[1] != user3.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
- t.Fatal("should've mentioned user3 and user4 with @channel")
- } else if ids, ok := mentions["@all"]; !ok || len(ids) != 2 || (ids[0] != user3.Id && ids[1] != user3.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
- t.Fatal("should've mentioned user3 and user4 with @all")
- }
-}
-
-func TestGetExplicitMentionsAtHere(t *testing.T) {
- // test all the boundary cases that we know can break up terms (and those that we know won't)
- cases := map[string]bool{
- "": false,
- "here": false,
- "@here": true,
- " @here ": true,
- "\t@here\t": true,
- "\n@here\n": true,
- // "!@here!": true,
- // "@@here@": true,
- // "#@here#": true,
- // "$@here$": true,
- // "%@here%": true,
- // "^@here^": true,
- // "&@here&": true,
- // "*@here*": true,
- "(@here(": true,
- ")@here)": true,
- // "-@here-": true,
- // "_@here_": true,
- // "=@here=": true,
- "+@here+": true,
- "[@here[": true,
- "{@here{": true,
- "]@here]": true,
- "}@here}": true,
- "\\@here\\": true,
- // "|@here|": true,
- ";@here;": true,
- ":@here:": true,
- // "'@here'": true,
- // "\"@here\"": true,
- ",@here,": true,
- "<@here<": true,
- ".@here.": true,
- ">@here>": true,
- "/@here/": true,
- "?@here?": true,
- // "`@here`": true,
- // "~@here~": true,
- }
-
- for message, shouldMention := range cases {
- if _, _, hereMentioned, _, _ := getExplicitMentions(message, nil); hereMentioned && !shouldMention {
- t.Fatalf("shouldn't have mentioned @here with \"%v\"", message)
- } else if !hereMentioned && shouldMention {
- t.Fatalf("should've have mentioned @here with \"%v\"", message)
- }
- }
-
- // mentioning @here and someone
- id := model.NewId()
- if mentions, potential, hereMentioned, _, _ := getExplicitMentions("@here @user @potential", map[string][]string{"@user": {id}}); !hereMentioned {
- t.Fatal("should've mentioned @here with \"@here @user\"")
- } else if len(mentions) != 1 || !mentions[id] {
- t.Fatal("should've mentioned @user with \"@here @user\"")
- } else if len(potential) > 1 {
- t.Fatal("should've potential mentions for @potential")
- }
-}
-
-func TestGetExplicitMentions(t *testing.T) {
- id1 := model.NewId()
- id2 := model.NewId()
-
- // not mentioning anybody
- message := "this is a message"
- keywords := map[string][]string{}
- if mentions, potential, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 0 || len(potential) != 0 {
- t.Fatal("shouldn't have mentioned anybody or have any potencial mentions")
- }
-
- // mentioning a user that doesn't exist
- message = "this is a message for @user"
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 0 {
- t.Fatal("shouldn't have mentioned user that doesn't exist")
- }
-
- // mentioning one person
- keywords = map[string][]string{"@user": {id1}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] {
- t.Fatal("should've mentioned @user")
- }
-
- // mentioning one person without an @mention
- message = "this is a message for @user"
- keywords = map[string][]string{"this": {id1}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] {
- t.Fatal("should've mentioned this")
- }
-
- // mentioning multiple people with one word
- message = "this is a message for @user"
- keywords = map[string][]string{"@user": {id1, id2}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
- t.Fatal("should've mentioned two users with @user")
- }
-
- // mentioning only one of multiple people
- keywords = map[string][]string{"@user": {id1}, "@mention": {id2}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] || mentions[id2] {
- t.Fatal("should've mentioned @user and not @mention")
- }
-
- // mentioning multiple people with multiple words
- message = "this is an @mention for @user"
- keywords = map[string][]string{"@user": {id1}, "@mention": {id2}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
- t.Fatal("should've mentioned two users with @user and @mention")
- }
-
- // mentioning @channel (not a special case, but it's good to double check)
- message = "this is an message for @channel"
- keywords = map[string][]string{"@channel": {id1, id2}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
- t.Fatal("should've mentioned two users with @channel")
- }
-
- // mentioning @all (not a special case, but it's good to double check)
- message = "this is an message for @all"
- keywords = map[string][]string{"@all": {id1, id2}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
- t.Fatal("should've mentioned two users with @all")
- }
-
- // mentioning user.period without mentioning user (PLT-3222)
- message = "user.period doesn't complicate things at all by including periods in their username"
- keywords = map[string][]string{"user.period": {id1}, "user": {id2}}
- if mentions, _, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] || mentions[id2] {
- t.Fatal("should've mentioned user.period and not user")
- }
-
- // mentioning a potential out of channel user
- message = "this is an message for @potential and @user"
- keywords = map[string][]string{"@user": {id1}}
- if mentions, potential, _, _, _ := getExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] || len(potential) != 1 {
- t.Fatal("should've mentioned user and have a potential not in channel")
- }
-}
-
func TestGetFlaggedPosts(t *testing.T) {
th := Setup().InitBasic()
Client := th.BasicClient
@@ -1226,28 +954,28 @@ func TestGetFlaggedPosts(t *testing.T) {
func TestGetMessageForNotification(t *testing.T) {
Setup().InitBasic()
- testPng := store.Must(Srv.Store.FileInfo().Save(&model.FileInfo{
+ testPng := store.Must(app.Srv.Store.FileInfo().Save(&model.FileInfo{
CreatorId: model.NewId(),
Path: "test1.png",
Name: "test1.png",
MimeType: "image/png",
})).(*model.FileInfo)
- testJpg1 := store.Must(Srv.Store.FileInfo().Save(&model.FileInfo{
+ testJpg1 := store.Must(app.Srv.Store.FileInfo().Save(&model.FileInfo{
CreatorId: model.NewId(),
Path: "test2.jpg",
Name: "test2.jpg",
MimeType: "image/jpeg",
})).(*model.FileInfo)
- testFile := store.Must(Srv.Store.FileInfo().Save(&model.FileInfo{
+ testFile := store.Must(app.Srv.Store.FileInfo().Save(&model.FileInfo{
CreatorId: model.NewId(),
Path: "test1.go",
Name: "test1.go",
MimeType: "text/plain",
})).(*model.FileInfo)
- testJpg2 := store.Must(Srv.Store.FileInfo().Save(&model.FileInfo{
+ testJpg2 := store.Must(app.Srv.Store.FileInfo().Save(&model.FileInfo{
CreatorId: model.NewId(),
Path: "test3.jpg",
Name: "test3.jpg",
@@ -1261,37 +989,37 @@ func TestGetMessageForNotification(t *testing.T) {
Message: "test",
}
- if getMessageForNotification(post, translateFunc) != "test" {
+ if app.GetMessageForNotification(post, translateFunc) != "test" {
t.Fatal("should've returned message text")
}
post.FileIds = model.StringArray{testPng.Id}
- store.Must(Srv.Store.FileInfo().AttachToPost(testPng.Id, post.Id))
- if getMessageForNotification(post, translateFunc) != "test" {
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(testPng.Id, post.Id))
+ if app.GetMessageForNotification(post, translateFunc) != "test" {
t.Fatal("should've returned message text, even with attachments")
}
post.Message = ""
- if message := getMessageForNotification(post, translateFunc); message != "1 image sent: test1.png" {
+ if message := app.GetMessageForNotification(post, translateFunc); message != "1 image sent: test1.png" {
t.Fatal("should've returned number of images:", message)
}
post.FileIds = model.StringArray{testPng.Id, testJpg1.Id}
- store.Must(Srv.Store.FileInfo().AttachToPost(testJpg1.Id, post.Id))
- if message := getMessageForNotification(post, translateFunc); message != "2 images sent: test1.png, test2.jpg" && message != "2 images sent: test2.jpg, test1.png" {
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(testJpg1.Id, post.Id))
+ if message := app.GetMessageForNotification(post, translateFunc); message != "2 images sent: test1.png, test2.jpg" && message != "2 images sent: test2.jpg, test1.png" {
t.Fatal("should've returned number of images:", message)
}
post.Id = model.NewId()
post.FileIds = model.StringArray{testFile.Id}
- store.Must(Srv.Store.FileInfo().AttachToPost(testFile.Id, post.Id))
- if message := getMessageForNotification(post, translateFunc); message != "1 file sent: test1.go" {
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(testFile.Id, post.Id))
+ if message := app.GetMessageForNotification(post, translateFunc); message != "1 file sent: test1.go" {
t.Fatal("should've returned number of files:", message)
}
- store.Must(Srv.Store.FileInfo().AttachToPost(testJpg2.Id, post.Id))
+ store.Must(app.Srv.Store.FileInfo().AttachToPost(testJpg2.Id, post.Id))
post.FileIds = model.StringArray{testFile.Id, testJpg2.Id}
- if message := getMessageForNotification(post, translateFunc); message != "2 files sent: test1.go, test3.jpg" && message != "2 files sent: test3.jpg, test1.go" {
+ if message := app.GetMessageForNotification(post, translateFunc); message != "2 files sent: test1.go, test3.jpg" && message != "2 files sent: test3.jpg, test1.go" {
t.Fatal("should've returned number of mixed files:", message)
}
}
@@ -1334,43 +1062,6 @@ func TestGetFileInfosForPost(t *testing.T) {
}
}
-func TestSendNotifications(t *testing.T) {
- th := Setup().InitBasic()
- Client := th.BasicClient
-
- AddUserToChannel(th.BasicUser2, th.BasicChannel)
-
- mockSession := model.Session{
- UserId: th.BasicUser.Id,
- TeamMembers: []*model.TeamMember{{TeamId: th.BasicTeam.Id, UserId: th.BasicUser.Id}},
- IsOAuth: false,
- }
-
- newContext := &Context{
- Session: mockSession,
- RequestId: model.NewId(),
- IpAddress: "",
- Path: "fake",
- Err: nil,
- siteURL: *utils.Cfg.ServiceSettings.SiteURL,
- TeamId: th.BasicTeam.Id,
- }
-
- post1 := Client.Must(Client.CreatePost(&model.Post{
- ChannelId: th.BasicChannel.Id,
- Message: "@" + th.BasicUser2.Username,
- })).Data.(*model.Post)
-
- mentions := sendNotifications(newContext, post1, th.BasicTeam, th.BasicChannel)
- if mentions == nil {
- t.Log(mentions)
- t.Fatal("user should have been mentioned")
- } else if mentions[0] != th.BasicUser2.Id {
- t.Log(mentions)
- t.Fatal("user should have been mentioned")
- }
-}
-
func TestGetPostById(t *testing.T) {
th := Setup().InitBasic()
Client := th.BasicClient
diff --git a/api/preference.go b/api/preference.go
index 240ead571..5384afbb5 100644
--- a/api/preference.go
+++ b/api/preference.go
@@ -6,6 +6,7 @@ package api
import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"net/http"
@@ -22,7 +23,7 @@ func InitPreference() {
}
func getAllPreferences(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-Srv.Store.Preference().GetAll(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().GetAll(c.Session.UserId); result.Err != nil {
c.Err = result.Err
} else {
data := result.Data.(model.Preferences)
@@ -49,7 +50,7 @@ func savePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Save(&preferences); result.Err != nil {
c.Err = result.Err
return
}
@@ -61,7 +62,7 @@ func getPreferenceCategory(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
category := params["category"]
- if result := <-Srv.Store.Preference().GetCategory(c.Session.UserId, category); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().GetCategory(c.Session.UserId, category); result.Err != nil {
c.Err = result.Err
} else {
data := result.Data.(model.Preferences)
@@ -75,7 +76,7 @@ func getPreference(c *Context, w http.ResponseWriter, r *http.Request) {
category := params["category"]
name := params["name"]
- if result := <-Srv.Store.Preference().Get(c.Session.UserId, category, name); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Get(c.Session.UserId, category, name); result.Err != nil {
c.Err = result.Err
} else {
data := result.Data.(model.Preference)
@@ -101,7 +102,7 @@ func deletePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
}
for _, preference := range preferences {
- if result := <-Srv.Store.Preference().Delete(c.Session.UserId, preference.Category, preference.Name); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Delete(c.Session.UserId, preference.Category, preference.Name); result.Err != nil {
c.Err = result.Err
return
}
diff --git a/api/reaction.go b/api/reaction.go
index 5acf09f9e..ac5df4516 100644
--- a/api/reaction.go
+++ b/api/reaction.go
@@ -6,6 +6,7 @@ package api
import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"net/http"
@@ -50,7 +51,7 @@ func saveReaction(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(reaction.PostId)
+ pchan := app.Srv.Store.Post().Get(reaction.PostId)
var postHadReactions bool
if result := <-pchan; result.Err != nil {
@@ -65,7 +66,7 @@ func saveReaction(c *Context, w http.ResponseWriter, r *http.Request) {
postHadReactions = post.HasReactions
}
- if result := <-Srv.Store.Reaction().Save(reaction); result.Err != nil {
+ if result := <-app.Srv.Store.Reaction().Save(reaction); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -108,7 +109,7 @@ func deleteReaction(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(reaction.PostId)
+ pchan := app.Srv.Store.Post().Get(reaction.PostId)
var postHadReactions bool
if result := <-pchan; result.Err != nil {
@@ -123,7 +124,7 @@ func deleteReaction(c *Context, w http.ResponseWriter, r *http.Request) {
postHadReactions = post.HasReactions
}
- if result := <-Srv.Store.Reaction().Delete(reaction); result.Err != nil {
+ if result := <-app.Srv.Store.Reaction().Delete(reaction); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -139,13 +140,13 @@ func sendReactionEvent(event string, channelId string, reaction *model.Reaction,
message := model.NewWebSocketEvent(event, "", channelId, "", nil)
message.Add("reaction", reaction.ToJson())
- Publish(message)
+ app.Publish(message)
}()
// send out that a post was updated if post.HasReactions has changed
go func() {
var post *model.Post
- if result := <-Srv.Store.Post().Get(reaction.PostId); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Get(reaction.PostId); result.Err != nil {
l4g.Warn(utils.T("api.reaction.send_reaction_event.post.app_error"))
return
} else {
@@ -156,7 +157,7 @@ func sendReactionEvent(event string, channelId string, reaction *model.Reaction,
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_EDITED, "", channelId, "", nil)
message.Add("post", post.ToJson())
- Publish(message)
+ app.Publish(message)
}
}()
}
@@ -176,7 +177,7 @@ func listReactions(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
@@ -192,7 +193,7 @@ func listReactions(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Reaction().GetForPost(postId); result.Err != nil {
+ if result := <-app.Srv.Store.Reaction().GetForPost(postId); result.Err != nil {
c.Err = result.Err
return
} else {
diff --git a/api/slackimport.go b/api/slackimport.go
index 3fd0ec3f6..2db1b44f0 100644
--- a/api/slackimport.go
+++ b/api/slackimport.go
@@ -16,6 +16,7 @@ import (
"unicode/utf8"
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -137,7 +138,7 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
// Need the team
var team *model.Team
- if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(teamId); result.Err != nil {
log.WriteString(utils.T("api.slackimport.slack_import.team_fail"))
return addedUsers
} else {
@@ -159,10 +160,10 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
password := model.NewId()
// Check for email conflict and use existing user if found
- if result := <-Srv.Store.User().GetByEmail(email); result.Err == nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err == nil {
existingUser := result.Data.(*model.User)
addedUsers[sUser.Id] = existingUser
- if err := JoinUserToTeam(team, addedUsers[sUser.Id]); err != nil {
+ if err := app.JoinUserToTeam(team, addedUsers[sUser.Id]); err != nil {
log.WriteString(utils.T("api.slackimport.slack_add_users.merge_existing_failed", map[string]interface{}{"Email": existingUser.Email, "Username": existingUser.Username}))
} else {
log.WriteString(utils.T("api.slackimport.slack_add_users.merge_existing", map[string]interface{}{"Email": existingUser.Email, "Username": existingUser.Username}))
@@ -191,7 +192,7 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
func SlackAddBotUser(teamId string, log *bytes.Buffer) *model.User {
var team *model.Team
- if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(teamId); result.Err != nil {
log.WriteString(utils.T("api.slackimport.slack_import.team_fail"))
return nil
} else {
@@ -244,7 +245,7 @@ func SlackAddPosts(teamId string, channel *model.Channel, posts []SlackPost, use
}
ImportPost(&newPost)
for _, fileId := range newPost.FileIds {
- if result := <-Srv.Store.FileInfo().AttachToPost(fileId, newPost.Id); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().AttachToPost(fileId, newPost.Id); result.Err != nil {
l4g.Error(utils.T("api.slackimport.slack_add_posts.attach_files.error"), newPost.Id, newPost.FileIds, result.Err)
}
}
@@ -375,7 +376,7 @@ func addSlackUsersToChannel(members []string, users map[string]*model.User, chan
if user, ok := users[member]; !ok {
log.WriteString(utils.T("api.slackimport.slack_add_channels.failed_to_add_user", map[string]interface{}{"Username": "?"}))
} else {
- if _, err := AddUserToChannel(user, channel); err != nil {
+ if _, err := app.AddUserToChannel(user, channel); err != nil {
log.WriteString(utils.T("api.slackimport.slack_add_channels.failed_to_add_user", map[string]interface{}{"Username": user.Username}))
}
}
@@ -425,7 +426,7 @@ func SlackAddChannels(teamId string, slackchannels []SlackChannel, posts map[str
mChannel := ImportChannel(&newChannel)
if mChannel == nil {
// Maybe it already exists?
- if result := <-Srv.Store.Channel().GetByName(teamId, sChannel.Name); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetByName(teamId, sChannel.Name); result.Err != nil {
l4g.Warn(utils.T("api.slackimport.slack_add_channels.import_failed.warn"), newChannel.DisplayName)
log.WriteString(utils.T("api.slackimport.slack_add_channels.import_failed", map[string]interface{}{"DisplayName": newChannel.DisplayName}))
continue
@@ -560,7 +561,7 @@ func SlackImport(fileData multipart.File, fileSize int64, teamID string) (*model
deactivateSlackBotUser(botUser)
}
- InvalidateAllCaches()
+ app.InvalidateAllCaches()
log.WriteString(utils.T("api.slackimport.slack_import.notes"))
log.WriteString("=======\r\n\r\n")
diff --git a/api/status.go b/api/status.go
index 909ab50ec..69f391f47 100644
--- a/api/status.go
+++ b/api/status.go
@@ -8,67 +8,30 @@ import (
l4g "github.com/alecthomas/log4go"
- "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
-var statusCache *utils.Cache = utils.NewLru(model.STATUS_CACHE_SIZE)
-
-func ClearStatusCache() {
- statusCache.Purge()
-}
-
-func AddStatusCacheSkipClusterSend(status *model.Status) {
- statusCache.Add(status.UserId, status)
-}
-
-func AddStatusCache(status *model.Status) {
- AddStatusCacheSkipClusterSend(status)
-
- if einterfaces.GetClusterInterface() != nil {
- einterfaces.GetClusterInterface().UpdateStatus(status)
- }
-}
-
func InitStatus() {
l4g.Debug(utils.T("api.status.init.debug"))
BaseRoutes.Users.Handle("/status", ApiUserRequired(getStatusesHttp)).Methods("GET")
BaseRoutes.Users.Handle("/status/ids", ApiUserRequired(getStatusesByIdsHttp)).Methods("POST")
- BaseRoutes.WebSocket.Handle("get_statuses", ApiWebSocketHandler(getStatusesWebSocket))
- BaseRoutes.WebSocket.Handle("get_statuses_by_ids", ApiWebSocketHandler(getStatusesByIdsWebSocket))
+ app.Srv.WebSocketRouter.Handle("get_statuses", ApiWebSocketHandler(getStatusesWebSocket))
+ app.Srv.WebSocketRouter.Handle("get_statuses_by_ids", ApiWebSocketHandler(getStatusesByIdsWebSocket))
}
func getStatusesHttp(c *Context, w http.ResponseWriter, r *http.Request) {
- statusMap := model.StatusMapToInterfaceMap(GetAllStatuses())
+ statusMap := model.StatusMapToInterfaceMap(app.GetAllStatuses())
w.Write([]byte(model.StringInterfaceToJson(statusMap)))
}
func getStatusesWebSocket(req *model.WebSocketRequest) (map[string]interface{}, *model.AppError) {
- statusMap := GetAllStatuses()
+ statusMap := app.GetAllStatuses()
return model.StatusMapToInterfaceMap(statusMap), nil
}
-func GetAllStatuses() map[string]*model.Status {
- userIds := statusCache.Keys()
- statusMap := map[string]*model.Status{}
-
- for _, userId := range userIds {
- if id, ok := userId.(string); !ok {
- continue
- } else {
- status := GetStatusFromCache(id)
- if status != nil {
- statusMap[id] = status
- }
- }
- }
-
- return statusMap
-}
-
func getStatusesByIdsHttp(c *Context, w http.ResponseWriter, r *http.Request) {
userIds := model.ArrayFromJson(r.Body)
@@ -77,7 +40,7 @@ func getStatusesByIdsHttp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- statusMap, err := GetStatusesByIds(userIds)
+ statusMap, err := app.GetStatusesByIds(userIds)
if err != nil {
c.Err = err
return
@@ -93,216 +56,10 @@ func getStatusesByIdsWebSocket(req *model.WebSocketRequest) (map[string]interfac
return nil, NewInvalidWebSocketParamError(req.Action, "user_ids")
}
- statusMap, err := GetStatusesByIds(userIds)
+ statusMap, err := app.GetStatusesByIds(userIds)
if err != nil {
return nil, err
}
return statusMap, nil
}
-
-func GetStatusesByIds(userIds []string) (map[string]interface{}, *model.AppError) {
- statusMap := map[string]interface{}{}
- metrics := einterfaces.GetMetricsInterface()
-
- missingUserIds := []string{}
- for _, userId := range userIds {
- if result, ok := statusCache.Get(userId); ok {
- statusMap[userId] = result.(*model.Status).Status
- if metrics != nil {
- metrics.IncrementMemCacheHitCounter("Status")
- }
- } else {
- missingUserIds = append(missingUserIds, userId)
- if metrics != nil {
- metrics.IncrementMemCacheMissCounter("Status")
- }
- }
- }
-
- if len(missingUserIds) > 0 {
- if result := <-Srv.Store.Status().GetByIds(missingUserIds); result.Err != nil {
- return nil, result.Err
- } else {
- statuses := result.Data.([]*model.Status)
-
- for _, s := range statuses {
- AddStatusCache(s)
- statusMap[s.UserId] = s.Status
- }
- }
- }
-
- // For the case where the user does not have a row in the Status table and cache
- for _, userId := range missingUserIds {
- if _, ok := statusMap[userId]; !ok {
- statusMap[userId] = model.STATUS_OFFLINE
- }
- }
-
- return statusMap, nil
-}
-
-func SetStatusOnline(userId string, sessionId string, manual bool) {
- broadcast := false
-
- var oldStatus string = model.STATUS_OFFLINE
- var oldTime int64 = 0
- var oldManual bool = false
- var status *model.Status
- var err *model.AppError
-
- if status, err = GetStatus(userId); err != nil {
- status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), ""}
- broadcast = true
- } else {
- if status.Manual && !manual {
- return // manually set status always overrides non-manual one
- }
-
- if status.Status != model.STATUS_ONLINE {
- broadcast = true
- }
-
- oldStatus = status.Status
- oldTime = status.LastActivityAt
- oldManual = status.Manual
-
- status.Status = model.STATUS_ONLINE
- status.Manual = false // for "online" there's no manual setting
- status.LastActivityAt = model.GetMillis()
- }
-
- AddStatusCache(status)
-
- // Only update the database if the status has changed, the status has been manually set,
- // or enough time has passed since the previous action
- if status.Status != oldStatus || status.Manual != oldManual || status.LastActivityAt-oldTime > model.STATUS_MIN_UPDATE_TIME {
- achan := Srv.Store.Session().UpdateLastActivityAt(sessionId, status.LastActivityAt)
-
- var schan store.StoreChannel
- if broadcast {
- schan = Srv.Store.Status().SaveOrUpdate(status)
- } else {
- schan = Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt)
- }
-
- if result := <-achan; result.Err != nil {
- l4g.Error(utils.T("api.status.last_activity.error"), userId, sessionId, result.Err)
- }
-
- if result := <-schan; result.Err != nil {
- l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err)
- }
- }
-
- if broadcast {
- event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil)
- event.Add("status", model.STATUS_ONLINE)
- event.Add("user_id", status.UserId)
- go Publish(event)
- }
-}
-
-func SetStatusOffline(userId string, manual bool) {
- status, err := GetStatus(userId)
- if err == nil && status.Manual && !manual {
- return // manually set status always overrides non-manual one
- }
-
- status = &model.Status{userId, model.STATUS_OFFLINE, manual, model.GetMillis(), ""}
-
- AddStatusCache(status)
-
- if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil {
- l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err)
- }
-
- event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil)
- event.Add("status", model.STATUS_OFFLINE)
- event.Add("user_id", status.UserId)
- go Publish(event)
-}
-
-func SetStatusAwayIfNeeded(userId string, manual bool) {
- status, err := GetStatus(userId)
-
- if err != nil {
- status = &model.Status{userId, model.STATUS_OFFLINE, manual, 0, ""}
- }
-
- if !manual && status.Manual {
- return // manually set status always overrides non-manual one
- }
-
- if !manual {
- if status.Status == model.STATUS_AWAY {
- return
- }
-
- if !IsUserAway(status.LastActivityAt) {
- return
- }
- }
-
- status.Status = model.STATUS_AWAY
- status.Manual = manual
- status.ActiveChannel = ""
-
- AddStatusCache(status)
-
- if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil {
- l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err)
- }
-
- event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil)
- event.Add("status", model.STATUS_AWAY)
- event.Add("user_id", status.UserId)
- go Publish(event)
-}
-
-func GetStatusFromCache(userId string) *model.Status {
- if result, ok := statusCache.Get(userId); ok {
- status := result.(*model.Status)
- statusCopy := &model.Status{}
- *statusCopy = *status
- return statusCopy
- }
-
- return nil
-}
-
-func GetStatus(userId string) (*model.Status, *model.AppError) {
- status := GetStatusFromCache(userId)
- if status != nil {
- return status, nil
- }
-
- if result := <-Srv.Store.Status().Get(userId); result.Err != nil {
- return nil, result.Err
- } else {
- return result.Data.(*model.Status), nil
- }
-}
-
-func IsUserAway(lastActivityAt int64) bool {
- return model.GetMillis()-lastActivityAt >= *utils.Cfg.TeamSettings.UserStatusAwayTimeout*1000
-}
-
-func DoesStatusAllowPushNotification(user *model.User, status *model.Status, channelId string) bool {
- props := user.NotifyProps
-
- if props["push"] == "none" {
- return false
- }
-
- if pushStatus, ok := props["push_status"]; (pushStatus == model.STATUS_ONLINE || !ok) && (status.ActiveChannel != channelId || model.GetMillis()-status.LastActivityAt > model.STATUS_CHANNEL_TIMEOUT) {
- return true
- } else if pushStatus == model.STATUS_AWAY && (status.Status == model.STATUS_AWAY || status.Status == model.STATUS_OFFLINE) {
- return true
- } else if pushStatus == model.STATUS_OFFLINE && status.Status == model.STATUS_OFFLINE {
- return true
- }
-
- return false
-}
diff --git a/api/status_test.go b/api/status_test.go
index 5db5a8d7c..34c3320bd 100644
--- a/api/status_test.go
+++ b/api/status_test.go
@@ -8,6 +8,7 @@ import (
"testing"
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -34,12 +35,12 @@ func TestStatuses(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
LinkUserToTeam(ruser, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser2 := Client.Must(Client.CreateUser(&user2, "")).Data.(*model.User)
LinkUserToTeam(ruser2, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser2.Id))
Client.Login(user.Email, user.Password)
Client.SetTeamId(team.Id)
@@ -137,7 +138,7 @@ func TestStatuses(t *testing.T) {
WebSocketClient2.Close()
- SetStatusAwayIfNeeded(th.BasicUser.Id, false)
+ app.SetStatusAwayIfNeeded(th.BasicUser.Id, false)
awayTimeout := *utils.Cfg.TeamSettings.UserStatusAwayTimeout
defer func() {
@@ -147,8 +148,8 @@ func TestStatuses(t *testing.T) {
time.Sleep(1500 * time.Millisecond)
- SetStatusAwayIfNeeded(th.BasicUser.Id, false)
- SetStatusOnline(th.BasicUser.Id, "junk", false)
+ app.SetStatusAwayIfNeeded(th.BasicUser.Id, false)
+ app.SetStatusOnline(th.BasicUser.Id, "junk", false)
time.Sleep(1500 * time.Millisecond)
diff --git a/api/team.go b/api/team.go
index c855a515d..a8ed90eb5 100644
--- a/api/team.go
+++ b/api/team.go
@@ -16,6 +16,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -61,7 +62,7 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
var user *model.User
if len(c.Session.UserId) > 0 {
- uchan := Srv.Store.User().Get(c.Session.UserId)
+ uchan := app.Srv.Store.User().Get(c.Session.UserId)
if result := <-uchan; result.Err != nil {
c.Err = result.Err
@@ -76,13 +77,14 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- rteam := CreateTeam(c, team)
- if c.Err != nil {
+ rteam, err := app.CreateTeam(team)
+ if err != nil {
+ c.Err = err
return
}
if user != nil {
- err := JoinUserToTeam(team, user)
+ err := app.JoinUserToTeam(team, user)
if err != nil {
c.Err = err
return
@@ -92,84 +94,11 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(rteam.ToJson()))
}
-func CreateTeam(c *Context, team *model.Team) *model.Team {
- if result := <-Srv.Store.Team().Save(team); result.Err != nil {
- c.Err = result.Err
- return nil
- } else {
- rteam := result.Data.(*model.Team)
-
- if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
- c.Err = err
- return nil
- }
-
- return rteam
- }
-}
-
-func JoinUserToTeamById(teamId string, user *model.User) *model.AppError {
- if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
- return result.Err
- } else {
- return JoinUserToTeam(result.Data.(*model.Team), user)
- }
-}
-
-func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
-
- tm := &model.TeamMember{
- TeamId: team.Id,
- UserId: user.Id,
- Roles: model.ROLE_TEAM_USER.Id,
- }
-
- channelRole := model.ROLE_CHANNEL_USER.Id
-
- if team.Email == user.Email {
- tm.Roles = model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id
- channelRole = model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id
- }
-
- if etmr := <-Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil {
- // Membership alredy exists. Check if deleted and and update, otherwise do nothing
- rtm := etmr.Data.(model.TeamMember)
-
- // Do nothing if already added
- if rtm.DeleteAt == 0 {
- return nil
- }
-
- if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
- return tmr.Err
- }
- } else {
- // Membership appears to be missing. Lets try to add.
- if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil {
- return tmr.Err
- }
- }
-
- if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
- return uua.Err
- }
-
- // Soft error if there is an issue joining the default channels
- if err := JoinDefaultChannels(team.Id, user, channelRole); err != nil {
- l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err)
- }
-
- RemoveAllSessionsForUserId(user.Id)
- InvalidateCacheForUser(user.Id)
-
- return nil
-}
-
func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
var teamMember model.TeamMember
- if result := <-Srv.Store.Team().GetMember(team.Id, user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetMember(team.Id, user.Id); result.Err != nil {
return model.NewLocAppError("RemoveUserFromTeam", "api.team.remove_user_from_team.missing.app_error", nil, result.Err.Error())
} else {
teamMember = result.Data.(model.TeamMember)
@@ -177,7 +106,7 @@ func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
var channelList *model.ChannelList
- if result := <-Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
channelList = &model.ChannelList{}
} else {
@@ -190,8 +119,8 @@ func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
for _, channel := range *channelList {
if channel.Type != model.CHANNEL_DIRECT {
- InvalidateCacheForChannel(channel.Id)
- if result := <-Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
+ app.InvalidateCacheForChannel(channel.Id)
+ if result := <-app.Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
return result.Err
}
}
@@ -201,26 +130,26 @@ func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil)
message.Add("user_id", user.Id)
message.Add("team_id", team.Id)
- Publish(message)
+ app.Publish(message)
teamMember.Roles = ""
teamMember.DeleteAt = model.GetMillis()
- if result := <-Srv.Store.Team().UpdateMember(&teamMember); result.Err != nil {
+ if result := <-app.Srv.Store.Team().UpdateMember(&teamMember); result.Err != nil {
return result.Err
}
- if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
+ if uua := <-app.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
return uua.Err
}
// delete the preferences that set the last channel used in the team and other team specific preferences
- if result := <-Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
return result.Err
}
- RemoveAllSessionsForUserId(user.Id)
- InvalidateCacheForUser(user.Id)
+ app.RemoveAllSessionsForUserId(user.Id)
+ app.InvalidateCacheForUser(user.Id)
return nil
}
@@ -235,7 +164,7 @@ func isTeamCreationAllowed(c *Context, email string) bool {
}
c.Err = nil
- if result := <-Srv.Store.User().GetByEmail(email); result.Err == nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err == nil {
user := result.Data.(*model.User)
if len(user.AuthService) > 0 && len(*user.AuthData) > 0 {
return true
@@ -263,7 +192,7 @@ func isTeamCreationAllowed(c *Context, email string) bool {
}
func GetAllTeamListings(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -286,10 +215,10 @@ func GetAllTeamListings(c *Context, w http.ResponseWriter, r *http.Request) {
func getAll(c *Context, w http.ResponseWriter, r *http.Request) {
var tchan store.StoreChannel
if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- tchan = Srv.Store.Team().GetAll()
+ tchan = app.Srv.Store.Team().GetAll()
} else {
c.Err = nil
- tchan = Srv.Store.Team().GetTeamsByUserId(c.Session.UserId)
+ tchan = app.Srv.Store.Team().GetTeamsByUserId(c.Session.UserId)
}
if result := <-tchan; result.Err != nil {
@@ -310,7 +239,7 @@ func revokeAllSessions(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
id := props["id"]
- if result := <-Srv.Store.Session().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -321,11 +250,11 @@ func revokeAllSessions(c *Context, w http.ResponseWriter, r *http.Request) {
if session.IsOAuth {
RevokeAccessToken(session.Token)
} else {
- if result := <-Srv.Store.Session().Remove(session.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
c.Err = result.Err
return
} else {
- RemoveAllSessionsForUserId(session.UserId)
+ app.RemoveAllSessionsForUserId(session.UserId)
w.Write([]byte(model.MapToJson(props)))
return
}
@@ -354,8 +283,8 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- tchan := Srv.Store.Team().Get(c.TeamId)
- uchan := Srv.Store.User().Get(c.Session.UserId)
+ tchan := app.Srv.Store.Team().Get(c.TeamId)
+ uchan := app.Srv.Store.User().Get(c.Session.UserId)
var team *model.Team
if result := <-tchan; result.Err != nil {
@@ -392,8 +321,8 @@ func addUserToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- tchan := Srv.Store.Team().Get(c.TeamId)
- uchan := Srv.Store.User().Get(userId)
+ tchan := app.Srv.Store.Team().Get(c.TeamId)
+ uchan := app.Srv.Store.User().Get(userId)
var team *model.Team
if result := <-tchan; result.Err != nil {
@@ -415,7 +344,7 @@ func addUserToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- err := JoinUserToTeam(team, user)
+ err := app.JoinUserToTeam(team, user)
if err != nil {
c.Err = err
return
@@ -433,8 +362,8 @@ func removeUserFromTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- tchan := Srv.Store.Team().Get(c.TeamId)
- uchan := Srv.Store.User().Get(userId)
+ tchan := app.Srv.Store.Team().Get(c.TeamId)
+ uchan := app.Srv.Store.User().Get(userId)
var team *model.Team
if result := <-tchan; result.Err != nil {
@@ -494,7 +423,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
teamId = props["id"]
// try to load the team to make sure it exists
- if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(teamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -503,7 +432,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
}
if len(inviteId) > 0 {
- if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -517,7 +446,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
return
}
- uchan := Srv.Store.User().Get(c.Session.UserId)
+ uchan := app.Srv.Store.User().Get(c.Session.UserId)
var user *model.User
if result := <-uchan; result.Err != nil {
@@ -530,7 +459,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
tm := c.Session.GetTeamByTeamId(teamId)
if tm == nil {
- err := JoinUserToTeam(team, user)
+ err := app.JoinUserToTeam(team, user)
if err != nil {
c.Err = err
return
@@ -543,7 +472,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
}
func FindTeamByName(name string) bool {
- if result := <-Srv.Store.Team().GetByName(name); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(name); result.Err != nil {
return false
} else {
return true
@@ -568,7 +497,7 @@ func getTeamByName(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
teamname := params["team_name"]
- if result := <-Srv.Store.Team().GetByName(teamname); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(teamname); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -589,7 +518,7 @@ func getMyTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
if len(c.Session.TeamMembers) > 0 {
w.Write([]byte(model.TeamMembersToJson(c.Session.TeamMembers)))
} else {
- if result := <-Srv.Store.Team().GetTeamsForUser(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetTeamsForUser(c.Session.UserId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -602,7 +531,7 @@ func getMyTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
func getMyTeamsUnread(c *Context, w http.ResponseWriter, r *http.Request) {
teamId := r.URL.Query().Get("id")
- if result := <-Srv.Store.Team().GetTeamsUnreadForUser(teamId, c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetTeamsUnreadForUser(teamId, c.Session.UserId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -696,7 +625,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
var oldTeam *model.Team
- if result := <-Srv.Store.Team().Get(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(team.Id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -711,7 +640,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
oldTeam.AllowedDomains = team.AllowedDomains
//oldTeam.Type = team.Type
- if result := <-Srv.Store.Team().Update(oldTeam); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Update(oldTeam); result.Err != nil {
c.Err = result.Err
return
}
@@ -720,7 +649,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_UPDATE_TEAM, "", "", "", nil)
message.Add("team", oldTeam.ToJson())
- go Publish(message)
+ go app.Publish(message)
w.Write([]byte(oldTeam.ToJson()))
}
@@ -734,7 +663,7 @@ func updateMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- mchan := Srv.Store.Team().GetTeamsForUser(userId)
+ mchan := app.Srv.Store.Team().GetTeamsForUser(userId)
teamId := c.TeamId
@@ -769,12 +698,12 @@ func updateMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
member.Roles = newRoles
- if result := <-Srv.Store.Team().UpdateMember(member); result.Err != nil {
+ if result := <-app.Srv.Store.Team().UpdateMember(member); result.Err != nil {
c.Err = result.Err
return
}
- RemoveAllSessionsForUserId(userId)
+ app.RemoveAllSessionsForUserId(userId)
rdata := map[string]string{}
rdata["status"] = "ok"
@@ -783,19 +712,19 @@ func updateMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
func PermanentDeleteTeam(team *model.Team) *model.AppError {
team.DeleteAt = model.GetMillis()
- if result := <-Srv.Store.Team().Update(team); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Update(team); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
return result.Err
}
@@ -808,7 +737,7 @@ func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Team().Get(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else if HandleEtag(result.Data.(*model.Team).Etag(), "Get My Team", w, r) {
@@ -827,8 +756,8 @@ func getTeamStats(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- tchan := Srv.Store.Team().GetTotalMemberCount(c.TeamId)
- achan := Srv.Store.Team().GetActiveMemberCount(c.TeamId)
+ tchan := app.Srv.Store.Team().GetTotalMemberCount(c.TeamId)
+ achan := app.Srv.Store.Team().GetActiveMemberCount(c.TeamId)
stats := &model.TeamStats{}
stats.TeamId = c.TeamId
@@ -925,7 +854,7 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
m := model.MapFromJson(r.Body)
inviteId := m["invite_id"]
- if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -965,7 +894,7 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.Team().GetMembers(c.TeamId, offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetMembers(c.TeamId, offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -990,7 +919,7 @@ func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.Team().GetMember(c.TeamId, userId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetMember(c.TeamId, userId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1013,7 +942,7 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.Team().GetMembersByIds(c.TeamId, userIds); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetMembersByIds(c.TeamId, userIds); result.Err != nil {
c.Err = result.Err
return
} else {
diff --git a/api/team_test.go b/api/team_test.go
index 7403afd8a..641f7b98d 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -6,6 +6,7 @@ package api
import (
"testing"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -25,7 +26,7 @@ func TestCreateTeam(t *testing.T) {
user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
Client.SetTeamId(rteam.Data.(*model.Team).Id)
@@ -140,7 +141,7 @@ func TestGetAllTeams(t *testing.T) {
user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -173,7 +174,7 @@ func TestGetAllTeamListings(t *testing.T) {
user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -219,7 +220,7 @@ func TestTeamPermDelete(t *testing.T) {
user1 := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
LinkUserToTeam(user1, team)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user1.Id))
Client.Login(user1.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -263,7 +264,7 @@ func TestInviteMembers(t *testing.T) {
user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -347,12 +348,12 @@ func TestUpdateTeamDisplayName(t *testing.T) {
user := &model.User{Email: team.Email, Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
Client.Login(user2.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -413,7 +414,7 @@ func TestGetMyTeam(t *testing.T) {
user := model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
Client.Login(user.Email, user.Password)
Client.SetTeamId(team.Id)
@@ -658,7 +659,7 @@ func TestGetTeamStats(t *testing.T) {
user := model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
Client.Login(user.Email, user.Password)
@@ -678,12 +679,12 @@ func TestUpdateTeamDescription(t *testing.T) {
user := &model.User{Email: team.Email, Nickname: "My Testing", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Jabba the Hutt", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
Client.Login(user2.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -721,7 +722,7 @@ func TestGetTeamByName(t *testing.T) {
user := &model.User{Email: team.Email, Nickname: "My Testing", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
if _, err := Client.GetTeamByName(team.Name); err != nil {
@@ -740,7 +741,7 @@ func TestGetTeamByName(t *testing.T) {
user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Jabba the Hutt", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
Client.Login(user2.Email, "passwd1")
diff --git a/api/user.go b/api/user.go
index 966223a5b..e3cae3704 100644
--- a/api/user.go
+++ b/api/user.go
@@ -27,6 +27,7 @@ import (
"github.com/disintegration/imaging"
"github.com/golang/freetype"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
@@ -84,7 +85,7 @@ func InitUser() {
BaseRoutes.Root.Handle("/login/sso/saml", AppHandlerIndependent(loginWithSaml)).Methods("GET")
BaseRoutes.Root.Handle("/login/sso/saml", AppHandlerIndependent(completeSaml)).Methods("POST")
- BaseRoutes.WebSocket.Handle("user_typing", ApiWebSocketHandler(userTyping))
+ app.Srv.WebSocketRouter.Handle("user_typing", ApiWebSocketHandler(userTyping))
}
func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -125,7 +126,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
teamId = props["id"]
// try to load the team to make sure it exists
- if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Get(teamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -139,7 +140,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
inviteId := r.URL.Query().Get("iid")
if len(inviteId) > 0 {
- if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -149,8 +150,8 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
firstAccount := false
- if sessionCache.Len() == 0 {
- if cr := <-Srv.Store.User().GetTotalUsersCount(); cr.Err != nil {
+ if app.SessionCacheLength() == 0 {
+ if cr := <-app.Srv.Store.User().GetTotalUsersCount(); cr.Err != nil {
c.Err = cr.Err
return
} else {
@@ -171,14 +172,14 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- ruser, err := CreateUser(user)
+ ruser, err := app.CreateUser(user)
if err != nil {
c.Err = err
return
}
if len(teamId) > 0 {
- err := JoinUserToTeam(team, ruser)
+ err := app.JoinUserToTeam(team, ruser)
if err != nil {
c.Err = err
return
@@ -238,56 +239,6 @@ func IsVerifyHashRequired(user *model.User, team *model.Team, hash string) bool
return shouldVerifyHash
}
-func CreateUser(user *model.User) (*model.User, *model.AppError) {
-
- user.Roles = model.ROLE_SYSTEM_USER.Id
-
- // Below is a special case where the first user in the entire
- // system is granted the system_admin role
- if result := <-Srv.Store.User().GetTotalUsersCount(); result.Err != nil {
- return nil, result.Err
- } else {
- count := result.Data.(int64)
- if count <= 0 {
- user.Roles = model.ROLE_SYSTEM_ADMIN.Id + " " + model.ROLE_SYSTEM_USER.Id
- }
- }
-
- user.MakeNonNil()
- user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
-
- if err := utils.IsPasswordValid(user.Password); user.AuthService == "" && err != nil {
- return nil, err
- }
-
- if result := <-Srv.Store.User().Save(user); result.Err != nil {
- l4g.Error(utils.T("api.user.create_user.save.error"), result.Err)
- return nil, result.Err
- } else {
- ruser := result.Data.(*model.User)
-
- if user.EmailVerified {
- if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- l4g.Error(utils.T("api.user.create_user.verified.error"), cresult.Err)
- }
- }
-
- pref := model.Preference{UserId: ruser.Id, Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, Name: ruser.Id, Value: "0"}
- if presult := <-Srv.Store.Preference().Save(&model.Preferences{pref}); presult.Err != nil {
- l4g.Error(utils.T("api.user.create_user.tutorial.error"), presult.Err.Message)
- }
-
- ruser.Sanitize(map[string]bool{})
-
- // This message goes to everyone, so the teamId, channelId and userId are irrelevant
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil)
- message.Add("user_id", ruser.Id)
- go Publish(message)
-
- return ruser, nil
- }
-}
-
func CreateOAuthUser(c *Context, w http.ResponseWriter, r *http.Request, service string, userData io.Reader, teamId string) *model.User {
var user *model.User
provider := einterfaces.GetOauthProvider(service)
@@ -303,8 +254,8 @@ func CreateOAuthUser(c *Context, w http.ResponseWriter, r *http.Request, service
return nil
}
- suchan := Srv.Store.User().GetByAuth(user.AuthData, service)
- euchan := Srv.Store.User().GetByEmail(user.Email)
+ suchan := app.Srv.Store.User().GetByAuth(user.AuthData, service)
+ euchan := app.Srv.Store.User().GetByEmail(user.Email)
found := true
count := 0
@@ -335,14 +286,14 @@ func CreateOAuthUser(c *Context, w http.ResponseWriter, r *http.Request, service
user.EmailVerified = true
- ruser, err := CreateUser(user)
+ ruser, err := app.CreateUser(user)
if err != nil {
c.Err = err
return nil
}
if len(teamId) > 0 {
- err = JoinUserToTeamById(teamId, user)
+ err = app.JoinUserToTeamById(teamId, user)
if err != nil {
c.Err = err
return nil
@@ -390,7 +341,7 @@ func sendWelcomeEmail(c *Context, userId string, email string, siteURL string, v
func addDirectChannels(teamId string, user *model.User) {
var profiles map[string]*model.User
- if result := <-Srv.Store.User().GetProfiles(teamId, 0, 100); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetProfiles(teamId, 0, 100); result.Err != nil {
l4g.Error(utils.T("api.user.add_direct_channels_and_forget.failed.error"), user.Id, teamId, result.Err.Error())
return
} else {
@@ -420,7 +371,7 @@ func addDirectChannels(teamId string, user *model.User) {
}
}
- if result := <-Srv.Store.Preference().Save(&preferences); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Save(&preferences); result.Err != nil {
l4g.Error(utils.T("api.user.add_direct_channels_and_forget.failed.error"), user.Id, teamId, result.Err.Error())
}
}
@@ -467,7 +418,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
if len(id) != 0 {
c.LogAuditWithUserId(id, "attempt")
- if result := <-Srv.Store.User().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(id); result.Err != nil {
c.LogAuditWithUserId(id, "failure")
c.Err = result.Err
c.Err.StatusCode = http.StatusBadRequest
@@ -521,7 +472,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
func getUserForLogin(loginId string, onlyLdap bool) (*model.User, *model.AppError) {
ldapAvailable := *utils.Cfg.LdapSettings.Enable && einterfaces.GetLdapInterface() != nil && utils.IsLicensed && *utils.License.Features.LDAP
- if result := <-Srv.Store.User().GetForLogin(
+ if result := <-app.Srv.Store.User().GetForLogin(
loginId,
*utils.Cfg.EmailSettings.EnableSignInWithUsername && !onlyLdap,
*utils.Cfg.EmailSettings.EnableSignInWithEmail && !onlyLdap,
@@ -570,7 +521,7 @@ func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service st
}
var user *model.User
- if result := <-Srv.Store.User().GetByAuth(&authData, service); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByAuth(&authData, service); result.Err != nil {
if result.Err.Id == store.MISSING_AUTH_ACCOUNT_ERROR {
return CreateOAuthUser(c, w, r, service, bytes.NewReader(buf.Bytes()), "")
}
@@ -598,7 +549,7 @@ func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.Use
maxAge = *utils.Cfg.ServiceSettings.SessionLengthMobileInDays * 60 * 60 * 24
// A special case where we logout of all other sessions with the same Id
- if result := <-Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
c.Err = result.Err
c.Err.StatusCode = http.StatusInternalServerError
return
@@ -648,13 +599,13 @@ func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.Use
session.AddProp(model.SESSION_PROP_OS, os)
session.AddProp(model.SESSION_PROP_BROWSER, fmt.Sprintf("%v/%v", bname, bversion))
- if result := <-Srv.Store.Session().Save(session); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Save(session); result.Err != nil {
c.Err = result.Err
c.Err.StatusCode = http.StatusInternalServerError
return
} else {
session = result.Data.(*model.Session)
- AddSessionToCache(session)
+ app.AddSessionToCache(session)
}
w.Header().Set(model.HEADER_TOKEN, session.Token)
@@ -702,7 +653,7 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
}
// A special case where we logout of all other sessions with the same Id
- if result := <-Srv.Store.Session().GetSessions(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Session().GetSessions(c.Session.UserId); result.Err != nil {
c.Err = result.Err
c.Err.StatusCode = http.StatusInternalServerError
return
@@ -720,7 +671,7 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- RemoveAllSessionsForUserId(c.Session.UserId)
+ app.RemoveAllSessionsForUserId(c.Session.UserId)
c.Session.SetExpireInDays(*utils.Cfg.ServiceSettings.SessionLengthMobileInDays)
maxAge := *utils.Cfg.ServiceSettings.SessionLengthMobileInDays * 60 * 60 * 24
@@ -743,7 +694,7 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, sessionCookie)
- if result := <-Srv.Store.Session().UpdateDeviceId(c.Session.Id, deviceId, c.Session.ExpiresAt); result.Err != nil {
+ if result := <-app.Srv.Store.Session().UpdateDeviceId(c.Session.Id, deviceId, c.Session.ExpiresAt); result.Err != nil {
c.Err = result.Err
return
}
@@ -752,7 +703,7 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
}
func RevokeSessionById(c *Context, sessionId string) {
- if result := <-Srv.Store.Session().Get(sessionId); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Get(sessionId); result.Err != nil {
c.Err = result.Err
} else {
session := result.Data.(*model.Session)
@@ -761,19 +712,19 @@ func RevokeSessionById(c *Context, sessionId string) {
if session.IsOAuth {
RevokeAccessToken(session.Token)
} else {
- if result := <-Srv.Store.Session().Remove(session.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
c.Err = result.Err
}
}
RevokeWebrtcToken(session.Id)
- RemoveAllSessionsForUserId(session.UserId)
+ app.RemoveAllSessionsForUserId(session.UserId)
}
}
// IF YOU UPDATE THIS PLEASE UPDATE BELOW
func RevokeAllSession(c *Context, userId string) {
- if result := <-Srv.Store.Session().GetSessions(userId); result.Err != nil {
+ if result := <-app.Srv.Store.Session().GetSessions(userId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -784,7 +735,7 @@ func RevokeAllSession(c *Context, userId string) {
if session.IsOAuth {
RevokeAccessToken(session.Token)
} else {
- if result := <-Srv.Store.Session().Remove(session.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
c.Err = result.Err
return
}
@@ -794,13 +745,13 @@ func RevokeAllSession(c *Context, userId string) {
}
}
- RemoveAllSessionsForUserId(userId)
+ app.RemoveAllSessionsForUserId(userId)
}
// UGH...
// If you update this please update above
func RevokeAllSessionsNoContext(userId string) *model.AppError {
- if result := <-Srv.Store.Session().GetSessions(userId); result.Err != nil {
+ if result := <-app.Srv.Store.Session().GetSessions(userId); result.Err != nil {
return result.Err
} else {
sessions := result.Data.([]*model.Session)
@@ -809,7 +760,7 @@ func RevokeAllSessionsNoContext(userId string) *model.AppError {
if session.IsOAuth {
RevokeAccessToken(session.Token)
} else {
- if result := <-Srv.Store.Session().Remove(session.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
return result.Err
}
}
@@ -818,7 +769,7 @@ func RevokeAllSessionsNoContext(userId string) *model.AppError {
}
}
- RemoveAllSessionsForUserId(userId)
+ app.RemoveAllSessionsForUserId(userId)
return nil
}
@@ -832,7 +783,7 @@ func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Session().GetSessions(id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().GetSessions(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -865,7 +816,7 @@ func Logout(c *Context, w http.ResponseWriter, r *http.Request) {
func getMe(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
c.Err = result.Err
c.RemoveSessionCookie(w, r)
l4g.Error(utils.T("api.user.get_me.getting.error"), c.Session.UserId)
@@ -886,17 +837,17 @@ func getInitialLoad(c *Context, w http.ResponseWriter, r *http.Request) {
var cchan store.StoreChannel
- if sessionCache.Len() == 0 {
+ if app.SessionCacheLength() == 0 {
// Below is a special case when intializating a new server
// Lets check to make sure the server is really empty
- cchan = Srv.Store.User().GetTotalUsersCount()
+ cchan = app.Srv.Store.User().GetTotalUsersCount()
}
if len(c.Session.UserId) != 0 {
- uchan := Srv.Store.User().Get(c.Session.UserId)
- pchan := Srv.Store.Preference().GetAll(c.Session.UserId)
- tchan := Srv.Store.Team().GetTeamsByUserId(c.Session.UserId)
+ uchan := app.Srv.Store.User().Get(c.Session.UserId)
+ pchan := app.Srv.Store.Preference().GetAll(c.Session.UserId)
+ tchan := app.Srv.Store.Team().GetTeamsByUserId(c.Session.UserId)
il.TeamMembers = c.Session.TeamMembers
@@ -954,7 +905,7 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["user_id"]
- if result := <-Srv.Store.User().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(id); result.Err != nil {
c.Err = result.Err
return
} else if HandleEtag(result.Data.(*model.User).Etag(utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress), "Get User", w, r) {
@@ -972,7 +923,7 @@ func getByUsername(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
username := params["username"]
- if result := <-Srv.Store.User().GetByUsername(username); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByUsername(username); result.Err != nil {
c.Err = result.Err
return
} else if HandleEtag(result.Data.(*model.User).Etag(utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress), "Get By Username", w, r) {
@@ -990,7 +941,7 @@ func getByEmail(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
email := params["email"]
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
c.Err = result.Err
return
} else if HandleEtag(result.Data.(*model.User).Etag(utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress), "Get By Email", w, r) {
@@ -1019,12 +970,12 @@ func getProfiles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- etag := (<-Srv.Store.User().GetEtagForAllProfiles()).Data.(string)
+ etag := (<-app.Srv.Store.User().GetEtagForAllProfiles()).Data.(string)
if HandleEtag(etag, "Get Profiles", w, r) {
return
}
- if result := <-Srv.Store.User().GetAllProfiles(offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetAllProfiles(offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1061,12 +1012,12 @@ func getProfilesInTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- etag := (<-Srv.Store.User().GetEtagForProfiles(teamId)).Data.(string)
+ etag := (<-app.Srv.Store.User().GetEtagForProfiles(teamId)).Data.(string)
if HandleEtag(etag, "Get Profiles In Team", w, r) {
return
}
- if result := <-Srv.Store.User().GetProfiles(teamId, offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetProfiles(teamId, offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1107,7 +1058,7 @@ func getProfilesInChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.User().GetProfilesInChannel(channelId, offset, limit, false); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetProfilesInChannel(channelId, offset, limit, false); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1147,7 +1098,7 @@ func getProfilesNotInChannel(c *Context, w http.ResponseWriter, r *http.Request)
return
}
- if result := <-Srv.Store.User().GetProfilesNotInChannel(c.TeamId, channelId, offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetProfilesNotInChannel(c.TeamId, channelId, offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1169,8 +1120,8 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- userChan := Srv.Store.User().Get(id)
- auditChan := Srv.Store.Audit().Get(id, 20)
+ userChan := app.Srv.Store.User().Get(id)
+ auditChan := app.Srv.Store.Audit().Get(id, 20)
if c.Err = (<-userChan).Err; c.Err != nil {
return
@@ -1278,7 +1229,7 @@ func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
var etag string
- if result := <-Srv.Store.User().Get(id); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1407,9 +1358,9 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- Srv.Store.User().UpdateLastPictureUpdate(c.Session.UserId)
+ app.Srv.Store.User().UpdateLastPictureUpdate(c.Session.UserId)
- if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
l4g.Error(utils.T("api.user.get_me.getting.error"), c.Session.UserId)
} else {
user := result.Data.(*model.User)
@@ -1419,7 +1370,7 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", omitUsers)
message.Add("user", user)
- go Publish(message)
+ go app.Publish(message)
}
c.LogAudit("")
@@ -1445,7 +1396,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.User().Update(user, false); result.Err != nil {
+ if result := <-app.Srv.Store.User().Update(user, false); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1465,7 +1416,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
go sendEmailChangeUsername(c, rusers[1].Username, rusers[0].Username, rusers[0].Email, c.GetSiteURL())
}
- InvalidateCacheForUser(user.Id)
+ app.InvalidateCacheForUser(user.Id)
updatedUser := rusers[0]
updatedUser = sanitizeProfile(c, updatedUser)
@@ -1474,7 +1425,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
omitUsers[user.Id] = true
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", omitUsers)
message.Add("user", updatedUser)
- go Publish(message)
+ go app.Publish(message)
rusers[0].Password = ""
rusers[0].AuthData = new(string)
@@ -1514,7 +1465,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
var result store.StoreResult
- if result = <-Srv.Store.User().Get(userId); result.Err != nil {
+ if result = <-app.Srv.Store.User().Get(userId); result.Err != nil {
c.Err = result.Err
return
}
@@ -1544,7 +1495,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if uresult := <-Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(newPassword)); uresult.Err != nil {
+ if uresult := <-app.Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(newPassword)); uresult.Err != nil {
c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.failed.app_error", nil, uresult.Err.Error())
return
} else {
@@ -1579,7 +1530,7 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
}
var user *model.User
- if result := <-Srv.Store.User().Get(userId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(userId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1600,8 +1551,8 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
func UpdateUserRoles(user *model.User, newRoles string) (*model.User, *model.AppError) {
user.Roles = newRoles
- uchan := Srv.Store.User().Update(user, true)
- schan := Srv.Store.Session().UpdateRoles(user.Id, newRoles)
+ uchan := app.Srv.Store.User().Update(user, true)
+ schan := app.Srv.Store.Session().UpdateRoles(user.Id, newRoles)
var ruser *model.User
if result := <-uchan; result.Err != nil {
@@ -1615,7 +1566,7 @@ func UpdateUserRoles(user *model.User, newRoles string) (*model.User, *model.App
l4g.Error(result.Err)
}
- RemoveAllSessionsForUserId(user.Id)
+ app.RemoveAllSessionsForUserId(user.Id)
return ruser, nil
}
@@ -1632,7 +1583,7 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
active := props["active"] == "true"
var user *model.User
- if result := <-Srv.Store.User().Get(user_id); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(user_id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1658,7 +1609,7 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
} else {
if !active {
- SetStatusOffline(ruser.Id, false)
+ app.SetStatusOffline(ruser.Id, false)
}
c.LogAuditWithUserId(ruser.Id, fmt.Sprintf("active=%v", active))
@@ -1673,14 +1624,14 @@ func UpdateActive(user *model.User, active bool) (*model.User, *model.AppError)
user.DeleteAt = model.GetMillis()
}
- if result := <-Srv.Store.User().Update(user, true); result.Err != nil {
+ if result := <-app.Srv.Store.User().Update(user, true); result.Err != nil {
return nil, result.Err
} else {
if user.DeleteAt > 0 {
RevokeAllSessionsNoContext(user.Id)
}
- if extra := <-Srv.Store.Channel().ExtraUpdateByUser(user.Id, model.GetMillis()); extra.Err != nil {
+ if extra := <-app.Srv.Store.Channel().ExtraUpdateByUser(user.Id, model.GetMillis()); extra.Err != nil {
return nil, extra.Err
}
@@ -1702,51 +1653,51 @@ func PermanentDeleteUser(user *model.User) *model.AppError {
return err
}
- if result := <-Srv.Store.Session().PermanentDeleteSessionsByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().PermanentDeleteSessionsByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.OAuth().PermanentDeleteAuthDataByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.OAuth().PermanentDeleteAuthDataByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Webhook().PermanentDeleteIncomingByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().PermanentDeleteIncomingByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Webhook().PermanentDeleteOutgoingByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().PermanentDeleteOutgoingByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Command().PermanentDeleteByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Command().PermanentDeleteByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Preference().PermanentDeleteByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().PermanentDeleteByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Channel().PermanentDeleteMembersByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().PermanentDeleteMembersByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Post().PermanentDeleteByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Post().PermanentDeleteByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.User().PermanentDelete(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.User().PermanentDelete(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Audit().PermanentDeleteByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Audit().PermanentDeleteByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.Team().RemoveAllMembersByUser(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Team().RemoveAllMembersByUser(user.Id); result.Err != nil {
return result.Err
}
- if result := <-Srv.Store.PasswordRecovery().Delete(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.PasswordRecovery().Delete(user.Id); result.Err != nil {
return result.Err
}
@@ -1756,7 +1707,7 @@ func PermanentDeleteUser(user *model.User) *model.AppError {
}
func PermanentDeleteAllUsers() *model.AppError {
- if result := <-Srv.Store.User().GetAll(); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetAll(); result.Err != nil {
return result.Err
} else {
users := result.Data.([]*model.User)
@@ -1778,7 +1729,7 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
}
var user *model.User
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
w.Write([]byte(model.MapToJson(props)))
return
} else {
@@ -1793,7 +1744,7 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
recovery := &model.PasswordRecovery{}
recovery.UserId = user.Id
- if result := <-Srv.Store.PasswordRecovery().SaveOrUpdate(recovery); result.Err != nil {
+ if result := <-app.Srv.Store.PasswordRecovery().SaveOrUpdate(recovery); result.Err != nil {
c.Err = result.Err
return
}
@@ -1838,7 +1789,7 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
userId := ""
- if result := <-Srv.Store.PasswordRecovery().GetByCode(code); result.Err != nil {
+ if result := <-app.Srv.Store.PasswordRecovery().GetByCode(code); result.Err != nil {
c.LogAuditWithUserId(userId, "fail - bad code")
c.Err = model.NewLocAppError("resetPassword", "api.user.reset_password.invalid_link.app_error", nil, result.Err.Error())
return
@@ -1854,7 +1805,7 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
}
go func() {
- if result := <-Srv.Store.PasswordRecovery().Delete(userId); result.Err != nil {
+ if result := <-app.Srv.Store.PasswordRecovery().Delete(userId); result.Err != nil {
l4g.Error("%v", result.Err)
}
}()
@@ -1874,7 +1825,7 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
func ResetPassword(c *Context, userId, newPassword string) *model.AppError {
var user *model.User
- if result := <-Srv.Store.User().Get(userId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(userId); result.Err != nil {
return result.Err
} else {
user = result.Data.(*model.User)
@@ -1885,7 +1836,7 @@ func ResetPassword(c *Context, userId, newPassword string) *model.AppError {
}
- if result := <-Srv.Store.User().UpdatePassword(userId, model.HashPassword(newPassword)); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdatePassword(userId, model.HashPassword(newPassword)); result.Err != nil {
return result.Err
}
@@ -1992,7 +1943,7 @@ func updateUserNotify(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- uchan := Srv.Store.User().Get(user_id)
+ uchan := app.Srv.Store.User().Get(user_id)
if !HasPermissionToUser(c, user_id) {
return
@@ -2034,12 +1985,12 @@ func updateUserNotify(c *Context, w http.ResponseWriter, r *http.Request) {
user.NotifyProps = props
- if result := <-Srv.Store.User().Update(user, false); result.Err != nil {
+ if result := <-app.Srv.Store.User().Update(user, false); result.Err != nil {
c.Err = result.Err
return
} else {
c.LogAuditWithUserId(user.Id, "")
- InvalidateCacheForUser(user.Id)
+ app.InvalidateCacheForUser(user.Id)
ruser := result.Data.([2]*model.User)[0]
options := utils.Cfg.GetSanitizeOptions()
@@ -2056,7 +2007,7 @@ func IsUsernameTaken(name string) bool {
return false
}
- if result := <-Srv.Store.User().GetByUsername(name); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByUsername(name); result.Err != nil {
return false
} else {
return true
@@ -2091,7 +2042,7 @@ func emailToOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
c.LogAudit("fail - couldn't get user")
c.Err = result.Err
return
@@ -2144,7 +2095,7 @@ func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
c.LogAudit("fail - couldn't get user")
c.Err = result.Err
return
@@ -2159,7 +2110,7 @@ func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(password)); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(password)); result.Err != nil {
c.LogAudit("fail - database issue")
c.Err = result.Err
return
@@ -2212,7 +2163,7 @@ func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
c.LogAudit("fail - couldn't get user")
c.Err = result.Err
return
@@ -2280,7 +2231,7 @@ func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
c.LogAudit("fail - couldn't get user")
c.Err = result.Err
return
@@ -2312,7 +2263,7 @@ func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(emailPassword)); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(emailPassword)); result.Err != nil {
c.LogAudit("fail - database issue")
c.Err = result.Err
return
@@ -2364,7 +2315,7 @@ func verifyEmail(c *Context, w http.ResponseWriter, r *http.Request) {
}
if model.ComparePassword(hashedId, userId+utils.Cfg.EmailSettings.InviteSalt) {
- if c.Err = (<-Srv.Store.User().VerifyEmail(userId)).Err; c.Err != nil {
+ if c.Err = (<-app.Srv.Store.User().VerifyEmail(userId)).Err; c.Err != nil {
return
} else {
c.LogAudit("Email Verified")
@@ -2389,7 +2340,7 @@ func resendVerification(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = error
return
} else {
- if _, err := GetStatus(user.Id); err != nil {
+ if _, err := app.GetStatus(user.Id); err != nil {
go SendVerifyEmail(c, user.Id, user.Email, c.GetSiteURL())
} else {
go SendEmailChangeVerifyEmail(c, user.Id, user.Email, c.GetSiteURL())
@@ -2398,7 +2349,7 @@ func resendVerification(c *Context, w http.ResponseWriter, r *http.Request) {
}
func generateMfaSecret(c *Context, w http.ResponseWriter, r *http.Request) {
- uchan := Srv.Store.User().Get(c.Session.UserId)
+ uchan := app.Srv.Store.User().Get(c.Session.UserId)
var user *model.User
if result := <-uchan; result.Err != nil {
@@ -2467,7 +2418,7 @@ func updateMfa(c *Context, w http.ResponseWriter, r *http.Request) {
go func() {
var user *model.User
- if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
l4g.Warn(result.Err)
} else {
user = result.Data.(*model.User)
@@ -2490,7 +2441,7 @@ func ActivateMfa(userId, token string) *model.AppError {
}
var user *model.User
- if result := <-Srv.Store.User().Get(userId); result.Err != nil {
+ if result := <-app.Srv.Store.User().Get(userId); result.Err != nil {
return result.Err
} else {
user = result.Data.(*model.User)
@@ -2540,7 +2491,7 @@ func checkMfa(c *Context, w http.ResponseWriter, r *http.Request) {
// we don't need to worry about contacting the ldap server to get this user because
// only users already in the system could have MFA enabled
- uchan := Srv.Store.User().GetForLogin(
+ uchan := app.Srv.Store.User().GetForLogin(
loginId,
*utils.Cfg.EmailSettings.EnableSignInWithUsername,
*utils.Cfg.EmailSettings.EnableSignInWithEmail,
@@ -2680,7 +2631,7 @@ func userTyping(req *model.WebSocketRequest) (map[string]interface{}, *model.App
event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_TYPING, "", channelId, "", omitUsers)
event.Add("parent_id", parentId)
event.Add("user_id", req.Session.UserId)
- go Publish(event)
+ go app.Publish(event)
return nil, nil
}
@@ -2740,11 +2691,11 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
var uchan store.StoreChannel
if props.InChannelId != "" {
- uchan = Srv.Store.User().SearchInChannel(props.InChannelId, props.Term, searchOptions)
+ uchan = app.Srv.Store.User().SearchInChannel(props.InChannelId, props.Term, searchOptions)
} else if props.NotInChannelId != "" {
- uchan = Srv.Store.User().SearchNotInChannel(props.TeamId, props.NotInChannelId, props.Term, searchOptions)
+ uchan = app.Srv.Store.User().SearchNotInChannel(props.TeamId, props.NotInChannelId, props.Term, searchOptions)
} else {
- uchan = Srv.Store.User().Search(props.TeamId, props.Term, searchOptions)
+ uchan = app.Srv.Store.User().Search(props.TeamId, props.Term, searchOptions)
}
if result := <-uchan; result.Err != nil {
@@ -2769,7 +2720,7 @@ func getProfilesByIds(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.User().GetProfileByIds(userIds, true); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetProfileByIds(userIds, true); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -2810,8 +2761,8 @@ func autocompleteUsersInChannel(c *Context, w http.ResponseWriter, r *http.Reque
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
- uchan := Srv.Store.User().SearchInChannel(channelId, term, searchOptions)
- nuchan := Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions)
+ uchan := app.Srv.Store.User().SearchInChannel(channelId, term, searchOptions)
+ nuchan := app.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions)
autocomplete := &model.UserAutocompleteInChannel{}
@@ -2866,7 +2817,7 @@ func autocompleteUsersInTeam(c *Context, w http.ResponseWriter, r *http.Request)
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
- uchan := Srv.Store.User().Search(teamId, term, searchOptions)
+ uchan := app.Srv.Store.User().Search(teamId, term, searchOptions)
autocomplete := &model.UserAutocompleteInTeam{}
@@ -2899,7 +2850,7 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
- uchan := Srv.Store.User().Search("", term, searchOptions)
+ uchan := app.Srv.Store.User().Search("", term, searchOptions)
var profiles []*model.User
diff --git a/api/user_test.go b/api/user_test.go
index c846beee3..fa7f28e6b 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -16,6 +16,7 @@ import (
"testing"
"time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -148,7 +149,7 @@ func TestLogin(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Username: "corey" + model.NewId(), Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
if result, err := Client.LoginById(ruser.Data.(*model.User).Id, user.Password); err != nil {
t.Fatal(err)
@@ -242,7 +243,7 @@ func TestLogin(t *testing.T) {
AuthService: model.USER_AUTH_SERVICE_LDAP,
}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user3.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user3.Id))
if _, err := Client.Login(user3.Id, user3.Password); err == nil {
t.Fatal("AD/LDAP user should not be able to log in with AD/LDAP disabled")
@@ -259,7 +260,7 @@ func TestLoginByLdap(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Username: "corey" + model.NewId(), Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
if _, err := Client.LoginByLdap(ruser.Data.(*model.User).Id, user.Password); err == nil {
t.Fatal("should have failed to log in with non AD/LDAP user")
@@ -286,7 +287,7 @@ func TestLoginWithDeviceId(t *testing.T) {
t.Fatal(err)
}
- if sresult := <-Srv.Store.Session().Get(sessions[0].Id); sresult.Err == nil {
+ if sresult := <-app.Srv.Store.Session().Get(sessions[0].Id); sresult.Err == nil {
t.Fatal("session should have been removed")
}
}
@@ -387,12 +388,12 @@ func TestGetUser(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", FirstName: "Corey", LastName: "Hulen"}
ruser2, _ := Client.CreateUser(&user2, "")
LinkUserToTeam(ruser2.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser2.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser2.Data.(*model.User).Id))
team2 := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
rteam2, _ := Client.CreateTeam(&team2)
@@ -400,7 +401,7 @@ func TestGetUser(t *testing.T) {
user3 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser3, _ := Client.CreateUser(&user3, "")
LinkUserToTeam(ruser3.Data.(*model.User), rteam2.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser3.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser3.Data.(*model.User).Id))
Client.Login(user.Email, user.Password)
@@ -653,7 +654,7 @@ func TestGetAudits(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
time.Sleep(100 * time.Millisecond)
@@ -708,7 +709,7 @@ func TestUserCreateImage(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
@@ -753,7 +754,7 @@ func TestUserUploadProfileImage(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
if utils.Cfg.FileSettings.DriverName != "" {
@@ -862,7 +863,7 @@ func TestUserUpdate(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", Roles: ""}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.UpdateUser(user); err == nil {
t.Fatal("Should have errored")
@@ -892,7 +893,7 @@ func TestUserUpdate(t *testing.T) {
user2 := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
Client.Login(user2.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -915,7 +916,7 @@ func TestUserUpdatePassword(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.UpdateUserPassword(user.Id, "passwd1", "newpasswd1"); err == nil {
t.Fatal("Should have errored")
@@ -997,12 +998,12 @@ func TestUserUpdateRoles(t *testing.T) {
user := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.UpdateUserRoles(user.Id, ""); err == nil {
t.Fatal("Should have errored, not logged in")
@@ -1021,7 +1022,7 @@ func TestUserUpdateRoles(t *testing.T) {
user3 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
LinkUserToTeam(user3, team2)
- store.Must(Srv.Store.User().VerifyEmail(user3.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user3.Id))
Client.Login(user3.Email, "passwd1")
Client.SetTeamId(team2.Id)
@@ -1116,7 +1117,7 @@ func TestUserUpdateDeviceId(t *testing.T) {
user := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Login(user.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -1126,7 +1127,7 @@ func TestUserUpdateDeviceId(t *testing.T) {
t.Fatal(err)
}
- if result := <-Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
t.Fatal(result.Err)
} else {
sessions := result.Data.([]*model.Session)
@@ -1148,12 +1149,12 @@ func TestUserUpdateActive(t *testing.T) {
user := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.UpdateActive(user.Id, false); err == nil {
t.Fatal("Should have errored, not logged in")
@@ -1174,7 +1175,7 @@ func TestUserUpdateActive(t *testing.T) {
user3 := &model.User{Email: "success+" + model.NewId() + "@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
LinkUserToTeam(user2, team2)
- store.Must(Srv.Store.User().VerifyEmail(user3.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user3.Id))
Client.Login(user3.Email, "passwd1")
Client.SetTeamId(team2.Id)
@@ -1194,13 +1195,13 @@ func TestUserUpdateActive(t *testing.T) {
t.Fatal("Should have errored, bad id")
}
- SetStatusOnline(user3.Id, "", false)
+ app.SetStatusOnline(user3.Id, "", false)
if _, err := SystemAdminClient.UpdateActive(user3.Id, false); err != nil {
t.Fatal(err)
}
- if status, err := GetStatus(user3.Id); err != nil {
+ if status, err := app.GetStatus(user3.Id); err != nil {
t.Fatal(err)
} else if status.Status != model.STATUS_OFFLINE {
t.Fatal("status should have been set to offline")
@@ -1217,7 +1218,7 @@ func TestUserPermDelete(t *testing.T) {
user1 := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
LinkUserToTeam(user1, team)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user1.Id))
Client.Login(user1.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -1259,7 +1260,7 @@ func TestSendPasswordReset(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
if result, err := Client.SendPasswordReset(user.Email); err != nil {
t.Fatal(err)
@@ -1282,7 +1283,7 @@ func TestSendPasswordReset(t *testing.T) {
user2 := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", AuthData: &authData, AuthService: "random"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
LinkUserToTeam(user2, team)
- store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.SendPasswordReset(user2.Email); err == nil {
t.Fatal("should have errored - SSO user can't send reset password link")
@@ -1297,12 +1298,12 @@ func TestResetPassword(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
Client.Must(Client.SendPasswordReset(user.Email))
var recovery *model.PasswordRecovery
- if result := <-Srv.Store.PasswordRecovery().Get(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.PasswordRecovery().Get(user.Id); result.Err != nil {
t.Fatal(result.Err)
} else {
recovery = result.Data.(*model.PasswordRecovery)
@@ -1342,14 +1343,14 @@ func TestResetPassword(t *testing.T) {
Client.Must(Client.SendPasswordReset(user.Email))
- if result := <-Srv.Store.PasswordRecovery().Get(user.Id); result.Err != nil {
+ if result := <-app.Srv.Store.PasswordRecovery().Get(user.Id); result.Err != nil {
t.Fatal(result.Err)
} else {
recovery = result.Data.(*model.PasswordRecovery)
}
authData := model.NewId()
- if result := <-Srv.Store.User().UpdateAuthData(user.Id, "random", &authData, "", true); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdateAuthData(user.Id, "random", &authData, "", true); result.Err != nil {
t.Fatal(result.Err)
}
@@ -1368,7 +1369,7 @@ func TestUserUpdateNotify(t *testing.T) {
user := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", Roles: ""}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
LinkUserToTeam(user, team)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
data := make(map[string]string)
data["user_id"] = user.Id
@@ -1479,7 +1480,7 @@ func TestEmailToOAuth(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
LinkUserToTeam(ruser, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
m := map[string]string{}
if _, err := Client.EmailToOAuth(m); err == nil {
@@ -1530,12 +1531,12 @@ func TestOAuthToEmail(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
LinkUserToTeam(ruser, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser2 := Client.Must(Client.CreateUser(&user2, "")).Data.(*model.User)
LinkUserToTeam(ruser2, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser2.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser2.Id))
m := map[string]string{}
if _, err := Client.OAuthToEmail(m); err == nil {
@@ -1581,7 +1582,7 @@ func TestLDAPToEmail(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
LinkUserToTeam(ruser, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
Client.Login(user.Email, user.Password)
@@ -1634,7 +1635,7 @@ func TestEmailToLDAP(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
LinkUserToTeam(ruser, rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
Client.Login(user.Email, user.Password)
@@ -1765,7 +1766,7 @@ func TestGenerateMfaSecret(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
Client.Logout()
@@ -1803,7 +1804,7 @@ func TestUpdateMfa(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
Client.Logout()
@@ -1842,7 +1843,7 @@ func TestCheckMfa(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
ruser, _ := Client.CreateUser(&user, "")
LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
- store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
if result, err := Client.CheckMfa(user.Email); err != nil {
t.Fatal(err)
diff --git a/api/webhook.go b/api/webhook.go
index 8a4263533..32c6d80b9 100644
--- a/api/webhook.go
+++ b/api/webhook.go
@@ -11,6 +11,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -31,7 +32,7 @@ func InitWebhook() {
BaseRoutes.Hooks.Handle("/{id:[A-Za-z0-9]+}", ApiAppHandler(incomingWebhook)).Methods("POST")
// Old route. Remove eventually.
- mr := Srv.Router
+ mr := app.Srv.Router
mr.Handle("/hooks/{id:[A-Za-z0-9]+}", ApiAppHandler(incomingWebhook)).Methods("POST")
}
@@ -55,7 +56,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().Get(hook.ChannelId, true)
+ cchan := app.Srv.Store.Channel().Get(hook.ChannelId, true)
hook.UserId = c.Session.UserId
hook.TeamId = c.TeamId
@@ -73,7 +74,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Webhook().SaveIncoming(hook); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().SaveIncoming(hook); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -106,7 +107,7 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Webhook().GetIncoming(id); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().GetIncoming(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -117,7 +118,7 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if err := (<-Srv.Store.Webhook().DeleteIncoming(id, model.GetMillis())).Err; err != nil {
+ if err := (<-app.Srv.Store.Webhook().DeleteIncoming(id, model.GetMillis())).Err; err != nil {
c.Err = err
return
}
@@ -139,7 +140,7 @@ func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Webhook().GetIncomingByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().GetIncomingByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -174,7 +175,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
hook.TeamId = c.TeamId
if len(hook.ChannelId) != 0 {
- cchan := Srv.Store.Channel().Get(hook.ChannelId, true)
+ cchan := app.Srv.Store.Channel().Get(hook.ChannelId, true)
var channel *model.Channel
if result := <-cchan; result.Err != nil {
@@ -200,7 +201,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -217,7 +218,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-Srv.Store.Webhook().SaveOutgoing(hook); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().SaveOutgoing(hook); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -240,7 +241,7 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -272,7 +273,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Webhook().GetOutgoing(id); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().GetOutgoing(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -283,7 +284,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if err := (<-Srv.Store.Webhook().DeleteOutgoing(id, model.GetMillis())).Err; err != nil {
+ if err := (<-app.Srv.Store.Webhook().DeleteOutgoing(id, model.GetMillis())).Err; err != nil {
c.Err = err
return
}
@@ -316,7 +317,7 @@ func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request)
}
var hook *model.OutgoingWebhook
- if result := <-Srv.Store.Webhook().GetOutgoing(id); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().GetOutgoing(id); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -331,7 +332,7 @@ func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request)
hook.Token = model.NewId()
- if result := <-Srv.Store.Webhook().UpdateOutgoing(hook); result.Err != nil {
+ if result := <-app.Srv.Store.Webhook().UpdateOutgoing(hook); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -349,7 +350,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["id"]
- hchan := Srv.Store.Webhook().GetIncoming(id)
+ hchan := app.Srv.Store.Webhook().GetIncoming(id)
r.ParseForm()
@@ -434,7 +435,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
if len(channelName) != 0 {
if channelName[0] == '@' {
- if result := <-Srv.Store.User().GetByUsername(channelName[1:]); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByUsername(channelName[1:]); result.Err != nil {
c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message)
return
} else {
@@ -445,9 +446,9 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
channelName = channelName[1:]
}
- cchan = Srv.Store.Channel().GetByName(hook.TeamId, channelName)
+ cchan = app.Srv.Store.Channel().GetByName(hook.TeamId, channelName)
} else {
- cchan = Srv.Store.Channel().Get(hook.ChannelId, true)
+ cchan = app.Srv.Store.Channel().Get(hook.ChannelId, true)
}
overrideUsername := parsedRequest.Username
@@ -455,14 +456,14 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
result := <-cchan
if result.Err != nil && result.Err.Id == store.MISSING_CHANNEL_ERROR && directUserId != "" {
- newChanResult := <-Srv.Store.Channel().CreateDirectChannel(directUserId, hook.UserId)
+ newChanResult := <-app.Srv.Store.Channel().CreateDirectChannel(directUserId, hook.UserId)
if newChanResult.Err != nil {
c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+newChanResult.Err.Message)
return
} else {
channel = newChanResult.Data.(*model.Channel)
- InvalidateCacheForUser(directUserId)
- InvalidateCacheForUser(hook.UserId)
+ app.InvalidateCacheForUser(directUserId)
+ app.InvalidateCacheForUser(hook.UserId)
}
} else if result.Err != nil {
c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message)
@@ -490,7 +491,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
}
c.Err = nil
- if _, err := CreateWebhookPost(c, channel.Id, text, overrideUsername, overrideIconUrl, parsedRequest.Props, webhookType); err != nil {
+ if _, err := app.CreateWebhookPost(hook.UserId, hook.TeamId, channel.Id, text, overrideUsername, overrideIconUrl, parsedRequest.Props, webhookType); err != nil {
c.Err = err
return
}
diff --git a/api/webrtc.go b/api/webrtc.go
index 0ccbd8be1..7f30ffef9 100644
--- a/api/webrtc.go
+++ b/api/webrtc.go
@@ -8,14 +8,16 @@ import (
"crypto/sha1"
"crypto/tls"
"encoding/base64"
- l4g "github.com/alecthomas/log4go"
- "github.com/mattermost/platform/model"
- "github.com/mattermost/platform/utils"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
)
func InitWebrtc() {
@@ -23,7 +25,7 @@ func InitWebrtc() {
BaseRoutes.Webrtc.Handle("/token", ApiUserRequired(webrtcToken)).Methods("POST")
- BaseRoutes.WebSocket.Handle("webrtc", ApiWebSocketHandler(webrtcMessage))
+ app.Srv.WebSocketRouter.Handle("webrtc", ApiWebSocketHandler(webrtcMessage))
}
func webrtcToken(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -60,7 +62,7 @@ func webrtcMessage(req *model.WebSocketRequest) (map[string]interface{}, *model.
event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_WEBRTC, "", "", toUserId, nil)
event.Data = req.Data
- go Publish(event)
+ go app.Publish(event)
return nil, nil
}
diff --git a/api/websocket.go b/api/websocket.go
index 1c3277497..11ae09036 100644
--- a/api/websocket.go
+++ b/api/websocket.go
@@ -4,27 +4,25 @@
package api
import (
+ "net/http"
+
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/websocket"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
- "net/http"
-)
-
-const (
- SOCKET_MAX_MESSAGE_SIZE_KB = 8 * 1024 // 8KB
)
func InitWebSocket() {
l4g.Debug(utils.T("api.web_socket.init.debug"))
BaseRoutes.Users.Handle("/websocket", ApiAppHandlerTrustRequester(connect)).Methods("GET")
- HubStart()
+ app.HubStart()
}
func connect(c *Context, w http.ResponseWriter, r *http.Request) {
upgrader := websocket.Upgrader{
- ReadBufferSize: SOCKET_MAX_MESSAGE_SIZE_KB,
- WriteBufferSize: SOCKET_MAX_MESSAGE_SIZE_KB,
+ ReadBufferSize: model.SOCKET_MAX_MESSAGE_SIZE_KB,
+ WriteBufferSize: model.SOCKET_MAX_MESSAGE_SIZE_KB,
CheckOrigin: func(r *http.Request) bool {
return true
},
@@ -37,8 +35,8 @@ func connect(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- wc := NewWebConn(c, ws)
- HubRegister(wc)
- go wc.writePump()
- wc.readPump()
+ wc := app.NewWebConn(ws, c.Session, c.T, c.Locale)
+ app.HubRegister(wc)
+ go wc.WritePump()
+ wc.ReadPump()
}
diff --git a/api/websocket_handler.go b/api/websocket_handler.go
index 95aad8fee..25cdf6458 100644
--- a/api/websocket_handler.go
+++ b/api/websocket_handler.go
@@ -6,22 +6,34 @@ package api
import (
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
-func ApiWebSocketHandler(wh func(*model.WebSocketRequest) (map[string]interface{}, *model.AppError)) *webSocketHandler {
- return &webSocketHandler{wh}
+func ApiWebSocketHandler(wh func(*model.WebSocketRequest) (map[string]interface{}, *model.AppError)) webSocketHandler {
+ return webSocketHandler{wh}
}
type webSocketHandler struct {
handlerFunc func(*model.WebSocketRequest) (map[string]interface{}, *model.AppError)
}
-func (wh *webSocketHandler) ServeWebSocket(conn *WebConn, r *model.WebSocketRequest) {
+func (wh webSocketHandler) ServeWebSocket(conn *app.WebConn, r *model.WebSocketRequest) {
l4g.Debug("/api/v3/users/websocket:%s", r.Action)
- r.Session = *GetSession(conn.SessionToken)
+ session, sessionErr := app.GetSession(conn.SessionToken)
+ if sessionErr != nil {
+ l4g.Error(utils.T("api.web_socket_handler.log.error"), "/api/v3/users/websocket", r.Action, r.Seq, conn.UserId, sessionErr.SystemMessage(utils.T), sessionErr.Error())
+ sessionErr.DetailedError = ""
+ errResp := model.NewWebSocketError(r.Seq, sessionErr)
+ errResp.DoPreComputeJson()
+
+ conn.Send <- errResp
+ return
+ }
+
+ r.Session = *session
r.T = conn.T
r.Locale = conn.Locale
diff --git a/api/websocket_test.go b/api/websocket_test.go
index d7dbf1561..39a55f8f4 100644
--- a/api/websocket_test.go
+++ b/api/websocket_test.go
@@ -10,6 +10,7 @@ import (
"time"
//"github.com/gorilla/websocket"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -192,7 +193,7 @@ func TestWebSocketEvent(t *testing.T) {
omitUser["somerandomid"] = true
evt1 := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_TYPING, "", th.BasicChannel.Id, "", omitUser)
evt1.Add("user_id", "somerandomid")
- Publish(evt1)
+ app.Publish(evt1)
time.Sleep(300 * time.Millisecond)
@@ -221,7 +222,7 @@ func TestWebSocketEvent(t *testing.T) {
}
evt2 := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_TYPING, "", "somerandomid", "", nil)
- go Publish(evt2)
+ go app.Publish(evt2)
time.Sleep(300 * time.Millisecond)
eventHit = false
diff --git a/app/apptestlib.go b/app/apptestlib.go
new file mode 100644
index 000000000..dee6f0fd9
--- /dev/null
+++ b/app/apptestlib.go
@@ -0,0 +1,191 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "time"
+
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+
+ l4g "github.com/alecthomas/log4go"
+)
+
+type TestHelper struct {
+ BasicTeam *model.Team
+ BasicUser *model.User
+ BasicUser2 *model.User
+ BasicChannel *model.Channel
+ BasicPost *model.Post
+}
+
+func SetupEnterprise() *TestHelper {
+ if Srv == nil {
+ utils.TranslationsPreInit()
+ utils.LoadConfig("config.json")
+ utils.InitTranslations(utils.Cfg.LocalizationSettings)
+ utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
+ *utils.Cfg.RateLimitSettings.Enable = false
+ utils.DisableDebugLogForTest()
+ utils.License.Features.SetDefaults()
+ NewServer()
+ InitStores()
+ StartServer()
+ utils.InitHTML()
+ utils.EnableDebugLogForTest()
+ Srv.Store.MarkSystemRanUnitTests()
+
+ *utils.Cfg.TeamSettings.EnableOpenServer = true
+ }
+
+ return &TestHelper{}
+}
+
+func Setup() *TestHelper {
+ if Srv == nil {
+ utils.TranslationsPreInit()
+ utils.LoadConfig("config.json")
+ utils.InitTranslations(utils.Cfg.LocalizationSettings)
+ utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
+ *utils.Cfg.RateLimitSettings.Enable = false
+ utils.DisableDebugLogForTest()
+ NewServer()
+ InitStores()
+ StartServer()
+ utils.EnableDebugLogForTest()
+ Srv.Store.MarkSystemRanUnitTests()
+
+ *utils.Cfg.TeamSettings.EnableOpenServer = true
+ }
+
+ return &TestHelper{}
+}
+
+func (me *TestHelper) InitBasic() *TestHelper {
+ me.BasicTeam = me.CreateTeam()
+ me.BasicUser = me.CreateUser()
+ LinkUserToTeam(me.BasicUser, me.BasicTeam)
+ me.BasicUser2 = me.CreateUser()
+ LinkUserToTeam(me.BasicUser2, me.BasicTeam)
+ me.BasicChannel = me.CreateChannel(me.BasicTeam)
+ me.BasicPost = me.CreatePost(me.BasicChannel)
+
+ return me
+}
+
+func (me *TestHelper) CreateTeam() *model.Team {
+ id := model.NewId()
+ team := &model.Team{
+ DisplayName: "dn_" + id,
+ Name: "name" + id,
+ Email: "success+" + id + "@simulator.amazonses.com",
+ Type: model.TEAM_OPEN,
+ }
+
+ utils.DisableDebugLogForTest()
+ var err *model.AppError
+ if team, err = CreateTeam(team); err != nil {
+ l4g.Error(err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(err)
+ }
+ utils.EnableDebugLogForTest()
+ return team
+}
+
+func (me *TestHelper) CreateUser() *model.User {
+ id := model.NewId()
+
+ user := &model.User{
+ Email: "success+" + id + "@simulator.amazonses.com",
+ Username: "un_" + id,
+ Nickname: "nn_" + id,
+ Password: "Password1",
+ EmailVerified: true,
+ }
+
+ utils.DisableDebugLogForTest()
+ var err *model.AppError
+ if user, err = CreateUser(user); err != nil {
+ l4g.Error(err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(err)
+ }
+ utils.EnableDebugLogForTest()
+ return user
+}
+
+func (me *TestHelper) CreateChannel(team *model.Team) *model.Channel {
+ return me.createChannel(team, model.CHANNEL_OPEN)
+}
+
+func (me *TestHelper) CreatePrivateChannel(team *model.Team) *model.Channel {
+ return me.createChannel(team, model.CHANNEL_PRIVATE)
+}
+
+func (me *TestHelper) createChannel(team *model.Team, channelType string) *model.Channel {
+ id := model.NewId()
+
+ channel := &model.Channel{
+ DisplayName: "dn_" + id,
+ Name: "name_" + id,
+ Type: channelType,
+ TeamId: team.Id,
+ CreatorId: me.BasicUser.Id,
+ }
+
+ utils.DisableDebugLogForTest()
+ var err *model.AppError
+ if channel, err = CreateChannel(channel, true); err != nil {
+ l4g.Error(err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(err)
+ }
+ utils.EnableDebugLogForTest()
+ return channel
+}
+
+func (me *TestHelper) CreatePost(channel *model.Channel) *model.Post {
+ id := model.NewId()
+
+ post := &model.Post{
+ UserId: me.BasicUser.Id,
+ ChannelId: channel.Id,
+ Message: "message_" + id,
+ }
+
+ utils.DisableDebugLogForTest()
+ var err *model.AppError
+ if post, err = CreatePost(post, channel.TeamId, false); err != nil {
+ l4g.Error(err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(err)
+ }
+ utils.EnableDebugLogForTest()
+ return post
+}
+
+func LinkUserToTeam(user *model.User, team *model.Team) {
+ utils.DisableDebugLogForTest()
+
+ err := JoinUserToTeam(team, user)
+ if err != nil {
+ l4g.Error(err.Error())
+ l4g.Close()
+ time.Sleep(time.Second)
+ panic(err)
+ }
+
+ utils.EnableDebugLogForTest()
+}
+
+func TearDown() {
+ if Srv != nil {
+ StopServer()
+ }
+}
diff --git a/app/channel.go b/app/channel.go
new file mode 100644
index 000000000..1771c856b
--- /dev/null
+++ b/app/channel.go
@@ -0,0 +1,216 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "fmt"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
+)
+
+func MakeDirectChannelVisible(channelId string) *model.AppError {
+ var members []model.ChannelMember
+ if result := <-Srv.Store.Channel().GetMembers(channelId); result.Err != nil {
+ return result.Err
+ } else {
+ members = result.Data.([]model.ChannelMember)
+ }
+
+ if len(members) != 2 {
+ return model.NewLocAppError("MakeDirectChannelVisible", "api.post.make_direct_channel_visible.get_2_members.error", map[string]interface{}{"ChannelId": channelId}, "")
+ }
+
+ // make sure the channel is visible to both members
+ for i, member := range members {
+ otherUserId := members[1-i].UserId
+
+ if result := <-Srv.Store.Preference().Get(member.UserId, model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, otherUserId); result.Err != nil {
+ // create a new preference since one doesn't exist yet
+ preference := &model.Preference{
+ UserId: member.UserId,
+ Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
+ Name: otherUserId,
+ Value: "true",
+ }
+
+ if saveResult := <-Srv.Store.Preference().Save(&model.Preferences{*preference}); saveResult.Err != nil {
+ return saveResult.Err
+ } else {
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil)
+ message.Add("preference", preference.ToJson())
+
+ go Publish(message)
+ }
+ } else {
+ preference := result.Data.(model.Preference)
+
+ if preference.Value != "true" {
+ // update the existing preference to make the channel visible
+ preference.Value = "true"
+
+ if updateResult := <-Srv.Store.Preference().Save(&model.Preferences{preference}); updateResult.Err != nil {
+ return updateResult.Err
+ } else {
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil)
+ message.Add("preference", preference.ToJson())
+
+ go Publish(message)
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func CreateDefaultChannels(teamId string) ([]*model.Channel, *model.AppError) {
+ townSquare := &model.Channel{DisplayName: utils.T("api.channel.create_default_channels.town_square"), Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: teamId}
+
+ if _, err := CreateChannel(townSquare, false); err != nil {
+ return nil, err
+ }
+
+ offTopic := &model.Channel{DisplayName: utils.T("api.channel.create_default_channels.off_topic"), Name: "off-topic", Type: model.CHANNEL_OPEN, TeamId: teamId}
+
+ if _, err := CreateChannel(offTopic, false); err != nil {
+ return nil, err
+ }
+
+ channels := []*model.Channel{townSquare, offTopic}
+ return channels, nil
+}
+
+func JoinDefaultChannels(teamId string, user *model.User, channelRole string) *model.AppError {
+ var err *model.AppError = nil
+
+ if result := <-Srv.Store.Channel().GetByName(teamId, "town-square"); result.Err != nil {
+ err = result.Err
+ } else {
+ cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id,
+ Roles: channelRole, NotifyProps: model.GetDefaultChannelNotifyProps()}
+
+ if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
+ err = cmResult.Err
+ }
+
+ post := &model.Post{
+ ChannelId: result.Data.(*model.Channel).Id,
+ Message: fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username),
+ Type: model.POST_JOIN_LEAVE,
+ UserId: user.Id,
+ }
+
+ InvalidateCacheForChannel(result.Data.(*model.Channel).Id)
+
+ if _, err := CreatePost(post, teamId, false); err != nil {
+ l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
+ }
+ }
+
+ if result := <-Srv.Store.Channel().GetByName(teamId, "off-topic"); result.Err != nil {
+ err = result.Err
+ } else {
+ cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id,
+ Roles: channelRole, NotifyProps: model.GetDefaultChannelNotifyProps()}
+
+ if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
+ err = cmResult.Err
+ }
+
+ post := &model.Post{
+ ChannelId: result.Data.(*model.Channel).Id,
+ Message: fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username),
+ Type: model.POST_JOIN_LEAVE,
+ UserId: user.Id,
+ }
+
+ InvalidateCacheForChannel(result.Data.(*model.Channel).Id)
+
+ if _, err := CreatePost(post, teamId, false); err != nil {
+ l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
+ }
+ }
+
+ return err
+}
+
+func CreateChannel(channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) {
+ if result := <-Srv.Store.Channel().Save(channel); result.Err != nil {
+ return nil, result.Err
+ } else {
+ sc := result.Data.(*model.Channel)
+
+ if addMember {
+ cm := &model.ChannelMember{
+ ChannelId: sc.Id,
+ UserId: channel.CreatorId,
+ Roles: model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id,
+ NotifyProps: model.GetDefaultChannelNotifyProps(),
+ }
+
+ if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
+ return nil, cmresult.Err
+ }
+
+ InvalidateCacheForUser(channel.CreatorId)
+ }
+
+ return sc, nil
+ }
+}
+
+func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) {
+ if channel.DeleteAt > 0 {
+ return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user_to_channel.deleted.app_error", nil, "")
+ }
+
+ if channel.Type != model.CHANNEL_OPEN && channel.Type != model.CHANNEL_PRIVATE {
+ return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "")
+ }
+
+ tmchan := Srv.Store.Team().GetMember(channel.TeamId, user.Id)
+ cmchan := Srv.Store.Channel().GetMember(channel.Id, user.Id)
+
+ if result := <-tmchan; result.Err != nil {
+ return nil, result.Err
+ } else {
+ teamMember := result.Data.(model.TeamMember)
+ if teamMember.DeleteAt > 0 {
+ return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.deleted.app_error", nil, "")
+ }
+ }
+
+ if result := <-cmchan; result.Err != nil {
+ if result.Err.Id != store.MISSING_CHANNEL_MEMBER_ERROR {
+ return nil, result.Err
+ }
+ } else {
+ channelMember := result.Data.(model.ChannelMember)
+ return &channelMember, nil
+ }
+
+ newMember := &model.ChannelMember{
+ ChannelId: channel.Id,
+ UserId: user.Id,
+ NotifyProps: model.GetDefaultChannelNotifyProps(),
+ Roles: model.ROLE_CHANNEL_USER.Id,
+ }
+ if result := <-Srv.Store.Channel().SaveMember(newMember); result.Err != nil {
+ l4g.Error("Failed to add member user_id=%v channel_id=%v err=%v", user.Id, channel.Id, result.Err)
+ return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "")
+ }
+
+ InvalidateCacheForUser(user.Id)
+ InvalidateCacheForChannel(channel.Id)
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil)
+ message.Add("user_id", user.Id)
+ message.Add("team_id", channel.TeamId)
+ go Publish(message)
+
+ return newMember, nil
+}
diff --git a/app/command.go b/app/command.go
new file mode 100644
index 000000000..2d5861206
--- /dev/null
+++ b/app/command.go
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "github.com/mattermost/platform/model"
+)
+
+func CreateCommandPost(post *model.Post, teamId string, response *model.CommandResponse) (*model.Post, *model.AppError) {
+ post.Message = parseSlackLinksToMarkdown(response.Text)
+ post.CreateAt = model.GetMillis()
+
+ if response.Attachments != nil {
+ parseSlackAttachment(post, response.Attachments)
+ }
+
+ switch response.ResponseType {
+ case model.COMMAND_RESPONSE_TYPE_IN_CHANNEL:
+ return CreatePost(post, teamId, true)
+ case model.COMMAND_RESPONSE_TYPE_EPHEMERAL:
+ if response.Text == "" {
+ return post, nil
+ }
+
+ post.ParentId = ""
+ SendEphemeralPost(teamId, post.UserId, post)
+ }
+
+ return post, nil
+}
diff --git a/api/email_batching.go b/app/email_batching.go
index 608d839da..fc2fb1cea 100644
--- a/api/email_batching.go
+++ b/app/email_batching.go
@@ -1,7 +1,7 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package api
+package app
import (
"database/sql"
@@ -217,7 +217,7 @@ func renderBatchedPost(template *utils.HTMLTemplate, post *model.Post, teamName
cchan := Srv.Store.Channel().Get(post.ChannelId, true)
template.Props["Button"] = translateFunc("api.email_batching.render_batched_post.go_to_post")
- template.Props["PostMessage"] = getMessageForNotification(post, translateFunc)
+ template.Props["PostMessage"] = GetMessageForNotification(post, translateFunc)
template.Props["PostLink"] = *utils.Cfg.ServiceSettings.SiteURL + "/" + teamName + "/pl/" + post.Id
tm := time.Unix(post.CreateAt/1000, 0)
diff --git a/api/email_batching_test.go b/app/email_batching_test.go
index d1619f912..23722facd 100644
--- a/api/email_batching_test.go
+++ b/app/email_batching_test.go
@@ -1,7 +1,7 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package api
+package app
import (
"testing"
diff --git a/app/notification.go b/app/notification.go
new file mode 100644
index 000000000..d5e3c7b13
--- /dev/null
+++ b/app/notification.go
@@ -0,0 +1,732 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "crypto/tls"
+ "fmt"
+ "html"
+ "html/template"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
+ "github.com/nicksnyder/go-i18n/i18n"
+)
+
+func SendNotifications(post *model.Post, team *model.Team, channel *model.Channel) ([]string, *model.AppError) {
+ mentionedUsersList := make([]string, 0)
+ var fchan store.StoreChannel
+ var senderUsername string
+
+ if post.IsSystemMessage() {
+ senderUsername = utils.T("system.message.name")
+ } else {
+ pchan := Srv.Store.User().GetProfilesInChannel(channel.Id, -1, -1, true)
+ fchan = Srv.Store.FileInfo().GetForPost(post.Id)
+
+ var profileMap map[string]*model.User
+ if result := <-pchan; result.Err != nil {
+ return nil, result.Err
+ } else {
+ profileMap = result.Data.(map[string]*model.User)
+ }
+
+ // If the user who made the post isn't in the channel don't send a notification
+ if _, ok := profileMap[post.UserId]; !ok {
+ l4g.Debug(utils.T("api.post.send_notifications.user_id.debug"), post.Id, channel.Id, post.UserId)
+ return []string{}, nil
+ }
+
+ mentionedUserIds := make(map[string]bool)
+ allActivityPushUserIds := []string{}
+ hereNotification := false
+ channelNotification := false
+ allNotification := false
+ updateMentionChans := []store.StoreChannel{}
+
+ if channel.Type == model.CHANNEL_DIRECT {
+ var otherUserId string
+ if userIds := strings.Split(channel.Name, "__"); userIds[0] == post.UserId {
+ otherUserId = userIds[1]
+ } else {
+ otherUserId = userIds[0]
+ }
+
+ mentionedUserIds[otherUserId] = true
+ if post.Props["from_webhook"] == "true" {
+ mentionedUserIds[post.UserId] = true
+ }
+ } else {
+ keywords := GetMentionKeywordsInChannel(profileMap)
+
+ var potentialOtherMentions []string
+ mentionedUserIds, potentialOtherMentions, hereNotification, channelNotification, allNotification = GetExplicitMentions(post.Message, keywords)
+
+ // get users that have comment thread mentions enabled
+ if len(post.RootId) > 0 {
+ if result := <-Srv.Store.Post().Get(post.RootId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ list := result.Data.(*model.PostList)
+
+ for _, threadPost := range list.Posts {
+ if profile, ok := profileMap[threadPost.UserId]; ok {
+ if profile.NotifyProps["comments"] == "any" || (profile.NotifyProps["comments"] == "root" && threadPost.Id == list.Order[0]) {
+ mentionedUserIds[threadPost.UserId] = true
+ }
+ }
+ }
+ }
+ }
+
+ // prevent the user from mentioning themselves
+ if post.Props["from_webhook"] != "true" {
+ delete(mentionedUserIds, post.UserId)
+ }
+
+ if len(potentialOtherMentions) > 0 {
+ if result := <-Srv.Store.User().GetProfilesByUsernames(potentialOtherMentions, team.Id); result.Err == nil {
+ outOfChannelMentions := result.Data.(map[string]*model.User)
+ go sendOutOfChannelMentions(post, team.Id, outOfChannelMentions)
+ }
+ }
+
+ // find which users in the channel are set up to always receive mobile notifications
+ for _, profile := range profileMap {
+ if profile.NotifyProps["push"] == model.USER_NOTIFY_ALL &&
+ (post.UserId != profile.Id || post.Props["from_webhook"] == "true") {
+ allActivityPushUserIds = append(allActivityPushUserIds, profile.Id)
+ }
+ }
+ }
+
+ mentionedUsersList = make([]string, 0, len(mentionedUserIds))
+ for id := range mentionedUserIds {
+ mentionedUsersList = append(mentionedUsersList, id)
+ updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, id))
+ }
+
+ var sender *model.User
+ senderName := make(map[string]string)
+ for _, id := range mentionedUsersList {
+ senderName[id] = ""
+ if profile, ok := profileMap[post.UserId]; ok {
+ if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" {
+ senderName[id] = value.(string)
+ } else {
+ //Get the Display name preference from the receiver
+ if result := <-Srv.Store.Preference().Get(id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "name_format"); result.Err != nil {
+ // Show default sender's name if user doesn't set display settings.
+ senderName[id] = profile.Username
+ } else {
+ senderName[id] = profile.GetDisplayNameForPreference(result.Data.(model.Preference).Value)
+ }
+ }
+ sender = profile
+ }
+ }
+
+ if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" {
+ senderUsername = value.(string)
+ } else {
+ senderUsername = profileMap[post.UserId].Username
+ }
+
+ if utils.Cfg.EmailSettings.SendEmailNotifications {
+ for _, id := range mentionedUsersList {
+ userAllowsEmails := profileMap[id].NotifyProps["email"] != "false"
+
+ var status *model.Status
+ var err *model.AppError
+ if status, err = GetStatus(id); err != nil {
+ status = &model.Status{
+ UserId: id,
+ Status: model.STATUS_OFFLINE,
+ Manual: false,
+ LastActivityAt: 0,
+ ActiveChannel: "",
+ }
+ }
+
+ if userAllowsEmails && status.Status != model.STATUS_ONLINE && profileMap[id].DeleteAt == 0 {
+ if err := sendNotificationEmail(post, profileMap[id], channel, team, senderName[id], sender); err != nil {
+ l4g.Error(err.Error())
+ }
+ }
+ }
+ }
+
+ T := utils.GetUserTranslations(profileMap[post.UserId].Locale)
+
+ // If the channel has more than 1K users then @here is disabled
+ if hereNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
+ hereNotification = false
+ SendEphemeralPost(
+ team.Id,
+ post.UserId,
+ &model.Post{
+ ChannelId: post.ChannelId,
+ Message: T("api.post.disabled_here", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
+ CreateAt: post.CreateAt + 1,
+ },
+ )
+ }
+
+ // If the channel has more than 1K users then @channel is disabled
+ if channelNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
+ SendEphemeralPost(
+ team.Id,
+ post.UserId,
+ &model.Post{
+ ChannelId: post.ChannelId,
+ Message: T("api.post.disabled_channel", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
+ CreateAt: post.CreateAt + 1,
+ },
+ )
+ }
+
+ // If the channel has more than 1K users then @all is disabled
+ if allNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
+ SendEphemeralPost(
+ team.Id,
+ post.UserId,
+ &model.Post{
+ ChannelId: post.ChannelId,
+ Message: T("api.post.disabled_all", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
+ CreateAt: post.CreateAt + 1,
+ },
+ )
+ }
+
+ if hereNotification {
+ statuses := GetAllStatuses()
+ for _, status := range statuses {
+ if status.UserId == post.UserId {
+ continue
+ }
+
+ _, profileFound := profileMap[status.UserId]
+ _, alreadyMentioned := mentionedUserIds[status.UserId]
+
+ if status.Status == model.STATUS_ONLINE && profileFound && !alreadyMentioned {
+ mentionedUsersList = append(mentionedUsersList, status.UserId)
+ updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, status.UserId))
+ }
+ }
+ }
+
+ // Make sure all mention updates are complete to prevent race
+ // Probably better to batch these DB updates in the future
+ // MUST be completed before push notifications send
+ for _, uchan := range updateMentionChans {
+ if result := <-uchan; result.Err != nil {
+ l4g.Warn(utils.T("api.post.update_mention_count_and_forget.update_error"), post.Id, post.ChannelId, result.Err)
+ }
+ }
+
+ sendPushNotifications := false
+ if *utils.Cfg.EmailSettings.SendPushNotifications {
+ pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
+ if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) {
+ l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn"))
+ sendPushNotifications = false
+ } else {
+ sendPushNotifications = true
+ }
+ }
+
+ if sendPushNotifications {
+ for _, id := range mentionedUsersList {
+ var status *model.Status
+ var err *model.AppError
+ if status, err = GetStatus(id); err != nil {
+ status = &model.Status{id, model.STATUS_OFFLINE, false, 0, ""}
+ }
+
+ if DoesStatusAllowPushNotification(profileMap[id], status, post.ChannelId) {
+ if err := sendPushNotification(post, profileMap[id], channel, senderName[id], true); err != nil {
+ l4g.Error(err.Error())
+ }
+ }
+ }
+
+ for _, id := range allActivityPushUserIds {
+ if _, ok := mentionedUserIds[id]; !ok {
+ var status *model.Status
+ var err *model.AppError
+ if status, err = GetStatus(id); err != nil {
+ status = &model.Status{id, model.STATUS_OFFLINE, false, 0, ""}
+ }
+
+ if DoesStatusAllowPushNotification(profileMap[id], status, post.ChannelId) {
+ if err := sendPushNotification(post, profileMap[id], channel, senderName[id], false); err != nil {
+ l4g.Error(err.Error())
+ }
+ }
+ }
+ }
+ }
+ }
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POSTED, "", post.ChannelId, "", nil)
+ message.Add("post", post.ToJson())
+ message.Add("channel_type", channel.Type)
+ message.Add("channel_display_name", channel.DisplayName)
+ message.Add("channel_name", channel.Name)
+ message.Add("sender_name", senderUsername)
+ message.Add("team_id", team.Id)
+
+ if len(post.FileIds) != 0 && fchan != nil {
+ message.Add("otherFile", "true")
+
+ var infos []*model.FileInfo
+ if result := <-fchan; result.Err != nil {
+ l4g.Warn(utils.T("api.post.send_notifications.files.error"), post.Id, result.Err)
+ } else {
+ infos = result.Data.([]*model.FileInfo)
+ }
+
+ for _, info := range infos {
+ if info.IsImage() {
+ message.Add("image", "true")
+ break
+ }
+ }
+ }
+
+ if len(mentionedUsersList) != 0 {
+ message.Add("mentions", model.ArrayToJson(mentionedUsersList))
+ }
+
+ Publish(message)
+ return mentionedUsersList, nil
+}
+
+func sendNotificationEmail(post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string, sender *model.User) *model.AppError {
+
+ if channel.Type == model.CHANNEL_DIRECT && channel.TeamId != team.Id {
+ // this message is a cross-team DM so it we need to find a team that the recipient is on to use in the link
+ if result := <-Srv.Store.Team().GetTeamsByUserId(user.Id); result.Err != nil {
+ return result.Err
+ } else {
+ // if the recipient isn't in the current user's team, just pick one
+ teams := result.Data.([]*model.Team)
+ found := false
+
+ for i := range teams {
+ if teams[i].Id == team.Id {
+ found = true
+ team = teams[i]
+ break
+ }
+ }
+
+ if !found {
+ if len(teams) > 0 {
+ team = teams[0]
+ } else {
+ // in case the user hasn't joined any teams we send them to the select_team page
+ team = &model.Team{Name: "select_team", DisplayName: utils.Cfg.TeamSettings.SiteName}
+ }
+ }
+ }
+ }
+ if *utils.Cfg.EmailSettings.EnableEmailBatching {
+ var sendBatched bool
+
+ if result := <-Srv.Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_NOTIFICATIONS, model.PREFERENCE_NAME_EMAIL_INTERVAL); result.Err != nil {
+ // if the call fails, assume it hasn't been set and use the default
+ sendBatched = false
+ } else {
+ // default to not using batching if the setting is set to immediate
+ sendBatched = result.Data.(model.Preference).Value != model.PREFERENCE_DEFAULT_EMAIL_INTERVAL
+ }
+
+ if sendBatched {
+ if err := AddNotificationEmailToBatch(user, post, team); err == nil {
+ return nil
+ }
+ }
+
+ // fall back to sending a single email if we can't batch it for some reason
+ }
+
+ var channelName string
+ var bodyText string
+ var subjectText string
+ var mailTemplate string
+ var mailParameters map[string]interface{}
+
+ teamURL := utils.GetSiteURL() + "/" + team.Name
+ tm := time.Unix(post.CreateAt/1000, 0)
+
+ userLocale := utils.GetUserTranslations(user.Locale)
+ month := userLocale(tm.Month().String())
+ day := fmt.Sprintf("%d", tm.Day())
+ year := fmt.Sprintf("%d", tm.Year())
+ zone, _ := tm.Zone()
+
+ if channel.Type == model.CHANNEL_DIRECT {
+ bodyText = userLocale("api.post.send_notifications_and_forget.message_body")
+ subjectText = userLocale("api.post.send_notifications_and_forget.message_subject")
+
+ senderDisplayName := senderName
+
+ mailTemplate = "api.templates.post_subject_in_direct_message"
+ mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
+ "SenderDisplayName": senderDisplayName, "Month": month, "Day": day, "Year": year}
+ } else {
+ bodyText = userLocale("api.post.send_notifications_and_forget.mention_body")
+ subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject")
+ channelName = channel.DisplayName
+ mailTemplate = "api.templates.post_subject_in_channel"
+ mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
+ "ChannelName": channelName, "Month": month, "Day": day, "Year": year}
+ }
+
+ subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, userLocale(mailTemplate, mailParameters))
+
+ bodyPage := utils.NewHTMLTemplate("post_body", user.Locale)
+ bodyPage.Props["SiteURL"] = utils.GetSiteURL()
+ bodyPage.Props["PostMessage"] = GetMessageForNotification(post, userLocale)
+ if team.Name != "select_team" {
+ bodyPage.Props["TeamLink"] = teamURL + "/pl/" + post.Id
+ } else {
+ bodyPage.Props["TeamLink"] = teamURL
+ }
+
+ bodyPage.Props["BodyText"] = bodyText
+ bodyPage.Props["Button"] = userLocale("api.templates.post_body.button")
+ bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info",
+ map[string]interface{}{"ChannelName": channelName, "SenderName": senderName,
+ "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()),
+ "TimeZone": zone, "Month": month, "Day": day}))
+
+ if err := utils.SendMail(user.Email, html.UnescapeString(subject), bodyPage.Render()); err != nil {
+ return err
+ }
+
+ if einterfaces.GetMetricsInterface() != nil {
+ einterfaces.GetMetricsInterface().IncrementPostSentEmail()
+ }
+
+ return nil
+}
+
+func GetMessageForNotification(post *model.Post, translateFunc i18n.TranslateFunc) string {
+ if len(strings.TrimSpace(post.Message)) != 0 || len(post.FileIds) == 0 {
+ return post.Message
+ }
+
+ // extract the filenames from their paths and determine what type of files are attached
+ var infos []*model.FileInfo
+ if result := <-Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil {
+ l4g.Warn(utils.T("api.post.get_message_for_notification.get_files.error"), post.Id, result.Err)
+ } else {
+ infos = result.Data.([]*model.FileInfo)
+ }
+
+ filenames := make([]string, len(infos))
+ onlyImages := true
+ for i, info := range infos {
+ if escaped, err := url.QueryUnescape(filepath.Base(info.Name)); err != nil {
+ // this should never error since filepath was escaped using url.QueryEscape
+ filenames[i] = escaped
+ } else {
+ filenames[i] = info.Name
+ }
+
+ onlyImages = onlyImages && info.IsImage()
+ }
+
+ props := map[string]interface{}{"Filenames": strings.Join(filenames, ", ")}
+
+ if onlyImages {
+ return translateFunc("api.post.get_message_for_notification.images_sent", len(filenames), props)
+ } else {
+ return translateFunc("api.post.get_message_for_notification.files_sent", len(filenames), props)
+ }
+}
+
+func sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, senderName string, wasMentioned bool) *model.AppError {
+ sessions, err := getMobileAppSessions(user.Id)
+ if err != nil {
+ return err
+ }
+
+ var channelName string
+
+ if channel.Type == model.CHANNEL_DIRECT {
+ channelName = senderName
+ } else {
+ channelName = channel.DisplayName
+ }
+
+ userLocale := utils.GetUserTranslations(user.Locale)
+
+ msg := model.PushNotification{}
+ if badge := <-Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil {
+ msg.Badge = 1
+ l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), user.Id, badge.Err)
+ } else {
+ msg.Badge = int(badge.Data.(int64))
+ }
+ msg.Type = model.PUSH_TYPE_MESSAGE
+ msg.TeamId = channel.TeamId
+ msg.ChannelId = channel.Id
+ msg.ChannelName = channel.Name
+
+ if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
+ if channel.Type == model.CHANNEL_DIRECT {
+ msg.Category = model.CATEGORY_DM
+ msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
+ } else {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message)
+ }
+ } else {
+ if channel.Type == model.CHANNEL_DIRECT {
+ msg.Category = model.CATEGORY_DM
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
+ } else if wasMentioned {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
+ } else {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName
+ }
+ }
+
+ l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
+
+ for _, session := range sessions {
+ tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson()))
+ tmpMessage.SetDeviceIdAndPlatform(session.DeviceId)
+ if err := sendToPushProxy(tmpMessage); err != nil {
+ l4g.Error(err.Error)
+ }
+ if einterfaces.GetMetricsInterface() != nil {
+ einterfaces.GetMetricsInterface().IncrementPostSentPush()
+ }
+ }
+
+ return nil
+}
+
+func ClearPushNotification(userId string, channelId string) *model.AppError {
+ sessions, err := getMobileAppSessions(userId)
+ if err != nil {
+ return err
+ }
+
+ msg := model.PushNotification{}
+ msg.Type = model.PUSH_TYPE_CLEAR
+ msg.ChannelId = channelId
+ msg.ContentAvailable = 0
+ if badge := <-Srv.Store.User().GetUnreadCount(userId); badge.Err != nil {
+ msg.Badge = 0
+ l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), userId, badge.Err)
+ } else {
+ msg.Badge = int(badge.Data.(int64))
+ }
+
+ l4g.Debug(utils.T("api.post.send_notifications_and_forget.clear_push_notification.debug"), msg.DeviceId, msg.ChannelId)
+ for _, session := range sessions {
+ tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson()))
+ tmpMessage.SetDeviceIdAndPlatform(session.DeviceId)
+ if err := sendToPushProxy(tmpMessage); err != nil {
+ l4g.Error(err.Error)
+ }
+ }
+
+ return nil
+}
+
+func sendToPushProxy(msg model.PushNotification) *model.AppError {
+ msg.ServerId = utils.CfgDiagnosticId
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ httpClient := &http.Client{Transport: tr}
+ request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
+
+ if resp, err := httpClient.Do(request); err != nil {
+ return model.NewLocAppError("sendToPushProxy", "api.post.send_notifications_and_forget.push_notification.error", map[string]interface{}{"DeviceId": msg.DeviceId, "Error": err.Error()}, "")
+ } else {
+ ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ }
+
+ return nil
+}
+
+func getMobileAppSessions(userId string) ([]*model.Session, *model.AppError) {
+ if result := <-Srv.Store.Session().GetSessionsWithActiveDeviceIds(userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Session), nil
+ }
+}
+
+func sendOutOfChannelMentions(post *model.Post, teamId string, profiles map[string]*model.User) *model.AppError {
+ if len(profiles) == 0 {
+ return nil
+ }
+
+ var usernames []string
+ for _, user := range profiles {
+ usernames = append(usernames, user.Username)
+ }
+ sort.Strings(usernames)
+
+ T := utils.GetUserTranslations(profiles[post.UserId].Locale)
+
+ var message string
+ if len(usernames) == 1 {
+ message = T("api.post.check_for_out_of_channel_mentions.message.one", map[string]interface{}{
+ "Username": usernames[0],
+ })
+ } else {
+ message = T("api.post.check_for_out_of_channel_mentions.message.multiple", map[string]interface{}{
+ "Usernames": strings.Join(usernames[:len(usernames)-1], ", "),
+ "LastUsername": usernames[len(usernames)-1],
+ })
+ }
+
+ SendEphemeralPost(
+ teamId,
+ post.UserId,
+ &model.Post{
+ ChannelId: post.ChannelId,
+ Message: message,
+ CreateAt: post.CreateAt + 1,
+ },
+ )
+
+ return nil
+}
+
+// Given a message and a map mapping mention keywords to the users who use them, returns a map of mentioned
+// users and a slice of potential mention users not in the channel and whether or not @here was mentioned.
+func GetExplicitMentions(message string, keywords map[string][]string) (map[string]bool, []string, bool, bool, bool) {
+ mentioned := make(map[string]bool)
+ potentialOthersMentioned := make([]string, 0)
+ systemMentions := map[string]bool{"@here": true, "@channel": true, "@all": true}
+ hereMentioned := false
+ allMentioned := false
+ channelMentioned := false
+
+ addMentionedUsers := func(ids []string) {
+ for _, id := range ids {
+ mentioned[id] = true
+ }
+ }
+
+ for _, word := range strings.Fields(message) {
+ isMention := false
+
+ if word == "@here" {
+ hereMentioned = true
+ }
+
+ if word == "@channel" {
+ channelMentioned = true
+ }
+
+ if word == "@all" {
+ allMentioned = true
+ }
+
+ // Non-case-sensitive check for regular keys
+ if ids, match := keywords[strings.ToLower(word)]; match {
+ addMentionedUsers(ids)
+ isMention = true
+ }
+
+ // Case-sensitive check for first name
+ if ids, match := keywords[word]; match {
+ addMentionedUsers(ids)
+ isMention = true
+ }
+
+ if !isMention {
+ // No matches were found with the string split just on whitespace so try further splitting
+ // the message on punctuation
+ splitWords := strings.FieldsFunc(word, func(c rune) bool {
+ return model.SplitRunes[c]
+ })
+
+ for _, splitWord := range splitWords {
+ if splitWord == "@here" {
+ hereMentioned = true
+ }
+
+ if splitWord == "@all" {
+ allMentioned = true
+ }
+
+ if splitWord == "@channel" {
+ channelMentioned = true
+ }
+
+ // Non-case-sensitive check for regular keys
+ if ids, match := keywords[strings.ToLower(splitWord)]; match {
+ addMentionedUsers(ids)
+ }
+
+ // Case-sensitive check for first name
+ if ids, match := keywords[splitWord]; match {
+ addMentionedUsers(ids)
+ } else if _, ok := systemMentions[word]; !ok && strings.HasPrefix(word, "@") {
+ username := word[1:len(splitWord)]
+ potentialOthersMentioned = append(potentialOthersMentioned, username)
+ }
+ }
+ }
+ }
+
+ return mentioned, potentialOthersMentioned, hereMentioned, channelMentioned, allMentioned
+}
+
+// Given a map of user IDs to profiles, returns a list of mention
+// keywords for all users in the channel.
+func GetMentionKeywordsInChannel(profiles map[string]*model.User) map[string][]string {
+ keywords := make(map[string][]string)
+
+ for id, profile := range profiles {
+ userMention := "@" + strings.ToLower(profile.Username)
+ keywords[userMention] = append(keywords[userMention], id)
+
+ if len(profile.NotifyProps["mention_keys"]) > 0 {
+ // Add all the user's mention keys
+ splitKeys := strings.Split(profile.NotifyProps["mention_keys"], ",")
+ for _, k := range splitKeys {
+ // note that these are made lower case so that we can do a case insensitive check for them
+ key := strings.ToLower(k)
+ keywords[key] = append(keywords[key], id)
+ }
+ }
+
+ // If turned on, add the user's case sensitive first name
+ if profile.NotifyProps["first_name"] == "true" {
+ keywords[profile.FirstName] = append(keywords[profile.FirstName], profile.Id)
+ }
+
+ // Add @channel and @all to keywords if user has them turned on
+ if int64(len(profiles)) < *utils.Cfg.TeamSettings.MaxNotificationsPerChannel && profile.NotifyProps["channel"] == "true" {
+ keywords["@channel"] = append(keywords["@channel"], profile.Id)
+ keywords["@all"] = append(keywords["@all"], profile.Id)
+ }
+ }
+
+ return keywords
+}
diff --git a/app/notification_test.go b/app/notification_test.go
new file mode 100644
index 000000000..d3aea214c
--- /dev/null
+++ b/app/notification_test.go
@@ -0,0 +1,312 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/model"
+)
+
+func TestSendNotifications(t *testing.T) {
+ th := Setup().InitBasic()
+
+ AddUserToChannel(th.BasicUser2, th.BasicChannel)
+
+ post1, postErr := CreatePost(&model.Post{
+ UserId: th.BasicUser.Id,
+ ChannelId: th.BasicChannel.Id,
+ Message: "@" + th.BasicUser2.Username,
+ }, th.BasicTeam.Id, true)
+
+ if postErr != nil {
+ t.Fatal(postErr)
+ }
+
+ mentions, err := SendNotifications(post1, th.BasicTeam, th.BasicChannel)
+ if err != nil {
+ t.Fatal(err)
+ } else if mentions == nil {
+ t.Log(mentions)
+ t.Fatal("user should have been mentioned")
+ } else if mentions[0] != th.BasicUser2.Id {
+ t.Log(mentions)
+ t.Fatal("user should have been mentioned")
+ }
+}
+
+func TestGetExplicitMentions(t *testing.T) {
+ id1 := model.NewId()
+ id2 := model.NewId()
+
+ // not mentioning anybody
+ message := "this is a message"
+ keywords := map[string][]string{}
+ if mentions, potential, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 0 || len(potential) != 0 {
+ t.Fatal("shouldn't have mentioned anybody or have any potencial mentions")
+ }
+
+ // mentioning a user that doesn't exist
+ message = "this is a message for @user"
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 0 {
+ t.Fatal("shouldn't have mentioned user that doesn't exist")
+ }
+
+ // mentioning one person
+ keywords = map[string][]string{"@user": {id1}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] {
+ t.Fatal("should've mentioned @user")
+ }
+
+ // mentioning one person without an @mention
+ message = "this is a message for @user"
+ keywords = map[string][]string{"this": {id1}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] {
+ t.Fatal("should've mentioned this")
+ }
+
+ // mentioning multiple people with one word
+ message = "this is a message for @user"
+ keywords = map[string][]string{"@user": {id1, id2}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
+ t.Fatal("should've mentioned two users with @user")
+ }
+
+ // mentioning only one of multiple people
+ keywords = map[string][]string{"@user": {id1}, "@mention": {id2}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] || mentions[id2] {
+ t.Fatal("should've mentioned @user and not @mention")
+ }
+
+ // mentioning multiple people with multiple words
+ message = "this is an @mention for @user"
+ keywords = map[string][]string{"@user": {id1}, "@mention": {id2}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
+ t.Fatal("should've mentioned two users with @user and @mention")
+ }
+
+ // mentioning @channel (not a special case, but it's good to double check)
+ message = "this is an message for @channel"
+ keywords = map[string][]string{"@channel": {id1, id2}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
+ t.Fatal("should've mentioned two users with @channel")
+ }
+
+ // mentioning @all (not a special case, but it's good to double check)
+ message = "this is an message for @all"
+ keywords = map[string][]string{"@all": {id1, id2}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 2 || !mentions[id1] || !mentions[id2] {
+ t.Fatal("should've mentioned two users with @all")
+ }
+
+ // mentioning user.period without mentioning user (PLT-3222)
+ message = "user.period doesn't complicate things at all by including periods in their username"
+ keywords = map[string][]string{"user.period": {id1}, "user": {id2}}
+ if mentions, _, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] || mentions[id2] {
+ t.Fatal("should've mentioned user.period and not user")
+ }
+
+ // mentioning a potential out of channel user
+ message = "this is an message for @potential and @user"
+ keywords = map[string][]string{"@user": {id1}}
+ if mentions, potential, _, _, _ := GetExplicitMentions(message, keywords); len(mentions) != 1 || !mentions[id1] || len(potential) != 1 {
+ t.Fatal("should've mentioned user and have a potential not in channel")
+ }
+}
+
+func TestGetExplicitMentionsAtHere(t *testing.T) {
+ // test all the boundary cases that we know can break up terms (and those that we know won't)
+ cases := map[string]bool{
+ "": false,
+ "here": false,
+ "@here": true,
+ " @here ": true,
+ "\t@here\t": true,
+ "\n@here\n": true,
+ // "!@here!": true,
+ // "@@here@": true,
+ // "#@here#": true,
+ // "$@here$": true,
+ // "%@here%": true,
+ // "^@here^": true,
+ // "&@here&": true,
+ // "*@here*": true,
+ "(@here(": true,
+ ")@here)": true,
+ // "-@here-": true,
+ // "_@here_": true,
+ // "=@here=": true,
+ "+@here+": true,
+ "[@here[": true,
+ "{@here{": true,
+ "]@here]": true,
+ "}@here}": true,
+ "\\@here\\": true,
+ // "|@here|": true,
+ ";@here;": true,
+ ":@here:": true,
+ // "'@here'": true,
+ // "\"@here\"": true,
+ ",@here,": true,
+ "<@here<": true,
+ ".@here.": true,
+ ">@here>": true,
+ "/@here/": true,
+ "?@here?": true,
+ // "`@here`": true,
+ // "~@here~": true,
+ }
+
+ for message, shouldMention := range cases {
+ if _, _, hereMentioned, _, _ := GetExplicitMentions(message, nil); hereMentioned && !shouldMention {
+ t.Fatalf("shouldn't have mentioned @here with \"%v\"", message)
+ } else if !hereMentioned && shouldMention {
+ t.Fatalf("should've have mentioned @here with \"%v\"", message)
+ }
+ }
+
+ // mentioning @here and someone
+ id := model.NewId()
+ if mentions, potential, hereMentioned, _, _ := GetExplicitMentions("@here @user @potential", map[string][]string{"@user": {id}}); !hereMentioned {
+ t.Fatal("should've mentioned @here with \"@here @user\"")
+ } else if len(mentions) != 1 || !mentions[id] {
+ t.Fatal("should've mentioned @user with \"@here @user\"")
+ } else if len(potential) > 1 {
+ t.Fatal("should've potential mentions for @potential")
+ }
+}
+
+func TestGetMentionKeywords(t *testing.T) {
+ // user with username or custom mentions enabled
+ user1 := &model.User{
+ Id: model.NewId(),
+ FirstName: "First",
+ Username: "User",
+ NotifyProps: map[string]string{
+ "mention_keys": "User,@User,MENTION",
+ },
+ }
+
+ profiles := map[string]*model.User{user1.Id: user1}
+ mentions := GetMentionKeywordsInChannel(profiles)
+ if len(mentions) != 3 {
+ t.Fatal("should've returned three mention keywords")
+ } else if ids, ok := mentions["user"]; !ok || ids[0] != user1.Id {
+ t.Fatal("should've returned mention key of user")
+ } else if ids, ok := mentions["@user"]; !ok || ids[0] != user1.Id {
+ t.Fatal("should've returned mention key of @user")
+ } else if ids, ok := mentions["mention"]; !ok || ids[0] != user1.Id {
+ t.Fatal("should've returned mention key of mention")
+ }
+
+ // user with first name mention enabled
+ user2 := &model.User{
+ Id: model.NewId(),
+ FirstName: "First",
+ Username: "User",
+ NotifyProps: map[string]string{
+ "first_name": "true",
+ },
+ }
+
+ profiles = map[string]*model.User{user2.Id: user2}
+ mentions = GetMentionKeywordsInChannel(profiles)
+ if len(mentions) != 2 {
+ t.Fatal("should've returned two mention keyword")
+ } else if ids, ok := mentions["First"]; !ok || ids[0] != user2.Id {
+ t.Fatal("should've returned mention key of First")
+ }
+
+ // user with @channel/@all mentions enabled
+ user3 := &model.User{
+ Id: model.NewId(),
+ FirstName: "First",
+ Username: "User",
+ NotifyProps: map[string]string{
+ "channel": "true",
+ },
+ }
+
+ profiles = map[string]*model.User{user3.Id: user3}
+ mentions = GetMentionKeywordsInChannel(profiles)
+ if len(mentions) != 3 {
+ t.Fatal("should've returned three mention keywords")
+ } else if ids, ok := mentions["@channel"]; !ok || ids[0] != user3.Id {
+ t.Fatal("should've returned mention key of @channel")
+ } else if ids, ok := mentions["@all"]; !ok || ids[0] != user3.Id {
+ t.Fatal("should've returned mention key of @all")
+ }
+
+ // user with all types of mentions enabled
+ user4 := &model.User{
+ Id: model.NewId(),
+ FirstName: "First",
+ Username: "User",
+ NotifyProps: map[string]string{
+ "mention_keys": "User,@User,MENTION",
+ "first_name": "true",
+ "channel": "true",
+ },
+ }
+
+ profiles = map[string]*model.User{user4.Id: user4}
+ mentions = GetMentionKeywordsInChannel(profiles)
+ if len(mentions) != 6 {
+ t.Fatal("should've returned six mention keywords")
+ } else if ids, ok := mentions["user"]; !ok || ids[0] != user4.Id {
+ t.Fatal("should've returned mention key of user")
+ } else if ids, ok := mentions["@user"]; !ok || ids[0] != user4.Id {
+ t.Fatal("should've returned mention key of @user")
+ } else if ids, ok := mentions["mention"]; !ok || ids[0] != user4.Id {
+ t.Fatal("should've returned mention key of mention")
+ } else if ids, ok := mentions["First"]; !ok || ids[0] != user4.Id {
+ t.Fatal("should've returned mention key of First")
+ } else if ids, ok := mentions["@channel"]; !ok || ids[0] != user4.Id {
+ t.Fatal("should've returned mention key of @channel")
+ } else if ids, ok := mentions["@all"]; !ok || ids[0] != user4.Id {
+ t.Fatal("should've returned mention key of @all")
+ }
+
+ dup_count := func(list []string) map[string]int {
+
+ duplicate_frequency := make(map[string]int)
+
+ for _, item := range list {
+ // check if the item/element exist in the duplicate_frequency map
+
+ _, exist := duplicate_frequency[item]
+
+ if exist {
+ duplicate_frequency[item] += 1 // increase counter by 1 if already in the map
+ } else {
+ duplicate_frequency[item] = 1 // else start counting from 1
+ }
+ }
+ return duplicate_frequency
+ }
+
+ // multiple users
+ profiles = map[string]*model.User{
+ user1.Id: user1,
+ user2.Id: user2,
+ user3.Id: user3,
+ user4.Id: user4,
+ }
+ mentions = GetMentionKeywordsInChannel(profiles)
+ if len(mentions) != 6 {
+ t.Fatal("should've returned six mention keywords")
+ } else if ids, ok := mentions["user"]; !ok || len(ids) != 2 || (ids[0] != user1.Id && ids[1] != user1.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
+ t.Fatal("should've mentioned user1 and user4 with user")
+ } else if ids := dup_count(mentions["@user"]); len(ids) != 4 || (ids[user1.Id] != 2) || (ids[user4.Id] != 2) {
+ t.Fatal("should've mentioned user1 and user4 with @user")
+ } else if ids, ok := mentions["mention"]; !ok || len(ids) != 2 || (ids[0] != user1.Id && ids[1] != user1.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
+ t.Fatal("should've mentioned user1 and user4 with mention")
+ } else if ids, ok := mentions["First"]; !ok || len(ids) != 2 || (ids[0] != user2.Id && ids[1] != user2.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
+ t.Fatal("should've mentioned user2 and user4 with mention")
+ } else if ids, ok := mentions["@channel"]; !ok || len(ids) != 2 || (ids[0] != user3.Id && ids[1] != user3.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
+ t.Fatal("should've mentioned user3 and user4 with @channel")
+ } else if ids, ok := mentions["@all"]; !ok || len(ids) != 2 || (ids[0] != user3.Id && ids[1] != user3.Id) || (ids[0] != user4.Id && ids[1] != user4.Id) {
+ t.Fatal("should've mentioned user3 and user4 with @all")
+ }
+}
diff --git a/app/post.go b/app/post.go
new file mode 100644
index 000000000..7eebe905f
--- /dev/null
+++ b/app/post.go
@@ -0,0 +1,196 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "regexp"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
+)
+
+func CreatePost(post *model.Post, teamId string, triggerWebhooks bool) (*model.Post, *model.AppError) {
+ var pchan store.StoreChannel
+ if len(post.RootId) > 0 {
+ pchan = Srv.Store.Post().Get(post.RootId)
+ }
+
+ // Verify the parent/child relationships are correct
+ if pchan != nil {
+ if presult := <-pchan; presult.Err != nil {
+ return nil, model.NewLocAppError("createPost", "api.post.create_post.root_id.app_error", nil, "")
+ } else {
+ list := presult.Data.(*model.PostList)
+ if len(list.Posts) == 0 || !list.IsChannelId(post.ChannelId) {
+ return nil, model.NewLocAppError("createPost", "api.post.create_post.channel_root_id.app_error", nil, "")
+ }
+
+ if post.ParentId == "" {
+ post.ParentId = post.RootId
+ }
+
+ if post.RootId != post.ParentId {
+ parent := list.Posts[post.ParentId]
+ if parent == nil {
+ return nil, model.NewLocAppError("createPost", "api.post.create_post.parent_id.app_error", nil, "")
+ }
+ }
+ }
+ }
+
+ post.Hashtags, _ = model.ParseHashtags(post.Message)
+
+ var rpost *model.Post
+ if result := <-Srv.Store.Post().Save(post); result.Err != nil {
+ return nil, result.Err
+ } else {
+ rpost = result.Data.(*model.Post)
+ }
+
+ if einterfaces.GetMetricsInterface() != nil {
+ einterfaces.GetMetricsInterface().IncrementPostCreate()
+ }
+
+ if len(post.FileIds) > 0 {
+ // There's a rare bug where the client sends up duplicate FileIds so protect against that
+ post.FileIds = utils.RemoveDuplicatesFromStringArray(post.FileIds)
+
+ for _, fileId := range post.FileIds {
+ if result := <-Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
+ l4g.Error(utils.T("api.post.create_post.attach_files.error"), post.Id, post.FileIds, post.UserId, result.Err)
+ }
+ }
+
+ if einterfaces.GetMetricsInterface() != nil {
+ einterfaces.GetMetricsInterface().IncrementPostFileAttachment(len(post.FileIds))
+ }
+ }
+
+ InvalidateCacheForChannel(rpost.ChannelId)
+ InvalidateCacheForChannelPosts(rpost.ChannelId)
+
+ if err := handlePostEvents(rpost, teamId, triggerWebhooks); err != nil {
+ return nil, err
+ }
+
+ return rpost, nil
+}
+
+func handlePostEvents(post *model.Post, teamId string, triggerWebhooks bool) *model.AppError {
+ tchan := Srv.Store.Team().Get(teamId)
+ cchan := Srv.Store.Channel().Get(post.ChannelId, true)
+ uchan := Srv.Store.User().Get(post.UserId)
+
+ var team *model.Team
+ if result := <-tchan; result.Err != nil {
+ return result.Err
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ var channel *model.Channel
+ if result := <-cchan; result.Err != nil {
+ return result.Err
+ } else {
+ channel = result.Data.(*model.Channel)
+ }
+
+ if _, err := SendNotifications(post, team, channel); err != nil {
+ return err
+ }
+
+ var user *model.User
+ if result := <-uchan; result.Err != nil {
+ return result.Err
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ if triggerWebhooks {
+ go func() {
+ if err := handleWebhookEvents(post, team, channel, user); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+ }
+
+ if channel.Type == model.CHANNEL_DIRECT {
+ go func() {
+ if err := MakeDirectChannelVisible(post.ChannelId); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+ }
+
+ return nil
+}
+
+var linkWithTextRegex *regexp.Regexp = regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
+
+// This method only parses and processes the attachments,
+// all else should be set in the post which is passed
+func parseSlackAttachment(post *model.Post, attachments interface{}) {
+ post.Type = model.POST_SLACK_ATTACHMENT
+
+ if list, success := attachments.([]interface{}); success {
+ for i, aInt := range list {
+ attachment := aInt.(map[string]interface{})
+ if aText, ok := attachment["text"].(string); ok {
+ aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
+ attachment["text"] = aText
+ list[i] = attachment
+ }
+ if aText, ok := attachment["pretext"].(string); ok {
+ aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
+ attachment["pretext"] = aText
+ list[i] = attachment
+ }
+ if fVal, ok := attachment["fields"]; ok {
+ if fields, ok := fVal.([]interface{}); ok {
+ // parse attachment field links into Markdown format
+ for j, fInt := range fields {
+ field := fInt.(map[string]interface{})
+ if fValue, ok := field["value"].(string); ok {
+ fValue = linkWithTextRegex.ReplaceAllString(fValue, "[${2}](${1})")
+ field["value"] = fValue
+ fields[j] = field
+ }
+ }
+ attachment["fields"] = fields
+ list[i] = attachment
+ }
+ }
+ }
+ post.AddProp("attachments", list)
+ }
+}
+
+func parseSlackLinksToMarkdown(text string) string {
+ return linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})")
+}
+
+func SendEphemeralPost(teamId, userId string, post *model.Post) *model.Post {
+ post.Type = model.POST_EPHEMERAL
+
+ // fill in fields which haven't been specified which have sensible defaults
+ if post.Id == "" {
+ post.Id = model.NewId()
+ }
+ if post.CreateAt == 0 {
+ post.CreateAt = model.GetMillis()
+ }
+ if post.Props == nil {
+ post.Props = model.StringInterface{}
+ }
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE, "", post.ChannelId, userId, nil)
+ message.Add("post", post.ToJson())
+
+ go Publish(message)
+
+ return post
+}
diff --git a/api/server.go b/app/server.go
index 2698f159c..972c91ea3 100644
--- a/api/server.go
+++ b/app/server.go
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package api
+package app
import (
"crypto/tls"
@@ -23,15 +23,50 @@ import (
)
type Server struct {
- Store store.Store
- Router *mux.Router
- GracefulServer *graceful.Server
+ Store store.Store
+ WebSocketRouter *WebSocketRouter
+ Router *mux.Router
+ GracefulServer *graceful.Server
+}
+
+var allowedMethods []string = []string{
+ "POST",
+ "GET",
+ "OPTIONS",
+ "PUT",
+ "PATCH",
+ "DELETE",
}
type CorsWrapper struct {
router *mux.Router
}
+func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if len(*utils.Cfg.ServiceSettings.AllowCorsFrom) > 0 {
+ origin := r.Header.Get("Origin")
+ if *utils.Cfg.ServiceSettings.AllowCorsFrom == "*" || strings.Contains(*utils.Cfg.ServiceSettings.AllowCorsFrom, origin) {
+ w.Header().Set("Access-Control-Allow-Origin", origin)
+
+ if r.Method == "OPTIONS" {
+ w.Header().Set(
+ "Access-Control-Allow-Methods",
+ strings.Join(allowedMethods, ", "))
+
+ w.Header().Set(
+ "Access-Control-Allow-Headers",
+ r.Header.Get("Access-Control-Request-Headers"))
+ }
+ }
+ }
+
+ if r.Method == "OPTIONS" {
+ return
+ }
+
+ cw.router.ServeHTTP(w, r)
+}
+
const TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN = time.Second
var Srv *Server
@@ -46,15 +81,10 @@ func InitStores() {
Srv.Store = store.NewSqlStore()
}
-func InitRouter() {
- Srv.Router = mux.NewRouter()
- Srv.Router.NotFoundHandler = http.HandlerFunc(Handle404)
-}
-
type VaryBy struct{}
func (m *VaryBy) Key(r *http.Request) string {
- return GetIpAddress(r)
+ return utils.GetIpAddress(r)
}
func initalizeThrottledVaryBy() *throttled.VaryBy {
@@ -116,7 +146,7 @@ func StartServer() {
RateLimiter: rateLimiter,
VaryBy: &VaryBy{},
DeniedHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- l4g.Error("%v: Denied due to throttling settings code=429 ip=%v", r.URL.Path, GetIpAddress(r))
+ l4g.Error("%v: Denied due to throttling settings code=429 ip=%v", r.URL.Path, utils.GetIpAddress(r))
throttled.DefaultDeniedHandler.ServeHTTP(w, r)
}),
}
diff --git a/app/session.go b/app/session.go
new file mode 100644
index 000000000..29c961e81
--- /dev/null
+++ b/app/session.go
@@ -0,0 +1,94 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
+
+ l4g "github.com/alecthomas/log4go"
+)
+
+var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE)
+
+func GetSession(token string) (*model.Session, *model.AppError) {
+ metrics := einterfaces.GetMetricsInterface()
+
+ var session *model.Session
+ if ts, ok := sessionCache.Get(token); ok {
+ session = ts.(*model.Session)
+ if metrics != nil {
+ metrics.IncrementMemCacheHitCounter("Session")
+ }
+ } else {
+ if metrics != nil {
+ metrics.IncrementMemCacheMissCounter("Session")
+ }
+ }
+
+ if session == nil {
+ if sessionResult := <-Srv.Store.Session().Get(token); sessionResult.Err != nil {
+ return nil, model.NewLocAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": sessionResult.Err.DetailedError}, "")
+ } else {
+ session = sessionResult.Data.(*model.Session)
+
+ if session.IsExpired() || session.Token != token {
+ return nil, model.NewLocAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": sessionResult.Err.DetailedError}, "")
+ } else {
+ AddSessionToCache(session)
+ return session, nil
+ }
+ }
+ }
+
+ if session == nil || session.IsExpired() {
+ return nil, model.NewLocAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token}, "")
+ }
+
+ return session, nil
+}
+
+func RemoveAllSessionsForUserId(userId string) {
+
+ RemoveAllSessionsForUserIdSkipClusterSend(userId)
+
+ if einterfaces.GetClusterInterface() != nil {
+ einterfaces.GetClusterInterface().RemoveAllSessionsForUserId(userId)
+ }
+}
+
+func RemoveAllSessionsForUserIdSkipClusterSend(userId string) {
+ keys := sessionCache.Keys()
+
+ for _, key := range keys {
+ if ts, ok := sessionCache.Get(key); ok {
+ session := ts.(*model.Session)
+ if session.UserId == userId {
+ sessionCache.Remove(key)
+ }
+ }
+ }
+
+ InvalidateWebConnSessionCacheForUser(userId)
+
+}
+
+func AddSessionToCache(session *model.Session) {
+ sessionCache.AddWithExpiresInSecs(session.Token, session, int64(*utils.Cfg.ServiceSettings.SessionCacheInMinutes*60))
+}
+
+func InvalidateAllCaches() {
+ l4g.Info(utils.T("api.context.invalidate_all_caches"))
+ sessionCache.Purge()
+ ClearStatusCache()
+ store.ClearChannelCaches()
+ store.ClearUserCaches()
+ store.ClearPostCaches()
+}
+
+func SessionCacheLength() int {
+ return sessionCache.Len()
+}
diff --git a/app/session_test.go b/app/session_test.go
new file mode 100644
index 000000000..352395c76
--- /dev/null
+++ b/app/session_test.go
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "github.com/mattermost/platform/model"
+ "testing"
+)
+
+func TestCache(t *testing.T) {
+ session := &model.Session{
+ Id: model.NewId(),
+ Token: model.NewId(),
+ UserId: model.NewId(),
+ }
+
+ sessionCache.AddWithExpiresInSecs(session.Token, session, 5*60)
+
+ keys := sessionCache.Keys()
+ if len(keys) <= 0 {
+ t.Fatal("should have items")
+ }
+
+ RemoveAllSessionsForUserId(session.UserId)
+
+ rkeys := sessionCache.Keys()
+ if len(rkeys) != len(keys)-1 {
+ t.Fatal("should have one less")
+ }
+}
diff --git a/app/status.go b/app/status.go
new file mode 100644
index 000000000..98cdb0dc0
--- /dev/null
+++ b/app/status.go
@@ -0,0 +1,255 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ l4g "github.com/alecthomas/log4go"
+
+ "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
+)
+
+var statusCache *utils.Cache = utils.NewLru(model.STATUS_CACHE_SIZE)
+
+func ClearStatusCache() {
+ statusCache.Purge()
+}
+
+func AddStatusCacheSkipClusterSend(status *model.Status) {
+ statusCache.Add(status.UserId, status)
+}
+
+func AddStatusCache(status *model.Status) {
+ AddStatusCacheSkipClusterSend(status)
+
+ if einterfaces.GetClusterInterface() != nil {
+ einterfaces.GetClusterInterface().UpdateStatus(status)
+ }
+}
+
+func GetAllStatuses() map[string]*model.Status {
+ userIds := statusCache.Keys()
+ statusMap := map[string]*model.Status{}
+
+ for _, userId := range userIds {
+ if id, ok := userId.(string); !ok {
+ continue
+ } else {
+ status := GetStatusFromCache(id)
+ if status != nil {
+ statusMap[id] = status
+ }
+ }
+ }
+
+ return statusMap
+}
+
+func GetStatusesByIds(userIds []string) (map[string]interface{}, *model.AppError) {
+ statusMap := map[string]interface{}{}
+ metrics := einterfaces.GetMetricsInterface()
+
+ missingUserIds := []string{}
+ for _, userId := range userIds {
+ if result, ok := statusCache.Get(userId); ok {
+ statusMap[userId] = result.(*model.Status).Status
+ if metrics != nil {
+ metrics.IncrementMemCacheHitCounter("Status")
+ }
+ } else {
+ missingUserIds = append(missingUserIds, userId)
+ if metrics != nil {
+ metrics.IncrementMemCacheMissCounter("Status")
+ }
+ }
+ }
+
+ if len(missingUserIds) > 0 {
+ if result := <-Srv.Store.Status().GetByIds(missingUserIds); result.Err != nil {
+ return nil, result.Err
+ } else {
+ statuses := result.Data.([]*model.Status)
+
+ for _, s := range statuses {
+ AddStatusCache(s)
+ statusMap[s.UserId] = s.Status
+ }
+ }
+ }
+
+ // For the case where the user does not have a row in the Status table and cache
+ for _, userId := range missingUserIds {
+ if _, ok := statusMap[userId]; !ok {
+ statusMap[userId] = model.STATUS_OFFLINE
+ }
+ }
+
+ return statusMap, nil
+}
+
+func SetStatusOnline(userId string, sessionId string, manual bool) {
+ broadcast := false
+
+ var oldStatus string = model.STATUS_OFFLINE
+ var oldTime int64 = 0
+ var oldManual bool = false
+ var status *model.Status
+ var err *model.AppError
+
+ if status, err = GetStatus(userId); err != nil {
+ status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), ""}
+ broadcast = true
+ } else {
+ if status.Manual && !manual {
+ return // manually set status always overrides non-manual one
+ }
+
+ if status.Status != model.STATUS_ONLINE {
+ broadcast = true
+ }
+
+ oldStatus = status.Status
+ oldTime = status.LastActivityAt
+ oldManual = status.Manual
+
+ status.Status = model.STATUS_ONLINE
+ status.Manual = false // for "online" there's no manual setting
+ status.LastActivityAt = model.GetMillis()
+ }
+
+ AddStatusCache(status)
+
+ // Only update the database if the status has changed, the status has been manually set,
+ // or enough time has passed since the previous action
+ if status.Status != oldStatus || status.Manual != oldManual || status.LastActivityAt-oldTime > model.STATUS_MIN_UPDATE_TIME {
+ achan := Srv.Store.Session().UpdateLastActivityAt(sessionId, status.LastActivityAt)
+
+ var schan store.StoreChannel
+ if broadcast {
+ schan = Srv.Store.Status().SaveOrUpdate(status)
+ } else {
+ schan = Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt)
+ }
+
+ if result := <-achan; result.Err != nil {
+ l4g.Error(utils.T("api.status.last_activity.error"), userId, sessionId, result.Err)
+ }
+
+ if result := <-schan; result.Err != nil {
+ l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err)
+ }
+ }
+
+ if broadcast {
+ event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil)
+ event.Add("status", model.STATUS_ONLINE)
+ event.Add("user_id", status.UserId)
+ go Publish(event)
+ }
+}
+
+func SetStatusOffline(userId string, manual bool) {
+ status, err := GetStatus(userId)
+ if err == nil && status.Manual && !manual {
+ return // manually set status always overrides non-manual one
+ }
+
+ status = &model.Status{userId, model.STATUS_OFFLINE, manual, model.GetMillis(), ""}
+
+ AddStatusCache(status)
+
+ if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil {
+ l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err)
+ }
+
+ event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil)
+ event.Add("status", model.STATUS_OFFLINE)
+ event.Add("user_id", status.UserId)
+ go Publish(event)
+}
+
+func SetStatusAwayIfNeeded(userId string, manual bool) {
+ status, err := GetStatus(userId)
+
+ if err != nil {
+ status = &model.Status{userId, model.STATUS_OFFLINE, manual, 0, ""}
+ }
+
+ if !manual && status.Manual {
+ return // manually set status always overrides non-manual one
+ }
+
+ if !manual {
+ if status.Status == model.STATUS_AWAY {
+ return
+ }
+
+ if !IsUserAway(status.LastActivityAt) {
+ return
+ }
+ }
+
+ status.Status = model.STATUS_AWAY
+ status.Manual = manual
+ status.ActiveChannel = ""
+
+ AddStatusCache(status)
+
+ if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil {
+ l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err)
+ }
+
+ event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil)
+ event.Add("status", model.STATUS_AWAY)
+ event.Add("user_id", status.UserId)
+ go Publish(event)
+}
+
+func GetStatusFromCache(userId string) *model.Status {
+ if result, ok := statusCache.Get(userId); ok {
+ status := result.(*model.Status)
+ statusCopy := &model.Status{}
+ *statusCopy = *status
+ return statusCopy
+ }
+
+ return nil
+}
+
+func GetStatus(userId string) (*model.Status, *model.AppError) {
+ status := GetStatusFromCache(userId)
+ if status != nil {
+ return status, nil
+ }
+
+ if result := <-Srv.Store.Status().Get(userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Status), nil
+ }
+}
+
+func IsUserAway(lastActivityAt int64) bool {
+ return model.GetMillis()-lastActivityAt >= *utils.Cfg.TeamSettings.UserStatusAwayTimeout*1000
+}
+
+func DoesStatusAllowPushNotification(user *model.User, status *model.Status, channelId string) bool {
+ props := user.NotifyProps
+
+ if props["push"] == "none" {
+ return false
+ }
+
+ if pushStatus, ok := props["push_status"]; (pushStatus == model.STATUS_ONLINE || !ok) && (status.ActiveChannel != channelId || model.GetMillis()-status.LastActivityAt > model.STATUS_CHANNEL_TIMEOUT) {
+ return true
+ } else if pushStatus == model.STATUS_AWAY && (status.Status == model.STATUS_AWAY || status.Status == model.STATUS_OFFLINE) {
+ return true
+ } else if pushStatus == model.STATUS_OFFLINE && status.Status == model.STATUS_OFFLINE {
+ return true
+ }
+
+ return false
+}
diff --git a/app/team.go b/app/team.go
new file mode 100644
index 000000000..98b6894a5
--- /dev/null
+++ b/app/team.go
@@ -0,0 +1,82 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ l4g "github.com/alecthomas/log4go"
+
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func CreateTeam(team *model.Team) (*model.Team, *model.AppError) {
+ if result := <-Srv.Store.Team().Save(team); result.Err != nil {
+ return nil, result.Err
+ } else {
+ rteam := result.Data.(*model.Team)
+
+ if _, err := CreateDefaultChannels(rteam.Id); err != nil {
+ return nil, err
+ }
+
+ return rteam, nil
+ }
+}
+
+func JoinUserToTeamById(teamId string, user *model.User) *model.AppError {
+ if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
+ return result.Err
+ } else {
+ return JoinUserToTeam(result.Data.(*model.Team), user)
+ }
+}
+
+func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
+
+ tm := &model.TeamMember{
+ TeamId: team.Id,
+ UserId: user.Id,
+ Roles: model.ROLE_TEAM_USER.Id,
+ }
+
+ channelRole := model.ROLE_CHANNEL_USER.Id
+
+ if team.Email == user.Email {
+ tm.Roles = model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id
+ channelRole = model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id
+ }
+
+ if etmr := <-Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil {
+ // Membership alredy exists. Check if deleted and and update, otherwise do nothing
+ rtm := etmr.Data.(model.TeamMember)
+
+ // Do nothing if already added
+ if rtm.DeleteAt == 0 {
+ return nil
+ }
+
+ if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
+ return tmr.Err
+ }
+ } else {
+ // Membership appears to be missing. Lets try to add.
+ if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil {
+ return tmr.Err
+ }
+ }
+
+ if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
+ return uua.Err
+ }
+
+ // Soft error if there is an issue joining the default channels
+ if err := JoinDefaultChannels(team.Id, user, channelRole); err != nil {
+ l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err)
+ }
+
+ RemoveAllSessionsForUserId(user.Id)
+ InvalidateCacheForUser(user.Id)
+
+ return nil
+}
diff --git a/app/user.go b/app/user.go
new file mode 100644
index 000000000..5acd9dcaa
--- /dev/null
+++ b/app/user.go
@@ -0,0 +1,60 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func CreateUser(user *model.User) (*model.User, *model.AppError) {
+
+ user.Roles = model.ROLE_SYSTEM_USER.Id
+
+ // Below is a special case where the first user in the entire
+ // system is granted the system_admin role
+ if result := <-Srv.Store.User().GetTotalUsersCount(); result.Err != nil {
+ return nil, result.Err
+ } else {
+ count := result.Data.(int64)
+ if count <= 0 {
+ user.Roles = model.ROLE_SYSTEM_ADMIN.Id + " " + model.ROLE_SYSTEM_USER.Id
+ }
+ }
+
+ user.MakeNonNil()
+ user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
+
+ if err := utils.IsPasswordValid(user.Password); user.AuthService == "" && err != nil {
+ return nil, err
+ }
+
+ if result := <-Srv.Store.User().Save(user); result.Err != nil {
+ l4g.Error(utils.T("api.user.create_user.save.error"), result.Err)
+ return nil, result.Err
+ } else {
+ ruser := result.Data.(*model.User)
+
+ if user.EmailVerified {
+ if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
+ l4g.Error(utils.T("api.user.create_user.verified.error"), cresult.Err)
+ }
+ }
+
+ pref := model.Preference{UserId: ruser.Id, Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, Name: ruser.Id, Value: "0"}
+ if presult := <-Srv.Store.Preference().Save(&model.Preferences{pref}); presult.Err != nil {
+ l4g.Error(utils.T("api.user.create_user.tutorial.error"), presult.Err.Message)
+ }
+
+ ruser.Sanitize(map[string]bool{})
+
+ // This message goes to everyone, so the teamId, channelId and userId are irrelevant
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil)
+ message.Add("user_id", ruser.Id)
+ go Publish(message)
+
+ return ruser, nil
+ }
+}
diff --git a/api/web_conn.go b/app/web_conn.go
index 2f5036922..02c3b2642 100644
--- a/api/web_conn.go
+++ b/app/web_conn.go
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package api
+package app
import (
"fmt"
@@ -35,32 +35,32 @@ type WebConn struct {
LastAllChannelMembersTime int64
}
-func NewWebConn(c *Context, ws *websocket.Conn) *WebConn {
- if len(c.Session.UserId) > 0 {
- go SetStatusOnline(c.Session.UserId, c.Session.Id, false)
+func NewWebConn(ws *websocket.Conn, session model.Session, t goi18n.TranslateFunc, locale string) *WebConn {
+ if len(session.UserId) > 0 {
+ go SetStatusOnline(session.UserId, session.Id, false)
}
return &WebConn{
Send: make(chan model.WebSocketMessage, 256),
WebSocket: ws,
- UserId: c.Session.UserId,
- SessionToken: c.Session.Token,
- SessionExpiresAt: c.Session.ExpiresAt,
- T: c.T,
- Locale: c.Locale,
+ UserId: session.UserId,
+ SessionToken: session.Token,
+ SessionExpiresAt: session.ExpiresAt,
+ T: t,
+ Locale: locale,
}
}
-func (c *WebConn) readPump() {
+func (c *WebConn) ReadPump() {
defer func() {
HubUnregister(c)
c.WebSocket.Close()
}()
- c.WebSocket.SetReadLimit(SOCKET_MAX_MESSAGE_SIZE_KB)
+ c.WebSocket.SetReadLimit(model.SOCKET_MAX_MESSAGE_SIZE_KB)
c.WebSocket.SetReadDeadline(time.Now().Add(PONG_WAIT))
c.WebSocket.SetPongHandler(func(string) error {
c.WebSocket.SetReadDeadline(time.Now().Add(PONG_WAIT))
- if c.isAuthenticated() {
+ if c.IsAuthenticated() {
go SetStatusAwayIfNeeded(c.UserId, false)
}
return nil
@@ -78,12 +78,12 @@ func (c *WebConn) readPump() {
return
} else {
- BaseRoutes.WebSocket.ServeWebSocket(c, &req)
+ Srv.WebSocketRouter.ServeWebSocket(c, &req)
}
}
}
-func (c *WebConn) writePump() {
+func (c *WebConn) WritePump() {
ticker := time.NewTicker(PING_PERIOD)
authTicker := time.NewTicker(AUTH_TIMEOUT)
@@ -149,15 +149,16 @@ func (webCon *WebConn) InvalidateCache() {
webCon.SessionExpiresAt = 0
}
-func (webCon *WebConn) isAuthenticated() bool {
+func (webCon *WebConn) IsAuthenticated() bool {
// Check the expiry to see if we need to check for a new session
if webCon.SessionExpiresAt < model.GetMillis() {
if webCon.SessionToken == "" {
return false
}
- session := GetSession(webCon.SessionToken)
- if session == nil || session.IsExpired() {
+ session, err := GetSession(webCon.SessionToken)
+ if err != nil {
+ l4g.Error(utils.T("api.websocket.invalid_session.error"), err.Error())
webCon.SessionToken = ""
webCon.SessionExpiresAt = 0
return false
@@ -179,7 +180,7 @@ func (webCon *WebConn) SendHello() {
func (webCon *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool {
// IMPORTANT: Do not send event if WebConn does not have a session
- if !webCon.isAuthenticated() {
+ if !webCon.IsAuthenticated() {
return false
}
@@ -237,8 +238,9 @@ func (webCon *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool {
}
func (webCon *WebConn) IsMemberOfTeam(teamId string) bool {
- session := GetSession(webCon.SessionToken)
- if session == nil {
+ session, err := GetSession(webCon.SessionToken)
+ if err != nil {
+ l4g.Error(utils.T("api.websocket.invalid_session.error"), err.Error())
return false
} else {
member := session.GetTeamByTeamId(teamId)
diff --git a/api/web_hub.go b/app/web_hub.go
index 076236dfb..28d2c0095 100644
--- a/api/web_hub.go
+++ b/app/web_hub.go
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package api
+package app
import (
"fmt"
@@ -156,7 +156,7 @@ func InvalidateWebConnSessionCacheForUser(userId string) {
func (h *Hub) Register(webConn *WebConn) {
h.register <- webConn
- if webConn.isAuthenticated() {
+ if webConn.IsAuthenticated() {
webConn.SendHello()
}
}
diff --git a/app/webhook.go b/app/webhook.go
new file mode 100644
index 000000000..dfd59349f
--- /dev/null
+++ b/app/webhook.go
@@ -0,0 +1,155 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "crypto/tls"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strings"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+const (
+ TRIGGERWORDS_FULL = 0
+ TRIGGERWORDS_STARTSWITH = 1
+)
+
+func handleWebhookEvents(post *model.Post, team *model.Team, channel *model.Channel, user *model.User) *model.AppError {
+ if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
+ return nil
+ }
+
+ if channel.Type != model.CHANNEL_OPEN {
+ return nil
+ }
+
+ hchan := Srv.Store.Webhook().GetOutgoingByTeam(team.Id)
+ result := <-hchan
+ if result.Err != nil {
+ return result.Err
+ }
+
+ hooks := result.Data.([]*model.OutgoingWebhook)
+ if len(hooks) == 0 {
+ return nil
+ }
+
+ splitWords := strings.Fields(post.Message)
+ if len(splitWords) == 0 {
+ return nil
+ }
+ firstWord := splitWords[0]
+
+ relevantHooks := []*model.OutgoingWebhook{}
+ for _, hook := range hooks {
+ if hook.ChannelId == post.ChannelId || len(hook.ChannelId) == 0 {
+ if hook.ChannelId == post.ChannelId && len(hook.TriggerWords) == 0 {
+ relevantHooks = append(relevantHooks, hook)
+ } else if hook.TriggerWhen == TRIGGERWORDS_FULL && hook.HasTriggerWord(firstWord) {
+ relevantHooks = append(relevantHooks, hook)
+ } else if hook.TriggerWhen == TRIGGERWORDS_STARTSWITH && hook.TriggerWordStartsWith(firstWord) {
+ relevantHooks = append(relevantHooks, hook)
+ }
+ }
+ }
+
+ for _, hook := range relevantHooks {
+ go func(hook *model.OutgoingWebhook) {
+ payload := &model.OutgoingWebhookPayload{
+ Token: hook.Token,
+ TeamId: hook.TeamId,
+ TeamDomain: team.Name,
+ ChannelId: post.ChannelId,
+ ChannelName: channel.Name,
+ Timestamp: post.CreateAt,
+ UserId: post.UserId,
+ UserName: user.Username,
+ PostId: post.Id,
+ Text: post.Message,
+ TriggerWord: firstWord,
+ }
+ var body io.Reader
+ var contentType string
+ if hook.ContentType == "application/json" {
+ body = strings.NewReader(payload.ToJSON())
+ contentType = "application/json"
+ } else {
+ body = strings.NewReader(payload.ToFormValues())
+ contentType = "application/x-www-form-urlencoded"
+ }
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ client := &http.Client{Transport: tr}
+
+ for _, url := range hook.CallbackURLs {
+ go func(url string) {
+ req, _ := http.NewRequest("POST", url, body)
+ req.Header.Set("Content-Type", contentType)
+ req.Header.Set("Accept", "application/json")
+ if resp, err := client.Do(req); err != nil {
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.event_post.error"), err.Error())
+ } else {
+ defer func() {
+ ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ }()
+ respProps := model.MapFromJson(resp.Body)
+
+ if text, ok := respProps["text"]; ok {
+ if _, err := CreateWebhookPost(hook.CreatorId, hook.TeamId, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil {
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.create_post.error"), err)
+ }
+ }
+ }
+ }(url)
+ }
+
+ }(hook)
+ }
+
+ return nil
+}
+
+func CreateWebhookPost(userId, teamId, channelId, text, overrideUsername, overrideIconUrl string, props model.StringInterface, postType string) (*model.Post, *model.AppError) {
+ post := &model.Post{UserId: userId, ChannelId: channelId, Message: text, Type: postType}
+ post.AddProp("from_webhook", "true")
+
+ if utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
+ if len(overrideUsername) != 0 {
+ post.AddProp("override_username", overrideUsername)
+ } else {
+ post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
+ }
+ }
+
+ if utils.Cfg.ServiceSettings.EnablePostIconOverride {
+ if len(overrideIconUrl) != 0 {
+ post.AddProp("override_icon_url", overrideIconUrl)
+ }
+ }
+
+ post.Message = parseSlackLinksToMarkdown(post.Message)
+
+ if len(props) > 0 {
+ for key, val := range props {
+ if key == "attachments" {
+ parseSlackAttachment(post, val)
+ } else if key != "override_icon_url" && key != "override_username" && key != "from_webhook" {
+ post.AddProp(key, val)
+ }
+ }
+ }
+
+ if _, err := CreatePost(post, teamId, false); err != nil {
+ return nil, model.NewLocAppError("CreateWebhookPost", "api.post.create_webhook_post.creating.app_error", nil, "err="+err.Message)
+ }
+
+ return post, nil
+}
diff --git a/api/websocket_router.go b/app/websocket_router.go
index 989d41373..984b9d17e 100644
--- a/api/websocket_router.go
+++ b/app/websocket_router.go
@@ -1,7 +1,7 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-package api
+package app
import (
l4g "github.com/alecthomas/log4go"
@@ -10,30 +10,34 @@ import (
"github.com/mattermost/platform/utils"
)
+type webSocketHandler interface {
+ ServeWebSocket(*WebConn, *model.WebSocketRequest)
+}
+
type WebSocketRouter struct {
- handlers map[string]*webSocketHandler
+ handlers map[string]webSocketHandler
}
func NewWebSocketRouter() *WebSocketRouter {
router := &WebSocketRouter{}
- router.handlers = make(map[string]*webSocketHandler)
+ router.handlers = make(map[string]webSocketHandler)
return router
}
-func (wr *WebSocketRouter) Handle(action string, handler *webSocketHandler) {
+func (wr *WebSocketRouter) Handle(action string, handler webSocketHandler) {
wr.handlers[action] = handler
}
func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketRequest) {
if r.Action == "" {
err := model.NewLocAppError("ServeWebSocket", "api.web_socket_router.no_action.app_error", nil, "")
- wr.ReturnWebSocketError(conn, r, err)
+ ReturnWebSocketError(conn, r, err)
return
}
if r.Seq <= 0 {
err := model.NewLocAppError("ServeWebSocket", "api.web_socket_router.bad_seq.app_error", nil, "")
- wr.ReturnWebSocketError(conn, r, err)
+ ReturnWebSocketError(conn, r, err)
return
}
@@ -44,9 +48,9 @@ func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketReque
return
}
- session := GetSession(token)
+ session, err := GetSession(token)
- if session == nil || session.IsExpired() {
+ if err != nil {
conn.WebSocket.Close()
} else {
go SetStatusOnline(session.UserId, session.Id, false)
@@ -63,16 +67,16 @@ func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketReque
return
}
- if !conn.isAuthenticated() {
+ if !conn.IsAuthenticated() {
err := model.NewLocAppError("ServeWebSocket", "api.web_socket_router.not_authenticated.app_error", nil, "")
- wr.ReturnWebSocketError(conn, r, err)
+ ReturnWebSocketError(conn, r, err)
return
}
- var handler *webSocketHandler
+ var handler webSocketHandler
if h, ok := wr.handlers[r.Action]; !ok {
err := model.NewLocAppError("ServeWebSocket", "api.web_socket_router.bad_action.app_error", nil, "")
- wr.ReturnWebSocketError(conn, r, err)
+ ReturnWebSocketError(conn, r, err)
return
} else {
handler = h
@@ -81,7 +85,7 @@ func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketReque
handler.ServeWebSocket(conn, r)
}
-func (wr *WebSocketRouter) ReturnWebSocketError(conn *WebConn, r *model.WebSocketRequest, err *model.AppError) {
+func ReturnWebSocketError(conn *WebConn, r *model.WebSocketRequest, err *model.AppError) {
l4g.Error(utils.T("api.web_socket_router.log.error"), r.Seq, conn.UserId, err.SystemMessage(utils.T), err.DetailedError)
err.DetailedError = ""
diff --git a/cmd/platform/channel.go b/cmd/platform/channel.go
index cf5ef61bc..2a10516af 100644
--- a/cmd/platform/channel.go
+++ b/cmd/platform/channel.go
@@ -6,6 +6,7 @@ import (
"errors"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"github.com/spf13/cobra"
@@ -117,6 +118,8 @@ func createChannelCmdF(cmd *cobra.Command, args []string) error {
team := getTeamFromTeamArg(teamArg)
+ c := getMockContext()
+
channel := &model.Channel{
TeamId: team.Id,
Name: name,
@@ -124,10 +127,10 @@ func createChannelCmdF(cmd *cobra.Command, args []string) error {
Header: header,
Purpose: purpose,
Type: channelType,
+ CreatorId: c.Session.UserId,
}
- c := getMockContext()
- if _, err := api.CreateChannel(c, channel, false); err != nil {
+ if _, err := app.CreateChannel(channel, false); err != nil {
return err
}
@@ -197,7 +200,7 @@ func addUserToChannel(channel *model.Channel, user *model.User, userArg string)
CommandPrintErrorln("Can't find user '" + userArg + "'")
return
}
- if _, err := api.AddUserToChannel(user, channel); err != nil {
+ if _, err := app.AddUserToChannel(user, channel); err != nil {
CommandPrintErrorln("Unable to add '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
}
}
@@ -215,7 +218,7 @@ func deleteChannelsCmdF(cmd *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
continue
}
- if result := <-api.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); result.Err != nil {
CommandPrintErrorln("Unable to delete channel '" + channel.Name + "' error: " + result.Err.Error())
}
}
@@ -240,7 +243,7 @@ func listChannelsCmdF(cmd *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to find team '" + args[i] + "'")
continue
}
- if result := <-api.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
CommandPrintErrorln("Unable to list channels for '" + args[i] + "'")
} else {
channels := result.Data.([]*model.Channel)
@@ -275,7 +278,7 @@ func restoreChannelsCmdF(cmd *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
continue
}
- if result := <-api.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
CommandPrintErrorln("Unable to restore channel '" + args[i] + "'")
}
}
diff --git a/cmd/platform/channelargs.go b/cmd/platform/channelargs.go
index b94bb6b70..ec697d86b 100644
--- a/cmd/platform/channelargs.go
+++ b/cmd/platform/channelargs.go
@@ -6,7 +6,7 @@ import (
"fmt"
"strings"
- "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -42,7 +42,7 @@ func getChannelFromChannelArg(channelArg string) *model.Channel {
return nil
}
- if result := <-api.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, channelPart); result.Err == nil {
+ if result := <-app.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, channelPart); result.Err == nil {
channel = result.Data.(*model.Channel)
} else {
fmt.Println(result.Err.Error())
@@ -50,7 +50,7 @@ func getChannelFromChannelArg(channelArg string) *model.Channel {
}
if channel == nil {
- if result := <-api.Srv.Store.Channel().Get(channelPart, true); result.Err == nil {
+ if result := <-app.Srv.Store.Channel().Get(channelPart, true); result.Err == nil {
channel = result.Data.(*model.Channel)
}
}
diff --git a/cmd/platform/init.go b/cmd/platform/init.go
index 7cf941e9c..eb842d302 100644
--- a/cmd/platform/init.go
+++ b/cmd/platform/init.go
@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"github.com/spf13/cobra"
@@ -37,8 +38,8 @@ func initDBCommandContext(configFileLocation string) {
utils.ConfigureCmdLineLog()
- api.NewServer()
- api.InitStores()
+ app.NewServer()
+ app.InitStores()
if model.BuildEnterpriseReady == "true" {
api.LoadLicense()
}
diff --git a/cmd/platform/mattermost.go b/cmd/platform/mattermost.go
index b5224c403..2ee539980 100644
--- a/cmd/platform/mattermost.go
+++ b/cmd/platform/mattermost.go
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
- "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/spf13/cobra"
// Plugins
@@ -79,7 +79,7 @@ func resetCmdF(cmd *cobra.Command, args []string) error {
}
}
- api.Srv.Store.DropAllTables()
+ app.Srv.Store.DropAllTables()
CommandPrettyPrintln("Database sucessfully reset")
return nil
diff --git a/cmd/platform/oldcommands.go b/cmd/platform/oldcommands.go
index a599fa47e..39560af7d 100644
--- a/cmd/platform/oldcommands.go
+++ b/cmd/platform/oldcommands.go
@@ -13,6 +13,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
@@ -69,8 +70,8 @@ func doLegacyCommands() {
doLoadConfig(flagConfigFile)
utils.InitTranslations(utils.Cfg.LocalizationSettings)
utils.ConfigureCmdLineLog()
- api.NewServer()
- api.InitStores()
+ app.NewServer()
+ app.InitStores()
api.InitRouter()
api.InitApi()
web.InitWeb()
@@ -187,9 +188,9 @@ func runCmds() {
func cmdRunClientTests() {
if flagCmdRunWebClientTests {
setupClientTests()
- api.StartServer()
+ app.StartServer()
runWebClientTests()
- api.StopServer()
+ app.StopServer()
}
}
@@ -220,9 +221,8 @@ func cmdCreateTeam() {
team.Email = flagEmail
team.Type = model.TEAM_OPEN
- api.CreateTeam(c, team)
- if c.Err != nil {
- if c.Err.Id != "store.sql_team.save.domain_exists.app_error" {
+ if _, err := app.CreateTeam(team); err != nil {
+ if err.Id != "store.sql_team.save.domain_exists.app_error" {
l4g.Error("%v", c.Err)
flushLogAndExit(1)
}
@@ -257,7 +257,7 @@ func cmdCreateUser() {
}
if len(flagTeamName) > 0 {
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -265,7 +265,7 @@ func cmdCreateUser() {
}
}
- ruser, err := api.CreateUser(user)
+ ruser, err := app.CreateUser(user)
if err != nil {
if err.Id != "store.sql_user.save.email_exists.app_error" {
l4g.Error("%v", err)
@@ -274,7 +274,7 @@ func cmdCreateUser() {
}
if team != nil {
- err = api.JoinUserToTeam(team, ruser)
+ err = app.JoinUserToTeam(team, ruser)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
@@ -303,7 +303,7 @@ func cmdInviteUser() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -311,7 +311,7 @@ func cmdInviteUser() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(team.Email); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(team.Email); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -333,7 +333,7 @@ func cmdVersion() {
fmt.Fprintln(os.Stderr, "Build Date: "+model.BuildDate)
fmt.Fprintln(os.Stderr, "Build Hash: "+model.BuildHash)
fmt.Fprintln(os.Stderr, "Build Enterprise Ready: "+model.BuildEnterpriseReady)
- fmt.Fprintln(os.Stderr, "DB Version: "+api.Srv.Store.(*store.SqlStore).SchemaVersion)
+ fmt.Fprintln(os.Stderr, "DB Version: "+app.Srv.Store.(*store.SqlStore).SchemaVersion)
os.Exit(0)
}
@@ -361,7 +361,7 @@ func cmdAssignRole() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -404,7 +404,7 @@ func cmdCreateChannel() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v %v", utils.T(result.Err.Message), result.Err.DetailedError)
flushLogAndExit(1)
} else {
@@ -412,7 +412,7 @@ func cmdCreateChannel() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v %v", utils.T(result.Err.Message), result.Err.DetailedError)
flushLogAndExit(1)
} else {
@@ -431,7 +431,7 @@ func cmdCreateChannel() {
channel.Header = flagChannelHeader
channel.Purpose = flagChannelPurpose
- if _, err := api.CreateChannel(c, channel, true); err != nil {
+ if _, err := app.CreateChannel(channel, true); err != nil {
l4g.Error("%v %v", utils.T(err.Message), err.DetailedError)
flushLogAndExit(1)
}
@@ -463,7 +463,7 @@ func cmdJoinChannel() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -471,7 +471,7 @@ func cmdJoinChannel() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -479,14 +479,14 @@ func cmdJoinChannel() {
}
var channel *model.Channel
- if result := <-api.Srv.Store.Channel().GetByName(team.Id, flagChannelName); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetByName(team.Id, flagChannelName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
channel = result.Data.(*model.Channel)
}
- _, err := api.AddUserToChannel(user, channel)
+ _, err := app.AddUserToChannel(user, channel)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
@@ -524,7 +524,7 @@ func cmdLeaveChannel() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -532,7 +532,7 @@ func cmdLeaveChannel() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -540,7 +540,7 @@ func cmdLeaveChannel() {
}
var channel *model.Channel
- if result := <-api.Srv.Store.Channel().GetByName(team.Id, flagChannelName); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetByName(team.Id, flagChannelName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -570,14 +570,14 @@ func cmdListChannels() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
- if result := <-api.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -615,7 +615,7 @@ func cmdRestoreChannel() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -623,7 +623,7 @@ func cmdRestoreChannel() {
}
var channel *model.Channel
- if result := <-api.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -637,7 +637,7 @@ func cmdRestoreChannel() {
}
}
- if result := <-api.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
}
@@ -659,7 +659,7 @@ func cmdJoinTeam() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -667,14 +667,14 @@ func cmdJoinTeam() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
- err := api.JoinUserToTeam(team, user)
+ err := app.JoinUserToTeam(team, user)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
@@ -697,7 +697,7 @@ func cmdLeaveTeam() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -705,7 +705,7 @@ func cmdLeaveTeam() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -741,14 +741,14 @@ func cmdResetPassword() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
- if result := <-api.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(flagPassword)); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(flagPassword)); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
}
@@ -766,14 +766,14 @@ func cmdResetMfa() {
var user *model.User
if len(flagEmail) > 0 {
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
} else {
- if result := <-api.Srv.Store.User().GetByUsername(flagUsername); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByUsername(flagUsername); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -798,7 +798,7 @@ func cmdPermDeleteUser() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -841,7 +841,7 @@ func cmdPermDeleteTeam() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -927,7 +927,7 @@ func cmdResetDatabase() {
flushLogAndExit(1)
}
- api.Srv.Store.DropAllTables()
+ app.Srv.Store.DropAllTables()
fmt.Print("SUCCESS: Database reset.")
flushLogAndExit(0)
}
@@ -1022,7 +1022,7 @@ func cmdActivateUser() {
}
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
+ if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
@@ -1054,7 +1054,7 @@ func cmdSlackImport() {
}
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
+ if result := <-app.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
diff --git a/cmd/platform/server.go b/cmd/platform/server.go
index 51078b6aa..5abc4d6e8 100644
--- a/cmd/platform/server.go
+++ b/cmd/platform/server.go
@@ -16,6 +16,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/manualtesting"
"github.com/mattermost/platform/model"
@@ -63,8 +64,8 @@ func runServer(configFileLocation string) {
cmdUpdateDb30()
- api.NewServer()
- api.InitStores()
+ app.NewServer()
+ app.InitStores()
api.InitRouter()
api.InitApi()
web.InitWeb()
@@ -84,7 +85,7 @@ func runServer(configFileLocation string) {
resetStatuses()
- api.StartServer()
+ app.StartServer()
// If we allow testing then listen for manual testing URL hits
if utils.Cfg.ServiceSettings.EnableTesting {
@@ -120,7 +121,7 @@ func runServer(configFileLocation string) {
einterfaces.GetMetricsInterface().StopServer()
}
- api.StopServer()
+ app.StopServer()
}
func runSecurityAndDiagnosticsJob() {
@@ -129,20 +130,20 @@ func runSecurityAndDiagnosticsJob() {
}
func resetStatuses() {
- if result := <-api.Srv.Store.Status().ResetAll(); result.Err != nil {
+ if result := <-app.Srv.Store.Status().ResetAll(); result.Err != nil {
l4g.Error(utils.T("mattermost.reset_status.error"), result.Err.Error())
}
}
func setDiagnosticId() {
- if result := <-api.Srv.Store.System().Get(); result.Err == nil {
+ if result := <-app.Srv.Store.System().Get(); result.Err == nil {
props := result.Data.(model.StringMap)
id := props[model.SYSTEM_DIAGNOSTIC_ID]
if len(id) == 0 {
id = model.NewId()
systemId := &model.System{Name: model.SYSTEM_DIAGNOSTIC_ID, Value: id}
- <-api.Srv.Store.System().Save(systemId)
+ <-app.Srv.Store.System().Save(systemId)
}
utils.CfgDiagnosticId = id
@@ -151,7 +152,7 @@ func setDiagnosticId() {
func doSecurityAndDiagnostics() {
if *utils.Cfg.ServiceSettings.EnableSecurityFixAlert {
- if result := <-api.Srv.Store.System().Get(); result.Err == nil {
+ if result := <-app.Srv.Store.System().Get(); result.Err == nil {
props := result.Data.(model.StringMap)
lastSecurityTime, _ := strconv.ParseInt(props[model.SYSTEM_LAST_SECURITY_TIME], 10, 0)
currentTime := model.GetMillis()
@@ -176,20 +177,20 @@ func doSecurityAndDiagnostics() {
systemSecurityLastTime := &model.System{Name: model.SYSTEM_LAST_SECURITY_TIME, Value: strconv.FormatInt(currentTime, 10)}
if lastSecurityTime == 0 {
- <-api.Srv.Store.System().Save(systemSecurityLastTime)
+ <-app.Srv.Store.System().Save(systemSecurityLastTime)
} else {
- <-api.Srv.Store.System().Update(systemSecurityLastTime)
+ <-app.Srv.Store.System().Update(systemSecurityLastTime)
}
- if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
+ if ucr := <-app.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
v.Set(utils.PROP_DIAGNOSTIC_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
}
- if ucr := <-api.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
+ if ucr := <-app.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
v.Set(utils.PROP_DIAGNOSTIC_ACTIVE_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
}
- if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
+ if tcr := <-app.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
v.Set(utils.PROP_DIAGNOSTIC_TEAM_COUNT, strconv.FormatInt(tcr.Data.(int64), 10))
}
@@ -206,7 +207,7 @@ func doSecurityAndDiagnostics() {
for _, bulletin := range bulletins {
if bulletin.AppliesToVersion == model.CurrentVersion {
if props["SecurityBulletin_"+bulletin.Id] == "" {
- if results := <-api.Srv.Store.User().GetSystemAdminProfiles(); results.Err != nil {
+ if results := <-app.Srv.Store.User().GetSystemAdminProfiles(); results.Err != nil {
l4g.Error(utils.T("mattermost.system_admins.error"))
return
} else {
@@ -232,7 +233,7 @@ func doSecurityAndDiagnostics() {
}
bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
- <-api.Srv.Store.System().Save(bulletinSeen)
+ <-app.Srv.Store.System().Save(bulletinSeen)
}
}
}
@@ -251,15 +252,15 @@ func sendServerDiagnostics() {
var activeUserCount int64
var teamCount int64
- if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
+ if ucr := <-app.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
userCount = ucr.Data.(int64)
}
- if ucr := <-api.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
+ if ucr := <-app.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
activeUserCount = ucr.Data.(int64)
}
- if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
+ if tcr := <-app.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
teamCount = tcr.Data.(int64)
}
diff --git a/cmd/platform/team.go b/cmd/platform/team.go
index 8fecda6e1..43d0b2582 100644
--- a/cmd/platform/team.go
+++ b/cmd/platform/team.go
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/spf13/cobra"
)
@@ -92,10 +93,8 @@ func createTeamCmdF(cmd *cobra.Command, args []string) error {
Type: teamType,
}
- c := getMockContext()
- api.CreateTeam(c, team)
- if c.Err != nil {
- return errors.New("Team creation failed: " + c.Err.Error())
+ if _, err := app.CreateTeam(team); err != nil {
+ return errors.New("Team creation failed: " + err.Error())
}
return nil
@@ -156,7 +155,7 @@ func addUserToTeam(team *model.Team, user *model.User, userArg string) {
CommandPrintErrorln("Can't find user '" + userArg + "'")
return
}
- if err := api.JoinUserToTeam(team, user); err != nil {
+ if err := app.JoinUserToTeam(team, user); err != nil {
CommandPrintErrorln("Unable to add '" + userArg + "' to " + team.Name)
}
}
diff --git a/cmd/platform/teamargs.go b/cmd/platform/teamargs.go
index 5ad56f5d9..506cc88ef 100644
--- a/cmd/platform/teamargs.go
+++ b/cmd/platform/teamargs.go
@@ -3,7 +3,7 @@
package main
import (
- "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -18,12 +18,12 @@ func getTeamsFromTeamArgs(teamArgs []string) []*model.Team {
func getTeamFromTeamArg(teamArg string) *model.Team {
var team *model.Team
- if result := <-api.Srv.Store.Team().GetByName(teamArg); result.Err == nil {
+ if result := <-app.Srv.Store.Team().GetByName(teamArg); result.Err == nil {
team = result.Data.(*model.Team)
}
if team == nil {
- if result := <-api.Srv.Store.Team().Get(teamArg); result.Err == nil {
+ if result := <-app.Srv.Store.Team().Get(teamArg); result.Err == nil {
team = result.Data.(*model.Team)
}
}
diff --git a/cmd/platform/test.go b/cmd/platform/test.go
index d82734c75..124397350 100644
--- a/cmd/platform/test.go
+++ b/cmd/platform/test.go
@@ -10,6 +10,7 @@ import (
"os/exec"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/utils"
"github.com/spf13/cobra"
)
@@ -38,9 +39,9 @@ func webClientTestsCmdF(cmd *cobra.Command, args []string) error {
api.InitRouter()
api.InitApi()
setupClientTests()
- api.StartServer()
+ app.StartServer()
runWebClientTests()
- api.StopServer()
+ app.StopServer()
return nil
}
diff --git a/cmd/platform/user.go b/cmd/platform/user.go
index 373274241..aabc6afcf 100644
--- a/cmd/platform/user.go
+++ b/cmd/platform/user.go
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
@@ -220,7 +221,7 @@ func userCreateCmdF(cmd *cobra.Command, args []string) error {
Locale: locale,
}
- ruser, err := api.CreateUser(user)
+ ruser, err := app.CreateUser(user)
if err != nil {
return errors.New("Unable to create user. Error: " + err.Error())
}
@@ -277,7 +278,7 @@ func resetUserPasswordCmdF(cmd *cobra.Command, args []string) error {
}
password := args[1]
- if result := <-api.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil {
+ if result := <-app.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil {
return result.Err
}
@@ -423,7 +424,7 @@ func verifyUserCmdF(cmd *cobra.Command, args []string) error {
if user == nil {
CommandPrintErrorln("Unable to find user '" + args[i] + "'")
}
- if cresult := <-api.Srv.Store.User().VerifyEmail(user.Id); cresult.Err != nil {
+ if cresult := <-app.Srv.Store.User().VerifyEmail(user.Id); cresult.Err != nil {
CommandPrintErrorln("Unable to verify '" + args[i] + "' email. Error: " + cresult.Err.Error())
}
}
diff --git a/cmd/platform/userargs.go b/cmd/platform/userargs.go
index 9ac00ae70..31ae3c251 100644
--- a/cmd/platform/userargs.go
+++ b/cmd/platform/userargs.go
@@ -3,7 +3,7 @@
package main
import (
- "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
)
@@ -18,18 +18,18 @@ func getUsersFromUserArgs(userArgs []string) []*model.User {
func getUserFromUserArg(userArg string) *model.User {
var user *model.User
- if result := <-api.Srv.Store.User().GetByEmail(userArg); result.Err == nil {
+ if result := <-app.Srv.Store.User().GetByEmail(userArg); result.Err == nil {
user = result.Data.(*model.User)
}
if user == nil {
- if result := <-api.Srv.Store.User().GetByUsername(userArg); result.Err == nil {
+ if result := <-app.Srv.Store.User().GetByUsername(userArg); result.Err == nil {
user = result.Data.(*model.User)
}
}
if user == nil {
- if result := <-api.Srv.Store.User().Get(userArg); result.Err == nil {
+ if result := <-app.Srv.Store.User().Get(userArg); result.Err == nil {
user = result.Data.(*model.User)
}
}
diff --git a/cmd/platform/version.go b/cmd/platform/version.go
index 8da34e3a9..8978aa841 100644
--- a/cmd/platform/version.go
+++ b/cmd/platform/version.go
@@ -3,7 +3,7 @@
package main
import (
- "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/spf13/cobra"
@@ -26,5 +26,5 @@ func printVersion() {
CommandPrintln("Build Date: " + model.BuildDate)
CommandPrintln("Build Hash: " + model.BuildHash)
CommandPrintln("Build Enterprise Ready: " + model.BuildEnterpriseReady)
- CommandPrintln("DB Version: " + api.Srv.Store.(*store.SqlStore).SchemaVersion)
+ CommandPrintln("DB Version: " + app.Srv.Store.(*store.SqlStore).SchemaVersion)
}
diff --git a/i18n/en.json b/i18n/en.json
index 520195812..84ebd2748 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -805,7 +805,15 @@
},
{
"id": "api.context.invalid_token.error",
- "translation": "Invalid session token=%v, err=%v"
+ "translation": "Invalid session token={{.Token}}, err={{.Error}}"
+ },
+ {
+ "id": "api.context.invalid_session.error",
+ "translation": "Invalid session err=%v"
+ },
+ {
+ "id": "api.websocket.invalid_session.error",
+ "translation": "Invalid session err=%v"
},
{
"id": "api.context.invalidate_all_caches",
@@ -1468,26 +1476,10 @@
"translation": "You do not have the appropriate permissions"
},
{
- "id": "api.post.handle_post_events_and_forget.channel.error",
- "translation": "Encountered error getting channel, channel_id=%s, err=%v"
- },
- {
"id": "api.post.handle_post_events_and_forget.members.error",
"translation": "Failed to get channel members channel_id=%v err=%v"
},
{
- "id": "api.post.handle_post_events_and_forget.profiles.error",
- "translation": "Failed to retrieve user profiles team_id=%v, err=%v"
- },
- {
- "id": "api.post.handle_post_events_and_forget.team.error",
- "translation": "Encountered error getting team, team_id=%s, err=%v"
- },
- {
- "id": "api.post.handle_post_events_and_forget.user.error",
- "translation": "Encountered error getting user, user_id=%s, err=%v"
- },
- {
"id": "api.post.handle_webhook_events_and_forget.create_post.error",
"translation": "Failed to create response post, err=%v"
},
@@ -1496,16 +1488,12 @@
"translation": "Event POST failed, err=%s"
},
{
- "id": "api.post.handle_webhook_events_and_forget.getting.error",
- "translation": "Encountered error getting webhooks by team, err=%v"
- },
- {
"id": "api.post.init.debug",
"translation": "Initializing post API routes"
},
{
"id": "api.post.make_direct_channel_visible.get_2_members.error",
- "translation": "Failed to get 2 members for a direct channel channel_id=%v"
+ "translation": "Failed to get 2 members for a direct channel channel_id={{.ChannelId}}"
},
{
"id": "api.post.make_direct_channel_visible.get_members.error",
@@ -1520,10 +1508,6 @@
"translation": "Failed to update direct channel preference user_id=%v other_user_id=%v err=%v"
},
{
- "id": "api.post.notification.here.warn",
- "translation": "Unable to send notification to online users with @here, err=%v"
- },
- {
"id": "api.post.notification.member_profile.warn",
"translation": "Unable to get profile for channel member, user_id=%v"
},
@@ -1532,10 +1516,6 @@
"translation": "Clearing push notification to %v with channel_id %v"
},
{
- "id": "api.post.send_notifications_and_forget.comment_thread.error",
- "translation": "Failed to retrieve comment thread posts in notifications root_post_id=%v, err=%v"
- },
- {
"id": "api.post.send_notifications_and_forget.files.error",
"translation": "Failed to get files for post notification post_id=%v, err=%v"
},
@@ -1581,23 +1561,15 @@
},
{
"id": "api.post.send_notifications_and_forget.push_notification.error",
- "translation": "Failed to send push device_id=%v, err=%v"
- },
- {
- "id": "api.post.send_notifications_and_forget.send.error",
- "translation": "Failed to send mention email successfully email=%v err=%v"
+ "translation": "Failed to send push device_id={{.DeviceId}}, err={{.Error}}"
},
{
"id": "api.post.send_notifications_and_forget.sent",
"translation": "{{.Prefix}} {{.Filenames}} sent"
},
{
- "id": "api.post.send_notifications_and_forget.sessions.error",
- "translation": "Failed to retrieve sessions in notifications id=%v, err=%v"
- },
- {
- "id": "api.post.send_notifications_and_forget.user_id.error",
- "translation": "Post user_id not returned by GetProfiles user_id=%v"
+ "id": "api.post.send_notifications.user_id.debug",
+ "translation": "Post creator not in channel for the post, no notification sent post_id=%v channel_id=%v user_id=%v"
},
{
"id": "api.post.update_mention_count_and_forget.update_error",
diff --git a/manualtesting/manual_testing.go b/manualtesting/manual_testing.go
index 9a2d557bc..30249f995 100644
--- a/manualtesting/manual_testing.go
+++ b/manualtesting/manual_testing.go
@@ -4,16 +4,18 @@
package manualtesting
import (
- l4g "github.com/alecthomas/log4go"
- "github.com/mattermost/platform/api"
- "github.com/mattermost/platform/model"
- "github.com/mattermost/platform/utils"
"hash/fnv"
"math/rand"
"net/http"
"net/url"
"strconv"
"time"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
)
type TestEnvironment struct {
@@ -27,7 +29,7 @@ type TestEnvironment struct {
}
func InitManualTesting() {
- api.Srv.Router.Handle("/manualtest", api.AppHandler(manualTest)).Methods("GET")
+ app.Srv.Router.Handle("/manualtest", api.AppHandler(manualTest)).Methods("GET")
}
func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
@@ -70,7 +72,7 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
Type: model.TEAM_OPEN,
}
- if result := <-api.Srv.Store.Team().Save(team); result.Err != nil {
+ if result := <-app.Srv.Store.Team().Save(team); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -78,7 +80,7 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
createdTeam := result.Data.(*model.Team)
channel := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: createdTeam.Id}
- if _, err := api.CreateChannel(c, channel, false); err != nil {
+ if _, err := app.CreateChannel(channel, false); err != nil {
c.Err = err
return
}
@@ -98,8 +100,8 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
return
}
- <-api.Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)
- <-api.Srv.Store.Team().SaveMember(&model.TeamMember{TeamId: teamID, UserId: result.Data.(*model.User).Id})
+ <-app.Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)
+ <-app.Srv.Store.Team().SaveMember(&model.TeamMember{TeamId: teamID, UserId: result.Data.(*model.User).Id})
newuser := result.Data.(*model.User)
userID = newuser.Id
@@ -153,7 +155,7 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
func getChannelID(channelname string, teamid string, userid string) (id string, err bool) {
// Grab all the channels
- result := <-api.Srv.Store.Channel().GetChannels(teamid, userid)
+ result := <-app.Srv.Store.Channel().GetChannels(teamid, userid)
if result.Err != nil {
l4g.Debug(utils.T("manaultesting.get_channel_id.unable.debug"))
return "", false
diff --git a/model/websocket_client.go b/model/websocket_client.go
index 453ae49b7..c91855134 100644
--- a/model/websocket_client.go
+++ b/model/websocket_client.go
@@ -8,6 +8,10 @@ import (
"github.com/gorilla/websocket"
)
+const (
+ SOCKET_MAX_MESSAGE_SIZE_KB = 8 * 1024 // 8KB
+)
+
type WebSocketClient struct {
Url string // The location of the server like "ws://localhost:8065"
ApiUrl string // The api location of the server like "ws://localhost:8065/api/v3"
diff --git a/utils/config.go b/utils/config.go
index ab149d55f..da070012e 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -32,6 +32,15 @@ var CfgHash = ""
var CfgFileName string = ""
var ClientCfg map[string]string = map[string]string{}
var originalDisableDebugLvl l4g.Level = l4g.DEBUG
+var siteURL = ""
+
+func GetSiteURL() string {
+ return siteURL
+}
+
+func SetSiteURL(url string) {
+ siteURL = url
+}
func FindConfigFile(fileName string) string {
if _, err := os.Stat("./config/" + fileName); err == nil {
@@ -215,6 +224,7 @@ func LoadConfig(fileName string) {
}
SetDefaultRolesBasedOnConfig()
+ SetSiteURL(*Cfg.ServiceSettings.SiteURL)
}
func RegenerateClientConfig() {
diff --git a/utils/utils.go b/utils/utils.go
index dd60f6060..6d34387c4 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -4,7 +4,11 @@
package utils
import (
+ "net"
+ "net/http"
"os"
+
+ "github.com/mattermost/platform/model"
)
func StringArrayIntersection(arr1, arr2 []string) []string {
@@ -48,3 +52,17 @@ func RemoveDuplicatesFromStringArray(arr []string) []string {
return result
}
+
+func GetIpAddress(r *http.Request) string {
+ address := r.Header.Get(model.HEADER_FORWARDED)
+
+ if len(address) == 0 {
+ address = r.Header.Get(model.HEADER_REAL_IP)
+ }
+
+ if len(address) == 0 {
+ address, _, _ = net.SplitHostPort(r.RemoteAddr)
+ }
+
+ return address
+}
diff --git a/web/web.go b/web/web.go
index d1a181d73..1ee216d55 100644
--- a/web/web.go
+++ b/web/web.go
@@ -11,6 +11,7 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"github.com/mssola/user_agent"
@@ -19,7 +20,7 @@ import (
func InitWeb() {
l4g.Debug(utils.T("web.init.debug"))
- mainrouter := api.Srv.Router
+ mainrouter := app.Srv.Router
if *utils.Cfg.ServiceSettings.WebserverMode != "disabled" {
staticDir := utils.FindDir(model.CLIENT_DIR)
diff --git a/web/web_test.go b/web/web_test.go
index 812fa4239..80a0282b4 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -10,6 +10,7 @@ import (
"time"
"github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
@@ -19,28 +20,28 @@ var ApiClient *model.Client
var URL string
func Setup() {
- if api.Srv == nil {
+ if app.Srv == nil {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
- api.NewServer()
- api.InitStores()
+ app.NewServer()
+ app.InitStores()
api.InitRouter()
- api.StartServer()
+ app.StartServer()
api.InitApi()
InitWeb()
URL = "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress
ApiClient = model.NewClient(URL)
- api.Srv.Store.MarkSystemRanUnitTests()
+ app.Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true
}
}
func TearDown() {
- if api.Srv != nil {
- api.StopServer()
+ if app.Srv != nil {
+ app.StopServer()
}
}
@@ -69,13 +70,13 @@ func TestGetAccessToken(t *testing.T) {
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Password: "passwd1"}
ruser := ApiClient.Must(ApiClient.CreateUser(&user, "")).Data.(*model.User)
- api.JoinUserToTeam(rteam.Data.(*model.Team), ruser)
- store.Must(api.Srv.Store.User().VerifyEmail(ruser.Id))
+ app.JoinUserToTeam(rteam.Data.(*model.Team), ruser)
+ store.Must(app.Srv.Store.User().VerifyEmail(ruser.Id))
- app := &model.OAuthApp{Name: "TestApp" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
+ oauthApp := &model.OAuthApp{Name: "TestApp" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
utils.Cfg.ServiceSettings.EnableOAuthServiceProvider = false
- data := url.Values{"grant_type": []string{"junk"}, "client_id": []string{"12345678901234567890123456"}, "client_secret": []string{"12345678901234567890123456"}, "code": []string{"junk"}, "redirect_uri": []string{app.CallbackUrls[0]}}
+ data := url.Values{"grant_type": []string{"junk"}, "client_id": []string{"12345678901234567890123456"}, "client_secret": []string{"12345678901234567890123456"}, "code": []string{"junk"}, "redirect_uri": []string{oauthApp.CallbackUrls[0]}}
if _, err := ApiClient.GetAccessToken(data); err == nil {
t.Fatal("should have failed - oauth providing turned off")
@@ -86,18 +87,18 @@ func TestGetAccessToken(t *testing.T) {
ApiClient.SetTeamId(rteam.Data.(*model.Team).Id)
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
utils.SetDefaultRolesBasedOnConfig()
- app = ApiClient.Must(ApiClient.RegisterApp(app)).Data.(*model.OAuthApp)
+ oauthApp = ApiClient.Must(ApiClient.RegisterApp(oauthApp)).Data.(*model.OAuthApp)
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
utils.SetDefaultRolesBasedOnConfig()
- redirect := ApiClient.Must(ApiClient.AllowOAuth(model.AUTHCODE_RESPONSE_TYPE, app.Id, app.CallbackUrls[0], "all", "123")).Data.(map[string]string)["redirect"]
+ redirect := ApiClient.Must(ApiClient.AllowOAuth(model.AUTHCODE_RESPONSE_TYPE, oauthApp.Id, oauthApp.CallbackUrls[0], "all", "123")).Data.(map[string]string)["redirect"]
rurl, _ := url.Parse(redirect)
teamId := rteam.Data.(*model.Team).Id
ApiClient.Logout()
- data = url.Values{"grant_type": []string{"junk"}, "client_id": []string{app.Id}, "client_secret": []string{app.ClientSecret}, "code": []string{rurl.Query().Get("code")}, "redirect_uri": []string{app.CallbackUrls[0]}}
+ data = url.Values{"grant_type": []string{"junk"}, "client_id": []string{oauthApp.Id}, "client_secret": []string{oauthApp.ClientSecret}, "code": []string{rurl.Query().Get("code")}, "redirect_uri": []string{oauthApp.CallbackUrls[0]}}
if _, err := ApiClient.GetAccessToken(data); err == nil {
t.Fatal("should have failed - bad grant type")
@@ -113,7 +114,7 @@ func TestGetAccessToken(t *testing.T) {
t.Fatal("should have failed - bad client id")
}
- data.Set("client_id", app.Id)
+ data.Set("client_id", oauthApp.Id)
data.Set("client_secret", "")
if _, err := ApiClient.GetAccessToken(data); err == nil {
t.Fatal("should have failed - missing client secret")
@@ -124,7 +125,7 @@ func TestGetAccessToken(t *testing.T) {
t.Fatal("should have failed - bad client secret")
}
- data.Set("client_secret", app.ClientSecret)
+ data.Set("client_secret", oauthApp.ClientSecret)
data.Set("code", "")
if _, err := ApiClient.GetAccessToken(data); err == nil {
t.Fatal("should have failed - missing code")
@@ -143,10 +144,10 @@ func TestGetAccessToken(t *testing.T) {
// reset data for successful request
data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
- data.Set("client_id", app.Id)
- data.Set("client_secret", app.ClientSecret)
+ data.Set("client_id", oauthApp.Id)
+ data.Set("client_secret", oauthApp.ClientSecret)
data.Set("code", rurl.Query().Get("code"))
- data.Set("redirect_uri", app.CallbackUrls[0])
+ data.Set("redirect_uri", oauthApp.CallbackUrls[0])
token := ""
if result, err := ApiClient.GetAccessToken(data); err != nil {
@@ -205,8 +206,8 @@ func TestIncomingWebhook(t *testing.T) {
user := &model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1"}
user = ApiClient.Must(ApiClient.CreateUser(user, "")).Data.(*model.User)
- store.Must(api.Srv.Store.User().VerifyEmail(user.Id))
- api.JoinUserToTeam(team, user)
+ store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
+ app.JoinUserToTeam(team, user)
api.UpdateUserRoles(user, model.ROLE_SYSTEM_ADMIN.Id)
ApiClient.Login(user.Email, "passwd1")