Skip to content

GODRIVER-2190 Support authorizedCollections option for ListCollections #832

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mongo/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,9 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt
cursorOpts.BatchSize = *lco.BatchSize
op = op.BatchSize(*lco.BatchSize)
}
if lco.AuthorizedCollections != nil {
op = op.AuthorizedCollections(*lco.AuthorizedCollections)
}

retry := driver.RetryNone
if db.client.retryReads {
Expand Down
13 changes: 13 additions & 0 deletions mongo/integration/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,19 @@ func TestDatabase(t *testing.T) {
_, err = evt.Command.LookupErr("cursor", "batchSize")
assert.Nil(mt, err, "expected command %s to contain key 'batchSize'", evt.Command)
})
mt.RunOpts("authorizedCollections", mtest.NewOptions().MinServerVersion("4.0"), func(mt *mtest.T) {
mt.ClearEvents()
lcOpts := options.ListCollections().SetAuthorizedCollections(true)
_, err := mt.DB.ListCollections(mtest.Background, bson.D{}, lcOpts)
assert.Nil(mt, err, "ListCollections error: %v", err)

evt := mt.GetStartedEvent()
assert.Equal(mt, "listCollections", evt.CommandName,
"expected 'listCollections' command to be sent, got %q", evt.CommandName)
_, err = evt.Command.LookupErr("authorizedCollections")
assert.Nil(mt, err, "expected command to contain key 'authorizedCollections'")

})
mt.Run("getMore commands are monitored", func(mt *mtest.T) {
createCollections(mt, 2)
assertGetMoreCommandsAreMonitored(mt, cmdMonitoringCmdName, func() (*mongo.Cursor, error) {
Expand Down
14 changes: 14 additions & 0 deletions mongo/options/listcollectionsoptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ type ListCollectionsOptions struct {

// The maximum number of documents to be included in each batch returned by the server.
BatchSize *int32

// If true, and NameOnly is true, limits the documents returned to only contain collections the user is authorized to use. The default value
// is false. This option is only valid for MongoDB server versions >= 4.0. Server versions < 4.0 ignore this option.
AuthorizedCollections *bool
}

// ListCollections creates a new ListCollectionsOptions instance.
Expand All @@ -32,6 +36,13 @@ func (lc *ListCollectionsOptions) SetBatchSize(size int32) *ListCollectionsOptio
return lc
}

// SetAuthorizedCollections sets the value for the AuthorizedCollections field. This option is only valid for MongoDB server versions >= 4.0. Server
// versions < 4.0 ignore this option.
func (lc *ListCollectionsOptions) SetAuthorizedCollections(b bool) *ListCollectionsOptions {
lc.AuthorizedCollections = &b
return lc
}

// MergeListCollectionsOptions combines the given ListCollectionsOptions instances into a single *ListCollectionsOptions
// in a last-one-wins fashion.
func MergeListCollectionsOptions(opts ...*ListCollectionsOptions) *ListCollectionsOptions {
Expand All @@ -46,6 +57,9 @@ func MergeListCollectionsOptions(opts ...*ListCollectionsOptions) *ListCollectio
if opt.BatchSize != nil {
lc.BatchSize = opt.BatchSize
}
if opt.AuthorizedCollections != nil {
lc.AuthorizedCollections = opt.AuthorizedCollections
}
}

return lc
Expand Down
45 changes: 30 additions & 15 deletions x/mongo/driver/operation/list_collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,21 @@ import (

// ListCollections performs a listCollections operation.
type ListCollections struct {
filter bsoncore.Document
nameOnly *bool
session *session.Client
clock *session.ClusterClock
monitor *event.CommandMonitor
crypt driver.Crypt
database string
deployment driver.Deployment
readPreference *readpref.ReadPref
selector description.ServerSelector
retry *driver.RetryMode
result driver.CursorResponse
batchSize *int32
serverAPI *driver.ServerAPIOptions
filter bsoncore.Document
nameOnly *bool
authorizedCollections *bool
session *session.Client
clock *session.ClusterClock
monitor *event.CommandMonitor
crypt driver.Crypt
database string
deployment driver.Deployment
readPreference *readpref.ReadPref
selector description.ServerSelector
retry *driver.RetryMode
result driver.CursorResponse
batchSize *int32
serverAPI *driver.ServerAPIOptions
}

// NewListCollections constructs and returns a new ListCollections.
Expand Down Expand Up @@ -89,14 +90,17 @@ func (lc *ListCollections) Execute(ctx context.Context) error {
}

func (lc *ListCollections) command(dst []byte, desc description.SelectedServer) ([]byte, error) {

dst = bsoncore.AppendInt32Element(dst, "listCollections", 1)
if lc.filter != nil {
dst = bsoncore.AppendDocumentElement(dst, "filter", lc.filter)
}
if lc.nameOnly != nil {
dst = bsoncore.AppendBooleanElement(dst, "nameOnly", *lc.nameOnly)
}
if lc.authorizedCollections != nil {
dst = bsoncore.AppendBooleanElement(dst, "authorizedCollections", *lc.authorizedCollections)
}

cursorDoc := bsoncore.NewDocumentBuilder()
if lc.batchSize != nil {
cursorDoc.AppendInt32("batchSize", *lc.batchSize)
Expand Down Expand Up @@ -126,6 +130,17 @@ func (lc *ListCollections) NameOnly(nameOnly bool) *ListCollections {
return lc
}

// AuthorizedCollections specifies whether to only return collections the user
// is authorized to use.
func (lc *ListCollections) AuthorizedCollections(authorizedCollections bool) *ListCollections {
if lc == nil {
lc = new(ListCollections)
}

lc.authorizedCollections = &authorizedCollections
return lc
}

// Session sets the session for this operation.
func (lc *ListCollections) Session(session *session.Client) *ListCollections {
if lc == nil {
Expand Down