mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 17:31:43 +00:00
authz: Drop requirement for installing authz providers in every service (#63743)
This is a register call that is easy to forget. When forgotten, all queries against the repo store will block forever. In addition, this adds a hard-dependency on conf to every services startup, plus a busy loop. With multi-tenant, this will not work great because authz providers would be a global, and we instead want most things to be ephemeral so they're per-provider. This is a step toward that, but doesn't yet remove the providers global variable. Good news, it turns out that we don't actually need to register the providers in every service! The reason they were required was to check if zero providers are configured, or if authzbypass mode is enabled. Authz bypass mode is usually ON, except when there are problems with the authz providers, meaning some authz providers might not be able to sync permissions. Bypassing of permissions is only ever happening if there are ALSO zero providers configured. So this is basically an optimization for the case where an instance has zero authz configured so that the SQL queries are a bit simpler. This also helps in tests because with bypass mode on and no providers configured, authz enforcement is effectively off in the repo store. This makes it so that in tests we need to do slightly more work, but also makes for a more realistic test vs at runtime setup. Also, it's highly recommended to use mocks for DB wherever possible in more high-level components to keep tests fast. To never have a scenario where we accidentally mess up here and enable bypass mode erroneously, this PR drops that entirely. Authz is always enforced, but when a code host connection is unrestricted (i.e., will not spawn a provider) the repos are still visible, so this should be no change over before. ## Test plan The stack starts and works, and all CI tests are still passing. Code review should help as well.
This commit is contained in:
parent
32720268cc
commit
c917330d6b
@ -17,7 +17,6 @@ go_library(
|
||||
"//internal/actor",
|
||||
"//internal/api",
|
||||
"//internal/authz",
|
||||
"//internal/authz/providers",
|
||||
"//internal/authz/subrepoperms",
|
||||
"//internal/conf",
|
||||
"//internal/conf/conftypes",
|
||||
|
||||
@ -13,7 +13,6 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz/providers"
|
||||
srp "github.com/sourcegraph/sourcegraph/internal/authz/subrepoperms"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf/conftypes"
|
||||
@ -50,8 +49,6 @@ func Main(ctx context.Context, observationCtx *observation.Context, ready servic
|
||||
sqlDB := mustInitializeFrontendDB(observationCtx)
|
||||
db := database.NewDB(logger, sqlDB)
|
||||
|
||||
go setAuthzProviders(ctx, db)
|
||||
|
||||
repoStore := db.Repos()
|
||||
repoEmbeddingJobsStore := repo.NewRepoEmbeddingJobsStore(db)
|
||||
|
||||
@ -170,17 +167,6 @@ func mustInitializeFrontendDB(observationCtx *observation.Context) *sql.DB {
|
||||
return db
|
||||
}
|
||||
|
||||
// SetAuthzProviders periodically refreshes the global authz providers. This changes the repositories that are visible for reads based on the
|
||||
// current actor stored in an operation's context, which is likely an internal actor for many of
|
||||
// the jobs configured in this service. This also enables repository update operations to fetch
|
||||
// permissions from code hosts.
|
||||
func setAuthzProviders(ctx context.Context, db database.DB) {
|
||||
for range time.NewTicker(providers.RefreshInterval(conf.Get())).C {
|
||||
allowAccessByDefault, authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
authz.SetProviders(allowAccessByDefault, authzProviders)
|
||||
}
|
||||
}
|
||||
|
||||
func handlePanic(logger log.Logger, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
|
||||
@ -298,7 +298,7 @@ func NewJSContextFromRequest(req *http.Request, db database.DB) JSContext {
|
||||
|
||||
// Auth providers
|
||||
authProviders := []authProviderInfo{} // Explicitly initialise array, otherwise it gets marshalled to null instead of []
|
||||
_, authzProviders := authz.GetProviders()
|
||||
authzProviders := authz.GetProviders()
|
||||
for _, p := range providers.SortedProviders() {
|
||||
commonConfig := providers.GetAuthProviderCommon(p)
|
||||
if commonConfig.Hidden {
|
||||
|
||||
@ -69,10 +69,9 @@ func Init(
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, _, _, invalidConnections := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
_, _, _, invalidConnections := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
|
||||
// We currently support three types of authz providers: GitHub, GitLab and Bitbucket Server.
|
||||
authzTypes := make(map[string]struct{}, 3)
|
||||
authzTypes := map[string]struct{}{}
|
||||
for _, conn := range invalidConnections {
|
||||
authzTypes[conn] = struct{}{}
|
||||
}
|
||||
@ -133,10 +132,9 @@ func Init(
|
||||
})
|
||||
|
||||
go func() {
|
||||
t := time.NewTicker(5 * time.Second)
|
||||
for range t.C {
|
||||
allowAccessByDefault, authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
authz.SetProviders(allowAccessByDefault, authzProviders)
|
||||
for range time.NewTicker(providers.RefreshInterval(conf.Get())).C {
|
||||
authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
authz.SetProviders(authzProviders)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@ -492,7 +492,7 @@ func (r *Resolver) AuthzProviderTypes(ctx context.Context) ([]string, error) {
|
||||
if err := auth.CheckCurrentUserIsSiteAdmin(ctx, r.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, providers := authz.GetProviders()
|
||||
providers := authz.GetProviders()
|
||||
providerTypes := make([]string, 0, len(providers))
|
||||
for _, p := range providers {
|
||||
providerTypes = append(providerTypes, p.ServiceType())
|
||||
|
||||
@ -1200,8 +1200,8 @@ func TestResolver_AuthzProviderTypes(t *testing.T) {
|
||||
ctx := actor.WithActor(context.Background(), &actor.Actor{UID: 1})
|
||||
|
||||
ghProvider := github.NewProvider("https://github.com", github.ProviderOptions{GitHubURL: mustURL(t, "https://github.com")})
|
||||
authz.SetProviders(false, []authz.Provider{ghProvider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{ghProvider})
|
||||
defer authz.SetProviders(nil)
|
||||
result, err := (&Resolver{db: db}).AuthzProviderTypes(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"github"}, result)
|
||||
@ -1471,7 +1471,6 @@ func TestResolver_RepositoryPermissionsInfo(t *testing.T) {
|
||||
perms.LoadRepoPermissionsFunc.SetDefaultHook(func(_ context.Context, repoID int32) ([]authz.Permission, error) {
|
||||
return []authz.Permission{{RepoID: repoID, UserID: 42, UpdatedAt: clock()}}, nil
|
||||
})
|
||||
perms.IsRepoUnrestrictedFunc.SetDefaultReturn(false, nil)
|
||||
perms.ListRepoPermissionsFunc.SetDefaultReturn([]*database.RepoPermission{{User: &types.User{ID: 42}}}, nil)
|
||||
|
||||
syncJobs := dbmocks.NewStrictMockPermissionSyncJobStore()
|
||||
|
||||
@ -56,6 +56,7 @@ func TestBatchSpecResolver(t *testing.T) {
|
||||
userID := bt.CreateTestUser(t, db, false).ID
|
||||
adminID := bt.CreateTestUser(t, db, true).ID
|
||||
orgID := bt.CreateTestOrg(t, db, orgname, userID).ID
|
||||
bt.MockRepoPermissions(t, db, userID, repo.ID)
|
||||
|
||||
spec, err := btypes.NewBatchSpecFromRaw(bt.TestRawBatchSpec)
|
||||
if err != nil {
|
||||
@ -275,6 +276,7 @@ func TestBatchSpecResolver_BatchSpecCreatedFromRaw(t *testing.T) {
|
||||
userCtx := actor.WithActor(ctx, actor.FromUser(user.ID))
|
||||
|
||||
rs, extSvc := bt.CreateTestRepos(t, ctx, db, 3)
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID)
|
||||
|
||||
bstore := store.New(db, observation.TestContextTB(t), nil)
|
||||
|
||||
@ -495,6 +497,7 @@ func TestBatchSpecResolver_BatchSpecCreatedFromRaw(t *testing.T) {
|
||||
want.ViewerCanAdminister = false
|
||||
want.ViewerCanRetry = false
|
||||
otherUser := bt.CreateTestUser(t, db, false)
|
||||
bt.MockRepoPermissions(t, db, otherUser.ID, rs[0].ID, rs[1].ID, rs[2].ID)
|
||||
otherUserCtx := actor.WithActor(ctx, actor.FromUser(otherUser.ID))
|
||||
queryAndAssertBatchSpec(t, otherUserCtx, s, apiID, want)
|
||||
}
|
||||
|
||||
@ -84,6 +84,8 @@ func TestPermissionLevels(t *testing.T) {
|
||||
if err := repoStore.Create(ctx, repo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bt.MockRepoPermissions(t, db, userID, repo.ID)
|
||||
bt.MockRepoPermissions(t, db, nonOrgUserID, repo.ID)
|
||||
|
||||
changeset := &btypes.Changeset{
|
||||
RepoID: repo.ID,
|
||||
@ -1392,6 +1394,7 @@ func TestRepositoryPermissions(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("BatchChange and changesets", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, userID, repos[0].ID, repos[1].ID)
|
||||
// Create 2 changesets for 2 repositories
|
||||
changesetBaseRefOid := "f00b4r"
|
||||
changesetHeadRefOid := "b4rf00"
|
||||
@ -1523,6 +1526,7 @@ func TestRepositoryPermissions(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("BatchSpec and changesetSpecs", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, userID, repos[0].ID, repos[1].ID)
|
||||
batchSpec := &btypes.BatchSpec{
|
||||
UserID: userID,
|
||||
NamespaceUserID: userID,
|
||||
@ -1602,6 +1606,7 @@ func TestRepositoryPermissions(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("BatchSpec and workspaces", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, userID, repos[0].ID, repos[1].ID)
|
||||
batchSpec := &btypes.BatchSpec{
|
||||
UserID: userID,
|
||||
NamespaceUserID: userID,
|
||||
|
||||
@ -286,7 +286,7 @@ func Main(ctx context.Context, observationCtx *observation.Context, ready servic
|
||||
ExternalServiceURL string `json:"external_service_url"`
|
||||
}
|
||||
|
||||
_, providers := authz.GetProviders()
|
||||
providers := authz.GetProviders()
|
||||
infos := make([]providerInfo, len(providers))
|
||||
for i, p := range providers {
|
||||
_, id := extsvc.DecodeURN(p.URN())
|
||||
|
||||
@ -290,12 +290,6 @@ func makeGRPCServer(logger log.Logger, s *server.Server, c *Config) *grpc.Server
|
||||
|
||||
// getDB initializes a connection to the database and returns a dbutil.DB
|
||||
func getDB(observationCtx *observation.Context) (*sql.DB, error) {
|
||||
// Gitserver is an internal actor. We rely on the frontend to do authz checks for
|
||||
// user requests.
|
||||
//
|
||||
// This call to SetProviders is here so that calls to GetProviders don't block.
|
||||
authz.SetProviders(true, []authz.Provider{})
|
||||
|
||||
dsn := conf.GetServiceConnectionValueAndRestartOnChange(func(serviceConnections conftypes.ServiceConnections) string {
|
||||
return serviceConnections.PostgresDSN
|
||||
})
|
||||
|
||||
@ -12,7 +12,6 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//internal/authz",
|
||||
"//internal/authz/providers",
|
||||
"//internal/authz/subrepoperms",
|
||||
"//internal/codeintel",
|
||||
"//internal/codeintel/shared",
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"github.com/sourcegraph/log"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz/providers"
|
||||
srp "github.com/sourcegraph/sourcegraph/internal/authz/subrepoperms"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel"
|
||||
codeintelshared "github.com/sourcegraph/sourcegraph/internal/codeintel/shared"
|
||||
@ -106,21 +105,6 @@ func mustInitializeDB(observationCtx *observation.Context) *sql.DB {
|
||||
log.Scoped("init db").Fatal("Failed to connect to frontend database", log.Error(err))
|
||||
}
|
||||
|
||||
//
|
||||
// START FLAILING
|
||||
|
||||
ctx := context.Background()
|
||||
db := database.NewDB(observationCtx.Logger, sqlDB)
|
||||
go func() {
|
||||
for range time.NewTicker(providers.RefreshInterval(conf.Get())).C {
|
||||
allowAccessByDefault, authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
authz.SetProviders(allowAccessByDefault, authzProviders)
|
||||
}
|
||||
}()
|
||||
|
||||
// END FLAILING
|
||||
//
|
||||
|
||||
return sqlDB
|
||||
}
|
||||
|
||||
|
||||
@ -19,8 +19,6 @@ go_library(
|
||||
"//cmd/repo-updater/internal/repoupdater",
|
||||
"//cmd/repo-updater/internal/scheduler",
|
||||
"//internal/actor",
|
||||
"//internal/authz",
|
||||
"//internal/authz/providers",
|
||||
"//internal/batches",
|
||||
"//internal/batches/syncer",
|
||||
"//internal/codeintel/dependencies",
|
||||
|
||||
@ -23,8 +23,6 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/cmd/repo-updater/internal/repoupdater"
|
||||
"github.com/sourcegraph/sourcegraph/cmd/repo-updater/internal/scheduler"
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz/providers"
|
||||
"github.com/sourcegraph/sourcegraph/internal/batches"
|
||||
"github.com/sourcegraph/sourcegraph/internal/batches/syncer"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/dependencies"
|
||||
@ -121,7 +119,6 @@ func Main(ctx context.Context, observationCtx *observation.Context, ready servic
|
||||
}
|
||||
|
||||
go globals.WatchExternalURL()
|
||||
go watchAuthzProviders(ctx, db)
|
||||
go watchSyncer(ctx, logger, syncer, updateScheduler, server.ChangesetSyncRegistry)
|
||||
|
||||
routines := []goroutine.BackgroundRoutine{
|
||||
@ -349,22 +346,6 @@ func newUnclonedReposManager(ctx context.Context, logger log.Logger, sched *sche
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: This might clash with what osscmd.Main does.
|
||||
// watchAuthzProviders updates authz providers if config changes.
|
||||
func watchAuthzProviders(ctx context.Context, db database.DB) {
|
||||
go func() {
|
||||
t := time.NewTicker(providers.RefreshInterval(conf.Get()))
|
||||
for range t.C {
|
||||
allowAccessByDefault, authzProviders, _, _, _ := providers.ProvidersFromConfig(
|
||||
ctx,
|
||||
conf.Get(),
|
||||
db,
|
||||
)
|
||||
authz.SetProviders(allowAccessByDefault, authzProviders)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func mustRegisterMetrics(logger log.Logger, db dbutil.DB) {
|
||||
scanCount := func(sql string) (float64, error) {
|
||||
row := db.QueryRowContext(context.Background(), sql)
|
||||
|
||||
@ -14,7 +14,6 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//internal/api",
|
||||
"//internal/authz",
|
||||
"//internal/codeintel/shared",
|
||||
"//internal/codeintel/shared/lsifuploadstore",
|
||||
"//internal/codeintel/syntactic_indexing/jobstore",
|
||||
|
||||
@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/sourcegraph/log"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
codeintelshared "github.com/sourcegraph/sourcegraph/internal/codeintel/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/syntactic_indexing/jobstore"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
@ -79,16 +78,6 @@ func Main(ctx context.Context, observationCtx *observation.Context, ready servic
|
||||
}
|
||||
|
||||
func initCodeintelDB(observationCtx *observation.Context, name string) (*sql.DB, error) {
|
||||
// This is an internal service, so we rely on the
|
||||
// frontend to do authz checks for user requests.
|
||||
// Authz checks are enforced by the DB layer
|
||||
//
|
||||
// This call to SetProviders is here so that calls to GetProviders don't block.
|
||||
// Relevant PR: https://github.com/sourcegraph/sourcegraph/pull/15755
|
||||
// Relevant issue: https://github.com/sourcegraph/sourcegraph/issues/15962
|
||||
|
||||
authz.SetProviders(true, []authz.Provider{})
|
||||
|
||||
dsn := conf.GetServiceConnectionValueAndRestartOnChange(func(serviceConnections conftypes.ServiceConnections) string {
|
||||
return serviceConnections.PostgresDSN
|
||||
})
|
||||
@ -104,16 +93,6 @@ func initCodeintelDB(observationCtx *observation.Context, name string) (*sql.DB,
|
||||
}
|
||||
|
||||
func initDB(observationCtx *observation.Context, name string) (*sql.DB, error) {
|
||||
// This is an internal service, so we rely on the
|
||||
// frontend to do authz checks for user requests.
|
||||
// Authz checks are enforced by the DB layer
|
||||
//
|
||||
// This call to SetProviders is here so that calls to GetProviders don't block.
|
||||
// Relevant PR: https://github.com/sourcegraph/sourcegraph/pull/15755
|
||||
// Relevant issue: https://github.com/sourcegraph/sourcegraph/issues/15962
|
||||
|
||||
authz.SetProviders(true, []authz.Provider{})
|
||||
|
||||
dsn := conf.GetServiceConnectionValueAndRestartOnChange(func(serviceConnections conftypes.ServiceConnections) string {
|
||||
return serviceConnections.PostgresDSN
|
||||
})
|
||||
|
||||
@ -215,8 +215,8 @@ func TestIntegration_GitHubPermissions(t *testing.T) {
|
||||
DB: testDB,
|
||||
})
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{provider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{provider})
|
||||
defer authz.SetProviders(nil)
|
||||
|
||||
assertGitHubRepoPermissions(t, ctx, repo.ID, user.ID, uri.String(), syncer, permsStore, []int32{1})
|
||||
})
|
||||
@ -232,8 +232,8 @@ func TestIntegration_GitHubPermissions(t *testing.T) {
|
||||
DB: testDB,
|
||||
})
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{provider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{provider})
|
||||
defer authz.SetProviders(nil)
|
||||
|
||||
assertGitHubRepoPermissions(t, ctx, repo.ID, user.ID, uri.String(), syncer, permsStore, []int32{1})
|
||||
})
|
||||
@ -254,8 +254,8 @@ func TestIntegration_GitHubPermissions(t *testing.T) {
|
||||
DB: testDB,
|
||||
})
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{provider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{provider})
|
||||
defer authz.SetProviders(nil)
|
||||
|
||||
assertGitHubUserPermissions(t, ctx, user.ID, uri.String(), syncer, permsStore, []int32{1})
|
||||
})
|
||||
@ -271,8 +271,8 @@ func TestIntegration_GitHubPermissions(t *testing.T) {
|
||||
DB: testDB,
|
||||
})
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{provider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{provider})
|
||||
defer authz.SetProviders(nil)
|
||||
|
||||
assertGitHubUserPermissions(t, ctx, user.ID, uri.String(), syncer, permsStore, []int32{1})
|
||||
})
|
||||
@ -361,8 +361,8 @@ func TestIntegration_GitHubInternalRepositories(t *testing.T) {
|
||||
DB: testDB,
|
||||
})
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{provider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{provider})
|
||||
defer authz.SetProviders(nil)
|
||||
|
||||
repo := types.Repo{
|
||||
Name: "ghe.sgdev.org/sourcegraph/sourcegraph_internal_repo",
|
||||
@ -505,8 +505,8 @@ func TestIntegration_GitLabPermissions(t *testing.T) {
|
||||
SyncInternalRepoPermissions: true,
|
||||
})
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{provider})
|
||||
defer authz.SetProviders(true, nil)
|
||||
authz.SetProviders([]authz.Provider{provider})
|
||||
defer authz.SetProviders(nil)
|
||||
for _, repo := range testRepos {
|
||||
err = reposStore.RepoStore().Create(ctx, &repo)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -340,7 +340,7 @@ func (s *permsSyncerImpl) syncUserPerms(ctx context.Context, userID int32, noPer
|
||||
// providersByServiceID returns a list of authz.Provider configured in the external services.
|
||||
// Keys are ServiceID, e.g. "https://github.com/".
|
||||
func (s *permsSyncerImpl) providersByServiceID() map[string]authz.Provider {
|
||||
_, ps := authz.GetProviders()
|
||||
ps := authz.GetProviders()
|
||||
providers := make(map[string]authz.Provider, len(ps))
|
||||
for _, p := range ps {
|
||||
providers[p.ServiceID()] = p
|
||||
@ -351,7 +351,7 @@ func (s *permsSyncerImpl) providersByServiceID() map[string]authz.Provider {
|
||||
// providersByURNs returns a list of authz.Provider configured in the external services.
|
||||
// Keys are URN, e.g. "extsvc:github:1".
|
||||
func (s *permsSyncerImpl) providersByURNs() map[string]authz.Provider {
|
||||
_, ps := authz.GetProviders()
|
||||
ps := authz.GetProviders()
|
||||
providers := make(map[string]authz.Provider, len(ps))
|
||||
for _, p := range ps {
|
||||
providers[p.URN()] = p
|
||||
|
||||
@ -67,9 +67,9 @@ func TestPermsSyncer_syncUserPerms(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -157,9 +157,9 @@ func TestPermsSyncer_syncUserPerms_listExternalAccountsError(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
users := dbmocks.NewMockUserStore()
|
||||
@ -226,9 +226,9 @@ func TestPermsSyncer_syncUserPerms_fetchAccount(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitHub,
|
||||
serviceID: "https://github.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p1, p2})
|
||||
authz.SetProviders([]authz.Provider{p1, p2})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
users := dbmocks.NewMockUserStore()
|
||||
@ -397,9 +397,9 @@ func TestPermsSyncer_syncUserPermsTemporaryProviderError(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -488,9 +488,9 @@ func TestPermsSyncer_syncUserPermsTemporaryProviderError(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -605,9 +605,9 @@ func TestPermsSyncer_syncUserPermsTemporaryProviderError(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -742,9 +742,9 @@ func TestPermsSyncer_syncUserPerms_noPerms(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -838,9 +838,9 @@ func TestPermsSyncer_syncUserPerms_tokenExpire(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitHub,
|
||||
serviceID: "https://github.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -935,9 +935,9 @@ func TestPermsSyncer_syncUserPerms_prefixSpecs(t *testing.T) {
|
||||
serviceType: extsvc.TypePerforce,
|
||||
serviceID: "ssl:111.222.333.444:1666",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
extAccount := extsvc.Account{
|
||||
@ -1012,9 +1012,9 @@ func TestPermsSyncer_syncUserPerms_subRepoPermissions(t *testing.T) {
|
||||
serviceType: extsvc.TypePerforce,
|
||||
serviceID: "ssl:111.222.333.444:1666",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
users := dbmocks.NewMockUserStore()
|
||||
@ -1183,9 +1183,9 @@ func TestPermsSyncer_syncRepoPerms(t *testing.T) {
|
||||
return nil, errors.New("not supposed to be called")
|
||||
},
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p1, p2})
|
||||
authz.SetProviders([]authz.Provider{p1, p2})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
mockRepos.ListFunc.SetDefaultReturn(
|
||||
@ -1269,9 +1269,9 @@ func TestPermsSyncer_syncRepoPerms(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
mockRepos.GetFunc.SetDefaultReturn(
|
||||
&types.Repo{
|
||||
@ -1319,9 +1319,9 @@ func TestPermsSyncer_syncRepoPerms(t *testing.T) {
|
||||
serviceType: extsvc.TypeGitLab,
|
||||
serviceID: "https://gitlab.com/",
|
||||
}
|
||||
authz.SetProviders(false, []authz.Provider{p})
|
||||
authz.SetProviders([]authz.Provider{p})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
authz.SetProviders(nil)
|
||||
})
|
||||
|
||||
mockRepos.ListFunc.SetDefaultReturn(
|
||||
|
||||
@ -800,10 +800,11 @@ changesetTemplate:
|
||||
}
|
||||
|
||||
func TestBatchSpecWorkspaceCreatorProcess_Importing(t *testing.T) {
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
|
||||
repos, _ := bt.CreateTestRepos(t, context.Background(), db, 1)
|
||||
repos, _ := bt.CreateTestRepos(t, ctx, db, 1)
|
||||
|
||||
user := bt.CreateTestUser(t, db, true)
|
||||
|
||||
@ -820,7 +821,7 @@ importChangesets:
|
||||
`
|
||||
|
||||
batchSpec := &btypes.BatchSpec{UserID: user.ID, NamespaceUserID: user.ID, RawSpec: testSpecYAML}
|
||||
if err := s.CreateBatchSpec(context.Background(), batchSpec); err != nil {
|
||||
if err := s.CreateBatchSpec(ctx, batchSpec); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -829,11 +830,11 @@ importChangesets:
|
||||
resolver := &dummyWorkspaceResolver{}
|
||||
|
||||
creator := &batchSpecWorkspaceCreator{store: s, logger: logtest.Scoped(t)}
|
||||
if err := creator.process(context.Background(), resolver.DummyBuilder, job); err != nil {
|
||||
if err := creator.process(ctx, resolver.DummyBuilder, job); err != nil {
|
||||
t.Fatalf("proces failed: %s", err)
|
||||
}
|
||||
|
||||
have, _, err := s.ListChangesetSpecs(context.Background(), store.ListChangesetSpecsOpts{BatchSpecID: batchSpec.ID})
|
||||
have, _, err := s.ListChangesetSpecs(ctx, store.ListChangesetSpecsOpts{BatchSpecID: batchSpec.ID})
|
||||
if err != nil {
|
||||
t.Fatalf("listing specs failed: %s", err)
|
||||
}
|
||||
@ -859,9 +860,10 @@ importChangesets:
|
||||
|
||||
func TestBatchSpecWorkspaceCreatorProcess_NoDiff(t *testing.T) {
|
||||
logger := logtest.Scoped(t)
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
|
||||
repos, _ := bt.CreateTestRepos(t, context.Background(), db, 1)
|
||||
repos, _ := bt.CreateTestRepos(t, ctx, db, 1)
|
||||
|
||||
user := bt.CreateTestUser(t, db, true)
|
||||
|
||||
@ -878,7 +880,7 @@ importChangesets:
|
||||
`
|
||||
|
||||
batchSpec := &btypes.BatchSpec{UserID: user.ID, NamespaceUserID: user.ID, RawSpec: testSpecYAML}
|
||||
if err := s.CreateBatchSpec(context.Background(), batchSpec); err != nil {
|
||||
if err := s.CreateBatchSpec(ctx, batchSpec); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -887,11 +889,11 @@ importChangesets:
|
||||
resolver := &dummyWorkspaceResolver{}
|
||||
|
||||
creator := &batchSpecWorkspaceCreator{store: s, logger: logtest.Scoped(t)}
|
||||
if err := creator.process(context.Background(), resolver.DummyBuilder, job); err != nil {
|
||||
if err := creator.process(ctx, resolver.DummyBuilder, job); err != nil {
|
||||
t.Fatalf("proces failed: %s", err)
|
||||
}
|
||||
|
||||
have, _, err := s.ListChangesetSpecs(context.Background(), store.ListChangesetSpecsOpts{BatchSpecID: batchSpec.ID})
|
||||
have, _, err := s.ListChangesetSpecs(ctx, store.ListChangesetSpecsOpts{BatchSpecID: batchSpec.ID})
|
||||
if err != nil {
|
||||
t.Fatalf("listing specs failed: %s", err)
|
||||
}
|
||||
|
||||
@ -19,8 +19,8 @@ go_library(
|
||||
"//internal/api",
|
||||
"//internal/auth",
|
||||
"//internal/authz",
|
||||
"//internal/authz/providers",
|
||||
"//internal/conf",
|
||||
"//internal/conf/conftypes",
|
||||
"//internal/database",
|
||||
"//internal/database/basestore",
|
||||
"//internal/env",
|
||||
@ -30,6 +30,7 @@ go_library(
|
||||
"//internal/goroutine",
|
||||
"//internal/httpcli",
|
||||
"//internal/jsonc",
|
||||
"//internal/licensing",
|
||||
"//internal/metrics",
|
||||
"//internal/observation",
|
||||
"//internal/timeutil",
|
||||
@ -73,6 +74,7 @@ go_test(
|
||||
"//internal/errcode",
|
||||
"//internal/extsvc",
|
||||
"//internal/extsvc/bitbucketserver",
|
||||
"//internal/licensing",
|
||||
"//internal/observation",
|
||||
"//internal/timeutil",
|
||||
"//internal/types",
|
||||
@ -81,6 +83,7 @@ go_test(
|
||||
"@com_github_google_go_cmp//cmp",
|
||||
"@com_github_sourcegraph_log//:log",
|
||||
"@com_github_sourcegraph_log//logtest",
|
||||
"@com_github_stretchr_testify//assert",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
)
|
||||
|
||||
@ -12,11 +12,13 @@ import (
|
||||
workerdb "github.com/sourcegraph/sourcegraph/cmd/worker/shared/init/db"
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/auth"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz/providers"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf/conftypes"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/env"
|
||||
"github.com/sourcegraph/sourcegraph/internal/goroutine"
|
||||
"github.com/sourcegraph/sourcegraph/internal/licensing"
|
||||
"github.com/sourcegraph/sourcegraph/internal/metrics"
|
||||
"github.com/sourcegraph/sourcegraph/internal/observation"
|
||||
"github.com/sourcegraph/sourcegraph/internal/timeutil"
|
||||
@ -79,7 +81,7 @@ func (p *permissionSyncJobScheduler) Routines(_ context.Context, observationCtx
|
||||
context.Background(),
|
||||
goroutine.HandlerFunc(
|
||||
func(ctx context.Context) error {
|
||||
if providers.PermissionSyncingDisabled(conf.Get()) {
|
||||
if permissionSyncingDisabled(conf.Get()) {
|
||||
logger.Debug("scheduler disabled due to permission syncing disabled")
|
||||
return nil
|
||||
}
|
||||
@ -289,3 +291,15 @@ func oldestRepoPermissionsBatchSize() int {
|
||||
}
|
||||
return batchSize
|
||||
}
|
||||
|
||||
// permissionSyncingDisabled returns true if the background permissions syncing is not enabled.
|
||||
// It is not enabled if:
|
||||
// - There are no code host connections with authorization or enforcePermissions enabled
|
||||
// - Not purchased with the current license
|
||||
// - `disableAutoCodeHostSyncs` site setting is set to true
|
||||
func permissionSyncingDisabled(cfg conftypes.UnifiedQuerier) bool {
|
||||
p := authz.GetProviders()
|
||||
return len(p) == 0 ||
|
||||
licensing.Check(licensing.FeatureACLs) != nil ||
|
||||
cfg.SiteConfig().DisableAutoCodeHostSyncs
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/auth"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc"
|
||||
"github.com/sourcegraph/sourcegraph/internal/licensing"
|
||||
"github.com/sourcegraph/sourcegraph/internal/timeutil"
|
||||
"github.com/sourcegraph/sourcegraph/internal/types"
|
||||
"github.com/sourcegraph/sourcegraph/lib/pointers"
|
||||
@ -349,3 +351,87 @@ func TestOldestRepoPermissionsBatchSize(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPermissionSyncingDisabled(t *testing.T) {
|
||||
authz.SetProviders([]authz.Provider{&mockProvider{}})
|
||||
cleanupLicense := licensing.MockCheckFeatureError("")
|
||||
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(nil)
|
||||
cleanupLicense()
|
||||
})
|
||||
|
||||
t.Run("no authz providers", func(t *testing.T) {
|
||||
authz.SetProviders(nil)
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders([]authz.Provider{&mockProvider{}})
|
||||
})
|
||||
|
||||
assert.True(t, permissionSyncingDisabled(&conf.Unified{}))
|
||||
})
|
||||
|
||||
t.Run("permissions user mapping enabled", func(t *testing.T) {
|
||||
cleanup := mockExplicitPermissions(true)
|
||||
t.Cleanup(func() {
|
||||
cleanup()
|
||||
conf.Mock(nil)
|
||||
})
|
||||
|
||||
assert.False(t, permissionSyncingDisabled(&conf.Unified{}))
|
||||
})
|
||||
|
||||
t.Run("license does not have acls feature", func(t *testing.T) {
|
||||
licensing.MockCheckFeatureError("failed")
|
||||
t.Cleanup(func() {
|
||||
licensing.MockCheckFeatureError("")
|
||||
})
|
||||
assert.True(t, permissionSyncingDisabled(&conf.Unified{}))
|
||||
})
|
||||
|
||||
t.Run("Auto code host syncs disabled", func(t *testing.T) {
|
||||
assert.True(t, permissionSyncingDisabled(&conf.Unified{SiteConfiguration: schema.SiteConfiguration{DisableAutoCodeHostSyncs: true}}))
|
||||
})
|
||||
|
||||
t.Run("Auto code host syncs enabled", func(t *testing.T) {
|
||||
assert.False(t, permissionSyncingDisabled(&conf.Unified{SiteConfiguration: schema.SiteConfiguration{DisableAutoCodeHostSyncs: false}}))
|
||||
})
|
||||
}
|
||||
|
||||
type mockProvider struct {
|
||||
codeHost *extsvc.CodeHost
|
||||
extAcct *extsvc.Account
|
||||
}
|
||||
|
||||
func (p *mockProvider) FetchAccount(context.Context, *types.User, []*extsvc.Account, []string) (mine *extsvc.Account, err error) {
|
||||
return p.extAcct, nil
|
||||
}
|
||||
|
||||
func (p *mockProvider) ServiceType() string { return p.codeHost.ServiceType }
|
||||
func (p *mockProvider) ServiceID() string { return p.codeHost.ServiceID }
|
||||
func (p *mockProvider) URN() string { return extsvc.URN(p.codeHost.ServiceType, 0) }
|
||||
|
||||
func (p *mockProvider) ValidateConnection(context.Context) error { return nil }
|
||||
|
||||
func (p *mockProvider) FetchUserPerms(context.Context, *extsvc.Account, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *mockProvider) FetchUserPermsByToken(context.Context, string, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *mockProvider) FetchRepoPerms(context.Context, *extsvc.Repository, authz.FetchPermsOptions) ([]extsvc.AccountID, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func mockExplicitPermissions(enabled bool) func() {
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: enabled,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
return func() { conf.Mock(nil) }
|
||||
}
|
||||
|
||||
@ -405,7 +405,7 @@ func setAuthzProviders(ctx context.Context, observationCtx *observation.Context)
|
||||
}
|
||||
|
||||
for range time.NewTicker(providers.RefreshInterval(conf.Get())).C {
|
||||
allowAccessByDefault, authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
authz.SetProviders(allowAccessByDefault, authzProviders)
|
||||
authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db)
|
||||
authz.SetProviders(authzProviders)
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ go_library(
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//dev/ci/integration/executors/tester/config",
|
||||
"//internal/authz",
|
||||
"//internal/batches/store",
|
||||
"//internal/batches/types",
|
||||
"//internal/database",
|
||||
|
||||
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/sourcegraph/log"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
batchesstore "github.com/sourcegraph/sourcegraph/internal/batches/store"
|
||||
"github.com/sourcegraph/sourcegraph/internal/batches/types"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
@ -343,9 +342,6 @@ var expectedState = gqltestutil.BatchSpecDeep{
|
||||
}
|
||||
|
||||
func initDB(logger log.Logger) (database.DB, error) {
|
||||
// This call to SetProviders is here so that calls to GetProviders don't block.
|
||||
authz.SetProviders(true, []authz.Provider{})
|
||||
|
||||
obsCtx := observation.TestContext
|
||||
obsCtx.Logger = logger
|
||||
sqlDB, err := connections.RawNewFrontendDB(&obsCtx, "postgres://sg@127.0.0.1:5433/sg", "")
|
||||
|
||||
@ -20,7 +20,6 @@ go_library(
|
||||
"//internal/database",
|
||||
"//internal/extsvc",
|
||||
"//internal/httpcli",
|
||||
"//internal/licensing",
|
||||
"//internal/types",
|
||||
"//lib/errors",
|
||||
"//schema",
|
||||
|
||||
@ -19,7 +19,6 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc"
|
||||
"github.com/sourcegraph/sourcegraph/internal/httpcli"
|
||||
"github.com/sourcegraph/sourcegraph/internal/licensing"
|
||||
"github.com/sourcegraph/sourcegraph/internal/types"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
"github.com/sourcegraph/sourcegraph/schema"
|
||||
@ -40,7 +39,6 @@ func ProvidersFromConfig(
|
||||
cfg conftypes.SiteConfigQuerier,
|
||||
db database.DB,
|
||||
) (
|
||||
allowAccessByDefault bool,
|
||||
providers []authz.Provider,
|
||||
seriousProblems []string,
|
||||
warnings []string,
|
||||
@ -48,11 +46,9 @@ func ProvidersFromConfig(
|
||||
) {
|
||||
logger := log.Scoped("authz")
|
||||
|
||||
allowAccessByDefault = true
|
||||
defer func() {
|
||||
if len(seriousProblems) > 0 {
|
||||
logger.Error("Repository authz config was invalid (errors are visible in the UI as an admin user, you should fix ASAP). Restricting access to repositories by default for now to be safe.", log.Strings("seriousProblems", seriousProblems))
|
||||
allowAccessByDefault = false
|
||||
}
|
||||
}()
|
||||
|
||||
@ -157,14 +153,14 @@ func ProvidersFromConfig(
|
||||
}
|
||||
|
||||
initResult := github.NewAuthzProviders(ctx, db, gitHubConns, cfg.SiteConfig().AuthProviders, enableGithubInternalRepoVisibility)
|
||||
initResult.Append(gitlab.NewAuthzProviders(db, cfg.SiteConfig(), gitLabConns))
|
||||
initResult.Append(gitlab.NewAuthzProviders(db, gitLabConns, cfg.SiteConfig().AuthProviders))
|
||||
initResult.Append(bitbucketserver.NewAuthzProviders(bitbucketServerConns))
|
||||
initResult.Append(perforce.NewAuthzProviders(perforceConns))
|
||||
initResult.Append(bitbucketcloud.NewAuthzProviders(db, bitbucketCloudConns, cfg.SiteConfig().AuthProviders))
|
||||
initResult.Append(gerrit.NewAuthzProviders(gerritConns, cfg.SiteConfig().AuthProviders))
|
||||
initResult.Append(bitbucketcloud.NewAuthzProviders(db, bitbucketCloudConns))
|
||||
initResult.Append(gerrit.NewAuthzProviders(gerritConns))
|
||||
initResult.Append(azuredevops.NewAuthzProviders(db, azuredevopsConns, httpcli.ExternalClient))
|
||||
|
||||
return allowAccessByDefault, initResult.Providers, initResult.Problems, initResult.Warnings, initResult.InvalidConnections
|
||||
return initResult.Providers, initResult.Problems, initResult.Warnings, initResult.InvalidConnections
|
||||
}
|
||||
|
||||
func RefreshInterval(cfg conftypes.UnifiedQuerier) time.Duration {
|
||||
@ -175,18 +171,6 @@ func RefreshInterval(cfg conftypes.UnifiedQuerier) time.Duration {
|
||||
return time.Duration(interval) * time.Second
|
||||
}
|
||||
|
||||
// PermissionSyncingDisabled returns true if the background permissions syncing is not enabled.
|
||||
// It is not enabled if:
|
||||
// - There are no code host connections with authorization or enforcePermissions enabled
|
||||
// - Not purchased with the current license
|
||||
// - `disableAutoCodeHostSyncs` site setting is set to true
|
||||
func PermissionSyncingDisabled(cfg conftypes.UnifiedQuerier) bool {
|
||||
_, p := authz.GetProviders()
|
||||
return len(p) == 0 ||
|
||||
licensing.Check(licensing.FeatureACLs) != nil ||
|
||||
cfg.SiteConfig().DisableAutoCodeHostSyncs
|
||||
}
|
||||
|
||||
var ValidateExternalServiceConfig = database.MakeValidateExternalServiceConfigFunc(
|
||||
[]database.GitHubValidatorFunc{github.ValidateAuthz},
|
||||
[]database.GitLabValidatorFunc{gitlab.ValidateAuthz},
|
||||
|
||||
@ -87,13 +87,12 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
cfg conf.Unified
|
||||
gitlabConnections []*schema.GitLabConnection
|
||||
bitbucketServerConnections []*schema.BitbucketServerConnection
|
||||
expAuthzAllowAccessByDefault bool
|
||||
expAuthzProviders func(*testing.T, []authz.Provider)
|
||||
expSeriousProblems []string
|
||||
description string
|
||||
cfg conf.Unified
|
||||
gitlabConnections []*schema.GitLabConnection
|
||||
bitbucketServerConnections []*schema.BitbucketServerConnection
|
||||
expAuthzProviders func(*testing.T, []authz.Provider)
|
||||
expSeriousProblems []string
|
||||
}{
|
||||
{
|
||||
description: "1 GitLab connection with authz enabled, 1 GitLab matching auth provider",
|
||||
@ -119,7 +118,6 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: providersEqual(
|
||||
gitlabAuthzProviderParams{
|
||||
OAuthOp: gitlab.OAuthProviderOp{
|
||||
@ -155,8 +153,7 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: false,
|
||||
expSeriousProblems: []string{"Did not find authentication provider matching \"https://gitlab.mine\". Check the [**site configuration**](/site-admin/configuration) to verify an entry in [`auth.providers`](https://sourcegraph.com/docs/admin/auth) exists for https://gitlab.mine."},
|
||||
expSeriousProblems: []string{"Did not find authentication provider matching \"https://gitlab.mine\". Check the [**site configuration**](/site-admin/configuration) to verify an entry in [`auth.providers`](https://sourcegraph.com/docs/admin/auth) exists for https://gitlab.mine."},
|
||||
},
|
||||
{
|
||||
description: "1 GitLab connection with authz enabled, no GitLab auth provider",
|
||||
@ -176,8 +173,7 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: false,
|
||||
expSeriousProblems: []string{"Did not find authentication provider matching \"https://gitlab.mine\". Check the [**site configuration**](/site-admin/configuration) to verify an entry in [`auth.providers`](https://sourcegraph.com/docs/admin/auth) exists for https://gitlab.mine."},
|
||||
expSeriousProblems: []string{"Did not find authentication provider matching \"https://gitlab.mine\". Check the [**site configuration**](/site-admin/configuration) to verify an entry in [`auth.providers`](https://sourcegraph.com/docs/admin/auth) exists for https://gitlab.mine."},
|
||||
},
|
||||
{
|
||||
description: "Two GitLab connections with authz enabled, two matching GitLab auth providers",
|
||||
@ -220,7 +216,6 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: providersEqual(
|
||||
gitlabAuthzProviderParams{
|
||||
OAuthOp: gitlab.OAuthProviderOp{
|
||||
@ -262,8 +257,7 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: nil,
|
||||
expAuthzProviders: nil,
|
||||
},
|
||||
{
|
||||
description: "external auth provider",
|
||||
@ -291,7 +285,6 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: providersEqual(
|
||||
gitlabAuthzProviderParams{
|
||||
SudoOp: gitlab.SudoProviderOp{
|
||||
@ -325,7 +318,6 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: providersEqual(
|
||||
gitlabAuthzProviderParams{
|
||||
SudoOp: gitlab.SudoProviderOp{
|
||||
@ -348,8 +340,7 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "secret-token",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: providersEqual(),
|
||||
expAuthzProviders: providersEqual(),
|
||||
},
|
||||
{
|
||||
description: "Bitbucket Server Oauth config error",
|
||||
@ -372,8 +363,7 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "secret-token",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: false,
|
||||
expSeriousProblems: []string{"authorization.oauth.signingKey: illegal base64 data at input byte 7"},
|
||||
expSeriousProblems: []string{"authorization.oauth.signingKey: illegal base64 data at input byte 7"},
|
||||
},
|
||||
{
|
||||
description: "Bitbucket Server exact username matching",
|
||||
@ -396,7 +386,6 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "secret-token",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: func(t *testing.T, have []authz.Provider) {
|
||||
if len(have) == 0 {
|
||||
t.Fatalf("no providers")
|
||||
@ -437,7 +426,6 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
Token: "asdf",
|
||||
},
|
||||
},
|
||||
expAuthzAllowAccessByDefault: true,
|
||||
expAuthzProviders: providersEqual(
|
||||
gitlabAuthzProviderParams{
|
||||
OAuthOp: gitlab.OAuthProviderOp{
|
||||
@ -487,12 +475,11 @@ func TestAuthzProvidersFromConfig(t *testing.T) {
|
||||
}
|
||||
return svcs, nil
|
||||
})
|
||||
allowAccessByDefault, authzProviders, seriousProblems, _, _ := ProvidersFromConfig(
|
||||
authzProviders, seriousProblems, _, _ := ProvidersFromConfig(
|
||||
context.Background(),
|
||||
staticConfig(test.cfg.SiteConfiguration),
|
||||
db,
|
||||
)
|
||||
assert.Equal(t, test.expAuthzAllowAccessByDefault, allowAccessByDefault)
|
||||
if test.expAuthzProviders != nil {
|
||||
test.expAuthzProviders(t, authzProviders)
|
||||
}
|
||||
@ -733,7 +720,7 @@ func TestAuthzProvidersEnabledACLsDisabled(t *testing.T) {
|
||||
return svcs, nil
|
||||
})
|
||||
|
||||
_, _, seriousProblems, _, invalidConnections := ProvidersFromConfig(
|
||||
_, seriousProblems, _, invalidConnections := ProvidersFromConfig(
|
||||
context.Background(),
|
||||
staticConfig(test.cfg.SiteConfiguration),
|
||||
db,
|
||||
@ -759,90 +746,6 @@ func mustURLParse(t *testing.T, u string) *url.URL {
|
||||
return parsed
|
||||
}
|
||||
|
||||
type mockProvider struct {
|
||||
codeHost *extsvc.CodeHost
|
||||
extAcct *extsvc.Account
|
||||
}
|
||||
|
||||
func (p *mockProvider) FetchAccount(context.Context, *types.User, []*extsvc.Account, []string) (mine *extsvc.Account, err error) {
|
||||
return p.extAcct, nil
|
||||
}
|
||||
|
||||
func (p *mockProvider) ServiceType() string { return p.codeHost.ServiceType }
|
||||
func (p *mockProvider) ServiceID() string { return p.codeHost.ServiceID }
|
||||
func (p *mockProvider) URN() string { return extsvc.URN(p.codeHost.ServiceType, 0) }
|
||||
|
||||
func (p *mockProvider) ValidateConnection(context.Context) error { return nil }
|
||||
|
||||
func (p *mockProvider) FetchUserPerms(context.Context, *extsvc.Account, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *mockProvider) FetchUserPermsByToken(context.Context, string, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *mockProvider) FetchRepoPerms(context.Context, *extsvc.Repository, authz.FetchPermsOptions) ([]extsvc.AccountID, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func mockExplicitPermissions(enabled bool) func() {
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: enabled,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
return func() { conf.Mock(nil) }
|
||||
}
|
||||
|
||||
func TestPermissionSyncingDisabled(t *testing.T) {
|
||||
authz.SetProviders(true, []authz.Provider{&mockProvider{}})
|
||||
cleanupLicense := licensing.MockCheckFeatureError("")
|
||||
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
cleanupLicense()
|
||||
})
|
||||
|
||||
t.Run("no authz providers", func(t *testing.T) {
|
||||
authz.SetProviders(true, nil)
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, []authz.Provider{&mockProvider{}})
|
||||
})
|
||||
|
||||
assert.True(t, PermissionSyncingDisabled(&conf.Unified{}))
|
||||
})
|
||||
|
||||
t.Run("permissions user mapping enabled", func(t *testing.T) {
|
||||
cleanup := mockExplicitPermissions(true)
|
||||
t.Cleanup(func() {
|
||||
cleanup()
|
||||
conf.Mock(nil)
|
||||
})
|
||||
|
||||
assert.False(t, PermissionSyncingDisabled(&conf.Unified{}))
|
||||
})
|
||||
|
||||
t.Run("license does not have acls feature", func(t *testing.T) {
|
||||
licensing.MockCheckFeatureError("failed")
|
||||
t.Cleanup(func() {
|
||||
licensing.MockCheckFeatureError("")
|
||||
})
|
||||
assert.True(t, PermissionSyncingDisabled(&conf.Unified{}))
|
||||
})
|
||||
|
||||
t.Run("Auto code host syncs disabled", func(t *testing.T) {
|
||||
assert.True(t, PermissionSyncingDisabled(&conf.Unified{SiteConfiguration: schema.SiteConfiguration{DisableAutoCodeHostSyncs: true}}))
|
||||
})
|
||||
|
||||
t.Run("Auto code host syncs enabled", func(t *testing.T) {
|
||||
assert.False(t, PermissionSyncingDisabled(&conf.Unified{SiteConfiguration: schema.SiteConfiguration{DisableAutoCodeHostSyncs: false}}))
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateExternalServiceConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Cleanup(licensing.TestingSkipFeatureChecks())
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package bitbucketcloud
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/licensing"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
@ -23,24 +21,8 @@ import (
|
||||
// This constructor does not and should not directly check connectivity to external services - if
|
||||
// desired, callers should use `(*Provider).ValidateConnection` directly to get warnings related
|
||||
// to connection issues.
|
||||
func NewAuthzProviders(db database.DB, conns []*types.BitbucketCloudConnection, authProviders []schema.AuthProviders) *atypes.ProviderInitResult {
|
||||
func NewAuthzProviders(db database.DB, conns []*types.BitbucketCloudConnection) *atypes.ProviderInitResult {
|
||||
initResults := &atypes.ProviderInitResult{}
|
||||
bbcloudAuthProviders := make(map[string]*schema.BitbucketCloudAuthProvider)
|
||||
for _, p := range authProviders {
|
||||
if p.Bitbucketcloud != nil {
|
||||
var id string
|
||||
bbURL, err := url.Parse(p.Bitbucketcloud.GetURL())
|
||||
if err != nil {
|
||||
// error reporting for this should happen elsewhere, for now just use what is given
|
||||
id = p.Bitbucketcloud.GetURL()
|
||||
} else {
|
||||
// use codehost normalized URL as ID
|
||||
ch := extsvc.NewCodeHost(bbURL, p.Bitbucketcloud.Type)
|
||||
id = ch.ServiceID
|
||||
}
|
||||
bbcloudAuthProviders[id] = p.Bitbucketcloud
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range conns {
|
||||
p, err := newAuthzProvider(db, c)
|
||||
|
||||
@ -23,7 +23,6 @@ func TestNewAuthzProviders(t *testing.T) {
|
||||
Url: schema.DefaultBitbucketCloudURL,
|
||||
},
|
||||
}},
|
||||
[]schema.AuthProviders{},
|
||||
)
|
||||
|
||||
assertion := assert.New(t)
|
||||
@ -34,75 +33,47 @@ func TestNewAuthzProviders(t *testing.T) {
|
||||
assertion.Len(initResults.InvalidConnections, 0, "unexpected invalidConnections: %+v", initResults.InvalidConnections)
|
||||
})
|
||||
|
||||
t.Run("no matching auth provider", func(t *testing.T) {
|
||||
t.Run("default case", func(t *testing.T) {
|
||||
t.Cleanup(licensing.TestingSkipFeatureChecks())
|
||||
initResults := NewAuthzProviders(
|
||||
db,
|
||||
[]*types.BitbucketCloudConnection{
|
||||
{
|
||||
BitbucketCloudConnection: &schema.BitbucketCloudConnection{
|
||||
Url: "https://bitbucket.org/my-org", // incorrect
|
||||
Url: schema.DefaultBitbucketCloudURL,
|
||||
Authorization: &schema.BitbucketCloudAuthorization{},
|
||||
},
|
||||
},
|
||||
},
|
||||
[]schema.AuthProviders{{Bitbucketcloud: &schema.BitbucketCloudAuthProvider{}}},
|
||||
)
|
||||
|
||||
require.Len(t, initResults.Providers, 1, "expect exactly one provider")
|
||||
assert.NotNil(t, initResults.Providers[0])
|
||||
|
||||
assert.Empty(t, initResults.Problems)
|
||||
assert.Empty(t, initResults.Warnings)
|
||||
assert.Empty(t, initResults.InvalidConnections)
|
||||
|
||||
require.Len(t, initResults.Warnings, 0, "expect no warnings")
|
||||
})
|
||||
|
||||
t.Run("matching auth provider found", func(t *testing.T) {
|
||||
t.Run("default case", func(t *testing.T) {
|
||||
t.Cleanup(licensing.TestingSkipFeatureChecks())
|
||||
initResults := NewAuthzProviders(
|
||||
db,
|
||||
[]*types.BitbucketCloudConnection{
|
||||
{
|
||||
BitbucketCloudConnection: &schema.BitbucketCloudConnection{
|
||||
Url: schema.DefaultBitbucketCloudURL,
|
||||
Authorization: &schema.BitbucketCloudAuthorization{},
|
||||
},
|
||||
t.Run("license does not have ACLs feature", func(t *testing.T) {
|
||||
t.Cleanup(licensing.MockCheckFeatureError("failed"))
|
||||
initResults := NewAuthzProviders(
|
||||
db,
|
||||
[]*types.BitbucketCloudConnection{
|
||||
{
|
||||
BitbucketCloudConnection: &schema.BitbucketCloudConnection{
|
||||
Url: schema.DefaultBitbucketCloudURL,
|
||||
Authorization: &schema.BitbucketCloudAuthorization{},
|
||||
},
|
||||
},
|
||||
[]schema.AuthProviders{{Bitbucketcloud: &schema.BitbucketCloudAuthProvider{}}},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
require.Len(t, initResults.Providers, 1, "expect exactly one provider")
|
||||
assert.NotNil(t, initResults.Providers[0])
|
||||
|
||||
assert.Empty(t, initResults.Problems)
|
||||
assert.Empty(t, initResults.Warnings)
|
||||
assert.Empty(t, initResults.InvalidConnections)
|
||||
})
|
||||
|
||||
t.Run("license does not have ACLs feature", func(t *testing.T) {
|
||||
t.Cleanup(licensing.MockCheckFeatureError("failed"))
|
||||
initResults := NewAuthzProviders(
|
||||
db,
|
||||
[]*types.BitbucketCloudConnection{
|
||||
{
|
||||
BitbucketCloudConnection: &schema.BitbucketCloudConnection{
|
||||
Url: schema.DefaultBitbucketCloudURL,
|
||||
Authorization: &schema.BitbucketCloudAuthorization{},
|
||||
},
|
||||
},
|
||||
},
|
||||
[]schema.AuthProviders{{Bitbucketcloud: &schema.BitbucketCloudAuthProvider{}}},
|
||||
)
|
||||
|
||||
expectedError := []string{"failed"}
|
||||
expInvalidConnectionErr := []string{"bitbucketCloud"}
|
||||
assert.Equal(t, expectedError, initResults.Problems)
|
||||
assert.Equal(t, expInvalidConnectionErr, initResults.InvalidConnections)
|
||||
assert.Empty(t, initResults.Providers)
|
||||
assert.Empty(t, initResults.Warnings)
|
||||
})
|
||||
expectedError := []string{"failed"}
|
||||
expInvalidConnectionErr := []string{"bitbucketCloud"}
|
||||
assert.Equal(t, expectedError, initResults.Problems)
|
||||
assert.Equal(t, expInvalidConnectionErr, initResults.InvalidConnections)
|
||||
assert.Empty(t, initResults.Providers)
|
||||
assert.Empty(t, initResults.Warnings)
|
||||
})
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@ go_library(
|
||||
"//internal/licensing",
|
||||
"//internal/types",
|
||||
"//lib/errors",
|
||||
"//schema",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -1,43 +1,28 @@
|
||||
package gerrit
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
atypes "github.com/sourcegraph/sourcegraph/internal/authz/types"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc"
|
||||
"github.com/sourcegraph/sourcegraph/internal/licensing"
|
||||
"github.com/sourcegraph/sourcegraph/internal/types"
|
||||
"github.com/sourcegraph/sourcegraph/schema"
|
||||
)
|
||||
|
||||
// NewAuthzProviders returns the set of Gerrit authz providers derived from the connections.
|
||||
func NewAuthzProviders(conns []*types.GerritConnection, authProviders []schema.AuthProviders) *atypes.ProviderInitResult {
|
||||
func NewAuthzProviders(conns []*types.GerritConnection) *atypes.ProviderInitResult {
|
||||
initResults := &atypes.ProviderInitResult{}
|
||||
gerritAuthProviders := make(map[string]*schema.GerritAuthProvider)
|
||||
for _, p := range authProviders {
|
||||
if p.Gerrit == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
gerritURL, err := url.Parse(p.Gerrit.Url)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Use normalised base URL as ID.
|
||||
gerritAuthProviders[extsvc.NormalizeBaseURL(gerritURL).String()] = p.Gerrit
|
||||
}
|
||||
|
||||
for _, c := range conns {
|
||||
if c.Authorization == nil {
|
||||
// No authorization required
|
||||
continue
|
||||
}
|
||||
|
||||
if err := licensing.Check(licensing.FeatureACLs); err != nil {
|
||||
initResults.InvalidConnections = append(initResults.InvalidConnections, extsvc.TypeGerrit)
|
||||
initResults.Problems = append(initResults.Problems, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
p, err := NewProvider(c)
|
||||
if err != nil {
|
||||
initResults.InvalidConnections = append(initResults.InvalidConnections, extsvc.TypeGerrit)
|
||||
|
||||
@ -26,13 +26,13 @@ import (
|
||||
// to connection issues.
|
||||
func NewAuthzProviders(
|
||||
db database.DB,
|
||||
cfg schema.SiteConfiguration,
|
||||
conns []*types.GitLabConnection,
|
||||
ap []schema.AuthProviders,
|
||||
) *atypes.ProviderInitResult {
|
||||
initResults := &atypes.ProviderInitResult{}
|
||||
// Authorization (i.e., permissions) providers
|
||||
for _, c := range conns {
|
||||
p, err := newAuthzProvider(db, c, cfg.AuthProviders)
|
||||
p, err := newAuthzProvider(db, c, ap)
|
||||
if err != nil {
|
||||
initResults.InvalidConnections = append(initResults.InvalidConnections, extsvc.TypeGitLab)
|
||||
initResults.Problems = append(initResults.Problems, err.Error())
|
||||
|
||||
@ -7,12 +7,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// allowAccessByDefault, if set to true, grants all users access to repositories that are
|
||||
// not matched by any authz provider. The default value is true. It is only set to false in
|
||||
// error modes (when the configuration is in a state where interpreting it literally could lead
|
||||
// to leakage of private repositories).
|
||||
allowAccessByDefault = true
|
||||
|
||||
// authzProvidersReady and authzProvidersReadyOnce together indicate when
|
||||
// GetProviders should no longer block. It should block until SetProviders
|
||||
// is called at least once.
|
||||
@ -27,12 +21,11 @@ var (
|
||||
)
|
||||
|
||||
// SetProviders sets the current authz parameters. It is concurrency-safe.
|
||||
func SetProviders(authzAllowByDefault bool, z []Provider) {
|
||||
func SetProviders(z []Provider) {
|
||||
authzMu.Lock()
|
||||
defer authzMu.Unlock()
|
||||
|
||||
authzProviders = z
|
||||
allowAccessByDefault = authzAllowByDefault
|
||||
|
||||
authzProvidersReadyOnce.Do(func() {
|
||||
close(authzProvidersReady)
|
||||
@ -42,7 +35,7 @@ func SetProviders(authzAllowByDefault bool, z []Provider) {
|
||||
// GetProviders returns the current authz parameters. It is concurrency-safe.
|
||||
//
|
||||
// It blocks until SetProviders has been called at least once.
|
||||
func GetProviders() (authzAllowByDefault bool, providers []Provider) {
|
||||
func GetProviders() (providers []Provider) {
|
||||
if !testutil.IsTest {
|
||||
<-authzProvidersReady
|
||||
}
|
||||
@ -50,9 +43,9 @@ func GetProviders() (authzAllowByDefault bool, providers []Provider) {
|
||||
defer authzMu.Unlock()
|
||||
|
||||
if authzProviders == nil {
|
||||
return allowAccessByDefault, nil
|
||||
return nil
|
||||
}
|
||||
providers = make([]Provider, len(authzProviders))
|
||||
copy(providers, authzProviders)
|
||||
return allowAccessByDefault, providers
|
||||
return providers
|
||||
}
|
||||
|
||||
@ -873,7 +873,7 @@ func TestExecutor_ExecutePlan_PublishedChangesetDuplicateBranch(t *testing.T) {
|
||||
}
|
||||
|
||||
logger := logtest.Scoped(t)
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
|
||||
bstore := store.New(db, observation.TestContextTB(t), et.TestKey{})
|
||||
@ -916,7 +916,7 @@ func TestExecutor_ExecutePlan_PublishedChangesetDuplicateBranch(t *testing.T) {
|
||||
|
||||
func TestExecutor_ExecutePlan_AvoidLoadingChangesetSource(t *testing.T) {
|
||||
logger := logtest.Scoped(t)
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
bstore := store.New(db, observation.TestContextTB(t), et.TestKey{})
|
||||
repo, _ := bt.CreateTestRepo(t, ctx, db)
|
||||
@ -1178,7 +1178,7 @@ func TestExecutor_UserCredentialsForGitserver(t *testing.T) {
|
||||
})
|
||||
|
||||
_, err := executePlan(
|
||||
actor.WithActor(ctx, actor.FromUser(tt.user.ID)),
|
||||
actor.WithInternalActor(ctx),
|
||||
logtest.Scoped(t),
|
||||
gitserverClient,
|
||||
sourcer,
|
||||
|
||||
@ -4,11 +4,12 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/sourcegraph/sourcegraph/internal/batches/sources"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/batches/sources"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/graph-gophers/graphql-go/relay"
|
||||
@ -56,6 +57,9 @@ func TestServicePermissionLevels(t *testing.T) {
|
||||
nonOrgMember := bt.CreateTestUser(t, db, false)
|
||||
|
||||
repo, _ := bt.CreateTestRepo(t, ctx, db)
|
||||
bt.MockRepoPermissions(t, db, user.ID, repo.ID)
|
||||
bt.MockRepoPermissions(t, db, otherUser.ID, repo.ID)
|
||||
bt.MockRepoPermissions(t, db, nonOrgMember.ID, repo.ID)
|
||||
|
||||
org := bt.CreateTestOrg(t, db, "test-org-1", admin.ID, user.ID, otherUser.ID)
|
||||
|
||||
@ -317,6 +321,8 @@ func TestService(t *testing.T) {
|
||||
svc.sourcer = sourcer
|
||||
|
||||
t.Run("CheckViewerCanAdminister", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
org := bt.CreateTestOrg(t, db, "test-org-1", user.ID, user2.ID)
|
||||
|
||||
spec := testBatchSpec(user.ID)
|
||||
@ -424,6 +430,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("DeleteBatchChange", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
spec := testBatchSpec(admin.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -444,6 +452,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("CloseBatchChange", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
createBatchChange := func(t *testing.T) *btypes.BatchChange {
|
||||
t.Helper()
|
||||
|
||||
@ -516,6 +526,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("EnqueueChangesetSync", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
spec := testBatchSpec(user.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -559,6 +571,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("ReenqueueChangeset", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
spec := testBatchSpec(user.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -616,6 +630,8 @@ func TestService(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
opts := CreateBatchSpecOpts{
|
||||
NamespaceUserID: admin.ID,
|
||||
RawSpec: bt.TestRawBatchSpec,
|
||||
@ -657,6 +673,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("success with YAML raw spec", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
opts := CreateBatchSpecOpts{
|
||||
NamespaceUserID: admin.ID,
|
||||
RawSpec: bt.TestRawBatchSpecYAML,
|
||||
@ -696,6 +714,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid changesetspec id", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
containsInvalidID := []string{changesetSpecRandIDs[0], "foobar"}
|
||||
opts := CreateBatchSpecOpts{
|
||||
NamespaceUserID: admin.ID,
|
||||
@ -709,6 +729,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("namespace user is not admin and not creator", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
opts := CreateBatchSpecOpts{
|
||||
NamespaceUserID: admin.ID,
|
||||
RawSpec: bt.TestRawBatchSpecYAML,
|
||||
@ -729,6 +751,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("missing access to namespace org", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
orgID := bt.CreateTestOrg(t, db, "test-org").ID
|
||||
|
||||
opts := CreateBatchSpecOpts{
|
||||
@ -754,6 +778,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("no side-effects if no changeset spec IDs are given", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
// We already have ChangesetSpecs in the database. Here we
|
||||
// want to make sure that the new BatchSpec is created,
|
||||
// without accidently attaching the existing ChangesetSpecs.
|
||||
@ -780,6 +806,8 @@ func TestService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("CreateChangesetSpec", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
repo := rs[0]
|
||||
rawSpec := bt.NewRawChangesetSpecGitBranch(relay.MarshalID("Repository", repo.ID), "d34db33f")
|
||||
|
||||
@ -865,6 +893,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("CreateChangesetSpecs", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
rawSpec := bt.NewRawChangesetSpecGitBranch(relay.MarshalID("Repository", rs[0].ID), "d34db33f")
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
@ -949,6 +979,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("MoveBatchChange", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
createBatchChange := func(t *testing.T, name string, authorID, userID, orgID int32) *btypes.BatchChange {
|
||||
t.Helper()
|
||||
|
||||
@ -1061,6 +1093,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("GetBatchChangeMatchingBatchSpec", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
batchSpec := bt.CreateBatchSpec(t, ctx, s, "matching-batch-spec", admin.ID, 0)
|
||||
|
||||
haveBatchChange, err := svc.GetBatchChangeMatchingBatchSpec(ctx, batchSpec)
|
||||
@ -1116,6 +1150,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("GetNewestBatchSpec", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
older := bt.CreateBatchSpec(t, ctx, s, "superseding", user.ID, 0)
|
||||
newer := bt.CreateBatchSpec(t, ctx, s, "superseding", user.ID, 0)
|
||||
|
||||
@ -1148,6 +1184,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("FetchUsernameForBitbucketServerToken", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
fakeSource := &stesting.FakeChangesetSource{Username: "my-bbs-username"}
|
||||
sourcer := stesting.NewFakeSourcer(nil, fakeSource)
|
||||
|
||||
@ -1177,6 +1215,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("ValidateAuthenticator", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
fakeSource.AuthenticatorIsValid = true
|
||||
fakeSource.ValidateAuthenticatorCalled = false
|
||||
@ -1218,6 +1258,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("CreateChangesetJobs", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
spec := testBatchSpec(admin.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -1474,6 +1516,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("ExecuteBatchSpec", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
adminCtx := actor.WithActor(ctx, actor.FromUser(admin.ID))
|
||||
t.Run("success", func(t *testing.T) {
|
||||
spec := testBatchSpec(admin.ID)
|
||||
@ -1722,6 +1766,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("CancelBatchSpec", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
spec := testBatchSpec(admin.ID)
|
||||
spec.CreatedFromRaw = true
|
||||
@ -1829,6 +1875,8 @@ index e5af166..d44c3fc 100644
|
||||
})
|
||||
|
||||
t.Run("ReplaceBatchSpecInput", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
createBatchSpecWithWorkspaces := func(t *testing.T) *btypes.BatchSpec {
|
||||
t.Helper()
|
||||
spec := testBatchSpec(admin.ID)
|
||||
@ -2045,6 +2093,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("CreateBatchSpecFromRaw", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
t.Run("batch change isn't owned by non-admin user", func(t *testing.T) {
|
||||
spec := testBatchSpec(user.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
@ -2175,6 +2225,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("UpsertBatchSpecInput", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
adminCtx := actor.WithActor(ctx, actor.FromUser(admin.ID))
|
||||
t.Run("new spec", func(t *testing.T) {
|
||||
newSpec, err := svc.UpsertBatchSpecInput(adminCtx, UpsertBatchSpecInputOpts{
|
||||
@ -2241,6 +2293,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("ValidateChangesetSpecs", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
batchSpec := bt.CreateBatchSpec(t, ctx, s, "matching-batch-spec", admin.ID, 0)
|
||||
conflictingRef := "refs/heads/conflicting-head-ref"
|
||||
for _, opts := range []bt.TestSpecOpts{
|
||||
@ -2268,6 +2322,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("ComputeBatchSpecState", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
spec := testBatchSpec(admin.ID)
|
||||
spec.CreatedFromRaw = true
|
||||
@ -2318,6 +2374,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("RetryBatchSpecWorkspaces", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
failureMessage := "this failed"
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
@ -2521,6 +2579,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("RetryBatchSpecExecution", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
failureMessage := "this failed"
|
||||
|
||||
createSpec := func(t *testing.T) *btypes.BatchSpec {
|
||||
@ -2817,6 +2877,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("GetAvailableBulkOperations", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
spec := testBatchSpec(admin.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -3138,6 +3200,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("UpsertEmptyBatchChange", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
t.Run("creates new batch change if it is non-existent", func(t *testing.T) {
|
||||
name := "random-bc-name"
|
||||
|
||||
@ -3210,6 +3274,8 @@ changesetTemplate:
|
||||
})
|
||||
|
||||
t.Run("GetChangesetsByIDs", func(t *testing.T) {
|
||||
bt.MockRepoPermissions(t, db, user.ID, rs[0].ID, rs[1].ID, rs[2].ID, rs[3].ID)
|
||||
|
||||
spec := testBatchSpec(admin.ID)
|
||||
if err := s.CreateBatchSpec(ctx, spec); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@ -259,7 +259,7 @@ func testStoreBatchChanges(t *testing.T, ctx context.Context, s *Store, clock bt
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
opts := CountBatchChangesOpts{RepoID: tc.repoID}
|
||||
|
||||
count, err := s.CountBatchChanges(ctx, opts)
|
||||
count, err := s.CountBatchChanges(actor.WithInternalActor(ctx), opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -430,7 +430,7 @@ func testStoreBatchChanges(t *testing.T, ctx context.Context, s *Store, clock bt
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
opts := ListBatchChangesOpts{RepoID: tc.repoID}
|
||||
|
||||
ts, next, err := s.ListBatchChanges(ctx, opts)
|
||||
ts, next, err := s.ListBatchChanges(actor.WithInternalActor(ctx), opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -800,6 +800,8 @@ func testStoreBatchChanges(t *testing.T, ctx context.Context, s *Store, clock bt
|
||||
|
||||
batchChangeID := bcs[0].ID
|
||||
var testDiffStatCount int32 = 10
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), userID, repo.ID)
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), otherUserID, repo.ID)
|
||||
bt.CreateChangeset(t, ctx, s, bt.TestChangesetOpts{
|
||||
Repo: repo.ID,
|
||||
BatchChanges: []btypes.BatchChangeAssoc{{BatchChangeID: batchChangeID}},
|
||||
@ -825,7 +827,7 @@ func testStoreBatchChanges(t *testing.T, ctx context.Context, s *Store, clock bt
|
||||
|
||||
// Now give repo access only to otherUserID, and check that
|
||||
// userID cannot see it in the diff stat anymore.
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), otherUserID, repo.ID)
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), userID)
|
||||
{
|
||||
want := &godiff.Stat{
|
||||
Added: 0,
|
||||
@ -856,6 +858,7 @@ func testStoreBatchChanges(t *testing.T, ctx context.Context, s *Store, clock bt
|
||||
if err := repoStore.Create(ctx, repo1, repo2, repo3); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), userID, repo1.ID, repo2.ID, repo3.ID)
|
||||
|
||||
batchChangeID := bcs[0].ID
|
||||
var testDiffStatCount1 int32 = 10
|
||||
@ -930,6 +933,7 @@ func testStoreBatchChanges(t *testing.T, ctx context.Context, s *Store, clock bt
|
||||
|
||||
// Now give repo access only to otherUserID, and check that
|
||||
// userID cannot see it in the diff stat anymore.
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), userID)
|
||||
bt.MockRepoPermissions(t, s.DatabaseDB(), otherUserID, repo1.ID)
|
||||
{
|
||||
want := &godiff.Stat{
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/batches/search"
|
||||
bt "github.com/sourcegraph/sourcegraph/internal/batches/testing"
|
||||
@ -1439,7 +1440,7 @@ func testStoreChangesets(t *testing.T, ctx context.Context, s *Store, clock bt.C
|
||||
bt.CreateChangeset(t, ctx, s, opts9)
|
||||
wantStats.Draft += 1
|
||||
|
||||
haveStats, err := s.GetRepoChangesetsStats(ctx, r.ID)
|
||||
haveStats, err := s.GetRepoChangesetsStats(actor.WithInternalActor(ctx), r.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -32,9 +32,4 @@ func MockRepoPermissions(t *testing.T, db database.DB, userID int32, repoIDs ...
|
||||
UserID: userID,
|
||||
}, maps.Keys(repoIDMap), authz.SourceUserSync)
|
||||
require.NoError(t, err)
|
||||
|
||||
authz.SetProviders(false, nil)
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
})
|
||||
}
|
||||
|
||||
@ -67,5 +67,6 @@ go_test(
|
||||
"@com_github_keegancsmith_sqlf//:sqlf",
|
||||
"@com_github_lib_pq//:pq",
|
||||
"@com_github_sourcegraph_log//logtest",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
)
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
uploadsshared "github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
@ -234,9 +235,11 @@ func TestInsertIndexWithActor(t *testing.T) {
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
|
||||
insertRepo(t, db, 50, "")
|
||||
u, err := db.Users().Create(context.Background(), database.NewUser{Username: "alice"})
|
||||
require.NoError(t, err)
|
||||
|
||||
for i, ctx := range []context.Context{
|
||||
actor.WithActor(context.Background(), actor.FromMockUser(100)),
|
||||
actor.WithActor(context.Background(), actor.FromUser(u.ID)),
|
||||
actor.WithInternalActor(context.Background()),
|
||||
context.Background(),
|
||||
} {
|
||||
|
||||
@ -45,13 +45,12 @@ go_test(
|
||||
"requires-network",
|
||||
],
|
||||
deps = [
|
||||
"//internal/actor",
|
||||
"//internal/codeintel/policies/shared",
|
||||
"//internal/conf",
|
||||
"//internal/database",
|
||||
"//internal/database/basestore",
|
||||
"//internal/database/dbtest",
|
||||
"//internal/observation",
|
||||
"//schema",
|
||||
"@com_github_google_go_cmp//cmp",
|
||||
"@com_github_keegancsmith_sqlf//:sqlf",
|
||||
"@com_github_sourcegraph_log//logtest",
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
policiesshared "github.com/sourcegraph/sourcegraph/internal/codeintel/policies/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
@ -239,6 +240,7 @@ func TestDeleteConfigurationPolicyByID(t *testing.T) {
|
||||
|
||||
func TestDeleteConfigurationProtectedPolicy(t *testing.T) {
|
||||
logger := logtest.Scoped(t)
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := testStoreWithoutConfigurationPolicies(t, db)
|
||||
|
||||
@ -260,7 +262,7 @@ func TestDeleteConfigurationProtectedPolicy(t *testing.T) {
|
||||
IndexIntermediateCommits: true,
|
||||
}
|
||||
|
||||
hydratedConfigurationPolicy, err := store.CreateConfigurationPolicy(context.Background(), configurationPolicy)
|
||||
hydratedConfigurationPolicy, err := store.CreateConfigurationPolicy(ctx, configurationPolicy)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error creating configuration policy: %s", err)
|
||||
}
|
||||
@ -270,15 +272,15 @@ func TestDeleteConfigurationProtectedPolicy(t *testing.T) {
|
||||
}
|
||||
|
||||
// Mark configuration policy as protected (no other way to do so outside of migrations)
|
||||
if _, err := db.ExecContext(context.Background(), "UPDATE lsif_configuration_policies SET protected = true"); err != nil {
|
||||
if _, err := db.ExecContext(ctx, "UPDATE lsif_configuration_policies SET protected = true"); err != nil {
|
||||
t.Fatalf("unexpected error marking configuration policy as protected: %s", err)
|
||||
}
|
||||
|
||||
if err := store.DeleteConfigurationPolicyByID(context.Background(), hydratedConfigurationPolicy.ID); err == nil {
|
||||
if err := store.DeleteConfigurationPolicyByID(ctx, hydratedConfigurationPolicy.ID); err == nil {
|
||||
t.Fatalf("expected error deleting configuration policy: %s", err)
|
||||
}
|
||||
|
||||
_, ok, err := store.GetConfigurationPolicyByID(context.Background(), hydratedConfigurationPolicy.ID)
|
||||
_, ok, err := store.GetConfigurationPolicyByID(ctx, hydratedConfigurationPolicy.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error fetching configuration policy: %s", err)
|
||||
}
|
||||
|
||||
@ -9,16 +9,15 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
policiesshared "github.com/sourcegraph/sourcegraph/internal/codeintel/policies/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
"github.com/sourcegraph/sourcegraph/internal/observation"
|
||||
"github.com/sourcegraph/sourcegraph/schema"
|
||||
)
|
||||
|
||||
func TestRepoIDsByGlobPatterns(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
@ -72,20 +71,8 @@ func TestRepoIDsByGlobPatterns(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Turning on explicit permissions forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty and repos are private.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
repoIDs, _, err := store.GetRepoIDsByGlobPatterns(ctx, []string{"*"}, 10, 0)
|
||||
// We use an actor-less context here. Without an actor, no repositories should be visible.
|
||||
repoIDs, _, err := store.GetRepoIDsByGlobPatterns(context.Background(), []string{"*"}, 10, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -170,6 +170,7 @@ SELECT
|
||||
u.should_reindex,
|
||||
u.enqueuer_user_id
|
||||
FROM syntactic_scip_indexing_jobs_with_repository_name u
|
||||
JOIN repo ON repo.id = u.repository_id AND repo.deleted_at IS NULL AND repo.blocked IS NULL
|
||||
WHERE u.id IN (%s) and %s
|
||||
ORDER BY u.id
|
||||
`
|
||||
|
||||
@ -71,6 +71,7 @@ go_test(
|
||||
"requires-network",
|
||||
],
|
||||
deps = [
|
||||
"//internal/actor",
|
||||
"//internal/api",
|
||||
"//internal/byteutils",
|
||||
"//internal/codeintel/core",
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
logger "github.com/sourcegraph/log"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
uploadsshared "github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
@ -67,7 +68,7 @@ func TestDeleteUploadsStuckUploading(t *testing.T) {
|
||||
shared.Upload{ID: 5, Commit: makeCommit(1115), UploadedAt: t5, State: "uploading"}, // old
|
||||
)
|
||||
|
||||
_, count, err := store.DeleteUploadsStuckUploading(context.Background(), t1.Add(time.Minute*3))
|
||||
_, count, err := store.DeleteUploadsStuckUploading(actor.WithInternalActor(context.Background()), t1.Add(time.Minute*3))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error deleting uploads stuck uploading: %s", err)
|
||||
}
|
||||
@ -75,7 +76,7 @@ func TestDeleteUploadsStuckUploading(t *testing.T) {
|
||||
t.Errorf("unexpected count. want=%d have=%d", 2, count)
|
||||
}
|
||||
|
||||
uploads, totalCount, err := store.GetUploads(context.Background(), shared.GetUploadsOptions{Limit: 5})
|
||||
uploads, totalCount, err := store.GetUploads(actor.WithInternalActor(context.Background()), shared.GetUploadsOptions{Limit: 5})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting uploads: %s", err)
|
||||
}
|
||||
@ -121,12 +122,12 @@ func TestDeleteUploadsWithoutRepository(t *testing.T) {
|
||||
for repositoryID, deletedAt := range deletions {
|
||||
query := sqlf.Sprintf(`UPDATE repo SET deleted_at=%s WHERE id=%s`, deletedAt, repositoryID)
|
||||
|
||||
if _, err := db.QueryContext(context.Background(), query.Query(sqlf.PostgresBindVar), query.Args()...); err != nil {
|
||||
if _, err := db.QueryContext(actor.WithInternalActor(context.Background()), query.Query(sqlf.PostgresBindVar), query.Args()...); err != nil {
|
||||
t.Fatalf("Failed to update repository: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
_, count, err := store.DeleteUploadsWithoutRepository(context.Background(), t1)
|
||||
_, count, err := store.DeleteUploadsWithoutRepository(actor.WithInternalActor(context.Background()), t1)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error deleting uploads: %s", err)
|
||||
}
|
||||
@ -163,7 +164,7 @@ func TestDeleteOldAuditLogs(t *testing.T) {
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
|
||||
// Sanity check for syntax only
|
||||
if _, _, err := store.DeleteOldAuditLogs(context.Background(), time.Second, time.Now()); err != nil {
|
||||
if _, _, err := store.DeleteOldAuditLogs(actor.WithInternalActor(context.Background()), time.Second, time.Now()); err != nil {
|
||||
t.Fatalf("unexpected error deleting old audit logs: %s", err)
|
||||
}
|
||||
}
|
||||
@ -452,29 +453,29 @@ func TestGetQueuedUploadRank(t *testing.T) {
|
||||
shared.Upload{ID: 7, UploadedAt: t1, State: "queued", ProcessAfter: &t7},
|
||||
)
|
||||
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 1); upload.Rank == nil || *upload.Rank != 1 {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); upload.Rank == nil || *upload.Rank != 1 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 1, printableRank{upload.Rank})
|
||||
}
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 2); upload.Rank == nil || *upload.Rank != 6 {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 2); upload.Rank == nil || *upload.Rank != 6 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 5, printableRank{upload.Rank})
|
||||
}
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 3); upload.Rank == nil || *upload.Rank != 3 {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 3); upload.Rank == nil || *upload.Rank != 3 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 3, printableRank{upload.Rank})
|
||||
}
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 4); upload.Rank == nil || *upload.Rank != 2 {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 4); upload.Rank == nil || *upload.Rank != 2 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 2, printableRank{upload.Rank})
|
||||
}
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 5); upload.Rank == nil || *upload.Rank != 4 {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 5); upload.Rank == nil || *upload.Rank != 4 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 4, printableRank{upload.Rank})
|
||||
}
|
||||
|
||||
// Only considers queued uploads to determine rank
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 6); upload.Rank != nil {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 6); upload.Rank != nil {
|
||||
t.Errorf("unexpected rank. want=%s have=%s", "nil", printableRank{upload.Rank})
|
||||
}
|
||||
|
||||
// Process after takes priority over upload time
|
||||
if upload, _, _ := store.GetUploadByID(context.Background(), 7); upload.Rank == nil || *upload.Rank != 5 {
|
||||
if upload, _, _ := store.GetUploadByID(actor.WithInternalActor(context.Background()), 7); upload.Rank == nil || *upload.Rank != 5 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 4, printableRank{upload.Rank})
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,18 +11,17 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
uploadsshared "github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
"github.com/sourcegraph/sourcegraph/internal/executor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/observation"
|
||||
"github.com/sourcegraph/sourcegraph/schema"
|
||||
)
|
||||
|
||||
func TestGetIndexes(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
@ -132,20 +131,8 @@ func TestGetIndexes(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Enable permissions user mapping forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
indexes, totalCount, err := store.GetAutoIndexJobs(ctx,
|
||||
// Use an actorless context to test permissions.
|
||||
indexes, totalCount, err := store.GetAutoIndexJobs(context.Background(),
|
||||
shared.GetAutoIndexJobsOptions{
|
||||
Limit: 1,
|
||||
},
|
||||
@ -160,7 +147,7 @@ func TestGetIndexes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAutoIndexJobByID(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
@ -216,20 +203,8 @@ func TestGetAutoIndexJobByID(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Enable permissions user mapping forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
_, exists, err := store.GetAutoIndexJobByID(ctx, 1)
|
||||
// Use an actorless context to test permissions.
|
||||
_, exists, err := store.GetAutoIndexJobByID(context.Background(), 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -262,35 +237,35 @@ func TestGetQueuedIndexRank(t *testing.T) {
|
||||
uploadsshared.AutoIndexJob{ID: 7, QueuedAt: t1, State: "queued", ProcessAfter: &t7},
|
||||
)
|
||||
|
||||
if index, _, _ := store.GetAutoIndexJobByID(context.Background(), 1); index.Rank == nil || *index.Rank != 1 {
|
||||
if index, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 1); index.Rank == nil || *index.Rank != 1 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 1, printableRank{index.Rank})
|
||||
}
|
||||
if index, _, _ := store.GetAutoIndexJobByID(context.Background(), 2); index.Rank == nil || *index.Rank != 6 {
|
||||
if index, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 2); index.Rank == nil || *index.Rank != 6 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 5, printableRank{index.Rank})
|
||||
}
|
||||
if index, _, _ := store.GetAutoIndexJobByID(context.Background(), 3); index.Rank == nil || *index.Rank != 3 {
|
||||
if index, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 3); index.Rank == nil || *index.Rank != 3 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 3, printableRank{index.Rank})
|
||||
}
|
||||
if index, _, _ := store.GetAutoIndexJobByID(context.Background(), 4); index.Rank == nil || *index.Rank != 2 {
|
||||
if index, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 4); index.Rank == nil || *index.Rank != 2 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 2, printableRank{index.Rank})
|
||||
}
|
||||
if index, _, _ := store.GetAutoIndexJobByID(context.Background(), 5); index.Rank == nil || *index.Rank != 4 {
|
||||
if index, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 5); index.Rank == nil || *index.Rank != 4 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 4, printableRank{index.Rank})
|
||||
}
|
||||
|
||||
// Only considers queued indexes to determine rank
|
||||
if index, _, _ := store.GetAutoIndexJobByID(context.Background(), 6); index.Rank != nil {
|
||||
if index, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 6); index.Rank != nil {
|
||||
t.Errorf("unexpected rank. want=%s have=%s", "nil", printableRank{index.Rank})
|
||||
}
|
||||
|
||||
// Process after takes priority over upload time
|
||||
if upload, _, _ := store.GetAutoIndexJobByID(context.Background(), 7); upload.Rank == nil || *upload.Rank != 5 {
|
||||
if upload, _, _ := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 7); upload.Rank == nil || *upload.Rank != 5 {
|
||||
t.Errorf("unexpected rank. want=%d have=%s", 4, printableRank{upload.Rank})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAutoIndexJobsByIDs(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
@ -335,20 +310,8 @@ func TestGetAutoIndexJobsByIDs(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Enable permissions user mapping forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
indexes, err := store.GetAutoIndexJobsByIDs(ctx, 1, 2, 3, 4)
|
||||
// Use an actorless context to test permissions.
|
||||
indexes, err := store.GetAutoIndexJobsByIDs(context.Background(), 1, 2, 3, 4)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -372,7 +335,7 @@ func TestDeleteAutoIndexJobByID(t *testing.T) {
|
||||
}
|
||||
|
||||
// AutoIndexJob no longer exists
|
||||
if _, exists, err := store.GetAutoIndexJobByID(context.Background(), 1); err != nil {
|
||||
if _, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if exists {
|
||||
t.Fatal("unexpected record")
|
||||
@ -387,7 +350,7 @@ func TestDeleteAutoIndexJobs(t *testing.T) {
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 1, State: "completed"})
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 2, State: "errored"})
|
||||
|
||||
if err := store.DeleteAutoIndexJobs(context.Background(), shared.DeleteAutoIndexJobsOptions{
|
||||
if err := store.DeleteAutoIndexJobs(actor.WithInternalActor(context.Background()), shared.DeleteAutoIndexJobsOptions{
|
||||
States: []string{"errored"},
|
||||
Term: "",
|
||||
RepositoryID: 0,
|
||||
@ -396,7 +359,7 @@ func TestDeleteAutoIndexJobs(t *testing.T) {
|
||||
}
|
||||
|
||||
// AutoIndexJob no longer exists
|
||||
if _, exists, err := store.GetAutoIndexJobByID(context.Background(), 2); err != nil {
|
||||
if _, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 2); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if exists {
|
||||
t.Fatal("unexpected record")
|
||||
@ -413,7 +376,7 @@ func TestDeleteAutoIndexJobsWithIndexerKey(t *testing.T) {
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 3, Indexer: "sourcegraph/scip-typescript"})
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 4, Indexer: "sourcegraph/scip-typescript"})
|
||||
|
||||
if err := store.DeleteAutoIndexJobs(context.Background(), shared.DeleteAutoIndexJobsOptions{
|
||||
if err := store.DeleteAutoIndexJobs(actor.WithInternalActor(context.Background()), shared.DeleteAutoIndexJobsOptions{
|
||||
IndexerNames: []string{"scip-go"},
|
||||
}); err != nil {
|
||||
t.Fatalf("unexpected error deleting indexes: %s", err)
|
||||
@ -421,7 +384,7 @@ func TestDeleteAutoIndexJobsWithIndexerKey(t *testing.T) {
|
||||
|
||||
// Target indexes no longer exist
|
||||
for _, id := range []int{1, 2} {
|
||||
if _, exists, err := store.GetAutoIndexJobByID(context.Background(), id); err != nil {
|
||||
if _, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if exists {
|
||||
t.Fatal("unexpected record")
|
||||
@ -430,7 +393,7 @@ func TestDeleteAutoIndexJobsWithIndexerKey(t *testing.T) {
|
||||
|
||||
// Unmatched indexes remain
|
||||
for _, id := range []int{3, 4} {
|
||||
if _, exists, err := store.GetAutoIndexJobByID(context.Background(), id); err != nil {
|
||||
if _, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record, got none")
|
||||
@ -451,7 +414,7 @@ func TestSetRerunAutoIndexJobByID(t *testing.T) {
|
||||
}
|
||||
|
||||
// AutoIndexJob has been marked for reindexing
|
||||
if index, exists, err := store.GetAutoIndexJobByID(context.Background(), 2); err != nil {
|
||||
if index, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 2); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("index missing")
|
||||
@ -468,7 +431,7 @@ func TestSetRerunAutoIndexJobs(t *testing.T) {
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 1, State: "completed"})
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 2, State: "errored"})
|
||||
|
||||
if err := store.SetRerunAutoIndexJobs(context.Background(), shared.SetRerunAutoIndexJobsOptions{
|
||||
if err := store.SetRerunAutoIndexJobs(actor.WithInternalActor(context.Background()), shared.SetRerunAutoIndexJobsOptions{
|
||||
States: []string{"errored"},
|
||||
Term: "",
|
||||
RepositoryID: 0,
|
||||
@ -477,7 +440,7 @@ func TestSetRerunAutoIndexJobs(t *testing.T) {
|
||||
}
|
||||
|
||||
// AutoIndexJob has been marked for reindexing
|
||||
if index, exists, err := store.GetAutoIndexJobByID(context.Background(), 2); err != nil {
|
||||
if index, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), 2); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("index missing")
|
||||
@ -496,7 +459,7 @@ func TestSetRerunAutoIndexJobsWithIndexerKey(t *testing.T) {
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 3, Indexer: "sourcegraph/scip-typescript"})
|
||||
insertAutoIndexJobs(t, db, uploadsshared.AutoIndexJob{ID: 4, Indexer: "sourcegraph/scip-typescript"})
|
||||
|
||||
if err := store.SetRerunAutoIndexJobs(context.Background(), shared.SetRerunAutoIndexJobsOptions{
|
||||
if err := store.SetRerunAutoIndexJobs(actor.WithInternalActor(context.Background()), shared.SetRerunAutoIndexJobsOptions{
|
||||
IndexerNames: []string{"scip-go"},
|
||||
Term: "",
|
||||
RepositoryID: 0,
|
||||
@ -509,7 +472,7 @@ func TestSetRerunAutoIndexJobsWithIndexerKey(t *testing.T) {
|
||||
1: true, 2: true,
|
||||
3: false, 4: false,
|
||||
} {
|
||||
if index, exists, err := store.GetAutoIndexJobByID(context.Background(), id); err != nil {
|
||||
if index, exists, err := store.GetAutoIndexJobByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting index: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("index missing")
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
@ -51,7 +52,7 @@ func TestInsertUploadUploading(t *testing.T) {
|
||||
UploadedParts: []int{},
|
||||
}
|
||||
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), id); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -104,7 +105,7 @@ func TestInsertUploadQueued(t *testing.T) {
|
||||
Rank: &rank,
|
||||
}
|
||||
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), id); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -161,7 +162,7 @@ func TestInsertUploadWithAssociatedIndexID(t *testing.T) {
|
||||
AssociatedIndexID: &associatedIndexIDResult,
|
||||
}
|
||||
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), id); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -187,7 +188,7 @@ func TestAddUploadPart(t *testing.T) {
|
||||
t.Fatalf("unexpected error adding upload part: %s", err)
|
||||
}
|
||||
}
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -207,11 +208,11 @@ func TestMarkQueued(t *testing.T) {
|
||||
insertUploads(t, db, shared.Upload{ID: 1, State: "uploading"})
|
||||
|
||||
uploadSize := int64(300)
|
||||
if err := store.MarkQueued(context.Background(), 1, &uploadSize); err != nil {
|
||||
if err := store.MarkQueued(actor.WithInternalActor(context.Background()), 1, &uploadSize); err != nil {
|
||||
t.Fatalf("unexpected error marking upload as queued: %s", err)
|
||||
}
|
||||
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -233,11 +234,11 @@ func TestMarkQueuedNoSize(t *testing.T) {
|
||||
|
||||
insertUploads(t, db, shared.Upload{ID: 1, State: "uploading"})
|
||||
|
||||
if err := store.MarkQueued(context.Background(), 1, nil); err != nil {
|
||||
if err := store.MarkQueued(actor.WithInternalActor(context.Background()), 1, nil); err != nil {
|
||||
t.Fatalf("unexpected error marking upload as queued: %s", err)
|
||||
}
|
||||
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -260,7 +261,7 @@ func TestMarkFailed(t *testing.T) {
|
||||
t.Fatalf("unexpected error marking upload as failed: %s", err)
|
||||
}
|
||||
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected record to exist")
|
||||
@ -361,7 +362,7 @@ func TestDeleteOverlappingCompletedUploadsIgnoresIncompleteUploads(t *testing.T)
|
||||
}
|
||||
|
||||
// Original upload still exists
|
||||
if _, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if _, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting dump: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("expected dump record to still exist")
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
uploadsshared "github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
@ -19,7 +20,7 @@ func TestGetIndexers(t *testing.T) {
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
|
||||
insertUploads(t, db,
|
||||
shared.Upload{ID: 1, Indexer: "scip-typescript"},
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"github.com/lib/pq"
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/internal/commitgraph"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
|
||||
@ -28,7 +29,7 @@ func TestGetUploads(t *testing.T) {
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
|
||||
t1 := time.Unix(1587396557, 0).UTC()
|
||||
t2 := t1.Add(-time.Minute * 1)
|
||||
@ -215,20 +216,8 @@ func TestGetUploads(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Enable permissions user mapping forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
uploads, totalCount, err := store.GetUploads(ctx,
|
||||
// Use an actorless context to test permissions.
|
||||
uploads, totalCount, err := store.GetUploads(context.Background(),
|
||||
shared.GetUploadsOptions{
|
||||
Limit: 1,
|
||||
},
|
||||
@ -243,7 +232,7 @@ func TestGetUploads(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetUploadByID(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
@ -288,20 +277,8 @@ func TestGetUploadByID(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Enable permissions user mapping forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
_, exists, err := store.GetUploadByID(ctx, 1)
|
||||
// Use an actorless context to test permissions.
|
||||
_, exists, err := store.GetUploadByID(context.Background(), 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -317,7 +294,7 @@ func TestGetUploadByIDDeleted(t *testing.T) {
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
|
||||
// Upload does not exist initially
|
||||
if _, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if _, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if exists {
|
||||
t.Fatal("unexpected record")
|
||||
@ -346,7 +323,7 @@ func TestGetUploadByIDDeleted(t *testing.T) {
|
||||
insertUploads(t, db, expected)
|
||||
|
||||
// Should still not be queryable
|
||||
if _, exists, err := store.GetUploadByID(context.Background(), 1); err != nil {
|
||||
if _, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if exists {
|
||||
t.Fatal("unexpected record")
|
||||
@ -425,7 +402,7 @@ func TestGetCompletedUploadsByIDs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetUploadsByIDs(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := actor.WithInternalActor(context.Background())
|
||||
logger := logtest.Scoped(t)
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
@ -461,20 +438,8 @@ func TestGetUploadsByIDs(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Enable permissions user mapping forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
indexes, err := store.GetUploadsByIDs(ctx, 1, 2, 3, 4)
|
||||
// Use an actorless context to test permissions.
|
||||
indexes, err := store.GetUploadsByIDs(context.Background(), 1, 2, 3, 4)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -567,7 +532,7 @@ func TestGetVisibleUploadsMatchingMonikers(t *testing.T) {
|
||||
|
||||
for i, testCase := range testCases {
|
||||
t.Run(fmt.Sprintf("i=%d", i), func(t *testing.T) {
|
||||
scanner, totalCount, err := store.GetVisibleUploadsMatchingMonikers(context.Background(), 50, makeCommit(1), []precise.QualifiedMonikerData{moniker}, testCase.limit, testCase.offset)
|
||||
scanner, totalCount, err := store.GetVisibleUploadsMatchingMonikers(actor.WithInternalActor(context.Background()), 50, makeCommit(1), []precise.QualifiedMonikerData{moniker}, testCase.limit, testCase.offset)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting scanner: %s", err)
|
||||
}
|
||||
@ -637,7 +602,7 @@ func TestDefinitionDumps(t *testing.T) {
|
||||
}
|
||||
|
||||
// Package does not exist initially
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(context.Background(), []precise.QualifiedMonikerData{moniker1}); err != nil {
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(actor.WithInternalActor(context.Background()), []precise.QualifiedMonikerData{moniker1}); err != nil {
|
||||
t.Fatalf("unexpected error getting package: %s", err)
|
||||
} else if len(uploads) != 0 {
|
||||
t.Fatal("unexpected record")
|
||||
@ -715,7 +680,7 @@ func TestDefinitionDumps(t *testing.T) {
|
||||
t.Fatalf("unexpected error updating packages: %s", err)
|
||||
}
|
||||
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(context.Background(), []precise.QualifiedMonikerData{moniker1}); err != nil {
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(actor.WithInternalActor(context.Background()), []precise.QualifiedMonikerData{moniker1}); err != nil {
|
||||
t.Fatalf("unexpected error getting package: %s", err)
|
||||
} else if len(uploads) != 1 {
|
||||
t.Fatal("expected one record")
|
||||
@ -723,7 +688,7 @@ func TestDefinitionDumps(t *testing.T) {
|
||||
t.Errorf("unexpected dump (-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(context.Background(), []precise.QualifiedMonikerData{moniker1, moniker2}); err != nil {
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(actor.WithInternalActor(context.Background()), []precise.QualifiedMonikerData{moniker1, moniker2}); err != nil {
|
||||
t.Fatalf("unexpected error getting package: %s", err)
|
||||
} else if len(uploads) != 2 {
|
||||
t.Fatal("expected two records")
|
||||
@ -734,20 +699,7 @@ func TestDefinitionDumps(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("enforce repository permissions", func(t *testing.T) {
|
||||
// Turning on explicit permissions forces checking repository permissions
|
||||
// against permissions tables in the database, which should effectively block
|
||||
// all access because permissions tables are empty and repo that dumps belong
|
||||
// to are private.
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
PermissionsUserMapping: &schema.PermissionsUserMapping{
|
||||
Enabled: true,
|
||||
BindID: "email",
|
||||
},
|
||||
},
|
||||
})
|
||||
t.Cleanup(func() { conf.Mock(nil) })
|
||||
|
||||
// Use an actorless context to test permissions.
|
||||
if uploads, err := store.GetCompletedUploadsWithDefinitionsForMonikers(context.Background(), []precise.QualifiedMonikerData{moniker1, moniker2}); err != nil {
|
||||
t.Fatalf("unexpected error getting package: %s", err)
|
||||
} else if len(uploads) != 0 {
|
||||
@ -765,7 +717,7 @@ func TestUploadAuditLogs(t *testing.T) {
|
||||
insertUploads(t, db, shared.Upload{ID: 1})
|
||||
updateUploads(t, db, shared.Upload{ID: 1, State: "deleting"})
|
||||
|
||||
logs, err := store.GetAuditLogsForUpload(context.Background(), 1)
|
||||
logs, err := store.GetAuditLogsForUpload(actor.WithInternalActor(context.Background()), 1)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error fetching audit logs: %s", err)
|
||||
}
|
||||
@ -809,7 +761,7 @@ func TestDeleteUploads(t *testing.T) {
|
||||
shared.Upload{ID: 5, Commit: makeCommit(1115), UploadedAt: t5, State: "uploading"}, // will be deleted
|
||||
)
|
||||
|
||||
err := store.DeleteUploads(context.Background(), shared.DeleteUploadsOptions{
|
||||
err := store.DeleteUploads(actor.WithInternalActor(context.Background()), shared.DeleteUploadsOptions{
|
||||
States: []string{"uploading"},
|
||||
Term: "",
|
||||
VisibleAtTip: false,
|
||||
@ -818,7 +770,7 @@ func TestDeleteUploads(t *testing.T) {
|
||||
t.Fatalf("unexpected error deleting uploads: %s", err)
|
||||
}
|
||||
|
||||
uploads, totalCount, err := store.GetUploads(context.Background(), shared.GetUploadsOptions{Limit: 5})
|
||||
uploads, totalCount, err := store.GetUploads(actor.WithInternalActor(context.Background()), shared.GetUploadsOptions{Limit: 5})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting uploads: %s", err)
|
||||
}
|
||||
@ -850,7 +802,7 @@ func TestDeleteUploadsWithIndexerKey(t *testing.T) {
|
||||
insertUploads(t, db, shared.Upload{ID: 3, State: "queued", Indexer: "sourcegraph/scip-typescript"})
|
||||
insertUploads(t, db, shared.Upload{ID: 4, State: "queued", Indexer: "sourcegraph/scip-typescript"})
|
||||
|
||||
err := store.DeleteUploads(context.Background(), shared.DeleteUploadsOptions{
|
||||
err := store.DeleteUploads(actor.WithInternalActor(context.Background()), shared.DeleteUploadsOptions{
|
||||
IndexerNames: []string{"scip-go"},
|
||||
Term: "",
|
||||
VisibleAtTip: false,
|
||||
@ -859,7 +811,7 @@ func TestDeleteUploadsWithIndexerKey(t *testing.T) {
|
||||
t.Fatalf("unexpected error deleting uploads: %s", err)
|
||||
}
|
||||
|
||||
uploads, totalCount, err := store.GetUploads(context.Background(), shared.GetUploadsOptions{Limit: 5})
|
||||
uploads, totalCount, err := store.GetUploads(actor.WithInternalActor(context.Background()), shared.GetUploadsOptions{Limit: 5})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting uploads: %s", err)
|
||||
}
|
||||
@ -889,7 +841,7 @@ func TestDeleteUploadByID(t *testing.T) {
|
||||
shared.Upload{ID: 1, RepositoryID: 50},
|
||||
)
|
||||
|
||||
if found, err := store.DeleteUploadByID(context.Background(), 1); err != nil {
|
||||
if found, err := store.DeleteUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error deleting upload: %s", err)
|
||||
} else if !found {
|
||||
t.Fatalf("expected record to exist")
|
||||
@ -923,7 +875,7 @@ func TestDeleteUploadByIDMissingRow(t *testing.T) {
|
||||
db := database.NewDB(logger, dbtest.NewDB(t))
|
||||
store := New(observation.TestContextTB(t), db)
|
||||
|
||||
if found, err := store.DeleteUploadByID(context.Background(), 1); err != nil {
|
||||
if found, err := store.DeleteUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error deleting upload: %s", err)
|
||||
} else if found {
|
||||
t.Fatalf("unexpected record")
|
||||
@ -939,7 +891,7 @@ func TestDeleteUploadByIDNotCompleted(t *testing.T) {
|
||||
shared.Upload{ID: 1, RepositoryID: 50, State: "uploading"},
|
||||
)
|
||||
|
||||
if found, err := store.DeleteUploadByID(context.Background(), 1); err != nil {
|
||||
if found, err := store.DeleteUploadByID(actor.WithInternalActor(context.Background()), 1); err != nil {
|
||||
t.Fatalf("unexpected error deleting upload: %s", err)
|
||||
} else if !found {
|
||||
t.Fatalf("expected record to exist")
|
||||
@ -976,7 +928,7 @@ func TestReindexUploads(t *testing.T) {
|
||||
insertUploads(t, db, shared.Upload{ID: 1, State: "completed"})
|
||||
insertUploads(t, db, shared.Upload{ID: 2, State: "errored"})
|
||||
|
||||
if err := store.ReindexUploads(context.Background(), shared.ReindexUploadsOptions{
|
||||
if err := store.ReindexUploads(actor.WithInternalActor(context.Background()), shared.ReindexUploadsOptions{
|
||||
States: []string{"errored"},
|
||||
Term: "",
|
||||
RepositoryID: 0,
|
||||
@ -985,7 +937,7 @@ func TestReindexUploads(t *testing.T) {
|
||||
}
|
||||
|
||||
// Upload has been marked for reindexing
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), 2); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 2); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("upload missing")
|
||||
@ -1004,7 +956,7 @@ func TestReindexUploadsWithIndexerKey(t *testing.T) {
|
||||
insertUploads(t, db, shared.Upload{ID: 3, Indexer: "sourcegraph/scip-typescript"})
|
||||
insertUploads(t, db, shared.Upload{ID: 4, Indexer: "sourcegraph/scip-typescript"})
|
||||
|
||||
if err := store.ReindexUploads(context.Background(), shared.ReindexUploadsOptions{
|
||||
if err := store.ReindexUploads(actor.WithInternalActor(context.Background()), shared.ReindexUploadsOptions{
|
||||
IndexerNames: []string{"scip-go"},
|
||||
Term: "",
|
||||
RepositoryID: 0,
|
||||
@ -1017,7 +969,7 @@ func TestReindexUploadsWithIndexerKey(t *testing.T) {
|
||||
1: true, 2: true,
|
||||
3: false, 4: false,
|
||||
} {
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), id); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), id); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("upload missing")
|
||||
@ -1040,7 +992,7 @@ func TestReindexUploadByID(t *testing.T) {
|
||||
}
|
||||
|
||||
// Upload has been marked for reindexing
|
||||
if upload, exists, err := store.GetUploadByID(context.Background(), 2); err != nil {
|
||||
if upload, exists, err := store.GetUploadByID(actor.WithInternalActor(context.Background()), 2); err != nil {
|
||||
t.Fatalf("unexpected error getting upload: %s", err)
|
||||
} else if !exists {
|
||||
t.Fatal("upload missing")
|
||||
|
||||
@ -17,7 +17,7 @@ func init() {
|
||||
}
|
||||
|
||||
func validateAuthzProviders(cfg conftypes.SiteConfigQuerier, db database.DB) (problems conf.Problems) {
|
||||
_, providers, seriousProblems, warnings, _ := providers.ProvidersFromConfig(context.Background(), cfg, db)
|
||||
providers, seriousProblems, warnings, _ := providers.ProvidersFromConfig(context.Background(), cfg, db)
|
||||
problems = append(problems, conf.NewExternalServiceProblems(seriousProblems...)...)
|
||||
|
||||
// Validating the connection may make a cross service call, so we should use an
|
||||
|
||||
@ -52303,9 +52303,6 @@ type MockPermsStore struct {
|
||||
// HandleFunc is an instance of a mock function object controlling the
|
||||
// behavior of the method Handle.
|
||||
HandleFunc *PermsStoreHandleFunc
|
||||
// IsRepoUnrestrictedFunc is an instance of a mock function object
|
||||
// controlling the behavior of the method IsRepoUnrestricted.
|
||||
IsRepoUnrestrictedFunc *PermsStoreIsRepoUnrestrictedFunc
|
||||
// ListPendingUsersFunc is an instance of a mock function object
|
||||
// controlling the behavior of the method ListPendingUsers.
|
||||
ListPendingUsersFunc *PermsStoreListPendingUsersFunc
|
||||
@ -52425,11 +52422,6 @@ func NewMockPermsStore() *MockPermsStore {
|
||||
return
|
||||
},
|
||||
},
|
||||
IsRepoUnrestrictedFunc: &PermsStoreIsRepoUnrestrictedFunc{
|
||||
defaultHook: func(context.Context, api.RepoID) (r0 bool, r1 error) {
|
||||
return
|
||||
},
|
||||
},
|
||||
ListPendingUsersFunc: &PermsStoreListPendingUsersFunc{
|
||||
defaultHook: func(context.Context, string, string) (r0 []string, r1 error) {
|
||||
return
|
||||
@ -52582,11 +52574,6 @@ func NewStrictMockPermsStore() *MockPermsStore {
|
||||
panic("unexpected invocation of MockPermsStore.Handle")
|
||||
},
|
||||
},
|
||||
IsRepoUnrestrictedFunc: &PermsStoreIsRepoUnrestrictedFunc{
|
||||
defaultHook: func(context.Context, api.RepoID) (bool, error) {
|
||||
panic("unexpected invocation of MockPermsStore.IsRepoUnrestricted")
|
||||
},
|
||||
},
|
||||
ListPendingUsersFunc: &PermsStoreListPendingUsersFunc{
|
||||
defaultHook: func(context.Context, string, string) ([]string, error) {
|
||||
panic("unexpected invocation of MockPermsStore.ListPendingUsers")
|
||||
@ -52717,9 +52704,6 @@ func NewMockPermsStoreFrom(i database.PermsStore) *MockPermsStore {
|
||||
HandleFunc: &PermsStoreHandleFunc{
|
||||
defaultHook: i.Handle,
|
||||
},
|
||||
IsRepoUnrestrictedFunc: &PermsStoreIsRepoUnrestrictedFunc{
|
||||
defaultHook: i.IsRepoUnrestricted,
|
||||
},
|
||||
ListPendingUsersFunc: &PermsStoreListPendingUsersFunc{
|
||||
defaultHook: i.ListPendingUsers,
|
||||
},
|
||||
@ -53963,115 +53947,6 @@ func (c PermsStoreHandleFuncCall) Results() []interface{} {
|
||||
return []interface{}{c.Result0}
|
||||
}
|
||||
|
||||
// PermsStoreIsRepoUnrestrictedFunc describes the behavior when the
|
||||
// IsRepoUnrestricted method of the parent MockPermsStore instance is
|
||||
// invoked.
|
||||
type PermsStoreIsRepoUnrestrictedFunc struct {
|
||||
defaultHook func(context.Context, api.RepoID) (bool, error)
|
||||
hooks []func(context.Context, api.RepoID) (bool, error)
|
||||
history []PermsStoreIsRepoUnrestrictedFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// IsRepoUnrestricted delegates to the next hook function in the queue and
|
||||
// stores the parameter and result values of this invocation.
|
||||
func (m *MockPermsStore) IsRepoUnrestricted(v0 context.Context, v1 api.RepoID) (bool, error) {
|
||||
r0, r1 := m.IsRepoUnrestrictedFunc.nextHook()(v0, v1)
|
||||
m.IsRepoUnrestrictedFunc.appendCall(PermsStoreIsRepoUnrestrictedFuncCall{v0, v1, r0, r1})
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the IsRepoUnrestricted
|
||||
// method of the parent MockPermsStore instance is invoked and the hook
|
||||
// queue is empty.
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) SetDefaultHook(hook func(context.Context, api.RepoID) (bool, error)) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
// PushHook adds a function to the end of hook queue. Each invocation of the
|
||||
// IsRepoUnrestricted method of the parent MockPermsStore instance invokes
|
||||
// the hook at the front of the queue and discards it. After the queue is
|
||||
// empty, the default hook function is invoked for any future action.
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) PushHook(hook func(context.Context, api.RepoID) (bool, error)) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) SetDefaultReturn(r0 bool, r1 error) {
|
||||
f.SetDefaultHook(func(context.Context, api.RepoID) (bool, error) {
|
||||
return r0, r1
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) PushReturn(r0 bool, r1 error) {
|
||||
f.PushHook(func(context.Context, api.RepoID) (bool, error) {
|
||||
return r0, r1
|
||||
})
|
||||
}
|
||||
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) nextHook() func(context.Context, api.RepoID) (bool, error) {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
if len(f.hooks) == 0 {
|
||||
return f.defaultHook
|
||||
}
|
||||
|
||||
hook := f.hooks[0]
|
||||
f.hooks = f.hooks[1:]
|
||||
return hook
|
||||
}
|
||||
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) appendCall(r0 PermsStoreIsRepoUnrestrictedFuncCall) {
|
||||
f.mutex.Lock()
|
||||
f.history = append(f.history, r0)
|
||||
f.mutex.Unlock()
|
||||
}
|
||||
|
||||
// History returns a sequence of PermsStoreIsRepoUnrestrictedFuncCall
|
||||
// objects describing the invocations of this function.
|
||||
func (f *PermsStoreIsRepoUnrestrictedFunc) History() []PermsStoreIsRepoUnrestrictedFuncCall {
|
||||
f.mutex.Lock()
|
||||
history := make([]PermsStoreIsRepoUnrestrictedFuncCall, len(f.history))
|
||||
copy(history, f.history)
|
||||
f.mutex.Unlock()
|
||||
|
||||
return history
|
||||
}
|
||||
|
||||
// PermsStoreIsRepoUnrestrictedFuncCall is an object that describes an
|
||||
// invocation of method IsRepoUnrestricted on an instance of MockPermsStore.
|
||||
type PermsStoreIsRepoUnrestrictedFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 context.Context
|
||||
// Arg1 is the value of the 2nd argument passed to this method
|
||||
// invocation.
|
||||
Arg1 api.RepoID
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 bool
|
||||
// Result1 is the value of the 2nd result returned from this method
|
||||
// invocation.
|
||||
Result1 error
|
||||
}
|
||||
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c PermsStoreIsRepoUnrestrictedFuncCall) Args() []interface{} {
|
||||
return []interface{}{c.Arg0, c.Arg1}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
// invocation.
|
||||
func (c PermsStoreIsRepoUnrestrictedFuncCall) Results() []interface{} {
|
||||
return []interface{}{c.Result0, c.Result1}
|
||||
}
|
||||
|
||||
// PermsStoreListPendingUsersFunc describes the behavior when the
|
||||
// ListPendingUsers method of the parent MockPermsStore instance is invoked.
|
||||
type PermsStoreListPendingUsersFunc struct {
|
||||
|
||||
@ -179,8 +179,6 @@ type PermsStore interface {
|
||||
ListUserPermissions(ctx context.Context, userID int32, args *ListUserPermissionsArgs) (perms []*UserPermission, err error)
|
||||
// ListRepoPermissions returns list of users the repo is accessible to.
|
||||
ListRepoPermissions(ctx context.Context, repoID api.RepoID, args *ListRepoPermissionsArgs) (perms []*RepoPermission, err error)
|
||||
// IsRepoUnrestructed returns if the repo is unrestricted.
|
||||
IsRepoUnrestricted(ctx context.Context, repoID api.RepoID) (unrestricted bool, err error)
|
||||
}
|
||||
|
||||
// It is concurrency-safe and maintains data consistency over the 'user_permissions',
|
||||
@ -2041,28 +2039,22 @@ func (s *permsStore) ListRepoPermissions(ctx context.Context, repoID api.RepoID,
|
||||
permsQueryConditions := []*sqlf.Query{}
|
||||
unrestricted := false
|
||||
|
||||
if authzParams.BypassAuthzReasons.NoAuthzProvider {
|
||||
// return all users as auth is bypassed for everyone
|
||||
// find if the repo is unrestricted
|
||||
unrestricted, err = s.isRepoUnrestricted(ctx, repoID, authzParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if unrestricted {
|
||||
// return all users as repo is unrestricted
|
||||
permsQueryConditions = append(permsQueryConditions, sqlf.Sprintf("TRUE"))
|
||||
unrestricted = true
|
||||
} else {
|
||||
// find if the repo is unrestricted
|
||||
unrestricted, err = s.isRepoUnrestricted(ctx, repoID, authzParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !authzParams.AuthzEnforceForSiteAdmins {
|
||||
// include all site admins
|
||||
permsQueryConditions = append(permsQueryConditions, sqlf.Sprintf("users.site_admin"))
|
||||
}
|
||||
|
||||
if unrestricted {
|
||||
// return all users as repo is unrestricted
|
||||
permsQueryConditions = append(permsQueryConditions, sqlf.Sprintf("TRUE"))
|
||||
} else {
|
||||
if !authzParams.AuthzEnforceForSiteAdmins {
|
||||
// include all site admins
|
||||
permsQueryConditions = append(permsQueryConditions, sqlf.Sprintf("users.site_admin"))
|
||||
}
|
||||
|
||||
permsQueryConditions = append(permsQueryConditions, sqlf.Sprintf(`urp.repo_id = %d`, repoID))
|
||||
}
|
||||
permsQueryConditions = append(permsQueryConditions, sqlf.Sprintf(`urp.repo_id = %d`, repoID))
|
||||
}
|
||||
|
||||
where := []*sqlf.Query{sqlf.Sprintf("(%s)", sqlf.Join(permsQueryConditions, " OR "))}
|
||||
@ -2183,15 +2175,6 @@ WHERE
|
||||
AND %s
|
||||
`
|
||||
|
||||
func (s *permsStore) IsRepoUnrestricted(ctx context.Context, repoID api.RepoID) (bool, error) {
|
||||
authzParams, err := GetAuthzQueryParameters(context.Background(), s.db)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return s.isRepoUnrestricted(ctx, repoID, authzParams)
|
||||
}
|
||||
|
||||
func (s *permsStore) isRepoUnrestricted(ctx context.Context, repoID api.RepoID, authzParams *AuthzQueryParameters) (bool, error) {
|
||||
conditions := []*sqlf.Query{GetUnrestrictedReposCond()}
|
||||
|
||||
|
||||
@ -30,7 +30,6 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbutil"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc"
|
||||
"github.com/sourcegraph/sourcegraph/internal/types"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
"github.com/sourcegraph/sourcegraph/lib/pointers"
|
||||
"github.com/sourcegraph/sourcegraph/schema"
|
||||
@ -3926,9 +3925,6 @@ func TestPermsStore_ListUserPermissions(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
// Set fake authz providers otherwise authz is bypassed
|
||||
authz.SetProviders(false, []authz.Provider{&fakePermsProvider{}})
|
||||
defer authz.SetProviders(true, nil)
|
||||
// Set up some repositories and permissions
|
||||
qs := []*sqlf.Query{
|
||||
sqlf.Sprintf(`INSERT INTO users(id, username, site_admin) VALUES(555, 'user555', FALSE)`),
|
||||
@ -4149,31 +4145,6 @@ func TestPermsStore_ListRepoPermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TestPrivateRepoWithNoAuthzProviders",
|
||||
RepoID: 1,
|
||||
Args: nil,
|
||||
NoAuthzProviders: true,
|
||||
// all users have access
|
||||
WantResults: []*listRepoPermissionsResult{
|
||||
{
|
||||
UserID: 999,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
{
|
||||
UserID: 777,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
{
|
||||
UserID: 666,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
{
|
||||
UserID: 555,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TestPaginationWithPrivateRepo",
|
||||
RepoID: 1,
|
||||
@ -4272,32 +4243,6 @@ func TestPermsStore_ListRepoPermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TestUnrestrictedViaExternalServiceRepoWithoutPermsMapping",
|
||||
RepoID: 4,
|
||||
Args: nil,
|
||||
NoAuthzProviders: true,
|
||||
UsePermissionsUserMapping: false,
|
||||
// restricted access
|
||||
WantResults: []*listRepoPermissionsResult{
|
||||
{
|
||||
UserID: 999,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
{
|
||||
UserID: 777,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
{
|
||||
UserID: 666,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
{
|
||||
UserID: 555,
|
||||
Reason: UserRepoPermissionReasonUnrestricted,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TestPrivateRepoWithAuthzEnforceForSiteAdminsEnabled",
|
||||
RepoID: 1,
|
||||
@ -4325,12 +4270,6 @@ func TestPermsStore_ListRepoPermissions(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
if !test.NoAuthzProviders {
|
||||
// Set fake authz providers otherwise authz is bypassed
|
||||
authz.SetProviders(false, []authz.Provider{&fakePermsProvider{}})
|
||||
defer authz.SetProviders(true, nil)
|
||||
}
|
||||
|
||||
conf.Mock(
|
||||
&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
@ -4372,7 +4311,6 @@ type listRepoPermissionsTest struct {
|
||||
RepoID int
|
||||
Args *ListRepoPermissionsArgs
|
||||
WantResults []*listRepoPermissionsResult
|
||||
NoAuthzProviders bool
|
||||
UsePermissionsUserMapping bool
|
||||
AuthzEnforceForSiteAdmins bool
|
||||
}
|
||||
@ -4382,29 +4320,6 @@ type listRepoPermissionsResult struct {
|
||||
Reason UserRepoPermissionReason
|
||||
}
|
||||
|
||||
type fakePermsProvider struct {
|
||||
codeHost *extsvc.CodeHost
|
||||
extAcct *extsvc.Account
|
||||
}
|
||||
|
||||
func (p *fakePermsProvider) FetchAccount(context.Context, *types.User, []*extsvc.Account, []string) (mine *extsvc.Account, err error) {
|
||||
return p.extAcct, nil
|
||||
}
|
||||
|
||||
func (p *fakePermsProvider) ServiceType() string { return p.codeHost.ServiceType }
|
||||
func (p *fakePermsProvider) ServiceID() string { return p.codeHost.ServiceID }
|
||||
func (p *fakePermsProvider) URN() string { return extsvc.URN(p.codeHost.ServiceType, 0) }
|
||||
|
||||
func (p *fakePermsProvider) ValidateConnection(context.Context) error { return nil }
|
||||
|
||||
func (p *fakePermsProvider) FetchUserPerms(context.Context, *extsvc.Account, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *fakePermsProvider) FetchRepoPerms(context.Context, *extsvc.Repository, authz.FetchPermsOptions) ([]extsvc.AccountID, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func equal(t testing.TB, name string, want, have any) {
|
||||
t.Helper()
|
||||
if diff := cmp.Diff(want, have); diff != "" {
|
||||
|
||||
@ -6,14 +6,12 @@ import (
|
||||
"github.com/keegancsmith/sqlf"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
)
|
||||
|
||||
type BypassAuthzReasonsMap struct {
|
||||
SiteAdmin bool
|
||||
IsInternal bool
|
||||
NoAuthzProvider bool
|
||||
SiteAdmin bool
|
||||
IsInternal bool
|
||||
}
|
||||
|
||||
type AuthzQueryParameters struct {
|
||||
@ -30,16 +28,14 @@ func (p *AuthzQueryParameters) ToAuthzQuery() *sqlf.Query {
|
||||
|
||||
func GetAuthzQueryParameters(ctx context.Context, db DB) (params *AuthzQueryParameters, err error) {
|
||||
params = &AuthzQueryParameters{}
|
||||
authzAllowByDefault, authzProviders := authz.GetProviders()
|
||||
params.UsePermissionsUserMapping = conf.PermissionsUserMapping().Enabled
|
||||
params.AuthzEnforceForSiteAdmins = conf.Get().AuthzEnforceForSiteAdmins
|
||||
|
||||
a := actor.FromContext(ctx)
|
||||
|
||||
// Authz is bypassed when the request is coming from an internal actor or
|
||||
// there is no authz provider configured and access to all repositories are
|
||||
// allowed by default. Authz can be bypassed by site admins unless
|
||||
// conf.AuthEnforceForSiteAdmins is set to "true".
|
||||
// Authz is bypassed when the request is coming from an internal actor.
|
||||
// Authz can be bypassed by site admins unless conf.AuthEnforceForSiteAdmins
|
||||
// is set to "true".
|
||||
//
|
||||
// 🚨 SECURITY: internal requests bypass authz provider permissions checks,
|
||||
// so correctness is important here.
|
||||
@ -48,16 +44,8 @@ func GetAuthzQueryParameters(ctx context.Context, db DB) (params *AuthzQueryPara
|
||||
params.BypassAuthzReasons.IsInternal = true
|
||||
}
|
||||
|
||||
// 🚨 SECURITY: If explicit permissions API is ON, we want to enforce authz
|
||||
// even if there are no authz providers configured.
|
||||
// Otherwise bypass authorization with no authz providers.
|
||||
if !params.UsePermissionsUserMapping && authzAllowByDefault && len(authzProviders) == 0 {
|
||||
params.BypassAuthz = true
|
||||
params.BypassAuthzReasons.NoAuthzProvider = true
|
||||
}
|
||||
|
||||
if a.IsAuthenticated() {
|
||||
currentUser, err := db.Users().GetByCurrentAuthUser(ctx)
|
||||
currentUser, err := a.User(ctx, db.Users())
|
||||
if err != nil {
|
||||
if !params.BypassAuthz {
|
||||
return nil, err
|
||||
|
||||
@ -20,7 +20,6 @@ import (
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/actor"
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/batch"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database/dbtest"
|
||||
@ -29,33 +28,6 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/schema"
|
||||
)
|
||||
|
||||
type fakeProvider struct {
|
||||
codeHost *extsvc.CodeHost
|
||||
extAcct *extsvc.Account
|
||||
}
|
||||
|
||||
func (p *fakeProvider) FetchAccount(context.Context, *types.User, []*extsvc.Account, []string) (mine *extsvc.Account, err error) {
|
||||
return p.extAcct, nil
|
||||
}
|
||||
|
||||
func (p *fakeProvider) ServiceType() string { return p.codeHost.ServiceType }
|
||||
func (p *fakeProvider) ServiceID() string { return p.codeHost.ServiceID }
|
||||
func (p *fakeProvider) URN() string { return extsvc.URN(p.codeHost.ServiceType, 0) }
|
||||
|
||||
func (p *fakeProvider) ValidateConnection(context.Context) error { return nil }
|
||||
|
||||
func (p *fakeProvider) FetchUserPerms(context.Context, *extsvc.Account, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *fakeProvider) FetchUserPermsByToken(context.Context, string, authz.FetchPermsOptions) (*authz.ExternalUserPermissions, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *fakeProvider) FetchRepoPerms(context.Context, *extsvc.Repository, authz.FetchPermsOptions) ([]extsvc.AccountID, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func mockExplicitPermsConfig(enabled bool) func() {
|
||||
conf.Mock(&conf.Unified{
|
||||
SiteConfiguration: schema.SiteConfiguration{
|
||||
@ -76,10 +48,8 @@ func TestAuthzQueryConds(t *testing.T) {
|
||||
db := NewDB(logger, dbtest.NewDB(t))
|
||||
|
||||
t.Run("When permissions user mapping is enabled", func(t *testing.T) {
|
||||
authz.SetProviders(false, []authz.Provider{&fakeProvider{}})
|
||||
cleanup := mockExplicitPermsConfig(true)
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
cleanup()
|
||||
})
|
||||
|
||||
@ -93,10 +63,8 @@ func TestAuthzQueryConds(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When permissions user mapping is enabled, unrestricted repos work correctly", func(t *testing.T) {
|
||||
authz.SetProviders(false, []authz.Provider{&fakeProvider{}})
|
||||
cleanup := mockExplicitPermsConfig(true)
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
cleanup()
|
||||
})
|
||||
|
||||
@ -112,10 +80,9 @@ func TestAuthzQueryConds(t *testing.T) {
|
||||
u, err := db.Users().Create(context.Background(), NewUser{Username: "testuser"})
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func(t *testing.T) (context.Context, DB)
|
||||
authzAllowByDefault bool
|
||||
wantQuery *sqlf.Query
|
||||
name string
|
||||
setup func(t *testing.T) (context.Context, DB)
|
||||
wantQuery *sqlf.Query
|
||||
}{
|
||||
{
|
||||
name: "internal actor bypass checks",
|
||||
@ -125,20 +92,12 @@ func TestAuthzQueryConds(t *testing.T) {
|
||||
wantQuery: authzQuery(true, int32(0)),
|
||||
},
|
||||
{
|
||||
name: "no authz provider and not allow by default",
|
||||
name: "no authz provider",
|
||||
setup: func(t *testing.T) (context.Context, DB) {
|
||||
return context.Background(), db
|
||||
},
|
||||
wantQuery: authzQuery(false, int32(0)),
|
||||
},
|
||||
{
|
||||
name: "no authz provider but allow by default",
|
||||
setup: func(t *testing.T) (context.Context, DB) {
|
||||
return context.Background(), db
|
||||
},
|
||||
authzAllowByDefault: true,
|
||||
wantQuery: authzQuery(true, int32(0)),
|
||||
},
|
||||
{
|
||||
name: "authenticated user is a site admin",
|
||||
setup: func(_ *testing.T) (context.Context, DB) {
|
||||
@ -171,9 +130,6 @@ func TestAuthzQueryConds(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
authz.SetProviders(test.authzAllowByDefault, nil)
|
||||
defer authz.SetProviders(true, nil)
|
||||
|
||||
ctx, mockDB := test.setup(t)
|
||||
q, err := AuthzQueryConds(ctx, mockDB)
|
||||
if err != nil {
|
||||
@ -294,11 +250,6 @@ func TestRepoStore_userCanSeeUnrestricedRepo(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
alice, unrestrictedRepo := setupUnrestrictedDB(t, ctx, db)
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{&fakeProvider{}})
|
||||
t.Cleanup(func() {
|
||||
authz.SetProviders(true, nil)
|
||||
})
|
||||
|
||||
t.Run("Alice cannot see private repo, but can see unrestricted repo", func(t *testing.T) {
|
||||
aliceCtx := actor.WithActor(ctx, &actor.Actor{UID: alice.ID})
|
||||
repos, err := db.Repos().List(aliceCtx, ReposListOptions{})
|
||||
@ -365,12 +316,10 @@ func TestRepoStore_userCanSeePublicRepo(t *testing.T) {
|
||||
alice, publicRepo := setupPublicRepo(t, db)
|
||||
|
||||
t.Run("Alice can see public repo with explicit permissions ON", func(t *testing.T) {
|
||||
authz.SetProviders(false, []authz.Provider{&fakeProvider{}})
|
||||
cleanup := mockExplicitPermsConfig(true)
|
||||
|
||||
t.Cleanup(func() {
|
||||
cleanup()
|
||||
authz.SetProviders(true, nil)
|
||||
})
|
||||
|
||||
aliceCtx := actor.WithActor(ctx, &actor.Actor{UID: alice.ID})
|
||||
@ -526,9 +475,6 @@ func TestRepoStore_List_checkPermissions(t *testing.T) {
|
||||
admin, alice, bob, cindy := users["admin"], users["alice"], users["bob"], users["cindy"]
|
||||
alicePublicRepo, alicePrivateRepo, bobPublicRepo, bobPrivateRepo, cindyPrivateRepo := repos["alice_public_repo"], repos["alice_private_repo"], repos["bob_public_repo"], repos["bob_private_repo"], repos["cindy_private_repo"]
|
||||
|
||||
authz.SetProviders(false, []authz.Provider{&fakeProvider{}})
|
||||
defer authz.SetProviders(true, nil)
|
||||
|
||||
assertRepos := func(t *testing.T, ctx context.Context, want []*types.Repo) {
|
||||
t.Helper()
|
||||
repos, err := db.Repos().List(ctx, ReposListOptions{OrderBy: []RepoListSort{{Field: RepoListID}}})
|
||||
|
||||
@ -2915,7 +2915,7 @@ func TestRepoStore_Metadata(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
md, err := r.Metadata(ctx, 1, 2)
|
||||
md, err := r.Metadata(actor.WithInternalActor(ctx), 1, 2)
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, expected, md)
|
||||
}
|
||||
|
||||
@ -192,9 +192,6 @@ const (
|
||||
// VariantAzureDevOps is the (api.ExternalRepoSpec).ServiceType value for ADO projects.
|
||||
VariantAzureDevOps
|
||||
|
||||
// VariantAzureDevOps is the (api.ExternalRepoSpec).ServiceType value for ADO projects.
|
||||
VariantSCIM
|
||||
|
||||
// VariantNpmPackages is the (api.ExternalRepoSpec).ServiceType value for Npm packages (JavaScript/VariantScript ecosystem libraries).
|
||||
VariantNpmPackages
|
||||
|
||||
@ -238,7 +235,6 @@ var variantValuesMap = map[Variant]variantValues{
|
||||
VariantPythonPackages: {AsKind: "PYTHONPACKAGES", AsType: "pythonPackages", ConfigPrototype: func() any { return &schema.PythonPackagesConnection{} }},
|
||||
VariantRubyPackages: {AsKind: "RUBYPACKAGES", AsType: "rubyPackages", ConfigPrototype: func() any { return &schema.RubyPackagesConnection{} }},
|
||||
VariantRustPackages: {AsKind: "RUSTPACKAGES", AsType: "rustPackages", ConfigPrototype: func() any { return &schema.RustPackagesConnection{} }},
|
||||
VariantSCIM: {AsKind: "SCIM", AsType: "scim"},
|
||||
}
|
||||
|
||||
func (v Variant) AsKind() string {
|
||||
@ -304,7 +300,6 @@ var (
|
||||
KindNpmPackages = VariantNpmPackages.AsKind()
|
||||
KindPagure = VariantPagure.AsKind()
|
||||
KindAzureDevOps = VariantAzureDevOps.AsKind()
|
||||
KindSCIM = VariantSCIM.AsKind()
|
||||
KindOther = VariantOther.AsKind()
|
||||
)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user