satellite/admin: Response 404 when entity not found

* Add test cases to verify that all the endpoint that target a specific
  entity respond 404 status code when the entity isn't found.
* Fix the endpoints that target a specific entity which responded a 500
  status code response when the entity didn't exist to respond with 404
  status code.

Additionally:

* Simplify some tests using an existing test helper function.
* Rename test functions to start with the entity name (e.g. Project,
  User, etc.) for easing to run a set of test with the `-run` Go test
  flag.

Change-Id: I82aad92e429207b72932ad4b79c08db6b486a19a
This commit is contained in:
Ivan Fraixedes 2021-10-07 12:42:25 +02:00
parent fb0d055a41
commit 05960b2cf0
No known key found for this signature in database
GPG Key ID: 042B474597F96DB7
6 changed files with 214 additions and 174 deletions

View File

@ -4,7 +4,9 @@
package admin
import (
"database/sql"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
@ -127,6 +129,11 @@ func (server *Server) deleteAPIKey(w http.ResponseWriter, r *http.Request) {
}
info, err := server.db.Console().APIKeys().GetByHead(ctx, apikey.Head())
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, "API key does not exist",
"", http.StatusNotFound)
return
}
if err != nil {
sendJSONError(w, "could not get apikey id",
err.Error(), http.StatusInternalServerError)
@ -167,6 +174,11 @@ func (server *Server) deleteAPIKeyByName(w http.ResponseWriter, r *http.Request)
}
info, err := server.db.Console().APIKeys().GetByNameAndProjectID(ctx, apikeyName, projectUUID)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, "API key with specified name does not exist",
"", http.StatusNotFound)
return
}
if err != nil {
sendJSONError(w, "could not get apikey id",
err.Error(), http.StatusInternalServerError)

View File

@ -23,7 +23,7 @@ import (
"storj.io/storj/satellite/console"
)
func TestAddApiKey(t *testing.T) {
func TestApiKeyAdd(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -75,7 +75,7 @@ func TestAddApiKey(t *testing.T) {
})
}
func TestDeleteApiKey(t *testing.T) {
func TestApiKeyDelete(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -94,26 +94,22 @@ func TestDeleteApiKey(t *testing.T) {
require.Len(t, keys.APIKeys, 1)
apikey := planet.Uplinks[0].APIKey[planet.Satellites[0].ID()].Serialize()
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("http://"+address.String()+"/api/apikeys/%s", apikey), nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
responseBody, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Len(t, responseBody, 0)
link := fmt.Sprintf("http://"+address.String()+"/api/apikeys/%s", apikey)
body := assertReq(ctx, t, link, http.MethodDelete, "", http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
require.Len(t, body, 0)
keys, err = planet.Satellites[0].DB.Console().APIKeys().GetPagedByProjectID(ctx, projectID, console.APIKeyCursor{Page: 1, Limit: 10})
require.NoError(t, err)
require.Len(t, keys.APIKeys, 0)
// Delete a deleted key returns Not Found.
body = assertReq(ctx, t, link, http.MethodDelete, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
}
func TestDeleteApiKeyByName(t *testing.T) {
func TestApiKeyDelete_ByName(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -131,26 +127,21 @@ func TestDeleteApiKeyByName(t *testing.T) {
require.NoError(t, err)
require.Len(t, keys.APIKeys, 1)
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("http://"+address.String()+"/api/projects/%s/apikeys/%s", projectID.String(), keys.APIKeys[0].Name), nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
responseBody, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Len(t, responseBody, 0)
link := fmt.Sprintf("http://"+address.String()+"/api/projects/%s/apikeys/%s", projectID.String(), keys.APIKeys[0].Name)
body := assertReq(ctx, t, link, http.MethodDelete, "", http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
require.Len(t, body, 0)
keys, err = planet.Satellites[0].DB.Console().APIKeys().GetPagedByProjectID(ctx, projectID, console.APIKeyCursor{Page: 1, Limit: 10})
require.NoError(t, err)
require.Len(t, keys.APIKeys, 0)
// Delete a deleted key returns Not Found.
body = assertReq(ctx, t, link, http.MethodDelete, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
}
func TestListAPIKeys(t *testing.T) {
func TestApiKeysList(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,

View File

@ -107,6 +107,11 @@ func (server *Server) getProjectLimit(w http.ResponseWriter, r *http.Request) {
}
project, err := server.db.Console().Projects().Get(ctx, projectUUID)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, "project with specified uuid does not exist",
"", http.StatusNotFound)
return
}
if err != nil {
sendJSONError(w, "failed to get project",
err.Error(), http.StatusInternalServerError)
@ -192,6 +197,19 @@ func (server *Server) putProjectLimit(w http.ResponseWriter, r *http.Request) {
return
}
// check if the project exists.
_, err = server.db.Console().Projects().Get(ctx, projectUUID)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, "project with specified uuid does not exist",
"", http.StatusNotFound)
return
}
if err != nil {
sendJSONError(w, "failed to get project",
err.Error(), http.StatusInternalServerError)
return
}
if arguments.Usage != nil {
if *arguments.Usage < 0 {
sendJSONError(w, "negative usage",
@ -355,7 +373,7 @@ func (server *Server) renameProject(w http.ResponseWriter, r *http.Request) {
project, err := server.db.Console().Projects().Get(ctx, projectUUID)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, "project with specified uuid does not exist",
"", http.StatusBadRequest)
"", http.StatusNotFound)
return
}
if err != nil {

View File

@ -26,7 +26,7 @@ import (
"storj.io/storj/satellite/console"
)
func TestAPI(t *testing.T) {
func TestProjectGet(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -42,11 +42,8 @@ func TestAPI(t *testing.T) {
project, err := sat.DB.Console().Projects().Get(ctx, planet.Uplinks[0].Projects[0].ID)
require.NoError(t, err)
link := "http://" + address.String() + "/api/projects/" + project.ID.String()
linkLimit := link + "/limit"
t.Run("GetProject", func(t *testing.T) {
require.NoError(t, err)
t.Run("OK", func(t *testing.T) {
link := "http://" + address.String() + "/api/projects/" + project.ID.String()
expected := fmt.Sprintf(
`{"id":"%s","name":"%s","description":"%s","partnerId":"%s","ownerId":"%s","rateLimit":null,"burstLimit":null,"maxBuckets":null,"createdAt":"%s","memberCount":0,"storageLimit":"25.00 GB","bandwidthLimit":"25.00 GB"}`,
project.ID.String(),
@ -59,11 +56,73 @@ func TestAPI(t *testing.T) {
assertGet(ctx, t, link, expected, planet.Satellites[0].Config.Console.AuthToken)
})
t.Run("GetProjectLimits", func(t *testing.T) {
t.Run("Not Found", func(t *testing.T) {
id, err := uuid.New()
require.NoError(t, err)
link := "http://" + address.String() + "/api/projects/" + id.String() + "/limit"
body := assertReq(ctx, t, link, http.MethodGet, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
})
}
func TestProjectLimit(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
UplinkCount: 1,
Reconfigure: testplanet.Reconfigure{
Satellite: func(_ *zap.Logger, _ int, config *satellite.Config) {
config.Admin.Address = "127.0.0.1:0"
},
},
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
sat := planet.Satellites[0]
address := sat.Admin.Admin.Listener.Addr()
project, err := sat.DB.Console().Projects().Get(ctx, planet.Uplinks[0].Projects[0].ID)
require.NoError(t, err)
linkLimit := "http://" + address.String() + "/api/projects/" + project.ID.String() + "/limit"
t.Run("Get OK", func(t *testing.T) {
assertGet(ctx, t, linkLimit, `{"usage":{"amount":"25.00 GB","bytes":25000000000},"bandwidth":{"amount":"25.00 GB","bytes":25000000000},"rate":{"rps":0},"maxBuckets":0}`, planet.Satellites[0].Config.Console.AuthToken)
})
t.Run("UpdateUsage", func(t *testing.T) {
t.Run("Get Not Found", func(t *testing.T) {
id, err := uuid.New()
require.NoError(t, err)
link := "http://" + address.String() + "/api/projects/" + id.String() + "/limit"
body := assertReq(ctx, t, link, http.MethodGet, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
t.Run("Update Not Found", func(t *testing.T) {
id, err := uuid.New()
require.NoError(t, err)
link := "http://" + address.String() + "/api/projects/" + id.String() + "/limit?usage=100000000"
body := assertReq(ctx, t, link, http.MethodPut, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
t.Run("Update Nothing", func(t *testing.T) {
expectedBody := assertReq(ctx, t, linkLimit, http.MethodGet, "", http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, linkLimit, nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.NoError(t, response.Body.Close())
assertGet(ctx, t, linkLimit, string(expectedBody), planet.Satellites[0].Config.Console.AuthToken)
})
t.Run("Update Usage", func(t *testing.T) {
data := url.Values{"usage": []string{"1TiB"}}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, linkLimit, strings.NewReader(data.Encode()))
require.NoError(t, err)
@ -89,7 +148,7 @@ func TestAPI(t *testing.T) {
assertGet(ctx, t, linkLimit, `{"usage":{"amount":"1.00 GB","bytes":1000000000},"bandwidth":{"amount":"25.00 GB","bytes":25000000000},"rate":{"rps":0},"maxBuckets":0}`, planet.Satellites[0].Config.Console.AuthToken)
})
t.Run("UpdateBandwidth", func(t *testing.T) {
t.Run("Update Bandwidth", func(t *testing.T) {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, linkLimit+"?bandwidth=1MB", nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
@ -102,7 +161,7 @@ func TestAPI(t *testing.T) {
assertGet(ctx, t, linkLimit, `{"usage":{"amount":"1.00 GB","bytes":1000000000},"bandwidth":{"amount":"1.00 MB","bytes":1000000},"rate":{"rps":0},"maxBuckets":0}`, planet.Satellites[0].Config.Console.AuthToken)
})
t.Run("UpdateRate", func(t *testing.T) {
t.Run("Update Rate", func(t *testing.T) {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, linkLimit+"?rate=100", nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
@ -114,7 +173,8 @@ func TestAPI(t *testing.T) {
assertGet(ctx, t, linkLimit, `{"usage":{"amount":"1.00 GB","bytes":1000000000},"bandwidth":{"amount":"1.00 MB","bytes":1000000},"rate":{"rps":100},"maxBuckets":0}`, planet.Satellites[0].Config.Console.AuthToken)
})
t.Run("UpdateBuckets", func(t *testing.T) {
t.Run("Update Buckets", func(t *testing.T) {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, linkLimit+"?buckets=2000", nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
@ -129,7 +189,7 @@ func TestAPI(t *testing.T) {
})
}
func TestAddProject(t *testing.T) {
func TestProjectAdd(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -169,7 +229,7 @@ func TestAddProject(t *testing.T) {
})
}
func TestRenameProject(t *testing.T) {
func TestProjectRename(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -188,24 +248,36 @@ func TestRenameProject(t *testing.T) {
require.NoError(t, err)
require.Equal(t, oldName, project.Name)
body := strings.NewReader(fmt.Sprintf(`{"projectName":"%s","description":"This project got renamed"}`, newName))
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("http://"+address.String()+"/api/projects/%s", project.ID.String()), body)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
t.Run("OK", func(t *testing.T) {
body := strings.NewReader(fmt.Sprintf(`{"projectName":"%s","description":"This project got renamed"}`, newName))
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("http://"+address.String()+"/api/projects/%s", project.ID.String()), body)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
require.NoError(t, response.Body.Close())
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
require.NoError(t, response.Body.Close())
project, err = planet.Satellites[0].DB.Console().Projects().Get(ctx, project.ID)
require.NoError(t, err)
require.Equal(t, newName, project.Name)
project, err = planet.Satellites[0].DB.Console().Projects().Get(ctx, project.ID)
require.NoError(t, err)
require.Equal(t, newName, project.Name)
})
t.Run("Not Found", func(t *testing.T) {
id, err := uuid.New()
require.NoError(t, err)
link := fmt.Sprintf("http://"+address.String()+"/api/projects/%s", id.String())
putBody := fmt.Sprintf(`{"projectName":"%s","description":"This project got renamed"}`, newName)
body := assertReq(ctx, t, link, http.MethodPut, putBody, http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
})
}
func TestDeleteProject(t *testing.T) {
func TestProjectDelete(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -262,7 +334,7 @@ func TestDeleteProject(t *testing.T) {
})
}
func TestCheckUsageWithoutUsage(t *testing.T) {
func TestProjectCheckUsage_withoutUsage(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -302,7 +374,7 @@ func TestCheckUsageWithoutUsage(t *testing.T) {
})
}
func TestCheckUsageWithUsage(t *testing.T) {
func TestProjectCheckUsage_withUsage(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -368,7 +440,7 @@ func TestCheckUsageWithUsage(t *testing.T) {
})
}
func TestCheckUsageLastMonthUnappliedInvoice(t *testing.T) {
func TestProjectCheckUsage_lastMonthUnappliedInvoice(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -446,7 +518,7 @@ func TestCheckUsageLastMonthUnappliedInvoice(t *testing.T) {
})
}
func TestDeleteProjectWithUsageCurrentMonth(t *testing.T) {
func TestProjectDelete_withUsageCurrentMonth(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -512,7 +584,7 @@ func TestDeleteProjectWithUsageCurrentMonth(t *testing.T) {
})
}
func TestDeleteProjectWithUsagePreviousMonth(t *testing.T) {
func TestProjectDelete_withUsagePreviousMonth(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,

View File

@ -130,7 +130,7 @@ func (server *Server) userInfo(w http.ResponseWriter, r *http.Request) {
user, err := server.db.Console().Users().GetByEmail(ctx, userEmail)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, fmt.Sprintf("user with email %q not found", userEmail),
sendJSONError(w, fmt.Sprintf("user with email %q does not exist", userEmail),
"", http.StatusNotFound)
return
}
@ -213,7 +213,7 @@ func (server *Server) updateUser(w http.ResponseWriter, r *http.Request) {
user, err := server.db.Console().Users().GetByEmail(ctx, userEmail)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, fmt.Sprintf("user with email %q not found", userEmail),
sendJSONError(w, fmt.Sprintf("user with email %q does not exist", userEmail),
"", http.StatusNotFound)
return
}
@ -278,7 +278,7 @@ func (server *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
user, err := server.db.Console().Users().GetByEmail(ctx, userEmail)
if errors.Is(err, sql.ErrNoRows) {
sendJSONError(w, fmt.Sprintf("user with email %q not found", userEmail),
sendJSONError(w, fmt.Sprintf("user with email %q does not exist", userEmail),
"", http.StatusNotFound)
return
}

View File

@ -20,7 +20,7 @@ import (
"storj.io/storj/satellite/console"
)
func TestGetUser(t *testing.T) {
func TestUserGet(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -44,34 +44,21 @@ func TestGetUser(t *testing.T) {
couponsMarshaled, err := json.Marshal(coupons)
require.NoError(t, err)
t.Run("GetUser", func(t *testing.T) {
userLink := "http://" + address.String() + "/api/users/" + project.Owner.Email
expected := `{` +
fmt.Sprintf(`"user":{"id":"%s","fullName":"User uplink0_0","email":"%s","projectLimit":%d},`, project.Owner.ID, project.Owner.Email, projLimit) +
fmt.Sprintf(`"projects":[{"id":"%s","name":"uplink0_0","description":"","ownerId":"%s"}],`, project.ID, project.Owner.ID) +
fmt.Sprintf(`"coupons":%s}`, couponsMarshaled)
link := "http://" + address.String() + "/api/users/" + project.Owner.Email
expectedBody := `{` +
fmt.Sprintf(`"user":{"id":"%s","fullName":"User uplink0_0","email":"%s","projectLimit":%d},`, project.Owner.ID, project.Owner.Email, projLimit) +
fmt.Sprintf(`"projects":[{"id":"%s","name":"uplink0_0","description":"","ownerId":"%s"}],`, project.ID, project.Owner.ID) +
fmt.Sprintf(`"coupons":%s}`, couponsMarshaled)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, userLink, nil)
require.NoError(t, err)
assertReq(ctx, t, link, http.MethodGet, "", http.StatusOK, expectedBody, planet.Satellites[0].Config.Console.AuthToken)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "application/json", response.Header.Get("Content-Type"))
data, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Equal(t, http.StatusOK, response.StatusCode, string(data))
require.Equal(t, expected, string(data))
})
link = "http://" + address.String() + "/api/users/" + "user-not-exist@not-exist.test"
body := assertReq(ctx, t, link, http.MethodGet, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
}
func TestAddUser(t *testing.T) {
func TestUserAdd(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -110,7 +97,7 @@ func TestAddUser(t *testing.T) {
})
}
func TestAddUserSameEmail(t *testing.T) {
func TestUserAdd_sameEmail(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -161,7 +148,7 @@ func TestAddUserSameEmail(t *testing.T) {
})
}
func TestUpdateUser(t *testing.T) {
func TestUserUpdate(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -176,73 +163,48 @@ func TestUpdateUser(t *testing.T) {
user, err := planet.Satellites[0].DB.Console().Users().GetByEmail(ctx, planet.Uplinks[0].Projects[0].Owner.Email)
require.NoError(t, err)
body := strings.NewReader(`{"email":"alice+2@mail.test", "shortName":"Newbie"}`)
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("http://"+address.String()+"/api/users/%s", user.Email), body)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
t.Run("OK", func(t *testing.T) {
// Updat user data.
link := fmt.Sprintf("http://"+address.String()+"/api/users/%s", user.Email)
body := `{"email":"alice+2@mail.test", "shortName":"Newbie"}`
responseBody := assertReq(ctx, t, link, http.MethodPut, body, http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
require.Len(t, responseBody, 0)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
responseBody, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Len(t, responseBody, 0)
updatedUser, err := planet.Satellites[0].DB.Console().Users().Get(ctx, user.ID)
require.NoError(t, err)
require.Equal(t, "alice+2@mail.test", updatedUser.Email)
require.Equal(t, user.FullName, updatedUser.FullName)
require.NotEqual(t, "Newbie", user.ShortName)
require.Equal(t, "Newbie", updatedUser.ShortName)
require.Equal(t, user.ID, updatedUser.ID)
require.Equal(t, user.Status, updatedUser.Status)
require.Equal(t, user.ProjectLimit, updatedUser.ProjectLimit)
updatedUser, err := planet.Satellites[0].DB.Console().Users().Get(ctx, user.ID)
require.NoError(t, err)
require.Equal(t, "alice+2@mail.test", updatedUser.Email)
require.Equal(t, user.FullName, updatedUser.FullName)
require.NotEqual(t, "Newbie", user.ShortName)
require.Equal(t, "Newbie", updatedUser.ShortName)
require.Equal(t, user.ID, updatedUser.ID)
require.Equal(t, user.Status, updatedUser.Status)
require.Equal(t, user.ProjectLimit, updatedUser.ProjectLimit)
// Update rate limit.
link = "http://" + address.String() + "/api/users/alice+2@mail.test"
newLimit := 50
body = fmt.Sprintf(`{"projectLimit":%d}`, newLimit)
responseBody = assertReq(ctx, t, link, http.MethodPut, body, http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
require.Len(t, responseBody, 0)
updatedUserRate, err := planet.Satellites[0].DB.Console().Users().Get(ctx, user.ID)
require.NoError(t, err)
require.Equal(t, updatedUser.Email, updatedUserRate.Email)
require.Equal(t, updatedUser.ID, updatedUserRate.ID)
require.Equal(t, updatedUser.Status, updatedUserRate.Status)
require.Equal(t, newLimit, updatedUserRate.ProjectLimit)
})
t.Run("Not found", func(t *testing.T) {
link := "http://" + address.String() + "/api/users/user-not-exists@not-exists.test"
body := `{"email":"alice+2@mail.test", "shortName":"Newbie"}`
responseBody := assertReq(ctx, t, link, http.MethodPut, body, http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(responseBody), "does not exist")
})
})
}
func TestUpdateUserRateLimit(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
UplinkCount: 1,
Reconfigure: testplanet.Reconfigure{
Satellite: func(_ *zap.Logger, _ int, config *satellite.Config) {
config.Admin.Address = "127.0.0.1:0"
},
},
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
address := planet.Satellites[0].Admin.Admin.Listener.Addr()
user, err := planet.Satellites[0].DB.Console().Users().GetByEmail(ctx, planet.Uplinks[0].Projects[0].Owner.Email)
require.NoError(t, err)
newLimit := 50
body := strings.NewReader(fmt.Sprintf(`{"projectLimit":%d}`, newLimit))
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("http://"+address.String()+"/api/users/%s", user.Email), body)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
responseBody, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Len(t, responseBody, 0)
updatedUser, err := planet.Satellites[0].DB.Console().Users().Get(ctx, user.ID)
require.NoError(t, err)
require.Equal(t, user.Email, updatedUser.Email)
require.Equal(t, user.ID, updatedUser.ID)
require.Equal(t, user.Status, updatedUser.Status)
require.Equal(t, newLimit, updatedUser.ProjectLimit)
})
}
func TestDeleteUser(t *testing.T) {
func TestUserDelete(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
@ -258,34 +220,19 @@ func TestDeleteUser(t *testing.T) {
require.NoError(t, err)
// Deleting the user should fail, as project exists
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("http://"+address.String()+"/api/users/%s", user.Email), nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusConflict, response.StatusCode)
require.Equal(t, "application/json", response.Header.Get("Content-Type"))
responseBody, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Greater(t, len(responseBody), 0)
link := fmt.Sprintf("http://"+address.String()+"/api/users/%s", user.Email)
body := assertReq(ctx, t, link, http.MethodDelete, "", http.StatusConflict, "", planet.Satellites[0].Config.Console.AuthToken)
require.Greater(t, len(body), 0)
err = planet.Satellites[0].DB.Console().Projects().Delete(ctx, planet.Uplinks[0].Projects[0].ID)
require.NoError(t, err)
// Deleting the user should pass, as no project exists for given user
req, err = http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("http://"+address.String()+"/api/users/%s", user.Email), nil)
require.NoError(t, err)
req.Header.Set("Authorization", planet.Satellites[0].Config.Console.AuthToken)
// Deleting the user should pass, as no project exists for given user.
body = assertReq(ctx, t, link, http.MethodDelete, "", http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
require.Len(t, body, 0)
response, err = http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, "", response.Header.Get("Content-Type"))
responseBody, err = ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
require.Equal(t, len(responseBody), 0)
// Deleting unexisting user returns Not Found.
body = assertReq(ctx, t, link, http.MethodDelete, "", http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(body), "does not exist")
})
}