Skip to content

Commit

Permalink
satellite/{console,satellitedb}: change project limiting based on new…
Browse files Browse the repository at this point in the history
… users field

This change switches the backend logic to use the new DB column on the users table to restrict project creation.
Furthermore it back fills the existing limits from registration tokens to the new column to ensure no users are reset to the new default.

UI is updated to reflect ability to create several projects

Change-Id: Ie29157430ae6b065411ca4c4557c9f1be69cdc4f
  • Loading branch information
stefanbenten committed Jul 16, 2020
1 parent 1944d73 commit 9ace375
Show file tree
Hide file tree
Showing 22 changed files with 658 additions and 51 deletions.
1 change: 1 addition & 0 deletions private/testplanet/satellite.go
Expand Up @@ -546,6 +546,7 @@ func (planet *Planet) newSatellites(count int, satelliteDatabases satellitedbtes
AuthTokenSecret: "my-suppa-secret-key",
Config: console.Config{
PasswordCost: console.TestPasswordCost,
DefaultProjectLimit: 5,
},
RateLimit: web.IPRateLimiterConfig{
Duration: 5 * time.Minute,
Expand Down
4 changes: 4 additions & 0 deletions private/testplanet/satellite_test.go
Expand Up @@ -20,6 +20,10 @@ func TestSatellite_AddProject(t *testing.T) {
user, err := planet.Satellites[0].AddUser(ctx, "test user", "test-email@test", 4)
require.NoError(t, err)

limit, err := planet.Satellites[0].DB.Console().Users().GetProjectLimit(ctx, user.ID)
require.NoError(t, err)
require.Equal(t, 4, limit)

for i := 0; i < 4; i++ {
_, err = planet.Satellites[0].AddProject(ctx, user.ID, "test project "+strconv.Itoa(i))
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion satellite/console/consoleweb/consoleql/mutation_test.go
Expand Up @@ -101,7 +101,7 @@ func TestGrapqhlMutation(t *testing.T) {
db.Rewards(),
partnersService,
paymentsService.Accounts(),
console.Config{PasswordCost: console.TestPasswordCost},
console.Config{PasswordCost: console.TestPasswordCost, DefaultProjectLimit: 5},
5000,
)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion satellite/console/consoleweb/consoleql/query_test.go
Expand Up @@ -85,7 +85,7 @@ func TestGraphqlQuery(t *testing.T) {
db.Rewards(),
partnersService,
paymentsService.Accounts(),
console.Config{PasswordCost: console.TestPasswordCost},
console.Config{PasswordCost: console.TestPasswordCost, DefaultProjectLimit: 5},
5000,
)
require.NoError(t, err)
Expand Down
2 changes: 2 additions & 0 deletions satellite/console/consoleweb/server.go
Expand Up @@ -273,6 +273,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
VerificationPageURL string
PartneredSatelliteNames string
GoogleTagManagerID string
DefaultProjectLimit int
}

data.SatelliteName = server.config.SatelliteName
Expand All @@ -281,6 +282,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
data.VerificationPageURL = server.config.VerificationPageURL
data.PartneredSatelliteNames = server.config.PartneredSatelliteNames
data.GoogleTagManagerID = server.config.GoogleTagManagerID
data.DefaultProjectLimit = server.config.DefaultProjectLimit

if server.templates.index == nil || server.templates.index.Execute(w, data) != nil {
server.log.Error("index template could not be executed")
Expand Down
26 changes: 9 additions & 17 deletions satellite/console/service.go
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"crypto/subtle"
"database/sql"
"errors"
"fmt"
"sort"
"time"
Expand Down Expand Up @@ -504,6 +503,10 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R
}
}

if registrationToken != nil {
newUser.ProjectLimit = registrationToken.ProjectLimit
}

u, err = tx.Users().Insert(ctx,
newUser,
)
Expand Down Expand Up @@ -1383,35 +1386,24 @@ func (s *Service) Authorize(ctx context.Context) (a Authorization, err error) {
}, nil
}

func (s *Service) getProjectLimit(ctx context.Context, userID uuid.UUID) (limit int, err error) {
defer mon.Task()(&ctx)(&err)

registrationToken, err := s.store.RegistrationTokens().GetByOwnerID(ctx, userID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return s.config.DefaultProjectLimit, nil
}
return 0, err
}

return registrationToken.ProjectLimit, nil
}

// checkProjectLimit is used to check if user is able to create a new project
func (s *Service) checkProjectLimit(ctx context.Context, userID uuid.UUID) (err error) {
defer mon.Task()(&ctx)(&err)

projectLimit, err := s.getProjectLimit(ctx, userID)
limit, err := s.store.Users().GetProjectLimit(ctx, userID)
if err != nil {
return Error.Wrap(err)
}
if limit == 0 {
limit = s.config.DefaultProjectLimit
}

projects, err := s.GetUsersProjects(ctx)
if err != nil {
return Error.Wrap(err)
}

if len(projects) >= projectLimit {
if len(projects) >= limit {
return ErrProjLimit.Wrap(errs.New(projLimitErrMsg))
}

Expand Down
2 changes: 2 additions & 0 deletions satellite/console/users.go
Expand Up @@ -25,6 +25,8 @@ type Users interface {
Delete(ctx context.Context, id uuid.UUID) error
// Update is a method for updating user entity.
Update(ctx context.Context, user *User) error
// GetProjectLimit is a method to get the users project limit
GetProjectLimit(ctx context.Context, id uuid.UUID) (limit int, err error)
}

// UserInfo holds User updatable data.
Expand Down
9 changes: 9 additions & 0 deletions satellite/satellitedb/migrate.go
Expand Up @@ -1237,6 +1237,15 @@ func (db *satelliteDB) PostgresMigration() *migrate.Migration {
`ALTER TABLE users ADD COLUMN project_limit INTEGER NOT NULL DEFAULT 0;`,
},
},
{
DB: db.DB,
Description: "back fill user project limits from existing registration tokens",
Version: 120,
SeparateTx: true,
Action: migrate.SQL{
`UPDATE users SET project_limit = registration_tokens.project_limit FROM registration_tokens WHERE users.id = registration_tokens.owner_id;`,
},
},
},
}
}

0 comments on commit 9ace375

Please sign in to comment.