commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gnue/common doc/technotes/00005.txt doc/technot...


From: Jason Cater
Subject: gnue/common doc/technotes/00005.txt doc/technot...
Date: Wed, 18 Sep 2002 02:49:28 -0400

CVSROOT:        /home/cvs
Module name:    gnue
Changes by:     Jason Cater <address@hidden>    02/09/18 02:49:27

Modified files:
        common/doc/technotes: 00005.txt index.html index.txt 
        common/src     : GBaseApp.py GConnections.py GLoginHandler.py 

Log message:
        added support for custom login authenticators; read common technote 
00005.txt for more information

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/common/doc/technotes/00005.txt.diff?cvsroot=OldCVS&tr1=1.1&tr2=1.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/common/doc/technotes/index.html.diff?cvsroot=OldCVS&tr1=1.2&tr2=1.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/common/doc/technotes/index.txt.diff?cvsroot=OldCVS&tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/common/src/GBaseApp.py.diff?cvsroot=OldCVS&tr1=1.26&tr2=1.27&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/common/src/GConnections.py.diff?cvsroot=OldCVS&tr1=1.43&tr2=1.44&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/common/src/GLoginHandler.py.diff?cvsroot=OldCVS&tr1=1.5&tr2=1.6&r1=text&r2=text

Patches:
Index: gnue/common/doc/technotes/00005.txt
diff -c gnue/common/doc/technotes/00005.txt:1.1 
gnue/common/doc/technotes/00005.txt:1.2
*** gnue/common/doc/technotes/00005.txt:1.1     Thu Jul 18 14:40:47 2002
--- gnue/common/doc/technotes/00005.txt Wed Sep 18 02:49:27 2002
***************
*** 1,33 ****
  Title: Writing a Custom Login/Authentication Handler
! Status: Obsolete 
  
  
  Introduction
  ------------
  
! By default, GNUe clients look at a database connection, determine what 
! fields it needs in order to login (e.g., username and password), and then 
! asks its platform/interface dependent login handler to prompt the user for 
! this information. Once returned, the client connects to the database using 
! this information. 
  
! If needed, you can intercept a client's normal login handler to add your 
  own behavior.
  
  
  Why?
  ----
! Sometimes it is not enough to prompt for the "database" login.  Perhaps 
! you want finer control over logins, or simply need to authenticate against 
  something besides the database.
  
! You might want to authenticate against an NIS source, LDAP, or some custom 
! source.  Maybe you have many users and want to authenticate against rows in 
! a database table and have the actual database login name/password be a 
! common one that no one knows; i.e., while users Jason and James might log 
! in using "jason" and "james", they might both connect to the database as 
! "commonuser".  Since you may not trust James, you only want him to know 
! that he is logging in as "james" and never know that he is being connected 
  as "commonuser".
  
  
--- 1,34 ----
  Title: Writing a Custom Login/Authentication Handler
! Status: Current
! Revised: 18-SEP-2002
  
  
  Introduction
  ------------
  
! By default, GNUe clients look at a database connection, determine what
! fields it needs in order to login (e.g., username and password), and then
! asks its platform/interface dependent login handler to prompt the user for
! this information. Once returned, the client connects to the database using
! this information.
  
! If needed, you can intercept a client's normal login handler to add your
  own behavior.
  
  
  Why?
  ----
! Sometimes it is not enough to prompt for the "database" login.  Perhaps
! you want finer control over logins, or simply need to authenticate against
  something besides the database.
  
! You might want to authenticate against an NIS source, LDAP, or some custom
! source.  Maybe you have many users and want to authenticate against rows in
! a database table and have the actual database login name/password be a
! common one that no one knows; i.e., while users Jason and James might log
! in using "jason" and "james", they might both connect to the database as
! "commonuser".  Since you may not trust James, you only want him to know
! that he is logging in as "james" and never know that he is being connected
  as "commonuser".
  
  
***************
*** 35,172 ****
  What do I do?
  -------------
  
! First, a little explanation of how logins work: 
!   
! 1. A client needs to initialize a connection to a database, so it passes 
     GNUe-Common a description of the database and asks for it to connect.
  
! 2. GNUe-Common looks at the database description, determines what values 
     are needed to connect (usually, username and password).
  
! 3. GNUe-Common creates an instance of (or uses an existing instance of) 
     gnue.common.GLoginHander.LoginHandler, or if the client provides a
     more advanced login handler (e.g., GNUe Form's graphical handler), an
     instance of this.
  
! 4. GNUe-Common calls LoginHandler.getLogin(), passing it basic information 
!    about the needed connection and a list of values that login handler 
!    should provide (i.e., '_username' & '_password'). 
! 
! 5. GNUe-Common uses the results of the call to LoginHandler.getLogin() to 
!    create a connection to the database. 
! 
! 
! Now, if needed, you can subclass LoginHandler (basically intercepting 
! steps #3-4 above) and provide your own functionality.  All that is needed 
! is for you to provide class with a method called getLogin that takes as 
! input a tuple of:
! 
!     (database id, description, (requiredValues) ) 
! 
! and return a hash containing a dictionary/hash: 
!     
!     { 'field': 'value' }. 
! 
! RequiredValues is a tuple of tuples containing:
! 
!     (value id, value description, isPassword)
! 
! Example of a getLogin call as used by GNUe Common
! 
!     loginHandler.getLogin ('gnue',                  # Connection ID
!                            'GNUe Test Database',    # Connection Name
!                            ( ('_username','User Name', 0),    # Required
!                              ('_password','Password', 1) ) )  # Fields
! 
! You would want to write your own handler as such: 
! 
! 
!     #####################################################
!     #
!     # Template for a custom login handler
!     #
!     
!     # Import the base login handler; 
!     # Note: it is important that this line not change.
!     from gnue.common.GLoginHander import LoginHandler
!     
!     # Do not rename this class. 
!     # GNUe clients expect to see a MyLoginHander class
!     class MyLoginHandler(LoginHandler): 
!     
!       #
!       # getLogin is passed an list consisting of: 
!       #   Connection Name
!       #   Connection Comments/Description 
!       #   List of Fields to Input: 
!       #      Attribute Name, Label/Description, Is Password?
!       #
!       # It should return a dictionary of {Attribute Name: Inputted Value}
!       #
!       def getLogin(self, loginData): 
!     
!         connName = loginData[0]
!         connDescription = loginData[1]
!         requiredFields = loginData[2]
!     
!         # Perform any tasks prior to prompting for username/password. 
!         # At this point, you might want to add your needed fields to
!         # requiredFields or set default values.  Note: to set default
!         # values, set  'self._defaults['fieldname'] = 'default' 
!         # (e.g., 'self._defaults['_username'] = os.env['LOGNAME'] )
!     
!         loginFields = LoginHandler.getLogin (self, (connName, 
!                                                     connDescription, 
!                                                     requiredFields) )
!     
!         # Perform any tasks prior to returning username/password 
!         # The entered username/password is stored in loginFields['_username']
!         # and loginFields['_password']. At this point
!        
!         return loginFields
!     
!     #
!     #####################################################
! 
!     
! Save this file as a .py file and put it's location in your gnue.conf (change 
! "loginHandler =" to "loginHandler = /path/to/myhandler.py" )
  
  If all goes well, your login handler will be used the next time you log in.
  
! Some notes: 
  
!   1) GNUe-Common will expect to see to two objects in your handler's 
!      namespace:   LoginHandler   (from the import statement) and 
                    MyLoginHandler (your customized login class)
  
!      For this reason, do NOT change the import statement to read: 
         from gnue.common import GLoginHandler
       and then change the class' parent to be GLoginHandler.LoginHandler.
       If you do, your customized handler will probably not work the way
!      you expect. 
  
    2) Almost the only restriction placed on getLogin's functionality is
!      that it must return a hash containing at least the values requested 
!      when getLogin was called, using the value id's supplied. Your code, 
       in theory, can do whatever it needs in order to return these values.
  
!      HOWEVER: Even though it is possible, it is NOT recommended that you 
!      try to write your code to prompt for the values.  It is HIGHLY 
!      recommended that you call LoginHandler.getLogin (your superclass's
!      getLogin) to prompt for input.  The superclass' LoginHandler will  
!      know how to handle the current user's environment (i.e., should it 
!      display a GTK login box, generate HTML for a login box, not display 
       a box at all, but prompt using good ol' fashioned text prompts?)
!      It is quite extensible.  If you need to prompt for more fields than 
!      simply Username and Password, then simply add a definition to your 
!      requiredFields tuple and let the superclass' getLogin prompt for you.
  
  
  If you have written a customized login handler using backends not currently
! in our samples file (i.e., against NIS, Kerberos, LDAP, etc) and would like 
! to donate your example for others to learn from, please email it to: 
  
         address@hidden
-     
  
--- 36,203 ----
  What do I do?
  -------------
  
! First, a little explanation of how logins work:
! 
! 1. A client needs to initialize a connection to a database, so it passes
     GNUe-Common a description of the database and asks for it to connect.
  
! 2. GNUe-Common looks at the database description, determines what values
     are needed to connect (usually, username and password).
  
! 3. GNUe-Common creates an instance of (or uses an existing instance of)
     gnue.common.GLoginHander.LoginHandler, or if the client provides a
     more advanced login handler (e.g., GNUe Form's graphical handler), an
     instance of this.
  
! 4. GNUe-Common calls LoginHandler.getLogin(), passing it basic information
!    about the needed connection and a list of values that login handler
!    should provide (i.e., '_username' & '_password').
! 
! 5. GNUe-Common uses the results of the call to LoginHandler.getLogin() to
!    create a connection to the database.
! 
! 
! Now, if needed, you can create an Authenticator class that basically
! intervenes in between steps #3-4 above and provide your own functionality.
  
  If all goes well, your login handler will be used the next time you log in.
  
! Some notes:
  
!   1) GNUe-Common will expect to see to two objects in your handler's
!      namespace:   LoginHandler   (from the import statement) and
                    MyLoginHandler (your customized login class)
  
!      For this reason, do NOT change the import statement to read:
         from gnue.common import GLoginHandler
       and then change the class' parent to be GLoginHandler.LoginHandler.
       If you do, your customized handler will probably not work the way
!      you expect.
  
    2) Almost the only restriction placed on getLogin's functionality is
!      that it must return a hash containing at least the values requested
!      when getLogin was called, using the value id's supplied. Your code,
       in theory, can do whatever it needs in order to return these values.
  
!      HOWEVER: Even though it is possible, it is NOT recommended that you
!      try to write your code to prompt for the values.  It is HIGHLY
!      recommended that you return values in the getLoginFields method so
!      LoginHandler.getLogin can prompt for input.  The LoginHandler will
!      know how to handle the current user's environment (i.e., should it
!      display a GTK login box, generate HTML for a login box, not display
       a box at all, but prompt using good ol' fashioned text prompts?)
!      It is quite extensible.  If you need to prompt for more fields than
!      simply Username and Password, then simply add a definition to your
!      requiredFields tuple and let the LoginHandler's getLogin prompt for 
!      you.
! 
! 
! There are three steps to adding a custom authenticator:
! 
! 1. Create (or copy) a Python file that implements an Authenticator.
!    An Authenticator contains a class called Authenticator, which has
!    two methods, getRequiredFields() and login().  See the example below
!    for details on what's expected from these two methods.
! 
! 2. Place this file in either your Python search path, or in a
!    path specified by ImportPath (in the [common] section of gnue.conf)
! 
! 3. In your connections.conf file, add a custom_auth parameter that
!    is the name of the file (without the path or .py extension):
! 
!      [myconn]
!      adapter = psycopg
!      host = localhost
!      dbname = mydb
!      custom_auth = MyPostgresAuthenticator
! 
! 
! Creating a custom authenticator
! ===============================
! A slightly more complicated example.  You have a table in one of your 
databases
! called "users", that has a user and password field.
! 
! Your users will connect to the database using the username and password:
! dbUser  and dbPassword.
! 
! You, however, want them to use their own username and password to be
! authenticated, but after getting authenticated, the database only cares
! about the real "dbUser" and "dbPassword".
! 
! File: MyPostgresAuthenticator.py
! 
===============================================================================
! import psycopg
! from gnue.common.GConnections import LoginError
! 
! class Authenticator:
!   #
!   # getLoginFields is passed an list consisting of:
!   #   Fields to Input:
!   #      Attribute Name, Label/Description, Is Password?
!   #
!   #   This list is a list of the values the dbdriver
!   #   expects to get back in order to login.
!   #
!   #   It should return a similarly formatted list that
!   #   tells the LoginHandler what values need to be
!   #   prompted for. (Typically, _username and _password)
!   #   If nothing should be prompted (e.g., you have a
!   #   certificate) then return () (an empty list).
!   #
!   def getLoginFields(self, dbRequiredFields):
!     return dbRequiredFields
! 
!   #
!   # Authenticate the user givem the values prompted for.
!   # If the information is incorrect, then raise
!   # gnue.common.GConnections.LoginError
!   #
!   # It should return a dictionary of {Attribute Name: Value}
!   #
!   def login(self, loginData):
!     conn = psycopg.connect(user="theValidator",
!                  password="hotmomma",
!                  dbname="logins",
!                  host="localhost"')
!     cursor = conn.cursor()
!     results = cursor.execute (
!         'select 1 from users where username=%s and password=%s',
!         (loginData['_username'],
!          loginData['_password']) )
!     if not results.fetchone():
!       raise LoginError
!     else:
!       loginData['_username'] = 'dbLogin'
!       loginData['_password'] = 'dbPassword'
! 
===============================================================================
! 
! Note: there are no hard and fast rules about what can go into the
! connections.conf file.  If your authenticator needs more information
! stored in connections.conf, it is fine to do so.
! 
! However, to avoid namespace collisions, you should probably prefix
! any custom connection.conf entries with common prefix. For example,
! if you are writing an NIS adapter, you should prefix entries in
! connections.conf like:
! 
!   auth_nis_domain = MYDOMAIN
! 
! instead of something like:
! 
!   domain = MYDOMAIN
! 
! More examples:
! 
!   auth_ldap_*
!   auth_pg_*
!   auth_mysql_*
!   auth_kerberos_*
!   auth_custom_*
  
  
  If you have written a customized login handler using backends not currently
! in our samples file (i.e., against NIS, Kerberos, LDAP, etc) and would like
! to donate your example for others to learn from, please email it to:
  
         address@hidden
  
Index: gnue/common/doc/technotes/index.html
diff -c gnue/common/doc/technotes/index.html:1.2 
gnue/common/doc/technotes/index.html:1.3
*** gnue/common/doc/technotes/index.html:1.2    Wed Sep  4 19:29:11 2002
--- gnue/common/doc/technotes/index.html        Wed Sep 18 02:49:27 2002
***************
*** 17,33 ****
  <tr><td><a href="00002.txt">00002.txt</a></td><td>Overview of i18n support in 
GNUe tools</td></tr>
  <tr><td><a href="00003.txt">00003.txt</a></td><td>Menu Support in 
triggers</td></tr>
  <tr><td><a href="00004.txt">00004.txt</a></td><td>GNUe Client startup 
sequence</td></tr>
- <tr><td><a href="00006.txt">00006.txt</a></td><td>Trigger Extension for 
datasources</td></tr>
- </table>
- 
- 
- 
- <h3>Obsolete Tech Notes</h3>
- 
- <table border="1" width="100%">
- <tr><th>File</th><th>Title</th></tr>
- 
  <tr><td><a href="00005.txt">00005.txt</a></td><td>Writing a Custom 
Login/Authentication Handler</td></tr>
  </table>
  
  
--- 17,24 ----
  <tr><td><a href="00002.txt">00002.txt</a></td><td>Overview of i18n support in 
GNUe tools</td></tr>
  <tr><td><a href="00003.txt">00003.txt</a></td><td>Menu Support in 
triggers</td></tr>
  <tr><td><a href="00004.txt">00004.txt</a></td><td>GNUe Client startup 
sequence</td></tr>
  <tr><td><a href="00005.txt">00005.txt</a></td><td>Writing a Custom 
Login/Authentication Handler</td></tr>
+ <tr><td><a href="00006.txt">00006.txt</a></td><td>Trigger Extension for 
datasources</td></tr>
  </table>
  
  
Index: gnue/common/doc/technotes/index.txt
diff -c gnue/common/doc/technotes/index.txt:1.4 
gnue/common/doc/technotes/index.txt:1.5
*** gnue/common/doc/technotes/index.txt:1.4     Wed Sep  4 19:29:11 2002
--- gnue/common/doc/technotes/index.txt Wed Sep 18 02:49:27 2002
***************
*** 13,29 ****
  00002.txt   Overview of i18n support in GNUe tools
  00003.txt   Menu Support in triggers
  00004.txt   GNUe Client startup sequence
- 00006.txt   Trigger Extension for datasources
- ----------  ------------------------------------------------------------------
- 
- 
- ==============================================================================
- Obsolete Tech Notes
- ==============================================================================
- 
- File        Title
- ----------  ------------------------------------------------------------------
  00005.txt   Writing a Custom Login/Authentication Handler
  ----------  ------------------------------------------------------------------
  
  
--- 13,20 ----
  00002.txt   Overview of i18n support in GNUe tools
  00003.txt   Menu Support in triggers
  00004.txt   GNUe Client startup sequence
  00005.txt   Writing a Custom Login/Authentication Handler
+ 00006.txt   Trigger Extension for datasources
  ----------  ------------------------------------------------------------------
  
  
Index: gnue/common/src/GBaseApp.py
diff -c gnue/common/src/GBaseApp.py:1.26 gnue/common/src/GBaseApp.py:1.27
*** gnue/common/src/GBaseApp.py:1.26    Wed Sep 18 01:13:01 2002
--- gnue/common/src/GBaseApp.py Wed Sep 18 02:49:27 2002
***************
*** 214,220 ****
      # Add custom import to python's namespace
      try:
        extrapaths = gConfig('ImportPath')
-       print extrapaths
      except:
        extrapaths = ""
      if extrapaths:
--- 214,219 ----
***************
*** 222,228 ****
          p = string.strip(path)
          if not p in sys.path:
            sys.path.append(p)
-           print "Appending %s" % p
  
      # Get the connection definitions
      if connections != None:
--- 221,226 ----
Index: gnue/common/src/GConnections.py
diff -c gnue/common/src/GConnections.py:1.43 
gnue/common/src/GConnections.py:1.44
*** gnue/common/src/GConnections.py:1.43        Tue Sep 17 16:41:27 2002
--- gnue/common/src/GConnections.py     Wed Sep 18 02:49:27 2002
***************
*** 56,61 ****
--- 56,63 ----
    # in an unreadable format.
    pass
  
+ LoginError = GDataObjects.LoginError
+ 
  
  class GConnections:
  
***************
*** 242,257 ****
          loginData['_password'] = loginData['password']
          del loginData['password']
  
  
        haveAllInformation = 1
!       for rf, dummy1, dummy2 in dataObject.getLoginFields():
          if not (loginData.has_key(rf) and loginData[rf] != None):
            haveAllInformation = 0
            break
  
        if haveAllInformation:
! 
!         dataObject.connect(loginData)
          GDebug.printMesg(5, 'I had enough information to connect to %s 
without asking the user' % connection_name)
          # Save the newly opened connection for future datasources
          self._openConnections[connection_name] = 
dataObject.getDataConnection()
--- 244,268 ----
          loginData['_password'] = loginData['password']
          del loginData['password']
  
+       # Load
+       if loginData.has_key('custom_auth'):
+         authenticator = dyn_import(loginData['custom_auth']).Authenticator()
+         checkFields = 
authenticator.getLoginFields(dataObject.getLoginFields())
+       else:
+         checkFields = dataObject.getLoginFields()
+         authenticator = None
  
        haveAllInformation = 1
!       for rf, dummy1, dummy2 in checkFields:
          if not (loginData.has_key(rf) and loginData[rf] != None):
            haveAllInformation = 0
            break
  
        if haveAllInformation:
!         if authenticator: 
!           dataObject.connect(authenticator.login(loginData))
!         else:
!           dataObject.connect(loginData)
          GDebug.printMesg(5, 'I had enough information to connect to %s 
without asking the user' % connection_name)
          # Save the newly opened connection for future datasources
          self._openConnections[connection_name] = 
dataObject.getDataConnection()
Index: gnue/common/src/GLoginHandler.py
diff -c gnue/common/src/GLoginHandler.py:1.5 
gnue/common/src/GLoginHandler.py:1.6
*** gnue/common/src/GLoginHandler.py:1.5        Fri May  3 19:07:18 2002
--- gnue/common/src/GLoginHandler.py    Wed Sep 18 02:49:27 2002
***************
*** 11,22 ****
  # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  # PURPOSE. See the GNU General Public License for more details.
  #
! # You should have received a copy of the GNU General Public 
! # License along with program; see the file COPYING. If not, 
! # write to the Free Software Foundation, Inc., 59 Temple Place 
  # - Suite 330, Boston, MA 02111-1307, USA.
  #
! # Copyright 2000, 2001 Free Software Foundation
  #
  # FILE:
  # GConnections.py
--- 11,22 ----
  # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  # PURPOSE. See the GNU General Public License for more details.
  #
! # You should have received a copy of the GNU General Public
! # License along with program; see the file COPYING. If not,
! # write to the Free Software Foundation, Inc., 59 Temple Place
  # - Suite 330, Boston, MA 02111-1307, USA.
  #
! # Copyright 2000-2002 Free Software Foundation
  #
  # FILE:
  # GConnections.py
***************
*** 26,33 ****
  # (design to be subclassed by the UI portion).
  #
  # NOTES:
- #
- # HISTORY:
  #
  
  
--- 26,31 ----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]