Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dashboards): add limit to repos for dashboards and dashboards for users #1116

Merged
merged 3 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions constants/limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,45 @@ package constants

// Limits and constraints.
const (
// BuildLimitMin defines the minimum value for repo concurrent build limit.
BuildLimitMin = 1

// BuildLimitMax defines the maximum value for repo concurrent build limit.
BuildLimitMax = 30

// BuildLimitDefault defines the default value for repo concurrent build limit.
BuildLimitDefault = 10

// BuildTimeoutMin defines the minimum value in minutes for repo build timeout.
BuildTimeoutMin = 1

// BuildTimeoutMax defines the maximum value in minutes for repo build timeout.
BuildTimeoutMax = 90

// BuildTimeoutDefault defines the default value in minutes for repo build timeout.
BuildTimeoutDefault = 30

// FavoritesMaxSize defines the maximum size in characters for user favorites.
FavoritesMaxSize = 5000

// RunningBuildIDsMaxSize defines the maximum size in characters for worker RunningBuildIDs.
RunningBuildIDsMaxSize = 500

// TopicsMaxSize defines the maximum size in characters for repo topics. Ex: GitHub has a 20-topic, 50-char limit.
TopicsMaxSize = 1020

// DeployBuildsMaxSize defines the maximum size in characters for deployment builds.
DeployBuildsMaxSize = 500

// ReportStepStatusLimit defines the maximum number of steps in a pipeline that may report their status to the SCM.
ReportStepStatusLimit = 10

// DashboardRepoLimit defines the maximum number of repos that can be assigned to a dashboard.
DashboardRepoLimit = 10

// UserDashboardLimit defines the maximum number of dashboards that can be assigned to a user.
UserDashboardLimit = 10

// DashboardAdminMaxSize defines the maximum size in characters for dashboard admins.
DashboardAdminMaxSize = 5000
)
6 changes: 6 additions & 0 deletions database/types/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/google/uuid"

api "github.com/go-vela/server/api/types"
"github.com/go-vela/server/constants"
"github.com/go-vela/server/util"
)

Expand Down Expand Up @@ -142,6 +143,11 @@ func (d *Dashboard) Validate() error {
return ErrEmptyDashName
}

// verify the number of repos
if len(d.Repos) > constants.DashboardRepoLimit {
return fmt.Errorf("exceeded repos limit of %d", constants.DashboardRepoLimit)
}

// ensure that all Dashboard string fields
// that can be returned as JSON are sanitized
// to avoid unsafe HTML content
Expand Down
15 changes: 15 additions & 0 deletions database/types/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ func TestTypes_Dashboard_ToAPI(t *testing.T) {
func TestTypes_Dashboard_Validate(t *testing.T) {
uuid, _ := uuid.Parse("c8da1302-07d6-11ea-882f-4893bca275b8")

dashRepo := new(api.DashboardRepo)
dashRepo.SetName("dashboard-repo")

dashRepos := []*api.DashboardRepo{}
for i := 0; i < 11; i++ {
dashRepos = append(dashRepos, dashRepo)
}

exceededReposDashboard := testDashboard()
exceededReposDashboard.Repos = DashReposJSON(dashRepos)

// setup tests
tests := []struct {
failure bool
Expand All @@ -105,6 +116,10 @@ func TestTypes_Dashboard_Validate(t *testing.T) {
ID: uuid,
},
},
{ // hit repo limit
failure: true,
dashboard: exceededReposDashboard,
},
}

// run tests
Expand Down
14 changes: 3 additions & 11 deletions database/types/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"github.com/lib/pq"

api "github.com/go-vela/server/api/types"
"github.com/go-vela/server/constants"
"github.com/go-vela/server/util"
"github.com/go-vela/types/constants"
)

var (
Expand Down Expand Up @@ -216,16 +216,8 @@ func (u *User) Validate() error {
return ErrExceededFavoritesLimit
}

// calculate totalDashboards size of dashboards
totalDashboards := 0
for _, d := range u.Dashboards {
totalDashboards += len(d)
}

// verify the Dashboards field is within the database constraints
// len is to factor in number of comma separators included in the database field,
// removing 1 due to the last item not having an appended comma
if (totalDashboards + len(u.Dashboards) - 1) > constants.FavoritesMaxSize {
// validate number of dashboards
if len(u.Dashboards) > constants.UserDashboardLimit {
return ErrExceededDashboardsLimit
}

Expand Down
8 changes: 4 additions & 4 deletions database/types/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func TestTypes_User_Validate(t *testing.T) {
ID: sql.NullInt64{Int64: 1, Valid: true},
Name: sql.NullString{String: "octocat", Valid: true},
Token: sql.NullString{String: "superSecretToken", Valid: true},
Favorites: exceededField(),
Favorites: exceededField(500),
},
},
{ // invalid dashboards set for user
Expand All @@ -213,7 +213,7 @@ func TestTypes_User_Validate(t *testing.T) {
ID: sql.NullInt64{Int64: 1, Valid: true},
Name: sql.NullString{String: "octocat", Valid: true},
Token: sql.NullString{String: "superSecretToken", Valid: true},
Dashboards: exceededField(),
Dashboards: exceededField(11),
},
},
}
Expand Down Expand Up @@ -275,12 +275,12 @@ func testUser() *User {
}

// exceededField returns a list of strings that exceed the maximum size of a field.
func exceededField() []string {
func exceededField(indexes int) []string {
// initialize empty favorites
values := []string{}

// add enough strings to exceed the character limit
for i := 0; i < 500; i++ {
for i := 0; i < indexes; i++ {
// construct field
// use i to adhere to unique favorites
field := "github/octocat-" + strconv.Itoa(i)
Expand Down
Loading