mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Merge branch 'master' into PLT-25
This commit is contained in:
@@ -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")
|
||||
sr.Handle("/analytics/{id:[A-Za-z0-9]+}/{name:[A-Za-z0-9_]+}", ApiAppHandler(getAnalytics)).Methods("GET")
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -20,7 +20,7 @@ func NewServerTemplatePage(templateName string) *ServerTemplatePage {
|
||||
return &ServerTemplatePage{
|
||||
TemplateName: templateName,
|
||||
Props: make(map[string]string),
|
||||
ClientProps: utils.ClientProperties,
|
||||
ClientCfg: utils.ClientCfg,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,16 +131,21 @@ func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model
|
||||
return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
|
||||
}
|
||||
|
||||
if sc, err := CreateChannel(c, channel, true); err != nil {
|
||||
return nil, err
|
||||
cm1 := &model.ChannelMember{
|
||||
UserId: c.Session.UserId,
|
||||
Roles: model.CHANNEL_ROLE_ADMIN,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
}
|
||||
cm2 := &model.ChannelMember{
|
||||
UserId: otherUserId,
|
||||
Roles: "",
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
}
|
||||
|
||||
if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil {
|
||||
return nil, result.Err
|
||||
} else {
|
||||
cm := &model.ChannelMember{ChannelId: sc.Id, UserId: otherUserId, Roles: "", NotifyProps: model.GetDefaultChannelNotifyProps()}
|
||||
|
||||
if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
|
||||
return nil, cmresult.Err
|
||||
}
|
||||
|
||||
return sc, nil
|
||||
return result.Data.(*model.Channel), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,6 +508,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 +520,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 +555,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
|
||||
|
||||
147
api/context.go
147
api/context.go
@@ -8,6 +8,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
l4g "code.google.com/p/log4go"
|
||||
@@ -19,20 +20,24 @@ import (
|
||||
var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE)
|
||||
|
||||
type Context struct {
|
||||
Session model.Session
|
||||
RequestId string
|
||||
IpAddress string
|
||||
Path string
|
||||
Err *model.AppError
|
||||
teamURLValid bool
|
||||
teamURL string
|
||||
siteURL string
|
||||
Session model.Session
|
||||
RequestId string
|
||||
IpAddress string
|
||||
Path string
|
||||
Err *model.AppError
|
||||
teamURLValid bool
|
||||
teamURL string
|
||||
siteURL string
|
||||
SessionTokenIndex int64
|
||||
}
|
||||
|
||||
type Page struct {
|
||||
TemplateName string
|
||||
Props map[string]string
|
||||
ClientProps map[string]string
|
||||
TemplateName string
|
||||
Props map[string]string
|
||||
ClientCfg map[string]string
|
||||
User *model.User
|
||||
Team *model.Team
|
||||
SessionTokenIndex int64
|
||||
}
|
||||
|
||||
func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
@@ -96,8 +101,37 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Attempt to parse the token from the cookie
|
||||
if len(token) == 0 {
|
||||
if cookie, err := r.Cookie(model.SESSION_TOKEN); err == nil {
|
||||
token = cookie.Value
|
||||
tokens := GetMultiSessionCookieTokens(r)
|
||||
if len(tokens) > 0 {
|
||||
// If there is only 1 token in the cookie then just use it like normal
|
||||
if len(tokens) == 1 {
|
||||
token = tokens[0]
|
||||
} else {
|
||||
// If it is a multi-session token then find the correct session
|
||||
sessionTokenIndexStr := r.URL.Query().Get(model.SESSION_TOKEN_INDEX)
|
||||
sessionTokenIndex := int64(-1)
|
||||
if len(sessionTokenIndexStr) > 0 {
|
||||
if index, err := strconv.ParseInt(sessionTokenIndexStr, 10, 64); err == nil {
|
||||
sessionTokenIndex = index
|
||||
}
|
||||
} else {
|
||||
sessionTokenIndexStr := r.Header.Get(model.HEADER_MM_SESSION_TOKEN_INDEX)
|
||||
if len(sessionTokenIndexStr) > 0 {
|
||||
if index, err := strconv.ParseInt(sessionTokenIndexStr, 10, 64); err == nil {
|
||||
sessionTokenIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sessionTokenIndex >= 0 && sessionTokenIndex < int64(len(tokens)) {
|
||||
token = tokens[sessionTokenIndex]
|
||||
c.SessionTokenIndex = sessionTokenIndex
|
||||
} else {
|
||||
c.SessionTokenIndex = -1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.SessionTokenIndex = -1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,18 +157,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if len(token) != 0 {
|
||||
var session *model.Session
|
||||
if ts, ok := sessionCache.Get(token); ok {
|
||||
session = ts.(*model.Session)
|
||||
}
|
||||
|
||||
if session == nil {
|
||||
if sessionResult := <-Srv.Store.Session().Get(token); sessionResult.Err != nil {
|
||||
c.LogError(model.NewAppError("ServeHTTP", "Invalid session", "token="+token+", err="+sessionResult.Err.DetailedError))
|
||||
} else {
|
||||
session = sessionResult.Data.(*model.Session)
|
||||
}
|
||||
}
|
||||
session := GetSession(token)
|
||||
|
||||
if session == nil || session.IsExpired() {
|
||||
c.RemoveSessionCookie(w, r)
|
||||
@@ -318,10 +341,23 @@ func (c *Context) IsTeamAdmin() bool {
|
||||
|
||||
func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
sessionCache.Remove(c.Session.Token)
|
||||
// multiToken := ""
|
||||
// if oldMultiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil {
|
||||
// multiToken = oldMultiCookie.Value
|
||||
// }
|
||||
|
||||
// multiCookie := &http.Cookie{
|
||||
// Name: model.SESSION_COOKIE_TOKEN,
|
||||
// Value: strings.TrimSpace(strings.Replace(multiToken, c.Session.Token, "", -1)),
|
||||
// Path: "/",
|
||||
// MaxAge: model.SESSION_TIME_WEB_IN_SECS,
|
||||
// HttpOnly: true,
|
||||
// }
|
||||
|
||||
//http.SetCookie(w, multiCookie)
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: model.SESSION_TOKEN,
|
||||
Name: model.SESSION_COOKIE_TOKEN,
|
||||
Value: "",
|
||||
Path: "/",
|
||||
MaxAge: -1,
|
||||
@@ -329,21 +365,6 @@ func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
http.SetCookie(w, cookie)
|
||||
|
||||
multiToken := ""
|
||||
if oldMultiCookie, err := r.Cookie(model.MULTI_SESSION_TOKEN); err == nil {
|
||||
multiToken = oldMultiCookie.Value
|
||||
}
|
||||
|
||||
multiCookie := &http.Cookie{
|
||||
Name: model.MULTI_SESSION_TOKEN,
|
||||
Value: strings.TrimSpace(strings.Replace(multiToken, c.Session.Token, "", -1)),
|
||||
Path: "/",
|
||||
MaxAge: model.SESSION_TIME_WEB_IN_SECS,
|
||||
HttpOnly: true,
|
||||
}
|
||||
|
||||
http.SetCookie(w, multiCookie)
|
||||
}
|
||||
|
||||
func (c *Context) SetInvalidParam(where string, name string) {
|
||||
@@ -479,7 +500,7 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
w.WriteHeader(err.StatusCode)
|
||||
ServerTemplates.ExecuteTemplate(w, "error.html", Page{Props: props, ClientProps: utils.ClientProperties})
|
||||
ServerTemplates.ExecuteTemplate(w, "error.html", Page{Props: props, ClientCfg: utils.ClientCfg})
|
||||
}
|
||||
|
||||
func Handle404(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -489,6 +510,46 @@ func Handle404(w http.ResponseWriter, r *http.Request) {
|
||||
RenderWebError(err, w, r)
|
||||
}
|
||||
|
||||
func GetSession(token string) *model.Session {
|
||||
var session *model.Session
|
||||
if ts, ok := sessionCache.Get(token); ok {
|
||||
session = ts.(*model.Session)
|
||||
}
|
||||
|
||||
if session == nil {
|
||||
if sessionResult := <-Srv.Store.Session().Get(token); sessionResult.Err != nil {
|
||||
l4g.Error("Invalid session token=" + token + ", err=" + sessionResult.Err.DetailedError)
|
||||
} else {
|
||||
session = sessionResult.Data.(*model.Session)
|
||||
}
|
||||
}
|
||||
|
||||
return session
|
||||
}
|
||||
|
||||
func GetMultiSessionCookieTokens(r *http.Request) []string {
|
||||
if multiCookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil {
|
||||
multiToken := multiCookie.Value
|
||||
|
||||
if len(multiToken) > 0 {
|
||||
return strings.Split(multiToken, " ")
|
||||
}
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func FindMultiSessionForTeamId(r *http.Request, teamId string) (int64, *model.Session) {
|
||||
for index, token := range GetMultiSessionCookieTokens(r) {
|
||||
s := GetSession(token)
|
||||
if s != nil && !s.IsExpired() && s.TeamId == teamId {
|
||||
return int64(index), s
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func AddSessionToCache(session *model.Session) {
|
||||
sessionCache.Add(session.Token, session)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -426,9 +426,9 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
subjectPage := NewServerTemplatePage("find_teams_subject")
|
||||
subjectPage.ClientProps["SiteURL"] = c.GetSiteURL()
|
||||
subjectPage.ClientCfg["SiteURL"] = c.GetSiteURL()
|
||||
bodyPage := NewServerTemplatePage("find_teams_body")
|
||||
bodyPage.ClientProps["SiteURL"] = c.GetSiteURL()
|
||||
bodyPage.ClientCfg["SiteURL"] = c.GetSiteURL()
|
||||
|
||||
if result := <-Srv.Store.Team().GetTeamsForEmail(email); result.Err != nil {
|
||||
c.Err = result.Err
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1 +1 @@
|
||||
{{define "find_teams_subject"}}Your {{ .ClientProps.SiteName }} Teams{{end}}
|
||||
{{define "find_teams_subject"}}Your {{ .ClientCfg.SiteName }} Teams{{end}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1 +1 @@
|
||||
{{define "signup_team_subject"}}Invitation to {{ .ClientProps.SiteName }}{{end}}
|
||||
{{define "signup_team_subject"}}Invitation to {{ .ClientCfg.SiteName }}{{end}}
|
||||
@@ -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>
|
||||
|
||||
@@ -1 +1 @@
|
||||
{{define "verify_subject"}}[{{ .Props.TeamDisplayName }} {{ .ClientProps.SiteName }}] Email Verification{{end}}
|
||||
{{define "verify_subject"}}[{{ .Props.TeamDisplayName }} {{ .ClientCfg.SiteName }}] Email Verification{{end}}
|
||||
|
||||
@@ -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>
|
||||
|
||||
50
api/user.go
50
api/user.go
@@ -428,43 +428,23 @@ 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)
|
||||
|
||||
tokens := GetMultiSessionCookieTokens(r)
|
||||
multiToken := ""
|
||||
if originalMultiSessionCookie, err := r.Cookie(model.MULTI_SESSION_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
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
multiToken = strings.TrimSpace(session.Token + " " + multiToken)
|
||||
multiToken = strings.TrimSpace(multiToken + " " + session.Token)
|
||||
|
||||
multiSessionCookie := &http.Cookie{
|
||||
Name: model.MULTI_SESSION_TOKEN,
|
||||
Name: model.SESSION_COOKIE_TOKEN,
|
||||
Value: multiToken,
|
||||
Path: "/",
|
||||
MaxAge: maxAge,
|
||||
@@ -1241,6 +1221,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 +1310,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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user