mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[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
This commit is contained in:
committed by
Joram Wilander
parent
8e19ba029f
commit
7fa4913f90
76
api4/user.go
76
api4/user.go
@@ -61,6 +61,8 @@ func (api *API) InitUser() {
|
|||||||
api.BaseRoutes.User.Handle("/tokens", api.ApiSessionRequired(getUserAccessTokens)).Methods("GET")
|
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/{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/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) {
|
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)
|
c.LogAudit("success - token_id=" + accessToken.Id)
|
||||||
ReturnStatusOK(w)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2302,6 +2302,8 @@ func TestCreateUserAccessToken(t *testing.T) {
|
|||||||
t.Fatal("id should not be empty")
|
t.Fatal("id should not be empty")
|
||||||
} else if rtoken.Description != testDescription {
|
} else if rtoken.Description != testDescription {
|
||||||
t.Fatal("description did not match")
|
t.Fatal("description did not match")
|
||||||
|
} else if !rtoken.IsActive {
|
||||||
|
t.Fatal("token should be active")
|
||||||
}
|
}
|
||||||
|
|
||||||
oldSessionToken := Client.AuthToken
|
oldSessionToken := Client.AuthToken
|
||||||
@@ -2445,7 +2447,7 @@ func TestRevokeUserAccessToken(t *testing.T) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("should have passed")
|
t.Fatal("should have passed")
|
||||||
}
|
}
|
||||||
|
|
||||||
oldSessionToken = Client.AuthToken
|
oldSessionToken = Client.AuthToken
|
||||||
Client.AuthToken = token.Token
|
Client.AuthToken = token.Token
|
||||||
_, resp = Client.GetMe("")
|
_, 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) {
|
func TestUserAccessTokenInactiveUser(t *testing.T) {
|
||||||
th := Setup().InitBasic().InitSystemAdmin()
|
th := Setup().InitBasic().InitSystemAdmin()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|||||||
@@ -268,6 +268,10 @@ func (a *App) createSessionForUserAccessToken(tokenString string) (*model.Sessio
|
|||||||
return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, result.Err.Error(), http.StatusUnauthorized)
|
return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, result.Err.Error(), http.StatusUnauthorized)
|
||||||
} else {
|
} else {
|
||||||
token = result.Data.(*model.UserAccessToken)
|
token = result.Data.(*model.UserAccessToken)
|
||||||
|
|
||||||
|
if token.IsActive == false {
|
||||||
|
return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "inactive_token", http.StatusUnauthorized)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var user *model.User
|
var user *model.User
|
||||||
@@ -320,6 +324,40 @@ func (a *App) RevokeUserAccessToken(token *model.UserAccessToken) *model.AppErro
|
|||||||
return a.RevokeSession(session)
|
return a.RevokeSession(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) DisableUserAccessToken(token *model.UserAccessToken) *model.AppError {
|
||||||
|
var session *model.Session
|
||||||
|
if result := <-a.Srv.Store.Session().Get(token.Token); result.Err == nil {
|
||||||
|
session = result.Data.(*model.Session)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := <-a.Srv.Store.UserAccessToken().UpdateTokenDisable(token.Id); result.Err != nil {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
if session == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.RevokeSession(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) EnableUserAccessToken(token *model.UserAccessToken) *model.AppError {
|
||||||
|
var session *model.Session
|
||||||
|
if result := <-a.Srv.Store.Session().Get(token.Token); result.Err == nil {
|
||||||
|
session = result.Data.(*model.Session)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := <-a.Srv.Store.UserAccessToken().UpdateTokenEnable(token.Id); result.Err != nil {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
if session == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*model.UserAccessToken, *model.AppError) {
|
func (a *App) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*model.UserAccessToken, *model.AppError) {
|
||||||
if result := <-a.Srv.Store.UserAccessToken().GetByUser(userId, page*perPage, perPage); result.Err != nil {
|
if result := <-a.Srv.Store.UserAccessToken().GetByUser(userId, page*perPage, perPage); result.Err != nil {
|
||||||
return nil, result.Err
|
return nil, result.Err
|
||||||
|
|||||||
@@ -1065,6 +1065,32 @@ func (c *Client4) RevokeUserAccessToken(tokenId string) (bool, *Response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisableUserAccessToken will disable a user access token by id. Must have the
|
||||||
|
// 'revoke_user_access_token' permission and if disabling for another user, must have the
|
||||||
|
// 'edit_other_users' permission.
|
||||||
|
func (c *Client4) DisableUserAccessToken(tokenId string) (bool, *Response) {
|
||||||
|
requestBody := map[string]string{"token_id": tokenId}
|
||||||
|
if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/disable", MapToJson(requestBody)); err != nil {
|
||||||
|
return false, BuildErrorResponse(r, err)
|
||||||
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
|
return CheckStatusOK(r), BuildResponse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableUserAccessToken will enable a user access token by id. Must have the
|
||||||
|
// 'create_user_access_token' permission and if enabling for another user, must have the
|
||||||
|
// 'edit_other_users' permission.
|
||||||
|
func (c *Client4) EnableUserAccessToken(tokenId string) (bool, *Response) {
|
||||||
|
requestBody := map[string]string{"token_id": tokenId}
|
||||||
|
if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/enable", MapToJson(requestBody)); err != nil {
|
||||||
|
return false, BuildErrorResponse(r, err)
|
||||||
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
|
return CheckStatusOK(r), BuildResponse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Team Section
|
// Team Section
|
||||||
|
|
||||||
// CreateTeam creates a team in the system based on the provided team struct.
|
// CreateTeam creates a team in the system based on the provided team struct.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type UserAccessToken struct {
|
|||||||
Token string `json:"token,omitempty"`
|
Token string `json:"token,omitempty"`
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
IsActive bool `json:"is_active"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UserAccessToken) IsValid() *AppError {
|
func (t *UserAccessToken) IsValid() *AppError {
|
||||||
@@ -38,6 +39,7 @@ func (t *UserAccessToken) IsValid() *AppError {
|
|||||||
|
|
||||||
func (t *UserAccessToken) PreSave() {
|
func (t *UserAccessToken) PreSave() {
|
||||||
t.Id = NewId()
|
t.Id = NewId()
|
||||||
|
t.IsActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UserAccessToken) ToJson() string {
|
func (t *UserAccessToken) ToJson() string {
|
||||||
|
|||||||
@@ -312,8 +312,12 @@ func UpgradeDatabaseToVersion43(sqlStore SqlStore) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpgradeDatabaseToVersion44(sqlStore SqlStore) {
|
func UpgradeDatabaseToVersion44(sqlStore SqlStore) {
|
||||||
// TODO: Uncomment following when version 4.4.0 is released
|
// TODO: Uncomment following condition when version 4.4.0 is released
|
||||||
//if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) {
|
// if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) {
|
||||||
// saveSchemaVersion(sqlStore, VERSION_4_4_0)
|
|
||||||
//}
|
// Add the IsActive column to UserAccessToken.
|
||||||
|
sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1")
|
||||||
|
|
||||||
|
// saveSchemaVersion(sqlStore, VERSION_4_4_0)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,3 +198,65 @@ func (s SqlUserAccessTokenStore) GetByUser(userId string, offset, limit int) sto
|
|||||||
result.Data = tokens
|
result.Data = tokens
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlUserAccessTokenStore) UpdateTokenEnable(tokenId string) store.StoreChannel {
|
||||||
|
return store.Do(func(result *store.StoreResult) {
|
||||||
|
if _, err := s.GetMaster().Exec("UPDATE UserAccessTokens SET IsActive = TRUE WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenEnable", "store.sql_user_access_token.update_token_enable.app_error", nil, "id="+tokenId+", "+err.Error(), http.StatusInternalServerError)
|
||||||
|
} else {
|
||||||
|
result.Data = tokenId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SqlUserAccessTokenStore) UpdateTokenDisable(tokenId string) store.StoreChannel {
|
||||||
|
return store.Do(func(result *store.StoreResult) {
|
||||||
|
transaction, err := s.GetMaster().Begin()
|
||||||
|
if err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disble.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
} else {
|
||||||
|
if extrasResult := s.deleteSessionsAndDisableToken(transaction, tokenId); extrasResult.Err != nil {
|
||||||
|
*result = extrasResult
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Err == nil {
|
||||||
|
if err := transaction.Commit(); err != nil {
|
||||||
|
// don't need to rollback here since the transaction is already closed
|
||||||
|
result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := transaction.Rollback(); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SqlUserAccessTokenStore) deleteSessionsAndDisableToken(transaction *gorp.Transaction, tokenId string) store.StoreResult {
|
||||||
|
result := store.StoreResult{}
|
||||||
|
|
||||||
|
query := ""
|
||||||
|
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
|
||||||
|
query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.Id = :Id"
|
||||||
|
} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
|
||||||
|
query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.Id = :Id"
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := transaction.Exec(query, map[string]interface{}{"Id": tokenId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserAccessTokenStore.deleteSessionsAndDisableToken", "store.sql_user_access_token.update_token_disable.app_error", nil, "id="+tokenId+", err="+err.Error(), http.StatusInternalServerError)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.updateTokenDisable(transaction, tokenId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SqlUserAccessTokenStore) updateTokenDisable(transaction *gorp.Transaction, tokenId string) store.StoreResult {
|
||||||
|
result := store.StoreResult{}
|
||||||
|
|
||||||
|
if _, err := transaction.Exec("UPDATE UserAccessTokens SET IsActive = FALSE WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserAccessTokenStore.updateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, "", http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -436,4 +436,6 @@ type UserAccessTokenStore interface {
|
|||||||
Get(tokenId string) StoreChannel
|
Get(tokenId string) StoreChannel
|
||||||
GetByToken(tokenString string) StoreChannel
|
GetByToken(tokenString string) StoreChannel
|
||||||
GetByUser(userId string, page, perPage int) StoreChannel
|
GetByUser(userId string, page, perPage int) StoreChannel
|
||||||
|
UpdateTokenEnable(tokenId string) StoreChannel
|
||||||
|
UpdateTokenDisable(tokenId string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
func TestUserAccessTokenStore(t *testing.T, ss store.Store) {
|
func TestUserAccessTokenStore(t *testing.T, ss store.Store) {
|
||||||
t.Run("UserAccessTokenSaveGetDelete", func(t *testing.T) { testUserAccessTokenSaveGetDelete(t, ss) })
|
t.Run("UserAccessTokenSaveGetDelete", func(t *testing.T) { testUserAccessTokenSaveGetDelete(t, ss) })
|
||||||
|
t.Run("UserAccessTokenDisableEnable", func(t *testing.T) { testUserAccessTokenDisableEnable(t, ss) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserAccessTokenSaveGetDelete(t *testing.T, ss store.Store) {
|
func testUserAccessTokenSaveGetDelete(t *testing.T, ss store.Store) {
|
||||||
@@ -87,3 +88,39 @@ func testUserAccessTokenSaveGetDelete(t *testing.T, ss store.Store) {
|
|||||||
t.Fatal("should error - access token should be deleted")
|
t.Fatal("should error - access token should be deleted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testUserAccessTokenDisableEnable(t *testing.T, ss store.Store) {
|
||||||
|
uat := &model.UserAccessToken{
|
||||||
|
Token: model.NewId(),
|
||||||
|
UserId: model.NewId(),
|
||||||
|
Description: "testtoken",
|
||||||
|
}
|
||||||
|
|
||||||
|
s1 := model.Session{}
|
||||||
|
s1.UserId = uat.UserId
|
||||||
|
s1.Token = uat.Token
|
||||||
|
|
||||||
|
store.Must(ss.Session().Save(&s1))
|
||||||
|
|
||||||
|
if result := <-ss.UserAccessToken().Save(uat); result.Err != nil {
|
||||||
|
t.Fatal(result.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := (<-ss.UserAccessToken().UpdateTokenDisable(uat.Id)).Err; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := (<-ss.Session().Get(s1.Token)).Err; err == nil {
|
||||||
|
t.Fatal("should error - session should be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
s2 := model.Session{}
|
||||||
|
s2.UserId = uat.UserId
|
||||||
|
s2.Token = uat.Token
|
||||||
|
|
||||||
|
store.Must(ss.Session().Save(&s2))
|
||||||
|
|
||||||
|
if err := (<-ss.UserAccessToken().UpdateTokenEnable(uat.Id)).Err; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user