account_resolver_test.go

This commit is contained in:
Ilja Neumann
2020-12-22 16:16:57 +01:00
parent 6ce4bb739c
commit 1b29e56d12
5 changed files with 384 additions and 214 deletions
@@ -1,213 +0,0 @@
package middleware
/*
Temporarily disabled
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/micro/go-micro/v2/client"
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/oidc"
"github.com/owncloud/ocis/proxy/pkg/config"
settings "github.com/owncloud/ocis/settings/pkg/proto/v0"
)
func TestGetAccountSuccess(t *testing.T) {
if _, status := getAccount(log.NewLogger(), mockAccountResolverMiddlewareAccSvc(false, true), "mail eq 'success'"); status != 0 {
t.Errorf("expected an account")
}
}
func TestGetAccountInternalError(t *testing.T) {
if _, status := getAccount(log.NewLogger(), mockAccountResolverMiddlewareAccSvc(true, false), "mail eq 'failure'"); status != http.StatusInternalServerError {
t.Errorf("expected an internal server error")
}
}
func TestAccountResolverMiddleware(t *testing.T) {
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
m := AccountResolver(
Logger(log.NewLogger()),
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
AccountsClient(mockAccountResolverMiddlewareAccSvc(false, true)),
SettingsRoleService(mockAccountResolverMiddlewareRolesSvc(false)),
)(next)
r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil)
w := httptest.NewRecorder()
ctx := oidc.NewContext(r.Context(), &oidc.StandardClaims{Email: "success"})
r = r.WithContext(ctx)
m.ServeHTTP(w, r)
if r.Header.Get("x-access-token") == "" {
t.Errorf("expected a token")
}
}
func TestAccountResolverMiddlewareWithDisabledAccount(t *testing.T) {
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
m := AccountResolver(
Logger(log.NewLogger()),
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
AccountsClient(mockAccountResolverMiddlewareAccSvc(false, false)),
SettingsRoleService(mockAccountResolverMiddlewareRolesSvc(false)),
)(next)
r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil)
w := httptest.NewRecorder()
ctx := oidc.NewContext(r.Context(), &oidc.StandardClaims{Email: "failure"})
r = r.WithContext(ctx)
m.ServeHTTP(w, r)
rsp := w.Result()
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusUnauthorized {
t.Errorf("expected a disabled account to be unauthorized, got: %d", rsp.StatusCode)
}
}
func mockAccountResolverMiddlewareAccSvc(retErr, accEnabled bool) proto.AccountsService {
return &proto.MockAccountsService{
ListFunc: func(ctx context.Context, in *proto.ListAccountsRequest, opts ...client.CallOption) (out *proto.ListAccountsResponse, err error) {
if retErr {
return nil, fmt.Errorf("error returned by mockAccountsService LIST")
}
return &proto.ListAccountsResponse{
Accounts: []*proto.Account{
{
Id: "yay",
AccountEnabled: accEnabled,
},
},
}, nil
},
}
}
func mockAccountResolverMiddlewareRolesSvc(returnError bool) settings.RoleService {
return &settings.MockRoleService{
ListRoleAssignmentsFunc: func(ctx context.Context, req *settings.ListRoleAssignmentsRequest, opts ...client.CallOption) (res *settings.ListRoleAssignmentsResponse, err error) {
if returnError {
return nil, fmt.Errorf("error returned by mockRoleService.ListRoleAssignments")
}
return &settings.ListRoleAssignmentsResponse{
Assignments: []*settings.UserRoleAssignment{},
}, nil
},
}
}
/*
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/micro/go-micro/v2/client"
"github.com/owncloud/ocis/accounts/pkg/proto/v0"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/oidc"
"github.com/owncloud/ocis/proxy/pkg/config"
settings "github.com/owncloud/ocis/settings/pkg/proto/v0"
)
// TODO testing the getAccount method should inject a cache
func TestGetAccountSuccess(t *testing.T) {
svcCache.Invalidate(AccountsKey, "success")
if _, status := getAccount(log.NewLogger(), mockAccountUUIDMiddlewareAccSvc(false, true), "mail eq 'success'"); status != 0 {
t.Errorf("expected an account")
}
}
func TestGetAccountInternalError(t *testing.T) {
svcCache.Invalidate(AccountsKey, "failure")
if _, status := getAccount(log.NewLogger(), mockAccountUUIDMiddlewareAccSvc(true, false), "mail eq 'failure'"); status != http.StatusInternalServerError {
t.Errorf("expected an internal server error")
}
}
func TestAccountUUIDMiddleware(t *testing.T) {
svcCache.Invalidate(AccountsKey, "success")
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
m := AccountUUID(
Logger(log.NewLogger()),
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
AccountsClient(mockAccountUUIDMiddlewareAccSvc(false, true)),
SettingsRoleService(mockAccountUUIDMiddlewareRolesSvc(false)),
)(next)
r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil)
w := httptest.NewRecorder()
ctx := oidc.NewContext(r.Context(), &oidc.StandardClaims{Email: "success"})
r = r.WithContext(ctx)
m.ServeHTTP(w, r)
if r.Header.Get("x-access-token") == "" {
t.Errorf("expected a token")
}
}
func TestAccountUUIDMiddlewareWithDisabledAccount(t *testing.T) {
svcCache.Invalidate(AccountsKey, "failure")
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
m := AccountUUID(
Logger(log.NewLogger()),
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
AccountsClient(mockAccountUUIDMiddlewareAccSvc(false, false)),
SettingsRoleService(mockAccountUUIDMiddlewareRolesSvc(false)),
)(next)
r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil)
w := httptest.NewRecorder()
ctx := oidc.NewContext(r.Context(), &oidc.StandardClaims{Email: "failure"})
r = r.WithContext(ctx)
m.ServeHTTP(w, r)
rsp := w.Result()
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusUnauthorized {
t.Errorf("expected a disabled account to be unauthorized, got: %d", rsp.StatusCode)
}
}
func mockAccountUUIDMiddlewareAccSvc(retErr, accEnabled bool) proto.AccountsService {
return &proto.MockAccountsService{
ListFunc: func(ctx context.Context, in *proto.ListAccountsRequest, opts ...client.CallOption) (out *proto.ListAccountsResponse, err error) {
if retErr {
return nil, fmt.Errorf("error returned by mockAccountsService LIST")
}
return &proto.ListAccountsResponse{
Accounts: []*proto.Account{
{
Id: "yay",
AccountEnabled: accEnabled,
},
},
}, nil
},
}
}
func mockAccountUUIDMiddlewareRolesSvc(returnError bool) settings.RoleService {
return &settings.MockRoleService{
ListRoleAssignmentsFunc: func(ctx context.Context, req *settings.ListRoleAssignmentsRequest, opts ...client.CallOption) (res *settings.ListRoleAssignmentsResponse, err error) {
if returnError {
return nil, fmt.Errorf("error returned by mockRoleService.ListRoleAssignments")
}
return &settings.ListRoleAssignmentsResponse{
Assignments: []*settings.UserRoleAssignment{},
}, nil
},
}
}*/
+1 -1
View File
@@ -99,7 +99,7 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return
}
req.Header.Set("x-access-token", token)
req.Header.Set(tokenPkg.TokenHeader, token)
m.next.ServeHTTP(w, req)
}
@@ -0,0 +1,135 @@
package middleware
import (
"context"
"github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/cs3org/reva/pkg/token"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/oidc"
"github.com/owncloud/ocis/proxy/pkg/config"
"github.com/owncloud/ocis/proxy/pkg/user/backend"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestTokenIsAddedWithMailClaim(t *testing.T) {
sut := newMockAccountResolver(&userv1beta1.User{
Id: &userv1beta1.UserId{Idp: "https://idx.example.com", OpaqueId: "123"},
Mail: "foo@example.com",
}, nil)
req, rw := mockRequest(&oidc.StandardClaims{
Iss: "https://idx.example.com",
Email: "foo@example.com",
})
sut.ServeHTTP(rw, req)
token := req.Header.Get(token.TokenHeader)
assert.NotEmpty(t, token)
assert.Contains(t, token, "eyJ")
}
func TestTokenIsAddedWithUsernameClaim(t *testing.T) {
sut := newMockAccountResolver(&userv1beta1.User{
Id: &userv1beta1.UserId{Idp: "https://idx.example.com", OpaqueId: "123"},
Mail: "foo@example.com",
}, nil)
req, rw := mockRequest(&oidc.StandardClaims{
Iss: "https://idx.example.com",
PreferredUsername: "foo",
})
sut.ServeHTTP(rw, req)
token := req.Header.Get(token.TokenHeader)
assert.NotEmpty(t, token)
assert.Contains(t, token, "eyJ")
}
func TestNSkipOnNoClaims(t *testing.T) {
sut := newMockAccountResolver(nil, backend.ErrAccountDisabled)
req, rw := mockRequest(nil)
sut.ServeHTTP(rw, req)
token := req.Header.Get("x-access-token")
assert.Empty(t, token)
assert.Equal(t, http.StatusOK, rw.Code)
}
func TestUnauthorizedOnUserNotFound(t *testing.T) {
sut := newMockAccountResolver(nil, backend.ErrAccountNotFound)
req, rw := mockRequest(&oidc.StandardClaims{
Iss: "https://idx.example.com",
PreferredUsername: "foo",
})
sut.ServeHTTP(rw, req)
token := req.Header.Get(token.TokenHeader)
assert.Empty(t, token)
assert.Equal(t, http.StatusUnauthorized, rw.Code)
}
func TestUnauthorizedOnUserDisabled(t *testing.T) {
sut := newMockAccountResolver(nil, backend.ErrAccountDisabled)
req, rw := mockRequest(&oidc.StandardClaims{
Iss: "https://idx.example.com",
PreferredUsername: "foo",
})
sut.ServeHTTP(rw, req)
token := req.Header.Get(token.TokenHeader)
assert.Empty(t, token)
assert.Equal(t, http.StatusUnauthorized, rw.Code)
}
func TestInternalServerErrorOnMissingMailAndUsername(t *testing.T) {
sut := newMockAccountResolver(nil, backend.ErrAccountDisabled)
req, rw := mockRequest(&oidc.StandardClaims{
Iss: "https://idx.example.com",
})
sut.ServeHTTP(rw, req)
token := req.Header.Get(token.TokenHeader)
assert.Empty(t, token)
assert.Equal(t, http.StatusInternalServerError, rw.Code)
}
func newMockAccountResolver(userBackendResult *userv1beta1.User, userBackendErr error) http.Handler {
mock := &backend.UserBackendMock{
GetUserByClaimsFunc: func(ctx context.Context, claim string, value string, withRoles bool) (*userv1beta1.User, error) {
return userBackendResult, userBackendErr
},
}
return AccountResolver(
Logger(log.NewLogger()),
UserProvider(mock),
TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}),
AutoprovisionAccounts(false),
)(mockHandler{})
}
func mockRequest(claims *oidc.StandardClaims) (*http.Request, *httptest.ResponseRecorder) {
if claims == nil {
return httptest.NewRequest("GET", "http://example.com/foo", nil), httptest.NewRecorder()
}
ctx := oidc.NewContext(context.Background(), claims)
req := httptest.NewRequest("GET", "http://example.com/foo", nil).WithContext(ctx)
rw := httptest.NewRecorder()
return req, rw
}
type mockHandler struct{}
func (m mockHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {}