diff options
86 files changed, 893 insertions, 1216 deletions
diff --git a/api/api.go b/api/api.go index 70e1b64ae..25f3376c6 100644 --- a/api/api.go +++ b/api/api.go @@ -16,10 +16,10 @@ var ServerTemplates *template.Template type ServerTemplatePage Page -func NewServerTemplatePage(templateName, teamUrl string) *ServerTemplatePage { +func NewServerTemplatePage(templateName, teamURL string) *ServerTemplatePage { props := make(map[string]string) props["AnalyticsUrl"] = utils.Cfg.ServiceSettings.AnalyticsUrl - return &ServerTemplatePage{TemplateName: templateName, SiteName: utils.Cfg.ServiceSettings.SiteName, FeedbackEmail: utils.Cfg.EmailSettings.FeedbackEmail, TeamUrl: teamUrl, Props: props} + return &ServerTemplatePage{TemplateName: templateName, SiteName: utils.Cfg.ServiceSettings.SiteName, FeedbackEmail: utils.Cfg.EmailSettings.FeedbackEmail, TeamURL: teamURL, Props: props} } func (me *ServerTemplatePage) Render() string { diff --git a/api/api_test.go b/api/api_test.go index 7d2faed4f..0c2e57891 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -24,12 +24,12 @@ func Setup() { func SetupBenchmark() (*model.Team, *model.User, *model.Channel) { Setup() - team := &model.Team{Name: "Benchmark Team", Domain: "z-z-" + model.NewId() + "a", Email: "benchmark@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Benchmark Team", Name: "z-z-" + model.NewId() + "a", Email: "benchmark@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user := &model.User{TeamId: team.Id, Email: model.NewId() + "benchmark@test.com", Nickname: "Mr. Benchmarker", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel := &model.Channel{DisplayName: "Benchmark Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel) diff --git a/api/auto_constants.go b/api/auto_constants.go index 3f8831055..f80f15f2d 100644 --- a/api/auto_constants.go +++ b/api/auto_constants.go @@ -12,8 +12,8 @@ const ( USER_PASSWORD = "passwd" CHANNEL_TYPE = model.CHANNEL_OPEN FUZZ_USER_EMAIL_PREFIX_LEN = 10 - BTEST_TEAM_NAME = "TestTeam" - BTEST_TEAM_DOMAIN_NAME = "z-z-testdomaina" + BTEST_TEAM_DISPLAY_NAME = "TestTeam" + BTEST_TEAM_NAME = "z-z-testdomaina" BTEST_TEAM_EMAIL = "test@nowhere.com" BTEST_TEAM_TYPE = model.TEAM_OPEN BTEST_USER_NAME = "Mr. Testing Tester" diff --git a/api/auto_teams.go b/api/auto_teams.go index 2fe826774..e5c772b4c 100644 --- a/api/auto_teams.go +++ b/api/auto_teams.go @@ -39,22 +39,22 @@ func NewAutoTeamCreator(client *model.Client) *AutoTeamCreator { func (cfg *AutoTeamCreator) createRandomTeam() (*model.Team, bool) { var teamEmail string + var teamDisplayName string var teamName string - var teamDomain string if cfg.Fuzzy { teamEmail = utils.FuzzEmail() + teamDisplayName = utils.FuzzName() teamName = utils.FuzzName() - teamDomain = utils.FuzzName() } else { teamEmail = utils.RandomEmail(cfg.EmailLength, cfg.EmailCharset) - teamName = utils.RandomName(cfg.NameLength, cfg.NameCharset) - teamDomain = utils.RandomName(cfg.NameLength, cfg.NameCharset) + model.NewId() + teamDisplayName = utils.RandomName(cfg.NameLength, cfg.NameCharset) + teamName = utils.RandomName(cfg.NameLength, cfg.NameCharset) + model.NewId() } team := &model.Team{ - Name: teamName, - Domain: teamDomain, - Email: teamEmail, - Type: model.TEAM_OPEN, + DisplayName: teamDisplayName, + Name: teamName, + Email: teamEmail, + Type: model.TEAM_OPEN, } result, err := cfg.client.CreateTeam(team) diff --git a/api/auto_users.go b/api/auto_users.go index d6918f13a..39ed201b9 100644 --- a/api/auto_users.go +++ b/api/auto_users.go @@ -33,9 +33,9 @@ func NewAutoUserCreator(client *model.Client, teamID string) *AutoUserCreator { // Basic test team and user so you always know one func CreateBasicUser(client *model.Client) *model.AppError { - result, _ := client.FindTeamByDomain(BTEST_TEAM_DOMAIN_NAME, true) + result, _ := client.FindTeamByName(BTEST_TEAM_NAME, true) if result.Data.(bool) == false { - newteam := &model.Team{Name: BTEST_TEAM_NAME, Domain: BTEST_TEAM_DOMAIN_NAME, Email: BTEST_TEAM_EMAIL, Type: BTEST_TEAM_TYPE} + newteam := &model.Team{DisplayName: BTEST_TEAM_DISPLAY_NAME, Name: BTEST_TEAM_NAME, Email: BTEST_TEAM_EMAIL, Type: BTEST_TEAM_TYPE} result, err := client.CreateTeam(newteam) if err != nil { return err diff --git a/api/channel_benchmark_test.go b/api/channel_benchmark_test.go index 17d3deb27..881638176 100644 --- a/api/channel_benchmark_test.go +++ b/api/channel_benchmark_test.go @@ -141,7 +141,7 @@ func BenchmarkJoinChannel(b *testing.B) { user := &model.User{TeamId: team.Id, Email: model.NewId() + "random@test.com", Nickname: "That Guy", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") // Benchmark Start b.ResetTimer() diff --git a/api/channel_test.go b/api/channel_test.go index 31ab85117..ae7781302 100644 --- a/api/channel_test.go +++ b/api/channel_test.go @@ -14,17 +14,17 @@ import ( func TestCreateChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) - team2 := &model.Team{Name: "Name Team 2", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel := model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} rchannel, err := Client.CreateChannel(&channel) @@ -94,7 +94,7 @@ func TestCreateChannel(t *testing.T) { func TestCreateDirectChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -105,7 +105,7 @@ func TestCreateDirectChannel(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") data := make(map[string]string) data["user_id"] = user2.Id @@ -149,7 +149,7 @@ func TestCreateDirectChannel(t *testing.T) { func TestUpdateChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"} @@ -165,7 +165,7 @@ func TestUpdateChannel(t *testing.T) { store.Must(Srv.Store.User().VerifyEmail(userStd.Id)) userStd.Roles = "" - Client.LoginByEmail(team.Domain, userChannelAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userChannelAdmin.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -184,7 +184,7 @@ func TestUpdateChannel(t *testing.T) { t.Fatal("Channel admin failed to skip displayName") } - Client.LoginByEmail(team.Domain, userTeamAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd") desc = "b" + model.NewId() + "b" upChannel1 = &model.Channel{Id: channel1.Id, Description: desc} @@ -210,7 +210,7 @@ func TestUpdateChannel(t *testing.T) { } } - Client.LoginByEmail(team.Domain, userStd.Email, "pwd") + Client.LoginByEmail(team.Name, userStd.Email, "pwd") if _, err := Client.UpdateChannel(upChannel1); err == nil { t.Fatal("Standard User should have failed to update") @@ -220,14 +220,14 @@ func TestUpdateChannel(t *testing.T) { func TestUpdateChannelDesc(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -270,7 +270,7 @@ func TestUpdateChannelDesc(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") data["channel_id"] = channel1.Id data["channel_description"] = "new desc" @@ -282,14 +282,14 @@ func TestUpdateChannelDesc(t *testing.T) { func TestGetChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -324,14 +324,14 @@ func TestGetChannel(t *testing.T) { func TestGetMoreChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -343,7 +343,7 @@ func TestGetMoreChannel(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") rget := Client.Must(Client.GetMoreChannels("")) data := rget.Data.(*model.ChannelList) @@ -368,14 +368,14 @@ func TestGetMoreChannel(t *testing.T) { func TestJoinChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -387,7 +387,7 @@ func TestJoinChannel(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") Client.Must(Client.JoinChannel(channel1.Id)) @@ -402,7 +402,7 @@ func TestJoinChannel(t *testing.T) { user3 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) - Client.LoginByEmail(team.Domain, user3.Email, "pwd") + Client.LoginByEmail(team.Name, user3.Email, "pwd") if _, err := Client.JoinChannel(rchannel.Id); err == nil { t.Fatal("shoudn't be able to join direct channel") @@ -412,14 +412,14 @@ func TestJoinChannel(t *testing.T) { func TestLeaveChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -431,7 +431,7 @@ func TestLeaveChannel(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") Client.Must(Client.JoinChannel(channel1.Id)) @@ -461,7 +461,7 @@ func TestLeaveChannel(t *testing.T) { func TestDeleteChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"} @@ -472,14 +472,14 @@ func TestDeleteChannel(t *testing.T) { userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id)) - Client.LoginByEmail(team.Domain, userChannelAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userChannelAdmin.Email, "pwd") channelMadeByCA := &model.Channel{DisplayName: "C Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channelMadeByCA = Client.Must(Client.CreateChannel(channelMadeByCA)).Data.(*model.Channel) Client.AddChannelMember(channelMadeByCA.Id, userTeamAdmin.Id) - Client.LoginByEmail(team.Domain, userTeamAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -504,7 +504,7 @@ func TestDeleteChannel(t *testing.T) { userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(userStd.Id)) - Client.LoginByEmail(team.Domain, userStd.Email, "pwd") + Client.LoginByEmail(team.Name, userStd.Email, "pwd") if _, err := Client.JoinChannel(channel1.Id); err == nil { t.Fatal("should have failed to join deleted channel") @@ -531,14 +531,14 @@ func TestDeleteChannel(t *testing.T) { func TestGetChannelExtraInfo(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -552,14 +552,14 @@ func TestGetChannelExtraInfo(t *testing.T) { func TestAddChannelMember(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -591,13 +591,13 @@ func TestAddChannelMember(t *testing.T) { channel2 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") if _, err := Client.AddChannelMember(channel2.Id, user2.Id); err == nil { t.Fatal("Should have errored, user not in channel") } - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") Client.Must(Client.DeleteChannel(channel2.Id)) @@ -610,7 +610,7 @@ func TestAddChannelMember(t *testing.T) { func TestRemoveChannelMember(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"} @@ -621,14 +621,14 @@ func TestRemoveChannelMember(t *testing.T) { userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id)) - Client.LoginByEmail(team.Domain, userChannelAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userChannelAdmin.Email, "pwd") channelMadeByCA := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channelMadeByCA = Client.Must(Client.CreateChannel(channelMadeByCA)).Data.(*model.Channel) Client.Must(Client.AddChannelMember(channelMadeByCA.Id, userTeamAdmin.Id)) - Client.LoginByEmail(team.Domain, userTeamAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -660,13 +660,13 @@ func TestRemoveChannelMember(t *testing.T) { channel2 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) - Client.LoginByEmail(team.Domain, userStd.Email, "pwd") + Client.LoginByEmail(team.Name, userStd.Email, "pwd") if _, err := Client.RemoveChannelMember(channel2.Id, userStd.Id); err == nil { t.Fatal("Should have errored, user not channel admin") } - Client.LoginByEmail(team.Domain, userTeamAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userTeamAdmin.Email, "pwd") Client.Must(Client.AddChannelMember(channel2.Id, userStd.Id)) Client.Must(Client.DeleteChannel(channel2.Id)) @@ -680,14 +680,14 @@ func TestRemoveChannelMember(t *testing.T) { func TestUpdateNotifyLevel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -749,7 +749,7 @@ func TestUpdateNotifyLevel(t *testing.T) { user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") data["channel_id"] = channel1.Id data["user_id"] = user2.Id @@ -762,14 +762,14 @@ func TestUpdateNotifyLevel(t *testing.T) { func TestFuzzyChannel(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") // Strings that should pass as acceptable channel names var fuzzyStringsPass = []string{ diff --git a/api/command.go b/api/command.go index ee7a11af3..f051bd42e 100644 --- a/api/command.go +++ b/api/command.go @@ -321,14 +321,14 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool { numPosts, _ = strconv.Atoi(tokens[numArgs+2]) } } - client := model.NewClient(c.TeamUrl + "/api/v1") + client := model.NewClient(c.GetSiteURL() + "/api/v1") if doTeams { if err := CreateBasicUser(client); err != nil { l4g.Error("Failed to create testing enviroment") return true } - client.LoginByEmail(BTEST_TEAM_DOMAIN_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD) + client.LoginByEmail(BTEST_TEAM_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD) enviroment, err := CreateTestEnviromentWithTeams( client, utils.Range{numTeams, numTeams}, @@ -342,7 +342,7 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool { } else { l4g.Info("Testing enviroment created") for i := 0; i < len(enviroment.Teams); i++ { - l4g.Info("Team Created: " + enviroment.Teams[i].Domain) + l4g.Info("Team Created: " + enviroment.Teams[i].Name) l4g.Info("\t User to login: " + enviroment.Enviroments[i].Users[0].Email + ", " + USER_PASSWORD) } } @@ -381,7 +381,7 @@ func loadTestUsersCommand(c *Context, command *model.Command) bool { if err == false { usersr = utils.Range{10, 15} } - client := model.NewClient(c.TeamUrl + "/api/v1") + client := model.NewClient(c.GetSiteURL() + "/api/v1") userCreator := NewAutoUserCreator(client, c.Session.TeamId) userCreator.Fuzzy = doFuzz userCreator.CreateTestUsers(usersr) @@ -411,7 +411,7 @@ func loadTestChannelsCommand(c *Context, command *model.Command) bool { if err == false { channelsr = utils.Range{20, 30} } - client := model.NewClient(c.TeamUrl + "/api/v1") + client := model.NewClient(c.GetSiteURL() + "/api/v1") client.MockSession(c.Session.Id) channelCreator := NewAutoChannelCreator(client, c.Session.TeamId) channelCreator.Fuzzy = doFuzz @@ -463,7 +463,7 @@ func loadTestPostsCommand(c *Context, command *model.Command) bool { } } - client := model.NewClient(c.TeamUrl + "/api/v1") + client := model.NewClient(c.GetSiteURL() + "/api/v1") client.MockSession(c.Session.Id) testPoster := NewAutoPostCreator(client, command.ChannelId) testPoster.Fuzzy = doFuzz diff --git a/api/command_test.go b/api/command_test.go index d9912f9d8..a58ef9be5 100644 --- a/api/command_test.go +++ b/api/command_test.go @@ -12,14 +12,14 @@ import ( func TestSuggestRootCommands(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") if _, err := Client.Command("", "", true); err == nil { t.Fatal("Should fail") @@ -55,14 +55,14 @@ func TestSuggestRootCommands(t *testing.T) { func TestLogoutCommands(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") rs1 := Client.Must(Client.Command("", "/logout", false)).Data.(*model.Command) if rs1.GotoLocation != "/logout" { @@ -73,14 +73,14 @@ func TestLogoutCommands(t *testing.T) { func TestJoinCommands(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) diff --git a/api/context.go b/api/context.go index 054e42e2e..ac9dffcbc 100644 --- a/api/context.go +++ b/api/context.go @@ -17,12 +17,14 @@ import ( var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE) type Context struct { - Session model.Session - RequestId string - IpAddress string - TeamUrl string - Path string - Err *model.AppError + Session model.Session + RequestId string + IpAddress string + Path string + Err *model.AppError + teamURLValid bool + teamURL string + siteURL string } type Page struct { @@ -30,32 +32,36 @@ type Page struct { Title string SiteName string FeedbackEmail string - TeamUrl string + TeamURL string Props map[string]string } func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { - return &handler{h, false, false, true, false} + return &handler{h, false, false, true, false, false} } func AppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { - return &handler{h, false, false, false, false} + return &handler{h, false, false, false, false, false} +} + +func AppHandlerIndependent(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { + return &handler{h, false, false, false, false, true} } func ApiUserRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { - return &handler{h, true, false, true, true} + return &handler{h, true, false, true, true, false} } func ApiUserRequiredActivity(h func(*Context, http.ResponseWriter, *http.Request), isUserActivity bool) http.Handler { - return &handler{h, true, false, true, isUserActivity} + return &handler{h, true, false, true, isUserActivity, false} } func UserRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { - return &handler{h, true, false, false, false} + return &handler{h, true, false, false, false, false} } func ApiAdminSystemRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { - return &handler{h, true, true, true, false} + return &handler{h, true, true, true, false, false} } type handler struct { @@ -64,6 +70,7 @@ type handler struct { requireSystemAdmin bool isApi bool isUserActivity bool + isTeamIndependent bool } func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -73,7 +80,6 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { c := &Context{} c.RequestId = model.NewId() c.IpAddress = GetIpAddress(r) - c.Path = r.URL.Path protocol := "http" @@ -90,7 +96,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } - c.TeamUrl = protocol + "://" + r.Host + c.setSiteURL(protocol + "://" + r.Host) w.Header().Set(model.HEADER_REQUEST_ID, c.RequestId) w.Header().Set(model.HEADER_VERSION_ID, utils.Cfg.ServiceSettings.Version) @@ -135,6 +141,15 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } + if h.isApi || h.isTeamIndependent { + c.setTeamURL(c.GetSiteURL(), false) + c.Path = r.URL.Path + } else { + splitURL := strings.Split(r.URL.Path, "/") + c.setTeamURL(protocol+"://"+r.Host+"/"+splitURL[1], true) + c.Path = "/" + strings.Join(splitURL[2:], "/") + } + if c.Err == nil && h.requireUser { c.UserRequired() } @@ -165,7 +180,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte(c.Err.ToJson())) } else { if c.Err.StatusCode == http.StatusUnauthorized { - http.Redirect(w, r, "/?redirect="+url.QueryEscape(r.URL.Path), http.StatusTemporaryRedirect) + http.Redirect(w, r, c.GetTeamURL()+"/?redirect="+url.QueryEscape(r.URL.Path), http.StatusTemporaryRedirect) } else { RenderWebError(c.Err, w, r) } @@ -299,6 +314,39 @@ func (c *Context) SetUnknownError(where string, details string) { c.Err = model.NewAppError(where, "An unknown error has occured. Please contact support.", details) } +func (c *Context) setTeamURL(url string, valid bool) { + c.teamURL = url + c.teamURLValid = valid +} + +func (c *Context) setTeamURLFromSession() { + if result := <-Srv.Store.Team().Get(c.Session.TeamId); result.Err == nil { + c.setTeamURL(c.GetSiteURL()+"/"+result.Data.(*model.Team).Name, true) + } +} + +func (c *Context) setSiteURL(url string) { + c.siteURL = url +} + +func (c *Context) GetTeamURLFromTeam(team *model.Team) string { + return c.GetSiteURL() + "/" + team.Name +} + +func (c *Context) GetTeamURL() string { + if !c.teamURLValid { + c.setTeamURLFromSession() + if !c.teamURLValid { + l4g.Debug("TeamURL accessed when not valid. Team URL should not be used in api functions or those that are team independent") + } + } + return c.teamURL +} + +func (c *Context) GetSiteURL() string { + return c.siteURL +} + func GetIpAddress(r *http.Request) string { address := r.Header.Get(model.HEADER_FORWARDED) if len(address) == 0 { diff --git a/api/file.go b/api/file.go index 0e08567d6..362cdf896 100644 --- a/api/file.go +++ b/api/file.go @@ -13,9 +13,9 @@ import ( "github.com/mattermost/platform/model" "github.com/mattermost/platform/utils" "github.com/nfnt/resize" + _ "golang.org/x/image/bmp" "image" _ "image/gif" - _ "golang.org/x/image/bmp" "image/jpeg" "io" "net/http" @@ -115,7 +115,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) { return } - fileUrl := c.TeamUrl + "/api/v1/files/get/" + channelId + "/" + c.Session.UserId + "/" + uid + "/" + url.QueryEscape(files[i].Filename) + fileUrl := c.GetSiteURL() + "/api/v1/files/get/" + channelId + "/" + c.Session.UserId + "/" + uid + "/" + url.QueryEscape(files[i].Filename) resStruct.Filenames = append(resStruct.Filenames, fileUrl) } @@ -363,7 +363,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) { data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.PublicLinkSalt)) - url := fmt.Sprintf("%s/api/v1/files/%s/%s/%s/%s?d=%s&h=%s&t=%s", c.TeamUrl, getType, channelId, userId, filename, url.QueryEscape(data), url.QueryEscape(hash), c.Session.TeamId) + url := fmt.Sprintf("%s/api/v1/files/%s/%s/%s/%s?d=%s&h=%s&t=%s", c.GetSiteURL(), getType, channelId, userId, filename, url.QueryEscape(data), url.QueryEscape(hash), c.Session.TeamId) if !c.HasPermissionsToChannel(cchan, "getPublicLink") { return diff --git a/api/file_test.go b/api/file_test.go index 044cad921..79ee03c77 100644 --- a/api/file_test.go +++ b/api/file_test.go @@ -24,14 +24,14 @@ import ( func TestUploadFile(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -111,14 +111,14 @@ func TestUploadFile(t *testing.T) { func TestGetFile(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -173,7 +173,7 @@ func TestGetFile(t *testing.T) { t.Fatal("file get failed") } - team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user2 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -187,7 +187,7 @@ func TestGetFile(t *testing.T) { data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.PublicLinkSalt)) - Client.LoginByEmail(team2.Domain, user2.Email, "pwd") + Client.LoginByEmail(team2.Name, user2.Email, "pwd") if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t="+team.Id, true); downErr != nil { t.Fatal(downErr) @@ -258,7 +258,7 @@ func TestGetFile(t *testing.T) { func TestGetPublicLink(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -269,7 +269,7 @@ func TestGetPublicLink(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -344,7 +344,7 @@ func TestGetPublicLink(t *testing.T) { t.Fatal("Should have errored - bad file path") } - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") data["filename"] = filenames[0] if _, err := Client.GetPublicLink(data); err == nil { t.Fatal("should have errored, user not member of channel") diff --git a/api/post.go b/api/post.go index 27dedbf71..fb9fdd1ef 100644 --- a/api/post.go +++ b/api/post.go @@ -122,7 +122,7 @@ func CreateValetPost(c *Context, post *model.Post) (*model.Post, *model.AppError rpost = result.Data.(*model.Post) } - fireAndForgetNotifications(rpost, c.Session.TeamId, c.TeamUrl) + fireAndForgetNotifications(rpost, c.Session.TeamId, c.GetSiteURL()) return rpost, nil } @@ -201,14 +201,14 @@ func CreatePost(c *Context, post *model.Post, doUpdateLastViewed bool) (*model.P } else { rpost = result.Data.(*model.Post) - fireAndForgetNotifications(rpost, c.Session.TeamId, c.TeamUrl) + fireAndForgetNotifications(rpost, c.Session.TeamId, c.GetSiteURL()) } return rpost, nil } -func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { +func fireAndForgetNotifications(post *model.Post, teamId, siteURL string) { go func() { // Get a list of user names (to be used as keywords) and ids for the given team @@ -362,20 +362,22 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { mentionedUsers = append(mentionedUsers, k) } - var teamName string + var teamDisplayName string + var teamURL string if result := <-tchan; result.Err != nil { l4g.Error("Failed to retrieve team team_id=%v, err=%v", teamId, result.Err) return } else { - teamName = result.Data.(*model.Team).Name + teamDisplayName = result.Data.(*model.Team).DisplayName + teamURL = siteURL + "/" + result.Data.(*model.Team).Name } // Build and send the emails location, _ := time.LoadLocation("UTC") tm := time.Unix(post.CreateAt/1000, 0).In(location) - subjectPage := NewServerTemplatePage("post_subject", teamUrl) - subjectPage.Props["TeamName"] = teamName + subjectPage := NewServerTemplatePage("post_subject", teamURL) + subjectPage.Props["TeamDisplayName"] = teamDisplayName subjectPage.Props["SubjectText"] = subjectText subjectPage.Props["Month"] = tm.Month().String()[:3] subjectPage.Props["Day"] = fmt.Sprintf("%d", tm.Day()) @@ -392,9 +394,9 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { continue } - bodyPage := NewServerTemplatePage("post_body", teamUrl) + bodyPage := NewServerTemplatePage("post_body", teamURL) bodyPage.Props["Nickname"] = profileMap[id].FirstName - bodyPage.Props["TeamName"] = teamName + bodyPage.Props["TeamDisplayName"] = teamDisplayName bodyPage.Props["ChannelName"] = channelName bodyPage.Props["BodyText"] = bodyText bodyPage.Props["SenderName"] = senderName @@ -403,7 +405,7 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { bodyPage.Props["Month"] = tm.Month().String()[:3] bodyPage.Props["Day"] = fmt.Sprintf("%d", tm.Day()) bodyPage.Props["PostMessage"] = model.ClearMentionTags(post.Message) - bodyPage.Props["TeamLink"] = teamUrl + "/channels/" + channel.Name + bodyPage.Props["TeamLink"] = teamURL + "/channels/" + channel.Name if err := utils.SendMail(profileMap[id].Email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send mention email successfully email=%v err=%v", profileMap[id].Email, err) @@ -636,9 +638,9 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) { post := result.Data.(*model.PostList).Posts[postId] - if !c.HasPermissionsToChannel(cchan, "deletePost") && !c.IsTeamAdmin(post.UserId){ - return - } + if !c.HasPermissionsToChannel(cchan, "deletePost") && !c.IsTeamAdmin(post.UserId) { + return + } if post == nil { c.SetInvalidParam("deletePost", "postId") @@ -651,7 +653,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) { return } - if post.UserId != c.Session.UserId && !strings.Contains(c.Session.Roles,model.ROLE_ADMIN) { + if post.UserId != c.Session.UserId && !strings.Contains(c.Session.Roles, model.ROLE_ADMIN) { c.Err = model.NewAppError("deletePost", "You do not have the appropriate permissions", "") c.Err.StatusCode = http.StatusForbidden return diff --git a/api/post_test.go b/api/post_test.go index 583d1be43..3249ed7fa 100644 --- a/api/post_test.go +++ b/api/post_test.go @@ -15,10 +15,10 @@ import ( func TestCreatePost(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) - team2 := &model.Team{Name: "Name Team 2", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -29,7 +29,7 @@ func TestCreatePost(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -96,7 +96,7 @@ func TestCreatePost(t *testing.T) { t.Fatal("Should have been forbidden") } - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") post7 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} _, err = Client.CreatePost(post7) if err.StatusCode != http.StatusForbidden { @@ -107,7 +107,7 @@ func TestCreatePost(t *testing.T) { user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user3.Id)) - Client.LoginByEmail(team2.Domain, user3.Email, "pwd") + Client.LoginByEmail(team2.Name, user3.Email, "pwd") channel3 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id} channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel) @@ -126,10 +126,10 @@ func TestCreatePost(t *testing.T) { func TestCreateValetPost(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) - team2 := &model.Team{Name: "Name Team 2", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -140,7 +140,7 @@ func TestCreateValetPost(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -181,7 +181,7 @@ func TestCreateValetPost(t *testing.T) { t.Fatal("Should have been forbidden") } - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") post5 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} _, err = Client.CreateValetPost(post5) if err != nil { @@ -192,7 +192,7 @@ func TestCreateValetPost(t *testing.T) { user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user3.Id)) - Client.LoginByEmail(team2.Domain, user3.Email, "pwd") + Client.LoginByEmail(team2.Name, user3.Email, "pwd") channel3 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id} channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel) @@ -218,10 +218,10 @@ func TestCreateValetPost(t *testing.T) { func TestUpdatePost(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) - team2 := &model.Team{Name: "Name Team 2", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -232,7 +232,7 @@ func TestUpdatePost(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -289,14 +289,14 @@ func TestUpdatePost(t *testing.T) { func TestGetPosts(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -354,14 +354,14 @@ func TestGetPosts(t *testing.T) { func TestSearchPosts(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -400,14 +400,14 @@ func TestSearchPosts(t *testing.T) { func TestSearchHashtagPosts(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -431,14 +431,14 @@ func TestSearchHashtagPosts(t *testing.T) { func TestGetPostsCache(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -480,7 +480,7 @@ func TestGetPostsCache(t *testing.T) { func TestDeletePosts(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) userAdmin := &model.User{TeamId: team.Id, Email: team.Email, Nickname: "Corey Hulen", Password: "pwd"} @@ -491,7 +491,7 @@ func TestDeletePosts(t *testing.T) { user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -532,7 +532,7 @@ func TestDeletePosts(t *testing.T) { post4 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"} post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) - Client.LoginByEmail(team.Domain, userAdmin.Email, "pwd") + Client.LoginByEmail(team.Name, userAdmin.Email, "pwd") Client.Must(Client.DeletePost(channel1.Id, post4.Id)) } @@ -540,14 +540,14 @@ func TestDeletePosts(t *testing.T) { func TestEmailMention(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: "corey@test.com", Nickname: "Bob Bobby", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -562,14 +562,14 @@ func TestEmailMention(t *testing.T) { func TestFuzzyPosts(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) diff --git a/api/sharding.go b/api/sharding.go new file mode 100644 index 000000000..569d3a232 --- /dev/null +++ b/api/sharding.go @@ -0,0 +1,79 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +package api + +/* +func createSubDomain(subDomain string, target string) { + + if utils.Cfg.AWSSettings.Route53AccessKeyId == "" { + return + } + + creds := aws.Creds(utils.Cfg.AWSSettings.Route53AccessKeyId, utils.Cfg.AWSSettings.Route53SecretAccessKey, "") + r53 := route53.New(aws.DefaultConfig.Merge(&aws.Config{Credentials: creds, Region: utils.Cfg.AWSSettings.Route53Region})) + + rr := route53.ResourceRecord{ + Value: aws.String(target), + } + + rrs := make([]*route53.ResourceRecord, 1) + rrs[0] = &rr + + change := route53.Change{ + Action: aws.String("CREATE"), + ResourceRecordSet: &route53.ResourceRecordSet{ + Name: aws.String(fmt.Sprintf("%v.%v", subDomain, utils.Cfg.ServiceSettings.Domain)), + TTL: aws.Long(300), + Type: aws.String("CNAME"), + ResourceRecords: rrs, + }, + } + + changes := make([]*route53.Change, 1) + changes[0] = &change + + r53req := &route53.ChangeResourceRecordSetsInput{ + HostedZoneID: aws.String(utils.Cfg.AWSSettings.Route53ZoneId), + ChangeBatch: &route53.ChangeBatch{ + Changes: changes, + }, + } + + if _, err := r53.ChangeResourceRecordSets(r53req); err != nil { + l4g.Error("erro in createSubDomain domain=%v err=%v", subDomain, err) + return + } +} + +func doesSubDomainExist(subDomain string) bool { + + // if it's configured for testing then skip this step + if utils.Cfg.AWSSettings.Route53AccessKeyId == "" { + return false + } + + creds := aws.Creds(utils.Cfg.AWSSettings.Route53AccessKeyId, utils.Cfg.AWSSettings.Route53SecretAccessKey, "") + r53 := route53.New(aws.DefaultConfig.Merge(&aws.Config{Credentials: creds, Region: utils.Cfg.AWSSettings.Route53Region})) + + r53req := &route53.ListResourceRecordSetsInput{ + HostedZoneID: aws.String(utils.Cfg.AWSSettings.Route53ZoneId), + MaxItems: aws.String("1"), + StartRecordName: aws.String(fmt.Sprintf("%v.%v.", subDomain, utils.Cfg.ServiceSettings.Domain)), + } + + if result, err := r53.ListResourceRecordSets(r53req); err != nil { + l4g.Error("error in doesSubDomainExist domain=%v err=%v", subDomain, err) + return true + } else { + + for _, v := range result.ResourceRecordSets { + if v.Name != nil && *v.Name == fmt.Sprintf("%v.%v.", subDomain, utils.Cfg.ServiceSettings.Domain) { + return true + } + } + } + + return false +} +*/ diff --git a/api/team.go b/api/team.go index 7a4cabf7e..1145e6e81 100644 --- a/api/team.go +++ b/api/team.go @@ -6,8 +6,6 @@ package api import ( l4g "code.google.com/p/log4go" "fmt" - "github.com/awslabs/aws-sdk-go/aws" - "github.com/awslabs/aws-sdk-go/service/route53" "github.com/gorilla/mux" "github.com/mattermost/platform/model" "github.com/mattermost/platform/utils" @@ -24,11 +22,11 @@ func InitTeam(r *mux.Router) { sr.Handle("/create", ApiAppHandler(createTeam)).Methods("POST") sr.Handle("/create_from_signup", ApiAppHandler(createTeamFromSignup)).Methods("POST") sr.Handle("/signup", ApiAppHandler(signupTeam)).Methods("POST") - sr.Handle("/find_team_by_domain", ApiAppHandler(findTeamByDomain)).Methods("POST") + sr.Handle("/find_team_by_name", ApiAppHandler(findTeamByName)).Methods("POST") sr.Handle("/find_teams", ApiAppHandler(findTeams)).Methods("POST") 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_name", ApiUserRequired(updateTeamDisplayName)).Methods("POST") sr.Handle("/update_valet_feature", ApiUserRequired(updateValetFeature)).Methods("POST") sr.Handle("/me", ApiUserRequired(getMyTeam)).Methods("GET") } @@ -37,31 +35,31 @@ func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { m := model.MapFromJson(r.Body) email := strings.ToLower(strings.TrimSpace(m["email"])) - name := strings.TrimSpace(m["name"]) + displayName := strings.TrimSpace(m["display_name"]) if len(email) == 0 { c.SetInvalidParam("signupTeam", "email") return } - if len(name) == 0 { - c.SetInvalidParam("signupTeam", "name") + if len(displayName) == 0 { + c.SetInvalidParam("signupTeam", "display_name") return } - subjectPage := NewServerTemplatePage("signup_team_subject", c.TeamUrl) - bodyPage := NewServerTemplatePage("signup_team_body", c.TeamUrl) + subjectPage := NewServerTemplatePage("signup_team_subject", c.GetSiteURL()) + bodyPage := NewServerTemplatePage("signup_team_body", c.GetSiteURL()) bodyPage.Props["TourUrl"] = utils.Cfg.TeamSettings.TourLink props := make(map[string]string) props["email"] = email - props["name"] = name + props["display_name"] = displayName props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) - bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_team_complete/?d=%s&h=%s", c.TeamUrl, url.QueryEscape(data), url.QueryEscape(hash)) + bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_team_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { c.Err = err @@ -119,25 +117,16 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { return } - found := FindTeamByDomain(c, teamSignup.Team.Domain, "true") + found := FindTeamByName(c, teamSignup.Team.Name, "true") if c.Err != nil { return } if found { - c.Err = model.NewAppError("createTeamFromSignup", "This URL is unavailable. Please try another.", "d="+teamSignup.Team.Domain) + c.Err = model.NewAppError("createTeamFromSignup", "This URL is unavailable. Please try another.", "d="+teamSignup.Team.Name) return } - if IsBetaDomain(r) { - for key, value := range utils.Cfg.ServiceSettings.Shards { - if strings.Index(r.Host, key) == 0 { - createSubDomain(teamSignup.Team.Domain, value) - break - } - } - } - teamSignup.Team.AllowValet = utils.Cfg.TeamSettings.AllowValetDefault if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil { @@ -166,7 +155,7 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { } } - InviteMembers(rteam, ruser, teamSignup.Invites) + InviteMembers(c, rteam, ruser, teamSignup.Invites) teamSignup.Team = *rteam teamSignup.User = *ruser @@ -211,87 +200,14 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) { } } -func doesSubDomainExist(subDomain string) bool { - - // if it's configured for testing then skip this step - if utils.Cfg.AWSSettings.Route53AccessKeyId == "" { - return false - } - - creds := aws.Creds(utils.Cfg.AWSSettings.Route53AccessKeyId, utils.Cfg.AWSSettings.Route53SecretAccessKey, "") - r53 := route53.New(aws.DefaultConfig.Merge(&aws.Config{Credentials: creds, Region: utils.Cfg.AWSSettings.Route53Region})) - - r53req := &route53.ListResourceRecordSetsInput{ - HostedZoneID: aws.String(utils.Cfg.AWSSettings.Route53ZoneId), - MaxItems: aws.String("1"), - StartRecordName: aws.String(fmt.Sprintf("%v.%v.", subDomain, utils.Cfg.ServiceSettings.Domain)), - } - - if result, err := r53.ListResourceRecordSets(r53req); err != nil { - l4g.Error("error in doesSubDomainExist domain=%v err=%v", subDomain, err) - return true - } else { - - for _, v := range result.ResourceRecordSets { - if v.Name != nil && *v.Name == fmt.Sprintf("%v.%v.", subDomain, utils.Cfg.ServiceSettings.Domain) { - return true - } - } - } - - return false -} - -func createSubDomain(subDomain string, target string) { - - if utils.Cfg.AWSSettings.Route53AccessKeyId == "" { - return - } - - creds := aws.Creds(utils.Cfg.AWSSettings.Route53AccessKeyId, utils.Cfg.AWSSettings.Route53SecretAccessKey, "") - r53 := route53.New(aws.DefaultConfig.Merge(&aws.Config{Credentials: creds, Region: utils.Cfg.AWSSettings.Route53Region})) - - rr := route53.ResourceRecord{ - Value: aws.String(target), - } - - rrs := make([]*route53.ResourceRecord, 1) - rrs[0] = &rr - - change := route53.Change{ - Action: aws.String("CREATE"), - ResourceRecordSet: &route53.ResourceRecordSet{ - Name: aws.String(fmt.Sprintf("%v.%v", subDomain, utils.Cfg.ServiceSettings.Domain)), - TTL: aws.Long(300), - Type: aws.String("CNAME"), - ResourceRecords: rrs, - }, - } - - changes := make([]*route53.Change, 1) - changes[0] = &change - - r53req := &route53.ChangeResourceRecordSetsInput{ - HostedZoneID: aws.String(utils.Cfg.AWSSettings.Route53ZoneId), - ChangeBatch: &route53.ChangeBatch{ - Changes: changes, - }, - } - - if _, err := r53.ChangeResourceRecordSets(r53req); err != nil { - l4g.Error("erro in createSubDomain domain=%v err=%v", subDomain, err) - return - } -} - -func findTeamByDomain(c *Context, w http.ResponseWriter, r *http.Request) { +func findTeamByName(c *Context, w http.ResponseWriter, r *http.Request) { m := model.MapFromJson(r.Body) - domain := strings.ToLower(strings.TrimSpace(m["domain"])) + name := strings.ToLower(strings.TrimSpace(m["name"])) all := strings.ToLower(strings.TrimSpace(m["all"])) - found := FindTeamByDomain(c, domain, all) + found := FindTeamByName(c, name, all) if c.Err != nil { return @@ -304,56 +220,25 @@ func findTeamByDomain(c *Context, w http.ResponseWriter, r *http.Request) { } } -func FindTeamByDomain(c *Context, domain string, all string) bool { +func FindTeamByName(c *Context, name string, all string) bool { - if domain == "" || len(domain) > 64 { - c.SetInvalidParam("findTeamByDomain", "domain") + if name == "" || len(name) > 64 { + c.SetInvalidParam("findTeamByName", "domain") return false } - if model.IsReservedDomain(domain) { - c.Err = model.NewAppError("findTeamByDomain", "This URL is unavailable. Please try another.", "d="+domain) + if model.IsReservedTeamName(name) { + c.Err = model.NewAppError("findTeamByName", "This URL is unavailable. Please try another.", "name="+name) return false } - if all == "false" { - if result := <-Srv.Store.Team().GetByDomain(domain); result.Err != nil { - return false - } else { - return true - } - } else { - if doesSubDomainExist(domain) { - return true - } - - protocol := "http" - - if utils.Cfg.ServiceSettings.UseSSL { - protocol = "https" - } - - for key, _ := range utils.Cfg.ServiceSettings.Shards { - url := fmt.Sprintf("%v://%v.%v/api/v1", protocol, key, utils.Cfg.ServiceSettings.Domain) - - if strings.Index(utils.Cfg.ServiceSettings.Domain, "localhost") == 0 { - url = fmt.Sprintf("%v://%v/api/v1", protocol, utils.Cfg.ServiceSettings.Domain) - } - - client := model.NewClient(url) - - if result, err := client.FindTeamByDomain(domain, false); err != nil { - c.Err = err - return false - } else { - if result.Data.(bool) { - return true - } - } - } - + if result := <-Srv.Store.Team().GetByName(name); result.Err != nil { return false + } else { + return true } + + return false } func findTeams(c *Context, w http.ResponseWriter, r *http.Request) { @@ -376,7 +261,7 @@ func findTeams(c *Context, w http.ResponseWriter, r *http.Request) { s := make([]string, 0, len(teams)) for _, v := range teams { - s = append(s, v.Domain) + s = append(s, v.Name) } w.Write([]byte(model.ArrayToJson(s))) @@ -394,33 +279,8 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) { return } - protocol := "http" - - if utils.Cfg.ServiceSettings.UseSSL { - protocol = "https" - } - - subjectPage := NewServerTemplatePage("find_teams_subject", c.TeamUrl) - bodyPage := NewServerTemplatePage("find_teams_body", c.TeamUrl) - - for key, _ := range utils.Cfg.ServiceSettings.Shards { - url := fmt.Sprintf("%v://%v.%v/api/v1", protocol, key, utils.Cfg.ServiceSettings.Domain) - - if strings.Index(utils.Cfg.ServiceSettings.Domain, "localhost") == 0 { - url = fmt.Sprintf("%v://%v/api/v1", protocol, utils.Cfg.ServiceSettings.Domain) - } - - client := model.NewClient(url) - - if result, err := client.FindTeams(email); err != nil { - l4g.Error("An error occured while finding teams at %v err=%v", key, err) - } else { - data := result.Data.([]string) - for _, domain := range data { - bodyPage.Props[fmt.Sprintf("%v://%v.%v", protocol, domain, utils.Cfg.ServiceSettings.Domain)] = "" - } - } - } + subjectPage := NewServerTemplatePage("find_teams_subject", c.GetSiteURL()) + bodyPage := NewServerTemplatePage("find_teams_body", c.GetSiteURL()) if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("An error occured while sending an email in emailTeams err=%v", err) @@ -470,22 +330,16 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) { ia = append(ia, invite["email"]) } - InviteMembers(team, user, ia) + InviteMembers(c, team, user, ia) w.Write([]byte(invites.ToJson())) } -func InviteMembers(team *model.Team, user *model.User, invites []string) { +func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) { for _, invite := range invites { if len(invite) > 0 { - teamUrl := "" - if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV { - teamUrl = "http://localhost:8065" - } else if utils.Cfg.ServiceSettings.UseSSL { - teamUrl = fmt.Sprintf("https://%v.%v", team.Domain, utils.Cfg.ServiceSettings.Domain) - } else { - teamUrl = fmt.Sprintf("http://%v.%v", team.Domain, utils.Cfg.ServiceSettings.Domain) - } + teamURL := "" + teamURL = c.GetTeamURLFromTeam(team) sender := user.GetDisplayName() @@ -496,11 +350,11 @@ func InviteMembers(team *model.Team, user *model.User, invites []string) { senderRole = "member" } - subjectPage := NewServerTemplatePage("invite_subject", teamUrl) + subjectPage := NewServerTemplatePage("invite_subject", teamURL) subjectPage.Props["SenderName"] = sender - subjectPage.Props["TeamName"] = team.Name - bodyPage := NewServerTemplatePage("invite_body", teamUrl) - bodyPage.Props["TeamName"] = team.Name + subjectPage.Props["TeamDisplayName"] = team.DisplayName + bodyPage := NewServerTemplatePage("invite_body", teamURL) + bodyPage.Props["TeamDisplayName"] = team.DisplayName bodyPage.Props["SenderName"] = sender bodyPage.Props["SenderStatus"] = senderRole @@ -509,12 +363,12 @@ func InviteMembers(team *model.Team, user *model.User, invites []string) { props := make(map[string]string) props["email"] = invite props["id"] = team.Id + props["display_name"] = team.DisplayName props["name"] = team.Name - props["domain"] = team.Domain props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) - bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", teamUrl, url.QueryEscape(data), url.QueryEscape(hash)) + bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV { l4g.Info("sending invitation to %v %v", invite, bodyPage.Props["Link"]) @@ -527,35 +381,35 @@ func InviteMembers(team *model.Team, user *model.User, invites []string) { } } -func updateTeamName(c *Context, w http.ResponseWriter, r *http.Request) { +func updateTeamDisplayName(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) new_name := props["new_name"] if len(new_name) == 0 { - c.SetInvalidParam("updateTeamName", "new_name") + c.SetInvalidParam("updateTeamDisplayName", "new_name") return } teamId := props["team_id"] if len(teamId) > 0 && len(teamId) != 26 { - c.SetInvalidParam("updateTeamName", "team_id") + c.SetInvalidParam("updateTeamDisplayName", "team_id") return } else if len(teamId) == 0 { teamId = c.Session.TeamId } - if !c.HasPermissionsToTeam(teamId, "updateTeamName") { + if !c.HasPermissionsToTeam(teamId, "updateTeamDisplayName") { return } if !strings.Contains(c.Session.Roles, model.ROLE_ADMIN) { - c.Err = model.NewAppError("updateTeamName", "You do not have the appropriate permissions", "userId="+c.Session.UserId) + c.Err = model.NewAppError("updateTeamDisplayName", "You do not have the appropriate permissions", "userId="+c.Session.UserId) c.Err.StatusCode = http.StatusForbidden return } - if result := <-Srv.Store.Team().UpdateName(new_name, c.Session.TeamId); result.Err != nil { + if result := <-Srv.Store.Team().UpdateDisplayName(new_name, c.Session.TeamId); result.Err != nil { c.Err = result.Err return } diff --git a/api/team_test.go b/api/team_test.go index f61babe8e..2723eff57 100644 --- a/api/team_test.go +++ b/api/team_test.go @@ -32,7 +32,7 @@ func TestCreateFromSignupTeam(t *testing.T) { data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} user := model.User{Email: props["email"], Nickname: "Corey Hulen", Password: "hello"} ts := model.TeamSignup{Team: team, User: user, Invites: []string{"corey@test.com"}, Data: data, Hash: hash} @@ -42,7 +42,7 @@ func TestCreateFromSignupTeam(t *testing.T) { t.Fatal(err) } - if rts.Data.(*model.TeamSignup).Team.Name != team.Name { + if rts.Data.(*model.TeamSignup).Team.DisplayName != team.DisplayName { t.Fatal("full name didn't match") } @@ -71,7 +71,7 @@ func TestCreateFromSignupTeam(t *testing.T) { func TestCreateTeam(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} rteam, err := Client.CreateTeam(&team) if err != nil { t.Fatal(err) @@ -81,14 +81,14 @@ func TestCreateTeam(t *testing.T) { user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, 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 { + if rteam.Data.(*model.Team).DisplayName != team.DisplayName { t.Fatal("full name didn't match") } @@ -111,7 +111,7 @@ func TestCreateTeam(t *testing.T) { func TestFindTeamByEmail(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -122,7 +122,7 @@ func TestFindTeamByEmail(t *testing.T) { t.Fatal(err) } else { domains := r1.Data.([]string) - if domains[0] != team.Domain { + if domains[0] != team.Name { t.Fatal(domains) } } @@ -139,14 +139,14 @@ XXXXXX investigate and fix failing test func TestFindTeamByDomain(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - if r1, err := Client.FindTeamByDomain(team.Domain, false); err != nil { + if r1, err := Client.FindTeamByDomain(team.Name, false); err != nil { t.Fatal(err) } else { val := r1.Data.(bool) @@ -155,7 +155,7 @@ func TestFindTeamByDomain(t *testing.T) { } } - if r1, err := Client.FindTeamByDomain(team.Domain, true); err != nil { + if r1, err := Client.FindTeamByDomain(team.Name, true); err != nil { t.Fatal(err) } else { val := r1.Data.(bool) @@ -179,7 +179,7 @@ func TestFindTeamByDomain(t *testing.T) { func TestFindTeamByEmailSend(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -203,14 +203,14 @@ func TestFindTeamByEmailSend(t *testing.T) { func TestInviteMembers(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") invite := make(map[string]string) invite["email"] = model.NewId() + "corey@test.com" @@ -229,10 +229,10 @@ func TestInviteMembers(t *testing.T) { } } -func TestUpdateTeamName(t *testing.T) { +func TestUpdateTeamDisplayName(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -243,40 +243,40 @@ func TestUpdateTeamName(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") data := make(map[string]string) data["new_name"] = "NewName" - if _, err := Client.UpdateTeamName(data); err == nil { + if _, err := Client.UpdateTeamDisplayName(data); err == nil { t.Fatal("Should have errored, not admin") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") data["new_name"] = "" - if _, err := Client.UpdateTeamName(data); err == nil { + if _, err := Client.UpdateTeamDisplayName(data); err == nil { t.Fatal("Should have errored, empty name") } data["new_name"] = "NewName" - if _, err := Client.UpdateTeamName(data); err != nil { + if _, err := Client.UpdateTeamDisplayName(data); err != nil { t.Fatal(err) } // No GET team web service, so hard to confirm here that team name updated data["team_id"] = "junk" - if _, err := Client.UpdateTeamName(data); err == nil { + if _, err := Client.UpdateTeamDisplayName(data); err == nil { t.Fatal("Should have errored, junk team id") } data["team_id"] = "12345678901234567890123456" - if _, err := Client.UpdateTeamName(data); err == nil { + if _, err := Client.UpdateTeamDisplayName(data); err == nil { t.Fatal("Should have errored, bad team id") } data["team_id"] = team.Id data["new_name"] = "NewNameAgain" - if _, err := Client.UpdateTeamName(data); err != nil { + if _, err := Client.UpdateTeamDisplayName(data); err != nil { t.Fatal(err) } // No GET team web service, so hard to confirm here that team name updated @@ -285,17 +285,17 @@ func TestUpdateTeamName(t *testing.T) { func TestFuzzyTeamCreate(t *testing.T) { for i := 0; i < len(utils.FUZZY_STRINGS_NAMES) || i < len(utils.FUZZY_STRINGS_EMAILS); i++ { - testName := "Name" + testDisplayName := "Name" testEmail := "test@nowhere.com" if i < len(utils.FUZZY_STRINGS_NAMES) { - testName = utils.FUZZY_STRINGS_NAMES[i] + testDisplayName = utils.FUZZY_STRINGS_NAMES[i] } if i < len(utils.FUZZY_STRINGS_EMAILS) { testEmail = utils.FUZZY_STRINGS_EMAILS[i] } - team := model.Team{Name: testName, Domain: "z-z-" + model.NewId() + "a", Email: testEmail, Type: model.TEAM_OPEN} + team := model.Team{DisplayName: testDisplayName, Name: "z-z-" + model.NewId() + "a", Email: testEmail, Type: model.TEAM_OPEN} _, err := Client.CreateTeam(&team) if err != nil { @@ -307,22 +307,22 @@ 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} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} ruser, _ := Client.CreateUser(&user, "") store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)) - Client.LoginByEmail(team.Domain, user.Email, user.Password) + Client.LoginByEmail(team.Name, 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 { + if result.Data.(*model.Team).DisplayName != team.DisplayName { t.Fatal("team names did not match") } - if result.Data.(*model.Team).Domain != team.Domain { + if result.Data.(*model.Team).Name != team.Name { t.Fatal("team domains did not match") } if result.Data.(*model.Team).Type != team.Type { @@ -334,7 +334,7 @@ func TestGetMyTeam(t *testing.T) { 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 := &model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -345,14 +345,14 @@ func TestUpdateValetFeature(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(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 := &model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user3.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") data := make(map[string]string) data["allow_valet"] = "true" @@ -360,7 +360,7 @@ func TestUpdateValetFeature(t *testing.T) { t.Fatal("Should have errored, not admin") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") data["allow_valet"] = "" if _, err := Client.UpdateValetFeature(data); err == nil { @@ -398,7 +398,7 @@ func TestUpdateValetFeature(t *testing.T) { t.Fatal("Should have errored - allow valet property not updated") } - Client.LoginByEmail(team2.Domain, user3.Email, "pwd") + Client.LoginByEmail(team2.Name, user3.Email, "pwd") data["team_id"] = team.Id data["allow_valet"] = "true" diff --git a/api/templates/email_change_body.html b/api/templates/email_change_body.html index dffe589cd..f8f3845e7 100644 --- a/api/templates/email_change_body.html +++ b/api/templates/email_change_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -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 updated your email</h2> - <p>You updated your email for {{.Props.TeamName}} on {{ .TeamUrl }}<br> If this change wasn't initiated by you, please reply to this email and let us know.</p> + <p>You updated your email for {{.Props.TeamDisplayName}} on {{ .TeamURL }}<br> If this change wasn't initiated by you, please reply to this email and let us know.</p> </td> </tr> <tr> @@ -34,7 +34,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/email_change_subject.html b/api/templates/email_change_subject.html index 612dfcbe7..5690b148a 100644 --- a/api/templates/email_change_subject.html +++ b/api/templates/email_change_subject.html @@ -1 +1 @@ -{{define "email_change_subject"}}You updated your email for {{.Props.TeamName}} on {{ .Props.Domain }}{{end}} +{{define "email_change_subject"}}You updated your email for {{.Props.TeamDisplayName}} on {{ .Props.Domain }}{{end}} diff --git a/api/templates/find_teams_body.html b/api/templates/find_teams_body.html index d8b582b8a..6eaaf56e0 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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -42,7 +42,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/invite_body.html b/api/templates/invite_body.html index 8be2ac0df..46189fae5 100644 --- a/api/templates/invite_body.html +++ b/api/templates/invite_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -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 {{.Props.SenderStatus}} <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamName}}</strong>.</p> + <p>{{.Props.TeamDisplayName}} started using {{.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> @@ -37,7 +37,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/invite_subject.html b/api/templates/invite_subject.html index 4be15e343..6a1e57dcc 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.TeamName }} Team on {{.SiteName}}{{end}} +{{define "invite_subject"}}{{ .Props.SenderName }} invited you to join {{ .Props.TeamDisplayName }} Team on {{.SiteName}}{{end}} diff --git a/api/templates/password_change_body.html b/api/templates/password_change_body.html index f6499d46d..515c0a7d9 100644 --- a/api/templates/password_change_body.html +++ b/api/templates/password_change_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -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 updated your password</h2> - <p>You updated your password for {{.Props.TeamName}} on {{ .TeamUrl }} by {{.Props.Method}}.<br> If this change wasn't initiated by you, please reply to this email and let us know.</p> + <p>You updated your password for {{.Props.TeamDisplayName}} on {{ .TeamURL }} by {{.Props.Method}}.<br> If this change wasn't initiated by you, please reply to this email and let us know.</p> </td> </tr> <tr> @@ -34,7 +34,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/password_change_subject.html b/api/templates/password_change_subject.html index 57422c692..55daefdb1 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.TeamName}} on {{ .SiteName }}{{end}} +{{define "password_change_subject"}}You updated your password for {{.Props.TeamDisplayName}} on {{ .SiteName }}{{end}} diff --git a/api/templates/post_body.html b/api/templates/post_body.html index 069cdf1fb..41a29d020 100644 --- a/api/templates/post_body.html +++ b/api/templates/post_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -37,7 +37,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/post_subject.html b/api/templates/post_subject.html index 32df31018..8ebc9550b 100644 --- a/api/templates/post_subject.html +++ b/api/templates/post_subject.html @@ -1 +1 @@ -{{define "post_subject"}}[{{.Props.TeamName}} {{.SiteName}}] {{.Props.SubjectText}} for {{.Props.Month}} {{.Props.Day}}, {{.Props.Year}}{{end}}
\ No newline at end of file +{{define "post_subject"}}[{{.Props.TeamDisplayName}} {{.SiteName}}] {{.Props.SubjectText}} for {{.Props.Month}} {{.Props.Day}}, {{.Props.Year}}{{end}} diff --git a/api/templates/reset_body.html b/api/templates/reset_body.html index 4b5976663..af9f6b4e8 100644 --- a/api/templates/reset_body.html +++ b/api/templates/reset_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -37,7 +37,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/signup_team_body.html b/api/templates/signup_team_body.html index 6f8bbd92d..5a5ae4d47 100644 --- a/api/templates/signup_team_body.html +++ b/api/templates/signup_team_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -40,7 +40,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/verify_body.html b/api/templates/verify_body.html index 56d85572b..67ded9c20 100644 --- a/api/templates/verify_body.html +++ b/api/templates/verify_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -37,7 +37,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/templates/verify_subject.html b/api/templates/verify_subject.html index de0ef1d7a..a66150735 100644 --- a/api/templates/verify_subject.html +++ b/api/templates/verify_subject.html @@ -1 +1 @@ -{{define "verify_subject"}}[{{ .Props.TeamName }} {{ .SiteName }}] Email Verification{{end}}
\ No newline at end of file +{{define "verify_subject"}}[{{ .Props.TeamDisplayName }} {{ .SiteName }}] Email Verification{{end}} diff --git a/api/templates/welcome_body.html b/api/templates/welcome_body.html index fbc2e5551..7107bc2e0 100644 --- a/api/templates/welcome_body.html +++ b/api/templates/welcome_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 30px 10px; text-align:left;"> - <img src="{{.TeamUrl}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> + <img src="{{.TeamURL}}/static/images/{{.SiteName}}-logodark.png" width="130px" style="opacity: 0.5" alt=""> </td> </tr> <tr> @@ -17,8 +17,8 @@ <table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto"> <tr> <td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;"> - <h2 style="font-weight: normal; margin-top: 10px;">You joined the {{.Props.TeamName}} team at {{.SiteName}}!</h2> - <p>Please let me know if you have any questions.<br>Enjoy your stay at <a href="{{.TeamUrl}}">{{.SiteName}}</a>.</p> + <h2 style="font-weight: normal; margin-top: 10px;">You joined the {{.Props.TeamDisplayName}} team at {{.SiteName}}!</h2> + <p>Please let me know if you have any questions.<br>Enjoy your stay at <a href="{{.TeamURL}}">{{.SiteName}}</a>.</p> </td> </tr> <tr> @@ -34,7 +34,7 @@ <tr> <td style="text-align: center;color: #AAA; font-size: 13px; padding-bottom: 10px;"> <p style="margin: 25px 0;"> - <img width="65" src="{{.TeamUrl}}/static/images/circles.png" alt=""> + <img width="65" src="{{.TeamURL}}/static/images/circles.png" alt=""> </p> <p style="padding: 0 50px;"> (c) 2015 SpinPunch, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br> diff --git a/api/user.go b/api/user.go index f6422f844..18c5e863a 100644 --- a/api/user.go +++ b/api/user.go @@ -181,14 +181,13 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User { l4g.Error("Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v", ruser.Id, ruser.TeamId, err) } - //fireAndForgetWelcomeEmail(ruser.FirstName, ruser.Email, team.Name, c.TeamUrl+"/channels/town-square") - + //fireAndForgetWelcomeEmail(ruser.FirstName, 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 set email verified err=%v", cresult.Err) } } else { - FireAndForgetVerifyEmail(result.Data.(*model.User).Id, ruser.FirstName, ruser.Email, team.Name, c.TeamUrl) + FireAndForgetVerifyEmail(result.Data.(*model.User).Id, ruser.FirstName, ruser.Email, team.DisplayName, c.GetTeamURLFromTeam(team)) } ruser.Sanitize(map[string]bool{}) @@ -202,13 +201,13 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User { } } -func fireAndForgetWelcomeEmail(name, email, teamName, link string) { +func fireAndForgetWelcomeEmail(name, email, teamDisplayName, link string) { go func() { subjectPage := NewServerTemplatePage("welcome_subject", link) bodyPage := NewServerTemplatePage("welcome_body", link) bodyPage.Props["Nickname"] = name - bodyPage.Props["TeamName"] = teamName + bodyPage.Props["TeamDisplayName"] = teamDisplayName bodyPage.Props["FeedbackName"] = utils.Cfg.EmailSettings.FeedbackName if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { @@ -218,16 +217,16 @@ func fireAndForgetWelcomeEmail(name, email, teamName, link string) { }() } -func FireAndForgetVerifyEmail(userId, name, email, teamName, teamUrl string) { +func FireAndForgetVerifyEmail(userId, name, email, teamDisplayName, teamURL string) { go func() { - link := fmt.Sprintf("%s/verify?uid=%s&hid=%s", teamUrl, userId, model.HashPassword(userId)) + link := fmt.Sprintf("%s/verify_email?uid=%s&hid=%s", teamURL, userId, model.HashPassword(userId)) - subjectPage := NewServerTemplatePage("verify_subject", teamUrl) - subjectPage.Props["TeamName"] = teamName - bodyPage := NewServerTemplatePage("verify_body", teamUrl) + subjectPage := NewServerTemplatePage("verify_subject", teamURL) + subjectPage.Props["TeamDisplayName"] = teamDisplayName + bodyPage := NewServerTemplatePage("verify_body", teamURL) bodyPage.Props["Nickname"] = name - bodyPage.Props["TeamName"] = teamName + bodyPage.Props["TeamDisplayName"] = teamDisplayName bodyPage.Props["VerifyUrl"] = link if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { @@ -251,10 +250,10 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) { } var team *model.Team - if result.Data == nil && len(props["email"]) != 0 && len(props["domain"]) != 0 { - extraInfo = props["email"] + " in " + props["domain"] + if result.Data == nil && len(props["email"]) != 0 && len(props["name"]) != 0 { + extraInfo = props["email"] + " in " + props["name"] - if nr := <-Srv.Store.Team().GetByDomain(props["domain"]); nr.Err != nil { + if nr := <-Srv.Store.Team().GetByName(props["name"]); nr.Err != nil { c.Err = nr.Err return } else { @@ -517,7 +516,6 @@ func getProfiles(c *Context, w http.ResponseWriter, r *http.Request) { } w.Header().Set(model.HEADER_ETAG_SERVER, etag) - w.Header().Set("Cache-Control", "max-age=120, public") // 2 mins w.Write([]byte(model.UserMapToJson(profiles))) return } @@ -758,7 +756,8 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) { if tresult := <-Srv.Store.Team().Get(rusers[1].TeamId); tresult.Err != nil { l4g.Error(tresult.Err.Message) } else { - fireAndForgetEmailChangeEmail(rusers[1].Email, tresult.Data.(*model.Team).Name, c.TeamUrl) + team := tresult.Data.(*model.Team) + fireAndForgetEmailChangeEmail(rusers[1].Email, team.DisplayName, c.GetTeamURLFromTeam(team)) } } @@ -829,7 +828,8 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) { if tresult := <-tchan; tresult.Err != nil { l4g.Error(tresult.Err.Message) } else { - fireAndForgetPasswordChangeEmail(user.Email, tresult.Data.(*model.Team).Name, c.TeamUrl, "using the settings menu") + team := tresult.Data.(*model.Team) + fireAndForgetPasswordChangeEmail(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), "using the settings menu") } data := make(map[string]string) @@ -988,14 +988,14 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { return } - domain := props["domain"] - if len(domain) == 0 { - c.SetInvalidParam("sendPasswordReset", "domain") + name := props["name"] + if len(name) == 0 { + c.SetInvalidParam("sendPasswordReset", "name") return } var team *model.Team - if result := <-Srv.Store.Team().GetByDomain(domain); result.Err != nil { + if result := <-Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { @@ -1017,10 +1017,10 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.ResetSalt)) - link := fmt.Sprintf("%s/reset_password?d=%s&h=%s", c.TeamUrl, url.QueryEscape(data), url.QueryEscape(hash)) + link := fmt.Sprintf("%s/reset_password?d=%s&h=%s", c.GetTeamURLFromTeam(team), url.QueryEscape(data), url.QueryEscape(hash)) - subjectPage := NewServerTemplatePage("reset_subject", c.TeamUrl) - bodyPage := NewServerTemplatePage("reset_body", c.TeamUrl) + subjectPage := NewServerTemplatePage("reset_subject", c.GetTeamURLFromTeam(team)) + bodyPage := NewServerTemplatePage("reset_body", c.GetTeamURLFromTeam(team)) bodyPage.Props["ResetUrl"] = link if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { @@ -1062,16 +1062,16 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { return } - domain := props["domain"] - if len(domain) == 0 { - c.SetInvalidParam("resetPassword", "domain") + name := props["name"] + if len(name) == 0 { + c.SetInvalidParam("resetPassword", "name") return } c.LogAuditWithUserId(userId, "attempt") var team *model.Team - if result := <-Srv.Store.Team().GetByDomain(domain); result.Err != nil { + if result := <-Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { @@ -1110,19 +1110,19 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { c.LogAuditWithUserId(userId, "success") } - fireAndForgetPasswordChangeEmail(user.Email, team.Name, c.TeamUrl, "using a reset password link") + fireAndForgetPasswordChangeEmail(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), "using a reset password link") props["new_password"] = "" w.Write([]byte(model.MapToJson(props))) } -func fireAndForgetPasswordChangeEmail(email, teamName, teamUrl, method string) { +func fireAndForgetPasswordChangeEmail(email, teamDisplayName, teamURL, method string) { go func() { - subjectPage := NewServerTemplatePage("password_change_subject", teamUrl) - subjectPage.Props["TeamName"] = teamName - bodyPage := NewServerTemplatePage("password_change_body", teamUrl) - bodyPage.Props["TeamName"] = teamName + subjectPage := NewServerTemplatePage("password_change_subject", teamURL) + subjectPage.Props["TeamDisplayName"] = teamDisplayName + bodyPage := NewServerTemplatePage("password_change_body", teamURL) + bodyPage.Props["TeamDisplayName"] = teamDisplayName bodyPage.Props["Method"] = method if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { @@ -1132,13 +1132,13 @@ func fireAndForgetPasswordChangeEmail(email, teamName, teamUrl, method string) { }() } -func fireAndForgetEmailChangeEmail(email, teamName, teamUrl string) { +func fireAndForgetEmailChangeEmail(email, teamDisplayName, teamURL string) { go func() { - subjectPage := NewServerTemplatePage("email_change_subject", teamUrl) - subjectPage.Props["TeamName"] = teamName - bodyPage := NewServerTemplatePage("email_change_body", teamUrl) - bodyPage.Props["TeamName"] = teamName + subjectPage := NewServerTemplatePage("email_change_subject", teamURL) + subjectPage.Props["TeamDisplayName"] = teamDisplayName + bodyPage := NewServerTemplatePage("email_change_body", teamURL) + bodyPage.Props["TeamDisplayName"] = teamDisplayName if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send update password email successfully err=%v", err) diff --git a/api/user_test.go b/api/user_test.go index edbef7c9a..fbd13492b 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -25,7 +25,7 @@ import ( func TestCreateUser(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "hello"} @@ -75,7 +75,7 @@ func TestCreateUser(t *testing.T) { func TestCreateUserAllowedDomains(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_INVITE, AllowedDomains: "spinpunch.com, @nowh.com,@hello.com"} + team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_INVITE, AllowedDomains: "spinpunch.com, @nowh.com,@hello.com"} rteam, _ := Client.CreateTeam(&team) user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "hello"} @@ -95,7 +95,7 @@ func TestCreateUserAllowedDomains(t *testing.T) { func TestLogin(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -110,7 +110,7 @@ func TestLogin(t *testing.T) { } } - if result, err := Client.LoginByEmail(team.Domain, user.Email, user.Password); err != nil { + if result, err := Client.LoginByEmail(team.Name, user.Email, user.Password); err != nil { t.Fatal(err) } else { if result.Data.(*model.User).Email != user.Email { @@ -118,11 +118,11 @@ func TestLogin(t *testing.T) { } } - if _, err := Client.LoginByEmail(team.Domain, user.Email, user.Password+"invalid"); err == nil { + if _, err := Client.LoginByEmail(team.Name, user.Email, user.Password+"invalid"); err == nil { t.Fatal("Invalid Password") } - if _, err := Client.LoginByEmail(team.Domain, "", user.Password); err == nil { + if _, err := Client.LoginByEmail(team.Name, "", user.Password); err == nil { t.Fatal("should have failed") } @@ -135,7 +135,7 @@ func TestLogin(t *testing.T) { Client.AuthToken = "" - team2 := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_INVITE} + team2 := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_INVITE} rteam2 := Client.Must(Client.CreateTeam(&team2)) user2 := model.User{TeamId: rteam2.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -147,14 +147,14 @@ func TestLogin(t *testing.T) { props := make(map[string]string) props["email"] = user2.Email props["id"] = rteam2.Data.(*model.Team).Id - props["name"] = rteam2.Data.(*model.Team).Name + props["display_name"] = rteam2.Data.(*model.Team).DisplayName props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) ruser2, _ := Client.CreateUserFromSignup(&user2, data, hash) - if _, err := Client.LoginByEmail(team2.Domain, ruser2.Data.(*model.User).Email, user2.Password); err != nil { + if _, err := Client.LoginByEmail(team2.Name, ruser2.Data.(*model.User).Email, user2.Password); err != nil { t.Fatal("From verfied hash") } @@ -164,7 +164,7 @@ func TestLogin(t *testing.T) { func TestSessions(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -172,8 +172,8 @@ func TestSessions(t *testing.T) { store.Must(Srv.Store.User().VerifyEmail(ruser.Id)) deviceId := model.NewId() - Client.LoginByEmailWithDevice(team.Domain, user.Email, user.Password, deviceId) - Client.LoginByEmail(team.Domain, user.Email, user.Password) + Client.LoginByEmailWithDevice(team.Name, user.Email, user.Password, deviceId) + Client.LoginByEmail(team.Name, user.Email, user.Password) r1, err := Client.GetSessions(ruser.Id) if err != nil { @@ -221,7 +221,7 @@ func TestSessions(t *testing.T) { func TestGetUser(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -232,7 +232,7 @@ func TestGetUser(t *testing.T) { ruser2, _ := Client.CreateUser(&user2, "") store.Must(Srv.Store.User().VerifyEmail(ruser2.Data.(*model.User).Id)) - Client.LoginByEmail(team.Domain, user.Email, user.Password) + Client.LoginByEmail(team.Name, user.Email, user.Password) rId := ruser.Data.(*model.User).Id if result, err := Client.GetUser(rId, ""); err != nil { @@ -292,7 +292,7 @@ func TestGetUser(t *testing.T) { func TestGetAudits(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -301,7 +301,7 @@ func TestGetAudits(t *testing.T) { time.Sleep(100 * time.Millisecond) - Client.LoginByEmail(team.Domain, user.Email, user.Password) + Client.LoginByEmail(team.Name, user.Email, user.Password) time.Sleep(100 * time.Millisecond) @@ -345,14 +345,14 @@ func TestUserCreateImage(t *testing.T) { t.Fatal("Failed to create correct color") } - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") Client.DoGet("/users/"+user.Id+"/image", "", "") @@ -361,7 +361,7 @@ func TestUserCreateImage(t *testing.T) { func TestUserUploadProfileImage(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -377,7 +377,7 @@ func TestUserUploadProfileImage(t *testing.T) { t.Fatal("Should have errored") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") if _, upErr := Client.UploadFile("/users/newimage", body.Bytes(), writer.FormDataContentType()); upErr == nil { t.Fatal("Should have errored") @@ -458,7 +458,7 @@ func TestUserUploadProfileImage(t *testing.T) { func TestUserUpdate(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) time1 := model.GetMillis() @@ -471,7 +471,7 @@ func TestUserUpdate(t *testing.T) { t.Fatal("Should have errored") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") time.Sleep(100 * time.Millisecond) @@ -523,7 +523,7 @@ func TestUserUpdate(t *testing.T) { user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") user.Nickname = "Tim Timmy" @@ -535,7 +535,7 @@ func TestUserUpdate(t *testing.T) { func TestUserUpdatePassword(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -546,7 +546,7 @@ func TestUserUpdatePassword(t *testing.T) { t.Fatal("Should have errored") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") if _, err := Client.UpdateUserPassword("123", "pwd", "newpwd"); err == nil { t.Fatal("Should have errored") @@ -577,14 +577,14 @@ func TestUserUpdatePassword(t *testing.T) { t.Fatal("LastPasswordUpdate should have changed") } - if _, err := Client.LoginByEmail(team.Domain, user.Email, "newpwd"); err != nil { + if _, err := Client.LoginByEmail(team.Name, user.Email, "newpwd"); err != nil { t.Fatal(err) } user2 := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") if _, err := Client.UpdateUserPassword(user.Id, "pwd", "newpwd"); err == nil { t.Fatal("Should have errored") @@ -594,7 +594,7 @@ func TestUserUpdatePassword(t *testing.T) { func TestUserUpdateRoles(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -613,20 +613,20 @@ func TestUserUpdateRoles(t *testing.T) { t.Fatal("Should have errored, not logged in") } - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") if _, err := Client.UpdateUserRoles(data); err == nil { t.Fatal("Should have errored, not admin") } - team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name", Name: "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: "test@nowhere.com", Nickname: "Corey Hulen", Password: "pwd"} user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user3.Id)) - Client.LoginByEmail(team2.Domain, user3.Email, "pwd") + Client.LoginByEmail(team2.Name, user3.Email, "pwd") data["user_id"] = user2.Id @@ -634,7 +634,7 @@ func TestUserUpdateRoles(t *testing.T) { t.Fatal("Should have errored, wrong team") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") data["user_id"] = "junk" data["new_roles"] = "admin" @@ -663,7 +663,7 @@ func TestUserUpdateRoles(t *testing.T) { func TestUserUpdateActive(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} @@ -678,26 +678,26 @@ func TestUserUpdateActive(t *testing.T) { t.Fatal("Should have errored, not logged in") } - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") if _, err := Client.UpdateActive(user.Id, false); err == nil { t.Fatal("Should have errored, not admin") } - team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name", Name: "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: "test@nowhere.com", Nickname: "Corey Hulen", Password: "pwd"} user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user3.Id)) - Client.LoginByEmail(team2.Domain, user3.Email, "pwd") + Client.LoginByEmail(team2.Name, user3.Email, "pwd") if _, err := Client.UpdateActive(user.Id, false); err == nil { t.Fatal("Should have errored, wrong team") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") if _, err := Client.UpdateActive("junk", false); err == nil { t.Fatal("Should have errored, bad id") @@ -727,7 +727,7 @@ func TestUserUpdateActive(t *testing.T) { func TestSendPasswordReset(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -736,7 +736,7 @@ func TestSendPasswordReset(t *testing.T) { data := make(map[string]string) data["email"] = user.Email - data["domain"] = team.Domain + data["name"] = team.Name if _, err := Client.SendPasswordReset(data); err != nil { t.Fatal(err) @@ -753,21 +753,21 @@ func TestSendPasswordReset(t *testing.T) { } data["email"] = user.Email - data["domain"] = "" + data["name"] = "" if _, err := Client.SendPasswordReset(data); err == nil { - t.Fatal("Should have errored - no domain") + t.Fatal("Should have errored - no name") } - data["domain"] = "junk" + data["name"] = "junk" if _, err := Client.SendPasswordReset(data); err == nil { - t.Fatal("Should have errored - bad domain") + t.Fatal("Should have errored - bad name") } } func TestResetPassword(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} @@ -781,7 +781,7 @@ func TestResetPassword(t *testing.T) { props["time"] = fmt.Sprintf("%v", model.GetMillis()) data["data"] = model.MapToJson(props) data["hash"] = model.HashPassword(fmt.Sprintf("%v:%v", data["data"], utils.Cfg.ServiceSettings.ResetSalt)) - data["domain"] = team.Domain + data["name"] = team.Name if _, err := Client.ResetPassword(data); err != nil { t.Fatal(err) @@ -839,10 +839,10 @@ func TestResetPassword(t *testing.T) { t.Fatal("Should have errored - bad domain") } - team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test2@nowhere.com", Type: model.TEAM_OPEN} + team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test2@nowhere.com", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) - data["domain"] = team2.Domain + data["domain"] = team2.Name if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - domain team doesn't match user team") } @@ -851,7 +851,7 @@ func TestResetPassword(t *testing.T) { func TestUserUpdateNotify(t *testing.T) { Setup() - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "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: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd", Roles: ""} @@ -868,7 +868,7 @@ func TestUserUpdateNotify(t *testing.T) { t.Fatal("Should have errored - not logged in") } - Client.LoginByEmail(team.Domain, user.Email, "pwd") + Client.LoginByEmail(team.Name, user.Email, "pwd") if result, err := Client.UpdateUserNotify(data); err != nil { t.Fatal(err) @@ -919,7 +919,7 @@ func TestUserUpdateNotify(t *testing.T) { func TestFuzzyUserCreate(t *testing.T) { - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} rteam, _ := Client.CreateTeam(&team) for i := 0; i < len(utils.FUZZY_STRINGS_NAMES) || i < len(utils.FUZZY_STRINGS_EMAILS); i++ { @@ -945,14 +945,14 @@ func TestFuzzyUserCreate(t *testing.T) { func TestStatuses(t *testing.T) { Setup() - team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := model.Team{DisplayName: "Name", Name: "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", Nickname: "Corey Hulen", Password: "pwd"} ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(ruser.Id)) - Client.LoginByEmail(team.Domain, user.Email, user.Password) + Client.LoginByEmail(team.Name, user.Email, user.Password) r1, err := Client.GetStatuses() if err != nil { diff --git a/api/web_socket_test.go b/api/web_socket_test.go index 07fdfea36..161274ff7 100644 --- a/api/web_socket_test.go +++ b/api/web_socket_test.go @@ -17,13 +17,13 @@ func TestSocket(t *testing.T) { Setup() url := "ws://localhost:" + utils.Cfg.ServiceSettings.Port + "/api/v1/websocket" - team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user1.Id)) - Client.LoginByEmail(team.Domain, user1.Email, "pwd") + Client.LoginByEmail(team.Name, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test Web Scoket 1", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) @@ -42,7 +42,7 @@ func TestSocket(t *testing.T) { user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user2.Id)) - Client.LoginByEmail(team.Domain, user2.Email, "pwd") + Client.LoginByEmail(team.Name, user2.Email, "pwd") header2 := http.Header{} header2.Set(model.HEADER_AUTH, "BEARER "+Client.AuthToken) diff --git a/config/config.json b/config/config.json index 27ca57e86..e6025ef51 100644 --- a/config/config.json +++ b/config/config.json @@ -9,7 +9,6 @@ }, "ServiceSettings": { "SiteName": "Mattermost", - "Domain": "xxxxxxmustbefilledin.com", "Mode" : "dev", "AllowTesting" : false, "UseSSL": false, @@ -35,11 +34,7 @@ "S3AccessKeyId": "", "S3SecretAccessKey": "", "S3Bucket": "", - "S3Region": "", - "Route53AccessKeyId": "", - "Route53SecretAccessKey": "", - "Route53ZoneId": "", - "Route53Region": "" + "S3Region": "" }, "ImageSettings": { "ThumbnailWidth": 200, diff --git a/config/config_docker.json b/config/config_docker.json index 185e9f215..9be837072 100644 --- a/config/config_docker.json +++ b/config/config_docker.json @@ -9,7 +9,6 @@ }, "ServiceSettings": { "SiteName": "Mattermost", - "Domain": "", "Mode" : "dev", "AllowTesting" : false, "UseSSL": false, @@ -35,11 +34,7 @@ "S3AccessKeyId": "", "S3SecretAccessKey": "", "S3Bucket": "", - "S3Region": "", - "Route53AccessKeyId": "", - "Route53SecretAccessKey": "", - "Route53ZoneId": "", - "Route53Region": "" + "S3Region": "" }, "ImageSettings": { "ThumbnailWidth": 200, diff --git a/manualtesting/manual_testing.go b/manualtesting/manual_testing.go index 6c4958a7b..f7408b814 100644 --- a/manualtesting/manual_testing.go +++ b/manualtesting/manual_testing.go @@ -57,17 +57,17 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) { // Check for username parameter and create a user if present username, ok1 := params["username"] - teamname, ok2 := params["teamname"] + teamDisplayName, ok2 := params["teamname"] var teamID string var userID string if ok1 && ok2 { l4g.Info("Creating user and team") // Create team for testing team := &model.Team{ - Name: teamname[0], - Domain: utils.RandomName(utils.Range{20, 20}, utils.LOWERCASE), - Email: utils.RandomEmail(utils.Range{20, 20}, utils.LOWERCASE), - Type: model.TEAM_OPEN, + DisplayName: teamDisplayName[0], + Name: utils.RandomName(utils.Range{20, 20}, utils.LOWERCASE), + Email: utils.RandomEmail(utils.Range{20, 20}, utils.LOWERCASE), + Type: model.TEAM_OPEN, } if result := <-api.Srv.Store.Team().Save(team); result.Err != nil { diff --git a/model/client.go b/model/client.go index ab01e7d62..c7e17a6db 100644 --- a/model/client.go +++ b/model/client.go @@ -98,10 +98,10 @@ func (c *Client) Must(result *Result, err *AppError) *Result { return result } -func (c *Client) SignupTeam(email string, name string) (*Result, *AppError) { +func (c *Client) SignupTeam(email string, displayName string) (*Result, *AppError) { m := make(map[string]string) m["email"] = email - m["name"] = name + m["display_name"] = displayName if r, err := c.DoPost("/teams/signup", MapToJson(m)); err != nil { return nil, err } else { @@ -128,11 +128,11 @@ func (c *Client) CreateTeam(team *Team) (*Result, *AppError) { } } -func (c *Client) FindTeamByDomain(domain string, allServers bool) (*Result, *AppError) { +func (c *Client) FindTeamByName(name string, allServers bool) (*Result, *AppError) { m := make(map[string]string) - m["domain"] = domain + m["name"] = name m["all"] = fmt.Sprintf("%v", allServers) - if r, err := c.DoPost("/teams/find_team_by_domain", MapToJson(m)); err != nil { + if r, err := c.DoPost("/teams/find_team_by_name", MapToJson(m)); err != nil { return nil, err } else { val := false @@ -177,7 +177,7 @@ func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { } } -func (c *Client) UpdateTeamName(data map[string]string) (*Result, *AppError) { +func (c *Client) UpdateTeamDisplayName(data map[string]string) (*Result, *AppError) { if r, err := c.DoPost("/teams/update_name", MapToJson(data)); err != nil { return nil, err } else { @@ -247,17 +247,17 @@ func (c *Client) LoginById(id string, password string) (*Result, *AppError) { return c.login(m) } -func (c *Client) LoginByEmail(domain string, email string, password string) (*Result, *AppError) { +func (c *Client) LoginByEmail(name string, email string, password string) (*Result, *AppError) { m := make(map[string]string) - m["domain"] = domain + m["name"] = name m["email"] = email m["password"] = password return c.login(m) } -func (c *Client) LoginByEmailWithDevice(domain string, email string, password string, deviceId string) (*Result, *AppError) { +func (c *Client) LoginByEmailWithDevice(name string, email string, password string, deviceId string) (*Result, *AppError) { m := make(map[string]string) - m["domain"] = domain + m["name"] = name m["email"] = email m["password"] = password m["device_id"] = deviceId diff --git a/model/team.go b/model/team.go index 5c66f3b1f..e7005625b 100644 --- a/model/team.go +++ b/model/team.go @@ -18,8 +18,8 @@ type Team struct { CreateAt int64 `json:"create_at"` UpdateAt int64 `json:"update_at"` DeleteAt int64 `json:"delete_at"` + DisplayName string `json:"display_name"` Name string `json:"name"` - Domain string `json:"domain"` Email string `json:"email"` Type string `json:"type"` CompanyName string `json:"company_name"` @@ -97,20 +97,20 @@ func (o *Team) IsValid() *AppError { return NewAppError("Team.IsValid", "Invalid email", "id="+o.Id) } - if len(o.Name) > 64 { + if len(o.DisplayName) > 64 { return NewAppError("Team.IsValid", "Invalid name", "id="+o.Id) } - if len(o.Domain) > 64 { - return NewAppError("Team.IsValid", "Invalid domain", "id="+o.Id) + if len(o.Name) > 64 { + return NewAppError("Team.IsValid", "Invalid URL Identifier", "id="+o.Id) } - if IsReservedDomain(o.Domain) { + if IsReservedTeamName(o.Name) { return NewAppError("Team.IsValid", "This URL is unavailable. Please try another.", "id="+o.Id) } - if !IsValidDomain(o.Domain) { - return NewAppError("Team.IsValid", "Domain must be 4 or more lowercase alphanumeric characters", "id="+o.Id) + if !IsValidTeamName(o.Name) { + return NewAppError("Team.IsValid", "Name must be 4 or more lowercase alphanumeric characters", "id="+o.Id) } if !(o.Type == TEAM_OPEN || o.Type == TEAM_INVITE) { diff --git a/model/team_signup_test.go b/model/team_signup_test.go index f3f74470b..eb2fbc69f 100644 --- a/model/team_signup_test.go +++ b/model/team_signup_test.go @@ -9,7 +9,7 @@ import ( ) func TestTeamSignupJson(t *testing.T) { - team := Team{Id: NewId(), Name: NewId()} + team := Team{Id: NewId(), DisplayName: NewId()} o := TeamSignup{Team: team, Data: "data"} json := o.ToJson() ro := TeamSignupFromJson(strings.NewReader(json)) diff --git a/model/team_test.go b/model/team_test.go index 6261ed6bf..071b1a2e9 100644 --- a/model/team_test.go +++ b/model/team_test.go @@ -9,7 +9,7 @@ import ( ) func TestTeamJson(t *testing.T) { - o := Team{Id: NewId(), Name: NewId()} + o := Team{Id: NewId(), DisplayName: NewId()} json := o.ToJson() ro := TeamFromJson(strings.NewReader(json)) @@ -46,18 +46,18 @@ func TestTeamIsValid(t *testing.T) { } o.Email = "corey@hulen.com" - o.Name = strings.Repeat("01234567890", 20) + o.DisplayName = strings.Repeat("01234567890", 20) if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.Name = "1234" - o.Domain = "ZZZZZZZ" + o.DisplayName = "1234" + o.Name = "ZZZZZZZ" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.Domain = "zzzzz" + o.Name = "zzzzz" o.Type = TEAM_OPEN if err := o.IsValid(); err != nil { t.Fatal(err) @@ -65,12 +65,12 @@ func TestTeamIsValid(t *testing.T) { } func TestTeamPreSave(t *testing.T) { - o := Team{Name: "test"} + o := Team{DisplayName: "test"} o.PreSave() o.Etag() } func TestTeamPreUpdate(t *testing.T) { - o := Team{Name: "test"} + o := Team{DisplayName: "test"} o.PreUpdate() } diff --git a/model/utils.go b/model/utils.go index 465901a09..38592b984 100644 --- a/model/utils.go +++ b/model/utils.go @@ -148,7 +148,7 @@ func IsValidEmail(email string) bool { return false } -var reservedDomains = []string{ +var reservedName = []string{ "www", "web", "admin", @@ -168,10 +168,10 @@ var reservedDomains = []string{ "api", } -func IsReservedDomain(s string) bool { +func IsReservedTeamName(s string) bool { s = strings.ToLower(s) - for _, value := range reservedDomains { + for _, value := range reservedName { if strings.Index(s, value) == 0 { return true } @@ -180,7 +180,7 @@ func IsReservedDomain(s string) bool { return false } -func IsValidDomain(s string) bool { +func IsValidTeamName(s string) bool { if !IsValidAlphaNum(s) { return false diff --git a/model/utils_test.go b/model/utils_test.go index a9721042d..dbb448882 100644 --- a/model/utils_test.go +++ b/model/utils_test.go @@ -83,9 +83,9 @@ var domains = []struct { {"test", true}, } -func TestValidDomain(t *testing.T) { +func TestValidTeamName(t *testing.T) { for _, v := range domains { - if IsValidDomain(v.value) != v.expected { + if IsValidTeamName(v.value) != v.expected { t.Errorf("expect %v as %v", v.value, v.expected) } } @@ -102,9 +102,9 @@ var tReservedDomains = []struct { {"spin-punch-admin", false}, } -func TestReservedDomain(t *testing.T) { +func TestReservedTeamName(t *testing.T) { for _, v := range tReservedDomains { - if IsReservedDomain(v.value) != v.expected { + if IsReservedTeamName(v.value) != v.expected { t.Errorf("expect %v as %v", v.value, v.expected) } } diff --git a/store/sql_team_store.go b/store/sql_team_store.go index ffb9f8093..b89dca03e 100644 --- a/store/sql_team_store.go +++ b/store/sql_team_store.go @@ -19,8 +19,8 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore { for _, db := range sqlStore.GetAllConns() { table := db.AddTableWithName(model.Team{}, "Teams").SetKeys(false, "Id") table.ColMap("Id").SetMaxSize(26) - table.ColMap("Name").SetMaxSize(64) - table.ColMap("Domain").SetMaxSize(64).SetUnique(true) + table.ColMap("DisplayName").SetMaxSize(64) + table.ColMap("Name").SetMaxSize(64).SetUnique(true) table.ColMap("Email").SetMaxSize(128) table.ColMap("CompanyName").SetMaxSize(64) table.ColMap("AllowedDomains").SetMaxSize(500) @@ -35,6 +35,10 @@ func (s SqlTeamStore) UpgradeSchemaIfNeeded() { defaultValue = "1" } s.CreateColumnIfNotExists("Teams", "AllowValet", "AllowedDomains", "tinyint(1)", defaultValue) + if !s.DoesColumnExist("Teams", "DisplayName") { + s.RenameColumnIfExists("Teams", "Name", "DisplayName", "varchar(64)") + s.RenameColumnIfExists("Teams", "Domain", "Name", "varchar(64)") + } } func (s SqlTeamStore) CreateIndexesIfNotExists() { @@ -62,7 +66,7 @@ func (s SqlTeamStore) Save(team *model.Team) StoreChannel { } if err := s.GetMaster().Insert(team); err != nil { - if strings.Contains(err.Error(), "Duplicate entry") && strings.Contains(err.Error(), "for key 'Domain'") { + if strings.Contains(err.Error(), "Duplicate entry") && strings.Contains(err.Error(), "for key 'Name'") { result.Err = model.NewAppError("SqlTeamStore.Save", "A team with that domain already exists", "id="+team.Id+", "+err.Error()) } else { result.Err = model.NewAppError("SqlTeamStore.Save", "We couldn't save the team", "id="+team.Id+", "+err.Error()) @@ -100,7 +104,7 @@ func (s SqlTeamStore) Update(team *model.Team) StoreChannel { } else { oldTeam := oldResult.(*model.Team) team.CreateAt = oldTeam.CreateAt - team.Domain = oldTeam.Domain + team.Name = oldTeam.Name if count, err := s.GetMaster().Update(team); err != nil { result.Err = model.NewAppError("SqlTeamStore.Update", "We encounted an error updating the team", "id="+team.Id+", "+err.Error()) @@ -118,15 +122,15 @@ func (s SqlTeamStore) Update(team *model.Team) StoreChannel { return storeChannel } -func (s SqlTeamStore) UpdateName(name string, teamId string) StoreChannel { +func (s SqlTeamStore) UpdateDisplayName(name string, teamId string) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} - if _, err := s.GetMaster().Exec("UPDATE Teams SET Name = ? WHERE Id = ?", name, teamId); err != nil { - result.Err = model.NewAppError("SqlTeamStore.UpdateName", "We couldn't update the team name", "team_id="+teamId) + if _, err := s.GetMaster().Exec("UPDATE Teams SET DisplayName = ? WHERE Id = ?", name, teamId); err != nil { + result.Err = model.NewAppError("SqlTeamStore.UpdateDisplayName", "We couldn't update the team name", "team_id="+teamId) } else { result.Data = teamId } @@ -159,7 +163,7 @@ func (s SqlTeamStore) Get(id string) StoreChannel { return storeChannel } -func (s SqlTeamStore) GetByDomain(domain string) StoreChannel { +func (s SqlTeamStore) GetByName(name string) StoreChannel { storeChannel := make(StoreChannel) go func() { @@ -167,8 +171,8 @@ func (s SqlTeamStore) GetByDomain(domain string) StoreChannel { team := model.Team{} - if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Domain=?", domain); err != nil { - result.Err = model.NewAppError("SqlTeamStore.GetByDomain", "We couldn't find the existing team", "domain="+domain+", "+err.Error()) + if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Name=?", name); err != nil { + result.Err = model.NewAppError("SqlTeamStore.GetByName", "We couldn't find the existing team", "name="+name+", "+err.Error()) } result.Data = &team diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go index bd1a7de2e..1f13e466c 100644 --- a/store/sql_team_store_test.go +++ b/store/sql_team_store_test.go @@ -13,8 +13,8 @@ func TestTeamStoreSave(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN @@ -36,8 +36,8 @@ func TestTeamStoreUpdate(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN if err := (<-store.Team().Save(&o1)).Err; err != nil { @@ -61,25 +61,25 @@ func TestTeamStoreUpdate(t *testing.T) { } } -func TestTeamStoreUpdateName(t *testing.T) { +func TestTeamStoreUpdateDisplayName(t *testing.T) { Setup() o1 := &model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "Display Name" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN o1 = (<-store.Team().Save(o1)).Data.(*model.Team) - newName := "NewName" + newDisplayName := "NewDisplayName" - if err := (<-store.Team().UpdateName(newName, o1.Id)).Err; err != nil { + if err := (<-store.Team().UpdateDisplayName(newDisplayName, o1.Id)).Err; err != nil { t.Fatal(err) } ro1 := (<-store.Team().Get(o1.Id)).Data.(*model.Team) - if ro1.Name != newName { - t.Fatal("Name not updated") + if ro1.DisplayName != newDisplayName { + t.Fatal("DisplayName not updated") } } @@ -87,8 +87,8 @@ func TestTeamStoreGet(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN Must(store.Team().Save(&o1)) @@ -106,12 +106,12 @@ func TestTeamStoreGet(t *testing.T) { } } -func TestTeamStoreGetByDomain(t *testing.T) { +func TestTeamStoreGetByName(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN @@ -119,7 +119,7 @@ func TestTeamStoreGetByDomain(t *testing.T) { t.Fatal(err) } - if r1 := <-store.Team().GetByDomain(o1.Domain); r1.Err != nil { + if r1 := <-store.Team().GetByName(o1.Name); r1.Err != nil { t.Fatal(r1.Err) } else { if r1.Data.(*model.Team).ToJson() != o1.ToJson() { @@ -127,7 +127,7 @@ func TestTeamStoreGetByDomain(t *testing.T) { } } - if err := (<-store.Team().GetByDomain("")).Err; err == nil { + if err := (<-store.Team().GetByName("")).Err; err == nil { t.Fatal("Missing id should have failed") } } @@ -136,8 +136,8 @@ func TestTeamStoreGetForEmail(t *testing.T) { Setup() o1 := model.Team{} - o1.Name = "Name" - o1.Domain = "a" + model.NewId() + "b" + o1.DisplayName = "DisplayName" + o1.Name = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN Must(store.Team().Save(&o1)) diff --git a/store/store.go b/store/store.go index 9faa6a9d7..5b0e13fce 100644 --- a/store/store.go +++ b/store/store.go @@ -36,9 +36,9 @@ type Store interface { type TeamStore interface { Save(team *model.Team) StoreChannel Update(team *model.Team) StoreChannel - UpdateName(name string, teamId string) StoreChannel + UpdateDisplayName(name string, teamId string) StoreChannel Get(id string) StoreChannel - GetByDomain(domain string) StoreChannel + GetByName(name string) StoreChannel GetTeamsForEmail(domain string) StoreChannel } diff --git a/utils/config.go b/utils/config.go index 6ad29ab7d..efa4b263a 100644 --- a/utils/config.go +++ b/utils/config.go @@ -19,13 +19,11 @@ const ( type ServiceSettings struct { SiteName string - Domain string Mode string AllowTesting bool UseSSL bool Port string Version string - Shards map[string]string InviteSalt string PublicLinkSalt string ResetSalt string @@ -52,14 +50,10 @@ type LogSettings struct { } type AWSSettings struct { - S3AccessKeyId string - S3SecretAccessKey string - S3Bucket string - S3Region string - Route53AccessKeyId string - Route53SecretAccessKey string - Route53ZoneId string - Route53Region string + S3AccessKeyId string + S3SecretAccessKey string + S3Bucket string + S3Region string } type ImageSettings struct { @@ -213,18 +207,10 @@ func LoadConfig(fileName string) { panic("Error decoding configuration " + err.Error()) } - // Grabs the domain from enviroment variable if not in configuration - if config.ServiceSettings.Domain == "" { - config.ServiceSettings.Domain = os.Getenv("MATTERMOST_DOMAIN") - // If the enviroment variable is not set, use a default - if config.ServiceSettings.Domain == "" { - config.ServiceSettings.Domain = "localhost" - } - } - // Check for a valid email for feedback, if not then do feedback@domain if _, err := mail.ParseAddress(config.EmailSettings.FeedbackEmail); err != nil { - config.EmailSettings.FeedbackEmail = "feedback@" + config.ServiceSettings.Domain + config.EmailSettings.FeedbackEmail = "feedback@localhost" + l4g.Error("Misconfigured feedback email setting: %s", config.EmailSettings.FeedbackEmail) } configureLog(config.LogSettings) diff --git a/utils/config_test.go b/utils/config_test.go index 9067dc647..4d37b4e88 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -4,24 +4,9 @@ package utils import ( - "os" "testing" ) func TestConfig(t *testing.T) { LoadConfig("config.json") } - -func TestEnvOverride(t *testing.T) { - os.Setenv("MATTERMOST_DOMAIN", "testdomain.com") - - LoadConfig("config_docker.json") - if Cfg.ServiceSettings.Domain != "testdomain.com" { - t.Fail() - } - - LoadConfig("config.json") - if Cfg.ServiceSettings.Domain == "testdomain.com" { - t.Fail() - } -} diff --git a/web/react/components/delete_channel_modal.jsx b/web/react/components/delete_channel_modal.jsx index a8c690789..e23a37740 100644 --- a/web/react/components/delete_channel_modal.jsx +++ b/web/react/components/delete_channel_modal.jsx @@ -12,7 +12,7 @@ module.exports = React.createClass({ Client.deleteChannel(this.state.channel_id, function(data) { AsyncClient.getChannels(true); - window.location.href = '/channels/town-square'; + window.location.href = '/'; }.bind(this), function(err) { AsyncClient.dispatchError(err, "handleDelete"); diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 74c7d4065..71fefff5b 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -1,102 +1,21 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. - - - var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); var BrowserStore = require('../stores/browser_store.jsx'); - - -var FindTeamDomain = React.createClass({ - handleSubmit: function(e) { - e.preventDefault(); - var state = { } - - var domain = this.refs.domain.getDOMNode().value.trim(); - if (!domain) { - state.server_error = "A domain is required" - this.setState(state); - return; - } - - if (!BrowserStore.isLocalStorageSupported()) { - state.server_error = "This service requires local storage to be enabled. Please enable it or exit private browsing."; - this.setState(state); - return; - } - - state.server_error = ""; - this.setState(state); - - client.findTeamByDomain(domain, - function(data) { - console.log(data); - if (data) { - window.location.href = window.location.protocol + "//" + domain + "." + utils.getDomainWithOutSub(); - } - else { - this.state.server_error = "We couldn't find your " + strings.Team + "."; - this.setState(this.state); - } - }.bind(this), - function(err) { - this.state.server_error = err.message; - this.setState(this.state); - }.bind(this) - ); - }, - getInitialState: function() { - return { }; - }, - render: function() { - var server_error = this.state.server_error ? <label className="control-label">{this.state.server_error}</label> : null; - - return ( - <div className="signup-team__container"> - <div> - <span className="signup-team__name">{ config.SiteName }</span> - <br/> - <span className="signup-team__subdomain">Enter your {strings.Team}'s domain.</span> - <br/> - <br/> - </div> - <form onSubmit={this.handleSubmit}> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - { server_error } - <input type="text" className="form-control" name="domain" ref="domain" placeholder="team domain" /> - </div> - <div className="form-group"> - <button type="submit" className="btn btn-primary">Continue</button> - </div> - <div> - <span>Don't remember your {strings.Team}'s domain? <a href="/find_team">Find it here</a></span> - </div> - <br/> - <br/> - <br/> - <br/> - <br/> - <br/> - <div> - <span>{"Want to create your own " + strings.Team + "?"} <a href={utils.getHomeLink()} className="signup-team-login">Sign up now</a></span> - </div> - </form> - </div> - ); - } -}); +var Constants = require('../utils/constants.jsx'); module.exports = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var state = { } - var domain = this.refs.domain.getDOMNode().value.trim(); - if (!domain) { - state.server_error = "A domain is required" + var name = this.props.teamName + if (!name) { + state.server_error = "Bad team name" this.setState(state); return; } @@ -124,23 +43,22 @@ module.exports = React.createClass({ state.server_error = ""; this.setState(state); - client.loginByEmail(domain, email, password, + client.loginByEmail(name, email, password, function(data) { - UserStore.setLastDomain(domain); - UserStore.setLastEmail(email); UserStore.setCurrentUser(data); + UserStore.setLastEmail(email); var redirect = utils.getUrlParameter("redirect"); if (redirect) { - window.location.href = decodeURI(redirect); + window.location.pathname = decodeURI(redirect); } else { - window.location.href = '/channels/town-square'; + window.location.pathname = '/' + name + '/channels/town-square'; } }.bind(this), function(err) { if (err.message == "Login failed because email address has not been verified") { - window.location.href = '/verify?domain=' + encodeURIComponent(domain) + '&email=' + encodeURIComponent(email); + window.location.href = '/verify_email?name=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(email); return; } state.server_error = err.message; @@ -161,35 +79,35 @@ module.exports = React.createClass({ priorEmail = decodeURIComponent(emailParam); } - var subDomainClass = "form-control hidden"; - var subDomain = utils.getSubDomain(); + var teamDisplayName = this.props.teamDisplayName; + var teamName = this.props.teamName; - if (utils.isTestDomain()) { - subDomainClass = "form-control"; - subDomain = UserStore.getLastDomain(); - } else if (subDomain == "") { - return (<FindTeamDomain />); + var focusEmail = false; + var focusPassword = false; + if (priorEmail != "") { + focusPassword = true; + } else { + focusEmail = true; } return ( <div className="signup-team__container"> <div> - <span className="signup-team__name">{ subDomain }</span> + <span className="signup-team__name">{ teamDisplayName }</span> <br/> - <span className="signup-team__subdomain">{ utils.getDomainWithOutSub() }</span> + <span className="signup-team__subdomain">/{ teamName }/</span> <br/> <br/> </div> <form onSubmit={this.handleSubmit}> <div className={server_error ? 'form-group has-error' : 'form-group'}> { server_error } - <input type="text" className={subDomainClass} name="domain" defaultValue={subDomain} ref="domain" placeholder="Domain" /> </div> <div className={server_error ? 'form-group has-error' : 'form-group'}> - <input type="email" className="form-control" name="email" defaultValue={priorEmail} ref="email" placeholder="Email" /> + <input autoFocus={focusEmail} type="email" className="form-control" name="email" defaultValue={priorEmail} ref="email" placeholder="Email" /> </div> <div className={server_error ? 'form-group has-error' : 'form-group'}> - <input type="password" className="form-control" name="password" ref="password" placeholder="Password" /> + <input autoFocus={focusPassword} type="password" className="form-control" name="password" ref="password" placeholder="Password" /> </div> <div className="form-group"> <button type="submit" className="btn btn-primary">Sign in</button> @@ -198,10 +116,10 @@ module.exports = React.createClass({ <span><a href="/find_team">{"Find other " + strings.TeamPlural}</a></span> </div> <div className="form-group"> - <a href="/reset_password">I forgot my password</a> + <a href={"/" + teamName + "/reset_password"}>I forgot my password</a> </div> <div className="external-link"> - <span>{"Want to create your own " + strings.Team + "?"} <a href={utils.getHomeLink()} className="signup-team-login">Sign up now</a></span> + <span>{"Want to create your own " + strings.Team + "?"} <a href="/" className="signup-team-login">Sign up now</a></span> </div> </form> </div> diff --git a/web/react/components/msg_typing.jsx b/web/react/components/msg_typing.jsx index a6953028f..aacb315dd 100644 --- a/web/react/components/msg_typing.jsx +++ b/web/react/components/msg_typing.jsx @@ -51,7 +51,7 @@ module.exports = React.createClass({ }, render: function() { return ( - <span className="msg-typing">{ this.state.text }</span> + <span className="msg-typing">{ this.state.text }</span> ); } }); diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx index 78cf7d8b8..34c65c34f 100644 --- a/web/react/components/navbar.jsx +++ b/web/react/components/navbar.jsx @@ -7,6 +7,7 @@ var client = require('../utils/client.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var UserStore = require('../stores/user_store.jsx'); var ChannelStore = require('../stores/channel_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); var UserProfile = require('./user_profile.jsx'); var MessageWrapper = require('./message_wrapper.jsx'); @@ -61,93 +62,6 @@ var NotifyCounts = React.createClass({ } }); -var NavbarLoginForm = React.createClass({ - handleSubmit: function(e) { - e.preventDefault(); - var state = { }; - - var domain = this.refs.domain.getDOMNode().value.trim(); - if (!domain) { - state.server_error = "A domain is required"; - this.setState(state); - return; - } - - var email = this.refs.email.getDOMNode().value.trim(); - if (!email) { - state.server_error = "An email is required"; - this.setState(state); - return; - } - - var password = this.refs.password.getDOMNode().value.trim(); - if (!password) { - state.server_error = "A password is required"; - this.setState(state); - return; - } - - state.server_error = ""; - this.setState(state); - - client.loginByEmail(domain, email, password, - function(data) { - UserStore.setLastDomain(domain); - UserStore.setLastEmail(email); - UserStore.setCurrentUser(data); - - var redirect = utils.getUrlParameter("redirect"); - if (redirect) { - window.location.href = decodeURI(redirect); - } else { - window.location.href = '/channels/town-square'; - } - - }, - function(err) { - if (err.message == "Login failed because email address has not been verified") { - window.location.href = '/verify?domain=' + encodeURIComponent(domain) + '&email=' + encodeURIComponent(email); - return; - } - state.server_error = err.message; - this.valid = false; - this.setState(state); - }.bind(this) - ); - }, - getInitialState: function() { - return { }; - }, - render: function() { - var server_error = this.state.server_error ? <label className="control-label">{this.state.server_error}</label> : null; - - var subDomain = utils.getSubDomain(); - var subDomainClass = "form-control hidden"; - - if (subDomain == "") { - subDomain = UserStore.getLastDomain(); - subDomainClass = "form-control"; - } - - return ( - <form className="navbar-form navbar-right" onSubmit={this.handleSubmit}> - <a href="/find_team">Find your team</a> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - { server_error } - <input type="text" className={subDomainClass} name="domain" defaultValue={subDomain} ref="domain" placeholder="Domain" /> - </div> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - <input type="text" className="form-control" name="email" defaultValue={UserStore.getLastEmail()} ref="email" placeholder="Email" /> - </div> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - <input type="password" className="form-control" name="password" ref="password" placeholder="Password" /> - </div> - <button type="submit" className="btn btn-default">Login</button> - </form> - ); - } -}); - function getStateFromStores() { return { channel: ChannelStore.getCurrent(), @@ -180,10 +94,10 @@ module.exports = React.createClass({ }, handleLeave: function(e) { client.leaveChannel(this.state.channel.id, - function() { + function(data, text, req) { AsyncClient.getChannels(true); - window.location.href = '/channels/town-square'; - }, + window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/town-square'; + }.bind(this), function(err) { AsyncClient.dispatchError(err, "handleLeave"); } @@ -229,7 +143,7 @@ module.exports = React.createClass({ var currentId = UserStore.getCurrentId(); var popoverContent = ""; - var channelTitle = this.props.teamName; + var channelTitle = this.props.teamDisplayName; var isAdmin = false; var isDirect = false; var description = "" @@ -333,14 +247,8 @@ module.exports = React.createClass({ <div className="navbar-brand"> <a href="/" className="heading">{ channelTitle }</a> </div> - : null } + : "" } </div> - { !currentId ? - <div className="collapse navbar-collapse" id="navbar-collapse-1"> - <NavbarLoginForm /> - </div> - : null - } </div> </nav> ); diff --git a/web/react/components/new_channel.jsx b/web/react/components/new_channel.jsx index 069e0d6b1..49e088458 100644 --- a/web/react/components/new_channel.jsx +++ b/web/react/components/new_channel.jsx @@ -6,6 +6,8 @@ var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var asyncClient = require('../utils/async_client.jsx'); var UserStore = require('../stores/user_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); +var Constants = require('../utils/constants.jsx'); module.exports = React.createClass({ handleSubmit: function(e) { @@ -60,13 +62,13 @@ module.exports = React.createClass({ var self = this; client.createChannel(channel, - function(data) { + function() { this.refs.display_name.getDOMNode().value = ""; this.refs.channel_name.getDOMNode().value = ""; this.refs.channel_desc.getDOMNode().value = ""; $(self.refs.modal.getDOMNode()).modal('hide'); - window.location.href = "/channels/" + channel.name; + window.location = TeamStore.getCurrentTeamUrl() + "/channels/" + channel.name; asyncClient.getChannels(true); }.bind(this), function(err) { diff --git a/web/react/components/password_reset.jsx b/web/react/components/password_reset.jsx index 24566c7b1..b2edea620 100644 --- a/web/react/components/password_reset.jsx +++ b/web/react/components/password_reset.jsx @@ -10,13 +10,6 @@ SendResetPasswordLink = React.createClass({ e.preventDefault(); var state = {}; - var domain = this.refs.domain.getDOMNode().value.trim(); - if (!domain) { - state.error = "A domain is required" - this.setState(state); - return; - } - var email = this.refs.email.getDOMNode().value.trim(); if (!email) { state.error = "Please enter a valid email address." @@ -29,17 +22,17 @@ SendResetPasswordLink = React.createClass({ data = {}; data['email'] = email; - data['domain'] = domain; + data['name'] = this.props.teamName; client.sendPasswordReset(data, - function(data) { - this.setState({ error: null, update_text: <p>A password reset link has been sent to <b>{email}</b> for your <b>{this.props.teamName}</b> team on {config.SiteName}.com.</p>, more_update_text: "Please check your inbox." }); - $(this.refs.reset_form.getDOMNode()).hide(); - }.bind(this), - function(err) { - this.setState({ error: err.message, update_text: null, more_update_text: null }); - }.bind(this) - ); + function(data) { + this.setState({ error: null, update_text: <p>A password reset link has been sent to <b>{email}</b> for your <b>{this.props.teamDisplayName}</b> team on {window.location.hostname}.</p>, more_update_text: "Please check your inbox." }); + $(this.refs.reset_form.getDOMNode()).hide(); + }.bind(this), + function(err) { + this.setState({ error: err.message, update_text: null, more_update_text: null }); + }.bind(this) + ); }, getInitialState: function() { return {}; @@ -48,24 +41,13 @@ SendResetPasswordLink = React.createClass({ var update_text = this.state.update_text ? <div className="reset-form alert alert-success">{this.state.update_text}{this.state.more_update_text}</div> : null; var error = this.state.error ? <div className="form-group has-error"><label className="control-label">{this.state.error}</label></div> : null; - var subDomain = utils.getSubDomain(); - var subDomainClass = "form-control hidden"; - - if (subDomain == "") { - subDomain = UserStore.getLastDomain(); - subDomainClass = "form-control"; - } - return ( <div className="col-sm-12"> <div className="signup-team__container"> <h3>Password Reset</h3> { update_text } <form onSubmit={this.handleSendLink} ref="reset_form"> - <p>{"To reset your password, enter the email address you used to sign up for " + this.props.teamName + "."}</p> - <div className="form-group"> - <input type="text" className={subDomainClass} name="domain" defaultValue={subDomain} ref="domain" placeholder="Domain" /> - </div> + <p>{"To reset your password, enter the email address you used to sign up for " + this.props.teamDisplayName + "."}</p> <div className={error ? 'form-group has-error' : 'form-group'}> <input type="text" className="form-control" name="email" ref="email" placeholder="Email" /> </div> @@ -83,13 +65,6 @@ ResetPassword = React.createClass({ e.preventDefault(); var state = {}; - var domain = this.refs.domain.getDOMNode().value.trim(); - if (!domain) { - state.error = "A domain is required" - this.setState(state); - return; - } - var password = this.refs.password.getDOMNode().value.trim(); if (!password || password.length < 5) { state.error = "Please enter at least 5 characters." @@ -104,41 +79,30 @@ ResetPassword = React.createClass({ data['new_password'] = password; data['hash'] = this.props.hash; data['data'] = this.props.data; - data['domain'] = domain; + data['name'] = this.props.teamName; client.resetPassword(data, - function(data) { - this.setState({ error: null, update_text: "Your password has been updated successfully." }); - }.bind(this), - function(err) { - this.setState({ error: err.message, update_text: null }); - }.bind(this) - ); + function(data) { + this.setState({ error: null, update_text: "Your password has been updated successfully." }); + }.bind(this), + function(err) { + this.setState({ error: err.message, update_text: null }); + }.bind(this) + ); }, getInitialState: function() { return {}; }, render: function() { - var update_text = this.state.update_text ? <div className="form-group"><br/><label className="control-label reset-form">{this.state.update_text} Click <a href="/login">here</a> to log in.</label></div> : null; + var update_text = this.state.update_text ? <div className="form-group"><br/><label className="control-label reset-form">{this.state.update_text} Click <a href={"/" + this.props.teamName + "/login"}>here</a> to log in.</label></div> : null; var error = this.state.error ? <div className="form-group has-error"><label className="control-label">{this.state.error}</label></div> : null; - var subDomain = this.props.domain != "" ? this.props.domain : utils.getSubDomain(); - var subDomainClass = "form-control hidden"; - - if (subDomain == "") { - subDomain = UserStore.getLastDomain(); - subDomainClass = "form-control"; - } - return ( <div className="col-sm-12"> <div className="signup-team__container"> <h3>Password Reset</h3> <form onSubmit={this.handlePasswordReset}> - <p>{"Enter a new password for your " + this.props.teamName + " " + config.SiteName + " account."}</p> - <div className="form-group"> - <input type="text" className={subDomainClass} name="domain" defaultValue={subDomain} ref="domain" placeholder="Domain" /> - </div> + <p>{"Enter a new password for your " + this.props.teamDisplayName + " " + config.SiteName + " account."}</p> <div className={error ? 'form-group has-error' : 'form-group'}> <input type="password" className="form-control" name="password" ref="password" placeholder="Password" /> </div> @@ -161,14 +125,15 @@ module.exports = React.createClass({ if (this.props.isReset === "false") { return ( <SendResetPasswordLink + teamDisplayName={this.props.teamDisplayName} teamName={this.props.teamName} /> ); } else { return ( <ResetPassword + teamDisplayName={this.props.teamDisplayName} teamName={this.props.teamName} - domain={this.props.domain} hash={this.props.hash} data={this.props.data} /> diff --git a/web/react/components/rename_channel_modal.jsx b/web/react/components/rename_channel_modal.jsx index b4ccb2937..2ae331626 100644 --- a/web/react/components/rename_channel_modal.jsx +++ b/web/react/components/rename_channel_modal.jsx @@ -6,6 +6,8 @@ var utils = require('../utils/utils.jsx'); var Client = require('../utils/client.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var ChannelStore = require('../stores/channel_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); +var Constants = require('../utils/constants.jsx'); module.exports = React.createClass({ handleSubmit: function(e) { @@ -60,12 +62,12 @@ module.exports = React.createClass({ return; Client.updateChannel(channel, - function(data) { + function(data, text, req) { this.refs.display_name.getDOMNode().value = ""; this.refs.channel_name.getDOMNode().value = ""; $('#' + this.props.modalId).modal('hide'); - window.location.href = '/channels/' + this.state.channel_name; + window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + this.state.channel_name; AsyncClient.getChannels(true); }.bind(this), function(err) { diff --git a/web/react/components/rename_team_modal.jsx b/web/react/components/rename_team_modal.jsx index 67a150b9d..a6da57b67 100644 --- a/web/react/components/rename_team_modal.jsx +++ b/web/react/components/rename_team_modal.jsx @@ -24,13 +24,13 @@ module.exports = React.createClass({ if (!valid) return; - if (this.props.teamName === name) + if (this.props.teamDisplayName === name) return; var data = {}; data["new_name"] = name; - Client.updateTeamName(data, + Client.updateTeamDisplayName(data, function(data) { $('#rename_team_link').modal('hide'); window.location.reload(); @@ -47,11 +47,11 @@ module.exports = React.createClass({ componentDidMount: function() { var self = this; $(this.refs.modal.getDOMNode()).on('hidden.bs.modal', function(e) { - self.setState({ name: self.props.teamName }); + self.setState({ name: self.props.teamDisplayName }); }); }, getInitialState: function() { - return { name: this.props.teamName }; + return { name: this.props.teamDisplayName }; }, render: function() { diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 65727c597..3cf67e410 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -6,6 +6,7 @@ var ChannelStore = require('../stores/channel_store.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var SocketStore = require('../stores/socket_store.jsx'); var UserStore = require('../stores/user_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); var utils = require('../utils/utils.jsx'); var SidebarHeader = require('./sidebar_header.jsx'); var SearchBox = require('./search_bar.jsx'); @@ -13,93 +14,6 @@ var SearchBox = require('./search_bar.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; -var SidebarLoginForm = React.createClass({ - handleSubmit: function(e) { - e.preventDefault(); - var state = { } - - var domain = this.refs.domain.getDOMNode().value.trim(); - if (!domain) { - state.server_error = "A domain is required" - this.setState(state); - return; - } - - var email = this.refs.email.getDOMNode().value.trim(); - if (!email) { - state.server_error = "An email is required" - this.setState(state); - return; - } - - var password = this.refs.password.getDOMNode().value.trim(); - if (!password) { - state.server_error = "A password is required" - this.setState(state); - return; - } - - state.server_error = ""; - this.setState(state); - - client.loginByEmail(domain, email, password, - function(data) { - UserStore.setLastDomain(domain); - UserStore.setLastEmail(email); - UserStore.setCurrentUser(data); - - var redirect = utils.getUrlParameter("redirect"); - if (redirect) { - window.location.href = decodeURI(redirect); - } else { - window.location.href = '/channels/town-square'; - } - - }.bind(this), - function(err) { - if (err.message == "Login failed because email address has not been verified") { - window.location.href = '/verify?domain=' + encodeURIComponent(domain) + '&email=' + encodeURIComponent(email); - return; - } - state.server_error = err.message; - this.valid = false; - this.setState(state); - }.bind(this) - ); - }, - getInitialState: function() { - return { }; - }, - render: function() { - var server_error = this.state.server_error ? <label className="control-label">{this.state.server_error}</label> : null; - - var subDomain = utils.getSubDomain(); - var subDomainClass = "form-control hidden"; - - if (subDomain == "") { - subDomain = UserStore.getLastDomain(); - subDomainClass = "form-control"; - } - - return ( - <form className="" onSubmit={this.handleSubmit}> - <a href="/find_team">{"Find your " + strings.Team}</a> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - { server_error } - <input type="text" className={subDomainClass} name="domain" defaultValue={subDomain} ref="domain" placeholder="Domain" /> - </div> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - <input type="text" className="form-control" name="email" defaultValue={UserStore.getLastEmail()} ref="email" placeholder="Email" /> - </div> - <div className={server_error ? 'form-group has-error' : 'form-group'}> - <input type="password" className="form-control" name="password" ref="password" placeholder="Password" /> - </div> - <button type="submit" className="btn btn-default">Login</button> - </form> - ); - } -}); - function getStateFromStores() { var members = ChannelStore.getAllMembers(); var team_member_map = UserStore.getActiveOnlyProfiles(); @@ -192,7 +106,7 @@ function getStateFromStores() { }; } -var SidebarLoggedIn = React.createClass({ +module.exports = React.createClass({ componentDidMount: function() { ChannelStore.addChangeListener(this._onChange); UserStore.addChangeListener(this._onChange); @@ -383,7 +297,7 @@ var SidebarLoggedIn = React.createClass({ ); } else { return ( - <li key={channel.name} className={active}><a className={"sidebar-channel " + titleClass} href={"/channels/"+channel.name}><span className="status" dangerouslySetInnerHTML={{__html: statusIcon}} /> {badge}{channel.display_name}</a></li> + <li key={channel.name} className={active}><a className={"sidebar-channel " + titleClass} href={TeamStore.getCurrentTeamUrl() + "/channels/"+channel.name}><span className="status" dangerouslySetInnerHTML={{__html: statusIcon}} /> {badge}{channel.display_name}</a></li> ); } @@ -414,7 +328,7 @@ var SidebarLoggedIn = React.createClass({ } return ( <div> - <SidebarHeader teamName={this.props.teamName} teamType={this.props.teamType} /> + <SidebarHeader teamDisplayName={this.props.teamDisplayName} teamType={this.props.teamType} /> <SearchBox /> <div className="nav-pills__container"> @@ -440,25 +354,3 @@ var SidebarLoggedIn = React.createClass({ ); } }); - -var SidebarLoggedOut = React.createClass({ - render: function() { - return ( - <div> - <SidebarHeader teamName={this.props.teamName} /> - <SidebarLoginForm /> - </div> - ); - } -}); - -module.exports = React.createClass({ - render: function() { - var currentId = UserStore.getCurrentId(); - if (currentId != null) { - return <SidebarLoggedIn teamName={this.props.teamName} teamType={this.props.teamType} />; - } else { - return <SidebarLoggedOut teamName={this.props.teamName} />; - } - } -}); diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 45c9ca629..bab2897b6 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -61,19 +61,15 @@ var NavbarDropdown = React.createClass({ var teams = []; + teams.push(<li className="divider" key="div"></li>); if (this.state.teams.length > 1) { for (var i = 0; i < this.state.teams.length; i++) { - var domain = this.state.teams[i]; + var teamName = this.state.teams[i]; - if (domain == utils.getSubDomain()) - continue; - - if (teams.length == 0) - teams.push(<li className="divider" key="div"></li>); - - teams.push(<li key={ domain }><a href={window.location.protocol + "//" + domain + "." + utils.getDomainWithOutSub() }>Switch to { domain }</a></li>); + teams.push(<li key={ teamName }><a href={window.location.origin + "/" + teamName }>Switch to { teamName }</a></li>); } } + teams.push(<li><a href={window.location.origin + "/signup_team" }>Create a New Team</a></li>); return ( <ul className="nav navbar-nav navbar-right"> @@ -110,19 +106,21 @@ module.exports = React.createClass({ }, render: function() { - var me = UserStore.getCurrentUser(); - + var teamDisplayName = this.props.teamDisplayName ? this.props.teamDisplayName : config.SiteName; + var me = UserStore.getCurrentUser() if (!me) { return null; } return ( <div className="team__header theme"> - <img className="user__picture" src={"/api/v1/users/" + me.id + "/image?time=" + me.update_at} /> - <div className="header__info"> - <div className="user__name">{'@' + me.username}</div> - <a className="team__name" href="/channels/town-square">{this.props.teamName}</a> - </div> + <a className="settings_link" href="#" data-toggle="modal" data-target="#user_settings1"> + <img className="user__picture" src={"/api/v1/users/" + me.id + "/image?time=" + me.update_at} /> + <div className="header__info"> + <div className="user__name">{ '@' + me.username}</div> + <div className="team__name">{ teamDisplayName }</div> + </div> + </a> <NavbarDropdown teamType={this.props.teamType} /> </div> ); diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx index 22d1d9ad2..15306a499 100644 --- a/web/react/components/sidebar_right_menu.jsx +++ b/web/react/components/sidebar_right_menu.jsx @@ -49,12 +49,12 @@ module.exports = React.createClass({ } var siteName = config.SiteName != null ? config.SiteName : ""; - var teamName = this.props.teamName ? this.props.teamName : siteName; + var teamDisplayName = this.props.teamDisplayName ? this.props.teamDisplayName : siteName; return ( <div> <div className="team__header theme"> - <a className="team__name" href="/channels/town-square">{ teamName }</a> + <a className="team__name" href="/channels/town-square">{ teamDisplayName }</a> </div> <div className="nav-pills__container"> diff --git a/web/react/components/signup_team.jsx b/web/react/components/signup_team.jsx index 22086250c..cf982cc1e 100644 --- a/web/react/components/signup_team.jsx +++ b/web/react/components/signup_team.jsx @@ -20,8 +20,8 @@ module.exports = React.createClass({ state.email_error = ""; } - team.name = this.refs.name.getDOMNode().value.trim(); - if (!team.name) { + team.display_name = this.refs.name.getDOMNode().value.trim(); + if (!team.display_name) { state.name_error = "This field is required"; state.inValid = true; } @@ -34,7 +34,7 @@ module.exports = React.createClass({ return; } - client.signupTeam(team.email, team.name, + client.signupTeam(team.email, team.display_name, function(data) { if (data["follow_link"]) { window.location.href = data["follow_link"]; @@ -61,7 +61,7 @@ module.exports = React.createClass({ return ( <form role="form" onSubmit={this.handleSubmit}> <div className={ email_error ? "form-group has-error" : "form-group" }> - <input type="email" ref="email" className="form-control" placeholder="Email Address" maxLength="128" /> + <input autoFocus={true} type="email" ref="email" className="form-control" placeholder="Email Address" maxLength="128" /> { email_error } </div> <div className={ name_error ? "form-group has-error" : "form-group" }> @@ -70,6 +70,9 @@ module.exports = React.createClass({ </div> { server_error } <button className="btn btn-md btn-primary" type="submit">Sign up for Free</button> + <div className="form-group form-group--small"> + <span><a href="/find_team">{"Find my " + strings.Team}</a></span> + </div> </form> ); } diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx index 9e2a13955..9ceeb6324 100644 --- a/web/react/components/signup_team_complete.jsx +++ b/web/react/components/signup_team_complete.jsx @@ -15,7 +15,7 @@ WelcomePage = React.createClass({ return; } e.preventDefault(); - this.props.state.wizard = "team_name"; + this.props.state.wizard = "team_display_name"; this.props.updateParent(this.props.state); }, handleDiffEmail: function (e) { @@ -57,6 +57,17 @@ WelcomePage = React.createClass({ getInitialState: function() { return { use_diff: false }; }, + handleKeyPress: function(event) { + if (event.keyCode == 13) { + this.submitNext(event); + } + }, + componentWillMount: function() { + document.addEventListener("keyup", this.handleKeyPress, false); + }, + componentWillUnmount: function() { + document.removeEventListener("keyup", this.handleKeyPress, false); + }, render: function() { client.track('signup', 'signup_team_01_welcome'); @@ -77,7 +88,7 @@ WelcomePage = React.createClass({ <span className="black">{ this.props.state.team.email }</span><br /> </p> <div className="form-group"> - <button className="btn-primary btn form-group" onClick={this.submitNext}><i className="glyphicon glyphicon-ok"></i>Yes, this address is correct</button> + <button className="btn-primary btn form-group" type="submit" onClick={this.submitNext}><i className="glyphicon glyphicon-ok"></i>Yes, this address is correct</button> { storage_error } </div> <hr /> @@ -92,15 +103,15 @@ WelcomePage = React.createClass({ { email_error } </div> { server_error } - <button className="btn btn-md btn-primary" onClick={this.handleDiffSubmit} type="submit">Use this instead</button> + <button className="btn btn-md btn-primary" type="button" onClick={this.handleDiffSubmit} type="submit">Use this instead</button> </div> - <button onClick={this.handleDiffEmail} className={ this.state.use_diff ? "btn-default btn hidden" : "btn-default btn" }>Use a different address</button> + <button type="button" onClick={this.handleDiffEmail} className={ this.state.use_diff ? "btn-default btn hidden" : "btn-default btn" }>Use a different address</button> </div> ); } }); -TeamNamePage = React.createClass({ +TeamDisplayNamePage = React.createClass({ submitBack: function (e) { e.preventDefault(); this.props.state.wizard = "welcome"; @@ -109,19 +120,24 @@ TeamNamePage = React.createClass({ submitNext: function (e) { e.preventDefault(); - var name = this.refs.name.getDOMNode().value.trim(); - if (!name) { + var display_name = this.refs.name.getDOMNode().value.trim(); + if (!display_name) { this.setState({name_error: "This field is required"}); return; } this.props.state.wizard = "team_url"; - this.props.state.team.name = name; + this.props.state.team.display_name = display_name; this.props.updateParent(this.props.state); }, getInitialState: function() { return { }; }, + handleFocus: function(e) { + e.preventDefault(); + + e.currentTarget.select(); + }, render: function() { client.track('signup', 'signup_team_02_name'); @@ -130,29 +146,31 @@ TeamNamePage = React.createClass({ return ( <div> + <form> <img className="signup-team-logo" src="/static/images/logo.png" /> <h2>{utils.toTitleCase(strings.Team) + " Name"}</h2> <div className={ name_error ? "form-group has-error" : "form-group" }> <div className="row"> <div className="col-sm-9"> - <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" defaultValue={this.props.state.team.name} /> + <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" defaultValue={this.props.state.team.display_name} autoFocus={true} onFocus={this.handleFocus} /> </div> </div> { name_error } </div> <p>{"Your " + strings.Team + " name shows in menus and headings. It may include the name of your " + strings.Company + ", but it's not required."}</p> - <button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> - <button className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> + <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + </form> </div> ); } }); -TeamUrlPage = React.createClass({ +TeamURLPage = React.createClass({ submitBack: function (e) { e.preventDefault(); - this.props.state.wizard = "team_name"; + this.props.state.wizard = "team_display_name"; this.props.updateParent(this.props.state); }, submitNext: function (e) { @@ -172,18 +190,18 @@ TeamUrlPage = React.createClass({ return; } else if (cleaned_name.length <= 3 || cleaned_name.length > 15) { - this.setState({name_error: "Domain must be 4 or more characters up to a maximum of 15"}) + this.setState({name_error: "Name must be 4 or more characters up to a maximum of 15"}) return; } - for (var index = 0; index < constants.RESERVED_DOMAINS.length; index++) { - if (cleaned_name.indexOf(constants.RESERVED_DOMAINS[index]) == 0) { - this.setState({name_error: "This Team URL name is unavailable"}) + for (var index = 0; index < constants.RESERVED_TEAM_NAMES.length; index++) { + if (cleaned_name.indexOf(constants.RESERVED_TEAM_NAMES[index]) == 0) { + this.setState({name_error: "This team name is unavailable"}) return; } } - client.findTeamByDomain(name, + client.findTeamByName(name, function(data) { if (!data) { if (config.AllowSignupDomainsWizard) { @@ -193,7 +211,7 @@ TeamUrlPage = React.createClass({ this.props.state.team.type = 'O'; } - this.props.state.team.domain = name; + this.props.state.team.name = name; this.props.updateParent(this.props.state); } else { @@ -210,6 +228,11 @@ TeamUrlPage = React.createClass({ getInitialState: function() { return { }; }, + handleFocus: function(e) { + e.preventDefault(); + + e.currentTarget.select(); + }, render: function() { client.track('signup', 'signup_team_03_url'); @@ -218,14 +241,15 @@ TeamUrlPage = React.createClass({ return ( <div> + <form> <img className="signup-team-logo" src="/static/images/logo.png" /> <h2>{utils.toTitleCase(strings.Team) + " URL"}</h2> <div className={ name_error ? "form-group has-error" : "form-group" }> <div className="row"> <div className="col-sm-9"> <div className="input-group"> - <input type="text" ref="name" className="form-control text-right" placeholder="" maxLength="128" defaultValue={this.props.state.team.domain} /> - <span className="input-group-addon">.{ utils.getDomainWithOutSub() }</span> + <span className="input-group-addon">{ window.location.origin + "/" }</span> + <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" defaultValue={this.props.state.team.name} autoFocus={true} onFocus={this.handleFocus}/> </div> </div> </div> @@ -233,8 +257,9 @@ TeamUrlPage = React.createClass({ </div> <p className="black">{"Pick something short and memorable for your " + strings.Team + "'s web address."}</p> <p>{"Your " + strings.Team + " URL can only contain lowercase letters, numbers and dashes. Also, it needs to start with a letter and cannot end in a dash."}</p> - <button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> - <button className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> + <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + </form> </div> ); } @@ -291,6 +316,7 @@ AllowedDomainsPage = React.createClass({ return ( <div> + <form> <img className="signup-team-logo" src="/static/images/logo.png" /> <h2>Email Domain</h2> <p> @@ -303,7 +329,7 @@ AllowedDomainsPage = React.createClass({ <div className="col-sm-9"> <div className="input-group"> <span className="input-group-addon">@</span> - <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" defaultValue={this.props.state.team.allowed_domains} /> + <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" defaultValue={this.props.state.team.allowed_domains} autoFocus={true} onFocus={this.handleFocus}/> </div> </div> </div> @@ -313,8 +339,9 @@ AllowedDomainsPage = React.createClass({ <p> <div className="checkbox"><label><input type="checkbox" ref="open_network" defaultChecked={this.props.state.team.type == 'O'} /> Allow anyone to signup to this domain without an invitation.</label></div> </p> - <button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> - <button className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> + <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + </form> </div> ); } @@ -356,7 +383,7 @@ EmailItem = React.createClass({ return ( <div className={ email_error ? "form-group has-error" : "form-group" }> - <input type="email" ref="email" className="form-control" placeholder="Email Address" defaultValue={this.props.email} maxLength="128" /> + <input autoFocus={this.props.focus} type="email" ref="email" className="form-control" placeholder="Email Address" defaultValue={this.props.email} maxLength="128" /> { email_error } </div> ); @@ -424,16 +451,22 @@ SendInivtesPage = React.createClass({ var emails = []; for (var i = 0; i < this.props.state.invites.length; i++) { - emails.push(<EmailItem key={i} ref={'email_' + i} email={this.props.state.invites[i]} />); + if (i == 0) { + emails.push(<EmailItem focus={true} key={i} ref={'email_' + i} email={this.props.state.invites[i]} />); + } else { + emails.push(<EmailItem focus={false} key={i} ref={'email_' + i} email={this.props.state.invites[i]} />); + } } return ( <div> + <form> <img className="signup-team-logo" src="/static/images/logo.png" /> <h2>Send Invitations</h2> { emails } - <div className="form-group"><button className="btn-default btn" onClick={this.submitAddInvite}>Add Invitation</button></div> - <div className="form btn-default-group"><button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> <button className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button></div> + <div className="form-group"><button type="button" className="btn-default btn" onClick={this.submitAddInvite}>Add Invitation</button></div> + <div className="form btn-default-group"><button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button></div> + </form> <p>{"If you'd prefer, you can send invitations after you finish setting up the "+ strings.Team + "."}</p> <div><a href="#" onClick={this.submitSkip}>Skip this step</a></div> </div> @@ -477,20 +510,22 @@ UsernamePage = React.createClass({ return ( <div> + <form> <img className="signup-team-logo" src="/static/images/logo.png" /> <h2>Choose a username</h2> <div className={ name_error ? "form-group has-error" : "form-group" }> <div className="row"> <div className="col-sm-9"> - <input type="text" ref="name" className="form-control" placeholder="" defaultValue={this.props.state.user.username} maxLength="128" /> + <input autoFocus={true} type="text" ref="name" className="form-control" placeholder="" defaultValue={this.props.state.user.username} maxLength="128" /> </div> </div> { name_error } </div> <p>{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others."}</p> <p>It can be made of lowercase letters and numbers.</p> - <button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> - <button className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> + <button type="submit" className="btn-primary btn" onClick={this.submitNext}>Next<i className="glyphicon glyphicon-chevron-right"></i></button> + </form> </div> ); } @@ -531,18 +566,11 @@ PasswordPage = React.createClass({ props.state.wizard = "finished"; props.updateParent(props.state, true); - if (utils.isTestDomain()) { - UserStore.setLastDomain(teamSignup.team.domain); - UserStore.setLastEmail(teamSignup.team.email); - window.location.href = window.location.protocol + '//' + utils.getDomainWithOutSub() + '/login?email=' + encodeURIComponent(teamSignup.team.email); - } - else { - window.location.href = window.location.protocol + '//' + teamSignup.team.domain + '.' + utils.getDomainWithOutSub() + '/login?email=' + encodeURIComponent(teamSignup.team.email); - } + window.location.href = window.location.origin + '/' + props.state.team.name + '/login?email=' + encodeURIComponent(teamSignup.team.email); // client.loginByEmail(teamSignup.team.domain, teamSignup.team.email, teamSignup.user.password, // function(data) { - // UserStore.setLastDomain(teamSignup.team.domain); + // TeamStore.setLastName(teamSignup.team.domain); // UserStore.setLastEmail(teamSignup.team.email); // UserStore.setCurrentUser(data); // window.location.href = '/channels/town-square'; @@ -570,13 +598,14 @@ PasswordPage = React.createClass({ return ( <div> + <form> <img className="signup-team-logo" src="/static/images/logo.png" /> <h2>Choose a password</h2> <p>You'll use your email address ({this.props.state.team.email}) and password to log into {config.SiteName}.</p> <div className={ name_error ? "form-group has-error" : "form-group" }> <div className="row"> <div className="col-sm-9"> - <input type="password" ref="password" className="form-control" placeholder="" maxLength="128" /> + <input autoFocus={true} type="password" ref="password" className="form-control" placeholder="" maxLength="128" /> </div> </div> { name_error } @@ -585,10 +614,11 @@ PasswordPage = React.createClass({ <label><input type="checkbox" ref="email_service" /> It's ok to send me occassional email with updates about the {config.SiteName} service.</label> </div> <div className="form-group"> - <button className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> - <button className="btn-primary btn" id="finish-button" data-loading-text={"<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> Creating "+strings.Team+"..."} onClick={this.submitNext}>Finish</button> + <button type="button" className="btn btn-default" onClick={this.submitBack}><i className="glyphicon glyphicon-chevron-left"></i> Back</button> + <button type="submit" className="btn-primary btn" id="finish-button" data-loading-text={"<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> Creating "+strings.Team+"..."} onClick={this.submitNext}>Finish</button> </div> <p>By proceeding to create your account and use { config.SiteName }, you agree to our <a href={ config.TermsLink }>Terms of Service</a> and <a href={ config.PrivacyLink }>Privacy Policy</a>. If you do not agree, you cannot use {config.SiteName}.</p> + </form> </div> ); } @@ -610,9 +640,9 @@ module.exports = React.createClass({ props.wizard = "welcome"; props.team = {}; props.team.email = this.props.email; - props.team.name = this.props.name; + props.team.display_name = this.props.name; props.team.company_name = this.props.name; - props.team.domain = utils.cleanUpUrlable(this.props.name); + props.team.name = utils.cleanUpUrlable(this.props.name); props.team.allowed_domains = ""; props.invites = []; props.invites.push(""); @@ -630,12 +660,12 @@ module.exports = React.createClass({ return <WelcomePage state={this.state} updateParent={this.updateParent} /> } - if (this.state.wizard == "team_name") { - return <TeamNamePage state={this.state} updateParent={this.updateParent} /> + if (this.state.wizard == "team_display_name") { + return <TeamDisplayNamePage state={this.state} updateParent={this.updateParent} /> } if (this.state.wizard == "team_url") { - return <TeamUrlPage state={this.state} updateParent={this.updateParent} /> + return <TeamURLPage state={this.state} updateParent={this.updateParent} /> } if (this.state.wizard == "allowed_domains") { diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index d1053c778..eed323d1f 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -48,16 +48,17 @@ module.exports = React.createClass({ client.loginByEmail(this.props.domain, this.state.user.email, this.state.user.password, function(data) { - UserStore.setLastDomain(this.props.domain); UserStore.setLastEmail(this.state.user.email); UserStore.setCurrentUser(data); if (this.props.hash > 0) + { BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: "finished"})); - window.location.href = '/channels/town-square'; + } + window.location.href = '/'; }.bind(this), function(err) { if (err.message == "Login failed because email address has not been verified") { - window.location.href = "/verify?email="+ encodeURIComponent(this.state.user.email) + "&domain=" + encodeURIComponent(this.props.domain); + window.location.href = "/verify_email?email="+ encodeURIComponent(this.state.user.email) + "&domain=" + encodeURIComponent(this.props.domain); } else { this.state.server_error = err.message; this.setState(this.state); diff --git a/web/react/components/team_members.jsx b/web/react/components/team_members.jsx index 6b978f88b..616fd2c99 100644 --- a/web/react/components/team_members.jsx +++ b/web/react/components/team_members.jsx @@ -57,7 +57,7 @@ module.exports = React.createClass({ <div className="modal-content"> <div className="modal-header"> <button type="button" className="close" data-dismiss="modal" aria-label="Close" data-reactid=".5.0.0.0.0"><span aria-hidden="true" data-reactid=".5.0.0.0.0.0">×</span></button> - <h4 className="modal-title" id="myModalLabel">{this.props.teamName + " Members"}</h4> + <h4 className="modal-title" id="myModalLabel">{this.props.teamDisplayName + " Members"}</h4> </div> <div ref="modalBody" className="modal-body"> <div className="channel-settings"> diff --git a/web/react/pages/channel.jsx b/web/react/pages/channel.jsx index 3aa985863..f70d60e3a 100644 --- a/web/react/pages/channel.jsx +++ b/web/react/pages/channel.jsx @@ -61,17 +61,17 @@ global.window.setup_channel_page = function(team_name, team_type, team_id, chann ); React.render( - <Navbar teamName={team_name} />, + <Navbar teamDisplayName={team_name} />, document.getElementById('navbar') ); React.render( - <Sidebar teamName={team_name} teamType={team_type} />, + <Sidebar teamDisplayName={team_name} teamType={team_type} />, document.getElementById('sidebar-left') ); React.render( - <RenameTeamModal teamName={team_name} />, + <RenameTeamModal teamDisplayName={team_name} />, document.getElementById('rename_team_modal') ); @@ -91,7 +91,7 @@ global.window.setup_channel_page = function(team_name, team_type, team_id, chann ); React.render( - <TeamMembersModal teamName={team_name} />, + <TeamMembersModal teamDisplayName={team_name} />, document.getElementById('team_members_modal') ); @@ -186,7 +186,7 @@ global.window.setup_channel_page = function(team_name, team_type, team_id, chann ); React.render( - <SidebarRightMenu teamName={team_name} teamType={team_type} />, + <SidebarRightMenu teamDisplayName={team_name} teamType={team_type} />, document.getElementById('sidebar-menu') ); diff --git a/web/react/pages/home.jsx b/web/react/pages/home.jsx index 08dd32f73..b12fa4949 100644 --- a/web/react/pages/home.jsx +++ b/web/react/pages/home.jsx @@ -2,13 +2,14 @@ // 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'); -global.window.setup_home_page = function() { +global.window.setup_home_page = function(teamURL) { var last = ChannelStore.getLastVisitedName(); if (last == null || last.length === 0) { - window.location.replace("/channels/" + Constants.DEFAULT_CHANNEL); + window.location = teamURL + "/channels/" + Constants.DEFAULT_CHANNEL; } else { - window.location.replace("/channels/" + last); + window.location = teamURL + "/channels/" + last; } } diff --git a/web/react/pages/login.jsx b/web/react/pages/login.jsx index a4e6b438e..8348f0b5d 100644 --- a/web/react/pages/login.jsx +++ b/web/react/pages/login.jsx @@ -3,9 +3,9 @@ var Login = require('../components/login.jsx'); -global.window.setup_login_page = function() { +global.window.setup_login_page = function(teamDisplayName, teamName) { React.render( - <Login />, + <Login teamDisplayName={teamDisplayName} teamName={teamName}/>, document.getElementById('login') ); }; diff --git a/web/react/pages/password_reset.jsx b/web/react/pages/password_reset.jsx index 6d0d88a10..c7a208973 100644 --- a/web/react/pages/password_reset.jsx +++ b/web/react/pages/password_reset.jsx @@ -3,13 +3,13 @@ var PasswordReset = require('../components/password_reset.jsx'); -global.window.setup_password_reset_page = function(is_reset, team_name, domain, hash, data) { +global.window.setup_password_reset_page = function(is_reset, team_display_name, team_name, hash, data) { React.render( <PasswordReset isReset={is_reset} + teamDisplayName={team_display_name} teamName={team_name} - domain={domain} hash={hash} data={data} />, diff --git a/web/react/pages/signup_team_complete.jsx b/web/react/pages/signup_team_complete.jsx index c17cbdfac..346f2ab5a 100644 --- a/web/react/pages/signup_team_complete.jsx +++ b/web/react/pages/signup_team_complete.jsx @@ -5,7 +5,7 @@ var SignupTeamComplete =require('../components/signup_team_complete.jsx'); global.window.setup_signup_team_complete_page = function(email, name, data, hash) { React.render( - <SignupTeamComplete name={name} email={email} hash={hash} data={data} />, + <SignupTeamComplete name={name} email={email} hash={hash} data={data}/>, document.getElementById('signup-team-complete') ); -};
\ No newline at end of file +}; diff --git a/web/react/stores/browser_store.jsx b/web/react/stores/browser_store.jsx index 4d6eb0b8d..4eed754cc 100644 --- a/web/react/stores/browser_store.jsx +++ b/web/react/stores/browser_store.jsx @@ -8,7 +8,7 @@ function getPrefix() { } // Also change model/utils.go ETAG_ROOT_VERSION -var BROWSER_STORE_VERSION = '.3'; +var BROWSER_STORE_VERSION = '.4'; module.exports = { _initialized: false, diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx index e773bb688..5280bfe08 100644 --- a/web/react/stores/post_store.jsx +++ b/web/react/stores/post_store.jsx @@ -151,12 +151,12 @@ var PostStore = assign({}, EventEmitter.prototype, { return BrowserStore.getItem("draft_" + channel_id + "_" + user_id); }, clearDraftUploads: function() { - BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) { - if (value) { - value.uploadsInProgress = 0; - BrowserStore.setItem(key, value); - } - }); + BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) { + if (value) { + value.uploadsInProgress = 0; + BrowserStore.setItem(key, value); + } + }); } }); diff --git a/web/react/stores/team_store.jsx b/web/react/stores/team_store.jsx index b7199a4a8..3f12725f8 100644 --- a/web/react/stores/team_store.jsx +++ b/web/react/stores/team_store.jsx @@ -57,10 +57,13 @@ var TeamStore = assign({}, EventEmitter.prototype, { else return null; }, + getCurrentTeamUrl: function() { + return window.location.origin + "/" + this.getCurrent().name; + }, storeTeam: function(team) { - var teams = this._getTeams(); - teams[team.id] = team; - this._storeTeams(teams); + var teams = this._getTeams(); + teams[team.id] = team; + this._storeTeams(teams); }, _storeTeams: function(teams) { BrowserStore.setItem("user_teams", teams); diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx index b0ea719d4..d03016c5d 100644 --- a/web/react/stores/user_store.jsx +++ b/web/react/stores/user_store.jsx @@ -67,9 +67,18 @@ var UserStore = assign({}, EventEmitter.prototype, { }, setCurrentId: function(id) { this._current_id = id; + if (id == null) { + BrowserStore.removeGlobalItem("current_user_id"); + } else { + BrowserStore.setGlobalItem("current_user_id", id); + } }, getCurrentId: function(skipFetch) { - var current_id = this._current_id; + var current_id = this._current_id; + + if (current_id == null) { + current_id = BrowserStore.getGlobalItem("current_user_id"); + } // this is a speical case to force fetch the // current user if it's missing @@ -92,17 +101,11 @@ var UserStore = assign({}, EventEmitter.prototype, { return this._getProfiles()[this.getCurrentId()]; }, setCurrentUser: function(user) { - this.saveProfile(user); this.setCurrentId(user.id); - }, - getLastDomain: function() { - return BrowserStore.getItem("last_domain", ''); - }, - setLastDomain: function(domain) { - BrowserStore.setItem("last_domain", domain); + this.saveProfile(user); }, getLastEmail: function() { - return BrowserStore.getItem("last_email", ''); + return BrowserStore.getItem("last_email", ''); }, setLastEmail: function(email) { BrowserStore.setItem("last_email", email); @@ -144,18 +147,18 @@ var UserStore = assign({}, EventEmitter.prototype, { this._storeProfiles(ps); }, _storeProfiles: function(profiles) { - BrowserStore.setGlobalItem("profiles", profiles); + BrowserStore.setItem("profiles", profiles); var profileUsernameMap = {}; for (var id in profiles) { profileUsernameMap[profiles[id].username] = profiles[id]; } - BrowserStore.setGlobalItem("profileUsernameMap", profileUsernameMap); + BrowserStore.setItem("profileUsernameMap", profileUsernameMap); }, _getProfiles: function() { - return BrowserStore.getGlobalItem("profiles", {}); + return BrowserStore.getItem("profiles", {}); }, _getProfilesUsernameMap: function() { - return BrowserStore.getGlobalItem("profileUsernameMap", {}); + return BrowserStore.getItem("profileUsernameMap", {}); }, setSessions: function(sessions) { BrowserStore.setItem("sessions", sessions); diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx index 11d4c2601..1c31dc5ed 100644 --- a/web/react/utils/client.jsx +++ b/web/react/utils/client.jsx @@ -2,6 +2,7 @@ // See License.txt for license information. var BrowserStore = require('../stores/browser_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); module.exports.track = function(category, action, label, prop, val) { global.window.snowplow('trackStructEvent', category, action, label, prop, val); @@ -44,7 +45,12 @@ function handleError(method_name, xhr, status, err) { module.exports.track('api', 'api_weberror', method_name, 'message', msg); if (xhr.status == 401) { - window.location.href = '/login?redirect=' + encodeURIComponent(window.location.pathname+window.location.search); + if (window.location.href.indexOf("/channels") === 0) { + window.location.pathname = '/login?redirect=' + encodeURIComponent(window.location.pathname+window.location.search); + } else { + var teamURL = window.location.href.split('/channels')[0]; + window.location.href = teamURL + '/login?redirect=' + encodeURIComponent(window.location.pathname+window.location.search); + } } return e; @@ -205,17 +211,18 @@ module.exports.resetPassword = function(data, success, error) { module.exports.logout = function() { module.exports.track('api', 'api_users_logout'); - BrowserStore.clear(); - window.location.href = "/logout"; + var currentTeamUrl = TeamStore.getCurrentTeamUrl(); + BrowserStore.clear(); + window.location.href = currentTeamUrl + "/logout"; }; -module.exports.loginByEmail = function(domain, email, password, success, error) { +module.exports.loginByEmail = function(name, email, password, success, error) { $.ajax({ url: "/api/v1/users/login", dataType: 'json', contentType: 'application/json', type: 'POST', - data: JSON.stringify({domain: domain, email: email, password: password}), + data: JSON.stringify({name: name, email: email, password: password}), success: function(data, textStatus, xhr) { module.exports.track('api', 'api_users_login_success', data.team_id, 'email', data.email); success(data, textStatus, xhr); @@ -317,7 +324,7 @@ module.exports.inviteMembers = function(data, success, error) { module.exports.track('api', 'api_teams_invite_members'); }; -module.exports.updateTeamName = function(data, success, error) { +module.exports.updateTeamDisplayName = function(data, success, error) { $.ajax({ url: "/api/v1/teams/update_name", dataType: 'json', @@ -326,7 +333,7 @@ module.exports.updateTeamName = function(data, success, error) { data: JSON.stringify(data), success: success, error: function(xhr, status, err) { - e = handleError("updateTeamName", xhr, status, err); + e = handleError("updateTeamDisplayName", xhr, status, err); error(e); } }); @@ -334,13 +341,13 @@ module.exports.updateTeamName = function(data, success, error) { module.exports.track('api', 'api_teams_update_name'); }; -module.exports.signupTeam = function(email, name, success, error) { +module.exports.signupTeam = function(email, display_name, success, error) { $.ajax({ url: "/api/v1/teams/signup", dataType: 'json', contentType: 'application/json', type: 'POST', - data: JSON.stringify({email: email, name: name}), + data: JSON.stringify({email: email, display_name: display_name}), success: success, error: function(xhr, status, err) { e = handleError("singupTeam", xhr, status, err); @@ -366,16 +373,16 @@ module.exports.createTeam = function(team, success, error) { }); }; -module.exports.findTeamByDomain = function(domain, success, error) { +module.exports.findTeamByName = function(teamName, success, error) { $.ajax({ - url: "/api/v1/teams/find_team_by_domain", + url: "/api/v1/teams/find_team_by_name", dataType: 'json', contentType: 'application/json', type: 'POST', - data: JSON.stringify({domain: domain}), + data: JSON.stringify({name: teamName}), success: success, error: function(xhr, status, err) { - e = handleError("findTeamByDomain", xhr, status, err); + e = handleError("findTeamByName", xhr, status, err); error(e); } }); diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index 3aadfb4b0..187e3c4a3 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -54,7 +54,7 @@ module.exports = { DEFAULT_CHANNEL: 'town-square', OFFTOPIC_CHANNEL: 'off-topic', POST_CHUNK_SIZE: 60, - RESERVED_DOMAINS: [ + RESERVED_TEAM_NAMES: [ "www", "web", "admin", diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 416ea5ae4..00580af6e 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -16,10 +16,10 @@ module.exports.isEmail = function(email) { }; module.exports.cleanUpUrlable = function(input) { - var cleaned = input.trim().replace(/-/g, ' ').replace(/[^\w\s]/gi, '').toLowerCase().replace(/\s/g, '-'); - cleaned = cleaned.replace(/^\-+/, ''); - cleaned = cleaned.replace(/\-+$/, ''); - return cleaned; + var cleaned = input.trim().replace(/-/g, ' ').replace(/[^\w\s]/gi, '').toLowerCase().replace(/\s/g, '-'); + cleaned = cleaned.replace(/^\-+/, ''); + cleaned = cleaned.replace(/\-+$/, ''); + return cleaned; }; @@ -114,7 +114,7 @@ module.exports.notifyMe = function(title, body, channel) { if (channel) { module.exports.switchChannel(channel); } else { - window.location.href = "/channels/town-square"; + window.location.href = "/"; } }; setTimeout(function(){ @@ -708,8 +708,8 @@ module.exports.switchChannel = function(channel, teammate_name) { id: channel.id }); - var domain = window.location.href.split('/channels')[0]; - history.replaceState('data', '', domain + '/channels/' + channel.name); + var teamURL = window.location.href.split('/channels')[0]; + history.replaceState('data', '', teamURL + '/channels/' + channel.name); if (channel.type === 'D' && teammate_name) { document.title = teammate_name + " " + document.title.substring(document.title.lastIndexOf("-")); @@ -784,18 +784,6 @@ Image.prototype.load = function(url, progressCallback) { Image.prototype.completedPercentage = 0; -module.exports.getHomeLink = function() { - if (config.HomeLink != "") { - return config.HomeLink; - } - var parts = window.location.host.split("."); - if (parts.length <= 1) { - return window.location.protocol + "//" + window.location.host; - } - parts[0] = "www"; - return window.location.protocol + "//" + parts.join("."); -} - module.exports.changeColor =function(col, amt) { var usePound = false; diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss index c2740891a..adeaa70d7 100644 --- a/web/sass-files/sass/partials/_headers.scss +++ b/web/sass-files/sass/partials/_headers.scss @@ -98,6 +98,9 @@ fill: #fff; } } + .settings__link a:hover, a:visited, a:link, a:active { + text-decoration: none; + } .user__picture { width: 36px; height: 36px; @@ -248,4 +251,4 @@ margin-top: 8px; fill: #AAA; } -}
\ No newline at end of file +} diff --git a/web/sass-files/sass/partials/_signup.scss b/web/sass-files/sass/partials/_signup.scss index a714aa44f..98931279b 100644 --- a/web/sass-files/sass/partials/_signup.scss +++ b/web/sass-files/sass/partials/_signup.scss @@ -6,7 +6,7 @@ } .signup-team__container { padding: 100px 0px 50px 0px; - max-width: 340px; + max-width: 600px; margin: 0 auto; font-size: 1.1em; position: relative; @@ -118,4 +118,4 @@ .signup-team-login { padding-bottom: 10px; font-weight: 700; -}
\ No newline at end of file +} diff --git a/web/templates/channel.html b/web/templates/channel.html index d96aee3d4..eaf0f2563 100644 --- a/web/templates/channel.html +++ b/web/templates/channel.html @@ -46,7 +46,7 @@ <div id="direct_channel_modal"></div> <div id="channel_info_modal"></div> <script> -window.setup_channel_page('{{ .Props.TeamName }}', '{{ .Props.TeamType }}', '{{ .Props.TeamId }}', '{{ .Props.ChannelName }}', '{{ .Props.ChannelId }}'); +window.setup_channel_page('{{ .Props.TeamDisplayName }}', '{{ .Props.TeamType }}', '{{ .Props.TeamId }}', '{{ .Props.ChannelName }}', '{{ .Props.ChannelId }}'); </script> </body> </html> diff --git a/web/templates/home.html b/web/templates/home.html index abf8062f2..9ec8b7000 100644 --- a/web/templates/home.html +++ b/web/templates/home.html @@ -17,7 +17,7 @@ </div> </div> <script> - window.setup_home_page(); + window.setup_home_page({{.Props.TeamURL}}); </script> </body> </html> diff --git a/web/templates/login.html b/web/templates/login.html index c107e1ad5..24cebec8f 100644 --- a/web/templates/login.html +++ b/web/templates/login.html @@ -7,7 +7,7 @@ <div class="inner__wrap"> <div class="row content"> <div class="signup-header"> - {{.Props.TeamName}} + {{.Props.TeamDisplayName}} </div> <div class="col-sm-12"> <div id="login"></div> @@ -20,7 +20,7 @@ </div> </div> <script> - window.setup_login_page(); +window.setup_login_page({{.Props.TeamDisplayName}}, {{.Props.TeamName}}); </script> </body> </html> diff --git a/web/templates/password_reset.html b/web/templates/password_reset.html index 8b63556b1..6244f6418 100644 --- a/web/templates/password_reset.html +++ b/web/templates/password_reset.html @@ -9,7 +9,7 @@ </div> </div> <script> - window.setup_password_reset_page('{{ .Props.IsReset }}', '{{ .Props.TeamName }}', '{{ .Props.Domain }}', '{{ .Props.Hash }}', '{{ .Props.Data }}'); + window.setup_password_reset_page('{{ .Props.IsReset }}', '{{ .Props.TeamDisplayName }}', '{{ .Props.TeamName }}', '{{ .Props.Hash }}', '{{ .Props.Data }}'); </script> </body> </html> diff --git a/web/templates/signup_team.html b/web/templates/signup_team.html index fad332bee..b86590589 100644 --- a/web/templates/signup_team.html +++ b/web/templates/signup_team.html @@ -12,7 +12,6 @@ <h2>All team communication in one place, searchable and accessible anywhere</h2> <h4 class="text--light">{{ .SiteName }} is free for an unlimited time, for unlimited users </h4 class="text--light"> <div id="signup-team"></div> - <a class="signup-team-login" href="/login">or Sign In</a> </div> </div> <div class="footer-push"></div> @@ -23,7 +22,7 @@ </div> </div> <script> - window.setup_signup_team_page(); +window.setup_signup_team_page(); </script> </body> </html> diff --git a/web/templates/signup_team_complete.html b/web/templates/signup_team_complete.html index 59f49cdbd..674e54ee2 100644 --- a/web/templates/signup_team_complete.html +++ b/web/templates/signup_team_complete.html @@ -19,7 +19,7 @@ </div> </div> <script> - window.setup_signup_team_complete_page('{{.Props.Email}}', '{{.Props.Name}}', '{{.Props.Data}}', '{{.Props.Hash}}'); +window.setup_signup_team_complete_page('{{.Props.Email}}', '{{.Props.DisplayName}}', '{{.Props.Data}}', '{{.Props.Hash}}'); </script> </body> </html> diff --git a/web/templates/signup_team_confirm.html b/web/templates/signup_team_confirm.html index 9e21126da..3a6134af3 100644 --- a/web/templates/signup_team_confirm.html +++ b/web/templates/signup_team_confirm.html @@ -8,7 +8,6 @@ <div class="row content"> <div class="col-sm-12"> <div class="signup-team__container"> - <p>Did you mean to sign-in rather than sign up? Sign in <a href="/login">here</a>. </p> <h3>Sign up Complete</h3> <p>Please check your email: {{ .Props.Email }}<br> You email contains a link to set up your team</p> diff --git a/web/templates/signup_user_complete.html b/web/templates/signup_user_complete.html index 5fe907ba7..0cc655b63 100644 --- a/web/templates/signup_user_complete.html +++ b/web/templates/signup_user_complete.html @@ -19,7 +19,7 @@ </div> </div> <script> - window.setup_signup_user_complete_page('{{.Props.Email}}', '{{.Props.TeamDomain}}', '{{.Props.TeamName}}', '{{.Props.TeamId}}', '{{.Props.Data}}', '{{.Props.Hash}}'); + window.setup_signup_user_complete_page('{{.Props.Email}}', '{{.Props.TeamName}}', '{{.Props.TeamDisplayName}}', '{{.Props.TeamId}}', '{{.Props.Data}}', '{{.Props.Hash}}'); </script> </body> </html> diff --git a/web/web.go b/web/web.go index b11e6e6b1..3e4bc2d53 100644 --- a/web/web.go +++ b/web/web.go @@ -42,25 +42,28 @@ func (me *HtmlTemplatePage) Render(c *api.Context, w http.ResponseWriter) { func InitWeb() { l4g.Debug("Initializing web routes") + mainrouter := api.Srv.Router + staticDir := utils.FindDir("web/static") l4g.Debug("Using static directory at %v", staticDir) - api.Srv.Router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", - http.FileServer(http.Dir(staticDir)))) - - api.Srv.Router.Handle("/", api.AppHandler(root)).Methods("GET") - api.Srv.Router.Handle("/login", api.AppHandler(login)).Methods("GET") - api.Srv.Router.Handle("/signup_team_confirm/", api.AppHandler(signupTeamConfirm)).Methods("GET") - api.Srv.Router.Handle("/signup_team_complete/", api.AppHandler(signupTeamComplete)).Methods("GET") - api.Srv.Router.Handle("/signup_user_complete/", api.AppHandler(signupUserComplete)).Methods("GET") - - api.Srv.Router.Handle("/logout", api.AppHandler(logout)).Methods("GET") - - api.Srv.Router.Handle("/verify", api.AppHandler(verifyEmail)).Methods("GET") - api.Srv.Router.Handle("/find_team", api.AppHandler(findTeam)).Methods("GET") - api.Srv.Router.Handle("/reset_password", api.AppHandler(resetPassword)).Methods("GET") - - csr := api.Srv.Router.PathPrefix("/channels").Subrouter() - csr.Handle("/{name:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}", api.UserRequired(getChannel)).Methods("GET") + mainrouter.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))) + + mainrouter.Handle("/", api.AppHandlerIndependent(root)).Methods("GET") + mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}", api.AppHandler(login)).Methods("GET") + mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/", api.AppHandler(login)).Methods("GET") + mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/login", api.AppHandler(login)).Methods("GET") + mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/logout", api.AppHandler(logout)).Methods("GET") + mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/reset_password", api.AppHandler(resetPassword)).Methods("GET") + // Bug in gorilla.mux pervents us from using regex here. + mainrouter.Handle("/{team}/channels/{channelname}", api.UserRequired(getChannel)).Methods("GET") + + // Anything added here must have an _ in it so it does not conflict with team names + mainrouter.Handle("/signup_team_complete/", api.AppHandlerIndependent(signupTeamComplete)).Methods("GET") + mainrouter.Handle("/signup_user_complete/", api.AppHandlerIndependent(signupUserComplete)).Methods("GET") + mainrouter.Handle("/signup_team_confirm/", api.AppHandlerIndependent(signupTeamConfirm)).Methods("GET") + mainrouter.Handle("/verify_email", api.AppHandlerIndependent(verifyEmail)).Methods("GET") + mainrouter.Handle("/find_team", api.AppHandlerIndependent(findTeam)).Methods("GET") + mainrouter.Handle("/signup_team", api.AppHandlerIndependent(signup)).Methods("GET") watchAndParseTemplates() } @@ -128,46 +131,53 @@ func root(c *api.Context, w http.ResponseWriter, r *http.Request) { } if len(c.Session.UserId) == 0 { - if api.IsTestDomain(r) || strings.Index(r.Host, "www") == 0 || strings.Index(r.Host, "beta") == 0 || strings.Index(r.Host, "ci") == 0 { - page := NewHtmlTemplatePage("signup_team", "Signup") - page.Render(c, w) - } else { - login(c, w, r) - } + page := NewHtmlTemplatePage("signup_team", "Signup") + page.Render(c, w) } else { page := NewHtmlTemplatePage("home", "Home") + page.Props["TeamURL"] = c.GetTeamURL() page.Render(c, w) } } -func login(c *api.Context, w http.ResponseWriter, r *http.Request) { +func signup(c *api.Context, w http.ResponseWriter, r *http.Request) { + if !CheckBrowserCompatability(c, r) { return } - teamName := "Beta" - teamDomain := "" - siteDomain := "." + utils.Cfg.ServiceSettings.Domain + page := NewHtmlTemplatePage("signup_team", "Signup") + page.Render(c, w) +} + +func login(c *api.Context, w http.ResponseWriter, r *http.Request) { + if !CheckBrowserCompatability(c, r) { + return + } + params := mux.Vars(r) + teamName := params["team"] - if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV { - teamDomain = "developer" - } else if utils.Cfg.ServiceSettings.Mode == utils.MODE_BETA { - teamDomain = "beta" + 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) + // This should probably do somthing nicer + http.Redirect(w, r, "http://"+r.Host, http.StatusTemporaryRedirect) + return } else { - teamDomain, siteDomain = model.GetSubDomain(c.TeamUrl) - siteDomain = "." + siteDomain + ".com" + team = tResult.Data.(*model.Team) + } - if tResult := <-api.Srv.Store.Team().GetByDomain(teamDomain); tResult.Err != nil { - l4g.Error("Couldn't find team teamDomain=%v, siteDomain=%v, teamUrl=%v, err=%v", teamDomain, siteDomain, c.TeamUrl, tResult.Err.Message) - } else { - teamName = tResult.Data.(*model.Team).Name - } + // If we are already logged into this team then go to home + if len(c.Session.UserId) != 0 && c.Session.TeamId == team.Id { + page := NewHtmlTemplatePage("home", "Home") + page.Props["TeamURL"] = c.GetTeamURL() + page.Render(c, w) + return } page := NewHtmlTemplatePage("login", "Login") + page.Props["TeamDisplayName"] = team.DisplayName page.Props["TeamName"] = teamName - page.Props["TeamDomain"] = teamDomain - page.Props["SiteDomain"] = siteDomain page.Render(c, w) } @@ -198,7 +208,7 @@ func signupTeamComplete(c *api.Context, w http.ResponseWriter, r *http.Request) page := NewHtmlTemplatePage("signup_team_complete", "Complete Team Sign Up") page.Props["Email"] = props["email"] - page.Props["Name"] = props["name"] + page.Props["DisplayName"] = props["display_name"] page.Props["Data"] = data page.Props["Hash"] = hash page.Render(c, w) @@ -225,8 +235,8 @@ func signupUserComplete(c *api.Context, w http.ResponseWriter, r *http.Request) } props["email"] = "" + props["display_name"] = team.DisplayName props["name"] = team.Name - props["domain"] = team.Domain props["id"] = team.Id data = model.MapToJson(props) hash = "" @@ -249,8 +259,8 @@ func signupUserComplete(c *api.Context, w http.ResponseWriter, r *http.Request) page := NewHtmlTemplatePage("signup_user_complete", "Complete User Sign Up") page.Props["Email"] = props["email"] + page.Props["TeamDisplayName"] = props["display_name"] page.Props["TeamName"] = props["name"] - page.Props["TeamDomain"] = props["domain"] page.Props["TeamId"] = props["id"] page.Props["Data"] = data page.Props["Hash"] = hash @@ -259,12 +269,12 @@ 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, "/", http.StatusFound) + http.Redirect(w, r, c.GetTeamURL(), http.StatusFound) } func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) - name := params["name"] + name := params["channelname"] var channelId string if result := <-api.Srv.Store.Channel().CheckPermissionsToByName(c.Session.TeamId, name, c.Session.UserId); result.Err != nil { @@ -304,7 +314,7 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { //api.Handle404(w, r) //Bad channel urls just redirect to the town-square for now - http.Redirect(w, r, "/channels/town-square", http.StatusFound) + http.Redirect(w, r, c.GetTeamURL()+"/channels/town-square", http.StatusFound) return } } @@ -319,8 +329,8 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { } page := NewHtmlTemplatePage("channel", "") - page.Title = name + " - " + team.Name + " " + page.SiteName - page.Props["TeamName"] = team.Name + page.Title = name + " - " + team.DisplayName + " " + page.SiteName + page.Props["TeamDisplayName"] = team.DisplayName page.Props["TeamType"] = team.Type page.Props["TeamId"] = team.Id page.Props["ChannelName"] = name @@ -331,7 +341,7 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { resend := r.URL.Query().Get("resend") - domain := r.URL.Query().Get("domain") + name := r.URL.Query().Get("name") email := r.URL.Query().Get("email") hashedId := r.URL.Query().Get("hid") userId := r.URL.Query().Get("uid") @@ -339,7 +349,7 @@ func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { if resend == "true" { teamId := "" - if result := <-api.Srv.Store.Team().GetByDomain(domain); result.Err != nil { + if result := <-api.Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { @@ -351,7 +361,7 @@ func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { return } else { user := result.Data.(*model.User) - api.FireAndForgetVerifyEmail(user.Id, user.FirstName, user.Email, domain, c.TeamUrl) + api.FireAndForgetVerifyEmail(user.Id, strings.Split(user.Nickname, " ")[0], user.Email, name, c.GetTeamURL()) http.Redirect(w, r, "/", http.StatusFound) return } @@ -387,6 +397,8 @@ func resetPassword(c *api.Context, w http.ResponseWriter, r *http.Request) { isResetLink := true hash := r.URL.Query().Get("h") data := r.URL.Query().Get("d") + params := mux.Vars(r) + teamName := params["team"] if len(hash) == 0 || len(data) == 0 { isResetLink = false @@ -405,30 +417,25 @@ func resetPassword(c *api.Context, w http.ResponseWriter, r *http.Request) { } } - teamName := "Developer/Beta" - domain := "" - if utils.Cfg.ServiceSettings.Mode != utils.MODE_DEV { - domain, _ = model.GetSubDomain(c.TeamUrl) - - var team *model.Team - if tResult := <-api.Srv.Store.Team().GetByDomain(domain); tResult.Err != nil { - c.Err = tResult.Err - return - } else { - team = tResult.Data.(*model.Team) - } + teamDisplayName := "Developer/Beta" + var team *model.Team + if tResult := <-api.Srv.Store.Team().GetByName(teamName); tResult.Err != nil { + c.Err = tResult.Err + return + } else { + team = tResult.Data.(*model.Team) + } - if team != nil { - teamName = team.Name - } + if team != nil { + teamDisplayName = team.DisplayName } page := NewHtmlTemplatePage("password_reset", "") page.Title = "Reset Password - " + page.SiteName - page.Props["TeamName"] = teamName + page.Props["TeamDisplayName"] = teamDisplayName page.Props["Hash"] = hash page.Props["Data"] = data - page.Props["Domain"] = domain + page.Props["TeamName"] = teamName page.Props["IsReset"] = strconv.FormatBool(isResetLink) page.Render(c, w) } |