Merge lp:~mandel/ubuntu-sso-client/support-user-name-url into lp:ubuntu-sso-client

Proposed by Manuel de la Peña
Status: Merged
Approved by: Natalia Bidart
Approved revision: 854
Merged at revision: 860
Proposed branch: lp:~mandel/ubuntu-sso-client/support-user-name-url
Merge into: lp:ubuntu-sso-client
Diff against target: 165 lines (+127/-4)
2 files modified
ubuntu_sso/utils/webclient/gsettings.py (+19/-4)
ubuntu_sso/utils/webclient/tests/test_gsettings.py (+108/-0)
To merge this branch: bzr merge lp:~mandel/ubuntu-sso-client/support-user-name-url
Reviewer Review Type Date Requested Status
Natalia Bidart (community) Abstain
Roberto Alsina (community) Approve
Alejandro J. Cura (community) Approve
Review via email: mp+92467@code.launchpad.net

Commit message

Adds support for username:password@domain urls in the qt implementation of the webclient

Description of the change

Adds support for username:password@domain urls in the qt implementation of the webclient

To post a comment you must log in.
Revision history for this message
Alejandro J. Cura (alecu) wrote :

"iwth" -> "with"
"suername" -> "username"

----

In this branch there are *only* the tests I've written... shame on you!
We should add tests in ProxySettingsTestCase for the logic you've added in get_proxy_settings()

review: Needs Fixing
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

I see a not minor issue with the logic of parsing username and password from the gsettings["http.host"] (correct me if I'm missing something):

* isn't there a chance to end up with a username from the url, and the password from the gsetting dict? or viceversa, the password of one and the username of the other?

My point is that I would expect the parsing logic to be really explicit about which config takes precedence over the other. If I have both u:<email address hidden>, and gsettings["http.use-authentication"] enabled, which one wins? is it ok that the gsettings one wins, like in this branch?

Minor fix: there is a typo in "settins".

Thanks!

review: Needs Information
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Reviewed code, ran tests on ubuntu. Looks fine!

review: Approve
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :

Voting does not meet specified criteria. Required: Approve >= 1, Disapprove == 0, Needs Fixing == 0, Needs Information == 0, Resubmit == 0, Pending == 0. Got: 2 Approve, 1 Needs Information.

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

I can re-review this as soon as mandel answers my question.

Thanks!

Revision history for this message
Manuel de la Peña (mandel) wrote :

> I see a not minor issue with the logic of parsing username and password from
> the gsettings["http.host"] (correct me if I'm missing something):
>
> * isn't there a chance to end up with a username from the url, and the
> password from the gsetting dict? or viceversa, the password of one and the
> username of the other?

Yes, there is.
>
> My point is that I would expect the parsing logic to be really explicit about
> which config takes precedence over the other. If I have both u:<email address hidden>, and
> gsettings["http.use-authentication"] enabled, which one wins? is it ok that
> the gsettings one wins, like in this branch?
>

After talking with alecu we decided to go for gsettings to step over the settings found in the url. AFAIK in the future there are going to be changes in gnome in which the creds will be correctly stored and gsettings or the keyring will be used.

> Minor fix: there is a typo in "settins".

Fixed! :)
>
> Thanks!

Revision history for this message
Manuel de la Peña (mandel) wrote :

> > I see a not minor issue with the logic of parsing username and password from
> > the gsettings["http.host"] (correct me if I'm missing something):
> >
> > * isn't there a chance to end up with a username from the url, and the
> > password from the gsetting dict? or viceversa, the password of one and the
> > username of the other?
>
> Yes, there is.

Sorry I'm utterly stupid and understood the wrong question. If gsettings is present there is no possibility that we mix the username and passwords. Because:

1. gsettings will always have both, username and password.
2. If anyone is missing we will have an exception because a key is missing.

Maybe is a good idea not to access the settings and gsettings['key'] but use the get method so that we don't crash. What do you think?

> >
> > My point is that I would expect the parsing logic to be really explicit
> about
> > which config takes precedence over the other. If I have both u:<email address hidden>,
> and
> > gsettings["http.use-authentication"] enabled, which one wins? is it ok that
> > the gsettings one wins, like in this branch?
> >
>
> After talking with alecu we decided to go for gsettings to step over the
> settings found in the url. AFAIK in the future there are going to be changes
> in gnome in which the creds will be correctly stored and gsettings or the
> keyring will be used.
>
> > Minor fix: there is a typo in "settins".
>
> Fixed! :)
> >
> > Thanks!

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

> > > I see a not minor issue with the logic of parsing username and password
> from
> > > the gsettings["http.host"] (correct me if I'm missing something):
> > >
> > > * isn't there a chance to end up with a username from the url, and the
> > > password from the gsetting dict? or viceversa, the password of one and the
> > > username of the other?
> >
> > Yes, there is.
>
> Sorry I'm utterly stupid and understood the wrong question. If gsettings is
> present there is no possibility that we mix the username and passwords.
> Because:
>
> 1. gsettings will always have both, username and password.
> 2. If anyone is missing we will have an exception because a key is missing.
>
> Maybe is a good idea not to access the settings and gsettings['key'] but use
> the get method so that we don't crash. What do you think?

Since we're depending on our logic that the gsettings have the 2 values, do not change that to .get() but keep using the [] so if our assumptions are wrong, we need that to blow in our faces.

Revision history for this message
Natalia Bidart (nataliabidart) :
review: Abstain

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntu_sso/utils/webclient/gsettings.py'
2--- ubuntu_sso/utils/webclient/gsettings.py 2012-01-10 20:51:04 +0000
3+++ ubuntu_sso/utils/webclient/gsettings.py 2012-02-10 19:24:02 +0000
4@@ -20,6 +20,17 @@
5 GSETTINGS_CMDLINE = "gsettings list-recursively org.gnome.system.proxy"
6
7
8+def parse_proxy_host(hostname):
9+ """Parse the host to get username and password."""
10+ username = None
11+ password = None
12+ if "@" in hostname:
13+ username, hostname = hostname.rsplit("@", 1)
14+ if ":" in username:
15+ username, password = username.split(":", 1)
16+ return hostname, username, password
17+
18+
19 def get_proxy_settings():
20 """Parse the proxy settings as returned by the gsettings executable."""
21 output = subprocess.check_output(GSETTINGS_CMDLINE.split())
22@@ -41,19 +52,23 @@
23 parsed_value = int(value)
24 relative_key = (path + "." + key)[base_len:]
25 gsettings[relative_key] = parsed_value
26-
27 mode = gsettings["mode"]
28 if mode == "none":
29 settings = {}
30 elif mode == "manual":
31+ # attempt to parse the host
32+ host, username, pwd = parse_proxy_host(gsettings["http.host"])
33 settings = {
34- "host": gsettings["http.host"],
35+ "host": host,
36 "port": gsettings["http.port"],
37 }
38 if gsettings["http.use-authentication"]:
39+ username = gsettings["http.authentication-user"]
40+ pwd = gsettings["http.authentication-password"]
41+ if username is not None and pwd is not None:
42 settings.update({
43- "username": gsettings["http.authentication-user"],
44- "password": gsettings["http.authentication-password"],
45+ "username": username,
46+ "password": pwd,
47 })
48 else:
49 # If mode is automatic the PAC javascript should be interpreted
50
51=== modified file 'ubuntu_sso/utils/webclient/tests/test_gsettings.py'
52--- ubuntu_sso/utils/webclient/tests/test_gsettings.py 2012-01-09 19:08:48 +0000
53+++ ubuntu_sso/utils/webclient/tests/test_gsettings.py 2012-02-10 19:24:02 +0000
54@@ -129,3 +129,111 @@
55 lambda _: fake_output)
56 ps = gsettings.get_proxy_settings()
57 self.assertEqual(ps, expected)
58+
59+ def test_gsettings_parser_authenticated_url(self):
60+ """Test a parser of gsettings with creds in the url."""
61+ template_values = dict(BASE_GSETTINGS_VALUES)
62+ expected_host = "expected_host"
63+ expected_port = 54321
64+ expected_user = "carlitos"
65+ expected_password = "very secret password"
66+ composed_url = '%s:%s@%s' % (expected_user, expected_password,
67+ expected_host)
68+ expected = {
69+ "host": expected_host,
70+ "port": expected_port,
71+ "username": expected_user,
72+ "password": expected_password,
73+ }
74+ template_values.update({
75+ "mode": "manual",
76+ "http_host": composed_url,
77+ "http_port": expected_port,
78+ "http_use_auth": "false",
79+ })
80+ fake_output = TEMPLATE_GSETTINGS_OUTPUT.format(**template_values)
81+ self.patch(gsettings.subprocess, "check_output",
82+ lambda _: fake_output)
83+ ps = gsettings.get_proxy_settings()
84+ self.assertEqual(ps, expected)
85+
86+ def test_gsettings_auth_over_url(self):
87+ """Test that the settings are more important that the url."""
88+ template_values = dict(BASE_GSETTINGS_VALUES)
89+ expected_host = "expected_host"
90+ expected_port = 54321
91+ expected_user = "carlitos"
92+ expected_password = "very secret password"
93+ composed_url = '%s:%s@%s' % ('user', 'random',
94+ expected_host)
95+ expected = {
96+ "host": expected_host,
97+ "port": expected_port,
98+ "username": expected_user,
99+ "password": expected_password,
100+ }
101+ template_values.update({
102+ "mode": "manual",
103+ "http_host": composed_url,
104+ "http_port": expected_port,
105+ "auth_user": expected_user,
106+ "auth_password": expected_password,
107+ "http_use_auth": "true",
108+ })
109+ fake_output = TEMPLATE_GSETTINGS_OUTPUT.format(**template_values)
110+ self.patch(gsettings.subprocess, "check_output",
111+ lambda _: fake_output)
112+ ps = gsettings.get_proxy_settings()
113+ self.assertEqual(ps, expected)
114+
115+
116+class ParseProxyHostTestCase(TestCase):
117+ """Test the parsing of the domain."""
118+
119+ def test_onlyhost(self):
120+ """Parse a host with no username or password."""
121+ sample = "hostname"
122+ hostname, username, password = gsettings.parse_proxy_host(sample)
123+ self.assertEqual(username, None)
124+ self.assertEqual(password, None)
125+ self.assertEqual(hostname, "hostname")
126+
127+ def test_user_and_host(self):
128+ """Parse host just with the username."""
129+ sample = "username@hostname"
130+ hostname, username, password = gsettings.parse_proxy_host(sample)
131+ self.assertEqual(username, "username")
132+ self.assertEqual(password, None)
133+ self.assertEqual(hostname, "hostname")
134+
135+ def test_user_pass_and_host(self):
136+ """Test parsing a host with a username and password."""
137+ sample = "username:password@hostname"
138+ hostname, username, password = gsettings.parse_proxy_host(sample)
139+ self.assertEqual(username, "username")
140+ self.assertEqual(password, "password")
141+ self.assertEqual(hostname, "hostname")
142+
143+ def test_username_with_at(self):
144+ """Test parsing the host with a username with @."""
145+ sample = "username@company.com:password@hostname"
146+ hostname, username, password = gsettings.parse_proxy_host(sample)
147+ self.assertEqual(username, "username@company.com")
148+ self.assertEqual(password, "password")
149+ self.assertEqual(hostname, "hostname")
150+
151+ def test_username_with_at_nopass(self):
152+ """Test parsing the host without a password."""
153+ sample = "username@company.com@hostname"
154+ hostname, username, password = gsettings.parse_proxy_host(sample)
155+ self.assertEqual(username, "username@company.com")
156+ self.assertEqual(password, None)
157+ self.assertEqual(hostname, "hostname")
158+
159+ def test_user_pass_with_colon_and_host(self):
160+ """Test parsing the host with a password that contains :."""
161+ sample = "username:pass:word@hostname"
162+ hostname, username, password = gsettings.parse_proxy_host(sample)
163+ self.assertEqual(username, "username")
164+ self.assertEqual(password, "pass:word")
165+ self.assertEqual(hostname, "hostname")

Subscribers

People subscribed via source and target branches