diff options
-rw-r--r-- | api/channel.go | 9 | ||||
-rw-r--r-- | api/user.go | 32 | ||||
-rw-r--r-- | api/user_test.go | 31 | ||||
-rw-r--r-- | model/preference.go | 3 | ||||
-rw-r--r-- | web/web.go | 12 |
5 files changed, 78 insertions, 9 deletions
diff --git a/api/channel.go b/api/channel.go index f17594c0a..b85de3071 100644 --- a/api/channel.go +++ b/api/channel.go @@ -679,6 +679,15 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) { Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId) + preference := model.Preference{ + UserId: c.Session.UserId, + Category: model.PREFERENCE_CATEGORY_LAST, + Name: model.PREFERENCE_NAME_LAST_CHANNEL, + Value: id, + } + + Srv.Store.Preference().Save(&model.Preferences{preference}) + message := model.NewMessage(c.Session.TeamId, id, c.Session.UserId, model.ACTION_CHANNEL_VIEWED) message.Add("channel_id", id) diff --git a/api/user.go b/api/user.go index 36a3fd5f9..42a65c934 100644 --- a/api/user.go +++ b/api/user.go @@ -497,6 +497,26 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, if len(deviceId) > 0 { session.SetExpireInDays(model.SESSION_TIME_MOBILE_IN_DAYS) maxAge = model.SESSION_TIME_MOBILE_IN_SECS + + // A special case where we logout of all other sessions with the same Id + if result := <-Srv.Store.Session().GetSessions(user.Id); result.Err != nil { + c.Err = result.Err + c.Err.StatusCode = http.StatusForbidden + return + } else { + sessions := result.Data.([]*model.Session) + for _, session := range sessions { + if session.DeviceId == deviceId { + l4g.Debug("Revoking sessionId=" + session.Id + " for userId=" + user.Id + " re-login with same device Id") + RevokeSessionById(c, session.Id) + if c.Err != nil { + c.LogError(c.Err) + c.Err = nil + } + } + } + } + } else { session.SetExpireInDays(model.SESSION_TIME_WEB_IN_DAYS) } @@ -664,13 +684,15 @@ func loginLdap(c *Context, w http.ResponseWriter, r *http.Request) { func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) id := props["id"] + RevokeSessionById(c, id) + w.Write([]byte(model.MapToJson(props))) +} - if result := <-Srv.Store.Session().Get(id); result.Err != nil { +func RevokeSessionById(c *Context, sessionId string) { + if result := <-Srv.Store.Session().Get(sessionId); result.Err != nil { c.Err = result.Err - return } else { session := result.Data.(*model.Session) - c.LogAudit("session_id=" + session.Id) if session.IsOAuth { @@ -680,10 +702,6 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) { if result := <-Srv.Store.Session().Remove(session.Id); result.Err != nil { c.Err = result.Err - return - } else { - w.Write([]byte(model.MapToJson(props))) - return } } } diff --git a/api/user_test.go b/api/user_test.go index ffa96cb66..9a172805a 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -162,6 +162,37 @@ func TestLogin(t *testing.T) { Client.AuthToken = authToken } +func TestLoginWithDeviceId(t *testing.T) { + Setup() + + 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@test.com", Nickname: "Corey Hulen", Password: "pwd"} + ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(ruser.Id)) + + deviceId := model.NewId() + if result, err := Client.LoginByEmailWithDevice(team.Name, user.Email, user.Password, deviceId); err != nil { + t.Fatal(err) + } else { + ruser := result.Data.(*model.User) + + if ssresult, err := Client.GetSessions(ruser.Id); err != nil { + t.Fatal(err) + } else { + sessions := ssresult.Data.([]*model.Session) + if _, err := Client.LoginByEmailWithDevice(team.Name, user.Email, user.Password, deviceId); err != nil { + t.Fatal(err) + } + + if sresult := <-Srv.Store.Session().Get(sessions[0].Id); sresult.Err == nil { + t.Fatal("session should have been removed") + } + } + } +} + func TestSessions(t *testing.T) { Setup() diff --git a/model/preference.go b/model/preference.go index a3230959c..e3ad23ed4 100644 --- a/model/preference.go +++ b/model/preference.go @@ -13,6 +13,9 @@ const ( PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW = "direct_channel_show" PREFERENCE_CATEGORY_TUTORIAL_STEPS = "tutorial_step" PREFERENCE_CATEGORY_ADVANCED_SETTINGS = "advanced_settings" + + PREFERENCE_CATEGORY_LAST = "last" + PREFERENCE_NAME_LAST_CHANNEL = "channel" ) type Preference struct { diff --git a/web/web.go b/web/web.go index 6e0e8df32..30a70ba2e 100644 --- a/web/web.go +++ b/web/web.go @@ -238,7 +238,14 @@ func login(c *api.Context, w http.ResponseWriter, r *http.Request) { _, session := api.FindMultiSessionForTeamId(r, team.Id) if session != nil { w.Header().Set(model.HEADER_TOKEN, session.Token) - http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/channels/town-square", http.StatusTemporaryRedirect) + lastViewChannelName := "town-square" + if lastViewResult := <-api.Srv.Store.Preference().Get(session.UserId, model.PREFERENCE_CATEGORY_LAST, model.PREFERENCE_NAME_LAST_CHANNEL); lastViewResult.Err == nil { + if lastViewChannelResult := <-api.Srv.Store.Channel().Get(lastViewResult.Data.(model.Preference).Value); lastViewChannelResult.Err == nil { + lastViewChannelName = lastViewChannelResult.Data.(*model.Channel).Name + } + } + + http.Redirect(w, r, c.GetSiteURL()+"/"+team.Name+"/channels/"+lastViewChannelName, http.StatusTemporaryRedirect) return } @@ -1017,7 +1024,8 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { r.ParseForm() var parsedRequest *model.IncomingWebhookRequest - if r.Header.Get("Content-Type") == "application/json" { + contentType := r.Header.Get("Content-Type") + if strings.Split(contentType, "; ")[0] == "application/json" { parsedRequest = model.IncomingWebhookRequestFromJson(r.Body) } else { parsedRequest = model.IncomingWebhookRequestFromJson(strings.NewReader(r.FormValue("payload"))) |