From 32f10a208bcee1e5dc3fccf49999e0484dca2d9d Mon Sep 17 00:00:00 2001 From: Ryan Slade Date: Mon, 12 Apr 2021 13:35:28 +0200 Subject: [PATCH] frontend: Return error early when user added repos exceed limit (#19920) --- .../graphqlbackend/set_external_service_repos.go | 12 ++++++++++-- internal/conf/computed.go | 16 ++++++++++++++++ internal/repos/conf.go | 16 ---------------- internal/repos/syncer.go | 4 ++-- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/cmd/frontend/graphqlbackend/set_external_service_repos.go b/cmd/frontend/graphqlbackend/set_external_service_repos.go index e77c7e305c2..c9148d71e7f 100644 --- a/cmd/frontend/graphqlbackend/set_external_service_repos.go +++ b/cmd/frontend/graphqlbackend/set_external_service_repos.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" "github.com/sourcegraph/sourcegraph/cmd/frontend/backend" + "github.com/sourcegraph/sourcegraph/internal/conf" "github.com/sourcegraph/sourcegraph/internal/database" "github.com/sourcegraph/sourcegraph/internal/timeutil" ) @@ -23,7 +24,8 @@ func (r *schemaResolver) SetExternalServiceRepos(ctx context.Context, args struc return nil, err } - es, err := database.GlobalExternalServices.GetByID(ctx, id) + extsvcStore := database.ExternalServices(r.db) + es, err := extsvcStore.GetByID(ctx, id) if err != nil { return nil, err } @@ -46,6 +48,12 @@ func (r *schemaResolver) SetExternalServiceRepos(ctx context.Context, args struc var repos []string if args.Repos != nil { repos = *args.Repos + // If we know the number of repos up front we can ensure that they don't exceed + // their limit before hitting the code host + maxAllowed := conf.UserReposMaxPerUser() + if es.NamespaceUserID != 0 && len(repos) > maxAllowed { + return nil, errors.Errorf("Too many repositories, %d. Sourcegraph supports adding a maximum of %d repositories.", len(repos), maxAllowed) + } } err = ra.SetRepos(args.AllRepos, repos) if err != nil { @@ -62,7 +70,7 @@ func (r *schemaResolver) SetExternalServiceRepos(ctx context.Context, args struc es.NextSyncAt = time.Time{} es.UpdatedAt = timeutil.Now() - err = database.GlobalExternalServices.Upsert(ctx, es) + err = extsvcStore.Upsert(ctx, es) if err != nil { return nil, err } diff --git a/internal/conf/computed.go b/internal/conf/computed.go index 8ee1def38bb..7d067a3705f 100644 --- a/internal/conf/computed.go +++ b/internal/conf/computed.go @@ -383,3 +383,19 @@ func GitMaxCodehostRequestsPerSecond() int { } return *val } + +func UserReposMaxPerUser() int { + v := Get().UserReposMaxPerUser + if v == 0 { + return 2000 + } + return v +} + +func UserReposMaxPerSite() int { + v := Get().UserReposMaxPerSite + if v == 0 { + return 200000 + } + return v +} diff --git a/internal/repos/conf.go b/internal/repos/conf.go index 367490aa33c..ca589d2e55f 100644 --- a/internal/repos/conf.go +++ b/internal/repos/conf.go @@ -21,19 +21,3 @@ func ConfRepoConcurrentExternalServiceSyncers() int { } return v } - -func ConfUserReposMaxPerUser() int { - v := conf.Get().UserReposMaxPerUser - if v == 0 { - return 2000 - } - return v -} - -func ConfUserReposMaxPerSite() int { - v := conf.Get().UserReposMaxPerSite - if v == 0 { - return 200000 - } - return v -} diff --git a/internal/repos/syncer.go b/internal/repos/syncer.go index 74068f9e7aa..f96bc30ffda 100644 --- a/internal/repos/syncer.go +++ b/internal/repos/syncer.go @@ -174,7 +174,7 @@ func (s *Syncer) SyncExternalService(ctx context.Context, tx *Store, externalSer // If we are over our limit for user added repos we abort the sync totalAllowed := uint64(s.UserReposMaxPerSite) if totalAllowed == 0 { - totalAllowed = uint64(ConfUserReposMaxPerSite()) + totalAllowed = uint64(conf.UserReposMaxPerSite()) } userAdded, err := tx.CountUserAddedRepos(ctx) if err != nil { @@ -189,7 +189,7 @@ func (s *Syncer) SyncExternalService(ctx context.Context, tx *Store, externalSer var sourcedRepoCount int64 maxAllowed := s.UserReposMaxPerUser if maxAllowed == 0 { - maxAllowed = ConfUserReposMaxPerUser() + maxAllowed = conf.UserReposMaxPerUser() } onSourced = func(r *types.Repo) error { newCount := atomic.AddInt64(&sourcedRepoCount, 1)