d999a963ca
This change removes all the separate implementations for `apiservice.serveJSONError()` and defines one for every service to use in `consoleapi/common.go`. Change-Id: Iabf184e5cba69a98eb25936ce11ebd07f02c8ff3
240 lines
6.6 KiB
Go
240 lines
6.6 KiB
Go
// Copyright (C) 2020 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package consoleapi_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"testing/quick"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
|
|
"storj.io/common/testcontext"
|
|
"storj.io/common/uuid"
|
|
"storj.io/storj/private/testplanet"
|
|
"storj.io/storj/satellite"
|
|
"storj.io/storj/satellite/console/consoleweb/consoleapi"
|
|
)
|
|
|
|
func TestAuth_Register(t *testing.T) {
|
|
testplanet.Run(t, testplanet.Config{
|
|
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 0,
|
|
Reconfigure: testplanet.Reconfigure{
|
|
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
|
config.Console.OpenRegistrationEnabled = true
|
|
config.Console.RateLimit.Burst = 10
|
|
},
|
|
},
|
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
|
for i, test := range []struct {
|
|
Partner string
|
|
ValidPartner bool
|
|
}{
|
|
{Partner: "minio", ValidPartner: true},
|
|
{Partner: "Minio", ValidPartner: true},
|
|
{Partner: "Raiden Network", ValidPartner: true},
|
|
{Partner: "Raiden nEtwork", ValidPartner: true},
|
|
{Partner: "invalid-name", ValidPartner: false},
|
|
} {
|
|
func() {
|
|
registerData := struct {
|
|
FullName string `json:"fullName"`
|
|
ShortName string `json:"shortName"`
|
|
Email string `json:"email"`
|
|
Partner string `json:"partner"`
|
|
PartnerID string `json:"partnerId"`
|
|
Password string `json:"password"`
|
|
SecretInput string `json:"secret"`
|
|
ReferrerUserID string `json:"referrerUserId"`
|
|
IsProfessional bool `json:"isProfessional"`
|
|
Position string `json:"Position"`
|
|
CompanyName string `json:"CompanyName"`
|
|
EmployeeCount string `json:"EmployeeCount"`
|
|
}{
|
|
FullName: "testuser" + strconv.Itoa(i),
|
|
ShortName: "test",
|
|
Email: "user@test" + strconv.Itoa(i),
|
|
Partner: test.Partner,
|
|
Password: "abc123",
|
|
IsProfessional: true,
|
|
Position: "testposition",
|
|
CompanyName: "companytestname",
|
|
EmployeeCount: "0",
|
|
}
|
|
|
|
jsonBody, err := json.Marshal(registerData)
|
|
require.NoError(t, err)
|
|
|
|
url := "http://" + planet.Satellites[0].API.Console.Listener.Addr().String() + "/api/v0/auth/register"
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonBody))
|
|
require.NoError(t, err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
result, err := http.DefaultClient.Do(req)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, result.StatusCode)
|
|
|
|
defer func() {
|
|
err = result.Body.Close()
|
|
require.NoError(t, err)
|
|
}()
|
|
|
|
body, err := ioutil.ReadAll(result.Body)
|
|
require.NoError(t, err)
|
|
|
|
var userID uuid.UUID
|
|
err = json.Unmarshal(body, &userID)
|
|
require.NoError(t, err)
|
|
|
|
user, err := planet.Satellites[0].API.Console.Service.GetUser(ctx, userID)
|
|
require.NoError(t, err)
|
|
|
|
if test.ValidPartner {
|
|
info, err := planet.Satellites[0].API.Marketing.PartnersService.ByName(ctx, test.Partner)
|
|
require.NoError(t, err)
|
|
require.Equal(t, info.UUID, user.PartnerID)
|
|
} else {
|
|
require.Equal(t, uuid.UUID{}, user.PartnerID)
|
|
}
|
|
}()
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestDeleteAccount(t *testing.T) {
|
|
ctx := testcontext.New(t)
|
|
|
|
// We do a black box testing because currently we don't allow to delete
|
|
// accounts through the API hence we must always return an error response.
|
|
|
|
config := &quick.Config{
|
|
Values: func(values []reflect.Value, rnd *rand.Rand) {
|
|
// TODO: use or implement a better and thorough HTTP Request random generator
|
|
|
|
var method string
|
|
switch rnd.Intn(9) {
|
|
case 0:
|
|
method = http.MethodGet
|
|
case 1:
|
|
method = http.MethodHead
|
|
case 2:
|
|
method = http.MethodPost
|
|
case 3:
|
|
method = http.MethodPut
|
|
case 4:
|
|
method = http.MethodPatch
|
|
case 5:
|
|
method = http.MethodDelete
|
|
case 6:
|
|
method = http.MethodConnect
|
|
case 7:
|
|
method = http.MethodOptions
|
|
case 8:
|
|
method = http.MethodTrace
|
|
default:
|
|
t.Fatal("unexpected random value for HTTP method selection")
|
|
}
|
|
|
|
var path string
|
|
{
|
|
|
|
val, ok := quick.Value(reflect.TypeOf(""), rnd)
|
|
require.True(t, ok, "quick.Values generator function couldn't generate a string")
|
|
path = url.PathEscape(val.String())
|
|
}
|
|
|
|
var query string
|
|
{
|
|
nparams := rnd.Intn(27)
|
|
params := make([]string, nparams)
|
|
|
|
for i := 0; i < nparams; i++ {
|
|
val, ok := quick.Value(reflect.TypeOf(""), rnd)
|
|
require.True(t, ok, "quick.Values generator function couldn't generate a string")
|
|
param := val.String()
|
|
|
|
val, ok = quick.Value(reflect.TypeOf(""), rnd)
|
|
require.True(t, ok, "quick.Values generator function couldn't generate a string")
|
|
param += "=" + val.String()
|
|
|
|
params[i] = param
|
|
}
|
|
|
|
query = url.QueryEscape(strings.Join(params, "&"))
|
|
}
|
|
|
|
var body io.Reader
|
|
{
|
|
val, ok := quick.Value(reflect.TypeOf([]byte(nil)), rnd)
|
|
require.True(t, ok, "quick.Values generator function couldn't generate a byte slice")
|
|
body = bytes.NewReader(val.Bytes())
|
|
}
|
|
|
|
withQuery := ""
|
|
if len(query) > 0 {
|
|
withQuery = "?"
|
|
}
|
|
|
|
reqURL, err := url.Parse("//storj.io/" + path + withQuery + query)
|
|
require.NoError(t, err, "error when generating a random URL")
|
|
req, err := http.NewRequestWithContext(ctx, method, reqURL.String(), body)
|
|
require.NoError(t, err, "error when geneating a random request")
|
|
values[0] = reflect.ValueOf(req)
|
|
},
|
|
}
|
|
|
|
expectedHandler := func(_ *http.Request) (status int, body []byte) {
|
|
return http.StatusNotImplemented, []byte("{\"error\":\"not implemented\"}\n")
|
|
}
|
|
|
|
actualHandler := func(r *http.Request) (status int, body []byte) {
|
|
rr := httptest.NewRecorder()
|
|
authController := consoleapi.NewAuth(zap.L(), nil, nil, nil, nil, nil, "", "", "", "")
|
|
authController.DeleteAccount(rr, r)
|
|
|
|
//nolint:bodyclose
|
|
result := rr.Result()
|
|
defer func() {
|
|
err := result.Body.Close()
|
|
require.NoError(t, err)
|
|
}()
|
|
|
|
body, err := ioutil.ReadAll(result.Body)
|
|
require.NoError(t, err)
|
|
|
|
return result.StatusCode, body
|
|
|
|
}
|
|
|
|
err := quick.CheckEqual(expectedHandler, actualHandler, config)
|
|
if err != nil {
|
|
fmt.Printf("%+v\n", err)
|
|
var cerr *quick.CheckEqualError
|
|
require.True(t, errors.As(err, &cerr))
|
|
|
|
t.Fatalf(`DeleteAccount handler has returned a different response:
|
|
round: %d
|
|
input args: %+v
|
|
expected response:
|
|
status code: %d
|
|
response body: %s
|
|
returned response:
|
|
status code: %d
|
|
response body: %s
|
|
`, cerr.Count, cerr.In, cerr.Out1[0], cerr.Out1[1], cerr.Out2[0], cerr.Out2[1])
|
|
}
|
|
}
|