r6846 - bigboard/trunk/bigboard



Author: hp
Date: 2007-10-26 16:58:42 -0500 (Fri, 26 Oct 2007)
New Revision: 6846

Modified:
   bigboard/trunk/bigboard/accounts.py
   bigboard/trunk/bigboard/keyring.py
Log:
redo keyring.py to match how accounts.py works

Modified: bigboard/trunk/bigboard/accounts.py
===================================================================
--- bigboard/trunk/bigboard/accounts.py	2007-10-26 21:37:11 UTC (rev 6845)
+++ bigboard/trunk/bigboard/accounts.py	2007-10-26 21:58:42 UTC (rev 6846)
@@ -174,20 +174,27 @@
         else:
             self.__weblogin_accounts.remove(account)
 
+        ## after compositing all this information, update our account object
+        account._update_from_origin(fields)
+
+        ## use updated information to find password
+        fields = {}
+        
         ## third, look for password in keyring
         k = keyring.get_keyring()                
-        if False:
-            ## FIXME
-            if 'password' not in fields:
-                fields['password'] = password
-
+        password = k.get_password(kind=account.get_kind().get_id(),
+                                  username=account.get_username(),
+                                  url=account.get_url())
+        if 'password' not in fields:
+            fields['password'] = password
+            
         ## fourth, if no password in keyring, use the weblogin one
         if weblogin_password and 'password' not in fields:
             fields['password'] = weblogin_password
 
-        ## after compositing all this information, update our account object
-        account._update_from_origin(fields)
-        
+        ## update account object again if we might have the password
+        if 'password' in fields:
+            account._update_from_origin(fields)
 
         ## now add or remove the account from the set of enabled accounts
         if was_enabled and not account.get_enabled():
@@ -311,6 +318,27 @@
                 i = i + 1
 
     def save_account_changes(self, account, new_properties):
+
+        ## special-case handling of password since it goes in the keyring
+        if 'password' in new_properties:
+            if 'username' in new_properties:
+                username = new_properties['username']
+            else:
+                username = account.get_username()
+
+            if 'url' in new_properties:
+                url = new_properties['url']
+            else:
+                url = account.get_url()
+
+            k = keyring.get_keyring()            
+            k.store_login(kind=account.get_kind().get_id(),
+                          username=username,
+                          url=url,
+                          password=new_properties['password'])
+
+        ## now do everything else by stuffing it in gconf
+            
         gconf_dir = account._get_gconf_dir()
         if not gconf_dir:
             gconf_dir = self.__find_unused_gconf_dir(account.get_kind())
@@ -339,9 +367,7 @@
 
         ## enable it last, so we ignore the other settings until we do this
         if 'enabled' in new_properties:
-            set_account_prop(self.__gconf, base_key, 'enabled', new_properties['enabled'])            
-        
-        ## FIXME set the password in keyring
+            set_account_prop(self.__gconf, base_key, 'enabled', new_properties['enabled'])
 
     def create_account(self, kind):
         gconf_dir = self.__find_unused_gconf_dir(kind)
@@ -352,4 +378,11 @@
 
     def get_accounts(self):
         return self.__enabled_accounts
+
+    def get_accounts_with_kind(self, kind):
+        accounts = set()
+        for a in self.__enabled_accounts:
+            if a.get_kind() == kind:
+                accounts.add(a)
+        return accounts
     

Modified: bigboard/trunk/bigboard/keyring.py
===================================================================
--- bigboard/trunk/bigboard/keyring.py	2007-10-26 21:37:11 UTC (rev 6845)
+++ bigboard/trunk/bigboard/keyring.py	2007-10-26 21:58:42 UTC (rev 6846)
@@ -7,82 +7,146 @@
 
 _logger = logging.getLogger("bigboard.Keyring")
 
+class KeyringItem(object):
+    def __init__(self, kind, username='', url='', password=''):
+        super(KeyringItem, self).__init__()        
+        self.__kind = kind
+        self.__username = username
+        self.__url = url
+        self.__password = password
+
+    def get_kind(self):
+        return self.__kind
+
+    def get_username(self):
+        return self.__username
+
+    def get_url(self):
+        return self.__url
+
+    def get_password(self):
+        return self.__password
+
+    def set_kind(self, kind):
+        self.__kind = kind
+
+    def set_username(self, username):
+        self.__username = username
+
+    def set_url(self, url):
+        self.__url = url
+
+    def set_password(self, password):
+        self.__password = password
+
+    def __repr__(self):
+        return '{kind=%s username=%s url=%s len(password)=%d}' % (self.__kind, self.__username, self.__url, len(self.__password))
+
+### The keyring is a map from the tuple (kind,username,url) to a password.
+### In gnome-keyring itself we add to the tuple appname=BigBoard
 class Keyring:
     def __init__(self, is_singleton):
         if not is_singleton == 42:
             raise Exception("use keyring.get_keyring()")
-        # self.__ids and self.__fallback are dictionaries, keyed off 'whatfor', with values
-        # that are dictionaries, keyed off 'username'. The values in inner dictionaries in 
-        # self.__ids are keyring ids. The values in inner dictionaries in self.__fallback 
-        # are passwords. This works best for retrieving and storing username-password pairs
-        # for a particular service. In case of Google, usernames are e-mails.
-        self.__ids = {}
-        self.__fallback = {}
 
+        ### an in-memory substitute for gnome-keyring, set of KeyringItem, used
+        ### when the real keyring is not available
+        self.__fallback_items = set()
+
     def is_available(self):
         return gnomekeyring.is_available()
 
-    # this can throw a TypeError if no matching item is found with 
-    # bignative.keyring_find_items_sync()
-    def get_logins(self, whatfor):
-        username_password_dict = {} 
+    # Returns a set of KeyringItem
+    def get_logins(self, kind, username, url):
+        matches = set()
+
         if not self.is_available():
-            if self.__fallback.has_key(whatfor):
-                _logger.debug("using fallback")
-                return self.__fallback[whatfor]
-            else:
-                return username_password_dict
-       
-        # we can use values from self.__ids if we are looking for a particular 
-        # username, but just using this to get all logins wouldn't work, because
-        # extra logins for the service might be stored in the keyring
-        # don't try to use gnomekeyring.find_items_sync, it's broken
-        found = bignative.keyring_find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET,
-                                                  { 'whatfor' : whatfor } )
-        for f in found:
-            if f.attributes.has_key("username"):
-                _logger.debug("found attribute 'username': %s", f.attributes["username"])
-                username = f.attributes["username"]
-                username_password_dict[username] = f.secret
+            for ki in self.__fallback_items:
+                if ki.get_kind() == kind and \
+                   ki.get_username() == username and \
+                   ki.get_url() == url:
+                    matches.add(ki)
 
-        return username_password_dict
+        else:
+            # don't try to use gnomekeyring.find_items_sync, it's broken
+            try:
+                found = bignative.keyring_find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET,
+                                                          dict(appname='BigBoard',
+                                                               kind=kind,
+                                                               username=username,
+                                                               url=url))
+            except TypeError:
+                found = set()
+                
+            for f in found:
+                ki = KeyringItem(kind=f.attributes['kind'],
+                                 username=f.attributes['username'],
+                                 url=f.attributes['url'],
+                                 password=f.secret)
+                matches.add(ki)
+
+        return matches
+
+    def get_password(self, kind, username, url):
+      logins = self.get_logins(kind, username, url)
+      if len(logins) > 0:
+          return logins.pop().get_password()
+      else:
+          return None
         
-    def remove_logins(self, whatfor):
-        if self.__fallback.has_key(whatfor):
-            del self.__fallback[whatfor]
-        if self.__ids.has_key(whatfor):
-            del self.__ids[whatfor]
+    def remove_logins(self, kind, username, url):
+        new_fallbacks = set()
+        for ki in self.__fallback_items:
+            if ki.get_kind() == kind and \
+                   ki.get_username() == username and \
+                   ki.get_url() == url:
+                pass
+            else:
+                new_fallbacks.add(ki)
+                
+        self.__fallback_items = new_fallbacks
 
-        if self.is_available():    
+        if self.is_available():
             try:   
                 found = bignative.keyring_find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET,
-                                                          { 'appname' : "BigBoard",
-                                                            'whatfor' : whatfor } )
-                for f in found:
-                    gnomekeyring.item_delete_sync('session', f.item_id)
+                                                          dict(appname='BigBoard',
+                                                               kind=kind,
+                                                               username=username,
+                                                               url=url))
             except TypeError:
-                pass
- 
-    def store_login(self, whatfor, username, password):
+                found = set()
+                
+            for f in found:
+                gnomekeyring.item_delete_sync('session', f.item_id)
+  
+    def store_login(self, kind, username, url, password):
         _logger.debug("storing login " + username)
         if not self.is_available():
-            self.__fallback[whatfor] = (username, password)
-            if self.__fallback.has_key(whatfor):
-                self.__fallback[whatfor][username] = password
+            found = None
+            for ki in self.__fallback_items:
+                if ki.get_kind() == kind and \
+                       ki.get_username() == username and \
+                       ki.get_url() == url:
+                    found = ki
+
+            if found:
+                found.set_password(password)
             else:
-                self.__fallback[whatfor] = {username : password} 
+                ki = KeyringItem(kind=kind,
+                                 username=username,
+                                 url=url,
+                                 password=password)
+                self.__fallback_items.add(ki)
+
         else:  
             keyring_item_id = gnomekeyring.item_create_sync('session',
                                                             gnomekeyring.ITEM_GENERIC_SECRET,
                                                             "BigBoard",
                                                             dict(appname="BigBoard",
-                                                                 whatfor=whatfor,
-                                                                 username=username),
+                                                                 kind=kind,
+                                                                 username=username,
+                                                                 url=url),
                                                             password, True)
-            if self.__ids.has_key(whatfor):
-                self.__ids[whatfor][username] = keyring_item_id
-            else:
-                self.__ids[whatfor] = {username : keyring_item_id} 
 
 keyring_inst = None
 def get_keyring():
@@ -101,10 +165,12 @@
     print ring.is_available()
 
     print "storing"
-    ring.store_login('frap', 'qxr', 'def')
+    ring.store_login(kind='google', username='havoc pennington+foo gmail com',
+                     url='http://google.com/', password='frob')
 
     print "getting"
-    print ring.get_logins('frap')
+    print ring.get_logins(kind='google', username='havoc pennington+foo gmail com',
+                          url='http://google.com/')
 
     print "done"
     



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]