fix: Handle sub-repo permissions in CodeGraphData API (#64241)

This commit is contained in:
Varun Gandhi 2024-08-05 12:31:07 +08:00 committed by GitHub
parent b0702f3c3c
commit ef77a1e0e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 80 additions and 0 deletions

View File

@ -26,6 +26,7 @@ go_library(
visibility = ["//:__subpackages__"],
deps = [
"//cmd/frontend/graphqlbackend/graphqlutil",
"//internal/actor",
"//internal/api",
"//internal/authz",
"//internal/codeintel/codenav",
@ -65,13 +66,16 @@ go_test(
embed = [":graphql"],
tags = [TAG_PLATFORM_GRAPH],
deps = [
"//internal/actor",
"//internal/api",
"//internal/authz",
"//internal/codeintel/codenav",
"//internal/codeintel/codenav/shared",
"//internal/codeintel/core",
"//internal/codeintel/resolvers",
"//internal/codeintel/shared/resolvers/gitresolvers",
"//internal/codeintel/uploads/shared",
"//internal/conf",
"//internal/database/dbmocks",
"//internal/gitserver",
"//internal/gitserver/gitdomain",
@ -79,6 +83,7 @@ go_test(
"//internal/types",
"//lib/errors",
"//lib/pointers",
"//schema",
"@com_github_derision_test_go_mockgen_v2//testutil/require",
"@com_github_hexops_autogold_v2//:autogold",
"@com_github_sourcegraph_scip//bindings/go/scip",

View File

@ -3,6 +3,7 @@ package graphql
import (
"context"
"fmt"
"os"
"sync"
"github.com/graph-gophers/graphql-go"
@ -13,6 +14,7 @@ import (
"github.com/sourcegraph/log"
"github.com/sourcegraph/scip/bindings/go/scip"
"github.com/sourcegraph/sourcegraph/internal/actor"
"github.com/sourcegraph/sourcegraph/internal/api"
"github.com/sourcegraph/sourcegraph/internal/authz"
"github.com/sourcegraph/sourcegraph/internal/codeintel/codenav"
@ -124,6 +126,15 @@ func (r *rootResolver) CodeGraphData(ctx context.Context, opts *resolverstubs.Co
return nil, ErrNotEnabled
}
currentActor := actor.FromContext(ctx)
hasAccess, err := authz.FilterActorPath(ctx, authz.DefaultSubRepoPermsChecker,
currentActor, opts.Repo.Name, opts.Path.RawValue())
if err != nil {
return nil, err
} else if !hasAccess {
return nil, os.ErrNotExist
}
gitTreeTranslator := r.MakeGitTreeTranslator(opts.Repo)
makeResolvers := func(prov codenav.CodeGraphDataProvenance) ([]resolverstubs.CodeGraphDataResolver, error) {
indexer := ""

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"fmt"
"os"
"strings"
"testing"
@ -14,13 +15,16 @@ import (
"github.com/sourcegraph/scip/bindings/go/scip"
"github.com/sourcegraph/scip/cmd/scip/tests/reprolang/bindings/go/repro"
"github.com/sourcegraph/sourcegraph/internal/actor"
"github.com/sourcegraph/sourcegraph/internal/api"
"github.com/sourcegraph/sourcegraph/internal/authz"
"github.com/sourcegraph/sourcegraph/internal/codeintel/codenav"
"github.com/sourcegraph/sourcegraph/internal/codeintel/codenav/shared"
"github.com/sourcegraph/sourcegraph/internal/codeintel/core"
resolverstubs "github.com/sourcegraph/sourcegraph/internal/codeintel/resolvers"
"github.com/sourcegraph/sourcegraph/internal/codeintel/shared/resolvers/gitresolvers"
uploadsshared "github.com/sourcegraph/sourcegraph/internal/codeintel/uploads/shared"
"github.com/sourcegraph/sourcegraph/internal/conf"
"github.com/sourcegraph/sourcegraph/internal/database/dbmocks"
"github.com/sourcegraph/sourcegraph/internal/gitserver"
"github.com/sourcegraph/sourcegraph/internal/gitserver/gitdomain"
@ -28,6 +32,7 @@ import (
sgtypes "github.com/sourcegraph/sourcegraph/internal/types"
"github.com/sourcegraph/sourcegraph/lib/errors"
"github.com/sourcegraph/sourcegraph/lib/pointers"
"github.com/sourcegraph/sourcegraph/schema"
)
// Only exposed for tests, production code should use Unchecked function
@ -599,3 +604,62 @@ func TestOccurrences_Pages(t *testing.T) {
})
}
}
func TestSubRepoPerms(t *testing.T) {
checker := authz.NewMockSubRepoPermissionChecker()
oldChecker := authz.DefaultSubRepoPermsChecker
conf.Mock(&conf.Unified{SiteConfiguration: schema.SiteConfiguration{
ExperimentalFeatures: &schema.ExperimentalFeatures{ScipBasedAPIs: pointers.Ptr(true)},
}})
authz.DefaultSubRepoPermsChecker = checker
t.Cleanup(func() {
conf.Mock(nil)
authz.DefaultSubRepoPermsChecker = oldChecker
})
a := &actor.Actor{UID: 1}
ctx := actor.WithActor(context.Background(), a)
repoName := api.RepoName("foo")
checker.EnabledFunc.SetDefaultReturn(true)
permsFunc := func(path string) (authz.Perms, error) {
switch path {
case "can-access.txt":
return authz.Read, nil
default:
return authz.None, nil
}
}
checker.PermissionsFunc.SetDefaultHook(func(ctx context.Context, i int32, content authz.RepoContent) (authz.Perms, error) {
return permsFunc(content.Path)
})
checker.EnabledForRepoFunc.SetDefaultHook(func(ctx context.Context, rn api.RepoName) (bool, error) {
if rn == repoName {
return true, nil
}
return false, nil
})
mockCodeNavService := NewMockCodeNavService()
observationCtx := observation.NewContext(nil)
resolver := NewRootResolver(
observationCtx, mockCodeNavService, nil, nil, nil, nil,
nil, nil, nil, nil, 10)
repo := sgtypes.Repo{ID: 0, Name: repoName}
opts := resolverstubs.CodeGraphDataOpts{Args: nil, Repo: &repo, Commit: ""}
{
opts := opts
opts.Path = core.NewRepoRelPathUnchecked("can-access.txt")
data, err := resolver.CodeGraphData(ctx, &opts)
require.NoError(t, err)
require.Empty(t, data)
}
{
opts := opts
opts.Path = core.NewRepoRelPathUnchecked("cannot-access.txt")
data, err := resolver.CodeGraphData(ctx, &opts)
require.ErrorIs(t, err, os.ErrNotExist)
require.Empty(t, data)
}
}