[rhmessaging-commits] rhmessaging commits: r1727 - in mgmt: cumin/python/cumin and 2 other directories.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Tue Feb 26 11:42:17 EST 2008


Author: justi9
Date: 2008-02-26 11:42:17 -0500 (Tue, 26 Feb 2008)
New Revision: 1727

Added:
   mgmt/cumin/bin/cumin-admin
Removed:
   mgmt/cumin/bin/cumin-database
Modified:
   mgmt/cumin/bin/cumin
   mgmt/cumin/python/cumin/__init__.py
   mgmt/cumin/python/cumin/page.py
   mgmt/cumin/python/cumin/page.strings
   mgmt/cumin/python/wooly/__init__.py
   mgmt/cumin/python/wooly/server.py
   mgmt/notes/justin-todo.txt
Log:
Adds user auth to cumin.

Introduces a CuminServer class that performs the authorization.

Replaces cumin-database with a new tool, cumin-admin, that now does
both schema operations and adds and removes users.

Restores the current user UI (for real this time) and implements log
out.



Modified: mgmt/cumin/bin/cumin
===================================================================
--- mgmt/cumin/bin/cumin	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/bin/cumin	2008-02-26 16:42:17 UTC (rev 1727)
@@ -1,7 +1,6 @@
 #!/usr/bin/env python
 
-import sys, os
-from wooly.server import WebServer
+import sys, os, socket
 
 from cumin import *
 from cumin.util import *
@@ -33,12 +32,11 @@
 
     app.init()
 
-    server = WebServer(app, port)
+    host = socket.gethostname()
+    server = CuminServer(app, host, port)
 
     try:
         server.start()
-    except KeyboardInterrupt:
-        server.stop()
     except:
         server.stop()
         raise
@@ -70,4 +68,7 @@
     do_main(home, data, port, debug)
 
 if __name__ == "__main__":
-    main()
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass

Added: mgmt/cumin/bin/cumin-admin
===================================================================
--- mgmt/cumin/bin/cumin-admin	                        (rev 0)
+++ mgmt/cumin/bin/cumin-admin	2008-02-26 16:42:17 UTC (rev 1727)
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+
+import sys, os
+from sqlobject import connectionForURI
+from traceback import print_exc
+from getpass import getpass
+from random import sample
+from crypt import crypt
+from mint import MintDatabase, ConsoleUser
+
+from cumin.util import *
+
+def usage():
+    print """Usage: cumin-admin [OPTIONS...] COMMAND
+Options:
+    -h, --help            Print this message
+    --data URL            Connect to database at URL
+                          (default postgesql://cumin@localhost/cumin)
+    --force yes           Don't complain and just do it
+Commands:
+    create-schema         Create the database schema
+    drop-schema           Drop the database schema; requires "--force yes"
+
+    add-user NAME         Add user called NAME
+    remove-user NAME      Remove user called NAME; requires "--force yes"
+    list-users            List existing users
+"""
+    sys.exit(1)
+
+def parse_command_args():
+    args = list()
+    parg = ""
+
+    for arg in sys.argv[1:]:
+        if not arg.startswith("--") and not parg.startswith("--"):
+            args.append(arg)
+
+        parg = arg
+
+    return args
+
+def main():
+    if "-h" in sys.argv or "--help" in sys.argv:
+        usage()
+
+    home = os.environ.get("CUMIN_HOME")
+
+    if not home:
+        home = os.path.normpath("/usr/share/cumin")
+
+    config = Config()
+    config.add_param("data", "s", "postgresql://cumin@localhost/cumin")
+    config.add_param("force", "b", False)
+
+    config.load_file(os.path.join(home, "etc", "cumin.conf"))
+    config.load_file(os.path.join(os.path.expanduser("~"), ".cumin.conf"))
+    config.load_args(sys.argv)
+
+    config.prt()
+
+    home = os.environ["CUMIN_HOME"]
+    data = config.get("data")
+    force = config.get("force")
+
+    args = parse_command_args()
+    
+    if not args:
+        print "Error: no command found"
+        usage()
+
+    command = args[0]
+
+    database = MintDatabase(data)
+    database.check()
+    database.init()
+
+    if command == "create-schema":
+        main = os.path.join(home, "sql", "schema.sql")
+        indexes = os.path.join(home, "sql", "indexes.sql")
+
+        database.createSchema((main, indexes))
+    elif command == "drop-schema":
+        if force:
+            database.dropSchema()
+        else:
+            print "Error: command create-schema requires --force yes"
+            usage()
+    elif command == "add-user":
+        if len(args) != 2:
+            print "Error: no user name given"
+            usage()
+
+        password = getpass()
+
+        chs = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+        ch0, ch1 = sample(chs, 2)
+
+        user = ConsoleUser()
+        user.name = args[1]
+        user.password = crypt(password, ch0 + ch1)
+        user.syncUpdate()
+    elif command == "remove-user":
+        if force:
+            if len(args) != 2:
+                print "Error: no user name given"
+                usage()
+
+            accounts = ConsoleUser.selectBy(name=args[1])
+            
+            if accounts.count():
+                for account in accounts:
+                    account.destroySelf()
+                    return
+            else:
+                print "Error: no such user '%s'" % args[1]
+        else:
+            print "Error: command remove-user requires --force yes"
+            usage()
+
+    elif command == "list-users":
+        accounts = ConsoleUser.select(orderBy='name')
+
+        for account in accounts:
+            print "%4i %s" % (account.id, account.name)
+
+        count = accounts.count()
+        print "(%i user%s found)" % (count, ess(count))
+    else:
+        print "Error: command '%s' not recognized" % command
+        usage()
+
+if __name__ == "__main__":
+    try:
+        main()
+    except SystemExit, e:
+        raise e
+    except:
+        print_exc()
+        sys.exit(1)


Property changes on: mgmt/cumin/bin/cumin-admin
___________________________________________________________________
Name: svn:executable
   + *

Deleted: mgmt/cumin/bin/cumin-database
===================================================================
--- mgmt/cumin/bin/cumin-database	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/bin/cumin-database	2008-02-26 16:42:17 UTC (rev 1727)
@@ -1,90 +0,0 @@
-#!/usr/bin/env python
-
-import sys, os
-from sqlobject import connectionForURI
-from traceback import print_exc
-from mint import MintDatabase
-
-from cumin.util import *
-
-def usage():
-    print """Usage: cumin-database [OPTIONS...] COMMAND
-Options:
-    -h, --help            Print this message
-    --data URL            Connect to database at URL
-                          (default postgesql://cumin@localhost/cumin)
-    --force yes           Don't complain and just do it
-Commands:
-    create-schema         Create the database schema; requires --force
-    drop-schema           Drop the database schema; requires --force
-"""
-    sys.exit(1)
-
-def parse_command():
-    parg = ""
-
-    for arg in sys.argv[1:]:
-        if not arg.startswith("--") and not parg.startswith("--"):
-            return arg
-
-        parg = arg
-
-def main():
-    if "-h" in sys.argv or "--help" in sys.argv:
-        usage()
-
-    home = os.environ.get("CUMIN_HOME")
-
-    if not home:
-        home = os.path.normpath("/usr/share/cumin")
-
-    config = Config()
-    config.add_param("data", "s", "postgresql://cumin@localhost/cumin")
-    config.add_param("force", "b", False)
-
-    config.load_file(os.path.join(home, "etc", "cumin.conf"))
-    config.load_file(os.path.join(os.path.expanduser("~"), ".cumin.conf"))
-    config.load_args(sys.argv)
-
-    config.prt()
-
-    home = os.environ["CUMIN_HOME"]
-    data = config.get("data")
-    force = config.get("force")
-
-    command = parse_command()
-    
-    if command is None:
-        print "Error: no command found"
-        usage()
-
-    database = MintDatabase(data)
-    database.checkConnection()
-
-    if command == "create-schema":
-        if force:
-            main = os.path.join(home, "sql", "schema.sql")
-            indexes = os.path.join(home, "sql", "indexes.sql")
-
-            database.createSchema((main, indexes))
-        else:
-            print "Command create-schema requires --force yes"
-            sys.exit(1)
-    elif command == "drop-schema":
-        if force:
-            database.dropSchema()
-        else:
-            print "Command create-schema requires --force yes"
-            sys.exit(1)
-    else:
-        print "Error: command '%s' not recognized" % command
-        usage()
-
-if __name__ == "__main__":
-    try:
-        main()
-    except SystemExit, e:
-        raise e
-    except:
-        print_exc()
-        sys.exit(1)

Modified: mgmt/cumin/python/cumin/__init__.py
===================================================================
--- mgmt/cumin/python/cumin/__init__.py	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/python/cumin/__init__.py	2008-02-26 16:42:17 UTC (rev 1727)
@@ -1,4 +1,4 @@
-import sys, os, socket
+import sys, os
 
 from random import randint
 from wooly import Application, Session, Page
@@ -10,6 +10,8 @@
 from time import sleep
 from threading import Thread, Event
 from traceback import print_exc
+from base64 import decodestring
+from crypt import crypt
 
 from model import CuminModel, ModelPage
 from demo import DemoData
@@ -90,3 +92,35 @@
                         reg.connect(self.model.data)
 
             self.event.wait(10)
+
+class CuminServer(WebServer):
+    def authorized(self, session):
+        name = session.credentials.get("name")
+        password = session.credentials.get("password")
+
+        if name:
+            try:
+                user = ConsoleUser.selectBy(name=name)[0]
+            except IndexError:
+                return False
+
+            if user:
+                crypted = user.password
+
+                if crypted and crypt(password, crypted) == crypted:
+                    lch = user.lastChallenged
+                    
+                    if lch:
+                        timeout = timedelta(seconds=3600)
+                        now = datetime.now()
+
+                        if now - lch < timeout:
+                            lout = user.lastLoggedOut
+
+                            if lout is None or lout < lch:
+                                return True
+
+            user.lastChallenged = datetime.now()
+            user.syncUpdate()
+
+        return False

Modified: mgmt/cumin/python/cumin/page.py
===================================================================
--- mgmt/cumin/python/cumin/page.py	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/python/cumin/page.py	2008-02-26 16:42:17 UTC (rev 1727)
@@ -1,6 +1,7 @@
 from wooly import *
 from wooly.widgets import *
 from wooly.resources import *
+from time import sleep
 
 from broker import *
 from brokergroup import *
@@ -58,6 +59,9 @@
     def __init__(self, app, name):
         super(MainFrame, self).__init__(app, name)
 
+        self.__logout = BooleanParameter(app, "logout")
+        self.add_parameter(self.__logout)
+
         self.__frame_tmpl = Template(self, "frame_html")
 
         self.__tabs = MainFrameTabs(app, "tabs")
@@ -95,6 +99,14 @@
     def get_title(self, session, object):
         return "Main"
 
+    def render_user_name(self, session, object):
+        return session.credentials.get("name")
+
+    def render_logout_href(self, session, object):
+        branch = session.branch()
+        self.__logout.set(branch, True)
+        return branch.marshal()
+
     def render_frames(self, session, object):
         self.__object.set(session, object)
         writer = Writer()
@@ -163,6 +175,31 @@
         frame.set_object(session, system)
         return self.page().set_current_frame(session, frame)
 
+    def do_process(self, session, object):
+        if self.__logout.get(session):
+            self.__logout.set(session, False)
+
+            name = session.credentials.get("name")
+
+            try:
+                user = ConsoleUser.selectBy(name=name)[0]
+            except IndexError:
+                pass
+
+            if user:
+                user.lastLoggedOut = datetime.now()
+                user.syncUpdate()
+
+                # XXX boy, this sucks.  necessary because the
+                # resolution of TimestampCol (lastLoggedOut) is too
+                # coarse for the subsequent comparison of
+                # lastLoggedOut and lastChallenged
+                sleep(1)
+
+            self.page().set_redirect_url(session, session.marshal())
+
+        super(MainFrame, self).do_process(session, object)
+
 class MainFrameTabs(LinkSet):
     def __init__(self, app, name):
         super(MainFrameTabs, self).__init__(app, name)

Modified: mgmt/cumin/python/cumin/page.strings
===================================================================
--- mgmt/cumin/python/cumin/page.strings	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/python/cumin/page.strings	2008-02-26 16:42:17 UTC (rev 1727)
@@ -708,12 +708,10 @@
 [MainFrame.html]
 <div id="head">
   <div>
-    <!--
     <ul id="user">
-      <li>Hi, <strong>user</strong></li>
-      <li><a class="nav" href="">Log Out</a></li>
+      <li>Hi, <strong>{user_name}</strong></li>
+      <li><a class="nav" onclick="wooly.clearUpdates()" href="{logout_href}">Log Out</a></li>
     </ul>
-    -->
 
     {tabs}
   </div>

Modified: mgmt/cumin/python/wooly/__init__.py
===================================================================
--- mgmt/cumin/python/wooly/__init__.py	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/python/wooly/__init__.py	2008-02-26 16:42:17 UTC (rev 1727)
@@ -518,6 +518,7 @@
         self.trunk = trunk
         self.page = None
         self.values = dict()
+        self.credentials = dict()
 
         if self.app.debug:
             self.debug = self.Debug(self)

Modified: mgmt/cumin/python/wooly/server.py
===================================================================
--- mgmt/cumin/python/wooly/server.py	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/cumin/python/wooly/server.py	2008-02-26 16:42:17 UTC (rev 1727)
@@ -1,7 +1,7 @@
-from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
 from traceback import print_exc
 from datetime import datetime
 from time import strptime
+from base64 import decodestring
 
 from wooly import *
 from devel import DevelPage
@@ -10,12 +10,13 @@
 class WebServer(object):
     http_date = "%a, %d %b %Y %H:%M:%S %Z"
 
-    def __init__(self, app, port=8080):
+    def __init__(self, app, host, port):
         self.app = app
+        self.host = host
         self.port = port
 
-        addr = ("localhost", self.port)
-        apps = [("", self.wsgi_app)]
+        addr = (self.host, self.port)
+        apps = [("", self.service)]
         self.__server = CherryPyWSGIServer(addr, apps)
         self.__server.ssl_certificate = None # "/tmp/localhost.crt"
         self.__server.ssl_private_key = None # "/tmp/localhost.key"
@@ -23,13 +24,11 @@
     def start(self):
         self.__server.start()
 
-        print "Web server started on port %s" % (self.port)
-
     def stop(self):
         self.__server.stop()
 
-    def wsgi_app(self, env, respond):
-        if env["PATH_INFO"].endswith(".html"):
+    def service(self, env, respond):
+        if False and env["PATH_INFO"].endswith(".html"):
             print "------------------------------------"
             for key in sorted(env):
                 print key, env[key]
@@ -38,6 +37,17 @@
         session.unmarshal_page(env["PATH_INFO"])
         session.unmarshal_url_vars(env["QUERY_STRING"])
 
+        if "HTTP_AUTHORIZATION" in env:
+            str = env["HTTP_AUTHORIZATION"].split(" ")[1]
+            name, password = decodestring(str).split(":", 1)
+            session.credentials["name"] = name
+            session.credentials["password"] = password
+
+        if not self.authorized(session):
+            headers = [("WWW-Authenticate", "Basic realm=\"MRG Management\"")]
+            respond("401 Unauthorized", headers)
+            return ()
+
         if env["REQUEST_METHOD"] == "POST":
             if env["CONTENT_TYPE"] == "application/x-www-form-urlencoded":
                 length = int(env["CONTENT_LENGTH"])
@@ -101,6 +111,9 @@
 
         return response
 
+    def authorized(self, session):
+        return False
+
     def error(self, session, respond):
         respond("500 Error", [("Content-Type", "text/plain")])
 

Modified: mgmt/notes/justin-todo.txt
===================================================================
--- mgmt/notes/justin-todo.txt	2008-02-26 16:34:01 UTC (rev 1726)
+++ mgmt/notes/justin-todo.txt	2008-02-26 16:42:17 UTC (rev 1727)
@@ -16,8 +16,12 @@
 
  * Add broker reg name unique constraint and validation
 
+ * Add unique constraint to user name, and deal with it in cumin-admin
+
 Deferred
 
+ * Blow up if we try to call set_redirect_url twice in a session
+
  * Need to add cherrypy bsd license to binary dist?
 
  * See if we can't avoid the app.add_parameter in Parameter; adding to




More information about the rhmessaging-commits mailing list