diff options
68 files changed, 509 insertions, 364 deletions
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..67eed674a 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 { @@ -123,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) @@ -479,7 +471,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 +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) } diff --git a/api/team.go b/api/team.go index f6038566a..666fd909b 100644 --- a/api/team.go +++ b/api/team.go @@ -431,9 +431,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 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -38,7 +38,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -41,7 +41,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> - <title>{{ .ClientProps.SiteName }} - Error</title> + <title>{{ .ClientCfg.SiteName }} - Error</title> <link rel="stylesheet" href="/static/css/bootstrap-3.3.5.min.css"> <link rel="stylesheet" href="/static/css/jasny-bootstrap.min.css" rel="stylesheet"> @@ -22,7 +22,7 @@ <div class="container-fluid"> <div class="error__container"> <div class="error__icon"><i class="fa fa-exclamation-triangle"></i></div> - <h2>{{ .ClientProps.SiteName }} needs your help:</h2> + <h2>{{ .ClientCfg.SiteName }} needs your help:</h2> <p>{{ .Props.Message }}</p> <a href="{{.Props.SiteURL}}">Go back to team site</a> </div> 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 @@ <table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;"> <tr> <td style="padding: 20px 20px 10px; text-align:left;"> - <img src="{{.ClientProps.SiteURL}}/static/images/logo-email.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.ClientCfg.SiteURL}}/static/images/logo-email.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -31,9 +31,9 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -42,11 +42,11 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 11px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.ClientProps.SiteURL}}/static/images/circles.png" alt=""> + <img width="65" src="{{.ClientCfg.SiteURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ <tr> <td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;"> <h2 style="font-weight: normal; margin-top: 10px;">You've been invited</h2> - <p>{{.Props.TeamDisplayName}} started using {{.ClientProps.SiteName}}.<br> The team {{.Props.SenderStatus}} <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamDisplayName}}</strong>.</p> + <p>{{.Props.TeamDisplayName}} started using {{.ClientCfg.SiteName}}.<br> The team {{.Props.SenderStatus}} <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamDisplayName}}</strong>.</p> <p style="margin: 20px 0 15px"> <a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Join Team</a> </p> @@ -26,9 +26,9 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -41,7 +41,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -38,7 +38,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -41,7 +41,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -41,7 +41,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ <p style="margin: 20px 0 25px"> <a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Set up your team</a> </p> - {{ .ClientProps.SiteName }} is one place for all your team communication, searchable and available anywhere.<br>You'll get more out of {{ .ClientProps.SiteName }} when your team is in constant communication--let's get them on board.<br></p> + {{ .ClientCfg.SiteName }} is one place for all your team communication, searchable and available anywhere.<br>You'll get more out of {{ .ClientCfg.SiteName }} when your team is in constant communication--let's get them on board.<br></p> </td> </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -41,7 +41,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ </tr> <tr> <td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;"> - Any questions at all, mail us any time: <a href="mailto:{{.ClientProps.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientProps.FeedbackEmail}}</a>.<br> + Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br> Best wishes,<br> - The {{.ClientProps.SiteName}} Team<br> + The {{.ClientCfg.SiteName}} Team<br> </td> </tr> </table> @@ -41,7 +41,7 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> 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 @@ </p> <p style="padding: 0 50px;"> (c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> - If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientProps.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> + If you no longer wish to receive these emails, click on the following link: <a href="mailto:{{.ClientCfg.FeedbackEmail}}?subject=Unsubscribe&body=Unsubscribe" style="text-decoration: none; color:#2389D7;">Unsubscribe</a> </p> </td> </tr> diff --git a/utils/config.go b/utils/config.go index e3349650b..c1e3a8d2a 100644 --- a/utils/config.go +++ b/utils/config.go @@ -26,7 +26,7 @@ const ( var Cfg *model.Config = &model.Config{} var CfgLastModified int64 = 0 var CfgFileName string = "" -var ClientProperties map[string]string = map[string]string{} +var ClientCfg map[string]string = map[string]string{} var SanitizeOptions map[string]bool = map[string]bool{} func FindConfigFile(fileName string) string { @@ -161,7 +161,7 @@ func LoadConfig(fileName string) { Cfg = &config SanitizeOptions = getSanitizeOptions(Cfg) - ClientProperties = getClientProperties(Cfg) + ClientCfg = getClientConfig(Cfg) } func getSanitizeOptions(c *model.Config) map[string]bool { @@ -172,7 +172,7 @@ func getSanitizeOptions(c *model.Config) map[string]bool { return options } -func getClientProperties(c *model.Config) map[string]string { +func getClientConfig(c *model.Config) map[string]string { props := make(map[string]string) props["Version"] = model.CurrentVersion diff --git a/web/react/components/about_build_modal.jsx b/web/react/components/about_build_modal.jsx index e8a46086a..6962876d4 100644 --- a/web/react/components/about_build_modal.jsx +++ b/web/react/components/about_build_modal.jsx @@ -14,7 +14,7 @@ export default class AboutBuildModal extends React.Component { } render() { - const config = global.window.config; + const config = global.window.mm_config; return ( <Modal diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx index 270631db2..55b4a55c0 100644 --- a/web/react/components/channel_loader.jsx +++ b/web/react/components/channel_loader.jsx @@ -26,7 +26,6 @@ export default class ChannelLoader extends React.Component { } componentDidMount() { /* Initial aysnc loads */ - AsyncClient.getMe(); AsyncClient.getPosts(ChannelStore.getCurrentId()); AsyncClient.getChannels(true, true); AsyncClient.getChannelExtraInfo(true); diff --git a/web/react/components/email_verify.jsx b/web/react/components/email_verify.jsx index 940b01f8d..9c07853b7 100644 --- a/web/react/components/email_verify.jsx +++ b/web/react/components/email_verify.jsx @@ -19,10 +19,10 @@ export default class EmailVerify extends React.Component { var resend = ''; var resendConfirm = ''; if (this.props.isVerified === 'true') { - title = global.window.config.SiteName + ' Email Verified'; + title = global.window.mm_config.SiteName + ' Email Verified'; body = <p>Your email has been verified! Click <a href={this.props.teamURL + '?email=' + this.props.userEmail}>here</a> to log in.</p>; } else { - title = global.window.config.SiteName + ': You are almost done'; + title = global.window.mm_config.SiteName + ': You are almost done'; body = <p>Please verify your email address. Check your inbox for an email.</p>; resend = ( <button diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index 90290099d..4986f88b6 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -21,7 +21,7 @@ export default class InviteMemberModal extends React.Component { emailErrors: {}, firstNameErrors: {}, lastNameErrors: {}, - emailEnabled: global.window.config.SendEmailNotifications === 'true' + emailEnabled: global.window.mm_config.SendEmailNotifications === 'true' }; } diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index c982d57ca..108735caf 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -16,7 +16,7 @@ export default class Login extends React.Component { } handleSubmit(e) { e.preventDefault(); - let state = {}; + var state = {}; const name = this.props.teamName; if (!name) { @@ -49,8 +49,7 @@ export default class Login extends React.Component { this.setState(state); Client.loginByEmail(name, email, password, - function loggedIn(data) { - UserStore.setCurrentUser(data); + () => { UserStore.setLastEmail(email); const redirect = Utils.getUrlParameter('redirect'); @@ -60,7 +59,7 @@ export default class Login extends React.Component { window.location.href = '/' + name + '/channels/town-square'; } }, - function loginFailed(err) { + (err) => { if (err.message === 'Login failed because email address has not been verified') { window.location.href = '/verify_email?teamname=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(email); return; @@ -68,7 +67,7 @@ export default class Login extends React.Component { state.serverError = err.message; this.valid = false; this.setState(state); - }.bind(this) + } ); } render() { @@ -95,7 +94,7 @@ export default class Login extends React.Component { } let loginMessage = []; - if (global.window.config.EnableSignUpWithGitLab === 'true') { + if (global.window.mm_config.EnableSignUpWithGitLab === 'true') { loginMessage.push( <a className='btn btn-custom-login gitlab' @@ -124,7 +123,7 @@ export default class Login extends React.Component { } let emailSignup; - if (global.window.config.EnableSignUpWithEmail === 'true') { + if (global.window.mm_config.EnableSignUpWithEmail === 'true') { emailSignup = ( <div> <div className={'form-group' + errorClass}> @@ -186,7 +185,7 @@ export default class Login extends React.Component { <div className='signup-team__container'> <h5 className='margin--less'>Sign in to:</h5> <h2 className='signup-team__name'>{teamDisplayName}</h2> - <h2 className='signup-team__subdomain'>on {global.window.config.SiteName}</h2> + <h2 className='signup-team__subdomain'>on {global.window.mm_config.SiteName}</h2> <form onSubmit={this.handleSubmit}> {verifiedBox} <div className={'form-group' + errorClass}> diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx index 1cb13bbe5..2b2cc2f95 100644 --- a/web/react/components/navbar_dropdown.jsx +++ b/web/react/components/navbar_dropdown.jsx @@ -178,7 +178,7 @@ export default class NavbarDropdown extends React.Component { }); } - if (global.window.config.EnableTeamCreation === 'true') { + if (global.window.mm_config.EnableTeamCreation === 'true') { teams.push( <li key='newTeam_li'> <a diff --git a/web/react/components/password_reset_form.jsx b/web/react/components/password_reset_form.jsx index 217f1b393..b452c40b7 100644 --- a/web/react/components/password_reset_form.jsx +++ b/web/react/components/password_reset_form.jsx @@ -61,7 +61,7 @@ export default class PasswordResetForm extends React.Component { <div className='signup-team__container'> <h3>Password Reset</h3> <form onSubmit={this.handlePasswordReset}> - <p>{'Enter a new password for your ' + this.props.teamDisplayName + ' ' + global.window.config.SiteName + ' account.'}</p> + <p>{'Enter a new password for your ' + this.props.teamDisplayName + ' ' + global.window.mm_config.SiteName + ' account.'}</p> <div className={formClass}> <input type='password' diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index 64d6776b4..3b3b0383c 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -159,7 +159,7 @@ export default class Post extends React.Component { var profilePic = null; if (!this.props.hideProfilePic) { let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp; - if (post.props && post.props.from_webhook && global.window.config.EnablePostIconOverride === 'true') { + if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') { if (post.props.override_icon_url) { src = post.props.override_icon_url; } diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index fb838b736..ae94bd42e 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -119,12 +119,12 @@ export default class PostBody extends React.Component { this.setState({youtubeTitle: metadata.title}); } - if (global.window.config.GoogleDeveloperKey && !this.receivedYoutubeData) { + if (global.window.mm_config.GoogleDeveloperKey && !this.receivedYoutubeData) { $.ajax({ async: true, url: 'https://www.googleapis.com/youtube/v3/videos', type: 'GET', - data: {part: 'snippet', id: youtubeId, key: global.window.config.GoogleDeveloperKey}, + data: {part: 'snippet', id: youtubeId, key: global.window.mm_config.GoogleDeveloperKey}, success: success.bind(this) }); } diff --git a/web/react/components/post_header.jsx b/web/react/components/post_header.jsx index 0ba5ce6b5..45e60c767 100644 --- a/web/react/components/post_header.jsx +++ b/web/react/components/post_header.jsx @@ -16,7 +16,7 @@ export default class PostHeader extends React.Component { let botIndicator; if (post.props && post.props.from_webhook) { - if (post.props.override_username && global.window.config.EnablePostUsernameOverride === 'true') { + if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { userProfile = ( <UserProfile userId={post.user_id} diff --git a/web/react/components/rhs_root_post.jsx b/web/react/components/rhs_root_post.jsx index a9f1fcd30..979c56036 100644 --- a/web/react/components/rhs_root_post.jsx +++ b/web/react/components/rhs_root_post.jsx @@ -121,7 +121,7 @@ export default class RhsRootPost extends React.Component { let botIndicator; if (post.props && post.props.from_webhook) { - if (post.props.override_username && global.window.config.EnablePostUsernameOverride === 'true') { + if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { userProfile = ( <UserProfile userId={post.user_id} @@ -135,7 +135,7 @@ export default class RhsRootPost extends React.Component { } let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp; - if (post.props && post.props.from_webhook && global.window.config.EnablePostIconOverride === 'true') { + if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') { if (post.props.override_icon_url) { src = post.props.override_icon_url; } diff --git a/web/react/components/setting_picture.jsx b/web/react/components/setting_picture.jsx index 2f577fe39..b6bcb13a6 100644 --- a/web/react/components/setting_picture.jsx +++ b/web/react/components/setting_picture.jsx @@ -79,7 +79,7 @@ export default class SettingPicture extends React.Component { >Save</a> ); } - var helpText = 'Upload a profile picture in either JPG or PNG format, at least ' + global.window.config.ProfileWidth + 'px in width and ' + global.window.config.ProfileHeight + 'px height.'; + var helpText = 'Upload a profile picture in either JPG or PNG format, at least ' + global.window.mm_config.ProfileWidth + 'px in width and ' + global.window.mm_config.ProfileHeight + 'px height.'; var self = this; return ( diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index f88522fb9..14868985b 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -171,8 +171,8 @@ export default class Sidebar extends React.Component { const channel = ChannelStore.getCurrent(); if (channel) { let currentSiteName = ''; - if (global.window.config.SiteName != null) { - currentSiteName = global.window.config.SiteName; + if (global.window.mm_config.SiteName != null) { + currentSiteName = global.window.mm_config.SiteName; } let currentChannelName = channel.display_name; diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index c3709bc0a..6b29da622 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -61,7 +61,7 @@ export default class SidebarHeader extends React.Component { } SidebarHeader.defaultProps = { - teamDisplayName: global.window.config.SiteName, + teamDisplayName: global.window.mm_config.SiteName, teamType: '' }; SidebarHeader.propTypes = { diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx index ac101d631..870fe77e5 100644 --- a/web/react/components/sidebar_right_menu.jsx +++ b/web/react/components/sidebar_right_menu.jsx @@ -92,8 +92,8 @@ export default class SidebarRightMenu extends React.Component { } var siteName = ''; - if (global.window.config.SiteName != null) { - siteName = global.window.config.SiteName; + if (global.window.mm_config.SiteName != null) { + siteName = global.window.mm_config.SiteName; } var teamDisplayName = siteName; if (this.props.teamDisplayName) { diff --git a/web/react/components/signup_team.jsx b/web/react/components/signup_team.jsx index 48cf2c73c..1858703ef 100644 --- a/web/react/components/signup_team.jsx +++ b/web/react/components/signup_team.jsx @@ -14,19 +14,19 @@ export default class TeamSignUp extends React.Component { var count = 0; - if (global.window.config.EnableSignUpWithEmail === 'true') { + if (global.window.mm_config.EnableSignUpWithEmail === 'true') { count = count + 1; } - if (global.window.config.EnableSignUpWithGitLab === 'true') { + if (global.window.mm_config.EnableSignUpWithGitLab === 'true') { count = count + 1; } if (count > 1) { this.state = {page: 'choose'}; - } else if (global.window.config.EnableSignUpWithEmail === 'true') { + } else if (global.window.mm_config.EnableSignUpWithEmail === 'true') { this.state = {page: 'email'}; - } else if (global.window.config.EnableSignUpWithGitLab === 'true') { + } else if (global.window.mm_config.EnableSignUpWithGitLab === 'true') { this.state = {page: 'gitlab'}; } } diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index f74c29d27..d70ea5065 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -82,30 +82,29 @@ export default class SignupUserComplete extends React.Component { }); client.createUser(user, this.props.data, this.props.hash, - function createUserSuccess() { + () => { client.track('signup', 'signup_user_02_complete'); client.loginByEmail(this.props.teamName, user.email, user.password, - function emailLoginSuccess(data) { + () => { UserStore.setLastEmail(user.email); - UserStore.setCurrentUser(data); if (this.props.hash > 0) { BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: 'finished'})); } window.location.href = '/' + this.props.teamName + '/channels/town-square'; - }.bind(this), - function emailLoginFailure(err) { + }, + (err) => { if (err.message === 'Login failed because email address has not been verified') { window.location.href = '/verify_email?email=' + encodeURIComponent(user.email) + '&teamname=' + encodeURIComponent(this.props.teamName); } else { this.setState({serverError: err.message}); } - }.bind(this) + } ); - }.bind(this), - function createUserFailure(err) { + }, + (err) => { this.setState({serverError: err.message}); - }.bind(this) + } ); } render() { @@ -149,7 +148,7 @@ export default class SignupUserComplete extends React.Component { // set up the email entry and hide it if an email was provided var yourEmailIs = ''; if (this.state.user.email) { - yourEmailIs = <span>Your email address is <strong>{this.state.user.email}</strong>. You'll use this address to sign in to {global.window.config.SiteName}.</span>; + yourEmailIs = <span>Your email address is <strong>{this.state.user.email}</strong>. You'll use this address to sign in to {global.window.mm_config.SiteName}.</span>; } var emailContainerStyle = 'margin--extra'; @@ -177,7 +176,7 @@ export default class SignupUserComplete extends React.Component { ); var signupMessage = []; - if (global.window.config.EnableSignUpWithGitLab === 'true') { + if (global.window.mm_config.EnableSignUpWithGitLab === 'true') { signupMessage.push( <a className='btn btn-custom-login gitlab' @@ -190,7 +189,7 @@ export default class SignupUserComplete extends React.Component { } var emailSignup; - if (global.window.config.EnableSignUpWithEmail === 'true') { + if (global.window.mm_config.EnableSignUpWithEmail === 'true') { emailSignup = ( <div> <div className='inner__content'> @@ -259,7 +258,7 @@ export default class SignupUserComplete extends React.Component { /> <h5 className='margin--less'>Welcome to:</h5> <h2 className='signup-team__name'>{this.props.teamDisplayName}</h2> - <h2 className='signup-team__subdomain'>on {global.window.config.SiteName}</h2> + <h2 className='signup-team__subdomain'>on {global.window.mm_config.SiteName}</h2> <h4 className='color--light'>Let's create your account</h4> {signupMessage} {emailSignup} diff --git a/web/react/components/team_signup_choose_auth.jsx b/web/react/components/team_signup_choose_auth.jsx index fa898f63c..0254c8b4e 100644 --- a/web/react/components/team_signup_choose_auth.jsx +++ b/web/react/components/team_signup_choose_auth.jsx @@ -8,7 +8,7 @@ export default class ChooseAuthPage extends React.Component { } render() { var buttons = []; - if (global.window.config.EnableSignUpWithGitLab === 'true') { + if (global.window.mm_config.EnableSignUpWithGitLab === 'true') { buttons.push( <a className='btn btn-custom-login gitlab btn-full' @@ -26,7 +26,7 @@ export default class ChooseAuthPage extends React.Component { ); } - if (global.window.config.EnableSignUpWithEmail === 'true') { + if (global.window.mm_config.EnableSignUpWithEmail === 'true') { buttons.push( <a className='btn btn-custom-login email btn-full' diff --git a/web/react/components/team_signup_password_page.jsx b/web/react/components/team_signup_password_page.jsx index daa898b53..67fd686bc 100644 --- a/web/react/components/team_signup_password_page.jsx +++ b/web/react/components/team_signup_password_page.jsx @@ -36,15 +36,14 @@ export default class TeamSignupPasswordPage extends React.Component { delete teamSignup.wizard; Client.createTeamFromSignup(teamSignup, - function success() { + () => { Client.track('signup', 'signup_team_08_complete'); var props = this.props; Client.loginByEmail(teamSignup.team.name, teamSignup.team.email, teamSignup.user.password, - function loginSuccess(data) { + () => { UserStore.setLastEmail(teamSignup.team.email); - UserStore.setCurrentUser(data); if (this.props.hash > 0) { BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: 'finished'})); } @@ -54,21 +53,21 @@ export default class TeamSignupPasswordPage extends React.Component { props.updateParent(props.state, true); window.location.href = '/' + teamSignup.team.name + '/channels/town-square'; - }.bind(this), - function loginFail(err) { + }, + (err) => { if (err.message === 'Login failed because email address has not been verified') { window.location.href = '/verify_email?email=' + encodeURIComponent(teamSignup.team.email) + '&teamname=' + encodeURIComponent(teamSignup.team.name); } else { this.setState({serverError: err.message}); $('#finish-button').button('reset'); } - }.bind(this) + } ); - }.bind(this), - function error(err) { + }, + (err) => { this.setState({serverError: err.message}); $('#finish-button').button('reset'); - }.bind(this) + } ); } render() { @@ -129,7 +128,7 @@ export default class TeamSignupPasswordPage extends React.Component { Finish </button> </div> - <p>By proceeding to create your account and use {global.window.config.SiteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {global.window.config.SiteName}.</p> + <p>By proceeding to create your account and use {global.window.mm_config.SiteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {global.window.mm_config.SiteName}.</p> <div className='margin--extra'> <a href='#' diff --git a/web/react/components/team_signup_send_invites_page.jsx b/web/react/components/team_signup_send_invites_page.jsx index e7bc0272d..b42343da0 100644 --- a/web/react/components/team_signup_send_invites_page.jsx +++ b/web/react/components/team_signup_send_invites_page.jsx @@ -13,7 +13,7 @@ export default class TeamSignupSendInvitesPage extends React.Component { this.submitSkip = this.submitSkip.bind(this); this.keySubmit = this.keySubmit.bind(this); this.state = { - emailEnabled: global.window.config.SendEmailNotifications === 'true' + emailEnabled: global.window.mm_config.SendEmailNotifications === 'true' }; if (!this.state.emailEnabled) { diff --git a/web/react/components/team_signup_username_page.jsx b/web/react/components/team_signup_username_page.jsx index 21e76e2b8..d8d0dbf2c 100644 --- a/web/react/components/team_signup_username_page.jsx +++ b/web/react/components/team_signup_username_page.jsx @@ -15,7 +15,7 @@ export default class TeamSignupUsernamePage extends React.Component { } submitBack(e) { e.preventDefault(); - if (global.window.config.SendEmailNotifications === 'true') { + if (global.window.mm_config.SendEmailNotifications === 'true') { this.props.state.wizard = 'send_invites'; } else { this.props.state.wizard = 'team_url'; diff --git a/web/react/components/team_signup_welcome_page.jsx b/web/react/components/team_signup_welcome_page.jsx index 1e9d8df0a..ee325fcaf 100644 --- a/web/react/components/team_signup_welcome_page.jsx +++ b/web/react/components/team_signup_welcome_page.jsx @@ -110,7 +110,7 @@ export default class TeamSignupWelcomePage extends React.Component { src='/static/images/logo.png' /> <h3 className='sub-heading'>Welcome to:</h3> - <h1 className='margin--top-none'>{global.window.config.SiteName}</h1> + <h1 className='margin--top-none'>{global.window.mm_config.SiteName}</h1> </p> <p className='margin--less'>Let's set up your new team</p> <p> diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx index 540331663..4a759bb21 100644 --- a/web/react/components/user_profile.jsx +++ b/web/react/components/user_profile.jsx @@ -73,7 +73,8 @@ export default class UserProfile extends React.Component { key='user-popover-image' /> ); - if (!global.window.config.ShowEmailAddress === 'true') { + + if (!global.window.mm_config.ShowEmailAddress === 'true') { dataContent.push( <div className='text-nowrap' diff --git a/web/react/components/user_settings/user_settings_general.jsx b/web/react/components/user_settings/user_settings_general.jsx index 9c03f77a6..e6430841f 100644 --- a/web/react/components/user_settings/user_settings_general.jsx +++ b/web/react/components/user_settings/user_settings_general.jsx @@ -122,7 +122,7 @@ export default class UserSettingsGeneralTab extends React.Component { () => { this.updateSection(''); AsyncClient.getMe(); - const verificationEnabled = global.window.config.SendEmailNotifications === 'true' && global.window.config.RequireEmailVerification === 'true' && emailUpdated; + const verificationEnabled = global.window.mm_config.SendEmailNotifications === 'true' && global.window.mm_config.RequireEmailVerification === 'true' && emailUpdated; if (verificationEnabled) { ErrorStore.storeLastError({message: 'Check your email at ' + user.email + ' to verify the address.'}); @@ -451,8 +451,8 @@ export default class UserSettingsGeneralTab extends React.Component { } var emailSection; if (this.props.activeSection === 'email') { - const emailEnabled = global.window.config.SendEmailNotifications === 'true'; - const emailVerificationEnabled = global.window.config.RequireEmailVerification === 'true'; + const emailEnabled = global.window.mm_config.SendEmailNotifications === 'true'; + const emailVerificationEnabled = global.window.mm_config.RequireEmailVerification === 'true'; let helpText = 'Email is used for notifications, and requires verification if changed.'; if (!emailEnabled) { diff --git a/web/react/components/user_settings/user_settings_integrations.jsx b/web/react/components/user_settings/user_settings_integrations.jsx index 231580cc3..1d9ea0ad5 100644 --- a/web/react/components/user_settings/user_settings_integrations.jsx +++ b/web/react/components/user_settings/user_settings_integrations.jsx @@ -34,7 +34,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { let outgoingHooksSection; var inputs = []; - if (global.window.config.EnableIncomingWebhooks === 'true') { + if (global.window.mm_config.EnableIncomingWebhooks === 'true') { if (this.props.activeSection === 'incoming-hooks') { inputs.push( <ManageIncomingHooks /> @@ -65,7 +65,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { } } - if (global.window.config.EnableOutgoingWebhooks === 'true') { + if (global.window.mm_config.EnableOutgoingWebhooks === 'true') { if (this.props.activeSection === 'outgoing-hooks') { inputs.push( <ManageOutgoingHooks /> diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index 44cd423b5..5449ae91e 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -35,10 +35,11 @@ export default class UserSettingsModal extends React.Component { tabs.push({name: 'security', uiName: 'Security', icon: 'glyphicon glyphicon-lock'}); tabs.push({name: 'notifications', uiName: 'Notifications', icon: 'glyphicon glyphicon-exclamation-sign'}); tabs.push({name: 'appearance', uiName: 'Appearance', icon: 'glyphicon glyphicon-wrench'}); - if (global.window.config.EnableOAuthServiceProvider === 'true') { + if (global.window.mm_config.EnableOAuthServiceProvider === 'true') { tabs.push({name: 'developer', uiName: 'Developer', icon: 'glyphicon glyphicon-th'}); } - if (global.window.config.EnableIncomingWebhooks === 'true' || global.window.config.EnableOutgoingWebhooks === 'true') { + + if (global.window.mm_config.EnableIncomingWebhooks === 'true' || global.window.mm_config.EnableOutgoingWebhooks === 'true') { tabs.push({name: 'integrations', uiName: 'Integrations', icon: 'glyphicon glyphicon-transfer'}); } tabs.push({name: 'display', uiName: 'Display', icon: 'glyphicon glyphicon-eye-open'}); diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx index 8693af494..61d49acb2 100644 --- a/web/react/components/user_settings/user_settings_notifications.jsx +++ b/web/react/components/user_settings/user_settings_notifications.jsx @@ -413,7 +413,7 @@ export default class NotificationsTab extends React.Component { </label> <br/> </div> - <div><br/>{'Email notifications are sent for mentions and direct messages after you’ve been offline for more than 60 seconds or away from ' + global.window.config.SiteName + ' for more than 5 minutes.'}</div> + <div><br/>{'Email notifications are sent for mentions and direct messages after you’ve been offline for more than 60 seconds or away from ' + global.window.mm_config.SiteName + ' for more than 5 minutes.'}</div> </div> ); diff --git a/web/react/components/view_image_popover_bar.jsx b/web/react/components/view_image_popover_bar.jsx index 5b3ee540c..1287f4fba 100644 --- a/web/react/components/view_image_popover_bar.jsx +++ b/web/react/components/view_image_popover_bar.jsx @@ -7,7 +7,7 @@ export default class ViewImagePopoverBar extends React.Component { } render() { var publicLink = ''; - if (global.window.config.EnablePublicLink === 'true') { + if (global.window.mm_config.EnablePublicLink === 'true') { publicLink = ( <div> <a diff --git a/web/react/pages/channel.jsx b/web/react/pages/channel.jsx index 20ed1bf0a..03e049db0 100644 --- a/web/react/pages/channel.jsx +++ b/web/react/pages/channel.jsx @@ -35,26 +35,18 @@ var RemovedFromChannelModal = require('../components/removed_from_channel_modal. var FileUploadOverlay = require('../components/file_upload_overlay.jsx'); var RegisterAppModal = require('../components/register_app_modal.jsx'); var ImportThemeModal = require('../components/user_settings/import_theme_modal.jsx'); -var TeamStore = require('../stores/team_store.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; function setupChannelPage(props) { - TeamStore.setCurrentId(props.TeamId); - AppDispatcher.handleViewAction({ type: ActionTypes.CLICK_CHANNEL, name: props.ChannelName, id: props.ChannelId }); - AppDispatcher.handleViewAction({ - type: ActionTypes.CLICK_TEAM, - id: props.TeamId - }); - AsyncClient.getAllPreferences(); // ChannelLoader must be rendered first @@ -237,7 +229,7 @@ function setupChannelPage(props) { document.getElementById('register_app_modal') ); - if (global.window.config.SendEmailNotifications === 'false') { + if (global.window.mm_config.SendEmailNotifications === 'false') { ErrorStore.storeLastError({message: 'Preview Mode: Email notifications have not been configured'}); ErrorStore.emitChange(); } diff --git a/web/react/pages/home.jsx b/web/react/pages/home.jsx index 5f0fa9d96..a59f2afd0 100644 --- a/web/react/pages/home.jsx +++ b/web/react/pages/home.jsx @@ -2,14 +2,15 @@ // See License.txt for license information. var ChannelStore = require('../stores/channel_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); var Constants = require('../utils/constants.jsx'); -function setupHomePage(props) { +function setupHomePage() { var last = ChannelStore.getLastVisitedName(); if (last == null || last.length === 0) { - window.location = props.TeamURL + '/channels/' + Constants.DEFAULT_CHANNEL; + window.location = TeamStore.getCurrentTeamUrl() + '/channels/' + Constants.DEFAULT_CHANNEL; } else { - window.location = props.TeamURL + '/channels/' + last; + window.location = TeamStore.getCurrentTeamUrl() + '/channels/' + last; } } diff --git a/web/react/stores/browser_store.jsx b/web/react/stores/browser_store.jsx index c2e7df58e..3eacff8b4 100644 --- a/web/react/stores/browser_store.jsx +++ b/web/react/stores/browser_store.jsx @@ -1,12 +1,12 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var UserStore; function getPrefix() { - if (!UserStore) { - UserStore = require('./user_store.jsx'); //eslint-disable-line global-require + if (global.window.mm_user) { + return global.window.mm_user.id + '_'; } - return UserStore.getCurrentId() + '_'; + + return 'unknown_'; } class BrowserStoreClass { @@ -17,32 +17,50 @@ class BrowserStoreClass { this.setGlobalItem = this.setGlobalItem.bind(this); this.getGlobalItem = this.getGlobalItem.bind(this); this.removeGlobalItem = this.removeGlobalItem.bind(this); - this.clear = this.clear.bind(this); this.actionOnItemsWithPrefix = this.actionOnItemsWithPrefix.bind(this); + this.actionOnGlobalItemsWithPrefix = this.actionOnGlobalItemsWithPrefix.bind(this); this.isLocalStorageSupported = this.isLocalStorageSupported.bind(this); + this.getLastServerVersion = this.getLastServerVersion.bind(this); + this.setLastServerVersion = this.setLastServerVersion.bind(this); + this.clear = this.clear.bind(this); - var currentVersion = localStorage.getItem('local_storage_version'); - if (currentVersion !== global.window.config.Version) { - this.clear(); - localStorage.setItem('local_storage_version', global.window.config.Version); + var currentVersion = sessionStorage.getItem('storage_version'); + if (currentVersion !== global.window.mm_config.Version) { + sessionStorage.clear(); + sessionStorage.setItem('storage_version', global.window.mm_config.Version); } } getItem(name, defaultValue) { - return this.getGlobalItem(getPrefix() + name, defaultValue); + var result = null; + try { + result = JSON.parse(sessionStorage.getItem(getPrefix() + name)); + } catch (err) { + result = null; + } + + if (result === null && typeof defaultValue !== 'undefined') { + result = defaultValue; + } + + return result; } setItem(name, value) { - this.setGlobalItem(getPrefix() + name, value); + sessionStorage.setItem(getPrefix() + name, JSON.stringify(value)); } removeItem(name) { - localStorage.removeItem(getPrefix() + name); + sessionStorage.removeItem(getPrefix() + name); } setGlobalItem(name, value) { try { - localStorage.setItem(name, JSON.stringify(value)); + if (this.isLocalStorageSupported()) { + localStorage.setItem(name, JSON.stringify(value)); + } else { + sessionStorage.setItem(name, JSON.stringify(value)); + } } catch (err) { console.log('An error occurred while setting local storage, clearing all props'); //eslint-disable-line no-console localStorage.clear(); @@ -53,7 +71,11 @@ class BrowserStoreClass { getGlobalItem(name, defaultValue) { var result = null; try { - result = JSON.parse(localStorage.getItem(name)); + if (this.isLocalStorageSupported()) { + result = JSON.parse(localStorage.getItem(name)); + } else { + result = JSON.parse(sessionStorage.getItem(name)); + } } catch (err) { result = null; } @@ -66,19 +88,26 @@ class BrowserStoreClass { } removeGlobalItem(name) { - localStorage.removeItem(name); + if (this.isLocalStorageSupported()) { + localStorage.removeItem(name); + } else { + sessionStorage.removeItem(name); + } } - clear() { - localStorage.clear(); - sessionStorage.clear(); + getLastServerVersion() { + return sessionStorage.getItem('last_server_version'); + } + + setLastServerVersion(version) { + sessionStorage.setItem('last_server_version', version); } /** * Preforms the given action on each item that has the given prefix * Signature for action is action(key, value) */ - actionOnItemsWithPrefix(prefix, action) { + actionOnGlobalItemsWithPrefix(prefix, action) { var globalPrefix = getPrefix(); var globalPrefixiLen = globalPrefix.length; for (var key in localStorage) { @@ -89,6 +118,21 @@ class BrowserStoreClass { } } + actionOnItemsWithPrefix(prefix, action) { + var globalPrefix = getPrefix(); + var globalPrefixiLen = globalPrefix.length; + for (var key in sessionStorage) { + if (key.lastIndexOf(globalPrefix + prefix, 0) === 0) { + var userkey = key.substring(globalPrefixiLen); + action(userkey, this.getGlobalItem(key)); + } + } + } + + clear() { + sessionStorage.clear(); + } + isLocalStorageSupported() { try { sessionStorage.setItem('testSession', '1'); diff --git a/web/react/stores/error_store.jsx b/web/react/stores/error_store.jsx index a4c42dcb7..90d593364 100644 --- a/web/react/stores/error_store.jsx +++ b/web/react/stores/error_store.jsx @@ -34,9 +34,11 @@ class ErrorStoreClass extends EventEmitter { removeChangeListener(callback) { this.removeListener(CHANGE_EVENT, callback); } + handledError() { BrowserStore.removeItem('last_error'); } + getLastError() { return BrowserStore.getItem('last_error'); } diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx index 8609d8bbf..b073ca68d 100644 --- a/web/react/stores/post_store.jsx +++ b/web/react/stores/post_store.jsx @@ -317,10 +317,10 @@ class PostStoreClass extends EventEmitter { return 0; }); - BrowserStore.setItem('pending_posts_' + channelId, postList); + BrowserStore.setGlobalItem('pending_posts_' + channelId, postList); } getPendingPosts(channelId) { - return BrowserStore.getItem('pending_posts_' + channelId); + return BrowserStore.getGlobalItem('pending_posts_' + channelId); } storeUnseenDeletedPost(post) { var posts = this.getUnseenDeletedPosts(post.channel_id); @@ -364,7 +364,7 @@ class PostStoreClass extends EventEmitter { this.pStorePendingPosts(channelId, postList); } clearPendingPosts() { - BrowserStore.actionOnItemsWithPrefix('pending_posts_', function clearPending(key) { + BrowserStore.actionOnGlobalItemsWithPrefix('pending_posts_', function clearPending(key) { BrowserStore.removeItem(key); }); } @@ -407,26 +407,26 @@ class PostStoreClass extends EventEmitter { } storeCurrentDraft(draft) { var channelId = ChannelStore.getCurrentId(); - BrowserStore.setItem('draft_' + channelId, draft); + BrowserStore.setGlobalItem('draft_' + channelId, draft); } getCurrentDraft() { var channelId = ChannelStore.getCurrentId(); return this.getDraft(channelId); } storeDraft(channelId, draft) { - BrowserStore.setItem('draft_' + channelId, draft); + BrowserStore.setGlobalItem('draft_' + channelId, draft); } getDraft(channelId) { - return BrowserStore.getItem('draft_' + channelId, this.getEmptyDraft()); + return BrowserStore.getGlobalItem('draft_' + channelId, this.getEmptyDraft()); } storeCommentDraft(parentPostId, draft) { - BrowserStore.setItem('comment_draft_' + parentPostId, draft); + BrowserStore.setGlobalItem('comment_draft_' + parentPostId, draft); } getCommentDraft(parentPostId) { - return BrowserStore.getItem('comment_draft_' + parentPostId, this.getEmptyDraft()); + return BrowserStore.getGlobalItem('comment_draft_' + parentPostId, this.getEmptyDraft()); } clearDraftUploads() { - BrowserStore.actionOnItemsWithPrefix('draft_', function clearUploads(key, value) { + BrowserStore.actionOnGlobalItemsWithPrefix('draft_', function clearUploads(key, value) { if (value) { value.uploadsInProgress = []; BrowserStore.setItem(key, value); @@ -434,7 +434,7 @@ class PostStoreClass extends EventEmitter { }); } clearCommentDraftUploads() { - BrowserStore.actionOnItemsWithPrefix('comment_draft_', function clearUploads(key, value) { + BrowserStore.actionOnGlobalItemsWithPrefix('comment_draft_', function clearUploads(key, value) { if (value) { value.uploadsInProgress = []; BrowserStore.setItem(key, value); diff --git a/web/react/stores/team_store.jsx b/web/react/stores/team_store.jsx index 7001acdb1..22114ae85 100644 --- a/web/react/stores/team_store.jsx +++ b/web/react/stores/team_store.jsx @@ -28,29 +28,31 @@ class TeamStoreClass extends EventEmitter { this.get = this.get.bind(this); this.getByName = this.getByName.bind(this); this.getAll = this.getAll.bind(this); - this.setCurrentId = this.setCurrentId.bind(this); this.getCurrentId = this.getCurrentId.bind(this); this.getCurrent = this.getCurrent.bind(this); this.getCurrentTeamUrl = this.getCurrentTeamUrl.bind(this); - this.storeTeam = this.storeTeam.bind(this); - this.pStoreTeams = this.pStoreTeams.bind(this); - this.pGetTeams = this.pGetTeams.bind(this); + this.saveTeam = this.saveTeam.bind(this); } + emitChange() { this.emit(CHANGE_EVENT); } + addChangeListener(callback) { this.on(CHANGE_EVENT, callback); } + removeChangeListener(callback) { this.removeListener(CHANGE_EVENT, callback); } + get(id) { - var c = this.pGetTeams(); + var c = this.getAll(); return c[id]; } + getByName(name) { - var t = this.pGetTeams(); + var t = this.getAll(); for (var id in t) { if (t[id].name === name) { @@ -60,59 +62,51 @@ class TeamStoreClass extends EventEmitter { return null; } + getAll() { - return this.pGetTeams(); - } - setCurrentId(id) { - if (id === null) { - BrowserStore.removeItem('current_team_id'); - } else { - BrowserStore.setItem('current_team_id', id); - } + return BrowserStore.getItem('user_teams', {}); } + getCurrentId() { - return BrowserStore.getItem('current_team_id'); - } - getCurrent() { - var currentId = this.getCurrentId(); + var team = global.window.mm_team; - if (currentId !== null) { - return this.get(currentId); + if (team) { + return team.id; } + return null; } + + getCurrent() { + if (global.window.mm_team != null && this.get(global.window.mm_team.id) == null) { + this.saveTeam(global.window.mm_team); + } + + return global.window.mm_team; + } + getCurrentTeamUrl() { if (this.getCurrent()) { return getWindowLocationOrigin() + '/' + this.getCurrent().name; } return null; } - storeTeam(team) { - var teams = this.pGetTeams(); + + saveTeam(team) { + var teams = this.getAll(); teams[team.id] = team; - this.pStoreTeams(teams); - } - pStoreTeams(teams) { BrowserStore.setItem('user_teams', teams); } - pGetTeams() { - return BrowserStore.getItem('user_teams', {}); - } } var TeamStore = new TeamStoreClass(); -TeamStore.dispatchToken = AppDispatcher.register(function registry(payload) { +TeamStore.dispatchToken = AppDispatcher.register((payload) => { var action = payload.action; switch (action.type) { - case ActionTypes.CLICK_TEAM: - TeamStore.setCurrentId(action.id); - TeamStore.emitChange(); - break; - case ActionTypes.RECIEVED_TEAM: - TeamStore.storeTeam(action.team); + TeamStore.saveTeam(action.team); TeamStore.emitChange(); break; diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx index fa74f812d..575e6d51e 100644 --- a/web/react/stores/user_store.jsx +++ b/web/react/stores/user_store.jsx @@ -3,7 +3,6 @@ var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var EventEmitter = require('events').EventEmitter; -var client = require('../utils/client.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; @@ -38,13 +37,11 @@ class UserStoreClass extends EventEmitter { this.emitToggleImportModal = this.emitToggleImportModal.bind(this); this.addImportModalListener = this.addImportModalListener.bind(this); this.removeImportModalListener = this.removeImportModalListener.bind(this); - this.setCurrentId = this.setCurrentId.bind(this); this.getCurrentId = this.getCurrentId.bind(this); this.getCurrentUser = this.getCurrentUser.bind(this); this.setCurrentUser = this.setCurrentUser.bind(this); this.getLastEmail = this.getLastEmail.bind(this); this.setLastEmail = this.setLastEmail.bind(this); - this.removeCurrentUser = this.removeCurrentUser.bind(this); this.hasProfile = this.hasProfile.bind(this); this.getProfile = this.getProfile.bind(this); this.getProfileByUsername = this.getProfileByUsername.bind(this); @@ -52,9 +49,6 @@ class UserStoreClass extends EventEmitter { this.getProfiles = this.getProfiles.bind(this); this.getActiveOnlyProfiles = this.getActiveOnlyProfiles.bind(this); this.saveProfile = this.saveProfile.bind(this); - this.pStoreProfiles = this.pStoreProfiles.bind(this); - this.pGetProfiles = this.pGetProfiles.bind(this); - this.pGetProfilesUsernameMap = this.pGetProfilesUsernameMap.bind(this); this.setSessions = this.setSessions.bind(this); this.getSessions = this.getSessions.bind(this); this.setAudits = this.setAudits.bind(this); @@ -62,138 +56,155 @@ class UserStoreClass extends EventEmitter { this.setTeams = this.setTeams.bind(this); this.getTeams = this.getTeams.bind(this); this.getCurrentMentionKeys = this.getCurrentMentionKeys.bind(this); - this.getLastVersion = this.getLastVersion.bind(this); - this.setLastVersion = this.setLastVersion.bind(this); this.setStatuses = this.setStatuses.bind(this); this.pSetStatuses = this.pSetStatuses.bind(this); this.setStatus = this.setStatus.bind(this); this.getStatuses = this.getStatuses.bind(this); this.getStatus = this.getStatus.bind(this); - - this.gCurrentId = null; } emitChange(userId) { this.emit(CHANGE_EVENT, userId); } + addChangeListener(callback) { this.on(CHANGE_EVENT, callback); } + removeChangeListener(callback) { this.removeListener(CHANGE_EVENT, callback); } + emitSessionsChange() { this.emit(CHANGE_EVENT_SESSIONS); } + addSessionsChangeListener(callback) { this.on(CHANGE_EVENT_SESSIONS, callback); } + removeSessionsChangeListener(callback) { this.removeListener(CHANGE_EVENT_SESSIONS, callback); } + emitAuditsChange() { this.emit(CHANGE_EVENT_AUDITS); } + addAuditsChangeListener(callback) { this.on(CHANGE_EVENT_AUDITS, callback); } + removeAuditsChangeListener(callback) { this.removeListener(CHANGE_EVENT_AUDITS, callback); } + emitTeamsChange() { this.emit(CHANGE_EVENT_TEAMS); } + addTeamsChangeListener(callback) { this.on(CHANGE_EVENT_TEAMS, callback); } + removeTeamsChangeListener(callback) { this.removeListener(CHANGE_EVENT_TEAMS, callback); } + emitStatusesChange() { this.emit(CHANGE_EVENT_STATUSES); } + addStatusesChangeListener(callback) { this.on(CHANGE_EVENT_STATUSES, callback); } + removeStatusesChangeListener(callback) { this.removeListener(CHANGE_EVENT_STATUSES, callback); } + emitToggleImportModal(value) { this.emit(TOGGLE_IMPORT_MODAL_EVENT, value); } + addImportModalListener(callback) { this.on(TOGGLE_IMPORT_MODAL_EVENT, callback); } + removeImportModalListener(callback) { this.removeListener(TOGGLE_IMPORT_MODAL_EVENT, callback); } - setCurrentId(id) { - this.gCurrentId = id; - if (id == null) { - BrowserStore.removeGlobalItem('current_user_id'); - } else { - BrowserStore.setGlobalItem('current_user_id', id); + + getCurrentUser() { + if (this.getProfiles()[global.window.mm_user.id] == null) { + this.saveProfile(global.window.mm_user); } + + return global.window.mm_user; } - getCurrentId(skipFetch) { - var currentId = this.gCurrentId; - if (currentId == null) { - currentId = BrowserStore.getGlobalItem('current_user_id'); - this.gCurrentId = currentId; - } + setCurrentUser(user) { + var oldUser = global.window.mm_user; - // this is a special case to force fetch the - // current user if it's missing - // it's synchronous to block rendering - if (currentId == null && !skipFetch) { - var me = client.getMeSynchronous(); - if (me != null) { - this.setCurrentUser(me); - currentId = me.id; - } + if (oldUser.id === user.id) { + global.window.mm_user = user; + this.saveProfile(user); + } else { + throw new Error('Problem with setCurrentUser old_user_id=' + oldUser.id + ' new_user_id=' + user.id); } - - return currentId; } - getCurrentUser() { - if (this.getCurrentId() == null) { - return null; + + getCurrentId() { + var user = global.window.mm_user; + + if (user) { + return user.id; } - return this.pGetProfiles()[this.getCurrentId()]; - } - setCurrentUser(user) { - this.setCurrentId(user.id); - this.saveProfile(user); + return null; } + getLastEmail() { - return BrowserStore.getItem('last_email', ''); + return BrowserStore.getGlobalItem('last_email', ''); } + setLastEmail(email) { - BrowserStore.setItem('last_email', email); - } - removeCurrentUser() { - this.setCurrentId(null); + BrowserStore.setGlobalItem('last_email', email); } + hasProfile(userId) { - return this.pGetProfiles()[userId] != null; + return this.getProfiles()[userId] != null; } + getProfile(userId) { - return this.pGetProfiles()[userId]; + return this.getProfiles()[userId]; } + getProfileByUsername(username) { - return this.pGetProfilesUsernameMap()[username]; + return this.getProfilesUsernameMap()[username]; } + getProfilesUsernameMap() { - return this.pGetProfilesUsernameMap(); + var profileUsernameMap = {}; + + var profiles = this.getProfiles(); + for (var key in profiles) { + if (profiles.hasOwnProperty(key)) { + var profile = profiles[key]; + profileUsernameMap[profile.username] = profile; + } + } + + return profileUsernameMap; } + getProfiles() { - return this.pGetProfiles(); + return BrowserStore.getItem('profiles', {}); } + getActiveOnlyProfiles() { var active = {}; - var current = this.pGetProfiles(); + var current = this.getProfiles(); for (var key in current) { if (current[key].delete_at === 0) { @@ -203,45 +214,37 @@ class UserStoreClass extends EventEmitter { return active; } + saveProfile(profile) { - var ps = this.pGetProfiles(); + var ps = this.getProfiles(); ps[profile.id] = profile; - this.pStoreProfiles(ps); - } - pStoreProfiles(profiles) { - BrowserStore.setItem('profiles', profiles); - var profileUsernameMap = {}; - for (var id in profiles) { - if (profiles.hasOwnProperty(id)) { - profileUsernameMap[profiles[id].username] = profiles[id]; - } - } - BrowserStore.setItem('profileUsernameMap', profileUsernameMap); - } - pGetProfiles() { - return BrowserStore.getItem('profiles', {}); - } - pGetProfilesUsernameMap() { - return BrowserStore.getItem('profileUsernameMap', {}); + BrowserStore.setItem('profiles', ps); } + setSessions(sessions) { BrowserStore.setItem('sessions', sessions); } + getSessions() { return BrowserStore.getItem('sessions', {loading: true}); } + setAudits(audits) { BrowserStore.setItem('audits', audits); } + getAudits() { return BrowserStore.getItem('audits', {loading: true}); } + setTeams(teams) { BrowserStore.setItem('teams', teams); } + getTeams() { return BrowserStore.getItem('teams', []); } + getCurrentMentionKeys() { var user = this.getCurrentUser(); @@ -269,28 +272,27 @@ class UserStoreClass extends EventEmitter { return keys; } - getLastVersion() { - return BrowserStore.getItem('last_version', ''); - } - setLastVersion(version) { - BrowserStore.setItem('last_version', version); - } + setStatuses(statuses) { this.pSetStatuses(statuses); this.emitStatusesChange(); } + pSetStatuses(statuses) { BrowserStore.setItem('statuses', statuses); } + setStatus(userId, status) { var statuses = this.getStatuses(); statuses[userId] = status; this.pSetStatuses(statuses); this.emitStatusesChange(); } + getStatuses() { return BrowserStore.getItem('statuses', {}); } + getStatus(id) { return this.getStatuses()[id]; } @@ -299,7 +301,7 @@ class UserStoreClass extends EventEmitter { var UserStore = new UserStoreClass(); UserStore.setMaxListeners(0); -UserStore.dispatchToken = AppDispatcher.register(function registry(payload) { +UserStore.dispatchToken = AppDispatcher.register((payload) => { var action = payload.action; switch (action.type) { diff --git a/web/react/utils/async_client.jsx b/web/react/utils/async_client.jsx index b22d7237e..fb7631159 100644 --- a/web/react/utils/async_client.jsx +++ b/web/react/utils/async_client.jsx @@ -3,6 +3,7 @@ var client = require('./client.jsx'); var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); +var BrowserStore = require('../stores/browser_store.jsx'); var ChannelStore = require('../stores/channel_store.jsx'); var PostStore = require('../stores/post_store.jsx'); var UserStore = require('../stores/user_store.jsx'); @@ -50,18 +51,18 @@ export function getChannels(force, updateLastViewed, checkVersion) { callTracker.getChannels = utils.getTimestamp(); client.getChannels( - function getChannelsSuccess(data, textStatus, xhr) { + (data, textStatus, xhr) => { callTracker.getChannels = 0; if (checkVersion) { var serverVersion = xhr.getResponseHeader('X-Version-ID'); - if (!UserStore.getLastVersion()) { - UserStore.setLastVersion(serverVersion); + if (!BrowserStore.getLastServerVersion()) { + BrowserStore.setLastServerVersion(serverVersion); } - if (serverVersion !== UserStore.getLastVersion()) { - UserStore.setLastVersion(serverVersion); + if (serverVersion !== BrowserStore.getLastServerVersion()) { + BrowserStore.setLastServerVersion(serverVersion); window.location.href = window.location.href; console.log('Detected version update refreshing the page'); //eslint-disable-line no-console } @@ -77,7 +78,7 @@ export function getChannels(force, updateLastViewed, checkVersion) { members: data.members }); }, - function getChannelsFailure(err) { + (err) => { callTracker.getChannels = 0; dispatchError(err, 'getChannels'); } @@ -566,8 +567,8 @@ export function getMe() { } callTracker.getMe = utils.getTimestamp(); - client.getMeSynchronous( - function getMeSyncSuccess(data, textStatus, xhr) { + client.getMe( + (data, textStatus, xhr) => { callTracker.getMe = 0; if (xhr.status === 304 || !data) { @@ -579,7 +580,7 @@ export function getMe() { me: data }); }, - function getMeSyncFailure(err) { + (err) => { callTracker.getMe = 0; dispatchError(err, 'getMe'); } diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx index f92633439..ee1f9ad27 100644 --- a/web/react/utils/client.jsx +++ b/web/react/utils/client.jsx @@ -232,6 +232,7 @@ export function logout() { track('api', 'api_users_logout'); var currentTeamUrl = TeamStore.getCurrentTeamUrl(); BrowserStore.clear(); + ErrorStore.storeLastError(null); window.location.href = currentTeamUrl + '/logout'; } @@ -385,10 +386,9 @@ export function getAllTeams(success, error) { }); } -export function getMeSynchronous(success, error) { +export function getMe(success, error) { var currentUser = null; $.ajax({ - async: false, cache: false, url: '/api/v1/users/me', dataType: 'json', @@ -402,7 +402,7 @@ export function getMeSynchronous(success, error) { }, error: function onError(xhr, status, err) { if (error) { - var e = handleError('getMeSynchronous', xhr, status, err); + var e = handleError('getMe', xhr, status, err); error(e); } } diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index 1d856e067..d891cc48b 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -33,7 +33,6 @@ module.exports = { RECIEVED_MSG: null, - CLICK_TEAM: null, RECIEVED_TEAM: null, RECIEVED_CONFIG: null, diff --git a/web/templates/footer.html b/web/templates/footer.html index 296e902cf..dc1a7c9d0 100644 --- a/web/templates/footer.html +++ b/web/templates/footer.html @@ -1,7 +1,7 @@ {{define "footer"}} <div class="footer-pane col-xs-12"> <div class="col-xs-12"> - <span class="pull-right footer-site-name">{{ .ClientProps.SiteName }}</span> + <span class="pull-right footer-site-name">{{ .ClientCfg.SiteName }}</span> </div> <div class="col-xs-12"> <span class="pull-right footer-link copyright">© 2015 Mattermost, Inc.</span> diff --git a/web/templates/head.html b/web/templates/head.html index 3466510d4..31a3c97f2 100644 --- a/web/templates/head.html +++ b/web/templates/head.html @@ -19,7 +19,10 @@ <!-- Android add to homescreen --> <script> - window.config = {{ .ClientProps }}; + window.mm_config = {{ .ClientCfg }}; + window.mm_team = {{ .Team }}; + window.mm_user = {{ .User }}; + window.mm_session = {{ .Session }}; </script> <!-- CSS Should always go first --> @@ -70,9 +73,9 @@ </script> <script type="text/javascript"> - if (window.config.SegmentDeveloperKey != null && window.config.SegmentDeveloperKey !== "") { + if (window.mm_config.SegmentDeveloperKey != null && window.mm_config.SegmentDeveloperKey !== "") { !function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.0.1"; - analytics.load(window.config.SegmentDeveloperKey); + analytics.load(window.mm_config.SegmentDeveloperKey); var user = window.UserStore.getCurrentUser(true); if (user) { analytics.identify(user.id, { diff --git a/web/templates/home.html b/web/templates/home.html index 0d8b89061..08876d41d 100644 --- a/web/templates/home.html +++ b/web/templates/home.html @@ -17,7 +17,7 @@ </div> </div> <script> - window.setup_home_page({{ .Props }}); + window.setup_home_page(); </script> </body> </html> diff --git a/web/templates/signup_team.html b/web/templates/signup_team.html index a6000696e..39fd3791b 100644 --- a/web/templates/signup_team.html +++ b/web/templates/signup_team.html @@ -9,7 +9,7 @@ <div class="col-sm-12"> <div class="signup-team__container"> <img class="signup-team-logo" src="/static/images/logo.png" /> - <h1>{{ .ClientProps.SiteName }}</h1> + <h1>{{ .ClientCfg.SiteName }}</h1> <h4 class="color--light">All team communication in one place, searchable and accessible anywhere</h4> <div id="signup-team"></div> </div> diff --git a/web/templates/welcome.html b/web/templates/welcome.html index e7eeb5648..15c072226 100644 --- a/web/templates/welcome.html +++ b/web/templates/welcome.html @@ -11,7 +11,7 @@ <div class="row main"> <div class="app__content"> <div class="welcome-info"> - <h1>Welcome to {{ .ClientProps.SiteName }}!</h1> + <h1>Welcome to {{ .ClientCfg.SiteName }}!</h1> <p> You do not appear to be part of any teams. Please contact your administrator to have him send you an invitation to a private team. diff --git a/web/web.go b/web/web.go index a24f1589d..701e36e95 100644 --- a/web/web.go +++ b/web/web.go @@ -15,6 +15,11 @@ import ( "gopkg.in/fsnotify.v1" "html/template" "net/http" +<<<<<<< HEAD + "net/url" + "regexp" +======= +>>>>>>> master "strconv" "strings" ) @@ -31,10 +36,22 @@ func NewHtmlTemplatePage(templateName string, title string) *HtmlTemplatePage { props := make(map[string]string) props["Title"] = title - return &HtmlTemplatePage{TemplateName: templateName, Props: props, ClientProps: utils.ClientProperties} + return &HtmlTemplatePage{TemplateName: templateName, Props: props, ClientCfg: utils.ClientCfg} } func (me *HtmlTemplatePage) Render(c *api.Context, w http.ResponseWriter) { + if me.Team != nil { + me.Team.Sanitize() + } + + if me.User != nil { + me.User.Sanitize(map[string]bool{}) + } + + if me.Session != nil { + me.Session.Sanitize() + } + if err := Templates.ExecuteTemplate(w, me.TemplateName, me); err != nil { c.SetUnknownError(me.TemplateName, err.Error()) } @@ -141,6 +158,20 @@ func CheckBrowserCompatability(c *api.Context, r *http.Request) bool { } +// func getTeamAndUser(c *api.Context) (*model.Team, *model.User) { +// if tr := <-api.Srv.Store.Team().Get(c.Session.TeamId); tr.Err != nil { +// c.Err = tr.Err +// return nil, nil +// } else { +// if ur := <-api.Srv.Store.User().Get(c.Session.UserId); ur.Err != nil { +// c.Err = ur.Err +// return nil, nil +// } else { +// return tr.Data.(*model.Team), ur.Data.(*model.User) +// } +// } +// } + func root(c *api.Context, w http.ResponseWriter, r *http.Request) { if !CheckBrowserCompatability(c, r) { @@ -151,8 +182,30 @@ func root(c *api.Context, w http.ResponseWriter, r *http.Request) { page := NewHtmlTemplatePage("signup_team", "Signup") page.Render(c, w) } else { + teamChan := api.Srv.Store.Team().Get(c.Session.TeamId) + userChan := api.Srv.Store.User().Get(c.Session.UserId) + + var team *model.Team + if tr := <-teamChan; tr.Err != nil { + c.Err = tr.Err + return + } else { + team = tr.Data.(*model.Team) + + } + + var user *model.User + if ur := <-userChan; ur.Err != nil { + c.Err = ur.Err + return + } else { + user = ur.Data.(*model.User) + } + page := NewHtmlTemplatePage("home", "Home") - page.Props["TeamURL"] = c.GetTeamURL() + page.Team = team + page.User = user + page.Session = &c.Session page.Render(c, w) } } @@ -176,50 +229,35 @@ func login(c *api.Context, w http.ResponseWriter, r *http.Request) { var team *model.Team if tResult := <-api.Srv.Store.Team().GetByName(teamName); tResult.Err != nil { - l4g.Error("Couldn't find team name=%v, teamURL=%v, err=%v", teamName, c.GetTeamURL(), tResult.Err.Message) + l4g.Error("Couldn't find team name=%v, err=%v", teamName, tResult.Err.Message) http.Redirect(w, r, api.GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect) return } else { team = tResult.Data.(*model.Team) } - // If we are already logged into this team then go to home + // If we are already logged into this team then go to town-square if len(c.Session.UserId) != 0 && c.Session.TeamId == team.Id { - page := NewHtmlTemplatePage("home", "Home") - page.Props["TeamURL"] = c.GetTeamURL() - page.Render(c, w) + http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/channels/town-square", http.StatusTemporaryRedirect) return } // We still might be able to switch to this team because we've logged in before - 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 { - if sr := <-api.Srv.Store.Session().Get(token); sr.Err == nil { - s := sr.Data.(*model.Session) - - if !s.IsExpired() && s.TeamId == team.Id { - w.Header().Set(model.HEADER_TOKEN, s.Token) - sessionCookie := &http.Cookie{ - Name: model.SESSION_TOKEN, - Value: s.Token, - Path: "/", - MaxAge: model.SESSION_TIME_WEB_IN_SECS, - HttpOnly: true, - } + session := api.FindMultiSessionForTeamId(r, team.Id) + if session != nil { + w.Header().Set(model.HEADER_TOKEN, session.Token) + sessionCookie := &http.Cookie{ + Name: model.SESSION_TOKEN, + Value: session.Token, + Path: "/", + MaxAge: model.SESSION_TIME_WEB_IN_SECS, + HttpOnly: true, + } - http.SetCookie(w, sessionCookie) + http.SetCookie(w, sessionCookie) - http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/channels/town-square", http.StatusTemporaryRedirect) - return - } - } - } - } + http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/channels/town-square", http.StatusTemporaryRedirect) + return } page := NewHtmlTemplatePage("login", "Login") @@ -315,7 +353,7 @@ func signupUserComplete(c *api.Context, w http.ResponseWriter, r *http.Request) func logout(c *api.Context, w http.ResponseWriter, r *http.Request) { api.Logout(c, w, r) - http.Redirect(w, r, c.GetTeamURL(), http.StatusFound) + http.Redirect(w, r, c.GetTeamURL(), http.StatusTemporaryRedirect) } func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { @@ -324,7 +362,26 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { teamName := params["team"] var team *model.Team - teamChan := api.Srv.Store.Team().Get(c.Session.TeamId) + if result := <-api.Srv.Store.Team().GetByName(teamName); result.Err != nil { + c.Err = result.Err + return + } else { + team = result.Data.(*model.Team) + } + + // We are logged into a different team. Lets see if we have another + // session in the cookie that will give us access. + if c.Session.TeamId != team.Id { + session := api.FindMultiSessionForTeamId(r, team.Id) + if session == nil { + // redirect to login + http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/?redirect="+url.QueryEscape(r.URL.Path), http.StatusTemporaryRedirect) + } else { + c.Session = *session + } + } + + userChan := api.Srv.Store.User().Get(c.Session.UserId) var channelId string if result := <-api.Srv.Store.Channel().CheckPermissionsToByName(c.Session.TeamId, name, c.Session.UserId); result.Err != nil { @@ -334,17 +391,14 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { channelId = result.Data.(string) } - if tResult := <-teamChan; tResult.Err != nil { - c.Err = tResult.Err + var user *model.User + if ur := <-userChan; ur.Err != nil { + c.Err = ur.Err + c.RemoveSessionCookie(w, r) + l4g.Error("Error in getting users profile for id=%v forcing logout", c.Session.UserId) return } else { - team = tResult.Data.(*model.Team) - } - - if team.Name != teamName { - l4g.Error("It appears you are logged into " + team.Name + ", but are trying to access " + teamName) - http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/channels/town-square", http.StatusFound) - return + user = ur.Data.(*model.User) } if len(channelId) == 0 { @@ -365,15 +419,6 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { channelId = sc.Id } } else { - - // lets make sure the user is valid - if result := <-api.Srv.Store.User().Get(c.Session.UserId); result.Err != nil { - c.Err = result.Err - c.RemoveSessionCookie(w, r) - l4g.Error("Error in getting users profile for id=%v forcing logout", c.Session.UserId) - return - } - // We will attempt to auto-join open channels if cr := <-api.Srv.Store.Channel().GetByName(c.Session.TeamId, name); cr.Err != nil { http.Redirect(w, r, c.GetTeamURL()+"/channels/town-square", http.StatusFound) @@ -394,7 +439,7 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { } page := NewHtmlTemplatePage("channel", "") - page.Props["Title"] = name + " - " + team.DisplayName + " " + page.ClientProps["SiteName"] + page.Props["Title"] = name + " - " + team.DisplayName + " " + page.ClientCfg["SiteName"] page.Props["TeamDisplayName"] = team.DisplayName page.Props["TeamName"] = team.Name page.Props["TeamType"] = team.Type @@ -402,6 +447,9 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { page.Props["ChannelName"] = name page.Props["ChannelId"] = channelId page.Props["UserId"] = c.Session.UserId + page.Team = team + page.User = user + page.Session = &c.Session page.Render(c, w) } @@ -500,7 +548,7 @@ func resetPassword(c *api.Context, w http.ResponseWriter, r *http.Request) { } page := NewHtmlTemplatePage("password_reset", "") - page.Props["Title"] = "Reset Password " + page.ClientProps["SiteName"] + page.Props["Title"] = "Reset Password " + page.ClientCfg["SiteName"] page.Props["TeamDisplayName"] = teamDisplayName page.Props["TeamName"] = teamName page.Props["Hash"] = hash @@ -627,7 +675,11 @@ func signupCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request) return } - root(c, w, r) + page := NewHtmlTemplatePage("home", "Home") + page.Team = team + page.User = ruser + page.Session = &c.Session + page.Render(c, w) } } @@ -690,6 +742,12 @@ func loginCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request) return } + page := NewHtmlTemplatePage("home", "Home") + page.Team = team + page.User = user + page.Session = &c.Session + page.Render(c, w) + root(c, w, r) } } @@ -701,12 +759,34 @@ func adminConsole(c *api.Context, w http.ResponseWriter, r *http.Request) { return } + teamChan := api.Srv.Store.Team().Get(c.Session.TeamId) + userChan := api.Srv.Store.User().Get(c.Session.UserId) + + var team *model.Team + if tr := <-teamChan; tr.Err != nil { + c.Err = tr.Err + return + } else { + team = tr.Data.(*model.Team) + + } + + var user *model.User + if ur := <-userChan; ur.Err != nil { + c.Err = ur.Err + return + } else { + user = ur.Data.(*model.User) + } + params := mux.Vars(r) activeTab := params["tab"] teamId := params["team"] page := NewHtmlTemplatePage("admin_console", "Admin Console") - + page.User = user + page.Team = team + page.Session = &c.Session page.Props["ActiveTab"] = activeTab page.Props["TeamId"] = teamId page.Render(c, w) |