Merge lp://staging/~sil/desktopcouch/create-oauth-tokens-startup into lp://staging/desktopcouch
- create-oauth-tokens-startup
- Merge into trunk
Status: | Rejected | ||||
---|---|---|---|---|---|
Rejected by: | Elliot Murphy | ||||
Proposed branch: | lp://staging/~sil/desktopcouch/create-oauth-tokens-startup | ||||
Merge into: | lp://staging/desktopcouch | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp://staging/~sil/desktopcouch/create-oauth-tokens-startup | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mark G. Saye (community) | Needs Fixing | ||
Elliot Murphy (community) | Needs Fixing | ||
Joshua Blount (community) | Approve | ||
Review via email: mp+10481@code.staging.launchpad.net |
Commit message
Description of the change
Stuart Langridge (sil) wrote : | # |
Joshua Blount (jblount) : | # |
Elliot Murphy (statik) wrote : | # |
I've packaged 0.10.0~
After merging with trunk and resolving the merge conflicts, I get errors on a number of tests, all appear to have the same cause: 401 on a HEAD request.
=======
[ERROR]: desktopcouch.
Traceback (most recent call last):
File "/usr/lib/
self.setUp()
File "/home/
self.dbname, create=True, uri=URI)
File "/home/
if database not in self._server:
File "/usr/lib/
self.
File "/usr/lib/
return self._request(
File "/usr/lib/
raise ServerError(
couchdb.
=======
[ERROR]: desktopcouch.
Traceback (most recent call last):
File "/usr/lib/
self.setUp()
File "/home/
self.dbname, create=True, uri=URI)
File "/home/
if database not in self._server:
File "/usr/lib/
self.
File "/usr/lib/
return self._request(
File "/usr/lib/
raise ServerError(
couchdb.
Stuart Langridge (sil) wrote : | # |
> I've packaged 0.10.0~
> that Jan created today, + the part of the patch for COUCHDB-478 that has not
> been applied to the branch yet.
>
> After merging with trunk and resolving the merge conflicts, I get errors on a
> number of tests, all appear to have the same cause: 401 on a HEAD request.
Yep. This is a COuch bug (http://
Stuart Langridge (sil) wrote : | # |
> > I've packaged 0.10.0~
> > that Jan created today, + the part of the patch for COUCHDB-478 that has not
> > been applied to the branch yet.
> >
> > After merging with trunk and resolving the merge conflicts, I get errors on
> a
> > number of tests, all appear to have the same cause: 401 on a HEAD request.
>
> Yep. This is a COuch bug (http://
> the fix for which has not yet been merged into trunk :-(
Ah, it may have been merged now, looking at the bug report, but I don't know if it's in our packages yet...
Mark G. Saye (markgsaye) wrote : | # |
> bzr merge lp:~sil/desktopcouch/create-oauth-tokens-startup
M data/couchdb.tmpl
M desktopcouch/
Text conflict in desktopcouch/
1 conflicts encountered.
> bzr diff desktopcouch/
=== modified file 'desktopcouch/
--- desktopcouch/
+++ desktopcouch/
@@ -34,14 +34,16 @@
"""
from __future__ import with_statement
-import os, subprocess, sys, glob
+import os, subprocess, sys, glob, random, string
import desktopcouch
from desktopcouch import local_files
import xdg.BaseDirectory
import errno
-import time
+import time, gtk, gnomekeyring
from desktopcouch.
+ACCEPTABLE_
+
def dump_ini(data, filename):
"""Dump INI data with sorted sections and keywords"""
fd = open(filename, 'w')
@@ -60,9 +62,38 @@
"""Write CouchDB ini file if not already present"""
+<<<<<<< TREE
if os.path.
return
ini = {
+=======
+ if os.path.
+ # load the username and password from the keyring
+ try:
+ data = gnomekeyring.
+ {'desktopcouch': 'basic'})
+ except gnomekeyring.
+ data = None
+ if data:
+ username, password = data[0]
+ return username, password
+ # otherwise fall through; for some reason the access details aren't
+ # in the keyring, so re-create the ini file and do it all again
+
+ # randomly generate tokens and usernames
+ def make_random_
+ return ''.join(
+ for x in range(count)])
+
+ ADMIN_ACCOUNT_
+ ADMIN_ACCOUNT_
+ CONSUMER_KEY = make_random_
+ CONSUMER_SECRET = make_random_
+ TOKEN = make_random_
+ TOKEN_SECRET = make_random_
+
+ local = {
+>>>>>>> MERGE-SOURCE
'couchdb': {
@@ -75,10 +106,51 @@
},
+ 'admins': {
+ ADMIN_ACCOUNT_
+ },
+ 'oauth_
+ CONSUMER_KEY: CONSUMER_SECRET
+ },
+ 'oauth_
+ TOKEN: TOKEN_SECRET
+ },
+ 'oauth_
+ TOKEN: ADMIN_ACCOUNT_
+ },
+ 'couch_httpd_auth': {
+ 'require_
+ }
}
+<<<<<<< TREE
dump...
Elliot Murphy (statik) wrote : | # |
> Ah, it may have been merged now, looking at the bug report, but I don't know
> if it's in our packages yet...
Yep, I made sure that the commit which included the purported fix for COUCHDB-479 was included in the couchdb snapshot, but looks like the fix for COUCHDB-479 was broken. We're waiting for couchdb devs to give us a working fix.
Elliot Murphy (statik) wrote : | # |
rejecting this branch, and merging thisfreds noauth, which combines everything as we discussed this morning.
Unmerged revisions
Preview Diff
1 | === modified file 'data/couchdb.tmpl' | |||
2 | --- data/couchdb.tmpl 2009-07-14 13:53:21 +0000 | |||
3 | +++ data/couchdb.tmpl 2009-08-20 12:55:54 +0000 | |||
4 | @@ -31,7 +31,7 @@ | |||
5 | 31 | come back to browse your CouchDB again.</p> | 31 | come back to browse your CouchDB again.</p> |
6 | 32 | <p>Don't bookmark the CouchDB page itself, because its location may change!</p> | 32 | <p>Don't bookmark the CouchDB page itself, because its location may change!</p> |
7 | 33 | <p>Taking you to your Desktop CouchDB in <span>30</span> seconds... | 33 | <p>Taking you to your Desktop CouchDB in <span>30</span> seconds... |
9 | 34 | <a id="there" href="http://localhost:[[COUCHDB_PORT]]/_utils">take me | 34 | <a id="there" href="http://[[COUCHDB_USERNAME]]:[[COUCHDB_PASSWORD]]@localhost:[[COUCHDB_PORT]]/_utils">take me |
10 | 35 | there straight away from now on</a> (remember to bookmark this page first!)</p> | 35 | there straight away from now on</a> (remember to bookmark this page first!)</p> |
11 | 36 | </body> | 36 | </body> |
12 | 37 | </html> | 37 | </html> |
13 | 38 | 38 | ||
14 | === modified file 'desktopcouch/start_local_couchdb.py' | |||
15 | --- desktopcouch/start_local_couchdb.py 2009-08-19 16:00:01 +0000 | |||
16 | +++ desktopcouch/start_local_couchdb.py 2009-08-20 12:55:54 +0000 | |||
17 | @@ -32,14 +32,16 @@ | |||
18 | 32 | """ | 32 | """ |
19 | 33 | 33 | ||
20 | 34 | from __future__ import with_statement | 34 | from __future__ import with_statement |
22 | 35 | import os, subprocess, sys, glob | 35 | import os, subprocess, sys, glob, random, string |
23 | 36 | import desktopcouch | 36 | import desktopcouch |
24 | 37 | from desktopcouch import local_files | 37 | from desktopcouch import local_files |
25 | 38 | import xdg.BaseDirectory | 38 | import xdg.BaseDirectory |
26 | 39 | import errno | 39 | import errno |
28 | 40 | import time | 40 | import time, gtk, gnomekeyring |
29 | 41 | from desktopcouch.records.server import CouchDatabase | 41 | from desktopcouch.records.server import CouchDatabase |
30 | 42 | 42 | ||
31 | 43 | ACCEPTABLE_USERNAME_PASSWORD_CHARS = string.lowercase + string.uppercase | ||
32 | 44 | |||
33 | 43 | def dump_ini(data, filename): | 45 | def dump_ini(data, filename): |
34 | 44 | """Dump INI data with sorted sections and keywords""" | 46 | """Dump INI data with sorted sections and keywords""" |
35 | 45 | fd = open(filename, 'w') | 47 | fd = open(filename, 'w') |
36 | @@ -56,18 +58,31 @@ | |||
37 | 56 | 58 | ||
38 | 57 | def create_ini_file(): | 59 | def create_ini_file(): |
39 | 58 | """Write CouchDB ini file if not already present""" | 60 | """Write CouchDB ini file if not already present""" |
40 | 59 | # FIXME add update trigger folder | ||
41 | 60 | #update_trigger_dir = [ | ||
42 | 61 | # 'lib', 'canonical', 'ubuntuone', 'cloud_server', 'update_triggers'] | ||
43 | 62 | # | ||
44 | 63 | #timestamp_trigger = os.path.join( | ||
45 | 64 | # *update_trigger_dir + ['timestamp_trigger.py']) | ||
46 | 65 | #update_trigger = os.path.join( | ||
47 | 66 | # *update_trigger_dir + ['update_trigger.py']) | ||
48 | 67 | |||
49 | 68 | if os.path.exists(local_files.FILE_INI): | 61 | if os.path.exists(local_files.FILE_INI): |
52 | 69 | return | 62 | # load the username and password from the keyring |
53 | 70 | 63 | try: | |
54 | 64 | data = gnomekeyring.find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET, | ||
55 | 65 | {'desktopcouch': 'basic'}) | ||
56 | 66 | except gnomekeyring.NoMatchError: | ||
57 | 67 | data = None | ||
58 | 68 | if data: | ||
59 | 69 | username, password = data[0].secret.split(":") | ||
60 | 70 | return username, password | ||
61 | 71 | # otherwise fall through; for some reason the access details aren't | ||
62 | 72 | # in the keyring, so re-create the ini file and do it all again | ||
63 | 73 | |||
64 | 74 | # randomly generate tokens and usernames | ||
65 | 75 | def make_random_string(count): | ||
66 | 76 | return ''.join([random.choice(ACCEPTABLE_USERNAME_PASSWORD_CHARS) | ||
67 | 77 | for x in range(count)]) | ||
68 | 78 | |||
69 | 79 | ADMIN_ACCOUNT_USERNAME = make_random_string(10) | ||
70 | 80 | ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD = make_random_string(10) | ||
71 | 81 | CONSUMER_KEY = make_random_string(10) | ||
72 | 82 | CONSUMER_SECRET = make_random_string(10) | ||
73 | 83 | TOKEN = make_random_string(10) | ||
74 | 84 | TOKEN_SECRET = make_random_string(10) | ||
75 | 85 | |||
76 | 71 | local = { | 86 | local = { |
77 | 72 | 'couchdb': { | 87 | 'couchdb': { |
78 | 73 | 'database_dir': local_files.DIR_DB, | 88 | 'database_dir': local_files.DIR_DB, |
79 | @@ -81,9 +96,43 @@ | |||
80 | 81 | 'file': local_files.FILE_LOG, | 96 | 'file': local_files.FILE_LOG, |
81 | 82 | 'level': 'info', | 97 | 'level': 'info', |
82 | 83 | }, | 98 | }, |
83 | 99 | 'admins': { | ||
84 | 100 | ADMIN_ACCOUNT_USERNAME: ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD | ||
85 | 101 | }, | ||
86 | 102 | 'oauth_consumer_secrets': { | ||
87 | 103 | CONSUMER_KEY: CONSUMER_SECRET | ||
88 | 104 | }, | ||
89 | 105 | 'oauth_token_secrets': { | ||
90 | 106 | TOKEN: TOKEN_SECRET | ||
91 | 107 | }, | ||
92 | 108 | 'oauth_token_users': { | ||
93 | 109 | TOKEN: ADMIN_ACCOUNT_USERNAME | ||
94 | 110 | }, | ||
95 | 111 | 'couch_httpd_auth': { | ||
96 | 112 | 'require_valid_user': 'true' | ||
97 | 113 | } | ||
98 | 84 | } | 114 | } |
99 | 85 | 115 | ||
100 | 86 | dump_ini(local, local_files.FILE_INI) | 116 | dump_ini(local, local_files.FILE_INI) |
101 | 117 | # save admin account details in keyring | ||
102 | 118 | item_id = gnomekeyring.item_create_sync( | ||
103 | 119 | None, | ||
104 | 120 | gnomekeyring.ITEM_GENERIC_SECRET, | ||
105 | 121 | 'Desktop Couch user authentication', | ||
106 | 122 | {'desktopcouch': 'basic'}, | ||
107 | 123 | "%s:%s" % (ADMIN_ACCOUNT_USERNAME, ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD), | ||
108 | 124 | True) | ||
109 | 125 | # and oauth tokens | ||
110 | 126 | item_id = gnomekeyring.item_create_sync( | ||
111 | 127 | None, | ||
112 | 128 | gnomekeyring.ITEM_GENERIC_SECRET, | ||
113 | 129 | 'Desktop Couch user authentication', | ||
114 | 130 | {'desktopcouch': 'oauth'}, | ||
115 | 131 | "%s:%s:%s:%s" % (CONSUMER_KEY, CONSUMER_SECRET, TOKEN, TOKEN_SECRET), | ||
116 | 132 | True) | ||
117 | 133 | |||
118 | 134 | |||
119 | 135 | return (ADMIN_ACCOUNT_USERNAME, ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD) | ||
120 | 87 | 136 | ||
121 | 88 | def run_couchdb(): | 137 | def run_couchdb(): |
122 | 89 | """Actually start the CouchDB process""" | 138 | """Actually start the CouchDB process""" |
123 | @@ -146,7 +195,7 @@ | |||
124 | 146 | # than inefficiently just overwriting it regardless | 195 | # than inefficiently just overwriting it regardless |
125 | 147 | db.add_view(view_name, mapjs, reducejs, dd_name) | 196 | db.add_view(view_name, mapjs, reducejs, dd_name) |
126 | 148 | 197 | ||
128 | 149 | def write_bookmark_file(): | 198 | def write_bookmark_file(username, password): |
129 | 150 | """Write out an HTML document that the user can bookmark to find their DB""" | 199 | """Write out an HTML document that the user can bookmark to find their DB""" |
130 | 151 | bookmark_file = os.path.join(local_files.DIR_DB, "couchdb.html") | 200 | bookmark_file = os.path.join(local_files.DIR_DB, "couchdb.html") |
131 | 152 | 201 | ||
132 | @@ -182,21 +231,24 @@ | |||
133 | 182 | pass | 231 | pass |
134 | 183 | else: | 232 | else: |
135 | 184 | fp = open(bookmark_file, "w") | 233 | fp = open(bookmark_file, "w") |
137 | 185 | fp.write(html.replace("[[COUCHDB_PORT]]", port)) | 234 | out = html.replace("[[COUCHDB_PORT]]", port) |
138 | 235 | out = out.replace("[[COUCHDB_USERNAME]]", username) | ||
139 | 236 | out = out.replace("[[COUCHDB_PASSWORD]]", password) | ||
140 | 237 | fp.write(out) | ||
141 | 186 | fp.close() | 238 | fp.close() |
142 | 187 | print "Browse your desktop CouchDB at file://%s" % \ | 239 | print "Browse your desktop CouchDB at file://%s" % \ |
143 | 188 | os.path.realpath(bookmark_file) | 240 | os.path.realpath(bookmark_file) |
144 | 189 | 241 | ||
145 | 190 | def start_couchdb(): | 242 | def start_couchdb(): |
146 | 191 | """Execute each step to start a desktop CouchDB""" | 243 | """Execute each step to start a desktop CouchDB""" |
148 | 192 | create_ini_file() | 244 | username, password = create_ini_file() |
149 | 193 | run_couchdb() | 245 | run_couchdb() |
150 | 194 | # Note that we do not call update_design_documents here. This is because | 246 | # Note that we do not call update_design_documents here. This is because |
151 | 195 | # Couch won't actually have started yet, so when update_design_documents | 247 | # Couch won't actually have started yet, so when update_design_documents |
152 | 196 | # calls the Records API, that will call back into get_pid and we end up | 248 | # calls the Records API, that will call back into get_pid and we end up |
153 | 197 | # starting Couch again. Instead, get_pid calls update_design_documents | 249 | # starting Couch again. Instead, get_pid calls update_design_documents |
154 | 198 | # *after* Couch startup has occurred. | 250 | # *after* Couch startup has occurred. |
156 | 199 | write_bookmark_file() | 251 | write_bookmark_file(username, password) |
157 | 200 | 252 | ||
158 | 201 | 253 | ||
159 | 202 | if __name__ == "__main__": | 254 | if __name__ == "__main__": |
Add oauth tokens as part of initial desktopcouch setup, and lock desktopcouch access to authenticated users only.
(NB: do not merge into desktopcouch trunk until http:// issues. apache. org/jira/ browse/ COUCHDB- 478 is in your couchdb build, or this will prevent access to your desktop Couch; it sets up an admin user in the ini file, but oauth authentication doesn't read from the ini file in Couch trunk; that's what the above patch is for.)