summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2015-07-05 09:02:23 -0800
committer=Corey Hulen <corey@hulen.com>2015-07-05 09:02:23 -0800
commit592d68cf4134b668e3ff962d17f8aa75b1bc055f (patch)
tree6e743b07487caf5fe350439aefdf0355a7e80d9b /api
parent72bfc1ee2afd2fa4a34186b62f144f8f6c50d693 (diff)
parent4a3003c0dcf7d642f233493e32b07beed5d08327 (diff)
downloadchat-592d68cf4134b668e3ff962d17f8aa75b1bc055f.tar.gz
chat-592d68cf4134b668e3ff962d17f8aa75b1bc055f.tar.bz2
chat-592d68cf4134b668e3ff962d17f8aa75b1bc055f.zip
Merge branch 'master' into mm-1391
Diffstat (limited to 'api')
-rw-r--r--api/channel.go59
-rw-r--r--api/channel_test.go23
-rw-r--r--api/command.go2
-rw-r--r--api/command_test.go2
-rw-r--r--api/post.go16
-rw-r--r--api/team.go21
-rw-r--r--api/team_test.go16
-rw-r--r--api/templates/error.html2
-rw-r--r--api/templates/invite_body.html2
-rw-r--r--api/templates/post_body.html2
-rw-r--r--api/user.go15
-rw-r--r--api/web_socket_test.go2
12 files changed, 122 insertions, 40 deletions
diff --git a/api/channel.go b/api/channel.go
index d3f6ca2de..c0c2d1548 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -57,7 +57,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if sc, err := CreateChannel(c, channel, r.URL.Path, true); err != nil {
+ if sc, err := CreateChannel(c, channel, true); err != nil {
c.Err = err
return
} else {
@@ -65,7 +65,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func CreateChannel(c *Context, channel *model.Channel, path string, addMember bool) (*model.Channel, *model.AppError) {
+func CreateChannel(c *Context, channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) {
if result := <-Srv.Store.Channel().Save(channel); result.Err != nil {
return nil, result.Err
} else {
@@ -100,7 +100,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if sc, err := CreateDirectChannel(c, userId, r.URL.Path); err != nil {
+ if sc, err := CreateDirectChannel(c, userId); err != nil {
c.Err = err
return
} else {
@@ -108,7 +108,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func CreateDirectChannel(c *Context, otherUserId string, path string) (*model.Channel, *model.AppError) {
+func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model.AppError) {
if len(otherUserId) != 26 {
return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
}
@@ -132,7 +132,7 @@ func CreateDirectChannel(c *Context, otherUserId string, path string) (*model.Ch
return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
}
- if sc, err := CreateChannel(c, channel, path, true); err != nil {
+ if sc, err := CreateChannel(c, channel, true); err != nil {
return nil, err
} else {
cm := &model.ChannelMember{ChannelId: sc.Id, UserId: otherUserId,
@@ -146,6 +146,23 @@ func CreateDirectChannel(c *Context, otherUserId string, path string) (*model.Ch
}
}
+func CreateDefaultChannels(c *Context, teamId string) ([]*model.Channel, *model.AppError) {
+ townSquare := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: teamId}
+
+ if _, err := CreateChannel(c, townSquare, false); err != nil {
+ return nil, err
+ }
+
+ offTopic := &model.Channel{DisplayName: "Off-Topic", Name: "off-topic", Type: model.CHANNEL_OPEN, TeamId: teamId}
+
+ if _, err := CreateChannel(c, offTopic, false); err != nil {
+ return nil, err
+ }
+
+ channels := []*model.Channel{townSquare, offTopic}
+ return channels, nil
+}
+
func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel := model.ChannelFromJson(r.Body)
@@ -303,7 +320,7 @@ func joinChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
channelId := params["id"]
- JoinChannel(c, channelId, r.URL.Path)
+ JoinChannel(c, channelId, "")
if c.Err != nil {
return
@@ -314,7 +331,7 @@ func joinChannel(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(result)))
}
-func JoinChannel(c *Context, channelId string, path string) {
+func JoinChannel(c *Context, channelId string, role string) {
sc := Srv.Store.Channel().Get(channelId)
uc := Srv.Store.User().Get(c.Session.UserId)
@@ -340,7 +357,7 @@ func JoinChannel(c *Context, channelId string, path string) {
}
if channel.Type == model.CHANNEL_OPEN {
- cm := &model.ChannelMember{ChannelId: channel.Id, UserId: c.Session.UserId, NotifyLevel: model.CHANNEL_NOTIFY_ALL}
+ cm := &model.ChannelMember{ChannelId: channel.Id, UserId: c.Session.UserId, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: role}
if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
c.Err = cmresult.Err
@@ -363,6 +380,32 @@ func JoinChannel(c *Context, channelId string, path string) {
}
}
+func JoinDefaultChannels(c *Context, user *model.User, channelRole string) *model.AppError {
+ // We don't call JoinChannel here since c.Session is not populated on user creation
+
+ var err *model.AppError = nil
+
+ if result := <-Srv.Store.Channel().GetByName(user.TeamId, "town-square"); result.Err != nil {
+ err = result.Err
+ } else {
+ cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: channelRole}
+ if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
+ err = cmResult.Err
+ }
+ }
+
+ if result := <-Srv.Store.Channel().GetByName(user.TeamId, "off-topic"); result.Err != nil {
+ err = result.Err
+ } else {
+ cm := &model.ChannelMember{ChannelId: result.Data.(*model.Channel).Id, UserId: user.Id, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: channelRole}
+ if cmResult := <-Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
+ err = cmResult.Err
+ }
+ }
+
+ return err
+}
+
func leaveChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
diff --git a/api/channel_test.go b/api/channel_test.go
index e8aaf4e3f..dfae840dc 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -35,8 +35,15 @@ func TestCreateChannel(t *testing.T) {
}
rget := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
- if rget.Channels[0].Name != channel.Name {
- t.Fatal("full name didn't match")
+ nameMatch := false
+ for _, c := range rget.Channels {
+ if c.Name == channel.Name {
+ nameMatch = true
+ }
+ }
+
+ if !nameMatch {
+ t.Fatal("Did not create channel with correct name")
}
if _, err := Client.CreateChannel(rchannel.Data.(*model.Channel)); err == nil {
@@ -679,6 +686,8 @@ func TestUpdateNotifyLevel(t *testing.T) {
data["user_id"] = user.Id
data["notify_level"] = model.CHANNEL_NOTIFY_MENTION
+ timeBeforeUpdate := model.GetMillis()
+
if _, err := Client.UpdateNotifyLevel(data); err != nil {
t.Fatal(err)
}
@@ -689,6 +698,10 @@ func TestUpdateNotifyLevel(t *testing.T) {
t.Fatal("NotifyLevel did not update properly")
}
+ if rdata.Members[channel1.Id].LastUpdateAt <= timeBeforeUpdate {
+ t.Fatal("LastUpdateAt did not update")
+ }
+
data["user_id"] = "junk"
if _, err := Client.UpdateNotifyLevel(data); err == nil {
t.Fatal("Should have errored - bad user id")
@@ -735,7 +748,7 @@ func TestUpdateNotifyLevel(t *testing.T) {
}
func TestFuzzyChannel(t *testing.T) {
- Setup();
+ Setup()
team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
@@ -747,9 +760,9 @@ func TestFuzzyChannel(t *testing.T) {
Client.LoginByEmail(team.Domain, user.Email, "pwd")
// Strings that should pass as acceptable channel names
- var fuzzyStringsPass = []string {
+ var fuzzyStringsPass = []string{
"*", "?", ".", "}{][)(><", "{}[]()<>",
-
+
"qahwah ( قهوة)",
"שָׁלוֹם עֲלֵיכֶם",
"Ramen チャーシュー chāshū",
diff --git a/api/command.go b/api/command.go
index aedbe07cc..810a8a07e 100644
--- a/api/command.go
+++ b/api/command.go
@@ -197,7 +197,7 @@ func joinCommand(c *Context, command *model.Command) bool {
return false
}
- JoinChannel(c, v.Id, "/command")
+ JoinChannel(c, v.Id, "")
if c.Err != nil {
return false
diff --git a/api/command_test.go b/api/command_test.go
index d3b0da455..5b7734628 100644
--- a/api/command_test.go
+++ b/api/command_test.go
@@ -129,7 +129,7 @@ func TestJoinCommands(t *testing.T) {
c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
- if len(c1.Channels) != 3 { // 3 because of town-square and direct
+ if len(c1.Channels) != 4 { // 4 because of town-square, off-topic and direct
t.Fatal("didn't join channel")
}
diff --git a/api/post.go b/api/post.go
index 99cbdcb85..650f47062 100644
--- a/api/post.go
+++ b/api/post.go
@@ -227,7 +227,7 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) {
channel = result.Data.(*model.Channel)
if channel.Type == model.CHANNEL_DIRECT {
bodyText = "You have one new message."
- subjectText = "New Direct Message"
+ subjectText = "New Private Message"
} else {
bodyText = "You have one new mention."
subjectText = "New Mention"
@@ -273,7 +273,7 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) {
} else {
- // Find out who is a member of the channel only keep those profiles
+ // Find out who is a member of the channel, only keep those profiles
if eResult := <-echan; eResult.Err != nil {
l4g.Error("Failed to get channel members channel_id=%v err=%v", post.ChannelId, eResult.Err.Message)
return
@@ -306,13 +306,23 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) {
}
}
}
+
+ // Add @all to keywords if user has them turned on
+ if profile.NotifyProps["all"] == "true" {
+ keywordMap["@all"] = append(keywordMap["@all"], profile.Id)
+ }
+
+ // Add @channel to keywords if user has them turned on
+ if profile.NotifyProps["channel"] == "true" {
+ keywordMap["@channel"] = append(keywordMap["@channel"], profile.Id)
+ }
}
// Build a map as a list of unique user_ids that are mentioned in this post
splitF := func(c rune) bool {
return model.SplitRunes[c]
}
- splitMessage := strings.FieldsFunc(strings.Replace(post.Message, "<br>", " ", -1), splitF)
+ splitMessage := strings.FieldsFunc(post.Message, splitF)
for _, word := range splitMessage {
// Non-case-sensitive check for regular keys
diff --git a/api/team.go b/api/team.go
index 775bc29ae..15e4e2c17 100644
--- a/api/team.go
+++ b/api/team.go
@@ -146,10 +146,8 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
rteam := result.Data.(*model.Team)
- channel := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: rteam.Id}
-
- if _, err := CreateChannel(c, channel, r.URL.Path, false); err != nil {
- c.Err = err
+ if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
+ c.Err = nil
return
}
@@ -197,10 +195,8 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
rteam := result.Data.(*model.Team)
- channel := &model.Channel{DisplayName: "Town Square", Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: rteam.Id}
-
- if _, err := CreateChannel(c, channel, r.URL.Path, false); err != nil {
- c.Err = err
+ if _, err := CreateDefaultChannels(c, rteam.Id); err != nil {
+ c.Err = nil
return
}
@@ -488,12 +484,21 @@ func InviteMembers(team *model.Team, user *model.User, invites []string) {
} else {
sender = user.FullName
}
+
+ senderRole := ""
+ if strings.Contains(user.Roles, model.ROLE_ADMIN) || strings.Contains(user.Roles, model.ROLE_SYSTEM_ADMIN) {
+ senderRole = "administrator"
+ } else {
+ senderRole = "member"
+ }
+
subjectPage := NewServerTemplatePage("invite_subject", teamUrl)
subjectPage.Props["SenderName"] = sender
subjectPage.Props["TeamName"] = team.Name
bodyPage := NewServerTemplatePage("invite_body", teamUrl)
bodyPage.Props["TeamName"] = team.Name
bodyPage.Props["SenderName"] = sender
+ bodyPage.Props["SenderStatus"] = senderRole
bodyPage.Props["Email"] = invite
diff --git a/api/team_test.go b/api/team_test.go
index 042c0a2e9..bb77d43a0 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -55,6 +55,11 @@ func TestCreateFromSignupTeam(t *testing.T) {
}
}
+ c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
+ if len(c1.Channels) != 2 {
+ t.Fatal("default channels not created")
+ }
+
ts.Data = "garbage"
_, err = Client.CreateTeamFromSignup(&ts)
if err == nil {
@@ -71,6 +76,17 @@ func TestCreateTeam(t *testing.T) {
t.Fatal(err)
}
+ user := &model.User{TeamId: rteam.Data.(*model.Team).Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
+ user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
+ Srv.Store.User().VerifyEmail(user.Id)
+
+ Client.LoginByEmail(team.Domain, user.Email, "pwd")
+
+ c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
+ if len(c1.Channels) != 2 {
+ t.Fatal("default channels not created")
+ }
+
if rteam.Data.(*model.Team).Name != team.Name {
t.Fatal("full name didn't match")
}
diff --git a/api/templates/error.html b/api/templates/error.html
index ab4d91378..f38bb81a1 100644
--- a/api/templates/error.html
+++ b/api/templates/error.html
@@ -5,7 +5,7 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
- <link href='https://fonts.googleapis.com/css?family=Lato:400,700,900' rel='stylesheet' type='text/css'>
+ <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body class="white error">
diff --git a/api/templates/invite_body.html b/api/templates/invite_body.html
index 06f48759c..8be2ac0df 100644
--- a/api/templates/invite_body.html
+++ b/api/templates/invite_body.html
@@ -18,7 +18,7 @@
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
<h2 style="font-weight: normal; margin-top: 10px;">You've been invited</h2>
- <p>{{.Props.TeamName}} started using {{.SiteName}}.<br> The team administrator <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamName}}</strong>.</p>
+ <p>{{.Props.TeamName}} started using {{.SiteName}}.<br> The team {{.Props.SenderStatus}} <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamName}}</strong>.</p>
<p style="margin: 20px 0 15px">
<a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Join Team</a>
</p>
diff --git a/api/templates/post_body.html b/api/templates/post_body.html
index 663ec66d2..069cdf1fb 100644
--- a/api/templates/post_body.html
+++ b/api/templates/post_body.html
@@ -20,7 +20,7 @@
<h2 style="font-weight: normal; margin-top: 10px;">You were mentioned</h2>
<p>CHANNEL: {{.Props.ChannelName}}<br>{{.Props.SenderName}} - {{.Props.Hour}}:{{.Props.Minute}} GMT, {{.Props.Month}} {{.Props.Day}}<br><pre style="text-align:left;font-family: 'Lato', sans-serif;">{{.Props.PostMessage}}</pre></p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.TeamLink}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Go To Channel</a>
+ <a href="{{.Props.TeamLink}}" style="background: #2389D7; display: inline-block; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 170px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Go To Channel</a>
</p>
</td>
</tr>
diff --git a/api/user.go b/api/user.go
index f8382cf2f..292d2b61b 100644
--- a/api/user.go
+++ b/api/user.go
@@ -176,21 +176,16 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
} else {
ruser := result.Data.(*model.User)
- // Do not error if user cannot be added to the town-square channel
- if cresult := <-Srv.Store.Channel().GetByName(team.Id, "town-square"); cresult.Err != nil {
- l4g.Error("Failed to get town-square err=%v", cresult.Err)
- } else {
- cm := &model.ChannelMember{ChannelId: cresult.Data.(*model.Channel).Id, UserId: ruser.Id, NotifyLevel: model.CHANNEL_NOTIFY_ALL, Roles: channelRole}
- if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
- l4g.Error("Failed to add member town-square err=%v", cmresult.Err)
- }
+ // Soft error if there is an issue joining the default channels
+ if err := JoinDefaultChannels(c, ruser, channelRole); err != nil {
+ l4g.Error("Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v", ruser.Id, ruser.TeamId, err)
}
//fireAndForgetWelcomeEmail(strings.Split(ruser.FullName, " ")[0], ruser.Email, team.Name, c.TeamUrl+"/channels/town-square")
if user.EmailVerified {
if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- l4g.Error("Failed to get town-square err=%v", cresult.Err)
+ l4g.Error("Failed to set email verified err=%v", cresult.Err)
}
} else {
FireAndForgetVerifyEmail(result.Data.(*model.User).Id, strings.Split(ruser.FullName, " ")[0], ruser.Email, team.Name, c.TeamUrl)
@@ -198,7 +193,7 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
ruser.Sanitize(map[string]bool{})
- //This message goes to every channel, so the channelId is irrelevant
+ // This message goes to every channel, so the channelId is irrelevant
message := model.NewMessage(team.Id, "", ruser.Id, model.ACTION_NEW_USER)
store.PublishAndForget(message)
diff --git a/api/web_socket_test.go b/api/web_socket_test.go
index c7b612cde..15bc3baeb 100644
--- a/api/web_socket_test.go
+++ b/api/web_socket_test.go
@@ -119,7 +119,7 @@ func TestSocket(t *testing.T) {
}
-func TestZZWebScoketTearDown(t *testing.T) {
+func TestZZWebSocketTearDown(t *testing.T) {
// *IMPORTANT* - Kind of hacky
// This should be the last function in any test file
// that calls Setup()