r5465 - in branches/vmotoska: cumin/bin cumin/bin/test cumin/instance/etc cumin/model/access cumin/model/admin cumin/python/cumin cumin/python/cumin/account cumin/python/cumin/users wooly/bin wooly/python/wooly

vmotoska at fedoraproject.org vmotoska at fedoraproject.org
Tue Sep 11 14:08:46 UTC 2012


Author: vmotoska
Date: 2012-09-11 14:08:44 +0000 (Tue, 11 Sep 2012)
New Revision: 5465

Added:
   branches/vmotoska/cumin/python/cumin/users/
   branches/vmotoska/cumin/python/cumin/users/__init__.py
   branches/vmotoska/cumin/python/cumin/users/main.py
   branches/vmotoska/cumin/python/cumin/users/main.strings
   branches/vmotoska/cumin/python/cumin/users/widgets.py
   branches/vmotoska/cumin/python/cumin/users/widgets.strings
Modified:
   branches/vmotoska/cumin/bin/cumin-web
   branches/vmotoska/cumin/bin/test/cumin-bench
   branches/vmotoska/cumin/instance/etc/cumin.conf
   branches/vmotoska/cumin/model/access/persona.xml
   branches/vmotoska/cumin/model/admin/cumin.xml
   branches/vmotoska/cumin/python/cumin/account/widgets.py
   branches/vmotoska/cumin/python/cumin/admin.py
   branches/vmotoska/cumin/python/cumin/authenticator.py
   branches/vmotoska/cumin/python/cumin/config.py
   branches/vmotoska/cumin/python/cumin/main.py
   branches/vmotoska/cumin/python/cumin/widgets.py
   branches/vmotoska/wooly/bin/wooly-demo
   branches/vmotoska/wooly/python/wooly/demo.py
   branches/vmotoska/wooly/python/wooly/pages.py
Log:
Users module snapshot, http auth in beta state, mobile app start...

Modified: branches/vmotoska/cumin/bin/cumin-web
===================================================================
--- branches/vmotoska/cumin/bin/cumin-web	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/bin/cumin-web	2012-09-11 14:08:44 UTC (rev 5465)
@@ -215,8 +215,8 @@
         set_ldap_configs(cumin, values)
 
         # Not used right now
-        #cumin.auth_create_ondemand = values.auth_create_ondemand
-        #cumin.auth_proxy = values.auth_proxy
+        cumin.auth_create_ondemand = values.auth_create_ondemand
+        cumin.auth_proxy = values.auth_proxy
 
         # Someday we may let this be configurable, for now it will
         # be hardwired

Modified: branches/vmotoska/cumin/bin/test/cumin-bench
===================================================================
--- branches/vmotoska/cumin/bin/test/cumin-bench	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/bin/test/cumin-bench	2012-09-11 14:08:44 UTC (rev 5465)
@@ -4,7 +4,7 @@
 
 from wooly.bench import BenchmarkHarness
 
-from cumin import Cumin
+from cumin.main import Cumin
 from cumin.config import *
 
 def do_main():

Modified: branches/vmotoska/cumin/instance/etc/cumin.conf
===================================================================
--- branches/vmotoska/cumin/instance/etc/cumin.conf	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/instance/etc/cumin.conf	2012-09-11 14:08:44 UTC (rev 5465)
@@ -1,11 +1,18 @@
 [common]
-# database: dbname=cumin user=cumin host=localhost
-# brokers: localhost:5672
-# debug: False
+database: dbname=cumin user=cumin host=localhost
+#rokers: localhost:5672
+brokers: cumin/rasca at 172.22.80.10:5672
+debug: True
+aviary-job-servers: http://172.22.80.10:9090,http://zodiac.sors.local:9090
+aviary-query-servers: http://172.22.80.10:9091,http://zodiac.sors.local:9091
 
 [web]
 # host: localhost
-# host: 0.0.0.0
-user: guest
+host: 0.0.0.0
+user: motto
+persona: default
+auth-proxy: false
+auth-create-ondemand: false
+auth: ldap=ldap://127.0.0.1?dc=test,dc=local?sub?cn=%%s
 
 [data]

Modified: branches/vmotoska/cumin/model/access/persona.xml
===================================================================
--- branches/vmotoska/cumin/model/access/persona.xml	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/model/access/persona.xml	2012-09-11 14:08:44 UTC (rev 5465)
@@ -6,6 +6,7 @@
     <Module name="grid"/>
     <Module name="inventory"/>
     <Module name="usergrid"/>
+    <Module name="users" />
 
     <GroupAccess name="nogroup">
       <MainPage name="login.html"/>
@@ -29,6 +30,7 @@
     <Module name="grid"/>
     <Module name="inventory"/>
     <Module name="usergrid"/>
+    <Module name="users" />
 
     <GroupAccess name="nogroup">
       <MainPage name="login.html"/>

Modified: branches/vmotoska/cumin/model/admin/cumin.xml
===================================================================
--- branches/vmotoska/cumin/model/admin/cumin.xml	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/model/admin/cumin.xml	2012-09-11 14:08:44 UTC (rev 5465)
@@ -7,6 +7,7 @@
     <class name="User">
       <property name="name" type="sstr" index="y"/>
       <property name="password" type="sstr"/>
+      <property name="pin" type="sstr" optional="y"/>
     </class>
 
     <class name="Role">

Modified: branches/vmotoska/cumin/python/cumin/account/widgets.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/account/widgets.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/python/cumin/account/widgets.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -3,6 +3,7 @@
 from wooly import *
 from wooly.widgets import *
 from wooly.resources import *
+from wooly.forms import *
 
 from cumin import *
 from cumin.objecttask import *
@@ -10,6 +11,7 @@
 from cumin.util import *
 
 import main
+import random
 
 from wooly import Session
 
@@ -34,7 +36,76 @@
 
         self.settings = SettingsFrame(app, "main")
         self.add_tab(self.settings)
-        
+
+class MobileSettingsForm(FoldingFieldSubmitForm):
+    def __init__(self, app, name):
+        super(MobileSettingsForm, self).__init__(app, name)
+
+        self.enable_mobile_access = self.MobileEnableBox(app, "mobile_access")
+        self.add_field(self.enable_mobile_access)
+
+        self.mobile_pin_field = self.MobilePinField(app, "mobile_pin")
+        self.mobile_pin_field.input.size = 40
+        self.mobile_pin_field.required = False
+        self.mobile_pin_field.input.disabled = True
+        self.add_field(self.mobile_pin_field)
+
+
+    def render_title(self, session):
+        return "Mobile Settings"
+
+    def render_content(self, session, *args):
+        user = session.client_session.attributes["login_session"].user
+        (pin, msg) = self.app.authenticator.get_pin(user.name)
+        self.mobile_pin_field.input.param.set(session, pin)
+        if pin:
+            self.enable_mobile_access.param.set(session, "yes" )
+        return self.content.render(session, *args)
+
+    def process_submit(self, session):
+        user = session.client_session.attributes["login_session"].user
+        if hasattr(user, "load"):
+            user.load(session.cursor)
+
+        try:
+
+            if self.enable_mobile_access.param.get(session) == "yes":
+                state = "enabled"
+                if not self.mobile_pin_field.input.param.get(session):
+                    val = "".join([ random.choice("".join(map(chr, range(97, 123)))) for i in range(0,10) ])
+                else:
+                    val = self.mobile_pin_field.input.param.get(session)
+
+                (msg, pin ) = self.app.authenticator.update_pin(user.name, val)
+            else:
+                ( msg, pin ) = self.app.authenticator.update_pin(user.name, None )
+                state = "disabled"
+
+        except Exception, e:
+                log.debug("Problem occured during pin setup  %s " % e)
+
+        if not self.errors.get(session):
+            session.add_notice(Notice(preamble="Settings updated", 
+                                      message="Mobile access is now %s" % state,
+                                      capitalize=False))
+            url = self.return_url.get(session)
+            self.page.redirect.set(session, url)
+
+
+    class MobilePinField(StringField):
+         def render_title(self, session):
+             return "Mobile Auth String"
+
+    class MobileEnableBox(TwoOptionRadioField):
+        def render_title(self, session):
+            return "Enable mobile access"
+
+        def render_title_1(self, session):
+            return "Yes"
+
+        def render_title_2(self, session):
+            return "No"
+
 class SettingsFrame(Frame):
     def __init__(self, app, name):
         super(SettingsFrame, self).__init__(app, name)
@@ -42,9 +113,19 @@
         self.change_password_form = ChangePasswordForm(app, "change_password")
         self.app.form_page.modes.add_mode(self.change_password_form)
 
+        my_linkset = LinkSet(app, "settings_liks")
+
         link = self.ChangePasswordLink(app, "change_password")
-        self.add_child(link)
+        my_linkset.add_link(link)
 
+        self.mobile_settings_form = MobileSettingsForm(app, "mobile_settings")
+        self.app.form_page.modes.add_mode(self.mobile_settings_form)
+
+        link2 = self.MobileSettingsLink(app, "mobile_settings")
+        my_linkset.add_link(link2)
+
+        self.add_child(my_linkset)
+
     def render_title(self, session):
         return "Settings"
 
@@ -52,7 +133,7 @@
         def render_href(self, session):
             nsession = wooly.Session(self.app.form_page)
             form = self.frame.change_password_form
-            
+
             form.return_url.set(nsession, session.marshal())
             form.show(nsession)
 
@@ -61,6 +142,19 @@
         def render_content(self, sessino):
             return "Change password"
 
+    class MobileSettingsLink(Link):
+        def render_href(self, session):
+            nsession = wooly.Session(self.app.form_page)
+            form = self.frame.mobile_settings_form
+
+            form.return_url.set(nsession, session.marshal())
+            form.show(nsession)
+
+            return nsession.marshal()
+
+        def render_content(self, session):
+            return "Mobile Settings"
+
 class LoginPage(HtmlPage):
     def __init__(self, app, name):
         super(LoginPage, self).__init__(app, name)
@@ -197,7 +291,7 @@
         # changes, refresh the user object
         if hasattr(user, "load"):
             user.load(session.cursor)
-        
+
         new0 = self.new0.get(session)
         new1 = self.new1.get(session)
 

Modified: branches/vmotoska/cumin/python/cumin/admin.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/admin.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/python/cumin/admin.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -88,6 +88,10 @@
         cls = self.app.model.com_redhat_cumin.Role
         return cls.get_object(cursor, name=name)
 
+    def get_role_by_id(self, cursor, id):
+        cls = self.app.model.com_redhat_cumin.Role
+        return cls.get_object(cursor, _id=id)
+
     def add_role(self, cursor, name):
         cls = self.app.model.com_redhat_cumin.Role
 
@@ -153,7 +157,6 @@
             user_cls.sql_table,
             user_cls._id.sql_column,
             mapping_cls.user.sql_column)
-        #TODO: one column ? 
         cols = [ role_cls.name.sql_column ]
         filt = SqlComparisonFilter(user_cls._id.sql_column, user._id, '=')
         query.add_filter(filt)

Modified: branches/vmotoska/cumin/python/cumin/authenticator.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/authenticator.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/python/cumin/authenticator.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -145,6 +145,7 @@
         if conn:
             filter = self._gen_filter(self.url.filterstr, user)
             try:
+                log.debug("%s", filter)
                 res = conn.search_s(self.url.dn, self.url.scope, filter)
             except Exception, e:
                 msg = str(e)
@@ -390,9 +391,10 @@
     authen_map = {'script': CuminAuthenticatorScript}
 
 class CuminAuthenticator(object):
-    def __init__(self, app, log_authentication=True):
+    def __init__(self, app, log_authentication=True, autocreate=False):
         self.authenticators=[]
         self.app = app
+        self.autocreate = autocreate
         _syslog.log_auth = log_authentication
         log.info("Initializing %s", self)
         if not have_ldap:
@@ -502,14 +504,14 @@
         _syslog.log(msg)
         return user, res
 
-    def find_user(self, username):
+    def find_user(self, username, ignore_external=False):
         # Like authenticate, but find_user only confirms the
         # existence of a user.  We are not concerned with password here.
         log.debug("Authenticator: calling find_user")
         cursor = self.app.database.get_read_cursor()
         cls = self.app.model.com_redhat_cumin.User
         user = cls.get_object(cursor, name=username)
-        res = user and len(user.password) > 0
+        res = user and ( len(user.password) > 0 or ignore_external )
         if not res:
             # Try to find the user externally
             log.debug("Authenticator: finding external user")
@@ -522,6 +524,66 @@
                     break
         return user, res
 
+    def create_external_user(self, username):
+        # after propper testing remove ...
+        if not self.autocreate:
+            return False
+
+        log.debug("Authenticator: creating external user %s", username)
+        conn = self.app.database.get_connection()
+        try:
+            curs = conn.cursor()
+            cls = self.app.model.com_redhat_cumin.User
+            found = cls.get_object(curs, name=username)
+            if found:
+                log.error("Attempt to create external user that exists")
+                return False
+            usr = cls.create_object(curs)
+            usr.name = username
+            usr.password = ""
+            usr.pin = ""
+            usr.fake_qmf_values()
+            usr.save(curs)
+            conn.commit()
+
+        except Exception ,e:
+            log.error("%s", e)
+            log.error("Unable to add ondemand user")
+        finally:
+            conn.close()
+        return True
+
+    def update_pin(self, username, pin):
+        conn =  self.app.database.get_connection()
+        try:
+            cur = conn.cursor()
+            cls = self.app.model.com_redhat_cumin.User
+            user = cls.get_object(cur, name=username)
+            if user is None:
+                message = "Error locationg user %s " % username
+            else:
+                message = ""
+                user.pin = pin
+                user.save(cur)
+                conn.commit()
+        finally:
+            conn.close()
+        return pin, message
+
+    def get_pin(self, username):
+        cursor = self.app.database.get_read_cursor()
+        cls = self.app.model.com_redhat_cumin.User
+        user = cls.get_object(cursor, name=username)
+        if user is None:
+            message = "Error locationg user %s " % username
+            pin = ""
+        else:
+            message = ""
+            pin = user.pin
+        return pin, message
+
+
+
     def update_password(self, username, oldpassword, newpassword):
         status = False
         message = ""

Modified: branches/vmotoska/cumin/python/cumin/config.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/config.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/python/cumin/config.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -178,9 +178,12 @@
         param = ConfigParameter(self, "authorize", bool)
         param.default = False
 
-#        param = ConfigParameter(self, "auth-proxy", bool)
-#        param.default = False
+        param = ConfigParameter(self, "auth-proxy", bool)
+        param.default = False
 
+        param = ConfigParameter(self, "auth-create-ondemand", bool)
+        param.default = False
+
         param = ConfigParameter(self, "wallaby-broker", str)
         param.default = ""
 

Modified: branches/vmotoska/cumin/python/cumin/main.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/main.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/python/cumin/main.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -162,7 +162,8 @@
             try:
                 m = __import__(name, globals())
                 m.Module(self, name)
-            except ImportError:
+            except Exception,e:
+                log.debug("Failed to load module %s (%s)", name, e)
                 pass
             except Exception, e:
                 import traceback
@@ -174,10 +175,9 @@
 
     def init(self, schema_version_check=True):
         log.info("Initializing %s", self)
-
         # Do this initialization as late as possible so that
         # the application can set config values.
-        self.authenticator = CuminAuthenticator(self)
+        self.authenticator = CuminAuthenticator(self, autocreate=self.auth_create_ondemand)
         self.authorizator = CuminAuthorizator(self, self.access_path, self.do_authorize)
         try:
             self.authorizator.set_persona(self.persona)
@@ -351,7 +351,7 @@
         self.main = main_view
         self.add_mode(self.main)
         self.set_default_frame(self.main)
-        self.cumin_module = ["messaging", "grid"]
+        self.cumin_module = ["messaging", "grid" , "users" ]
 
         self.page_html_class = "Cumin"
 
@@ -556,6 +556,7 @@
                                      "is not")
         self.adapter.query.add_filter(filter)
 
+
 class TopSubmissionTable(TopTable):
     def __init__(self, app, name):
         cls = app.model.com_redhat_grid.Submission

Added: branches/vmotoska/cumin/python/cumin/users/__init__.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/users/__init__.py	                        (rev 0)
+++ branches/vmotoska/cumin/python/cumin/users/__init__.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -0,0 +1 @@
+from main import *

Added: branches/vmotoska/cumin/python/cumin/users/main.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/users/main.py	                        (rev 0)
+++ branches/vmotoska/cumin/python/cumin/users/main.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -0,0 +1,58 @@
+from cumin.main import CuminModule
+from cumin.util import *
+
+from widgets import *
+
+strings = StringCatalog(__file__)
+
+class Module(CuminModule):
+    def __init__(self, app, name):
+        super(Module, self).__init__(app, name)
+        self.frame = UsersMainFrame(app, "users")
+        self.frame.cumin_module = name
+
+    def init(self):
+        self.app.main_page.main.users = self.frame
+        self.app.main_page.main.add_tab(self.frame)
+
+
+class UsersMainFrame(CuminFrame):
+    def __init__(self, app, name):
+        super(UsersMainFrame, self).__init__(app, name)
+
+        self.view = UsersMainView(app, "view")
+        self.add_mode(self.view)
+
+        self.userdetail = UserDetailFrame(app, "userdetail")
+        self.add_mode(self.userdetail)
+
+        self.addform = AddUserForm(app, "addform")
+        self.app.form_page.modes.add_mode(self.addform)
+
+    def init(self):
+        super(UsersMainFrame, self).init()
+
+    def render_title(self, session):
+        return "Users"
+
+class UsersMainView(Widget):
+    def __init__(self, app, name):
+        super(UsersMainView, self).__init__(app, name)
+
+        heading = self.Heading(app, "heading")
+        self.add_child(heading)
+
+        self.tabs = TabbedModeSet(app, "tabs")
+        self.add_child(self.tabs)
+
+        self.tabs.add_tab(UsersSelector(app, "users"))
+        self.tabs.add_tab(RolesSelector(app, "roles"))
+
+    class Heading(CuminHeading):
+        def render_title(self, session):
+            return "Users"
+
+        def render_icon_href(self, session):
+            return "resource?name=client-36.png"
+
+

Added: branches/vmotoska/cumin/python/cumin/users/main.strings
===================================================================
Added: branches/vmotoska/cumin/python/cumin/users/widgets.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/users/widgets.py	                        (rev 0)
+++ branches/vmotoska/cumin/python/cumin/users/widgets.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -0,0 +1,305 @@
+from wooly.widgets import *
+from cumin.widgets import *
+from crypt import crypt
+from random import sample
+
+from cumin.objectselector import ObjectSelector, ObjectLinkColumn, ObjectTable, ObjectTableColumn
+from cumin.objectframe import ObjectFrame
+
+from cumin.sqladapter import ObjectSqlAdapter
+
+strings = StringCatalog(__file__)
+log = logging.getLogger("cumin.users.widgets") 
+
+
+
+class UsernameSearchColumn(ObjectLinkColumn):
+    def __init__(self, app, name, attr, idx, frame):
+        super(UsernameSearchColumn, self).__init__(app, name, attr, idx, frame)
+        self.attr.title = "Login"
+
+class UserRoleAssignmentColumn(ObjectTableColumn):
+    def __init__(self, app, name, attr):
+        super(UserRoleAssignmentColumn, self).__init__(app, name, attr)
+        self.attr.title = "Roles"
+
+class BooleanUserColumn(ObjectTableColumn):
+    def __init__(self, app, name, attr):
+        super(BooleanUserColumn, self).__init__(app, name, attr)
+        self.attr.invert = False
+
+    def render_cell_content(self, session, record):
+        if self.field.get_content(session, record):
+            return True and not self.attr.invert
+        else:
+            return False or self.attr.invert
+
+class ExternalUserColumn(BooleanUserColumn):
+    def __init__(self, app, name, attr):
+        super(ExternalUserColumn, self).__init__(app, name, attr)
+        self.attr.title = "External User"
+        self.attr.invert = True
+
+class MobileUserColumn(BooleanUserColumn):
+    def __init__(self, app, name, attr):
+        super(MobileUserColumn, self).__init__(app, name, attr)
+        self.attr.title = "Mobile Access"
+
+class UserDataAdapter(ObjectSqlAdapter):
+    def __init__(self, app):
+        # TODO: other way to do this ? 
+        role_cls = app.model.com_redhat_cumin.Role
+        cls = app.model.com_redhat_cumin.UserRoleMapping
+        user_cls = app.model.com_redhat_cumin.User
+
+        super(UserDataAdapter, self).__init__(app, cls)
+
+        self.add_join(user_cls, cls.user , user_cls._id) 
+        self.add_join(role_cls, cls.role, role_cls._id)
+    # for postgresql 8.4+ array_agg ? 
+    # is support for  8.4 < needed ? 
+    def get_data(self, values, options):
+        if options.limit:
+            opts_limit = options.limit
+        else:
+            opts_limit = None
+
+        if options.offset:
+            opts_offset = options.offset
+        else:
+            opts_offset = 0
+
+        options.limit = 100000
+        options.offset = 0
+        data = super(UserDataAdapter, self).get_data(values, options)
+        res = []
+        if len(data) > 0:
+            for userrow in data:
+                user_record = list(userrow)
+                tmp_res = [user_record[0],user_record[1],user_record[2],user_record[3],user_record[4],'']
+                added = False
+                for i,r in enumerate(res):
+                    if r[1] == user_record[1]:
+                        groups = res[i][3]
+                        res[i][3] = "%s,%s" % ( groups, user_record[3])
+                        added = True
+                        break
+
+                if not added:
+                    res.append(tmp_res)
+
+        last = len(res)
+        if opts_limit:
+            last =  opts_offset + opts_limit
+
+        return res[opts_offset:last]
+
+    def get_count(self, values):
+        options = DataAdapterOptions()
+        options.limit = 100000
+        options.offset = 0
+        return len(self.get_data(values,options))
+
+
+class UsersRemove(ObjectSelectorTask):
+    def get_title(self, session):
+        return "Remove"
+
+    def do_exit(self, session):
+        self.app.main_page.main.users.view.show(session)
+
+
+class UsersSelector(ObjectSelector):
+    def __init__(self, app, name):
+        cls = app.model.com_redhat_cumin.UserRoleMapping
+        role_cls = app.model.com_redhat_cumin.Role
+        user_cls = app.model.com_redhat_cumin.User
+
+        super(UsersSelector, self).__init__(app, name, cls)
+        self.table.adapter = UserDataAdapter(app)
+        frame = "main.users.userdetail"
+        col = UsernameSearchColumn(app, "name", user_cls.name, user_cls._id, frame)
+
+        ext_col = ExternalUserColumn(app, "external", user_cls.password ) 
+        mob_col = MobileUserColumn(app, "mobile", user_cls.pin)
+        rol_col = UserRoleAssignmentColumn(app, "roles",role_cls.name) 
+        self.add_column(col)
+        self.add_column(rol_col)
+        self.add_column(ext_col)
+        self.add_column(mob_col)
+        self.add_search_filter(col)
+        self.remove = UsersRemove(app, self)
+
+        self.links.add_child(AddUserLink(app, "adduser"))
+
+    def create_table(self, app, name, cls):
+        return UsersTable(app, name, cls)
+
+    def render_title(self, session):
+        return "Users"
+
+class UsersTable(ObjectSelectorTable):
+    def __init__(self, app, name, cls):
+        super(UsersTable, self).__init__(app, name, cls)
+
+
+class UserDetailFrame(ObjectFrame):
+    def __init__(self, app, name):
+        cls = app.model.com_redhat_cumin.User
+        super(UserDetailFrame, self).__init__(app, name, cls)
+        self.icon_href = "resource?name=client-36.png"
+
+class AddUserLink(Link):
+    def __init__(self, app, name):
+        super(AddUserLink, self).__init__(app, name)
+        self.form = AddUserForm(app, "addform")
+
+    def render_href(self, session):
+        ns = wooly.Session(self.app.form_page)
+        form = self.frame.addform
+        form.return_url.set(ns, session.marshal())
+        form.show(ns)
+        return ns.marshal()
+
+    def render_content(self, session):
+        return "Add User"
+
+class AddUserForm(FoldingFieldSubmitForm):
+    def __init__(self, app, name):
+        super(AddUserForm, self).__init__(app, name)
+
+        self.login_field = AddLoginField(app, "login_field")
+        self.add_field(self.login_field)
+
+        self.pass_field = AddPasswordField(app, "pass_field")
+        self.add_field(self.pass_field)
+
+        self.group_select  = AddGroupSelectField(app, "group_field")
+        self.add_field(self.group_select)
+
+    def render_title(self, session):
+        return "Add User"
+
+    def process_submit(self, session):
+        self.validate(session)
+
+        passw = self.pass_field.input.param.get(session)
+        if len(passw) > 0:
+            crypted =   crypt(passw, "".join(sample("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2)))
+        else:
+            crypted = ""
+
+        login = self.login_field.input.param.get(session)
+        groups_ids = self.group_select.input.param.get(session)
+        try:
+            user_obj = self.app.admin.add_user(session.cursor, login, crypted)
+            for g in groups_ids:
+                group_obj = self.app.admin.get_role_by_id(session.cursor, g)
+                self.app.admin.add_assignment(session.cursor, user_obj, group_obj)
+        except Exception,e:
+            log.error("Problem adding user %s : %s",login, e)
+            err = FormError("Problem adding user, Please see the log file for details");
+            self.errors.append(err)
+
+
+        if not self.errors.get(session):
+            session.add_notice(Notice(preamble="User %s added" % login ,
+                                       message="OK",
+                                      capitalize=False))
+            url = self.return_url.get(session)
+            self.page.redirect.set(session, url)
+
+class AddLoginField(StringField):
+    def render_title(self, session):
+        return "Login"
+
+    def validate(self, session):
+        err = ""
+        login = self.input.param.get(session)
+        if len(login) < 3:
+            err = "Login must be longer than 3 characters."
+
+        cls = self.app.model.com_redhat_cumin.User
+        db_user = cls.get_object(session.cursor, name=login)
+
+        if db_user:
+            err = "User with login %s already exists." % login
+
+        if err:
+            errform = FormError(err)
+            self.form.errors.add(session ,errform)
+
+class AddPasswordField(StringField):
+    def render_title(self, session):
+        return "Password"
+
+    def render_help(self, session):
+        return "For external user leave password blank"
+
+    def validate(self, session):
+        passw = self.input.param.get(session)
+        if len(passw) > 0 and len(passw) < 5:
+            err = FormError("Password length should be at least 5 characters")
+            self.form.errors.add(err)
+
+class AddGroupSelectField(ScalarField):
+    def __init__(self, app, name):
+        super(AddGroupSelectField, self).__init__(app, name, None)
+
+        param = StringParameter(app, "param")
+        self.param = ListParameter(app, "param", param)
+        self.add_parameter(self.param)
+
+        self.input = self.GroupOptions(app, "input", self.param)
+        self.add_child(self.input)
+
+    def get(self, session):
+        return self.input.param.get(session)
+
+    def validate(self, session):
+        super(AddGroupSelectField, self).validate(session)
+
+        roles = self.input.param.get(session)
+        if not roles or len(roles) == 0:
+            error = FormError("No role selected")
+            self.form.errors.add(session, error)
+
+    def render_title(self, session):
+        return "Role"
+
+    class GroupOptions(OptionInputSet):
+        def get_items(self, session):
+            return self.do_get_items(session)
+
+        def do_get_items(self, session):
+            cls = self.app.model.com_redhat_cumin.Role
+            roles = cls.get_selection(session.cursor)
+            return roles
+
+        def render_disabled_attr(self, session):
+            # hack for multiple select
+            return "multiple=\"multiple\""
+
+        def render_item_value(self, session, item):
+            return item._id
+
+        def render_item_content(self, session, item):
+            return item.name
+
+        def render_item_selected_attr(self,  session, item):
+            # TODO: str 
+            if str(item._id) in self.param.get(session):
+                return "selected=\"selected\""
+
+class RolesFrame(ObjectFrame):
+    def __init__(self, app, name):
+        cls = app.model.com_redhat_cumin.Role
+        super(RolesFrame, self).__init__(app, name, cls)
+
+class RolesSelector(ObjectSelector):
+    def __init__(self, app, name):
+        cls = app.model.com_redhat_cumin.Role
+
+        super(RolesSelector, self).__init__(app, name, cls)
+        self.add_attribute_column(cls.name)
+

Added: branches/vmotoska/cumin/python/cumin/users/widgets.strings
===================================================================
Modified: branches/vmotoska/cumin/python/cumin/widgets.py
===================================================================
--- branches/vmotoska/cumin/python/cumin/widgets.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/cumin/python/cumin/widgets.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -1324,11 +1324,12 @@
             if self.app.auth_proxy:
                 try:
                     username = session.request_environment['HTTP_REMOTE_USER']
+                    log.debug("Proxy auth user %s", username)
                 except KeyError:
                     log.debug("Proxy auth enabled but no remote user set")
 
             if username:
-                user, ok = self.app.authenticator.find_user(username)
+                user, ok = self.app.authenticator.find_user(username, ignore_external= ( self.app.auth_create_ondemand or self.app.auth_proxy ) )
                 if not ok:
                     # We couldn't find the user, internally or externally
                     if not self.app.auth_proxy:
@@ -1337,14 +1338,17 @@
                     else:
                         log.info("User %s not found in db, "\
                                      "using auth proxy", username )
-                        #Hmmm, what is users here?  For now just let it return
-                        # to the login page
-                        return False
+                        if self.app.auth_create_ondemand:
+                            log.info("Creating user ondemand %s", username)
+                            if not self.app.authenticator.create_external_user(username):
+                                return False
+                            else:
+                                user, ok = self.app.authenticator.find_user(username, ignore_external=True)
+                                if not ok:
+                                    return False
+                        else:
+                            return False
 
-#TODO prehodit do authenticatora
-# ondemand -> authenticator.create_user
-# user -> authenticator.force_login
-
                 # Check for valid group
                 if self.app.authorizator.is_enforcing():
                     if not user:

Modified: branches/vmotoska/wooly/bin/wooly-demo
===================================================================
--- branches/vmotoska/wooly/bin/wooly-demo	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/wooly/bin/wooly-demo	2012-09-11 14:08:44 UTC (rev 5465)
@@ -2,6 +2,7 @@
 
 import sys
 import os
+from time import sleep
 
 from wooly.demo import *
 

Modified: branches/vmotoska/wooly/python/wooly/demo.py
===================================================================
--- branches/vmotoska/wooly/python/wooly/demo.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/wooly/python/wooly/demo.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -4,6 +4,7 @@
 from util import *
 from widgets import *
 from wooly import Application
+from time import sleep
 
 strings = StringCatalog(__file__)
 
@@ -26,12 +27,17 @@
 
         self.add_resource_dir(os.path.join(self.home, "resources"))
 
+        self.force_html_doctype = False
+
     def start(self):
         self.model.start()
 
     def stop(self):
         self.model.stop()
 
+    def authorize_cb(self, s, a):
+        return True
+
 class DemoModel(object):
     def __init__(self, app):
         super(DemoModel, self).__init__()

Modified: branches/vmotoska/wooly/python/wooly/pages.py
===================================================================
--- branches/vmotoska/wooly/python/wooly/pages.py	2012-09-11 14:06:56 UTC (rev 5464)
+++ branches/vmotoska/wooly/python/wooly/pages.py	2012-09-11 14:08:44 UTC (rev 5465)
@@ -474,3 +474,10 @@
     def do_render(self, session, *args):
         csv = self.render_content(session, *args)
         return csv and csv or " "
+
+class JSONPage(WidgetPage):
+    def get_content_type(self, session):
+        return "application/json"
+
+    def do_render(slef, session, *args):
+        return " "



More information about the cumin-developers mailing list