Skip to content

Commit 6b64405

Browse files
committed
PYTHON-860 - Ignore unauthorized errors for index creation in GridFs
1 parent aab0bd5 commit 6b64405

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

gridfs/__init__.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
GridOutCursor)
2929
from pymongo import (ASCENDING,
3030
DESCENDING)
31+
from pymongo.common import UNAUTHORIZED_CODES
3132
from pymongo.database import Database
32-
from pymongo.errors import ConfigurationError
33+
from pymongo.errors import ConfigurationError, OperationFailure
3334

3435

3536
class GridFS(object):
@@ -66,16 +67,25 @@ def __init__(self, database, collection="fs"):
6667
def __is_secondary(self):
6768
return not self.__database.client._is_writable()
6869

70+
def __create_index(self, coll, key, **kwargs):
71+
try:
72+
if not self.__is_secondary():
73+
coll.create_index(key, **kwargs)
74+
except OperationFailure as exc:
75+
if not (exc.code in UNAUTHORIZED_CODES
76+
or "authorized" in str(exc)):
77+
raise exc
78+
79+
6980
def __ensure_index_files_id(self):
70-
if not self.__is_secondary():
71-
self.__chunks.create_index([("files_id", ASCENDING),
72-
("n", ASCENDING)],
73-
unique=True)
81+
self.__create_index(self.__chunks,
82+
[("files_id", ASCENDING), ("n", ASCENDING)],
83+
unique=True)
7484

7585
def __ensure_index_filename(self):
76-
if not self.__is_secondary():
77-
self.__files.create_index([("filename", ASCENDING),
78-
("uploadDate", DESCENDING)])
86+
self.__create_index(self.__files,
87+
[("filename", ASCENDING),
88+
("uploadDate", DESCENDING)])
7989

8090
def new_file(self, **kwargs):
8191
"""Create a new file in GridFS.

gridfs/grid_file.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
NoFile)
2727
from pymongo import ASCENDING
2828
from pymongo.collection import Collection
29+
from pymongo.common import UNAUTHORIZED_CODES
2930
from pymongo.cursor import Cursor
30-
from pymongo.errors import ConfigurationError, DuplicateKeyError
31+
from pymongo.errors import (ConfigurationError,
32+
DuplicateKeyError,
33+
OperationFailure)
3134
from pymongo.read_preferences import ReadPreference
3235

3336
try:
@@ -166,9 +169,14 @@ def __init__(self, root_collection, **kwargs):
166169

167170
def _ensure_index(self):
168171
if not object.__getattribute__(self, "_ensured_index"):
169-
self._coll.chunks.create_index(
170-
[("files_id", ASCENDING), ("n", ASCENDING)],
171-
unique=True)
172+
try:
173+
self._coll.chunks.create_index(
174+
[("files_id", ASCENDING), ("n", ASCENDING)],
175+
unique=True)
176+
except OperationFailure as exc:
177+
if not (exc.code in UNAUTHORIZED_CODES
178+
or "authorized" in str(exc)):
179+
raise exc
172180
object.__setattr__(self, "_ensured_index", True)
173181

174182
@property

pymongo/common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
# exist.
7272
COMMAND_NOT_FOUND_CODES = (59, 13390, None)
7373

74+
# Error codes to ignore if GridFS calls createIndex on a secondary
75+
UNAUTHORIZED_CODES = (13, 16547, 16548)
7476

7577
def partition_node(node):
7678
"""Split a host:port string into (host, int(port)) pair."""

test/test_gridfs.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
single_client,
4141
one,
4242
rs_client,
43-
rs_or_single_client)
43+
rs_or_single_client,
44+
rs_or_single_client_noauth,
45+
remove_all_users)
4446

4547

4648
class JustWrite(threading.Thread):
@@ -514,6 +516,23 @@ def tearDown(self):
514516
rsc.pymongo_test.drop_collection('fs.files')
515517
rsc.pymongo_test.drop_collection('fs.chunks')
516518

519+
class TestGridfsAuth(IntegrationTest):
520+
521+
@client_context.require_auth
522+
def test_gridfs_readonly(self):
523+
# "self.client" is logged in as root. Make a read-only user.
524+
auth_db = self.client.test_gridfs_readonly
525+
auth_db.add_user('readonly', 'pw', readOnly=True)
526+
self.addCleanup(remove_all_users, auth_db)
527+
528+
db = rs_or_single_client_noauth().test_gridfs_readonly
529+
db.authenticate('readonly', 'pw')
530+
531+
fs = gridfs.GridFS(db)
532+
file = fs.new_file()
533+
file._ensure_index()
534+
fs.list()
535+
517536

518537
if __name__ == "__main__":
519538
unittest.main()

0 commit comments

Comments
 (0)