Skip to content

feat(NODE-3728): Allow to pass authorizedCollections option to the db.listCollections method #3021

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
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
7 changes: 6 additions & 1 deletion src/operations/list_collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const LIST_COLLECTIONS_WIRE_VERSION = 3;
export interface ListCollectionsOptions extends CommandOperationOptions {
/** Since 4.0: If true, will only return the collection name in the response, and will omit additional info */
nameOnly?: boolean;
/** Since 4.0: If true and nameOnly is true, allows a user without the required privilege (i.e. listCollections action on the database) to run the command when access control is enforced. */
authorizedCollections?: boolean;
/** The batchSize for the returned command cursor or if pre 2.8 the systems batch collection */
batchSize?: number;
}
Expand All @@ -25,6 +27,7 @@ export class ListCollectionsOperation extends CommandOperation<string[]> {
db: Db;
filter: Document;
nameOnly: boolean;
authorizedCollections: boolean;
batchSize?: number;

constructor(db: Db, filter: Document, options?: ListCollectionsOptions) {
Expand All @@ -34,6 +37,7 @@ export class ListCollectionsOperation extends CommandOperation<string[]> {
this.db = db;
this.filter = filter;
this.nameOnly = !!this.options.nameOnly;
this.authorizedCollections = !!this.options.authorizedCollections;

if (typeof this.options.batchSize === 'number') {
this.batchSize = this.options.batchSize;
Expand Down Expand Up @@ -99,7 +103,8 @@ export class ListCollectionsOperation extends CommandOperation<string[]> {
listCollections: 1,
filter: this.filter,
cursor: this.batchSize ? { batchSize: this.batchSize } : {},
nameOnly: this.nameOnly
nameOnly: this.nameOnly,
authorizedCollections: this.authorizedCollections
};
}
}
Expand Down
89 changes: 80 additions & 9 deletions test/unit/operations/list_collections.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,54 @@ describe('ListCollectionsOperation', function () {
const operation = new ListCollectionsOperation(db, {}, { nameOnly: true, dbName: db });

it('sets nameOnly to true', function () {
expect(operation.nameOnly).to.be.true;
expect(operation).to.have.property('nameOnly', true);
});
});

context('when nameOnly is false', function () {
const operation = new ListCollectionsOperation(db, {}, { nameOnly: false, dbName: db });

it('sets nameOnly to false', function () {
expect(operation.nameOnly).to.be.false;
expect(operation).to.have.property('nameOnly', false);
});
});
});

context('when nameOnly is not provided', function () {
context('when authorizedCollections is provided', function () {
context('when authorizedCollections is true', function () {
const operation = new ListCollectionsOperation(
db,
{},
{ authorizedCollections: true, dbName: db }
);

it('sets authorizedCollections to true', function () {
expect(operation).to.have.property('authorizedCollections', true);
});
});

context('when authorizedCollections is false', function () {
const operation = new ListCollectionsOperation(
db,
{},
{ authorizedCollections: false, dbName: db }
);

it('sets authorizedCollections to false', function () {
expect(operation).to.have.property('authorizedCollections', false);
});
});
});

context('when no options are provided', function () {
const operation = new ListCollectionsOperation(db, {}, { dbName: db });

it('sets nameOnly to false', function () {
expect(operation.nameOnly).to.be.false;
expect(operation).to.have.property('nameOnly', false);
});

it('sets authorizedCollections to false', function () {
expect(operation).to.have.property('authorizedCollections', false);
});
});
});
Expand All @@ -44,7 +74,8 @@ describe('ListCollectionsOperation', function () {
listCollections: 1,
cursor: {},
filter: {},
nameOnly: true
nameOnly: true,
authorizedCollections: false
});
});
});
Expand All @@ -57,21 +88,61 @@ describe('ListCollectionsOperation', function () {
listCollections: 1,
cursor: {},
filter: {},
nameOnly: false
nameOnly: false,
authorizedCollections: false
});
});
});
});

context('when nameOnly is not provided', function () {
context('when authorizedCollections is provided', function () {
context('when authorizedCollections is true', function () {
const operation = new ListCollectionsOperation(
db,
{},
{ authorizedCollections: true, dbName: db }
);

it('sets authorizedCollections to true', function () {
expect(operation.generateCommand()).to.deep.equal({
listCollections: 1,
cursor: {},
filter: {},
nameOnly: false,
authorizedCollections: true
});
});
});

context('when authorizedCollections is false', function () {
const operation = new ListCollectionsOperation(
db,
{},
{ authorizedCollections: false, dbName: db }
);

it('sets authorizedCollections to false', function () {
expect(operation.generateCommand()).to.deep.equal({
listCollections: 1,
cursor: {},
filter: {},
nameOnly: false,
authorizedCollections: false
});
});
});
});

context('when no options are provided', function () {
const operation = new ListCollectionsOperation(db, {}, { dbName: db });

it('sets nameOnly to false', function () {
it('sets nameOnly and authorizedCollections properties to false', function () {
expect(operation.generateCommand()).to.deep.equal({
listCollections: 1,
cursor: {},
filter: {},
nameOnly: false
nameOnly: false,
authorizedCollections: false
});
});
});
Expand Down