satellite/console: add more cross-user api tests
This change adds more endpoints to the cross-user api test. Issue: https://github.com/storj/storj/issues/6246 Change-Id: I4c3128c3a932c713b10499a8909836a599b79458
This commit is contained in:
parent
a2d37bc69a
commit
e599df03a8
@ -149,7 +149,13 @@ func (b *Buckets) GetBucketTotals(w http.ResponseWriter, r *http.Request) {
|
|||||||
Page: page,
|
Page: page,
|
||||||
}, before)
|
}, before)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if console.ErrUnauthorized.Has(err) {
|
||||||
|
b.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
b.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
b.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.NewEncoder(w).Encode(totals)
|
err = json.NewEncoder(w).Encode(totals)
|
||||||
|
@ -270,6 +270,11 @@ func (p *Payments) MakeCreditCardDefault(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
err = p.service.Payments().MakeCreditCardDefault(ctx, string(cardID))
|
err = p.service.Payments().MakeCreditCardDefault(ctx, string(cardID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if stripe.ErrCardNotFound.Has(err) {
|
||||||
|
p.serveJSONError(ctx, w, http.StatusNotFound, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if console.ErrUnauthorized.Has(err) {
|
if console.ErrUnauthorized.Has(err) {
|
||||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||||
return
|
return
|
||||||
@ -302,6 +307,10 @@ func (p *Payments) RemoveCreditCard(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
err = p.service.Payments().RemoveCreditCard(ctx, cardID)
|
err = p.service.Payments().RemoveCreditCard(ctx, cardID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if stripe.ErrCardNotFound.Has(err) {
|
||||||
|
p.serveJSONError(ctx, w, http.StatusNotFound, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
if console.ErrUnauthorized.Has(err) {
|
if console.ErrUnauthorized.Has(err) {
|
||||||
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
p.serveJSONError(ctx, w, http.StatusUnauthorized, err)
|
||||||
return
|
return
|
||||||
|
@ -16,11 +16,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"storj.io/common/testcontext"
|
"storj.io/common/testcontext"
|
||||||
"storj.io/common/uuid"
|
"storj.io/common/uuid"
|
||||||
"storj.io/storj/private/apigen"
|
"storj.io/storj/private/apigen"
|
||||||
"storj.io/storj/private/testplanet"
|
"storj.io/storj/private/testplanet"
|
||||||
|
"storj.io/storj/satellite"
|
||||||
"storj.io/storj/satellite/accounting"
|
"storj.io/storj/satellite/accounting"
|
||||||
"storj.io/storj/satellite/console"
|
"storj.io/storj/satellite/console"
|
||||||
"storj.io/storj/satellite/payments/storjscan/blockchaintest"
|
"storj.io/storj/satellite/payments/storjscan/blockchaintest"
|
||||||
@ -622,11 +624,15 @@ func TestProjects(t *testing.T) {
|
|||||||
func TestWrongUser(t *testing.T) {
|
func TestWrongUser(t *testing.T) {
|
||||||
testplanet.Run(t, testplanet.Config{
|
testplanet.Run(t, testplanet.Config{
|
||||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||||
|
Reconfigure: testplanet.Reconfigure{
|
||||||
|
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||||
|
config.Console.RateLimit.Burst = 4
|
||||||
|
},
|
||||||
|
},
|
||||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||||
test := newTest(t, ctx, planet)
|
test := newTest(t, ctx, planet)
|
||||||
authorizedUser := test.defaultUser()
|
authorizedUser := test.defaultUser()
|
||||||
unauthorizedUser := test.registerUser("user@mail.test", "#$Rnkl12i3nkljfds")
|
unauthorizedUser := test.registerUser("user@mail.test", "#$Rnkl12i3nkljfds")
|
||||||
test.login(unauthorizedUser.email, unauthorizedUser.password)
|
|
||||||
|
|
||||||
type endpointTest struct {
|
type endpointTest struct {
|
||||||
endpoint string
|
endpoint string
|
||||||
@ -635,10 +641,25 @@ func TestWrongUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
baseProjectsUrl := "/projects"
|
baseProjectsUrl := "/projects"
|
||||||
|
baseApiKeyUrl := "/api-keys"
|
||||||
baseProjectIdUrl := fmt.Sprintf("%s/%s", baseProjectsUrl, test.defaultProjectID())
|
baseProjectIdUrl := fmt.Sprintf("%s/%s", baseProjectsUrl, test.defaultProjectID())
|
||||||
getProjectResourceUrl := func(resource string) string {
|
getProjectResourceUrl := func(resource string) string {
|
||||||
return fmt.Sprintf("%s/%s", baseProjectIdUrl, resource)
|
return fmt.Sprintf("%s/%s", baseProjectIdUrl, resource)
|
||||||
}
|
}
|
||||||
|
getIdAppendedApiKeyUrl := func(resource string) string {
|
||||||
|
return fmt.Sprintf("%s/%s%s", baseApiKeyUrl, resource, test.defaultProjectID())
|
||||||
|
}
|
||||||
|
|
||||||
|
// login and create an api key and credit card to test deletion.
|
||||||
|
test.login(authorizedUser.email, authorizedUser.password)
|
||||||
|
resp, body := test.request(http.MethodPost, getIdAppendedApiKeyUrl("create/"), test.toJSON("some name"))
|
||||||
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
var response console.CreateAPIKeyResponse
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(body), &response))
|
||||||
|
|
||||||
|
apiKeyId := response.KeyInfo.ID.String()
|
||||||
|
|
||||||
|
test.login(unauthorizedUser.email, unauthorizedUser.password)
|
||||||
|
|
||||||
testCases := []endpointTest{
|
testCases := []endpointTest{
|
||||||
{
|
{
|
||||||
@ -680,20 +701,47 @@ func TestWrongUser(t *testing.T) {
|
|||||||
endpoint: getProjectResourceUrl("usage-limits"),
|
endpoint: getProjectResourceUrl("usage-limits"),
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
endpoint: "/buckets/bucket-names?projectID=" + test.defaultProjectID(),
|
||||||
|
method: http.MethodGet,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: "/buckets/usage-totals?limit=10&page=1&before=" + time.Now().Format(apigen.DateFormat) + "&projectID=" + test.defaultProjectID(),
|
||||||
|
method: http.MethodGet,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
endpoint: getProjectResourceUrl("daily-usage") + "?from=100000000&to=200000000000",
|
endpoint: getProjectResourceUrl("daily-usage") + "?from=100000000&to=200000000000",
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
endpoint: "/api-keys/create/" + test.defaultProjectID(),
|
endpoint: getIdAppendedApiKeyUrl("create/"),
|
||||||
method: http.MethodPost,
|
method: http.MethodPost,
|
||||||
body: "name",
|
body: "name",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
endpoint: getIdAppendedApiKeyUrl("delete-by-name?name=name&projectID="),
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: getIdAppendedApiKeyUrl("list-paged?limit=10&page=1&order=1&orderDirection=1&projectID="),
|
||||||
|
method: http.MethodGet,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: getIdAppendedApiKeyUrl("api-key-names?projectID="),
|
||||||
|
method: http.MethodGet,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: baseApiKeyUrl + "/delete-by-ids",
|
||||||
|
method: http.MethodDelete,
|
||||||
|
body: map[string]interface{}{
|
||||||
|
"ids": []string{apiKeyId},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(fmt.Sprintf("Unauthorized on %s", testCase.endpoint), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Unauthorized on %s", testCase.endpoint), func(t *testing.T) {
|
||||||
resp, body := test.request(testCase.method, testCase.endpoint, test.toJSON(testCase.body))
|
resp, body = test.request(testCase.method, testCase.endpoint, test.toJSON(testCase.body))
|
||||||
require.Contains(t, body, "not authorized")
|
require.Contains(t, body, "not authorized")
|
||||||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@ -703,7 +751,7 @@ func TestWrongUser(t *testing.T) {
|
|||||||
test.login(authorizedUser.email, authorizedUser.password)
|
test.login(authorizedUser.email, authorizedUser.password)
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(fmt.Sprintf("Authorized on %s", testCase.endpoint), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Authorized on %s", testCase.endpoint), func(t *testing.T) {
|
||||||
resp, body := test.request(testCase.method, testCase.endpoint, test.toJSON(testCase.body))
|
resp, body = test.request(testCase.method, testCase.endpoint, test.toJSON(testCase.body))
|
||||||
require.NotContains(t, body, "not authorized")
|
require.NotContains(t, body, "not authorized")
|
||||||
require.NotEqual(t, http.StatusUnauthorized, resp.StatusCode)
|
require.NotEqual(t, http.StatusUnauthorized, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@ -762,6 +810,10 @@ func (test *test) url(suffix string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (test *test) toJSON(v interface{}) io.Reader {
|
func (test *test) toJSON(v interface{}) io.Reader {
|
||||||
|
if str, ok := v.(string); ok {
|
||||||
|
return strings.NewReader(str)
|
||||||
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(v)
|
data, err := json.Marshal(v)
|
||||||
require.NoError(test.t, err)
|
require.NoError(test.t, err)
|
||||||
return strings.NewReader(string(data))
|
return strings.NewReader(string(data))
|
||||||
@ -784,6 +836,7 @@ func (test *test) login(email, password string) Response {
|
|||||||
"email": email,
|
"email": email,
|
||||||
"password": password,
|
"password": password,
|
||||||
}))
|
}))
|
||||||
|
require.Equal(test.t, http.StatusOK, resp.StatusCode)
|
||||||
cookie := findCookie(resp, "_tokenKey")
|
cookie := findCookie(resp, "_tokenKey")
|
||||||
require.NotNil(test.t, cookie)
|
require.NotNil(test.t, cookie)
|
||||||
|
|
||||||
|
@ -2460,7 +2460,7 @@ func (s *Service) GetAllAPIKeyNamesByProjectID(ctx context.Context, projectID uu
|
|||||||
|
|
||||||
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Error.Wrap(err)
|
return nil, ErrUnauthorized.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
names, err = s.store.APIKeys().GetAllNamesByProjectID(ctx, isMember.project.ID)
|
names, err = s.store.APIKeys().GetAllNamesByProjectID(ctx, isMember.project.ID)
|
||||||
@ -2483,7 +2483,7 @@ func (s *Service) DeleteAPIKeyByNameAndProjectID(ctx context.Context, name strin
|
|||||||
|
|
||||||
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Error.Wrap(err)
|
return ErrUnauthorized.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := s.store.APIKeys().GetByNameAndProjectID(ctx, name, isMember.project.ID)
|
key, err := s.store.APIKeys().GetByNameAndProjectID(ctx, name, isMember.project.ID)
|
||||||
@ -2599,7 +2599,7 @@ func (s *Service) GetBucketTotals(ctx context.Context, projectID uuid.UUID, curs
|
|||||||
|
|
||||||
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Error.Wrap(err)
|
return nil, ErrUnauthorized.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
usage, err := s.projectAccounting.GetBucketTotals(ctx, isMember.project.ID, cursor, before)
|
usage, err := s.projectAccounting.GetBucketTotals(ctx, isMember.project.ID, cursor, before)
|
||||||
@ -2622,7 +2622,7 @@ func (s *Service) GetAllBucketNames(ctx context.Context, projectID uuid.UUID) (_
|
|||||||
|
|
||||||
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
isMember, err := s.isProjectMember(ctx, user.ID, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Error.Wrap(err)
|
return nil, ErrUnauthorized.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
listOptions := buckets.ListOptions{
|
listOptions := buckets.ListOptions{
|
||||||
|
@ -5,6 +5,7 @@ package stripe
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/stripe/stripe-go/v72"
|
"github.com/stripe/stripe-go/v72"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
@ -20,6 +21,10 @@ var (
|
|||||||
ErrDefaultCard = errs.Class("default card")
|
ErrDefaultCard = errs.Class("default card")
|
||||||
// ErrDuplicateCard is returned when a user tries to add duplicate card.
|
// ErrDuplicateCard is returned when a user tries to add duplicate card.
|
||||||
ErrDuplicateCard = errs.Class("duplicate card")
|
ErrDuplicateCard = errs.Class("duplicate card")
|
||||||
|
|
||||||
|
// UnattachedErrString is part of the err string returned by stripe if a payment
|
||||||
|
// method does not belong to a customer.
|
||||||
|
UnattachedErrString = "The payment method must be attached to the customer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// creditCards is an implementation of payments.CreditCards.
|
// creditCards is an implementation of payments.CreditCards.
|
||||||
@ -165,6 +170,9 @@ func (creditCards *creditCards) MakeDefault(ctx context.Context, userID uuid.UUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = creditCards.service.stripeClient.Customers().Update(customerID, params)
|
_, err = creditCards.service.stripeClient.Customers().Update(customerID, params)
|
||||||
|
if err != nil && strings.Contains(err.Error(), UnattachedErrString) {
|
||||||
|
return ErrCardNotFound.New("this card is not attached to this account.")
|
||||||
|
}
|
||||||
|
|
||||||
return Error.Wrap(err)
|
return Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user