-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
let username and password be specified outside a uri #731
Conversation
since parse_uri() returns None for values not specified in the uri, 'name' was allowed to be specified outside the uri. This commit allows the same for username and password.
read_preference was already put in the conn_settings dict earlier, and the version placed here is unchanged, remove it.
@conslo good, can you add a test case please for that case? |
ping @conslo |
@yograterol sorry, been busy, I should have this done later today or tomorrow |
This setting was being removed from the dict it’s being compared to, but not it. This would cause any connection_setting with an authentication_source set to always cause new connections to be made.
Explanation of that slightly cryptic loop through settings when establishing a connection
@@ -54,9 +54,8 @@ def register_connection(alias, name=None, host=None, port=None, | |||
uri_dict = uri_parser.parse_uri(conn_settings['host']) | |||
conn_settings.update({ | |||
'name': uri_dict.get('database') or name, | |||
'username': uri_dict.get('username'), | |||
'password': uri_dict.get('password'), | |||
'read_preference': read_preference, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was redundant, as it gets overriden later anyway
# work fine, but there would be no username/password on the | ||
# connection. | ||
self.assertEqual(me_connection._connection_settings['test_uri_no_username']['username'], 'username') | ||
self.assertEqual(me_connection._connection_settings['test_uri_no_username']['password'], 'password') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like doing it this way. If anyone knows how to check the authenticated username on a connection (or anything else that solves this problem) please let me know?
I also added some comments to explain some stuff in get_connection(). I'm at least 95% sure that I'm correct in my assumption, but it could use a look by someone more experienced with the project. |
Conflicts: mongoengine/connection.py
connection_settings.pop('name', None) | ||
connection_settings.pop('username', None) | ||
connection_settings.pop('password', None) | ||
if conn_settings == connection_settings and _connections.get(db_alias, None): | ||
connection = _connections[db_alias] | ||
connection_settings.pop('authentication_source', None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment got removed due to merge, but I feel it's worth being visible:
this was popped off the setting we were comparing, but not within the loop. This would cause any settings with an authentication_source set to equate as not equal every time.
@conslo have you seen that the tests are not passing ? You should maybe explain the count difference. Also, don't you think that the possibility to connect without adding username and password could introduce a security hole ? |
Sorry, this totally fell off my radar. I haven't looked into it but at first glance it looks like there's a merge conflict, I'll reserve some cycles this week. As for the security hole; I don't understand what you mean. It's up to the database to require or not require a username/password, not the connection library (you can have a mongo connection without them, in fact this is the default). What I'm doing here is allowing you to use a URI string but specify the username and password outside the URI. |
Right, I misunderstood the purpose. But then I have difficulties to see the improvement, especially if one anyway has to "initiate" the connection with username and password a first time. |
I'll outline the case at my work where this came up to illustrate the reasoning.
Then from .production import *
try:
from .local import *
except ImportError:
pass Doing this allows us to put configuration in the environment on production, but still keep development values locally without constant re-setup. In order to specify multiple databases (we have two: a master and slave, with auto-failover) you need to use the URI, ie: (I'm going to take this too far now, but as I was writing this it started getting humorous so I kept going) |
@conslo ok I've understood the case and it makes sense. Just aside, I think that using a replica set and connecting via mongos (and therefore simplifying the connection parameters) could be more adapted to your setup, but that is out of scope ;-) Anyway to get a chance to get the pull request merged, you should fix the tests not passing. I don't know if you noticed that 'test_multiple_connection_settings' is not passing anymore. In this case, it is maybe really expected to get only one connection anymore with your fix. But then you should change this test and IMHO also write a new one with really different settings and an assert that we do have 2 distinct connections. |
@MRigal could you elaborate on 'connecting via mongos'? I'm not totally fluent on mongo connection handling, but from what a quick set of googles tell me using this multi-host connection URI is using a replica set: doc. Save for this |
and yes I see that, I'll have to dig into it to understand if this is a failure or a change in behavior and change things accordingly. |
@conslo ping for the failed tests. I think the ground idea is quite good, but I also think the current logic is not completely right. Regarding the connection credentials, what I was meaning is that the way MongoDB recommends to have the servers and the connections, for optimised security is a bit different from what you are using. |
See #1421 |
currently, if you use a uri without the username/password/db name inside it, ie:
mongodb://host1.com:1337,host2.com:1337/
it will pull the db name from the other args passed to connet():
'name': uri_dict.get('database') or name,
but the username and password specified in connect() will be overwritten with None:
This forces anyone using a uri, say to make handling multiple nodes easier, to put their username and password into the uri. This isn't a huge problem, but forces some awkward manual string formatting in some setups, and there's no need for that.
I also removed a duplicate read_preference update.