From 6a1755d2e32c3f3bcaa67c33f32cb5eb5ab76ea2 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Fri, 16 Oct 2015 09:10:54 -0700 Subject: Inital support for multi-tab loging --- api/admin.go | 6 +++--- api/api.go | 2 +- api/context.go | 7 +++++-- api/team.go | 4 ++-- api/templates/email_change_body.html | 6 +++--- api/templates/email_change_subject.html | 2 +- api/templates/email_change_verify_body.html | 6 +++--- api/templates/email_change_verify_subject.html | 2 +- api/templates/error.html | 4 ++-- api/templates/find_teams_body.html | 10 +++++----- api/templates/find_teams_subject.html | 2 +- api/templates/invite_body.html | 8 ++++---- api/templates/invite_subject.html | 2 +- api/templates/password_change_body.html | 6 +++--- api/templates/password_change_subject.html | 2 +- api/templates/post_body.html | 6 +++--- api/templates/post_subject.html | 2 +- api/templates/reset_body.html | 6 +++--- api/templates/signup_team_body.html | 8 ++++---- api/templates/signup_team_subject.html | 2 +- api/templates/verify_body.html | 6 +++--- api/templates/verify_subject.html | 2 +- api/templates/welcome_body.html | 2 +- 23 files changed, 53 insertions(+), 50 deletions(-) (limited to 'api') diff --git a/api/admin.go b/api/admin.go index cd1e5d2de..7a5616ede 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 4da1de62d..6c7eda0a2 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/context.go b/api/context.go index bd9744bf8..1347b9aed 100644 --- a/api/context.go +++ b/api/context.go @@ -32,7 +32,10 @@ type Context struct { type Page struct { TemplateName string Props map[string]string - ClientProps map[string]string + ClientCfg map[string]string + User *model.User + Team *model.Team + Session *model.Session } func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { @@ -479,7 +482,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) { diff --git a/api/team.go b/api/team.go index 6aa5ec1bb..65dfcc95d 100644 --- a/api/team.go +++ b/api/team.go @@ -432,9 +432,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 41fd6e4c3..df2db8730 100644 --- a/api/templates/email_change_body.html +++ b/api/templates/email_change_body.html @@ -23,9 +23,9 @@ - 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
@@ -38,7 +38,7 @@

(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

diff --git a/api/templates/email_change_subject.html b/api/templates/email_change_subject.html index 962ae868e..4ff8026f1 100644 --- a/api/templates/email_change_subject.html +++ b/api/templates/email_change_subject.html @@ -1 +1 @@ -{{define "email_change_subject"}}[{{.ClientProps.SiteName}}] Your email address has changed for {{.Props.TeamDisplayName}}{{end}} +{{define "email_change_subject"}}[{{.ClientCfg.SiteName}}] Your email address has changed for {{.Props.TeamDisplayName}}{{end}} diff --git a/api/templates/email_change_verify_body.html b/api/templates/email_change_verify_body.html index a9b2a0741..f6bc3bc39 100644 --- a/api/templates/email_change_verify_body.html +++ b/api/templates/email_change_verify_body.html @@ -26,9 +26,9 @@ - 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
@@ -41,7 +41,7 @@

(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

diff --git a/api/templates/email_change_verify_subject.html b/api/templates/email_change_verify_subject.html index 5e2ac1452..744aaccfc 100644 --- a/api/templates/email_change_verify_subject.html +++ b/api/templates/email_change_verify_subject.html @@ -1 +1 @@ -{{define "email_change_verify_subject"}}[{{.ClientProps.SiteName}}] Verify new email address for {{.Props.TeamDisplayName}}{{end}} +{{define "email_change_verify_subject"}}[{{.ClientCfg.SiteName}}] Verify new email address for {{.Props.TeamDisplayName}}{{end}} diff --git a/api/templates/error.html b/api/templates/error.html index 6b643556e..6944f6c68 100644 --- a/api/templates/error.html +++ b/api/templates/error.html @@ -1,7 +1,7 @@ - {{ .ClientProps.SiteName }} - Error + {{ .ClientCfg.SiteName }} - Error @@ -22,7 +22,7 @@
-

{{ .ClientProps.SiteName }} needs your help:

+

{{ .ClientCfg.SiteName }} needs your help:

{{ .Props.Message }}

Go back to team site
diff --git a/api/templates/find_teams_body.html b/api/templates/find_teams_body.html index 41f9dac01..4669d51c1 100644 --- a/api/templates/find_teams_body.html +++ b/api/templates/find_teams_body.html @@ -9,7 +9,7 @@ @@ -31,9 +31,9 @@
- +
- 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
@@ -42,11 +42,11 @@

- +

(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

diff --git a/api/templates/find_teams_subject.html b/api/templates/find_teams_subject.html index 3c2bef589..f3a1437b3 100644 --- a/api/templates/find_teams_subject.html +++ b/api/templates/find_teams_subject.html @@ -1 +1 @@ -{{define "find_teams_subject"}}Your {{ .ClientProps.SiteName }} Teams{{end}} +{{define "find_teams_subject"}}Your {{ .ClientCfg.SiteName }} Teams{{end}} diff --git a/api/templates/invite_body.html b/api/templates/invite_body.html index 57feef5d9..930bc099d 100644 --- a/api/templates/invite_body.html +++ b/api/templates/invite_body.html @@ -18,7 +18,7 @@

You've been invited

-

{{.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}}.

Join Team

@@ -26,9 +26,9 @@ - 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
@@ -41,7 +41,7 @@

(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

diff --git a/api/templates/invite_subject.html b/api/templates/invite_subject.html index f46bdcfaf..10f68969f 100644 --- a/api/templates/invite_subject.html +++ b/api/templates/invite_subject.html @@ -1 +1 @@ -{{define "invite_subject"}}{{ .Props.SenderName }} invited you to join {{ .Props.TeamDisplayName }} Team on {{.ClientProps.SiteName}}{{end}} +{{define "invite_subject"}}{{ .Props.SenderName }} invited you to join {{ .Props.TeamDisplayName }} Team on {{.ClientCfg.SiteName}}{{end}} diff --git a/api/templates/password_change_body.html b/api/templates/password_change_body.html index 542df4b74..47a93fcb9 100644 --- a/api/templates/password_change_body.html +++ b/api/templates/password_change_body.html @@ -23,9 +23,9 @@ - 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
@@ -38,7 +38,7 @@

(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

diff --git a/api/templates/password_change_subject.html b/api/templates/password_change_subject.html index 283fda1af..e7a794090 100644 --- a/api/templates/password_change_subject.html +++ b/api/templates/password_change_subject.html @@ -1 +1 @@ -{{define "password_change_subject"}}You updated your password for {{.Props.TeamDisplayName}} on {{ .ClientProps.SiteName }}{{end}} +{{define "password_change_subject"}}You updated your password for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}} diff --git a/api/templates/post_body.html b/api/templates/post_body.html index 63a53bf3c..182134b1a 100644 --- a/api/templates/post_body.html +++ b/api/templates/post_body.html @@ -26,9 +26,9 @@ - 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
@@ -41,7 +41,7 @@

(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

diff --git a/api/templates/post_subject.html b/api/templates/post_subject.html index 944cd5a42..f53353d85 100644 --- a/api/templates/post_subject.html +++ b/api/templates/post_subject.html @@ -1 +1 @@ -{{define "post_subject"}}[{{.ClientProps.SiteName}}] {{.Props.TeamDisplayName}} Team Notifications for {{.Props.Month}} {{.Props.Day}}, {{.Props.Year}}{{end}} +{{define "post_subject"}}[{{.ClientCfg.SiteName}}] {{.Props.TeamDisplayName}} Team Notifications for {{.Props.Month}} {{.Props.Day}}, {{.Props.Year}}{{end}} diff --git a/api/templates/reset_body.html b/api/templates/reset_body.html index 4bafc57e8..5e5f6cafc 100644 --- a/api/templates/reset_body.html +++ b/api/templates/reset_body.html @@ -26,9 +26,9 @@ - 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
@@ -41,7 +41,7 @@

(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

diff --git a/api/templates/signup_team_body.html b/api/templates/signup_team_body.html index dc2cb32ec..6f3deb28b 100644 --- a/api/templates/signup_team_body.html +++ b/api/templates/signup_team_body.html @@ -21,14 +21,14 @@

Set up your team

- {{ .ClientProps.SiteName }} is one place for all your team communication, searchable and available anywhere.
You'll get more out of {{ .ClientProps.SiteName }} when your team is in constant communication--let's get them on board.

+ {{ .ClientCfg.SiteName }} is one place for all your team communication, searchable and available anywhere.
You'll get more out of {{ .ClientCfg.SiteName }} when your team is in constant communication--let's get them on board.

- 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
@@ -41,7 +41,7 @@

(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

diff --git a/api/templates/signup_team_subject.html b/api/templates/signup_team_subject.html index 7bc0cc640..236b288fa 100644 --- a/api/templates/signup_team_subject.html +++ b/api/templates/signup_team_subject.html @@ -1 +1 @@ -{{define "signup_team_subject"}}Invitation to {{ .ClientProps.SiteName }}{{end}} \ No newline at end of file +{{define "signup_team_subject"}}Invitation to {{ .ClientCfg.SiteName }}{{end}} \ No newline at end of file diff --git a/api/templates/verify_body.html b/api/templates/verify_body.html index 0613b5dd5..a93de9a71 100644 --- a/api/templates/verify_body.html +++ b/api/templates/verify_body.html @@ -26,9 +26,9 @@ - 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
@@ -41,7 +41,7 @@

(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

diff --git a/api/templates/verify_subject.html b/api/templates/verify_subject.html index 7990df84a..9a3a11282 100644 --- a/api/templates/verify_subject.html +++ b/api/templates/verify_subject.html @@ -1 +1 @@ -{{define "verify_subject"}}[{{ .Props.TeamDisplayName }} {{ .ClientProps.SiteName }}] Email Verification{{end}} +{{define "verify_subject"}}[{{ .Props.TeamDisplayName }} {{ .ClientCfg.SiteName }}] Email Verification{{end}} diff --git a/api/templates/welcome_body.html b/api/templates/welcome_body.html index b7cb3704d..485bc6351 100644 --- a/api/templates/welcome_body.html +++ b/api/templates/welcome_body.html @@ -43,7 +43,7 @@

(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

-- cgit v1.2.3-1-g7c22 From a8f3f76c592928a0907fbaddd71ab6b8f68d28d6 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Fri, 16 Oct 2015 19:05:55 -0700 Subject: Refactoring web classes to use multi-session --- api/context.go | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'api') diff --git a/api/context.go b/api/context.go index 1347b9aed..67eed674a 100644 --- a/api/context.go +++ b/api/context.go @@ -126,18 +126,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) @@ -492,6 +481,43 @@ 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 FindMultiSessionForTeamId(r *http.Request, teamId string) *model.Session { + + if multiCookie, err := r.Cookie(model.MULTI_SESSION_TOKEN); err == nil { + multiToken := multiCookie.Value + + if len(multiToken) > 0 { + tokens := strings.Split(multiToken, " ") + + for _, token := range tokens { + s := GetSession(token) + if s != nil && !s.IsExpired() && s.TeamId == teamId { + return s + } + } + } + } + + return nil +} + func AddSessionToCache(session *model.Session) { sessionCache.Add(session.Token, session) } -- cgit v1.2.3-1-g7c22 From fa3a0df2b63d3f1bbbad44bf20afa48fed42aa06 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 20 Oct 2015 04:37:51 -0700 Subject: Adding multi-session cookie --- api/context.go | 56 +++++++++++++++++++++++++++++++++----------------------- api/user.go | 17 ++++++----------- 2 files changed, 39 insertions(+), 34 deletions(-) (limited to 'api') diff --git a/api/context.go b/api/context.go index 67eed674a..e5ef8b312 100644 --- a/api/context.go +++ b/api/context.go @@ -30,12 +30,12 @@ type Context struct { } type Page struct { - TemplateName string - Props map[string]string - ClientCfg map[string]string - User *model.User - Team *model.Team - Session *model.Session + TemplateName string + Props map[string]string + ClientCfg map[string]string + User *model.User + Team *model.Team + SessionTokenHash string } func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { @@ -99,8 +99,29 @@ 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 + if cookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { + multiToken := cookie.Value + + fmt.Println(">>>>>>>> multiToken: " + multiToken) + + if len(multiToken) > 0 { + tokens := strings.Split(multiToken, " ") + + // If there is only 1 token in the cookie then just use it like normal + if len(tokens) == 1 { + token = multiToken + } else { + // If it is a multi-session token then find the correct session + sessionTokenHash := r.Header.Get(model.HEADER_MM_SESSION_TOKEN_HASH) + fmt.Println(">>>>>>>> sessionHash: " + sessionTokenHash + " url=" + r.URL.Path) + for _, t := range tokens { + if sessionTokenHash == model.HashPassword(t) { + token = token + break + } + } + } + } } } @@ -179,6 +200,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte(c.Err.ToJson())) } else { if c.Err.StatusCode == http.StatusUnauthorized { + fmt.Println("!!!!!!!!!!!!!!!! url=" + r.URL.Path) http.Redirect(w, r, c.GetTeamURL()+"/?redirect="+url.QueryEscape(r.URL.Path), http.StatusTemporaryRedirect) } else { RenderWebError(c.Err, w, r) @@ -310,25 +332,13 @@ func (c *Context) IsTeamAdmin() bool { func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) { - sessionCache.Remove(c.Session.Token) - - cookie := &http.Cookie{ - Name: model.SESSION_TOKEN, - Value: "", - Path: "/", - MaxAge: -1, - HttpOnly: true, - } - - http.SetCookie(w, cookie) - multiToken := "" - if oldMultiCookie, err := r.Cookie(model.MULTI_SESSION_TOKEN); err == nil { + if oldMultiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { multiToken = oldMultiCookie.Value } multiCookie := &http.Cookie{ - Name: model.MULTI_SESSION_TOKEN, + Name: model.SESSION_COOKIE_TOKEN, Value: strings.TrimSpace(strings.Replace(multiToken, c.Session.Token, "", -1)), Path: "/", MaxAge: model.SESSION_TIME_WEB_IN_SECS, @@ -500,7 +510,7 @@ func GetSession(token string) *model.Session { func FindMultiSessionForTeamId(r *http.Request, teamId string) *model.Session { - if multiCookie, err := r.Cookie(model.MULTI_SESSION_TOKEN); err == nil { + if multiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { multiToken := multiCookie.Value if len(multiToken) > 0 { diff --git a/api/user.go b/api/user.go index ac33e81a1..1216dd30d 100644 --- a/api/user.go +++ b/api/user.go @@ -428,21 +428,14 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, } w.Header().Set(model.HEADER_TOKEN, session.Token) - sessionCookie := &http.Cookie{ - Name: model.SESSION_TOKEN, - Value: session.Token, - Path: "/", - MaxAge: maxAge, - HttpOnly: true, - } - - http.SetCookie(w, sessionCookie) multiToken := "" - if originalMultiSessionCookie, err := r.Cookie(model.MULTI_SESSION_TOKEN); err == nil { + if originalMultiSessionCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { multiToken = originalMultiSessionCookie.Value } + fmt.Println("original: " + multiToken) + // Attempt to clean all the old tokens or duplicate tokens if len(multiToken) > 0 { tokens := strings.Split(multiToken, " ") @@ -463,8 +456,10 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, multiToken = strings.TrimSpace(session.Token + " " + multiToken) + fmt.Println("new: " + multiToken) + multiSessionCookie := &http.Cookie{ - Name: model.MULTI_SESSION_TOKEN, + Name: model.SESSION_COOKIE_TOKEN, Value: multiToken, Path: "/", MaxAge: maxAge, -- cgit v1.2.3-1-g7c22 From 1fc12dd8ba2238eba7d154eee55e1381e7415372 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 20 Oct 2015 14:49:42 -0700 Subject: Multi-session login --- api/context.go | 124 +++++++++++++++++++++++++++++++++------------------------ api/post.go | 2 +- api/user.go | 6 +-- 3 files changed, 75 insertions(+), 57 deletions(-) (limited to 'api') diff --git a/api/context.go b/api/context.go index e5ef8b312..28d6951da 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,23 +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 - ClientCfg map[string]string - User *model.User - Team *model.Team - SessionTokenHash 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 { @@ -99,29 +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_COOKIE_TOKEN); err == nil { - multiToken := cookie.Value - - fmt.Println(">>>>>>>> multiToken: " + multiToken) - - if len(multiToken) > 0 { - tokens := strings.Split(multiToken, " ") - - // If there is only 1 token in the cookie then just use it like normal - if len(tokens) == 1 { - token = multiToken + tokens := GetMultiSessionCookie(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 { - // If it is a multi-session token then find the correct session - sessionTokenHash := r.Header.Get(model.HEADER_MM_SESSION_TOKEN_HASH) - fmt.Println(">>>>>>>> sessionHash: " + sessionTokenHash + " url=" + r.URL.Path) - for _, t := range tokens { - if sessionTokenHash == model.HashPassword(t) { - token = token - break + 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 } } @@ -200,7 +210,6 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte(c.Err.ToJson())) } else { if c.Err.StatusCode == http.StatusUnauthorized { - fmt.Println("!!!!!!!!!!!!!!!! url=" + r.URL.Path) http.Redirect(w, r, c.GetTeamURL()+"/?redirect="+url.QueryEscape(r.URL.Path), http.StatusTemporaryRedirect) } else { RenderWebError(c.Err, w, r) @@ -332,20 +341,30 @@ func (c *Context) IsTeamAdmin() bool { func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) { - multiToken := "" - if oldMultiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { - multiToken = oldMultiCookie.Value - } + // multiToken := "" + // if oldMultiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { + // multiToken = oldMultiCookie.Value + // } - multiCookie := &http.Cookie{ + // 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_COOKIE_TOKEN, - Value: strings.TrimSpace(strings.Replace(multiToken, c.Session.Token, "", -1)), + Value: "", Path: "/", - MaxAge: model.SESSION_TIME_WEB_IN_SECS, + MaxAge: -1, HttpOnly: true, } - http.SetCookie(w, multiCookie) + http.SetCookie(w, cookie) } func (c *Context) SetInvalidParam(where string, name string) { @@ -508,24 +527,27 @@ func GetSession(token string) *model.Session { return session } -func FindMultiSessionForTeamId(r *http.Request, teamId string) *model.Session { - +func GetMultiSessionCookie(r *http.Request) []string { if multiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { multiToken := multiCookie.Value if len(multiToken) > 0 { - tokens := strings.Split(multiToken, " ") + return strings.Split(multiToken, " ") + } + } - for _, token := range tokens { - s := GetSession(token) - if s != nil && !s.IsExpired() && s.TeamId == teamId { - return s - } - } + return []string{} +} + +func FindMultiSessionForTeamId(r *http.Request, teamId string) (int64, *model.Session) { + for index, token := range GetMultiSessionCookie(r) { + s := GetSession(token) + if s != nil && !s.IsExpired() && s.TeamId == teamId { + return int64(index), s } } - return nil + return -1, nil } func AddSessionToCache(session *model.Session) { diff --git a/api/post.go b/api/post.go index 73a63cb72..ded71f727 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/user.go b/api/user.go index 1216dd30d..3770baa76 100644 --- a/api/user.go +++ b/api/user.go @@ -434,8 +434,6 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, multiToken = originalMultiSessionCookie.Value } - fmt.Println("original: " + multiToken) - // Attempt to clean all the old tokens or duplicate tokens if len(multiToken) > 0 { tokens := strings.Split(multiToken, " ") @@ -454,9 +452,7 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, } } - multiToken = strings.TrimSpace(session.Token + " " + multiToken) - - fmt.Println("new: " + multiToken) + multiToken = strings.TrimSpace(multiToken + " " + session.Token) multiSessionCookie := &http.Cookie{ Name: model.SESSION_COOKIE_TOKEN, -- cgit v1.2.3-1-g7c22 From 6cc3bfe7a96e66d27a5b7f08bc1dc15a742b36ab Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 22 Oct 2015 09:31:27 -0400 Subject: Refactoring direct channel creation to use transaction to avaoid state where channel is created without both users --- api/channel.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/channel.go b/api/channel.go index 70f7eba4b..9c7ac053b 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 - } 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 - } + cm1 := &model.ChannelMember{ + UserId: c.Session.UserId, + Roles: model.CHANNEL_ROLE_ADMIN, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + cm2 := &model.ChannelMember{ + UserId: otherUserId, + Roles: "", + NotifyProps: model.GetDefaultChannelNotifyProps(), + } - return sc, nil + if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { + return nil, result.Err + } else { + return result.Data.(*model.Channel), nil } } -- cgit v1.2.3-1-g7c22 From 4734912c521be4367b1d8ca255cc76c0095839b4 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Thu, 22 Oct 2015 10:53:39 -0400 Subject: Prevent users from resetting their password when the user is using SSO --- api/user.go | 10 ++++++++++ api/user_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'api') diff --git a/api/user.go b/api/user.go index 0c7278711..5e5ff79f1 100644 --- a/api/user.go +++ b/api/user.go @@ -1241,6 +1241,11 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { user = result.Data.(*model.User) } + if len(user.AuthData) != 0 { + c.Err = model.NewAppError("sendPasswordReset", "Cannot reset password for SSO accounts", "userId="+user.Id+", teamId="+team.Id) + return + } + newProps := make(map[string]string) newProps["user_id"] = user.Id newProps["time"] = fmt.Sprintf("%v", model.GetMillis()) @@ -1325,6 +1330,11 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { user = result.Data.(*model.User) } + if len(user.AuthData) != 0 { + c.Err = model.NewAppError("resetPassword", "Cannot reset password for SSO accounts", "userId="+user.Id+", teamId="+team.Id) + return + } + if user.TeamId != team.Id { c.Err = model.NewAppError("resetPassword", "Trying to reset password for user on wrong team.", "userId="+user.Id+", teamId="+team.Id) c.Err.StatusCode = http.StatusForbidden diff --git a/api/user_test.go b/api/user_test.go index 77309e5b2..b54e030c5 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -817,6 +817,16 @@ func TestSendPasswordReset(t *testing.T) { if _, err := Client.SendPasswordReset(data); err == nil { t.Fatal("Should have errored - bad name") } + + user2 := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", AuthData: "1", AuthService: "random"} + user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(user2.Id)) + + data["email"] = user2.Email + data["name"] = team.Name + if _, err := Client.SendPasswordReset(data); err == nil { + t.Fatal("should have errored - SSO user can't send reset password link") + } } func TestResetPassword(t *testing.T) { @@ -901,6 +911,20 @@ func TestResetPassword(t *testing.T) { if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - domain team doesn't match user team") } + + user2 := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", AuthData: "1", AuthService: "random"} + user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(user2.Id)) + + data["new_password"] = "newpwd" + props["user_id"] = user2.Id + props["time"] = fmt.Sprintf("%v", model.GetMillis()) + data["data"] = model.MapToJson(props) + data["hash"] = model.HashPassword(fmt.Sprintf("%v:%v", data["data"], utils.Cfg.EmailSettings.PasswordResetSalt)) + data["name"] = team.Name + if _, err := Client.ResetPassword(data); err == nil { + t.Fatal("should have errored - SSO user can't reset password") + } } func TestUserUpdateNotify(t *testing.T) { -- cgit v1.2.3-1-g7c22 From cbbee5cadb1c0096bfff9ce1cc80d4be7adb5717 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 22 Oct 2015 09:36:46 -0700 Subject: Addressing issues from group code review --- api/user.go | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'api') diff --git a/api/user.go b/api/user.go index a5bc59a8d..406cbe291 100644 --- a/api/user.go +++ b/api/user.go @@ -429,26 +429,15 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, w.Header().Set(model.HEADER_TOKEN, session.Token) - multiToken := "" - if originalMultiSessionCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { - multiToken = originalMultiSessionCookie.Value - } - - // Attempt to clean all the old tokens or duplicate tokens - if len(multiToken) > 0 { - tokens := strings.Split(multiToken, " ") - - multiToken = "" - seen := make(map[string]string) - seen[session.TeamId] = session.TeamId - for _, token := range tokens { - if sr := <-Srv.Store.Session().Get(token); sr.Err == nil { - s := sr.Data.(*model.Session) - if !s.IsExpired() && seen[s.TeamId] == "" { - multiToken += " " + token - seen[s.TeamId] = s.TeamId - } - } + tokens := GetMultiSessionCookie(r) + multiToken = "" + seen := make(map[string]string) + seen[session.TeamId] = session.TeamId + for _, token := range tokens { + s := GetSession(token) + if s != nil && !s.IsExpired() && seen[s.TeamId] == "" { + multiToken += " " + token + seen[s.TeamId] = s.TeamId } } -- cgit v1.2.3-1-g7c22 From ab18616725fc7c3df00215e63830f6ec0a05976c Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 22 Oct 2015 10:17:25 -0700 Subject: Fixing group code review issues --- api/user.go | 2 +- api/web_team_hub.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/user.go b/api/user.go index 406cbe291..4c53bd104 100644 --- a/api/user.go +++ b/api/user.go @@ -430,7 +430,7 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, w.Header().Set(model.HEADER_TOKEN, session.Token) tokens := GetMultiSessionCookie(r) - multiToken = "" + multiToken := "" seen := make(map[string]string) seen[session.TeamId] = session.TeamId for _, token := range tokens { diff --git a/api/web_team_hub.go b/api/web_team_hub.go index 6a25b7d3d..12a14da17 100644 --- a/api/web_team_hub.go +++ b/api/web_team_hub.go @@ -96,7 +96,8 @@ func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool { } } else { // Don't share a user's view events with other users - if msg.Action == model.ACTION_CHANNEL_VIEWED { + // but you still need to share it with yourself + if webCon.UserId != msg.UserId && msg.Action == model.ACTION_CHANNEL_VIEWED { return false } -- cgit v1.2.3-1-g7c22 From a431ba2c22918412d90d00c37fb89f6841f47eb8 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Thu, 22 Oct 2015 14:27:47 -0400 Subject: Delete webhooks when the associated channel gets deleted --- api/channel.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'api') diff --git a/api/channel.go b/api/channel.go index 70f7eba4b..0a8489606 100644 --- a/api/channel.go +++ b/api/channel.go @@ -503,6 +503,8 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { sc := Srv.Store.Channel().Get(id) scm := Srv.Store.Channel().GetMember(id, c.Session.UserId) uc := Srv.Store.User().Get(c.Session.UserId) + ihc := Srv.Store.Webhook().GetIncomingByChannel(id) + ohc := Srv.Store.Webhook().GetOutgoingByChannel(id) if cresult := <-sc; cresult.Err != nil { c.Err = cresult.Err @@ -513,10 +515,18 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { } else if scmresult := <-scm; scmresult.Err != nil { c.Err = scmresult.Err return + } else if ihcresult := <-ihc; ihcresult.Err != nil { + c.Err = ihcresult.Err + return + } else if ohcresult := <-ohc; ohcresult.Err != nil { + c.Err = ohcresult.Err + return } else { channel := cresult.Data.(*model.Channel) user := uresult.Data.(*model.User) channelMember := scmresult.Data.(model.ChannelMember) + incomingHooks := ihcresult.Data.([]*model.IncomingWebhook) + outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook) if !c.HasPermissionsToTeam(channel.TeamId, "deleteChannel") { return @@ -540,6 +550,23 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { return } + now := model.GetMillis() + for _, hook := range incomingHooks { + go func() { + if result := <-Srv.Store.Webhook().DeleteIncoming(hook.Id, now); result.Err != nil { + l4g.Error("Encountered error deleting incoming webhook, id=" + hook.Id) + } + }() + } + + for _, hook := range outgoingHooks { + go func() { + if result := <-Srv.Store.Webhook().DeleteOutgoing(hook.Id, now); result.Err != nil { + l4g.Error("Encountered error deleting outgoing webhook, id=" + hook.Id) + } + }() + } + if dresult := <-Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); dresult.Err != nil { c.Err = dresult.Err return -- cgit v1.2.3-1-g7c22 From 079f047540504c987c7f97fc46e296ea1fc9aa78 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 22 Oct 2015 18:06:22 -0700 Subject: Fixing code review issues --- api/context.go | 6 +++--- api/user.go | 2 +- api/web_team_hub.go | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'api') diff --git a/api/context.go b/api/context.go index 28d6951da..9be3e85cc 100644 --- a/api/context.go +++ b/api/context.go @@ -101,7 +101,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Attempt to parse the token from the cookie if len(token) == 0 { - tokens := GetMultiSessionCookie(r) + 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 { @@ -527,7 +527,7 @@ func GetSession(token string) *model.Session { return session } -func GetMultiSessionCookie(r *http.Request) []string { +func GetMultiSessionCookieTokens(r *http.Request) []string { if multiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { multiToken := multiCookie.Value @@ -540,7 +540,7 @@ func GetMultiSessionCookie(r *http.Request) []string { } func FindMultiSessionForTeamId(r *http.Request, teamId string) (int64, *model.Session) { - for index, token := range GetMultiSessionCookie(r) { + for index, token := range GetMultiSessionCookieTokens(r) { s := GetSession(token) if s != nil && !s.IsExpired() && s.TeamId == teamId { return int64(index), s diff --git a/api/user.go b/api/user.go index 4c53bd104..aec975524 100644 --- a/api/user.go +++ b/api/user.go @@ -429,7 +429,7 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, w.Header().Set(model.HEADER_TOKEN, session.Token) - tokens := GetMultiSessionCookie(r) + tokens := GetMultiSessionCookieTokens(r) multiToken := "" seen := make(map[string]string) seen[session.TeamId] = session.TeamId diff --git a/api/web_team_hub.go b/api/web_team_hub.go index 12a14da17..6a25b7d3d 100644 --- a/api/web_team_hub.go +++ b/api/web_team_hub.go @@ -96,8 +96,7 @@ func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool { } } else { // Don't share a user's view events with other users - // but you still need to share it with yourself - if webCon.UserId != msg.UserId && msg.Action == model.ACTION_CHANNEL_VIEWED { + if msg.Action == model.ACTION_CHANNEL_VIEWED { return false } -- cgit v1.2.3-1-g7c22