satellite/console: fill default placement of project based on user info

https://github.com/storj/storj/issues/5879

Change-Id: I5aacbe57a7aab65e11915dd8bf0c68f89da32fb4
This commit is contained in:
Márton Elek 2023-06-07 11:25:57 +02:00
parent 5c26661cd3
commit 2ea6ca9c18
No known key found for this signature in database
7 changed files with 90 additions and 43 deletions

View File

@ -47,7 +47,7 @@ func TestProjectGet(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
link := "http://" + address.String() + "/api/projects/" + project.ID.String() link := "http://" + address.String() + "/api/projects/" + project.ID.String()
expected := fmt.Sprintf( expected := fmt.Sprintf(
`{"id":"%s","publicId":"%s","name":"%s","description":"%s","userAgent":null,"ownerId":"%s","rateLimit":null,"burstLimit":null,"maxBuckets":null,"createdAt":"%s","memberCount":0,"storageLimit":"25.00 GB","bandwidthLimit":"25.00 GB","userSpecifiedStorageLimit":null,"userSpecifiedBandwidthLimit":null,"segmentLimit":10000}`, `{"id":"%s","publicId":"%s","name":"%s","description":"%s","userAgent":null,"ownerId":"%s","rateLimit":null,"burstLimit":null,"maxBuckets":null,"createdAt":"%s","memberCount":0,"storageLimit":"25.00 GB","bandwidthLimit":"25.00 GB","userSpecifiedStorageLimit":null,"userSpecifiedBandwidthLimit":null,"segmentLimit":10000,"defaultPlacement":0}`,
project.ID.String(), project.ID.String(),
project.PublicID.String(), project.PublicID.String(),
project.Name, project.Name,

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"storj.io/common/memory" "storj.io/common/memory"
"storj.io/common/storj"
"storj.io/common/uuid" "storj.io/common/uuid"
) )
@ -93,20 +94,21 @@ type Project struct {
ID uuid.UUID `json:"id"` ID uuid.UUID `json:"id"`
PublicID uuid.UUID `json:"publicId"` PublicID uuid.UUID `json:"publicId"`
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
UserAgent []byte `json:"userAgent"` UserAgent []byte `json:"userAgent"`
OwnerID uuid.UUID `json:"ownerId"` OwnerID uuid.UUID `json:"ownerId"`
RateLimit *int `json:"rateLimit"` RateLimit *int `json:"rateLimit"`
BurstLimit *int `json:"burstLimit"` BurstLimit *int `json:"burstLimit"`
MaxBuckets *int `json:"maxBuckets"` MaxBuckets *int `json:"maxBuckets"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
MemberCount int `json:"memberCount"` MemberCount int `json:"memberCount"`
StorageLimit *memory.Size `json:"storageLimit"` StorageLimit *memory.Size `json:"storageLimit"`
BandwidthLimit *memory.Size `json:"bandwidthLimit"` BandwidthLimit *memory.Size `json:"bandwidthLimit"`
UserSpecifiedStorageLimit *memory.Size `json:"userSpecifiedStorageLimit"` UserSpecifiedStorageLimit *memory.Size `json:"userSpecifiedStorageLimit"`
UserSpecifiedBandwidthLimit *memory.Size `json:"userSpecifiedBandwidthLimit"` UserSpecifiedBandwidthLimit *memory.Size `json:"userSpecifiedBandwidthLimit"`
SegmentLimit *int64 `json:"segmentLimit"` SegmentLimit *int64 `json:"segmentLimit"`
DefaultPlacement storj.PlacementConstraint `json:"defaultPlacement"`
} }
// ProjectInfo holds data needed to create/update Project. // ProjectInfo holds data needed to create/update Project.

View File

@ -1616,13 +1616,14 @@ func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (p
bandwidthLimit := memory.Size(newProjectLimits.Bandwidth) bandwidthLimit := memory.Size(newProjectLimits.Bandwidth)
p, err = tx.Projects().Insert(ctx, p, err = tx.Projects().Insert(ctx,
&Project{ &Project{
Description: projectInfo.Description, Description: projectInfo.Description,
Name: projectInfo.Name, Name: projectInfo.Name,
OwnerID: user.ID, OwnerID: user.ID,
UserAgent: user.UserAgent, UserAgent: user.UserAgent,
StorageLimit: &storageLimit, StorageLimit: &storageLimit,
BandwidthLimit: &bandwidthLimit, BandwidthLimit: &bandwidthLimit,
SegmentLimit: &newProjectLimits.Segment, SegmentLimit: &newProjectLimits.Segment,
DefaultPlacement: user.DefaultPlacement,
}, },
) )
if err != nil { if err != nil {
@ -1683,13 +1684,14 @@ func (s *Service) GenCreateProject(ctx context.Context, projectInfo ProjectInfo)
bandwidthLimit := memory.Size(newProjectLimits.Bandwidth) bandwidthLimit := memory.Size(newProjectLimits.Bandwidth)
p, err = tx.Projects().Insert(ctx, p, err = tx.Projects().Insert(ctx,
&Project{ &Project{
Description: projectInfo.Description, Description: projectInfo.Description,
Name: projectInfo.Name, Name: projectInfo.Name,
OwnerID: user.ID, OwnerID: user.ID,
UserAgent: user.UserAgent, UserAgent: user.UserAgent,
StorageLimit: &storageLimit, StorageLimit: &storageLimit,
BandwidthLimit: &bandwidthLimit, BandwidthLimit: &bandwidthLimit,
SegmentLimit: &newProjectLimits.Segment, SegmentLimit: &newProjectLimits.Segment,
DefaultPlacement: user.DefaultPlacement,
}, },
) )
if err != nil { if err != nil {

View File

@ -23,6 +23,7 @@ import (
"storj.io/common/currency" "storj.io/common/currency"
"storj.io/common/macaroon" "storj.io/common/macaroon"
"storj.io/common/memory" "storj.io/common/memory"
"storj.io/common/storj"
"storj.io/common/testcontext" "storj.io/common/testcontext"
"storj.io/common/testrand" "storj.io/common/testrand"
"storj.io/common/uuid" "storj.io/common/uuid"
@ -41,7 +42,7 @@ import (
func TestService(t *testing.T) { func TestService(t *testing.T) {
testplanet.Run(t, testplanet.Config{ testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 2, SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 3,
Reconfigure: testplanet.Reconfigure{ Reconfigure: testplanet.Reconfigure{
Satellite: func(log *zap.Logger, index int, config *satellite.Config) { Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
config.Payments.StripeCoinPayments.StripeFreeTierCouponID = stripe.MockCouponID1 config.Payments.StripeCoinPayments.StripeFreeTierCouponID = stripe.MockCouponID1
@ -156,6 +157,29 @@ func TestService(t *testing.T) {
require.Nil(t, createdProject) require.Nil(t, createdProject)
}) })
t.Run("CreateProject with placement", func(t *testing.T) {
uid := planet.Uplinks[2].Projects[0].Owner.ID
err := sat.API.DB.Console().Users().Update(ctx, uid, console.UpdateUserRequest{
DefaultPlacement: storj.EU,
})
require.NoError(t, err)
user, err := service.GetUser(ctx, uid)
require.NoError(t, err)
userCtx, err := sat.UserContext(ctx, user.ID)
require.NoError(t, err)
p, err := service.CreateProject(userCtx, console.ProjectInfo{
Name: "eu-project",
Description: "project with eu1 default placement",
CreatedAt: time.Now(),
})
require.NoError(t, err)
require.Equal(t, storj.EU, p.DefaultPlacement)
})
t.Run("UpdateProject", func(t *testing.T) { t.Run("UpdateProject", func(t *testing.T) {
updatedName := "newName" updatedName := "newName"
updatedDescription := "newDescription" updatedDescription := "newDescription"

View File

@ -11,6 +11,7 @@ import (
"github.com/zeebo/errs" "github.com/zeebo/errs"
"storj.io/common/memory" "storj.io/common/memory"
"storj.io/common/storj"
"storj.io/common/uuid" "storj.io/common/uuid"
"storj.io/storj/satellite/console/consoleauth" "storj.io/storj/satellite/console/consoleauth"
) )
@ -184,6 +185,8 @@ type User struct {
FailedLoginCount int `json:"failedLoginCount"` FailedLoginCount int `json:"failedLoginCount"`
LoginLockoutExpiration time.Time `json:"loginLockoutExpiration"` LoginLockoutExpiration time.Time `json:"loginLockoutExpiration"`
SignupCaptcha *float64 `json:"-"` SignupCaptcha *float64 `json:"-"`
DefaultPlacement storj.PlacementConstraint `json:"defaultPlacement"`
} }
// ResponseUser is an entity which describes db User and can be sent in response. // ResponseUser is an entity which describes db User and can be sent in response.
@ -249,6 +252,8 @@ type UpdateUserRequest struct {
FailedLoginCount *int FailedLoginCount *int
LoginLockoutExpiration **time.Time LoginLockoutExpiration **time.Time
DefaultPlacement storj.PlacementConstraint
} }
// UserSettings contains configurations for a user. // UserSettings contains configurations for a user.

View File

@ -12,6 +12,7 @@ import (
"github.com/zeebo/errs" "github.com/zeebo/errs"
"storj.io/common/memory" "storj.io/common/memory"
"storj.io/common/storj"
"storj.io/common/uuid" "storj.io/common/uuid"
"storj.io/storj/satellite/console" "storj.io/storj/satellite/console"
"storj.io/storj/satellite/satellitedb/dbx" "storj.io/storj/satellite/satellitedb/dbx"
@ -153,6 +154,7 @@ func (projects *projects) Insert(ctx context.Context, project *console.Project)
createFields.MaxBuckets = dbx.Project_MaxBuckets_Raw(project.MaxBuckets) createFields.MaxBuckets = dbx.Project_MaxBuckets_Raw(project.MaxBuckets)
createFields.PublicId = dbx.Project_PublicId(publicID[:]) createFields.PublicId = dbx.Project_PublicId(publicID[:])
createFields.Salt = dbx.Project_Salt(salt[:]) createFields.Salt = dbx.Project_Salt(salt[:])
createFields.DefaultPlacement = dbx.Project_DefaultPlacement(int(project.DefaultPlacement))
createdProject, err := projects.db.Create_Project(ctx, createdProject, err := projects.db.Create_Project(ctx,
dbx.Project_Id(projectID[:]), dbx.Project_Id(projectID[:]),
@ -395,20 +397,26 @@ func projectFromDBX(ctx context.Context, project *dbx.Project) (_ *console.Proje
return nil, err return nil, err
} }
var placement storj.PlacementConstraint
if project.DefaultPlacement != nil {
placement = storj.PlacementConstraint(*project.DefaultPlacement)
}
return &console.Project{ return &console.Project{
ID: id, ID: id,
PublicID: publicID, PublicID: publicID,
Name: project.Name, Name: project.Name,
Description: project.Description, Description: project.Description,
UserAgent: userAgent, UserAgent: userAgent,
OwnerID: ownerID, OwnerID: ownerID,
RateLimit: project.RateLimit, RateLimit: project.RateLimit,
BurstLimit: project.BurstLimit, BurstLimit: project.BurstLimit,
MaxBuckets: project.MaxBuckets, MaxBuckets: project.MaxBuckets,
CreatedAt: project.CreatedAt, CreatedAt: project.CreatedAt,
StorageLimit: (*memory.Size)(project.UsageLimit), StorageLimit: (*memory.Size)(project.UsageLimit),
BandwidthLimit: (*memory.Size)(project.BandwidthLimit), BandwidthLimit: (*memory.Size)(project.BandwidthLimit),
SegmentLimit: project.SegmentLimit, SegmentLimit: project.SegmentLimit,
DefaultPlacement: placement,
}, nil }, nil
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/zeebo/errs" "github.com/zeebo/errs"
"storj.io/common/memory" "storj.io/common/memory"
"storj.io/common/storj"
"storj.io/common/uuid" "storj.io/common/uuid"
"storj.io/storj/satellite/console" "storj.io/storj/satellite/console"
"storj.io/storj/satellite/satellitedb/dbx" "storj.io/storj/satellite/satellitedb/dbx"
@ -507,6 +508,7 @@ func toUpdateUser(request console.UpdateUserRequest) (*dbx.User_Update_Fields, e
update.LoginLockoutExpiration = dbx.User_LoginLockoutExpiration(**request.LoginLockoutExpiration) update.LoginLockoutExpiration = dbx.User_LoginLockoutExpiration(**request.LoginLockoutExpiration)
} }
} }
update.DefaultPlacement = dbx.User_DefaultPlacement(int(request.DefaultPlacement))
return &update, nil return &update, nil
} }
@ -550,6 +552,10 @@ func userFromDBX(ctx context.Context, user *dbx.User) (_ *console.User, err erro
SignupCaptcha: user.SignupCaptcha, SignupCaptcha: user.SignupCaptcha,
} }
if user.DefaultPlacement != nil {
result.DefaultPlacement = storj.PlacementConstraint(*user.DefaultPlacement)
}
if user.UserAgent != nil { if user.UserAgent != nil {
result.UserAgent = user.UserAgent result.UserAgent = user.UserAgent
} }