2019-03-08 08:15:38 -06:00
package api
import (
2019-04-30 07:42:01 -05:00
"context"
2020-11-13 02:52:38 -06:00
"fmt"
2019-03-08 08:15:38 -06:00
"testing"
"time"
2022-08-02 09:58:05 -05:00
"github.com/stretchr/testify/assert"
2021-01-15 07:43:20 -06:00
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
2020-03-04 05:57:20 -06:00
"github.com/grafana/grafana/pkg/models"
2019-03-08 08:15:38 -06:00
"github.com/grafana/grafana/pkg/services/auth"
2022-11-18 02:56:06 -06:00
"github.com/grafana/grafana/pkg/services/auth/authtest"
2022-08-10 04:56:48 -05:00
"github.com/grafana/grafana/pkg/services/org"
2022-06-28 07:32:25 -05:00
"github.com/grafana/grafana/pkg/services/user"
2022-08-02 09:58:05 -05:00
"github.com/grafana/grafana/pkg/services/user/usertest"
2019-03-08 08:15:38 -06:00
)
2020-11-13 02:52:38 -06:00
func TestUserTokenAPIEndpoint ( t * testing . T ) {
2022-08-02 09:58:05 -05:00
userMock := usertest . NewUserServiceFake ( )
2020-11-13 02:52:38 -06:00
t . Run ( "When current user attempts to revoke an auth token for a non-existing user" , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
cmd := auth . RevokeAuthTokenCmd { AuthTokenId : 2 }
2022-08-02 09:58:05 -05:00
userMock . ExpectedError = user . ErrUserNotFound
2020-11-13 02:52:38 -06:00
revokeUserAuthTokenScenario ( t , "Should return not found when calling POST on" , "/api/user/revoke-auth-token" ,
"/api/user/revoke-auth-token" , cmd , 200 , func ( sc * scenarioContext ) {
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
assert . Equal ( t , 404 , sc . resp . Code )
2022-08-02 09:58:05 -05:00
} , userMock )
2019-03-08 08:15:38 -06:00
} )
2020-11-13 02:52:38 -06:00
t . Run ( "When current user gets auth tokens for a non-existing user" , func ( t * testing . T ) {
2022-08-02 09:58:05 -05:00
mockUser := & usertest . FakeUserService {
2022-06-28 07:32:25 -05:00
ExpectedUser : & user . User { ID : 200 } ,
2022-07-20 07:50:06 -05:00
ExpectedError : user . ErrUserNotFound ,
2022-02-03 02:20:20 -06:00
}
2020-11-13 02:52:38 -06:00
getUserAuthTokensScenario ( t , "Should return not found when calling GET on" , "/api/user/auth-tokens" , "/api/user/auth-tokens" , 200 , func ( sc * scenarioContext ) {
2019-03-08 08:15:38 -06:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , 404 , sc . resp . Code )
2022-08-02 09:58:05 -05:00
} , mockUser )
2019-03-08 08:15:38 -06:00
} )
2020-11-13 02:52:38 -06:00
t . Run ( "When logging out an existing user from all devices" , func ( t * testing . T ) {
2022-08-02 09:58:05 -05:00
userMock := & usertest . FakeUserService {
2022-06-28 07:32:25 -05:00
ExpectedUser : & user . User { ID : 200 } ,
2022-02-03 02:20:20 -06:00
}
2020-11-13 02:52:38 -06:00
logoutUserFromAllDevicesInternalScenario ( t , "Should be successful" , 1 , func ( sc * scenarioContext ) {
2019-03-08 08:15:38 -06:00
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , 200 , sc . resp . Code )
2022-08-02 09:58:05 -05:00
} , userMock )
2019-03-08 08:15:38 -06:00
} )
2020-11-13 02:52:38 -06:00
t . Run ( "When logout a non-existing user from all devices" , func ( t * testing . T ) {
logoutUserFromAllDevicesInternalScenario ( t , "Should return not found" , testUserID , func ( sc * scenarioContext ) {
2022-08-02 09:58:05 -05:00
userMock . ExpectedError = user . ErrUserNotFound
2019-03-08 08:15:38 -06:00
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , 404 , sc . resp . Code )
2022-08-02 09:58:05 -05:00
} , userMock )
2019-03-08 08:15:38 -06:00
} )
2020-11-13 02:52:38 -06:00
t . Run ( "When revoke an auth token for a user" , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
cmd := auth . RevokeAuthTokenCmd { AuthTokenId : 2 }
token := & auth . UserToken { Id : 1 }
2022-08-02 09:58:05 -05:00
mockUser := & usertest . FakeUserService {
2022-06-28 07:32:25 -05:00
ExpectedUser : & user . User { ID : 200 } ,
2022-02-03 02:20:20 -06:00
}
2019-03-08 08:15:38 -06:00
2020-11-13 02:52:38 -06:00
revokeUserAuthTokenInternalScenario ( t , "Should be successful" , cmd , 200 , token , func ( sc * scenarioContext ) {
2022-11-18 02:56:06 -06:00
sc . userAuthTokenService . GetUserTokenProvider = func ( ctx context . Context , userId , userTokenId int64 ) ( * auth . UserToken , error ) {
return & auth . UserToken { Id : 2 } , nil
2019-03-08 08:15:38 -06:00
}
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , 200 , sc . resp . Code )
2022-08-02 09:58:05 -05:00
} , mockUser )
2019-03-08 08:15:38 -06:00
} )
2020-11-13 02:52:38 -06:00
t . Run ( "When revoke the active auth token used by himself" , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
cmd := auth . RevokeAuthTokenCmd { AuthTokenId : 2 }
token := & auth . UserToken { Id : 2 }
2022-08-02 09:58:05 -05:00
mockUser := usertest . NewUserServiceFake ( )
2020-11-13 02:52:38 -06:00
revokeUserAuthTokenInternalScenario ( t , "Should not be successful" , cmd , testUserID , token , func ( sc * scenarioContext ) {
2022-11-18 02:56:06 -06:00
sc . userAuthTokenService . GetUserTokenProvider = func ( ctx context . Context , userId , userTokenId int64 ) ( * auth . UserToken , error ) {
2019-03-08 08:15:38 -06:00
return token , nil
}
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , 400 , sc . resp . Code )
2022-08-02 09:58:05 -05:00
} , mockUser )
2019-03-08 08:15:38 -06:00
} )
2020-11-13 02:52:38 -06:00
t . Run ( "When gets auth tokens for a user" , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
currentToken := & auth . UserToken { Id : 1 }
2022-08-02 09:58:05 -05:00
mockUser := usertest . NewUserServiceFake ( )
2020-11-13 02:52:38 -06:00
getUserAuthTokensInternalScenario ( t , "Should be successful" , currentToken , func ( sc * scenarioContext ) {
2022-11-18 02:56:06 -06:00
tokens := [ ] * auth . UserToken {
2019-03-08 08:15:38 -06:00
{
Id : 1 ,
ClientIp : "127.0.0.1" ,
UserAgent : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36" ,
CreatedAt : time . Now ( ) . Unix ( ) ,
SeenAt : time . Now ( ) . Unix ( ) ,
} ,
{
Id : 2 ,
ClientIp : "127.0.0.2" ,
UserAgent : "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" ,
CreatedAt : time . Now ( ) . Unix ( ) ,
2019-07-08 07:30:02 -05:00
SeenAt : 0 ,
2019-03-08 08:15:38 -06:00
} ,
}
2022-11-18 02:56:06 -06:00
sc . userAuthTokenService . GetUserTokensProvider = func ( ctx context . Context , userId int64 ) ( [ ] * auth . UserToken , error ) {
2019-03-08 08:15:38 -06:00
return tokens , nil
}
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , 200 , sc . resp . Code )
2019-03-08 08:15:38 -06:00
result := sc . ToJSON ( )
2020-11-13 02:52:38 -06:00
assert . Len ( t , result . MustArray ( ) , 2 )
2019-03-08 08:15:38 -06:00
resultOne := result . GetIndex ( 0 )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , tokens [ 0 ] . Id , resultOne . Get ( "id" ) . MustInt64 ( ) )
assert . True ( t , resultOne . Get ( "isActive" ) . MustBool ( ) )
assert . Equal ( t , "127.0.0.1" , resultOne . Get ( "clientIp" ) . MustString ( ) )
assert . Equal ( t , time . Unix ( tokens [ 0 ] . CreatedAt , 0 ) . Format ( time . RFC3339 ) , resultOne . Get ( "createdAt" ) . MustString ( ) )
assert . Equal ( t , time . Unix ( tokens [ 0 ] . SeenAt , 0 ) . Format ( time . RFC3339 ) , resultOne . Get ( "seenAt" ) . MustString ( ) )
assert . Equal ( t , "Other" , resultOne . Get ( "device" ) . MustString ( ) )
assert . Equal ( t , "Chrome" , resultOne . Get ( "browser" ) . MustString ( ) )
assert . Equal ( t , "72.0" , resultOne . Get ( "browserVersion" ) . MustString ( ) )
assert . Equal ( t , "Linux" , resultOne . Get ( "os" ) . MustString ( ) )
assert . Empty ( t , resultOne . Get ( "osVersion" ) . MustString ( ) )
2019-06-11 07:12:52 -05:00
2019-03-08 08:15:38 -06:00
resultTwo := result . GetIndex ( 1 )
2020-11-13 02:52:38 -06:00
assert . Equal ( t , tokens [ 1 ] . Id , resultTwo . Get ( "id" ) . MustInt64 ( ) )
assert . False ( t , resultTwo . Get ( "isActive" ) . MustBool ( ) )
assert . Equal ( t , "127.0.0.2" , resultTwo . Get ( "clientIp" ) . MustString ( ) )
assert . Equal ( t , time . Unix ( tokens [ 1 ] . CreatedAt , 0 ) . Format ( time . RFC3339 ) , resultTwo . Get ( "createdAt" ) . MustString ( ) )
assert . Equal ( t , time . Unix ( tokens [ 1 ] . CreatedAt , 0 ) . Format ( time . RFC3339 ) , resultTwo . Get ( "seenAt" ) . MustString ( ) )
assert . Equal ( t , "iPhone" , resultTwo . Get ( "device" ) . MustString ( ) )
assert . Equal ( t , "Mobile Safari" , resultTwo . Get ( "browser" ) . MustString ( ) )
assert . Equal ( t , "11.0" , resultTwo . Get ( "browserVersion" ) . MustString ( ) )
assert . Equal ( t , "iOS" , resultTwo . Get ( "os" ) . MustString ( ) )
assert . Equal ( t , "11.0" , resultTwo . Get ( "osVersion" ) . MustString ( ) )
2022-08-02 09:58:05 -05:00
} , mockUser )
2019-03-08 08:15:38 -06:00
} )
}
2022-11-18 02:56:06 -06:00
func revokeUserAuthTokenScenario ( t * testing . T , desc string , url string , routePattern string , cmd auth . RevokeAuthTokenCmd ,
2022-08-02 09:58:05 -05:00
userId int64 , fn scenarioFunc , userService user . Service ) {
2020-11-13 02:52:38 -06:00
t . Run ( fmt . Sprintf ( "%s %s" , desc , url ) , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
fakeAuthTokenService := authtest . NewFakeUserAuthTokenService ( )
2019-03-08 08:15:38 -06:00
hs := HTTPServer {
AuthTokenService : fakeAuthTokenService ,
2022-08-02 09:58:05 -05:00
userService : userService ,
2019-03-08 08:15:38 -06:00
}
2020-11-13 02:52:38 -06:00
sc := setupScenarioContext ( t , url )
2019-03-08 08:15:38 -06:00
sc . userAuthTokenService = fakeAuthTokenService
2021-01-15 07:43:20 -06:00
sc . defaultHandler = routing . Wrap ( func ( c * models . ReqContext ) response . Response {
2021-11-29 03:18:01 -06:00
c . Req . Body = mockRequestBody ( cmd )
2019-03-08 08:15:38 -06:00
sc . context = c
2022-08-11 06:28:55 -05:00
sc . context . UserID = userId
sc . context . OrgID = testOrgID
2022-08-10 04:56:48 -05:00
sc . context . OrgRole = org . RoleAdmin
2019-03-08 08:15:38 -06:00
2021-11-29 03:18:01 -06:00
return hs . RevokeUserAuthToken ( c )
2019-03-08 08:15:38 -06:00
} )
sc . m . Post ( routePattern , sc . defaultHandler )
fn ( sc )
} )
}
2022-08-02 09:58:05 -05:00
func getUserAuthTokensScenario ( t * testing . T , desc string , url string , routePattern string , userId int64 , fn scenarioFunc , userService user . Service ) {
2020-11-13 02:52:38 -06:00
t . Run ( fmt . Sprintf ( "%s %s" , desc , url ) , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
fakeAuthTokenService := authtest . NewFakeUserAuthTokenService ( )
2019-03-08 08:15:38 -06:00
hs := HTTPServer {
AuthTokenService : fakeAuthTokenService ,
2022-08-02 09:58:05 -05:00
userService : userService ,
2019-03-08 08:15:38 -06:00
}
2020-11-13 02:52:38 -06:00
sc := setupScenarioContext ( t , url )
2019-03-08 08:15:38 -06:00
sc . userAuthTokenService = fakeAuthTokenService
2021-01-15 07:43:20 -06:00
sc . defaultHandler = routing . Wrap ( func ( c * models . ReqContext ) response . Response {
2019-03-08 08:15:38 -06:00
sc . context = c
2022-08-11 06:28:55 -05:00
sc . context . UserID = userId
sc . context . OrgID = testOrgID
2022-08-10 04:56:48 -05:00
sc . context . OrgRole = org . RoleAdmin
2019-03-08 08:15:38 -06:00
return hs . GetUserAuthTokens ( c )
} )
sc . m . Get ( routePattern , sc . defaultHandler )
fn ( sc )
} )
}
2022-08-02 09:58:05 -05:00
func logoutUserFromAllDevicesInternalScenario ( t * testing . T , desc string , userId int64 , fn scenarioFunc , userService user . Service ) {
2020-11-13 02:52:38 -06:00
t . Run ( desc , func ( t * testing . T ) {
2019-03-08 08:15:38 -06:00
hs := HTTPServer {
2022-11-18 02:56:06 -06:00
AuthTokenService : authtest . NewFakeUserAuthTokenService ( ) ,
2022-08-02 09:58:05 -05:00
userService : userService ,
2019-03-08 08:15:38 -06:00
}
2020-11-13 02:52:38 -06:00
sc := setupScenarioContext ( t , "/" )
2021-01-15 07:43:20 -06:00
sc . defaultHandler = routing . Wrap ( func ( c * models . ReqContext ) response . Response {
2019-03-08 08:15:38 -06:00
sc . context = c
2022-08-11 06:28:55 -05:00
sc . context . UserID = testUserID
sc . context . OrgID = testOrgID
2022-08-10 04:56:48 -05:00
sc . context . OrgRole = org . RoleAdmin
2019-03-08 08:15:38 -06:00
2019-04-30 07:42:01 -05:00
return hs . logoutUserFromAllDevicesInternal ( context . Background ( ) , userId )
2019-03-08 08:15:38 -06:00
} )
sc . m . Post ( "/" , sc . defaultHandler )
fn ( sc )
} )
}
2022-11-18 02:56:06 -06:00
func revokeUserAuthTokenInternalScenario ( t * testing . T , desc string , cmd auth . RevokeAuthTokenCmd , userId int64 ,
token * auth . UserToken , fn scenarioFunc , userService user . Service ) {
2020-11-13 02:52:38 -06:00
t . Run ( desc , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
fakeAuthTokenService := authtest . NewFakeUserAuthTokenService ( )
2019-03-08 08:15:38 -06:00
hs := HTTPServer {
AuthTokenService : fakeAuthTokenService ,
2022-08-02 09:58:05 -05:00
userService : userService ,
2019-03-08 08:15:38 -06:00
}
2020-11-13 02:52:38 -06:00
sc := setupScenarioContext ( t , "/" )
2019-03-08 08:15:38 -06:00
sc . userAuthTokenService = fakeAuthTokenService
2021-01-15 07:43:20 -06:00
sc . defaultHandler = routing . Wrap ( func ( c * models . ReqContext ) response . Response {
2019-03-08 08:15:38 -06:00
sc . context = c
2022-08-11 06:28:55 -05:00
sc . context . UserID = testUserID
sc . context . OrgID = testOrgID
2022-08-10 04:56:48 -05:00
sc . context . OrgRole = org . RoleAdmin
2019-03-08 08:15:38 -06:00
sc . context . UserToken = token
return hs . revokeUserAuthTokenInternal ( c , userId , cmd )
} )
sc . m . Post ( "/" , sc . defaultHandler )
fn ( sc )
} )
}
2022-11-18 02:56:06 -06:00
func getUserAuthTokensInternalScenario ( t * testing . T , desc string , token * auth . UserToken , fn scenarioFunc , userService user . Service ) {
2020-11-13 02:52:38 -06:00
t . Run ( desc , func ( t * testing . T ) {
2022-11-18 02:56:06 -06:00
fakeAuthTokenService := authtest . NewFakeUserAuthTokenService ( )
2019-03-08 08:15:38 -06:00
hs := HTTPServer {
AuthTokenService : fakeAuthTokenService ,
2022-08-02 09:58:05 -05:00
userService : userService ,
2019-03-08 08:15:38 -06:00
}
2020-11-13 02:52:38 -06:00
sc := setupScenarioContext ( t , "/" )
2019-03-08 08:15:38 -06:00
sc . userAuthTokenService = fakeAuthTokenService
2021-01-15 07:43:20 -06:00
sc . defaultHandler = routing . Wrap ( func ( c * models . ReqContext ) response . Response {
2019-03-08 08:15:38 -06:00
sc . context = c
2022-08-11 06:28:55 -05:00
sc . context . UserID = testUserID
sc . context . OrgID = testOrgID
2022-08-10 04:56:48 -05:00
sc . context . OrgRole = org . RoleAdmin
2019-03-08 08:15:38 -06:00
sc . context . UserToken = token
2020-11-13 02:52:38 -06:00
return hs . getUserAuthTokensInternal ( c , testUserID )
2019-03-08 08:15:38 -06:00
} )
sc . m . Get ( "/" , sc . defaultHandler )
fn ( sc )
} )
}