##// END OF EJS Templates
robocze
Marcin Kasperski -
r4:de7bf5af default
parent child Browse files
Show More
@@ -1,123 +1,126 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 """
3 """
4 Storing HTTP authentication passwords in keyring database.
4 Storing HTTP authentication passwords in keyring database.
5
5
6 Installation method(s):
6 Installation method(s):
7
7
8 1) in ~/.hgrc (or /etc/hgext/...)
8 1) in ~/.hgrc (or /etc/hgext/...)
9
9
10 [extensions]
10 [extensions]
11 ...
11 ...
12 hgext.mercurial_keyring = /path/to/mercurial_keyring.py
12 hgext.mercurial_keyring = /path/to/mercurial_keyring.py
13
13
14
14
15 2) Drop this file to hgext directory and in ~/.hgrc
15 2) Drop this file to hgext directory and in ~/.hgrc
16
16
17 [extensions]
17 [extensions]
18 hgext.mercurial_keyring =
18 hgext.mercurial_keyring =
19
19
20 """
20 """
21
21
22 #import mercurial.demandimport
23 #mercurial.demandimport.disable()
24
22 from mercurial import hg, repo, util
25 from mercurial import hg, repo, util
23 from mercurial.i18n import _
26 from mercurial.i18n import _
24 try:
27 try:
25 from mercurial.url import passwordmgr
28 from mercurial.url import passwordmgr
26 except:
29 except:
27 from mercurial.httprepo import passwordmgr
30 from mercurial.httprepo import passwordmgr
28
31
29 import keyring
32 import keyring
30 import getpass
33 import getpass
31 from urlparse import urlparse
34 from urlparse import urlparse
32 import urllib2
35 import urllib2
33
36
34 KEYRING_SERVICE = "Mercurial"
37 KEYRING_SERVICE = "Mercurial"
35
38
36 ############################################################
39 ############################################################
37
40
38 def monkeypatch_class(name, bases, namespace):
41 def monkeypatch_class(name, bases, namespace):
39 """http://mail.python.org/pipermail/python-dev/2008-January/076194.html"""
42 """http://mail.python.org/pipermail/python-dev/2008-January/076194.html"""
40 assert len(bases) == 1, "Exactly one base class required"
43 assert len(bases) == 1, "Exactly one base class required"
41 base = bases[0]
44 base = bases[0]
42 for name, value in namespace.iteritems():
45 for name, value in namespace.iteritems():
43 if name != "__metaclass__":
46 if name != "__metaclass__":
44 setattr(base, name, value)
47 setattr(base, name, value)
45 return base
48 return base
46
49
47 def monkeypatch_method(cls):
50 def monkeypatch_method(cls):
48 def decorator(func):
51 def decorator(func):
49 setattr(cls, func.__name__, func)
52 setattr(cls, func.__name__, func)
50 return func
53 return func
51 return decorator
54 return decorator
52
55
53 ############################################################
56 ############################################################
54
57
55 class PasswordStore(object):
58 class PasswordStore(object):
56 """
59 """
57 Helper object handling password save&restore. Passwords
60 Helper object handling password save&restore. Passwords
58 are saved both in local memory cache, and keyring, and are
61 are saved both in local memory cache, and keyring, and are
59 restored from those.
62 restored from those.
60 """
63 """
61 def __init__(self):
64 def __init__(self):
62 self.cache = dict()
65 self.cache = dict()
63 def save_password(self, url, username, password):
66 def save_password(self, url, username, password):
64 self.cache[url] = (username, password)
67 self.cache[url] = (username, password)
65 # TODO: keyring save
68 # TODO: keyring save
66 def get_password(self, url):
69 def get_password(self, url):
67 r = self.cache.get(url)
70 r = self.cache.get(url)
68 if r:
71 if r:
69 return r
72 return r
70 # TODO: keyring restore
73 # TODO: keyring restore
71 return None, None
74 return None, None
72
75
73 password_store = PasswordStore()
76 password_store = PasswordStore()
74
77
75 ############################################################
78 ############################################################
76
79
77 @monkeypatch_method(passwordmgr)
80 @monkeypatch_method(passwordmgr)
78 def find_user_password(self, realm, authuri):
81 def find_user_password(self, realm, authuri):
79 """
82 """
80 keyring-based implementation of username/password query
83 keyring-based implementation of username/password query
81
84
82 Passwords are saved in gnome keyring, OSX/Chain or other platform
85 Passwords are saved in gnome keyring, OSX/Chain or other platform
83 specific storage and keyed by the repository url
86 specific storage and keyed by the repository url
84 """
87 """
85 # Calculate the true url. authuri happens to contain things like
88 # Calculate the true url. authuri happens to contain things like
86 # https://repo.machine.com/repos/apps/module?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between
89 # https://repo.machine.com/repos/apps/module?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between
87 parsed_url = urlparse(authuri)
90 parsed_url = urlparse(authuri)
88 base_url = "%s://%s%s" % (parsed_url.scheme, parsed_url.netloc, parsed_url.path)
91 base_url = "%s://%s%s" % (parsed_url.scheme, parsed_url.netloc, parsed_url.path)
89
92
90 #from mercurial import commands, hg
93 #from mercurial import commands, hg
91 #commands.showconfig(self.ui, hg.repository(self.ui, '.'))
94 #commands.showconfig(self.ui, hg.repository(self.ui, '.'))
92
95
93 for section, name, value in self.ui.walkconfig():
96 for section, name, value in self.ui.walkconfig():
94 print "cfg", section, name, value
97 print "cfg", section, name, value
95
98
96 # Extracting possible username/password stored in repository url
99 # Extracting possible username/password stored in repository url
97 user, pwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(self, realm, authuri)
100 user, pwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(self, realm, authuri)
98
101
99 auth_token = self.readauthtoken(base_url)
102 auth_token = self.readauthtoken(base_url)
100 print "token", auth_token
103 print "token", auth_token
101 print "configitems", list(self.ui.configitems('auth'))
104 print "configitems", list(self.ui.configitems('auth'))
102 print "configitems", list(self.ui.configitems('auth', untrusted=True))
105 print "configitems", list(self.ui.configitems('auth', untrusted=True))
103 print "configitems", list(self.ui.configitems('paths'))
106 print "configitems", list(self.ui.configitems('paths'))
104 print self.ui
107 print self.ui
105
108
106 print "find_user_password", realm, base_url, user, pwd, auth_token
109 print "find_user_password", realm, base_url, user, pwd, auth_token
107
110
108 user, pwd = password_store.get_password(base_url)
111 user, pwd = password_store.get_password(base_url)
109 if user and pwd:
112 if user and pwd:
110 return user, pwd
113 return user, pwd
111
114
112 if not self.ui.interactive():
115 if not self.ui.interactive():
113 raise util.Abort(_('mercurial_keyring: http authorization required'))
116 raise util.Abort(_('mercurial_keyring: http authorization required'))
114 self.ui.write(_("http authorization required\n"))
117 self.ui.write(_("http authorization required\n"))
115 self.ui.status(_("realm: %s, url: %s\n" % (realm, base_url)))
118 self.ui.status(_("realm: %s, url: %s\n" % (realm, base_url)))
116 user = self.ui.prompt(_("user:"), default = user)
119 user = self.ui.prompt(_("user:"), default = user)
117 pwd = self.ui.getpass(_("password: "))
120 pwd = self.ui.getpass(_("password: "))
118
121
119 password_store.save_password(base_url, user, pwd)
122 password_store.save_password(base_url, user, pwd)
120
123
121 return user, pwd
124 return user, pwd
122 #return None, None
125 #return None, None
123
126
General Comments 0
You need to be logged in to leave comments. Login now