Index: acct_mgr/admin.py
===================================================================
--- acct_mgr/admin.py	(revision 2186)
+++ acct_mgr/admin.py	(working copy)
@@ -28,6 +28,77 @@
     return [(name, value) for name, value in inspect.getmembers(cls)
             if isinstance(value, Option)]
 
+def _setorder(req, stores):
+    """Pull the password store ordering out of the req object"""
+    for store in stores.get_all_stores():
+        stores[store] = int(req.args.get(store.__class__.__name__, 0))
+        continue
+
+
+class StoreOrder(dict):
+    """Keeps the order of the Password Stores"""
+
+    instance = 0
+
+    def __init__(self, d={}, stores=[], list=[]):
+        self.instance += 1
+        self.d = {}
+        self.sxref = {}
+        for store in stores:
+            self.d[store] = 0
+            self[0] = store
+            self.sxref[store.__class__.__name__] = store
+            continue
+        for i, s in enumerate(list):
+            self.d[s] = i + 1
+            self[i + 1] = s
+
+    def __getitem__(self, key):
+        """Lookup a store in the list"""
+        return self.d[key]
+
+    def __setitem__(self, key, value):
+        if isinstance(key, Component):
+            order = self.d[key]
+            self.d[key] = value
+            self.d[order].remove(key)
+            self[value] = key
+        elif isinstance(key, basestring):
+            self.d[self.sxref[key]] = value
+        elif isinstance(key, int):
+            self.d.setdefault(key, [])
+            self.d[key].append(value)
+        else:
+            raise KeyError('Invalid key type (%s) for StoreOrder' 
+                           % str(type(key)))
+        pass
+
+    def get_enabled_stores(self):
+        """Return an ordered list of password stores
+        
+        All stores that are order 0 are dropped from the list.
+        """
+        keys = [k for k in self.d.keys() if isinstance(k, int)]
+        keys.sort()
+        storelist = []
+        for k in keys[1:]:
+            storelist.extend(self.d[k])
+            continue
+        return storelist
+
+    def get_enabled_store_names(self):
+        """Returns the class names of the enabled password stores"""
+        stores = self.get_enabled_stores()
+        return [s.__class__.__name__ for s in stores]
+    
+    def get_all_stores(self):
+        return [k for k in self.d.keys() if isinstance(k, Component)]
+
+    def numstores(self):
+        return len(self.get_all_stores())
+        
+    
+
 class AccountManagerAdminPage(Component):
 
     implements(IAdminPageProvider)
@@ -46,35 +117,45 @@
             return self._do_config(req)
         elif page == 'users': 
             return self._do_users(req) 
-            
+        
     def _do_config(self, req):
+        stores = StoreOrder(stores=self.account_manager.stores, 
+                            list=self.account_manager.password_store)
+
         if req.method == 'POST':
-            selected_class = req.args.get('selected')
-            self.config.set('account-manager', 'password_store', selected_class)
-            selected = self.account_manager.password_store
-            for attr, option in _getoptions(selected):
-                newvalue = req.args.get('%s.%s' % (selected_class, attr))
-                if newvalue is not None:
-                    self.config.set(option.section, option.name, newvalue)
-                    self.config.save()
-        try:
-            selected = self.account_manager.password_store
-        except AttributeError:
-            selected = None
-        sections = [
-            {'name': store.__class__.__name__,
-             'classname': store.__class__.__name__,
-             'selected': store is selected,
-             'options': [
-                {'label': attr,
-                 'name': '%s.%s' % (store.__class__.__name__, attr),
-                 'value': option.__get__(store, store),
-                }
-                for attr, option in _getoptions(store)
-             ],
-            } for store in self.account_manager.stores
-        ]
+            _setorder(req, stores)
+            self.config.set('account-manager', 'password_store', 
+                            ','.join(stores.get_enabled_store_names()))
+            for store in stores.get_all_stores():
+                for attr, option in _getoptions(store):
+                    newvalue = req.args.get('%s.%s' % (store.__class__.__name__, attr))
+                    self.log.debug("%s.%s: %s" % (store.__class__.__name__, attr, newvalue))
+                    if newvalue is not None:
+                        self.config.set(option.section, option.name, newvalue)
+                        self.config.save()
+        
+        sections = []
+        for store in self.account_manager.stores:
+            options = []
+            for attr, option in _getoptions(store):
+                opt_val = option.__get__(store, store)
+                opt_val = isinstance(opt_val, Component) and \
+                          opt_val.__class__.__name__ or opt_val
+                options.append(
+                            {'label': attr,
+                            'name': '%s.%s' % (store.__class__.__name__, attr),
+                            'value': opt_val,
+                            })
+                continue
+            sections.append(
+                        {'name': store.__class__.__name__,
+                        'classname': store.__class__.__name__,
+                        'order': stores[store],
+                        'options' : options,
+                        })
+            continue
         sections = sorted(sections, key=lambda i: i['name'])
+        req.hdf['numstores'] = range(0, stores.numstores() + 1)
         req.hdf['sections'] = sections
         return 'admin_accountsconfig.cs', None
             
Index: acct_mgr/api.py
===================================================================
--- acct_mgr/api.py	(revision 2186)
+++ acct_mgr/api.py	(working copy)
@@ -10,7 +10,7 @@
 # Author: Matthew Good <trac@matt-good.net>
 
 from trac.core import *
-from trac.config import Option, ExtensionOption
+from trac.config import Option, ExtensionOption, OrderedExtensionsOption
 
 class IPasswordStore(Interface):
     """An interface for Components that provide a storage method for users and
@@ -74,14 +74,17 @@
     provided by the IPasswordStore interface.
 
     The methods will be handled by the underlying password storage
-    implementation set in trac.ini with the "account-manager.password_format"
+    implementation set in trac.ini with the "account-manager.password_store"
     setting.
+
+    The "account-manager.password_store" may be an ordered list of password
+    stores.  if it is a list, then each password store is queried in turn.
     """
 
     implements(IAccountChangeListener)
 
-    _password_store = ExtensionOption('account-manager', 'password_store',
-                                      IPasswordStore)
+    _password_store = OrderedExtensionsOption('account-manager', 'password_store',
+                                              IPasswordStore, include_missing=False)
     _password_format = Option('account-manager', 'password_format')
     stores = ExtensionPoint(IPasswordStore)
     change_listeners = ExtensionPoint(IAccountChangeListener)
@@ -89,31 +92,62 @@
     # Public API
 
     def get_users(self):
-        return self.password_store.get_users()
+        users = []
+        for store in self._password_store:
+            users.extend(store.get_users())
+        return users
 
     def has_user(self, user):
-        return self.password_store.has_user(user)
+        exists = False
+        for store in self._password_store:
+            if store.has_user(user):
+                exists = True
+                break
+            continue
+        return exists
 
     def set_password(self, user, password):
-        if self.password_store.set_password(user, password):
-            self._notify('created', user, password)
+        store = self.find_user_store(user)
+        if store and not hasattr(store, 'set_password'):
+            raise TracError('The authentication backend for the user, %s, '
+                            'does not support setting the password' % user)
+        elif not store:
+            store = self.get_supporting_store('set_password')
+        if store:
+            if store.set_password(user, password):
+                self._notify('created', user, password)
+            else:
+                self._notify('password_changed', user, password)
         else:
-            self._notify('password_changed', user, password)
+            raise TracError('None of the IPasswordStore components listed in '
+                            'the trac.ini support setting the password or '
+                            'creating users')
 
     def check_password(self, user, password):
-        return self.password_store.check_password(user, password)
+        valid = False
+        for store in self._password_store:
+            if store.check_password(user, password):
+                valid = True
+                break
+            continue
+        return valid
 
     def delete_user(self, user):
-        if self.password_store.delete_user(user):
-            self._notify('deleted', user)
+        store = self.find_user_store(user)
+        if hasattr(store, 'delete_user'):
+            if store and store.delete_user(user):
+                self._notify('deleted', user)
 
     def supports(self, operation):
         try:
-            store = self.password_store
+            stores = self.password_store
         except AttributeError:
             return False
         else:
-            return hasattr(store, operation)
+            if self.get_supporting_store(operation):
+                return True
+            else:
+                return False
 
     def password_store(self):
         try:
@@ -126,11 +160,55 @@
                 if config_key is None:
                     continue
                 if config_key() == fmt:
-                    return store
+                    return [store]
             # if the "password_format" is not set re-raise the AttributeError
             raise
     password_store = property(password_store)
 
+    def get_supporting_store(self, operation):
+        """Returns the IPasswordStore that implements the specified operaion
+
+        None is returned if no supporting store can be found
+        """
+        supports = False
+        for store in self.password_store:
+            if hasattr(store, operation):
+                supports = True
+                break
+            continue
+        store = supports and store or None
+        return store
+
+    def get_all_supporting_stores(self, operation):
+        """Returns a list of stores that implement the specified operation"""
+        stores = []
+        for store in self.password_store:
+            if hasattr(store, operation):
+                stores.append(store)
+            continue
+        return stores
+
+    def find_user_store(self, user):
+        """Locates which store contains the user specified.
+
+        If the user isn't found in any IPasswordStore in the chain, None is
+        returned
+        """
+        ignore_auth_case = self.env.config.get('trac', 'ignore_auth_case')
+        user_stores = []
+        for store in self._password_store:
+            userlist = store.get_users()
+            if ignore_auth_case:
+                userlist = [u.lower() for u in userlist]
+            user_stores.append((store, userlist))
+            continue
+        user = ignore_auth_case and user.lower() or user
+        for store in user_stores:
+            if user in store[1]:
+                return store[0]
+            continue
+        return None
+
     def _notify(self, func, *args):
         func = 'user_' + func
         for l in self.change_listeners:
Index: acct_mgr/web_ui.py
===================================================================
--- acct_mgr/web_ui.py	(revision 2186)
+++ acct_mgr/web_ui.py	(working copy)
@@ -30,6 +30,11 @@
     mgr = AccountManager(env)
 
     user = req.args.get('user')
+    name = req.args.get('name')
+    email = req.args.get('email')
+    req.hdf['acctmgr.username'] = user
+    req.hdf['acctmgr.name'] = name
+    req.hdf['acctmgr.email'] = email
     if not user:
         raise TracError('Username cannot be empty.')
 
@@ -77,6 +82,10 @@
                            "VALUES (%s,1,%s,%s)",
                            (user, key, value))
     db.commit()
+    req.hdf.hdf.removeTree('acctmgr.username')
+    req.hdf.hdf.removeTree('acctmgr.name')
+    req.hdf.hdf.removeTree('acctmgr.email')
+    env.log.debug('created user %s' % user)
 
 
 class PasswordResetNotification(NotifyEmail):
@@ -126,7 +135,7 @@
         self._write_check(log=True) 
         
     def _write_check(self, log=False): 
-        writable = AccountManager(self.env).supports('set_password')
+        writable = AccountManager(self.env).get_all_supporting_stores('set_password')
         if not writable and log: 
             self.log.warn('AccountModule is disabled because the password '
                           'store does not support writing.')
@@ -137,11 +146,14 @@
         return 'account'
 
     def get_navigation_items(self, req):
-        if not self._write_check():
+        writable = self._write_check()
+        if not writable:
             return
         if req.authname != 'anonymous':
-            yield 'metanav', 'account', Markup('<a href="%s">My Account</a>',
-                                               (req.href.account()))
+            user_store = AccountManager(self.env).find_user_store(req.authname)
+            if user_store in writable:
+                yield 'metanav', 'account', Markup('<a href="%s">My Account</a>',
+                                                   (req.href.account()))
 
     # IRequestHandler methods
     def match_request(self, req):
@@ -149,12 +161,16 @@
                 and self._write_check(log=True))
 
     def process_request(self, req):
-        if req.path_info == '/account':
+        writable  = self._write_check()
+        user_store = AccountManager(self.env).find_user_store(req.authname)
+        if req.path_info == '/account' and (user_store in writable):
             self._do_account(req)
             return 'account.cs', None
-        elif req.path_info == '/reset_password':
+        elif req.path_info == '/reset_password' and (user_store in writable):
             self._do_reset_password(req)
             return 'reset_password.cs', None
+        else:
+            req.redirect(self.env.href.wiki())
 
     def _do_account(self, req):
         if req.authname == 'anonymous':
Index: acct_mgr/db.py
===================================================================
--- acct_mgr/db.py	(revision 2186)
+++ acct_mgr/db.py	(working copy)
@@ -55,11 +55,13 @@
                        "WHERE authenticated=1 AND name='password' "
                        "AND sid=%s", (hash, user))
         if cursor.rowcount > 0:
+            db.commit()
             return False # updated existing password
         cursor.execute("INSERT INTO session_attribute "
                        "(sid,authenticated,name,value) "
                        "VALUES (%s,1,'password',%s)",
                        (user, hash))
+        db.commit()
         return True
 
     def check_password(self, user, password):
@@ -87,4 +89,5 @@
                        "AND sid=%s", (user,))
         # TODO cursor.rowcount doesn't seem to get # deleted
         # is there another way to get count instead of using has_user?
+        db.commit()
         return True
Index: acct_mgr/templates/admin_accountsconfig.cs
===================================================================
--- acct_mgr/templates/admin_accountsconfig.cs	(revision 2186)
+++ acct_mgr/templates/admin_accountsconfig.cs	(working copy)
@@ -5,8 +5,12 @@
     <fieldset>
         <legend>
             <label>
-                <input type="radio" name="selected" value="<?cs var:section.classname ?>" 
-                       <?cs if:section.selected ?>checked="checked"<?cs /if ?> />
+                <select name="<?cs var:section.classname ?>" >
+                    <?cs each:order = numstores ?>
+                    <option value="<?cs var:order ?>" <?cs if:order == section.order ?>selected<?cs /if 
+                    ?> ><?cs if:order ?><?cs var:order ?><?cs else ?>--<?cs /if ?></option>
+                    <?cs /each ?>
+                </select>
                 <?cs var:section.name ?>
             </label>
         </legend>
Index: acct_mgr/templates/admin_users.cs
===================================================================
--- acct_mgr/templates/admin_users.cs	(revision 2186)
+++ acct_mgr/templates/admin_users.cs	(working copy)
@@ -9,7 +9,7 @@
 
   <legend>Add Account:</legend>
   <div class="field">
-   <label>Username: <input type="text" name="user" class="textwidget" /></label>
+   <label>Username: <input type="text" name="user" class="textwidget"  value="<?cs var:acctmgr.username ?>" /></label>
   </div>
   <div class="field">
    <label>Password: <input type="password" name="password" class="textwidget" /></label>
@@ -18,10 +18,10 @@
    <label>Confirm password: <input type="password" name="password_confirm" class="textwidget" /></label>
   </div>
   <div class="field">
-   <label>Name: <input type="text" name="name" class="textwidget" /></label>
+   <label>Name: <input type="text" name="name" class="textwidget" value="<?cs var:acctmgr.name ?>" /></label>
   </div>
   <div class="field">
-   <label>Email: <input type="text" name="email" class="textwidget" /></label>
+   <label>Email: <input type="text" name="email" class="textwidget" value="<?cs var:acctmgr.email ?>" /></label>
   </div>
   <p class="help">Add a new user account.</p>
   <div class="buttons">
