From 7fa4913f902457dadb1a4806ce194eb122dbc090 Mon Sep 17 00:00:00 2001 From: Nick Frazier Date: Thu, 19 Oct 2017 08:10:29 -0400 Subject: [PLT-7794] Add user access token enable/disable endpoints (#7630) * Add column to UserAccessTokens table * PLT-7794 Add user access token enable/disable endpoints * replaced eliminated global variable * updates to user_access_token_store and upgrade.go * style fix and cleanup --- api4/user.go | 76 ++++++++++++++++++++++++++++++++++++++++++ api4/user_test.go | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 1 deletion(-) (limited to 'api4') diff --git a/api4/user.go b/api4/user.go index d17591afa..889681b54 100644 --- a/api4/user.go +++ b/api4/user.go @@ -61,6 +61,8 @@ func (api *API) InitUser() { api.BaseRoutes.User.Handle("/tokens", api.ApiSessionRequired(getUserAccessTokens)).Methods("GET") api.BaseRoutes.Users.Handle("/tokens/{token_id:[A-Za-z0-9]+}", api.ApiSessionRequired(getUserAccessToken)).Methods("GET") api.BaseRoutes.Users.Handle("/tokens/revoke", api.ApiSessionRequired(revokeUserAccessToken)).Methods("POST") + api.BaseRoutes.Users.Handle("/tokens/disable", api.ApiSessionRequired(disableUserAccessToken)).Methods("POST") + api.BaseRoutes.Users.Handle("/tokens/enable", api.ApiSessionRequired(enableUserAccessToken)).Methods("POST") } func createUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1290,3 +1292,77 @@ func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { c.LogAudit("success - token_id=" + accessToken.Id) ReturnStatusOK(w) } + +func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { + props := model.MapFromJson(r.Body) + tokenId := props["token_id"] + + if tokenId == "" { + c.SetInvalidParam("token_id") + } + + c.LogAudit("") + + // No separate permission for this action for now + if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_REVOKE_USER_ACCESS_TOKEN) { + c.SetPermissionError(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN) + return + } + + accessToken, err := c.App.GetUserAccessToken(tokenId, false) + if err != nil { + c.Err = err + return + } + + if !app.SessionHasPermissionToUser(c.Session, accessToken.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + err = c.App.DisableUserAccessToken(accessToken) + if err != nil { + c.Err = err + return + } + + c.LogAudit("success - token_id=" + accessToken.Id) + ReturnStatusOK(w) +} + +func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { + props := model.MapFromJson(r.Body) + tokenId := props["token_id"] + + if tokenId == "" { + c.SetInvalidParam("token_id") + } + + c.LogAudit("") + + // No separate permission for this action for now + if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_CREATE_USER_ACCESS_TOKEN) { + c.SetPermissionError(model.PERMISSION_CREATE_USER_ACCESS_TOKEN) + return + } + + accessToken, err := c.App.GetUserAccessToken(tokenId, false) + if err != nil { + c.Err = err + return + } + + if !app.SessionHasPermissionToUser(c.Session, accessToken.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + err = c.App.EnableUserAccessToken(accessToken) + if err != nil { + c.Err = err + return + } + + c.LogAudit("success - token_id=" + accessToken.Id) + ReturnStatusOK(w) +} diff --git a/api4/user_test.go b/api4/user_test.go index ceaf3f038..1f408048e 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -2302,6 +2302,8 @@ func TestCreateUserAccessToken(t *testing.T) { t.Fatal("id should not be empty") } else if rtoken.Description != testDescription { t.Fatal("description did not match") + } else if !rtoken.IsActive { + t.Fatal("token should be active") } oldSessionToken := Client.AuthToken @@ -2445,7 +2447,7 @@ func TestRevokeUserAccessToken(t *testing.T) { if !ok { t.Fatal("should have passed") } - + oldSessionToken = Client.AuthToken Client.AuthToken = token.Token _, resp = Client.GetMe("") @@ -2463,6 +2465,100 @@ func TestRevokeUserAccessToken(t *testing.T) { } } +func TestDisableUserAccessToken(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer th.TearDown() + Client := th.Client + AdminClient := th.SystemAdminClient + + testDescription := "test token" + + enableUserAccessTokens := *utils.Cfg.ServiceSettings.EnableUserAccessTokens + defer func() { + *utils.Cfg.ServiceSettings.EnableUserAccessTokens = enableUserAccessTokens + }() + *utils.Cfg.ServiceSettings.EnableUserAccessTokens = true + + th.App.UpdateUserRoles(th.BasicUser.Id, model.ROLE_SYSTEM_USER.Id+" "+model.ROLE_SYSTEM_USER_ACCESS_TOKEN.Id) + token, resp := Client.CreateUserAccessToken(th.BasicUser.Id, testDescription) + CheckNoError(t, resp) + + oldSessionToken := Client.AuthToken + Client.AuthToken = token.Token + _, resp = Client.GetMe("") + CheckNoError(t, resp) + Client.AuthToken = oldSessionToken + + ok, resp := Client.DisableUserAccessToken(token.Id) + CheckNoError(t, resp) + + if !ok { + t.Fatal("should have passed") + } + + oldSessionToken = Client.AuthToken + Client.AuthToken = token.Token + _, resp = Client.GetMe("") + CheckUnauthorizedStatus(t, resp) + Client.AuthToken = oldSessionToken + + token, resp = AdminClient.CreateUserAccessToken(th.BasicUser2.Id, testDescription) + CheckNoError(t, resp) + + ok, resp = Client.DisableUserAccessToken(token.Id) + CheckForbiddenStatus(t, resp) + + if ok { + t.Fatal("should have failed") + } +} + +func TestEnableUserAccessToken(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer th.TearDown() + Client := th.Client + + testDescription := "test token" + + enableUserAccessTokens := *utils.Cfg.ServiceSettings.EnableUserAccessTokens + defer func() { + *utils.Cfg.ServiceSettings.EnableUserAccessTokens = enableUserAccessTokens + }() + *utils.Cfg.ServiceSettings.EnableUserAccessTokens = true + + th.App.UpdateUserRoles(th.BasicUser.Id, model.ROLE_SYSTEM_USER.Id+" "+model.ROLE_SYSTEM_USER_ACCESS_TOKEN.Id) + token, resp := Client.CreateUserAccessToken(th.BasicUser.Id, testDescription) + CheckNoError(t, resp) + + oldSessionToken := Client.AuthToken + Client.AuthToken = token.Token + _, resp = Client.GetMe("") + CheckNoError(t, resp) + Client.AuthToken = oldSessionToken + + _, resp = Client.DisableUserAccessToken(token.Id) + CheckNoError(t, resp) + + oldSessionToken = Client.AuthToken + Client.AuthToken = token.Token + _, resp = Client.GetMe("") + CheckUnauthorizedStatus(t, resp) + Client.AuthToken = oldSessionToken + + ok, resp := Client.EnableUserAccessToken(token.Id) + CheckNoError(t, resp) + + if !ok { + t.Fatal("should have passed") + } + + oldSessionToken = Client.AuthToken + Client.AuthToken = token.Token + _, resp = Client.GetMe("") + CheckNoError(t, resp) + Client.AuthToken = oldSessionToken +} + func TestUserAccessTokenInactiveUser(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer th.TearDown() -- cgit v1.2.3-1-g7c22