diff --git a/constants/limit.go b/constants/limit.go index 046b6c19b..8b492ec3e 100644 --- a/constants/limit.go +++ b/constants/limit.go @@ -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 ) diff --git a/database/types/dashboard.go b/database/types/dashboard.go index ba3b58efb..0d6023058 100644 --- a/database/types/dashboard.go +++ b/database/types/dashboard.go @@ -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" ) @@ -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 diff --git a/database/types/dashboard_test.go b/database/types/dashboard_test.go index f163e8b9c..60ca2cfa0 100644 --- a/database/types/dashboard_test.go +++ b/database/types/dashboard_test.go @@ -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 @@ -105,6 +116,10 @@ func TestTypes_Dashboard_Validate(t *testing.T) { ID: uuid, }, }, + { // hit repo limit + failure: true, + dashboard: exceededReposDashboard, + }, } // run tests diff --git a/database/types/user.go b/database/types/user.go index 0bfd13e2a..bde757a6b 100644 --- a/database/types/user.go +++ b/database/types/user.go @@ -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 ( @@ -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 } diff --git a/database/types/user_test.go b/database/types/user_test.go index 9edf57abf..3d02427e8 100644 --- a/database/types/user_test.go +++ b/database/types/user_test.go @@ -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 @@ -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), }, }, } @@ -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)