Implement PUT /users/sessions/device endpoint for APIv4 (#5866)

This commit is contained in:
Joram Wilander
2017-03-27 09:17:34 -04:00
committed by Christopher Speller
parent 84dc60a640
commit d145c35838
3 changed files with 89 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
"time"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/app" "github.com/mattermost/platform/app"
@@ -46,6 +47,7 @@ func InitUser() {
BaseRoutes.User.Handle("/sessions", ApiSessionRequired(getSessions)).Methods("GET") BaseRoutes.User.Handle("/sessions", ApiSessionRequired(getSessions)).Methods("GET")
BaseRoutes.User.Handle("/sessions/revoke", ApiSessionRequired(revokeSession)).Methods("POST") BaseRoutes.User.Handle("/sessions/revoke", ApiSessionRequired(revokeSession)).Methods("POST")
BaseRoutes.Users.Handle("/sessions/device", ApiSessionRequired(attachDeviceId)).Methods("PUT")
BaseRoutes.User.Handle("/audits", ApiSessionRequired(getUserAudits)).Methods("GET") BaseRoutes.User.Handle("/audits", ApiSessionRequired(getUserAudits)).Methods("GET")
} }
@@ -778,6 +780,53 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w) ReturnStatusOK(w)
} }
func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
deviceId := props["device_id"]
if len(deviceId) == 0 {
c.SetInvalidParam("device_id")
return
}
// A special case where we logout of all other sessions with the same device id
if err := app.RevokeSessionsForDeviceId(c.Session.UserId, deviceId, c.Session.Id); err != nil {
c.Err = err
return
}
app.ClearSessionCacheForUser(c.Session.UserId)
c.Session.SetExpireInDays(*utils.Cfg.ServiceSettings.SessionLengthMobileInDays)
maxAge := *utils.Cfg.ServiceSettings.SessionLengthMobileInDays * 60 * 60 * 24
secure := false
if app.GetProtocol(r) == "https" {
secure = true
}
expiresAt := time.Unix(model.GetMillis()/1000+int64(maxAge), 0)
sessionCookie := &http.Cookie{
Name: model.SESSION_COOKIE_TOKEN,
Value: c.Session.Token,
Path: "/",
MaxAge: maxAge,
Expires: expiresAt,
HttpOnly: true,
Secure: secure,
}
http.SetCookie(w, sessionCookie)
if err := app.AttachDeviceId(c.Session.Id, deviceId, c.Session.ExpiresAt); err != nil {
c.Err = err
return
}
c.LogAudit("")
ReturnStatusOK(w)
}
func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) { func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireUserId() c.RequireUserId()
if c.Err != nil { if c.Err != nil {

View File

@@ -1275,7 +1275,36 @@ func TestRevokeSessions(t *testing.T) {
_, resp = th.SystemAdminClient.RevokeSession(th.SystemAdminUser.Id, session.Id) _, resp = th.SystemAdminClient.RevokeSession(th.SystemAdminUser.Id, session.Id)
CheckNoError(t, resp) CheckNoError(t, resp)
}
func TestAttachDeviceId(t *testing.T) {
th := Setup().InitBasic()
defer TearDown()
Client := th.Client
deviceId := model.PUSH_NOTIFY_APPLE + ":1234567890"
pass, resp := Client.AttachDeviceId(deviceId)
CheckNoError(t, resp)
if !pass {
t.Fatal("should have passed")
}
if sessions, err := app.GetSessions(th.BasicUser.Id); err != nil {
t.Fatal(err)
} else {
if sessions[0].DeviceId != deviceId {
t.Fatal("Missing device Id")
}
}
_, resp = Client.AttachDeviceId("")
CheckBadRequestStatus(t, resp)
Client.Logout()
_, resp = Client.AttachDeviceId("")
CheckUnauthorizedStatus(t, resp)
} }
func TestGetUserAudits(t *testing.T) { func TestGetUserAudits(t *testing.T) {

View File

@@ -617,6 +617,17 @@ func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) {
} }
} }
// AttachDeviceId attaches a mobile device ID to the current session.
func (c *Client4) AttachDeviceId(deviceId string) (bool, *Response) {
requestBody := map[string]string{"device_id": deviceId}
if r, err := c.DoApiPut(c.GetUsersRoute()+"/sessions/device", MapToJson(requestBody)); err != nil {
return false, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return CheckStatusOK(r), BuildResponse(r)
}
}
// GetTeamsUnreadForUser will return an array with TeamUnread objects that contain the amount // GetTeamsUnreadForUser will return an array with TeamUnread objects that contain the amount
// of unread messages and mentions the current user has for the teams it belongs to. // of unread messages and mentions the current user has for the teams it belongs to.
// An optional team ID can be set to exclude that team from the results. Must be authenticated. // An optional team ID can be set to exclude that team from the results. Must be authenticated.