hub/internal/handlers/org/handlers_test.go

966 lines
24 KiB
Go

package org
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"github.com/artifacthub/hub/internal/authz"
"github.com/artifacthub/hub/internal/handlers/helpers"
"github.com/artifacthub/hub/internal/hub"
"github.com/artifacthub/hub/internal/org"
"github.com/artifacthub/hub/internal/tests"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestMain(m *testing.M) {
zerolog.SetGlobalLevel(zerolog.Disabled)
os.Exit(m.Run())
}
func TestAdd(t *testing.T) {
t.Run("invalid organization provided", func(t *testing.T) {
testCases := []struct {
description string
orgJSON string
omErr error
}{
{
"no organization provided",
"",
nil,
},
{
"invalid json",
"-",
nil,
},
{
"missing name",
`{"display_name": "Display Name"}`,
hub.ErrInvalidInput,
},
{
"invalid name",
`{"name": "_org"}`,
hub.ErrInvalidInput,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("POST", "/", strings.NewReader(tc.orgJSON))
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
hw := newHandlersWrapper()
if tc.omErr != nil {
hw.om.On("Add", r.Context(), mock.Anything).Return(tc.omErr)
}
hw.h.Add(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
t.Run("valid organization provided", func(t *testing.T) {
orgJSON := `
{
"name": "org1",
"display_name": "Organization 1",
"description": "description"
}
`
o := &hub.Organization{}
_ = json.Unmarshal([]byte(orgJSON), &o)
testCases := []struct {
description string
err error
expectedStatusCode int
}{
{
"add organization succeeded",
nil,
http.StatusCreated,
},
{
"error adding organization",
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("POST", "/", strings.NewReader(orgJSON))
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
hw := newHandlersWrapper()
hw.om.On("Add", r.Context(), o).Return(tc.err)
hw.h.Add(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
}
func TestAddMember(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
nil,
http.StatusCreated,
},
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
hub.ErrInsufficientPrivilege,
http.StatusForbidden,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
var desc string
if tc.omErr != nil {
desc = tc.omErr.Error()
}
t.Run(desc, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("POST", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName", "userAlias"},
Values: []string{"org1", "userAlias"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("AddMember", r.Context(), "org1", "userAlias").Return(tc.omErr)
hw.h.AddMember(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
}
func TestCheckAvailability(t *testing.T) {
t.Run("invalid input", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("HEAD", "/?v=value", nil)
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"resourceKind"},
Values: []string{"invalid"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("CheckAvailability", r.Context(), "invalid", "value").
Return(false, hub.ErrInvalidInput)
hw.h.CheckAvailability(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
hw.om.AssertExpectations(t)
})
t.Run("valid input", func(t *testing.T) {
t.Run("check availability succeeded", func(t *testing.T) {
testCases := []struct {
resourceKind string
available bool
}{
{
"organizationName",
true,
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("resource kind: %s", tc.resourceKind), func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("HEAD", "/?v=value", nil)
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"resourceKind"},
Values: []string{tc.resourceKind},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("CheckAvailability", r.Context(), tc.resourceKind, "value").Return(tc.available, nil)
hw.h.CheckAvailability(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
if tc.available {
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
} else {
assert.Equal(t, http.StatusNoContent, resp.StatusCode)
}
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
hw.om.AssertExpectations(t)
})
}
})
t.Run("check availability failed", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("HEAD", "/?v=value", nil)
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"resourceKind"},
Values: []string{"organizationName"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("CheckAvailability", r.Context(), "organizationName", "value").
Return(false, tests.ErrFakeDB)
hw.h.CheckAvailability(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
hw.om.AssertExpectations(t)
})
})
}
func TestConfirmMembership(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
nil,
http.StatusNoContent,
},
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
var desc string
if tc.omErr != nil {
desc = tc.omErr.Error()
}
t.Run(desc, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("PUT", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("ConfirmMembership", r.Context(), "org1").Return(tc.omErr)
hw.h.ConfirmMembership(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
}
func TestDelete(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
nil,
http.StatusNoContent,
},
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
hub.ErrInsufficientPrivilege,
http.StatusForbidden,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
var desc string
if tc.omErr != nil {
desc = tc.omErr.Error()
}
t.Run(desc, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("DELETE", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("Delete", r.Context(), "org1").Return(tc.omErr)
hw.h.Delete(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
}
func TestDeleteMember(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
nil,
http.StatusNoContent,
},
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
hub.ErrInsufficientPrivilege,
http.StatusForbidden,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
var desc string
if tc.omErr != nil {
desc = tc.omErr.Error()
}
t.Run(desc, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("DELETE", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName", "userAlias"},
Values: []string{"org1", "userAlias"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("DeleteMember", r.Context(), "org1", "userAlias").Return(tc.omErr)
hw.h.DeleteMember(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
}
func TestGet(t *testing.T) {
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
t.Run("error getting organization", func(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
t.Run(tc.omErr.Error(), func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("GetJSON", r.Context(), "org1").Return(nil, tc.omErr)
hw.h.Get(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
t.Run("get organization succeeded", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("GetJSON", r.Context(), "org1").Return([]byte("dataJSON"), nil)
hw.h.Get(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
data, _ := io.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", h.Get("Content-Type"))
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
assert.Equal(t, []byte("dataJSON"), data)
hw.om.AssertExpectations(t)
})
}
func TestGetAuthorizationPolicy(t *testing.T) {
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
t.Run("error getting authorization policy", func(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
t.Run(tc.omErr.Error(), func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("GetAuthorizationPolicyJSON", r.Context(), "org1").Return(nil, tc.omErr)
hw.h.GetAuthorizationPolicy(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
t.Run("get authorization policy succeeded", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("GetAuthorizationPolicyJSON", r.Context(), "org1").Return([]byte("dataJSON"), nil)
hw.h.GetAuthorizationPolicy(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
data, _ := io.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", h.Get("Content-Type"))
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
assert.Equal(t, []byte("dataJSON"), data)
hw.om.AssertExpectations(t)
})
}
func TestGetByUser(t *testing.T) {
t.Run("get user organizations succeeded", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
hw := newHandlersWrapper()
hw.om.On("GetByUserJSON", r.Context(), &hub.Pagination{
Limit: 10,
Offset: 1,
}).Return(&hub.JSONQueryResult{
Data: []byte("dataJSON"),
TotalCount: 1,
}, nil)
hw.h.GetByUser(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
data, _ := io.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, h.Get(helpers.PaginationTotalCount), "1")
assert.Equal(t, "application/json", h.Get("Content-Type"))
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
assert.Equal(t, []byte("dataJSON"), data)
hw.om.AssertExpectations(t)
})
t.Run("error getting user organizations", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
hw := newHandlersWrapper()
hw.om.On("GetByUserJSON", r.Context(), &hub.Pagination{
Limit: 10,
Offset: 1,
}).Return(nil, tests.ErrFakeDB)
hw.h.GetByUser(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
func TestGetMembers(t *testing.T) {
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
t.Run("error getting organization members", func(t *testing.T) {
testCases := []struct {
omErr error
expectedStatusCode int
}{
{
hub.ErrInvalidInput,
http.StatusBadRequest,
},
{
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
t.Run(tc.omErr.Error(), func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("GetMembersJSON", r.Context(), "org1", &hub.Pagination{
Limit: 10,
Offset: 1,
}).Return(nil, tc.omErr)
hw.h.GetMembers(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
t.Run("get organization members succeeded", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("GetMembersJSON", r.Context(), "org1", &hub.Pagination{
Limit: 10,
Offset: 1,
}).Return(&hub.JSONQueryResult{
Data: []byte("dataJSON"),
TotalCount: 1,
}, nil)
hw.h.GetMembers(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
data, _ := io.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, h.Get(helpers.PaginationTotalCount), "1")
assert.Equal(t, "application/json", h.Get("Content-Type"))
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
assert.Equal(t, []byte("dataJSON"), data)
hw.om.AssertExpectations(t)
})
}
func TestUpdate(t *testing.T) {
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
t.Run("invalid organization provided", func(t *testing.T) {
testCases := []struct {
description string
orgJSON string
omErr error
}{
{
"no organization provided",
"",
nil,
},
{
"invalid json",
"-",
nil,
},
{
"invalid logo image id",
`{"name": "org1", "logo_image_id": "invalid"}`,
hub.ErrInvalidInput,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("PUT", "/", strings.NewReader(tc.orgJSON))
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
if tc.omErr != nil {
hw.om.On("Update", r.Context(), "org1", mock.Anything).Return(tc.omErr)
}
hw.h.Update(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
t.Run("valid organization provided", func(t *testing.T) {
orgJSON := `
{
"name": "org1",
"display_name": "Organization 1 updated",
"description": "description updated"
}
`
o := &hub.Organization{}
_ = json.Unmarshal([]byte(orgJSON), &o)
testCases := []struct {
description string
err error
expectedStatusCode int
}{
{
"organization update succeeded",
nil,
http.StatusNoContent,
},
{
"error updating organization (insufficiente privilege)",
hub.ErrInsufficientPrivilege,
http.StatusForbidden,
},
{
"error updating organization (db error)",
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("PUT", "/", strings.NewReader(orgJSON))
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("Update", r.Context(), "org1", o).Return(tc.err)
hw.h.Update(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
}
func TestUpdateAuthorizationPolicy(t *testing.T) {
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
t.Run("invalid authorization policy provided", func(t *testing.T) {
testCases := []struct {
description string
policyJSON string
omErr error
}{
{
"no authorization policy provided",
"",
nil,
},
{
"invalid json",
"-",
nil,
},
{
"invalid policy data",
`{"policy_data": "invalid"}`,
hub.ErrInvalidInput,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("PUT", "/", strings.NewReader(tc.policyJSON))
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
if tc.omErr != nil {
hw.om.On("UpdateAuthorizationPolicy", r.Context(), "org1", mock.Anything).Return(tc.omErr)
}
hw.h.UpdateAuthorizationPolicy(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
t.Run("valid authorization policy provided", func(t *testing.T) {
policyJSON := `
{
"authorization_enabled": true,
"predefined_policy": "rbac.v1",
"custom_policy": "",
"policy_data": "{\"k\": \"v\"}"
}
`
policy := &hub.AuthorizationPolicy{}
_ = json.Unmarshal([]byte(policyJSON), &policy)
testCases := []struct {
description string
err error
expectedStatusCode int
}{
{
"authorization policy update succeeded",
nil,
http.StatusNoContent,
},
{
"error updating organization policy (insufficiente privilege)",
hub.ErrInsufficientPrivilege,
http.StatusForbidden,
},
{
"error updating organization policy (db error)",
tests.ErrFakeDB,
http.StatusInternalServerError,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("PUT", "/", strings.NewReader(policyJSON))
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.om.On("UpdateAuthorizationPolicy", r.Context(), "org1", policy).Return(tc.err)
hw.h.UpdateAuthorizationPolicy(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
hw.om.AssertExpectations(t)
})
}
})
}
func TestGetUserAllowedActions(t *testing.T) {
rctx := &chi.Context{
URLParams: chi.RouteParams{
Keys: []string{"orgName"},
Values: []string{"org1"},
},
}
t.Run("get allowed actions failed", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.az.On("GetAllowedActions", r.Context(), "userID", "org1").Return(nil, tests.ErrFake)
hw.h.GetUserAllowedActions(w, r)
resp := w.Result()
defer resp.Body.Close()
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
hw.om.AssertExpectations(t)
})
t.Run("get allowed actions succeeded", func(t *testing.T) {
t.Parallel()
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
hw := newHandlersWrapper()
hw.az.On("GetAllowedActions", r.Context(), "userID", "org1").Return([]hub.Action{
hub.AddOrganizationMember,
hub.DeleteOrganizationMember,
}, nil)
hw.h.GetUserAllowedActions(w, r)
resp := w.Result()
defer resp.Body.Close()
h := resp.Header
data, _ := io.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", h.Get("Content-Type"))
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
assert.Equal(t, []byte(`["addOrganizationMember","deleteOrganizationMember"]`), data)
hw.om.AssertExpectations(t)
})
}
type handlersWrapper struct {
cfg *viper.Viper
om *org.ManagerMock
az *authz.AuthorizerMock
h *Handlers
}
func newHandlersWrapper() *handlersWrapper {
cfg := viper.New()
cfg.Set("server.baseURL", "baseURL")
om := &org.ManagerMock{}
az := &authz.AuthorizerMock{}
return &handlersWrapper{
cfg: cfg,
om: om,
az: az,
h: NewHandlers(om, az, cfg),
}
}