Changeset 1102 for trunk/rp/trac

Show
Ignore:
Timestamp:
11/21/07 09:40:55 (14 months ago)
Author:
dbuss
Message:

Added dependency checking, fixed several exceptions in the ldapstore, moved the database files into a common location and made it so that trac-admin /pathtotrac upgrade command would create databases if the ldapstores were configured, prevent double click on infocard icon

Location:
trunk/rp/trac/infocard_acct/0.11
Files:
1 added
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/console.py

    r1061 r1102  
    9999from acct_mgr.api import AccountManager 
    100100 
     101import db_default 
     102from db import InfoCardAccountEnv 
     103 
    101104INFOCARD_ACCT_VERSION = pkg_resources.get_distribution('InfoCardAccountManager').version 
    102105TRAC_VERSION = pkg_resources.get_distribution('Trac').version 
     
    199202                if params: 
    200203                        cursor.execute(sql, params) 
     204                        print 'finished executing %s :: %s' % (sql, params) 
    201205                else: 
    202206                        cursor.execute(sql) 
     207                        print 'finished executing %s' % (sql) 
    203208                if cnx: 
    204209                        cnx.commit() 
     210 
     211        def db_attempt(self, sql, cursor=None, params=None): 
     212                try: 
     213                        if not cursor: 
     214                                cnx = self.db_open() 
     215                                cursor = cnx.cursor() 
     216                        else: 
     217                                cnx = None 
     218                        if params: 
     219                                cursor.execute(sql, params) 
     220                                print 'finished executing %s :: %s' % (sql, params) 
     221                        else: 
     222                                cursor.execute(sql) 
     223                                print 'finished executing %s' % (sql) 
     224                        if cnx: 
     225                                cnx.commit() 
     226                except Exception, e: 
     227                        print 'Ignoring error executing: %s' % (sql) 
    205228 
    206229        ## 
     
    285308                env = self.env_open() 
    286309                ctx = self.db_open() 
    287                 cursor = ctx.cursor() 
    288310 
    289311                tables = None 
    290                 user = Table('user', key=('username'))[ 
    291                                 Column('username'), 
    292                                 Column('passwordhash'), 
    293                                 Index(['username']) 
    294                                 ] 
    295                 cards = Table('cardkey', key=('cardkeyhash'))[ 
    296                                 Column('username'), 
    297                                 Column('cardkeyhash'), 
    298                                 Index(['username']), 
    299                                 Index(['cardkeyhash']) 
    300                                 ]  
    301                 usertables =  [ user ] 
    302                 cardtables = [ cards ] 
    303                 alltables = [user, cards] 
    304                  
    305                  
    306312                if arg[0] == 'user': 
    307                         tables = usertables 
     313                        tables = db_default.usertables 
    308314                elif arg[0] == 'card': 
    309                         tables = cardtables 
    310                 else: 
    311                         tables = alltables 
    312                          
     315                        tables = db_default.cardtables 
     316                else: 
     317                        tables = db_default.alltables 
     318 
    313319                try: 
    314          
    315                         db_connector, _ = DatabaseManager(env)._get_connector() 
    316                         for table in tables: 
    317                                 for stmt in db_connector.to_sql(table): 
    318                                         cursor.execute(stmt) 
     320                        ienv = InfoCardAccountEnv(env) 
     321                        ienv.upgrade_environment(ctx, tables) 
    319322                except TracError, e: 
    320323                        msg = unicode(e) 
     
    337340         
    338341                if arg[0] == 'user': 
    339                         cursor.execute("DROP TABLE user") 
     342                        self.db_attempt("DROP TABLE user", cursor) 
    340343                elif  arg[0] == 'card': 
    341                         cursor.execute("DROP TABLE cardkey") 
    342                 else: 
    343                         cursor.execute("DROP TABLE user") 
    344                         cursor.execute("DROP TABLE cardkey") 
     344                        self.db_attempt("DROP TABLE cardkey", cursor) 
     345                else: 
     346                        self.db_attempt("DROP TABLE user", cursor) 
     347                        self.db_attempt("DROP TABLE cardkey", cursor) 
     348                self.db_update("DELETE from system WHERE name=%s", cursor, (db_default.db_name,)) 
    345349                ctx.commit() 
    346350                print 'cleanenv done.'           
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/db.py

    r1061 r1102  
    3636from trac.config import ExtensionOption 
    3737from trac.db import Table, Column, Index, DatabaseManager 
     38from trac.env import IEnvironmentSetupParticipant 
     39 
     40import db_default 
    3841 
    3942from acct_mgr.api import IPasswordStore 
     
    161164                # is there another way to get count instead of using has_user? 
    162165                return True 
    163                  
     166 
     167 
     168class InfoCardAccountEnv(Component): 
     169 
     170        implements(IEnvironmentSetupParticipant) 
     171        # IEnvironmentSetupParticipant methods 
     172        """Extension point interface for components that need to participate in the 
     173        creation and upgrading of Trac environments, used to setup our database 
     174        tables, we store our component version in the .db for later use.""" 
     175 
     176        def environment_created(self): 
     177                """Called when a new Trac environment is created.""" 
     178                self.found_db_version = 0 
     179                self.upgrade_environment(self.env.get_db_cnx()) 
     180 
     181        def environment_needs_upgrade(self, db): 
     182                """Called when Trac checks whether the environment needs to be upgraded. 
     183                Should return `True` if this participant needs an upgrade to be 
     184                performed, `False` otherwise. If the version in the db is newer 
     185                should we downgrade or abort? 
     186                """ 
     187 
     188                self.found_db_version = 0 
     189                cursor = db.cursor() 
     190                cursor.execute("SELECT value FROM system WHERE name=%s", (db_default.db_name,)) 
     191                value = cursor.fetchone() 
     192                if value: 
     193                        self.found_db_version = int(value[0]) 
     194 
     195                self.log.debug('InfoCardAccountEnv: Current db version %s, required is %s' \ 
     196                                % (self.found_db_version, db_default.db_version)) 
     197 
     198                if self.found_db_version == db_default.db_version: 
     199                        return False 
     200 
     201                return True 
     202                         
     203        def upgrade_environment(self, db, tables=db_default.alltables): 
     204                """Actually perform an environment upgrade, the magic all happens here, 
     205                Note that the commit is called by the caller if we don't raise an error 
     206                """ 
     207                 
     208                if self.environment_needs_upgrade(db): 
     209                        db_connector, _ = DatabaseManager(self.env)._get_connector() 
     210 
     211                        # Insert the default table 
     212                        old_data = {} # {table_name: (col_names, [row, ...]), ...} 
     213                        cursor = db.cursor() 
     214                        if not self.found_db_version: 
     215                                cursor.execute("INSERT INTO system (name, value) VALUES (%s, %s)",(db_default.db_name, db_default.db_version)) 
     216                        else: 
     217                                cursor.execute("UPDATE system SET value=%s WHERE name=%s",(db_default.db_version, db_default.db_name)) 
     218                                for tbl in tables: 
     219                                        try: 
     220                                                cursor.execute('SELECT * FROM %s'%tbl.name) 
     221                                                old_data[tbl.name] = ([d[0] for d in cursor.description], cursor.fetchall()) 
     222                                                cursor.execute('DROP TABLE %s'%tbl.name) 
     223                                        except Exception, e: 
     224                                                if 'OperationalError' not in e.__class__.__name__: 
     225                                                        raise e # If it is an OperationalError, just move on to the next table 
     226 
     227                        for tbl in tables: 
     228                                for sql in db_connector.to_sql(tbl): 
     229                                        cursor.execute(sql) 
     230 
     231                        # Try to reinsert any old data 
     232                        if tbl.name in old_data: 
     233                                data = old_data[tbl.name] 
     234                                sql = 'INSERT INTO %s (%s) VALUES (%s)' % \ 
     235                                          (tbl.name, ','.join(data[0]), ','.join(['%s'] * len(data[0]))) 
     236                                for row in data[1]: 
     237                                        try: 
     238                                                cursor.execute(sql, row) 
     239                                        except Exception, e: 
     240                                                if 'OperationalError' not in e.__class__.__name__: 
     241                                                        raise e 
     242 
     243 
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/ldapstore.py

    r1098 r1102  
    7979                return None; 
    8080                 
    81         def _get_attr(self, url): 
     81        def _get_attrs(self, url): 
    8282                if len(url.attrs) > 0: 
    83                         return url.attrs[0].encode('utf-8') 
     83                        attrList = [] 
     84                        for attr in url.attrs: 
     85                                attrList.append(attr.encode('utf-8')) 
     86                        return attrList 
    8487                else: 
    85                         return 'uid'     
     88                        return ('uid',)  
    8689                 
    8790        def _user_is_invalid(self, user): 
     
    9396                return None 
    9497         
     98        def _get_userfilterstr(self, search_url, user): 
     99                attrs = self._get_attrs(search_url) 
     100                if len(attrs) == 1: 
     101                        return  '(& ' + search_url.filterstr + '('+ self._get_attrs(search_url)+'='+ user       +'))' 
     102                else: 
     103                        return '(& ' + search_url.filterstr + '(|' + ''.join("(%s=%s)" \ 
     104                                        % (attr, user) for attr in attrs)+'))' 
     105 
    95106        def get_users(self): 
    96                 """Returns an iterable of the known usernames 
     107                """Return known usernames 
    97108                """ 
    98109                search_url = self._setup_search_url() 
    99                 users =[] 
    100110                if search_url: 
     111                        self.log.debug('LDAPUserStore:get_users: binding as \"%s\" ' 
     112                                        + 'using \"%s\"', search_url.who, search_url.cred) 
    101113                        l = ldap.open(search_url.hostport) 
    102114                        l.simple_bind_s(search_url.who, search_url.cred) 
    103115                         
    104116                        #get first attr, place in list 
    105                         attrs = (self._get_attr(search_url)) 
     117                        attrs = self._get_attrs(search_url) 
     118                        self.log.debug('LDAPUserStore:get_users: searching \"%s\" ' 
     119                                        + 'for \"%s\"', search_url.dn, search_url.filterstr) 
    106120                        results = l.search_s(search_url.dn, search_url.scope,  
    107121                                search_url.filterstr, attrs) 
    108122                                 
    109                         #works because there is only one attr by convention 
     123                        #works because there is only one attr per entry based on the number 
     124                        # of attributes in the attrs variable above 
    110125                        for entry in results: 
    111                                 for attr in entry[1]: 
    112                                         users.append(entry[1][attr]) 
    113                 return users 
    114                  
     126#                               if entry[1].items() == 1: 
     127                                for attr in entry[1].values(): 
     128                                        self.log.debug('LDAPUserStore:get_users returning: %s' % (attr[0], )) 
     129                                        yield attr[0] 
     130#                               else: 
     131#                                       self.log.debug('LDAPUserStore:get_users found incorrect number of items') 
     132 
    115133        def has_user(self, user): 
    116134#               if self._user_is_invalid(user): 
    117135#                       return False 
    118                 search_url = self._setup_search_url() 
    119                 if search_url: 
    120                         l = ldap.open(search_url.hostport) 
    121                         l.simple_bind_s(search_url.who, search_url.cred) 
    122                         #todo fix so it looks for the user. 
    123                         results = l.search_s(search_url.dn, search_url.scope,  
    124                                 search_url.filterstr) 
    125                         if len(results) == 1: 
    126                                 return True 
     136                try: 
     137                        search_url = self._setup_search_url() 
     138                        if search_url: 
     139                                l = ldap.open(search_url.hostport) 
     140                                l.simple_bind_s(search_url.who, search_url.cred) 
     141                                #todo fix so it looks for the user. 
     142                                results = l.search_s(search_url.dn, search_url.scope,  
     143                                        self._userfilterstr(search_url, user)) 
     144                                if len(results) == 1: 
     145                                        return True 
     146                except: 
     147                        pass 
    127148                return False 
    128149 
     
    135156                                l = ldap.open(search_url.hostport) 
    136157                                l.simple_bind_s(search_url.who, search_url.cred) 
    137                                 searchfilter = '(& ' + search_url.filterstr + '('+ self._get_attr(search_url)+'='+ user +'))' 
    138 #                               self.log.debug('LDAPUserStore:check_password: searching \"%s\" ' 
    139 #                                       + 'for \"%s\"', search_url.dn, searchfilter) 
     158                                searchfilter = self._get_userfilterstr(search_url, user) 
     159                                self.log.debug('LDAPUserStore:check_password: searching \"%s\" ' 
     160                                        + 'for \"%s\"', search_url.dn, searchfilter) 
    140161                                results = l.search_s(search_url.dn, search_url.scope, searchfilter) 
    141162                                if len(results) == 1: 
     
    148169#                                       self.log.debug('LDAPUserStore:check_password succeeded') 
    149170                                        return True 
    150 #                               elif len(results) == 0: 
    151 #                                       self.log.debug('LDAPUserStore:check_password search failed') 
     171                                elif len(results) == 0: 
     172                                        self.log.debug('LDAPUserStore:check_password search failed') 
    152173#                               else: 
    153174#                                       for entry in results: 
     
    156177                except: 
    157178                        #on error just return the password failed 
    158                         self.log.debug('LDAPUserStore:check_password failed') 
     179                        self.log.debug('LDAPUserStore:check_password for \"%s\" failed' % (user)) 
    159180                        return False 
    160181 
    161         def delete_user(self, user): 
    162                 """Deletes the user account. 
    163                 Returns True if the account existed and was deleted, False otherwise. 
    164                 """ 
    165                 if not self.has_user(user): 
    166                         return False 
    167                 db = self.env.get_db_cnx() 
    168                 cursor = db.cursor() 
    169                 cursor.execute("DELETE FROM user " 
    170                                            "WHERE username=%s", (user,)) 
    171                 # TODO cursor.rowcount doesn't seem to get # deleted 
    172                 # is there another way to get count instead of using has_user? 
    173                 return True 
     182#       def delete_user(self, user): 
     183#               """Deletes the user account. 
     184#               Returns True if the account existed and was deleted, False otherwise. 
     185#               """ 
     186#               return False 
    174187                 
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/templates/authenticate.html

    r1061 r1102  
    1212        $('#user')[0].focus(); 
    1313    }); 
     14         
     15        submited = false; 
     16        function image_disable(ref) 
     17        { 
     18                if (!submited) 
     19                { 
     20                        ref.submit(); 
     21                        submited = true; 
     22                } 
     23        }; 
    1424    </script> 
    1525  </head> 
     
    5969                        src="${href.chrome('/infocard_acct/images/infocard_92x64.png')}" 
    6070                                alt="InfoCard Login"   
    61                         onClick='infocardLogin.submit()'/> 
     71                        onClick='image_disable(infocardLogin)'/> 
    6272                        <input type="hidden" name="referer" value="${referer}" /> 
    6373                        <input py:if="blockID" type="hidden" name="blockID" value="${blockID}" /> 
  • trunk/rp/trac/infocard_acct/0.11/setup.py

    r1098 r1102  
    130130 
    131131    install_requires = [ 
    132 #        'Trac>=0.11', 
    133 #               'M2Crypto>=0.18' 
     132        'TracAccountManager', 
     133        'Trac >= 0.11dev_r6153', 
     134        'M2Crypto >= 0.18' 
    134135    ], 
    135136