diff --git a/api/admin.go b/api/admin.go index cd1e5d2dee..7a5616edec 100644 --- a/api/admin.go +++ b/api/admin.go @@ -24,7 +24,7 @@ func InitAdmin(r *mux.Router) { sr.Handle("/config", ApiUserRequired(getConfig)).Methods("GET") sr.Handle("/save_config", ApiUserRequired(saveConfig)).Methods("POST") sr.Handle("/test_email", ApiUserRequired(testEmail)).Methods("POST") - sr.Handle("/client_props", ApiAppHandler(getClientProperties)).Methods("GET") + sr.Handle("/client_props", ApiAppHandler(getClientConfig)).Methods("GET") sr.Handle("/log_client", ApiAppHandler(logClient)).Methods("POST") } @@ -57,8 +57,8 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { w.Write([]byte(model.ArrayToJson(lines))) } -func getClientProperties(c *Context, w http.ResponseWriter, r *http.Request) { - w.Write([]byte(model.MapToJson(utils.ClientProperties))) +func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) { + w.Write([]byte(model.MapToJson(utils.ClientCfg))) } func logClient(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api/api.go b/api/api.go index 4da1de62d4..6c7eda0a2f 100644 --- a/api/api.go +++ b/api/api.go @@ -20,7 +20,7 @@ func NewServerTemplatePage(templateName string) *ServerTemplatePage { return &ServerTemplatePage{ TemplateName: templateName, Props: make(map[string]string), - ClientProps: utils.ClientProperties, + ClientCfg: utils.ClientCfg, } } diff --git a/api/channel.go b/api/channel.go index 70f7eba4bf..9c7ac053b0 100644 --- a/api/channel.go +++ b/api/channel.go @@ -131,16 +131,21 @@ func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId) } - if sc, err := CreateChannel(c, channel, true); err != nil { - return nil, err + cm1 := &model.ChannelMember{ + UserId: c.Session.UserId, + Roles: model.CHANNEL_ROLE_ADMIN, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + cm2 := &model.ChannelMember{ + UserId: otherUserId, + Roles: "", + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + + if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { + return nil, result.Err } else { - cm := &model.ChannelMember{ChannelId: sc.Id, UserId: otherUserId, Roles: "", NotifyProps: model.GetDefaultChannelNotifyProps()} - - if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil { - return nil, cmresult.Err - } - - return sc, nil + return result.Data.(*model.Channel), nil } } diff --git a/api/context.go b/api/context.go index bd9744bf84..9be3e85cc3 100644 --- a/api/context.go +++ b/api/context.go @@ -8,6 +8,7 @@ import ( "net" "net/http" "net/url" + "strconv" "strings" l4g "code.google.com/p/log4go" @@ -19,20 +20,24 @@ import ( var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE) type Context struct { - Session model.Session - RequestId string - IpAddress string - Path string - Err *model.AppError - teamURLValid bool - teamURL string - siteURL string + Session model.Session + RequestId string + IpAddress string + Path string + Err *model.AppError + teamURLValid bool + teamURL string + siteURL string + SessionTokenIndex int64 } type Page struct { - TemplateName string - Props map[string]string - ClientProps map[string]string + TemplateName string + Props map[string]string + ClientCfg map[string]string + User *model.User + Team *model.Team + SessionTokenIndex int64 } func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { @@ -96,8 +101,37 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Attempt to parse the token from the cookie if len(token) == 0 { - if cookie, err := r.Cookie(model.SESSION_TOKEN); err == nil { - token = cookie.Value + tokens := GetMultiSessionCookieTokens(r) + if len(tokens) > 0 { + // If there is only 1 token in the cookie then just use it like normal + if len(tokens) == 1 { + token = tokens[0] + } else { + // If it is a multi-session token then find the correct session + sessionTokenIndexStr := r.URL.Query().Get(model.SESSION_TOKEN_INDEX) + sessionTokenIndex := int64(-1) + if len(sessionTokenIndexStr) > 0 { + if index, err := strconv.ParseInt(sessionTokenIndexStr, 10, 64); err == nil { + sessionTokenIndex = index + } + } else { + sessionTokenIndexStr := r.Header.Get(model.HEADER_MM_SESSION_TOKEN_INDEX) + if len(sessionTokenIndexStr) > 0 { + if index, err := strconv.ParseInt(sessionTokenIndexStr, 10, 64); err == nil { + sessionTokenIndex = index + } + } + } + + if sessionTokenIndex >= 0 && sessionTokenIndex < int64(len(tokens)) { + token = tokens[sessionTokenIndex] + c.SessionTokenIndex = sessionTokenIndex + } else { + c.SessionTokenIndex = -1 + } + } + } else { + c.SessionTokenIndex = -1 } } @@ -123,18 +157,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if len(token) != 0 { - var session *model.Session - if ts, ok := sessionCache.Get(token); ok { - session = ts.(*model.Session) - } - - if session == nil { - if sessionResult := <-Srv.Store.Session().Get(token); sessionResult.Err != nil { - c.LogError(model.NewAppError("ServeHTTP", "Invalid session", "token="+token+", err="+sessionResult.Err.DetailedError)) - } else { - session = sessionResult.Data.(*model.Session) - } - } + session := GetSession(token) if session == nil || session.IsExpired() { c.RemoveSessionCookie(w, r) @@ -318,10 +341,23 @@ func (c *Context) IsTeamAdmin() bool { func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) { - sessionCache.Remove(c.Session.Token) + // multiToken := "" + // if oldMultiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { + // multiToken = oldMultiCookie.Value + // } + + // multiCookie := &http.Cookie{ + // Name: model.SESSION_COOKIE_TOKEN, + // Value: strings.TrimSpace(strings.Replace(multiToken, c.Session.Token, "", -1)), + // Path: "/", + // MaxAge: model.SESSION_TIME_WEB_IN_SECS, + // HttpOnly: true, + // } + + //http.SetCookie(w, multiCookie) cookie := &http.Cookie{ - Name: model.SESSION_TOKEN, + Name: model.SESSION_COOKIE_TOKEN, Value: "", Path: "/", MaxAge: -1, @@ -329,21 +365,6 @@ func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) { } http.SetCookie(w, cookie) - - multiToken := "" - if oldMultiCookie, err := r.Cookie(model.MULTI_SESSION_TOKEN); err == nil { - multiToken = oldMultiCookie.Value - } - - multiCookie := &http.Cookie{ - Name: model.MULTI_SESSION_TOKEN, - Value: strings.TrimSpace(strings.Replace(multiToken, c.Session.Token, "", -1)), - Path: "/", - MaxAge: model.SESSION_TIME_WEB_IN_SECS, - HttpOnly: true, - } - - http.SetCookie(w, multiCookie) } func (c *Context) SetInvalidParam(where string, name string) { @@ -479,7 +500,7 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request) } w.WriteHeader(err.StatusCode) - ServerTemplates.ExecuteTemplate(w, "error.html", Page{Props: props, ClientProps: utils.ClientProperties}) + ServerTemplates.ExecuteTemplate(w, "error.html", Page{Props: props, ClientCfg: utils.ClientCfg}) } func Handle404(w http.ResponseWriter, r *http.Request) { @@ -489,6 +510,46 @@ func Handle404(w http.ResponseWriter, r *http.Request) { RenderWebError(err, w, r) } +func GetSession(token string) *model.Session { + var session *model.Session + if ts, ok := sessionCache.Get(token); ok { + session = ts.(*model.Session) + } + + if session == nil { + if sessionResult := <-Srv.Store.Session().Get(token); sessionResult.Err != nil { + l4g.Error("Invalid session token=" + token + ", err=" + sessionResult.Err.DetailedError) + } else { + session = sessionResult.Data.(*model.Session) + } + } + + return session +} + +func GetMultiSessionCookieTokens(r *http.Request) []string { + if multiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { + multiToken := multiCookie.Value + + if len(multiToken) > 0 { + return strings.Split(multiToken, " ") + } + } + + return []string{} +} + +func FindMultiSessionForTeamId(r *http.Request, teamId string) (int64, *model.Session) { + for index, token := range GetMultiSessionCookieTokens(r) { + s := GetSession(token) + if s != nil && !s.IsExpired() && s.TeamId == teamId { + return int64(index), s + } + } + + return -1, nil +} + func AddSessionToCache(session *model.Session) { sessionCache.Add(session.Token, session) } diff --git a/api/post.go b/api/post.go index c5bcd4f5aa..79f84e04d8 100644 --- a/api/post.go +++ b/api/post.go @@ -281,7 +281,7 @@ func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team // copy the context and create a mock session for posting the message mockSession := model.Session{UserId: hook.CreatorId, TeamId: hook.TeamId, IsOAuth: false} - newContext := &Context{mockSession, model.NewId(), "", c.Path, nil, c.teamURLValid, c.teamURL, c.siteURL} + newContext := &Context{mockSession, model.NewId(), "", c.Path, nil, c.teamURLValid, c.teamURL, c.siteURL, 0} if text, ok := respProps["text"]; ok { if _, err := CreateWebhookPost(newContext, post.ChannelId, text, respProps["username"], respProps["icon_url"]); err != nil { diff --git a/api/team.go b/api/team.go index 2d7b05ff60..d39d8ed60c 100644 --- a/api/team.go +++ b/api/team.go @@ -426,9 +426,9 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) { } subjectPage := NewServerTemplatePage("find_teams_subject") - subjectPage.ClientProps["SiteURL"] = c.GetSiteURL() + subjectPage.ClientCfg["SiteURL"] = c.GetSiteURL() bodyPage := NewServerTemplatePage("find_teams_body") - bodyPage.ClientProps["SiteURL"] = c.GetSiteURL() + bodyPage.ClientCfg["SiteURL"] = c.GetSiteURL() if result := <-Srv.Store.Team().GetTeamsForEmail(email); result.Err != nil { c.Err = result.Err diff --git a/api/templates/email_change_body.html b/api/templates/email_change_body.html index 41fd6e4c3e..df2db87304 100644 --- a/api/templates/email_change_body.html +++ b/api/templates/email_change_body.html @@ -23,9 +23,9 @@
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
{{ .Props.Message }}
Go back to team site
-
+
|
|
- Any questions at all, mail us any time: {{.ClientProps.FeedbackEmail}}. + Any questions at all, mail us any time: {{.ClientCfg.FeedbackEmail}}. Best wishes, - The {{.ClientProps.SiteName}} Team + The {{.ClientCfg.SiteName}} Team |
-
+
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
{{.Props.TeamDisplayName}} started using {{.ClientProps.SiteName}}.
The team {{.Props.SenderStatus}} {{.Props.SenderName}}, has invited you to join {{.Props.TeamDisplayName}}.
{{.Props.TeamDisplayName}} started using {{.ClientCfg.SiteName}}.
The team {{.Props.SenderStatus}} {{.Props.SenderName}}, has invited you to join {{.Props.TeamDisplayName}}.
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
- If you no longer wish to receive these emails, click on the following link: Unsubscribe
+ If you no longer wish to receive these emails, click on the following link: Unsubscribe
Your email has been verified! Click here to log in.
; } else { - title = global.window.config.SiteName + ': You are almost done'; + title = global.window.mm_config.SiteName + ': You are almost done'; body =Please verify your email address. Check your inbox for an email.
; resend = ( ').attr('src', fileInfo.path + '_thumb.jpg').load(function loadWrapper(path, name) { + $('