diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/channel.go | 59 | ||||
-rw-r--r-- | api/channel_test.go | 23 | ||||
-rw-r--r-- | api/command.go | 25 | ||||
-rw-r--r-- | api/command_test.go | 2 | ||||
-rw-r--r-- | api/file.go | 1 | ||||
-rw-r--r-- | api/post.go | 34 | ||||
-rw-r--r-- | api/post_test.go | 2 | ||||
-rw-r--r-- | api/team.go | 103 | ||||
-rw-r--r-- | api/team_test.go | 119 | ||||
-rw-r--r-- | api/templates/invite_body.html | 2 | ||||
-rw-r--r-- | api/templates/post_body.html | 2 | ||||
-rw-r--r-- | api/user.go | 19 | ||||
-rw-r--r-- | api/web_socket_test.go | 2 |
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() |