satellite/admin: rework update user limits functionality
Fixed nil pointer dereference panic. Updated naming conventions so that PUT request and GET response bodies are the same (bandwidth, storage and segment). Allowed usage of notations like 150GB, 2TB for storage and bandwidth limits. Updated tests. Issue: https://github.com/storj/storj/issues/5674 Change-Id: I7ac27c00721a9b4bf507afa34cb05c4475a809ad
This commit is contained in:
parent
260b71e70c
commit
4d998970d4
@ -378,25 +378,31 @@ Blank fields will not be updated.`,
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'update user and project limits',
|
||||
name: "update user's project limits",
|
||||
desc: `Update limits for all of user's existing and future projects.
|
||||
Blank fields will not be updated.`,
|
||||
params: [
|
||||
["current user's email", new InputText('email', true)],
|
||||
['project storage limit (in bytes)', new InputText('number', false)],
|
||||
['project bandwidth limit (in bytes)', new InputText('number', false)],
|
||||
[
|
||||
'project storage limit (in bytes or notations like 1GB, 2tb)',
|
||||
new InputText('text', false)
|
||||
],
|
||||
[
|
||||
'project bandwidth limit (in bytes or notations like 1GB, 2tb)',
|
||||
new InputText('text', false)
|
||||
],
|
||||
['project segment limit (max number)', new InputText('number', false)]
|
||||
],
|
||||
func: async (
|
||||
currentEmail: string,
|
||||
projectStorageLimit?: number,
|
||||
projectBandwidthLimit?: number,
|
||||
projectSegmentLimit?: number
|
||||
storage?: number,
|
||||
bandwidth?: number,
|
||||
segment?: number
|
||||
): Promise<null> => {
|
||||
return this.fetch('PUT', `users/${currentEmail}/limits`, null, {
|
||||
projectStorageLimit,
|
||||
projectBandwidthLimit,
|
||||
projectSegmentLimit
|
||||
storage,
|
||||
bandwidth,
|
||||
segment
|
||||
}) as Promise<null>;
|
||||
}
|
||||
},
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"storj.io/common/memory"
|
||||
"storj.io/common/uuid"
|
||||
"storj.io/storj/satellite/console"
|
||||
)
|
||||
@ -224,7 +225,7 @@ func (server *Server) userLimits(w http.ResponseWriter, r *http.Request) {
|
||||
var limits struct {
|
||||
Storage int64 `json:"storage"`
|
||||
Bandwidth int64 `json:"bandwidth"`
|
||||
Segment int64 `json:"maxSegments"`
|
||||
Segment int64 `json:"segment"`
|
||||
}
|
||||
|
||||
limits.Storage = user.ProjectStorageLimit
|
||||
@ -362,12 +363,12 @@ func (server *Server) updateLimits(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
type User struct {
|
||||
console.User
|
||||
var input struct {
|
||||
Storage memory.Size `json:"storage"`
|
||||
Bandwidth memory.Size `json:"bandwidth"`
|
||||
Segment int64 `json:"segment"`
|
||||
}
|
||||
|
||||
var input User
|
||||
|
||||
err = json.Unmarshal(body, &input)
|
||||
if err != nil {
|
||||
sendJSONError(w, "failed to unmarshal request",
|
||||
@ -375,38 +376,46 @@ func (server *Server) updateLimits(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
updateRequest := console.UpdateUserRequest{}
|
||||
|
||||
if input.ProjectStorageLimit > 0 {
|
||||
updateRequest.ProjectStorageLimit = &input.ProjectStorageLimit
|
||||
}
|
||||
if input.ProjectBandwidthLimit > 0 {
|
||||
updateRequest.ProjectBandwidthLimit = &input.ProjectBandwidthLimit
|
||||
}
|
||||
if input.ProjectSegmentLimit > 0 {
|
||||
updateRequest.ProjectSegmentLimit = &input.ProjectSegmentLimit
|
||||
newLimits := console.UsageLimits{
|
||||
Storage: user.ProjectStorageLimit,
|
||||
Bandwidth: user.ProjectBandwidthLimit,
|
||||
Segment: user.ProjectSegmentLimit,
|
||||
}
|
||||
|
||||
userLimits := console.UsageLimits{
|
||||
Storage: *updateRequest.ProjectStorageLimit,
|
||||
Bandwidth: *updateRequest.ProjectBandwidthLimit,
|
||||
Segment: *updateRequest.ProjectSegmentLimit,
|
||||
if input.Storage > 0 {
|
||||
newLimits.Storage = input.Storage.Int64()
|
||||
}
|
||||
if input.Bandwidth > 0 {
|
||||
newLimits.Bandwidth = input.Bandwidth.Int64()
|
||||
}
|
||||
if input.Segment > 0 {
|
||||
newLimits.Segment = input.Segment
|
||||
}
|
||||
|
||||
err = server.db.Console().Users().UpdateUserProjectLimits(ctx, user.ID, userLimits)
|
||||
if newLimits.Storage == user.ProjectStorageLimit &&
|
||||
newLimits.Bandwidth == user.ProjectBandwidthLimit &&
|
||||
newLimits.Segment == user.ProjectSegmentLimit {
|
||||
sendJSONError(w, "no limits to update",
|
||||
"new values are equal to old ones", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.db.Console().Users().UpdateUserProjectLimits(ctx, user.ID, newLimits)
|
||||
if err != nil {
|
||||
sendJSONError(w, "failed to update user limits",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
userProjects, err := server.db.Console().Projects().GetOwn(ctx, user.ID)
|
||||
if err != nil {
|
||||
sendJSONError(w, "failed to get user's projects",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
for _, p := range userProjects {
|
||||
err = server.db.Console().Projects().UpdateUsageLimits(ctx, p.ID, userLimits)
|
||||
err = server.db.Console().Projects().UpdateUsageLimits(ctx, p.ID, newLimits)
|
||||
if err != nil {
|
||||
sendJSONError(w, "failed to update project limits",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"storj.io/common/memory"
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/storj/private/testplanet"
|
||||
"storj.io/storj/satellite"
|
||||
@ -204,32 +205,55 @@ func TestUserUpdate(t *testing.T) {
|
||||
require.Equal(t, newUsageLimit, updatedUserStatusAndUsageLimits.ProjectBandwidthLimit)
|
||||
require.Equal(t, newUsageLimit, updatedUserStatusAndUsageLimits.ProjectSegmentLimit)
|
||||
|
||||
// Update user limits and project limits (current and existing projects for a user).
|
||||
link = "http://" + address.String() + "/api/users/alice+2@mail.test/limits"
|
||||
newStorageLimit := int64(15000)
|
||||
newBandwidthLimit := int64(25000)
|
||||
newSegmentLimit := int64(35000)
|
||||
body2 := fmt.Sprintf(`{"projectStorageLimit":%d, "projectBandwidthLimit":%d, "projectSegmentLimit":%d}`, newStorageLimit, newBandwidthLimit, newSegmentLimit)
|
||||
responseBody = assertReq(ctx, t, link, http.MethodPut, body2, http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
|
||||
require.Len(t, responseBody, 0)
|
||||
var updateLimitsTests = []struct {
|
||||
newStorageLimit memory.Size
|
||||
newBandwidthLimit memory.Size
|
||||
newSegmentLimit int64
|
||||
useSizeString bool
|
||||
}{
|
||||
{
|
||||
15000,
|
||||
25000,
|
||||
35000,
|
||||
false,
|
||||
},
|
||||
{
|
||||
50 * memory.KB,
|
||||
75 * memory.KB,
|
||||
40000,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
// Get user limits returns new updated limits
|
||||
link2 := "http://" + address.String() + "/api/users/alice+2@mail.test/limits"
|
||||
expectedBody := `{` +
|
||||
fmt.Sprintf(`"storage":%d,"bandwidth":%d,"maxSegments":%d}`, newStorageLimit, newBandwidthLimit, newSegmentLimit)
|
||||
assertReq(ctx, t, link2, http.MethodGet, "", http.StatusOK, expectedBody, planet.Satellites[0].Config.Console.AuthToken)
|
||||
for _, tt := range updateLimitsTests {
|
||||
// Update user limits and project limits (current and existing projects for a user).
|
||||
link = "http://" + address.String() + "/api/users/alice+2@mail.test/limits"
|
||||
jsonStr := `{"storage":"%d", "bandwidth":"%d", "segment":%d}`
|
||||
if tt.useSizeString {
|
||||
jsonStr = strings.Replace(jsonStr, "%d", "%v", 2)
|
||||
}
|
||||
body2 := fmt.Sprintf(jsonStr, tt.newStorageLimit, tt.newBandwidthLimit, tt.newSegmentLimit)
|
||||
responseBody = assertReq(ctx, t, link, http.MethodPut, body2, http.StatusOK, "", planet.Satellites[0].Config.Console.AuthToken)
|
||||
require.Len(t, responseBody, 0)
|
||||
|
||||
userUpdatedLimits, err := planet.Satellites[0].DB.Console().Users().Get(ctx, user.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newStorageLimit, userUpdatedLimits.ProjectStorageLimit)
|
||||
require.Equal(t, newBandwidthLimit, userUpdatedLimits.ProjectBandwidthLimit)
|
||||
require.Equal(t, newSegmentLimit, userUpdatedLimits.ProjectSegmentLimit)
|
||||
// Get user limits returns new updated limits
|
||||
link2 := "http://" + address.String() + "/api/users/alice+2@mail.test/limits"
|
||||
expectedBody := `{` +
|
||||
fmt.Sprintf(`"storage":%d,"bandwidth":%d,"segment":%d}`, tt.newStorageLimit, tt.newBandwidthLimit, tt.newSegmentLimit)
|
||||
assertReq(ctx, t, link2, http.MethodGet, "", http.StatusOK, expectedBody, planet.Satellites[0].Config.Console.AuthToken)
|
||||
|
||||
projectUpdatedLimits, err := planet.Satellites[0].DB.Console().Projects().Get(ctx, planet.Uplinks[0].Projects[0].ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newStorageLimit, projectUpdatedLimits.StorageLimit.Int64())
|
||||
require.Equal(t, newBandwidthLimit, projectUpdatedLimits.BandwidthLimit.Int64())
|
||||
require.Equal(t, newSegmentLimit, *projectUpdatedLimits.SegmentLimit)
|
||||
userUpdatedLimits, err := planet.Satellites[0].DB.Console().Users().Get(ctx, user.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.newStorageLimit.Int64(), userUpdatedLimits.ProjectStorageLimit)
|
||||
require.Equal(t, tt.newBandwidthLimit.Int64(), userUpdatedLimits.ProjectBandwidthLimit)
|
||||
require.Equal(t, tt.newSegmentLimit, userUpdatedLimits.ProjectSegmentLimit)
|
||||
|
||||
projectUpdatedLimits, err := planet.Satellites[0].DB.Console().Projects().Get(ctx, planet.Uplinks[0].Projects[0].ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.newStorageLimit, *projectUpdatedLimits.StorageLimit)
|
||||
require.Equal(t, tt.newBandwidthLimit, *projectUpdatedLimits.BandwidthLimit)
|
||||
require.Equal(t, tt.newSegmentLimit, *projectUpdatedLimits.SegmentLimit)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Not found", func(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user