satellite/console: Prevent duplicate project names for the same user.

issue: https://github.com/storj/storj/issues/5247

Change-Id: Ie51f24dca5b9e5064cb06ae238055177bec5975a
This commit is contained in:
Malcolm Bouzi 2023-01-05 09:51:45 -05:00
parent 0185bba90a
commit 583ea51fb1
3 changed files with 53 additions and 2 deletions

View File

@ -133,7 +133,7 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
require.NoError(t, usersDB.UpdateUserProjectLimits(ctx, user.ID, userLimits))
proj1Limits := randUsageLimits()
proj1, err := sat.AddProject(ctx, user.ID, "")
proj1, err := sat.AddProject(ctx, user.ID, "project1")
require.NoError(t, err)
require.NoError(t, projectsDB.UpdateUsageLimits(ctx, proj1.ID, proj1Limits))
@ -143,7 +143,7 @@ func TestAccountFreezeAlreadyFrozen(t *testing.T) {
require.NoError(t, service.FreezeUser(ctx, user.ID))
proj2Limits := randUsageLimits()
proj2, err := sat.AddProject(ctx, user.ID, "")
proj2, err := sat.AddProject(ctx, user.ID, "project2")
require.NoError(t, err)
require.NoError(t, projectsDB.UpdateUsageLimits(ctx, proj2.ID, proj2Limits))

View File

@ -69,6 +69,7 @@ const (
activationTokenExpiredErrMsg = "This activation token has expired, please request another one"
usedRegTokenErrMsg = "This registration token has already been used"
projLimitErrMsg = "Sorry, project creation is limited for your account. Please contact support!"
projNameErrMsg = "The new project must have a name you haven't used before!"
)
var (
@ -119,6 +120,9 @@ var (
// ErrRecoveryToken describes account recovery token errors.
ErrRecoveryToken = errs.Class("recovery token")
// ErrProjName is error that occurs with reused project names.
ErrProjName = errs.Class("project name")
)
// Service is handling accounts related logic.
@ -1489,6 +1493,11 @@ func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (p
return nil, ErrProjLimit.Wrap(err)
}
passesNameCheck, err := s.checkProjectName(ctx, projectInfo, user.ID)
if err != nil || !passesNameCheck {
return nil, ErrProjName.Wrap(err)
}
newProjectLimits, err := s.getUserProjectLimits(ctx, user.ID)
if err != nil {
return nil, ErrProjLimit.Wrap(err)
@ -1695,7 +1704,14 @@ func (s *Service) UpdateProject(ctx context.Context, projectID uuid.UUID, update
if err != nil {
return nil, Error.Wrap(err)
}
project := isMember.project
if updatedProject.Name != project.Name {
passesNameCheck, err := s.checkProjectName(ctx, updatedProject, user.ID)
if err != nil || !passesNameCheck {
return nil, ErrProjName.Wrap(err)
}
}
project.Name = updatedProject.Name
project.Description = updatedProject.Description
@ -2776,6 +2792,25 @@ func (s *Service) checkProjectLimit(ctx context.Context, userID uuid.UUID) (curr
return len(projects), nil
}
// checkProjectName is used to check if user has used project name before.
func (s *Service) checkProjectName(ctx context.Context, projectInfo ProjectInfo, userID uuid.UUID) (passesNameCheck bool, err error) {
defer mon.Task()(&ctx)(&err)
passesCheck := true
projects, err := s.store.Projects().GetOwn(ctx, userID)
if err != nil {
return false, Error.Wrap(err)
}
for _, project := range projects {
if project.Name == projectInfo.Name {
return false, ErrProjName.New(projNameErrMsg)
}
}
return passesCheck, nil
}
// getUserProjectLimits is a method to get the users storage and bandwidth limits for new projects.
func (s *Service) getUserProjectLimits(ctx context.Context, userID uuid.UUID) (_ *UsageLimits, err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -91,6 +91,15 @@ func TestService(t *testing.T) {
require.Nil(t, salt)
})
t.Run("CreateProject", func(t *testing.T) {
// Creating a project with a previously used name should fail
createdProject, err := service.CreateProject(userCtx1, console.ProjectInfo{
Name: up1Pro1.Name,
})
require.Error(t, err)
require.Nil(t, createdProject)
})
t.Run("UpdateProject", func(t *testing.T) {
updatedName := "newName"
updatedDescription := "newDescription"
@ -188,6 +197,13 @@ func TestService(t *testing.T) {
require.NoError(t, err)
require.Equal(t, updateInfo.StorageLimit, *project.StorageLimit)
require.Equal(t, updateInfo.BandwidthLimit, *project.BandwidthLimit)
// attempting to update a project with a previously used name should fail
updatedProject, err = service.UpdateProject(userCtx1, up2Pro1.ID, console.ProjectInfo{
Name: up1Pro1.Name,
})
require.Error(t, err)
require.Nil(t, updatedProject)
})
t.Run("AddProjectMembers", func(t *testing.T) {