summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rw-r--r--api/channel.go59
-rw-r--r--api/channel_test.go23
-rw-r--r--api/command.go25
-rw-r--r--api/command_test.go2
-rw-r--r--api/file.go1
-rw-r--r--api/post.go34
-rw-r--r--api/post_test.go2
-rw-r--r--api/team.go103
-rw-r--r--api/team_test.go119
-rw-r--r--api/templates/invite_body.html2
-rw-r--r--api/templates/post_body.html2
-rw-r--r--api/user.go19
-rw-r--r--api/web_socket_test.go2
13 files changed, 339 insertions, 54 deletions
diff --git a/api/channel.go b/api/channel.go
index d3f6ca2de..c0c2d1548 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -57,7 +57,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if sc, err := CreateChannel(c, channel, r.URL.Path, true); err != nil {
+ if sc, err := CreateChannel(c, channel, true); err != nil {
c.Err = err
return
} else {
@@ -65,7 +65,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func CreateChannel(c *Context, channel *model.Channel, path string, addMember bool) (*model.Channel, *model.AppError) {
+func CreateChannel(c *Context, channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) {
if result := <-Srv.Store.Channel().Save(channel); result.Err != nil {
return nil, result.Err
} else {
@@ -100,7 +100,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if sc, err := CreateDirectChannel(c, userId, r.URL.Path); err != nil {
+ if sc, err := CreateDirectChannel(c, userId); err != nil {
c.Err = err
return
} else {
@@ -108,7 +108,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func CreateDirectChannel(c *Context, otherUserId string, path string) (*model.Channel, *model.AppError) {
+func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model.AppError) {
if len(otherUserId) != 26 {
return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
}
@@ -132,7 +132,7 @@ func CreateDirectChannel(c *Context, otherUserId string, path string) (*model.Ch
return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
}
- if sc, err := CreateChannel(c, channel, path, true); err != nil {
+ if sc, err := CreateChannel(c, channel, true); err != nil {
return nil, err
} else {
cm := &model.ChannelMember{ChannelId: sc.Id, UserId: otherUserId,
@@ -146,6 +146,23 @@ func CreateDirectChannel(c *Context, otherUserId string, path string) (*model.Ch
}
}
+func CreateDefaultChannels(c *Context, teamId string) ([]*model.Channel, *model.AppError) {
+ townSquare := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: teamId}
+
+ if _, err := CreateChannel(c, townSquare, false); err != nil {
+ return nil, err
+ }
+
+ offTopic := &model.Channel{DisplayName: "Off-Topic", Name: "off-topic", Type: model.CHANNEL_OPEN, TeamId: teamId}
+
+ if _, err := CreateChannel(c, offTopic, false); err != nil {
+ return nil, err
+ }
+
+ channels := []*model.Channel{townSquare, offTopic}
+ return channels, nil
+}
+
func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel := model.ChannelFromJson(r.Body)
@@ -303,7 +320,7 @@ func joinChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
channelId := params["id"]
- JoinChannel(c, channelId, r.URL.Path)
+ JoinChannel(c, channelId, "")
if c.Err != nil {
return
@@ -314,7 +331,7 @@ func joinChannel(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(result)))
}
-func JoinChannel(c *Context, channelId string, path string) {
+func JoinChannel(c *Context, channelId string, role string) {
sc := Srv.Store.Channel().Get(channelId)
uc := Srv.Store.User().Get(c.Session.UserId)
@@ -340,7 +357,7 @@ func JoinChannel(c *Context, channelId string, path string) {
}
if channel.Type == model.CHANNEL_OPEN {
- cm := &model.ChannelMember{ChannelId: channel.Id, UserId: c.Session.UserId, NotifyLevel: model.CHANNEL_NOTIFY_ALL}
+ cm := &model.ChannelMember{ChannelId: channel.Id, UserId: c.Session.UserId, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: role}
if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
c.Err = cmresult.Err
@@ -363,6 +380,32 @@ func JoinChannel(c *Context, channelId string, path string) {
}
}
+func JoinDefaultChannels(c *Context, user *model.User, channelRole string) *model.AppError {
+ // We don't call JoinChannel here since c.Session is not populated on user creation
+
+ var err *model.AppError = nil
+
+ if result := <-Srv.Store.Channel().GetByName(user.TeamId, "town-square"); result.Err != nil {
+ err = result.Err
+ } else {
+ cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: channelRole}
+ if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
+ err = cmResult.Err
+ }
+ }
+
+ if result := <-Srv.Store.Channel().GetByName(user.TeamId, "off-topic"); result.Err != nil {
+ err = result.Err
+ } else {
+ cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: channelRole}
+ if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
+ err = cmResult.Err
+ }
+ }
+
+ return err
+}
+
func leaveChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
diff --git a/api/channel_test.go b/api/channel_test.go
index e8aaf4e3f..dfae840dc 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -35,8 +35,15 @@ func TestCreateChannel(t *testing.T) {
}
rget := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
- if rget.Channels[0].Name != channel.Name {
- t.Fatal("full name didn't match")
+ nameMatch := false
+ for _, c := range rget.Channels {
+ if c.Name == channel.Name {
+ nameMatch = true
+ }
+ }
+
+ if !nameMatch {
+ t.Fatal("Did not create channel with correct name")
}
if _, err := Client.CreateChannel(rchannel.Data.(*model.Channel)); err == nil {
@@ -679,6 +686,8 @@ func TestUpdateNotifyLevel(t *testing.T) {
data["user_id"] = user.Id
data["notify_level"] = model.CHANNEL_NOTIFY_MENTION
+ timeBeforeUpdate := model.GetMillis()
+
if _, err := Client.UpdateNotifyLevel(data); err != nil {
t.Fatal(err)
}
@@ -689,6 +698,10 @@ func TestUpdateNotifyLevel(t *testing.T) {
t.Fatal("NotifyLevel did not update properly")
}
+ if rdata.Members[channel1.Id].LastUpdateAt <= timeBeforeUpdate {
+ t.Fatal("LastUpdateAt did not update")
+ }
+
data["user_id"] = "junk"
if _, err := Client.UpdateNotifyLevel(data); err == nil {
t.Fatal("Should have errored - bad user id")
@@ -735,7 +748,7 @@ func TestUpdateNotifyLevel(t *testing.T) {
}
func TestFuzzyChannel(t *testing.T) {
- Setup();
+ Setup()
team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
@@ -747,9 +760,9 @@ func TestFuzzyChannel(t *testing.T) {
Client.LoginByEmail(team.Domain, user.Email, "pwd")
// Strings that should pass as acceptable channel names
- var fuzzyStringsPass = []string {
+ var fuzzyStringsPass = []string{
"*", "?", ".", "}{][)(><", "{}[]()<>",
-
+
"qahwah ( قهوة)",
"שָׁלוֹם עֲלֵיכֶם",
"Ramen チャーシュー chāshū",
diff --git a/api/command.go b/api/command.go
index 449483bbf..810a8a07e 100644
--- a/api/command.go
+++ b/api/command.go
@@ -9,6 +9,8 @@ import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
"net/http"
+ "reflect"
+ "runtime"
"strconv"
"strings"
)
@@ -19,16 +21,13 @@ var commands = []commandHandler{
logoutCommand,
joinCommand,
loadTestCommand,
+ echoCommand,
}
func InitCommand(r *mux.Router) {
l4g.Debug("Initializing command api routes")
r.Handle("/command", ApiUserRequired(command)).Methods("POST")
- if utils.Cfg.TeamSettings.AllowValet {
- commands = append(commands, echoCommand)
- }
-
hub.Start()
}
@@ -59,6 +58,8 @@ func checkCommand(c *Context, command *model.Command) bool {
return false
}
+ tchan := Srv.Store.Team().Get(c.Session.TeamId)
+
if len(command.ChannelId) > 0 {
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, command.ChannelId, c.Session.UserId)
@@ -67,7 +68,21 @@ func checkCommand(c *Context, command *model.Command) bool {
}
}
+ allowValet := false
+ if tResult := <-tchan; tResult.Err != nil {
+ c.Err = model.NewAppError("checkCommand", "Could not find the team for this session, team_id="+c.Session.TeamId, "")
+ return false
+ } else {
+ allowValet = tResult.Data.(*model.Team).AllowValet
+ }
+
+ ec := runtime.FuncForPC(reflect.ValueOf(echoCommand).Pointer()).Name()
+
for _, v := range commands {
+ if !allowValet && ec == runtime.FuncForPC(reflect.ValueOf(v).Pointer()).Name() {
+ continue
+ }
+
if v(c, command) {
return true
} else if c.Err != nil {
@@ -182,7 +197,7 @@ func joinCommand(c *Context, command *model.Command) bool {
return false
}
- JoinChannel(c, v.Id, "/command")
+ JoinChannel(c, v.Id, "")
if c.Err != nil {
return false
diff --git a/api/command_test.go b/api/command_test.go
index d3b0da455..5b7734628 100644
--- a/api/command_test.go
+++ b/api/command_test.go
@@ -129,7 +129,7 @@ func TestJoinCommands(t *testing.T) {
c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
- if len(c1.Channels) != 3 { // 3 because of town-square and direct
+ if len(c1.Channels) != 4 { // 4 because of town-square, off-topic and direct
t.Fatal("didn't join channel")
}
diff --git a/api/file.go b/api/file.go
index 10167c6ff..0e08567d6 100644
--- a/api/file.go
+++ b/api/file.go
@@ -15,6 +15,7 @@ import (
"github.com/nfnt/resize"
"image"
_ "image/gif"
+ _ "golang.org/x/image/bmp"
"image/jpeg"
"io"
"net/http"
diff --git a/api/post.go b/api/post.go
index 3acc95551..2d812e8de 100644
--- a/api/post.go
+++ b/api/post.go
@@ -58,11 +58,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
func createValetPost(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.TeamSettings.AllowValet {
- c.Err = model.NewAppError("createValetPost", "The valet feature is currently turned off. Please contact your system administrator for details.", "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
+ tchan := Srv.Store.Team().Get(c.Session.TeamId)
post := model.PostFromJson(r.Body)
if post == nil {
@@ -70,13 +66,25 @@ func createValetPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- // Any one with access to the team can post as valet to any open channel
cchan := Srv.Store.Channel().CheckOpenChannelPermissions(c.Session.TeamId, post.ChannelId)
+ // Any one with access to the team can post as valet to any open channel
if !c.HasPermissionsToChannel(cchan, "createValetPost") {
return
}
+ // Make sure this team has the valet feature enabled
+ if tResult := <-tchan; tResult.Err != nil {
+ c.Err = model.NewAppError("createValetPost", "Could not find the team for this session, team_id="+c.Session.TeamId, "")
+ return
+ } else {
+ if !tResult.Data.(*model.Team).AllowValet {
+ c.Err = model.NewAppError("createValetPost", "The valet feature is currently turned off. Please contact your team administrator for details.", "")
+ c.Err.StatusCode = http.StatusNotImplemented
+ return
+ }
+ }
+
if rp, err := CreateValetPost(c, post); err != nil {
c.Err = err
@@ -265,7 +273,7 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) {
} else {
- // Find out who is a member of the channel only keep those profiles
+ // Find out who is a member of the channel, only keep those profiles
if eResult := <-echan; eResult.Err != nil {
l4g.Error("Failed to get channel members channel_id=%v err=%v", post.ChannelId, eResult.Err.Message)
return
@@ -298,13 +306,23 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) {
}
}
}
+
+ // Add @all to keywords if user has them turned on
+ if profile.NotifyProps["all"] == "true" {
+ keywordMap["@all"] = append(keywordMap["@all"], profile.Id)
+ }
+
+ // Add @channel to keywords if user has them turned on
+ if profile.NotifyProps["channel"] == "true" {
+ keywordMap["@channel"] = append(keywordMap["@channel"], profile.Id)
+ }
}
// Build a map as a list of unique user_ids that are mentioned in this post
splitF := func(c rune) bool {
return model.SplitRunes[c]
}
- splitMessage := strings.FieldsFunc(strings.Replace(post.Message, "<br>", " ", -1), splitF)
+ splitMessage := strings.FieldsFunc(post.Message, splitF)
for _, word := range splitMessage {
// Non-case-sensitive check for regular keys
diff --git a/api/post_test.go b/api/post_test.go
index b322a5017..03f70bff7 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -147,7 +147,7 @@ func TestCreateValetPost(t *testing.T) {
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
- if utils.Cfg.TeamSettings.AllowValet {
+ if utils.Cfg.TeamSettings.AllowValetDefault {
post1 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag a" + model.NewId() + "a"}
rpost1, err := Client.CreateValetPost(post1)
if err != nil {
diff --git a/api/team.go b/api/team.go
index cb60602c6..15e4e2c17 100644
--- a/api/team.go
+++ b/api/team.go
@@ -29,6 +29,8 @@ func InitTeam(r *mux.Router) {
sr.Handle("/email_teams", ApiAppHandler(emailTeams)).Methods("POST")
sr.Handle("/invite_members", ApiUserRequired(inviteMembers)).Methods("POST")
sr.Handle("/update_name", ApiUserRequired(updateTeamName)).Methods("POST")
+ sr.Handle("/update_valet_feature", ApiUserRequired(updateValetFeature)).Methods("POST")
+ sr.Handle("/me", ApiUserRequired(getMyTeam)).Methods("GET")
}
func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -136,16 +138,16 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
+ teamSignup.Team.AllowValet = utils.Cfg.TeamSettings.AllowValetDefault
+
if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil {
c.Err = result.Err
return
} else {
rteam := result.Data.(*model.Team)
- channel := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: rteam.Id}
-
- if _, err := CreateChannel(c, channel, r.URL.Path, false); err != nil {
- c.Err = err
+ if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
+ c.Err = nil
return
}
@@ -157,7 +159,7 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if utils.Cfg.TeamSettings.AllowValet {
+ if teamSignup.Team.AllowValet {
CreateValet(c, rteam)
if c.Err != nil {
return
@@ -193,13 +195,18 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
rteam := result.Data.(*model.Team)
- channel := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: rteam.Id}
-
- if _, err := CreateChannel(c, channel, r.URL.Path, false); err != nil {
- c.Err = err
+ if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
+ c.Err = nil
return
}
+ if rteam.AllowValet {
+ CreateValet(c, rteam)
+ if c.Err != nil {
+ return
+ }
+ }
+
w.Write([]byte(rteam.ToJson()))
}
}
@@ -477,12 +484,21 @@ func InviteMembers(team *model.Team, user *model.User, invites []string) {
} else {
sender = user.FullName
}
+
+ senderRole := ""
+ if strings.Contains(user.Roles, model.ROLE_ADMIN) || strings.Contains(user.Roles, model.ROLE_SYSTEM_ADMIN) {
+ senderRole = "administrator"
+ } else {
+ senderRole = "member"
+ }
+
subjectPage := NewServerTemplatePage("invite_subject", teamUrl)
subjectPage.Props["SenderName"] = sender
subjectPage.Props["TeamName"] = team.Name
bodyPage := NewServerTemplatePage("invite_body", teamUrl)
bodyPage.Props["TeamName"] = team.Name
bodyPage.Props["SenderName"] = sender
+ bodyPage.Props["SenderStatus"] = senderRole
bodyPage.Props["Email"] = invite
@@ -542,3 +558,72 @@ func updateTeamName(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(props)))
}
+
+func updateValetFeature(c *Context, w http.ResponseWriter, r *http.Request) {
+
+ props := model.MapFromJson(r.Body)
+
+ allowValetStr := props["allow_valet"]
+ if len(allowValetStr) == 0 {
+ c.SetInvalidParam("updateValetFeature", "allow_valet")
+ return
+ }
+
+ allowValet := allowValetStr == "true"
+
+ teamId := props["team_id"]
+ if len(teamId) > 0 && len(teamId) != 26 {
+ c.SetInvalidParam("updateValetFeature", "team_id")
+ return
+ } else if len(teamId) == 0 {
+ teamId = c.Session.TeamId
+ }
+
+ tchan := Srv.Store.Team().Get(teamId)
+
+ if !c.HasPermissionsToTeam(teamId, "updateValetFeature") {
+ return
+ }
+
+ if !strings.Contains(c.Session.Roles, model.ROLE_ADMIN) {
+ c.Err = model.NewAppError("updateValetFeature", "You do not have the appropriate permissions", "userId="+c.Session.UserId)
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
+
+ var team *model.Team
+ if tResult := <-tchan; tResult.Err != nil {
+ c.Err = tResult.Err
+ return
+ } else {
+ team = tResult.Data.(*model.Team)
+ }
+
+ team.AllowValet = allowValet
+
+ if result := <-Srv.Store.Team().Update(team); result.Err != nil {
+ c.Err = result.Err
+ return
+ }
+
+ w.Write([]byte(model.MapToJson(props)))
+}
+
+func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
+
+ if len(c.Session.TeamId) == 0 {
+ return
+ }
+
+ if result := <-Srv.Store.Team().Get(c.Session.TeamId); result.Err != nil {
+ c.Err = result.Err
+ return
+ } else if HandleEtag(result.Data.(*model.Team).Etag(), w, r) {
+ return
+ } else {
+ w.Header().Set(model.HEADER_ETAG_SERVER, result.Data.(*model.Team).Etag())
+ w.Header().Set("Expires", "-1")
+ w.Write([]byte(result.Data.(*model.Team).ToJson()))
+ return
+ }
+}
diff --git a/api/team_test.go b/api/team_test.go
index 74a184634..bb77d43a0 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -55,6 +55,11 @@ func TestCreateFromSignupTeam(t *testing.T) {
}
}
+ c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
+ if len(c1.Channels) != 2 {
+ t.Fatal("default channels not created")
+ }
+
ts.Data = "garbage"
_, err = Client.CreateTeamFromSignup(&ts)
if err == nil {
@@ -71,6 +76,17 @@ func TestCreateTeam(t *testing.T) {
t.Fatal(err)
}
+ user := &model.User{TeamId: rteam.Data.(*model.Team).Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
+ user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
+ Srv.Store.User().VerifyEmail(user.Id)
+
+ Client.LoginByEmail(team.Domain, user.Email, "pwd")
+
+ c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
+ if len(c1.Channels) != 2 {
+ t.Fatal("default channels not created")
+ }
+
if rteam.Data.(*model.Team).Name != team.Name {
t.Fatal("full name didn't match")
}
@@ -286,3 +302,106 @@ func TestFuzzyTeamCreate(t *testing.T) {
}
}
}
+
+func TestGetMyTeam(t *testing.T) {
+ Setup()
+
+ team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+ rteam, _ := Client.CreateTeam(&team)
+
+ user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
+ ruser, _ := Client.CreateUser(&user, "")
+ Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)
+
+ Client.LoginByEmail(team.Domain, user.Email, user.Password)
+
+ if result, err := Client.GetMyTeam(""); err != nil {
+ t.Fatal("Failed to get user")
+ } else {
+ if result.Data.(*model.Team).Name != team.Name {
+ t.Fatal("team names did not match")
+ }
+ if result.Data.(*model.Team).Domain != team.Domain {
+ t.Fatal("team domains did not match")
+ }
+ if result.Data.(*model.Team).Type != team.Type {
+ t.Fatal("team types did not match")
+ }
+ }
+}
+
+func TestUpdateValetFeature(t *testing.T) {
+ Setup()
+
+ team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+ team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+
+ user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
+ user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
+ Srv.Store.User().VerifyEmail(user.Id)
+
+ user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
+ user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
+ Srv.Store.User().VerifyEmail(user2.Id)
+
+ team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+ team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
+
+ user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
+ user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
+ Srv.Store.User().VerifyEmail(user3.Id)
+
+ Client.LoginByEmail(team.Domain, user2.Email, "pwd")
+
+ data := make(map[string]string)
+ data["allow_valet"] = "true"
+ if _, err := Client.UpdateValetFeature(data); err == nil {
+ t.Fatal("Should have errored, not admin")
+ }
+
+ Client.LoginByEmail(team.Domain, user.Email, "pwd")
+
+ data["allow_valet"] = ""
+ if _, err := Client.UpdateValetFeature(data); err == nil {
+ t.Fatal("Should have errored, empty allow_valet field")
+ }
+
+ data["allow_valet"] = "true"
+ if _, err := Client.UpdateValetFeature(data); err != nil {
+ t.Fatal(err)
+ }
+
+ rteam := Client.Must(Client.GetMyTeam("")).Data.(*model.Team)
+ if rteam.AllowValet != true {
+ t.Fatal("Should have errored - allow valet property not updated")
+ }
+
+ data["team_id"] = "junk"
+ if _, err := Client.UpdateValetFeature(data); err == nil {
+ t.Fatal("Should have errored, junk team id")
+ }
+
+ data["team_id"] = "12345678901234567890123456"
+ if _, err := Client.UpdateValetFeature(data); err == nil {
+ t.Fatal("Should have errored, bad team id")
+ }
+
+ data["team_id"] = team.Id
+ data["allow_valet"] = "false"
+ if _, err := Client.UpdateValetFeature(data); err != nil {
+ t.Fatal(err)
+ }
+
+ rteam = Client.Must(Client.GetMyTeam("")).Data.(*model.Team)
+ if rteam.AllowValet != false {
+ t.Fatal("Should have errored - allow valet property not updated")
+ }
+
+ Client.LoginByEmail(team2.Domain, user3.Email, "pwd")
+
+ data["team_id"] = team.Id
+ data["allow_valet"] = "true"
+ if _, err := Client.UpdateValetFeature(data); err == nil {
+ t.Fatal("Should have errored, not part of team")
+ }
+}
diff --git a/api/templates/invite_body.html b/api/templates/invite_body.html
index 06f48759c..8be2ac0df 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.TeamName}} started using {{.SiteName}}.<br> The team administrator <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamName}}</strong>.</p>
+ <p>{{.Props.TeamName}} started using {{.SiteName}}.<br> The team {{.Props.SenderStatus}} <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamName}}</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>
diff --git a/api/templates/post_body.html b/api/templates/post_body.html
index 663ec66d2..069cdf1fb 100644
--- a/api/templates/post_body.html
+++ b/api/templates/post_body.html
@@ -20,7 +20,7 @@
<h2 style="font-weight: normal; margin-top: 10px;">You were mentioned</h2>
<p>CHANNEL: {{.Props.ChannelName}}<br>{{.Props.SenderName}} - {{.Props.Hour}}:{{.Props.Minute}} GMT, {{.Props.Month}} {{.Props.Day}}<br><pre style="text-align:left;font-family: 'Lato', sans-serif;">{{.Props.PostMessage}}</pre></p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.TeamLink}}" 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;">Go To Channel</a>
+ <a href="{{.Props.TeamLink}}" style="background: #2389D7; display: inline-block; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 170px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Go To Channel</a>
</p>
</td>
</tr>
diff --git a/api/user.go b/api/user.go
index 79d4bb32c..292d2b61b 100644
--- a/api/user.go
+++ b/api/user.go
@@ -145,10 +145,6 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
func CreateValet(c *Context, team *model.Team) *model.User {
- if !utils.Cfg.TeamSettings.AllowValet {
- return &model.User{}
- }
-
valet := &model.User{}
valet.TeamId = team.Id
valet.Email = utils.Cfg.EmailSettings.FeedbackEmail
@@ -180,21 +176,16 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
} else {
ruser := result.Data.(*model.User)
- // Do not error if user cannot be added to the town-square channel
- if cresult := <-Srv.Store.Channel().GetByName(team.Id, "town-square"); cresult.Err != nil {
- l4g.Error("Failed to get town-square err=%v", cresult.Err)
- } else {
- cm := &model.ChannelMember{ChannelId: cresult.Data.(*model.Channel).Id, UserId: ruser.Id, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: channelRole}
- if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
- l4g.Error("Failed to add member town-square err=%v", cmresult.Err)
- }
+ // Soft error if there is an issue joining the default channels
+ if err := JoinDefaultChannels(c, ruser, channelRole); err != nil {
+ l4g.Error("Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v", ruser.Id, ruser.TeamId, err)
}
//fireAndForgetWelcomeEmail(strings.Split(ruser.FullName, " ")[0], ruser.Email, team.Name, c.TeamUrl+"/channels/town-square")
if user.EmailVerified {
if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- l4g.Error("Failed to get town-square err=%v", cresult.Err)
+ l4g.Error("Failed to set email verified err=%v", cresult.Err)
}
} else {
FireAndForgetVerifyEmail(result.Data.(*model.User).Id, strings.Split(ruser.FullName, " ")[0], ruser.Email, team.Name, c.TeamUrl)
@@ -202,7 +193,7 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
ruser.Sanitize(map[string]bool{})
- //This message goes to every channel, so the channelId is irrelevant
+ // This message goes to every channel, so the channelId is irrelevant
message := model.NewMessage(team.Id, "", ruser.Id, model.ACTION_NEW_USER)
store.PublishAndForget(message)
diff --git a/api/web_socket_test.go b/api/web_socket_test.go
index c7b612cde..15bc3baeb 100644
--- a/api/web_socket_test.go
+++ b/api/web_socket_test.go
@@ -119,7 +119,7 @@ func TestSocket(t *testing.T) {
}
-func TestZZWebScoketTearDown(t *testing.T) {
+func TestZZWebSocketTearDown(t *testing.T) {
// *IMPORTANT* - Kind of hacky
// This should be the last function in any test file
// that calls Setup()