Index: ow/models/root.py
===================================================================
--- ow/models/root.py	(revision 39b14977ea6c9734e86296a94d7560ff9591a1c9)
+++ ow/models/root.py	(revision 1d92bf2b47c1a3bf1482a589cdd6cc7ec38d552f)
@@ -3,9 +3,16 @@
 from repoze.folder import Folder
 from repoze.catalog.indexes.field import CatalogFieldIndex
+from repoze.catalog.query import Eq
 
 from pyramid.security import Allow, Everyone
 
 from ow.models.user import User
-from ow.catalog import get_catalog
+from ow.catalog import (
+    get_catalog,
+    install_catalog,
+    reindex_object,
+    remove_from_catalog,
+    resources_from_query_results
+)
 
 
@@ -14,4 +21,7 @@
     Root object, contains basically all the users, and in turn
     the users contain their workouts.
+
+    Users are stored in a dict-like structure, using a string containing
+    the user id (uid) as a key, and the User object as the value.
     """
 
@@ -20,32 +30,85 @@
     __acl__ = [
                (Allow, Everyone, 'view'),
-               (Allow, 'group:admins', 'edit')
+               (Allow, 'admins', 'edit')
               ]
+
+    def __init__(self, **kw):
+        install_catalog(self)
+        super(OpenWorkouts, self).__init__(**kw)
 
     def _get_catalog_indexes(self):
         indexes = {
+            'email': CatalogFieldIndex('email'),
             'sport': CatalogFieldIndex('sport'),
         }
         return indexes
 
-    def all_usernames(self):
+    def reindex(self, obj):
         """
-        Return all available usernames
+        Reindex the given object in the catalog
         """
-        return self.keys()
+        reindex_object(self.catalog, obj)
 
-    def lowercase_usernames(self):
+    def query(self, query):
         """
-        Return all available usernames in lower case. Useful for
-        username uniqueness validation on signup
+        Execute the given query on the catalog, returning the results
+        (generator with events found or empty list if no results were found)
         """
-        return [name.lower() for name in self.keys()]
+        catalog = get_catalog(self)
+        number, results = catalog.query(query)
+        if number:
+            return resources_from_query_results(catalog, results, self)
+        return []
 
+    def add_user(self, user):
+        self.add(str(user.uid), user)
+        self.reindex(user)
+
+    def del_user(self, user):
+        remove_from_catalog(self.catalog, user)
+        self.remove(str(user.uid))
+
+    def get_user_by_uid(self, uid):
+        return self.get(str(uid), None)
+
+    def get_user_by_email(self, email):
+        if email is not None:
+            # for some reason, when searching for None
+            # the catalog will return all users
+            res = self.query(Eq('email', email))
+            if res:
+                return next(res)
+        return None
+
+    @property
+    def users(self):
+        """
+        Return all user objects
+        """
+        return [user for user in self.values() if isinstance(user, User)]
+
+    @property
+    def all_nicknames(self):
+        """
+        Return all available nicknames
+        """
+        return [user.nickname for user in self.users if user.nickname]
+
+    @property
+    def lowercase_nicknames(self):
+        """
+        Return all available nicknames in lower case. Useful for
+        nickname uniqueness validation on signup
+        """
+        return [nick.lower() for nick in self.all_nicknames]
+
+    @property
     def emails(self):
         """
         Return all emails currently in use by users
         """
-        return [u.email for u in self.users()]
+        return [user.email for user in self.users]
 
+    @property
     def lowercase_emails(self):
         """
@@ -54,23 +117,9 @@
         against the currently used addresses
         """
-        return [u.email.lower() for u in self.users()]
-
-    def users(self):
-        """
-        Return all user objects
-        """
-        return [u for u in self.values() if isinstance(u, User)]
-
-    def get_user(self, uid):
-        return self.get(uid, None)
-
-    def add_user(self, uid, **kw):
-        u = User(**kw)
-        self[uid] = u
+        return [email.lower() for email in self.emails]
 
     @property
     def sports(self):
-        catalog = get_catalog(self)
-        return [s for s in catalog['sport']._fwd_index]
+        return [s for s in self.catalog['sport']._fwd_index]
 
     @property
