Changeset 1252

Show
Ignore:
Timestamp:
04/26/06 15:18:30 (3 years ago)
Author:
kevin
Message:

the identity model is now placed in a quickstart project.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1.0/CHANGELOG.txt

    r1231 r1252  
    1616  permissionId to be user\_name, group\_name, and permission_name. 
    1717* visit\_id has been deprecated in favor of visit_key 
     18 
     19*Changes* 
     20 
     21* Identity model classes are now placed directly into the model.py of 
     22  a quickstarted project. This new setup is much easier to change, 
     23  since requirements for the identity model vary dramatically. Another 
     24  advantage is that quickstart projects that don't need identity 
     25  start off with cleaner code, and projects that do need identity 
     26  need almost no additional configuration or setup. 
     27* quickstart projects include a "json.py" file as a home for JSON 
     28  view code. 
    1829 
    1930*Fixes* 
     
    3546 
    3647Alberto Valverde González, Jeff Watkins, Max Ischenko, Michele Cella,  
    37 Simon Belak, Jorge Godoy, Joost Moesker, Joseph Tate, Andrey Lebedev, 
    38 Brian Beck, Roger Demetrescu. 
     48Simon Belak, Jorge Godoy, Jorge Vargas, Joost Moesker, Joseph Tate,  
     49Andrey Lebedev, Brian Beck, Roger Demetrescu. 
    3950 
    40510.9a4 (April 5, 2006) 
  • branches/1.0/CONTRIBUTORS.txt

    r903 r1252  
    1818* Alberto Valverde 
    1919* Lee McFadden 
     20* Jorge Godoy 
    2021* Ondrej Zara (author of WWW SQL Designer) 
    2122 
  • branches/1.0/plugins/json/turbojson/jsonify.py

    r1203 r1252  
    3232    result['id'] = obj.id 
    3333    for name in obj.sqlmeta.columns.keys(): 
    34         result[name] = jsonify(getattr(obj, name)
     34        result[name] = getattr(obj, name
    3535    return result 
    3636jsonify_sqlobject = jsonify.when( 
     
    4848 
    4949def jsonify_select_results(obj): 
    50     return jsonify_list(obj) 
     50    return list(obj) 
    5151jsonify_select_results = jsonify.when( 
    5252        'isinstance(obj, sqlobject.SQLObject.SelectResultsClass)')( 
  • branches/1.0/turbogears/command/quickstart.py

    r1076 r1252  
    4040                            "quickstart") 
    4141    summary = "web framework" 
     42    use_cheetah = True 
    4243    
    4344 
     
    8889    package = None 
    8990    templates = "turbogears" 
     91    identity = None 
    9092     
    9193    def __init__(self, version): 
    92         parser = optparse.OptionParser(usage="%prog quickstart [options] [project name]", 
    93                                        version="%prog " + version) 
    94         parser.add_option("-p", "--package", help="package name for the code", 
     94        parser = optparse.OptionParser( 
     95                    usage="%prog quickstart [options] [project name]", 
     96                    version="%prog " + version) 
     97        parser.add_option("-p", "--package",  
     98            help="package name for the code", 
    9599            dest="package") 
    96         parser.add_option("--dry-run", help="dry run (don't actually do anything)", 
     100        parser.add_option("--dry-run",  
     101            help="dry run (don't actually do anything)", 
    97102            action="store_true", dest="dry_run") 
    98         parser.add_option("-t", "--templates", help="user specific templates", 
     103        parser.add_option("-t", "--templates",  
     104            help="user specific templates", 
    99105            dest="templates", default = self.templates) 
     106        parser.add_option("-i", "--identity",  
     107            help="identity provider to use (sqlobject (default)," 
     108                 " sqlalchemy, none)", 
     109            dest="identity", default = self.identity) 
     110 
    100111        (options, args) = parser.parse_args() 
    101112        self.__dict__.update(options.__dict__) 
     
    118129                self.package = package 
    119130 
     131        while not self.identity: 
     132            self.identity = raw_input("Choose an identity provider sqlobject, sqlalchemy or none [sqlobject]: ").lower() 
     133            if not self.identity: 
     134                self.identity = "sqlobject" 
     135            if self.identity not in ["sqlobject", "sqlalchemy", "none"]: 
     136                print "Please enter one of 'sqlobject', 'sqlalchemy' or " \ 
     137                      " 'none'" 
     138                self.identity = "" 
     139                continue 
     140     
    120141        self.name = pkg_resources.safe_name(self.name) 
    121142 
     
    138159            print("A directory called '%s' already exists. Exiting." 
    139160                      % self.name) 
    140             return 
    141  
     161            return         
     162             
     163         
    142164        command = create_distro.CreateDistroCommand("create") 
    143165        cmd_args = [] 
     
    146168        cmd_args.append(self.name) 
    147169        cmd_args.append("package=%s" %self.package) 
     170        cmd_args.append("identity=%s" %self.identity) 
    148171        if self.dry_run: 
    149172            cmd_args.append("--simulate") 
     
    175198    name = None 
    176199    templates = "turbogears" 
     200    identity = None 
    177201     
    178202    def __init__(self, version): 
     
    181205        parser.add_option("-t", "--templates", help="user specific templates", 
    182206            dest="templates", default=self.templates) 
     207        parser.add_option("-i", "--identity",  
     208            help="identity provider to use (sqlobject (default)," 
     209                 " sqlalchemy, none)", 
     210            dest="identity", default = self.identity) 
    183211        (options, args) = parser.parse_args() 
    184212        self.__dict__.update(options.__dict__) 
     
    189217        self.name = turbogears.util.get_project_name() 
    190218        self.package = turbogears.util.get_package_name() 
     219        if not self.identity: 
     220            self.identity = turbogears.config.get("identity.provider",  
     221                                                  "none") 
    191222        currentdir = os.path.basename(os.getcwd()) 
    192223        if not currentdir == self.name: 
     
    205236            cmd_args.append(self.name) 
    206237            cmd_args.append("package=%s" %self.package) 
     238            cmd_args.append("identity=%s" %self.identity) 
    207239            command.run(cmd_args) 
    208240 
  • branches/1.0/turbogears/identity/__init__.py

    r1037 r1252  
    1313from turbogears.util import request_available 
    1414from turbogears.identity.exceptions import * 
    15  
    1615 
    1716def create_default_provider(): 
     
    107106from turbogears.identity.conditions import * 
    108107 
     108def encrypt_password(cleartext): 
     109    # this next one ultimately needs to change to support SQLAlchemy 
     110    from turbogears.identity.soprovider import encrypt_password 
     111    return encrypt_password(cleartext) 
     112 
    109113# declare what should be exported 
    110114__all__ = [ "IdentityManagementNotEnabledException", 
     
    114118            "set_current_identity", "set_current_provider", 
    115119            "set_identity_errors", "get_identity_errors", 
    116             "was_login_attempted"
     120            "was_login_attempted", "encrypt_password"
  • branches/1.0/turbogears/identity/soprovider.py

    r1128 r1252  
    33import random 
    44 
    5 from turbojson.jsonify import * 
     5from turbojson.jsonify import jsonify_sqlobject, jsonify 
    66from sqlobject import * 
    77from sqlobject.inheritance import InheritableSQLObject 
     
    4949group_class= None 
    5050permission_class= None 
     51visit_class = None 
    5152 
    5253class SqlObjectIdentity(object): 
     
    6566        # a _user attribute, even if the value is None. 
    6667        try: 
    67             visit= TG_VisitIdentity.by_visit_key( self.visit_key ) 
     68            visit= visit_class.by_visit_key( self.visit_key ) 
    6869        except SQLObjectNotFound: 
    6970            # The visit ID is invalid 
     
    122123            return 
    123124        try: 
    124             visit= TG_VisitIdentity.by_visit_key(self.visit_key) 
     125            visit= visit_class.by_visit_key(self.visit_key) 
    125126            visit.destroySelf() 
    126127            # Clear the current identity 
     
    141142        get=turbogears.config.get 
    142143         
    143         global user_class, group_class, permission_class 
     144        global user_class, group_class, permission_class, visit_class 
    144145         
    145146        user_class_path= get( "identity.soprovider.model.user",  
     
    150151        if user_class: 
    151152            log.info("Succesfully loaded \"%s\"" % user_class_path) 
     153             
    152154        group_class_path= get( "identity.soprovider.model.group", 
    153155                                __name__ + ".TG_Group" ) 
     
    155157        if group_class: 
    156158            log.info("Succesfully loaded \"%s\"" % group_class_path) 
     159             
    157160        permission_class_path= get( "identity.soprovider.model.permission", 
    158161                                    __name__ + ".TG_Permission" ) 
     
    160163        if permission_class: 
    161164            log.info("Succesfully loaded \"%s\"" % permission_class_path) 
     165         
     166        visit_class_path= get( "visit.soprovider.model", 
     167                                __name__ + ".TG_VisitIdentity" ) 
     168        visit_class= load_class(visit_class_path) 
     169        if visit_class: 
     170            log.info("Succesfully loaded \"%s\"" % visit_class_path) 
     171         
    162172             
    163173        # Default encryption algorithm is to use plain text passwords 
     
    177187            group_class.createTable(ifNotExists=True) 
    178188            permission_class.createTable(ifNotExists=True) 
    179             TG_VisitIdentity.createTable(ifNotExists=True) 
     189            visit_class.createTable(ifNotExists=True) 
    180190            hub.commit() 
    181191            hub.end() 
     
    204214            # Link the user to the visit 
    205215            try: 
    206                 link= TG_VisitIdentity.by_visit_key( visit_key ) 
     216                link= visit_class.by_visit_key( visit_key ) 
    207217                link.user_id= user.id 
    208218            except SQLObjectNotFound: 
    209                 link= TG_VisitIdentity( visit_key=visit_key, user_id=user.id ) 
     219                link= visit_class( visit_key=visit_key, user_id=user.id ) 
    210220            return SqlObjectIdentity( visit_key, user ) 
    211221             
     
    275285def jsonify_group(obj): 
    276286    result = jsonify_sqlobject( obj ) 
    277     result["users"]= jsonify( [u.user_name for u in obj.users] ) 
    278     result["permissions"]= jsonify( [p.permission_name for p in obj.permissions] ) 
     287    result["users"]= [u.user_name for u in obj.users] 
     288    result["permissions"]= [p.permission_name for p in obj.permissions] 
    279289    return result 
    280290 
     
    334344    result = jsonify_sqlobject( obj ) 
    335345    del result['password'] 
    336     result["groups"]= jsonify( [g.group_name for g in obj.groups] ) 
    337     result["permissions"]= jsonify( [p.permission_name for p in obj.permissions] ) 
     346    result["groups"]= [g.group_name for g in obj.groups] 
     347    result["permissions"]= [p.permission_name for p in obj.permissions] 
    338348    return result 
    339349 
     
    358368def jsonify_permission(obj): 
    359369    result = jsonify_sqlobject( obj ) 
    360     result["groups"]= jsonify( [g.group_name for g in obj.groups] ) 
     370    result["groups"]= [g.group_name for g in obj.groups] 
    361371    return result 
    362372 
    363373jsonify_permission = jsonify.when( 
    364374        'isinstance(obj, TG_Permission)')(jsonify_permission) 
     375 
     376def encrypt_password(cleartext_password): 
     377    try: 
     378        hash = identity.current_provider.\ 
     379                            encrypt_password(cleartext_password) 
     380    except identity.exceptions.RequestRequiredException: 
     381        # Creating identity provider just to encrypt password 
     382        # (so we don't reimplement the encryption step). 
     383        ip = SqlObjectIdentityProvider() 
     384        hash = ip.encrypt_password(cleartext_password) 
     385        if hash == cleartext_password: 
     386            log.info("Identity provider not enabled, and no encryption " 
     387                    "algorithm " 
     388                    "specified in config.  Setting password as plaintext.") 
     389    return hash 
  • branches/1.0/turbogears/qstemplates/quickstart/+package+/config/app.cfg_tmpl

    r1175 r1252  
    3434# tg.mochikit_all = False 
    3535 
     36#if $identity != 'none' 
    3637# VISIT TRACKING 
    3738# Each visit to your application will be assigned a unique visit ID tracked via 
     
    4041 
    4142# Enable Visit tracking 
    42 # visit.on=Fals
     43visit.on=Tru
    4344 
    4445# Number of minutes a visit may be idle before it expires. 
     
    5859 
    5960# The name of the VisitManager plugin to use for visitor tracking. 
    60 # visit.manager="sqlobject
     61visit.manager="${identity}
    6162 
     63#if $identity == "sqlobject" 
     64# Database class to use for visit tracking 
     65visit.soprovider.model = "${package}.model.VisitIdentity" 
     66#else if $identity == "sqlalchemy" 
     67# Database class to use for visit tracking 
     68visit.saprovider.model = "${package}.model.VisitIdentity" 
     69#end if 
    6270 
    6371# IDENTITY 
     
    6674 
    6775# Switch to turn on or off the Identity management module 
    68 # identity.on=Fals
     76identity.on=Tru
    6977 
    7078# [REQUIRED] URL to which CherryPy will internally redirect when an access 
    7179# control check fails. If Identity management is turned on, a value for this 
    7280# option must be specified. 
    73 # identity.failure_url=None 
     81identity.failure_url="/login" 
    7482 
    75 # The IdentityProvider to use -- defaults to the SqlObjectIdentityProvider which 
    76 # pulls User, Group, and Permission data out of your model database. 
    77 # identity.provider="sqlobject" 
     83# identity.provider='${identity}' 
    7884 
    7985# The names of the fields on the login form containing the visitor's user ID 
     
    9096# identity.source="form,http_auth,visit" 
    9197 
    92  
     98#if $identity=='sqlobject' 
    9399# SqlObjectIdentityProvider 
    94100# Configuration options for the default IdentityProvider 
    95101# ------------------------- 
    96102 
    97 # The classes you wish to use for your Identity model. Leave these commented out 
    98 # to use the default classes for SqlObjectIdentityProvider. Or set them to the 
    99 # classes in your model. NOTE: These aren't TG_* because the TG prefix is 
    100 # reserved for classes created by TurboGears.  Also remember to not use reserved 
     103# The classes you wish to use for your Identity model. Remember to not use reserved 
    101104# SQL keywords for class names (at least unless you specify a different table 
    102105# name using sqlmeta). 
    103 # identity.soprovider.model.user="${package}.model.MyUserClass
    104 # identity.soprovider.model.group="${package}.model.MyGroupClass
    105 # identity.soprovider.model.permission="${package}.model.MyPermissionClass
     106identity.soprovider.model.user="${package}.model.User
     107identity.soprovider.model.group="${package}.model.Group
     108identity.soprovider.model.permission="${package}.model.Permission
    106109 
    107110# The password encryption algorithm used when comparing passwords against what's 
     
    117120 
    118121# identity.soprovider.encryption_algorithm=None 
     122#else  
     123# SqlAlchemyIdentityProvider 
     124# Configuration options for the default IdentityProvider 
     125# ------------------------- 
    119126 
     127# The classes you wish to use for your Identity model. Remember to not use reserved 
     128# SQL keywords for class names (at least unless you specify a different table 
     129# name using sqlmeta). 
     130identity.saprovider.model.user="${package}.model.User" 
     131identity.saprovider.model.group="${package}.model.Group" 
     132identity.saprovider.model.permission="${package}.model.Permission" 
     133 
     134# The password encryption algorithm used when comparing passwords against what's 
     135# stored in the database. Valid values are 'md5' or 'sha1'. If you do not 
     136# specify an encryption algorithm, passwords are expected to be clear text. 
     137# 
     138# The SqlAlchemyProvider *will* encrypt passwords supplied as part of your login 
     139# form.  If you set the password through the password property, like: 
     140# my_user.password = 'secret' 
     141# the password will be encrypted in the database, provided identity is up and  
     142# running, or you have loaded the configuration specifying what encryption to 
     143# use (in situations where identity may not yet be running, like tests). 
     144 
     145# identity.saprovider.encryption_algorithm=None 
     146#end if 
     147#end if 
    120148[/static] 
    121149static_filter.on = True 
  • branches/1.0/turbogears/qstemplates/quickstart/+package+/controllers.py_tmpl

    r1108 r1252  
    33from turbogears import controllers, expose, redirect 
    44from turbogears import identity 
     5 
     6from ${package} import json 
    57 
    68class Root(controllers.RootController): 
     
    911        import time 
    1012        return dict(now=time.ctime()) 
     13#if $identity != "none" 
    1114 
    1215    @expose(template="${package}.templates.login") 
     
    3740        identity.current.logout() 
    3841        raise redirect("/") 
     42#end if 
  • branches/1.0/turbogears/qstemplates/quickstart/+package+/model.py_tmpl

    r710 r1252  
     1#if $identity != "none" 
     2from datetime import datetime 
     3 
     4#end if 
    15from sqlobject import * 
    26from turbogears.database import PackageHub 
    3 # Uncomment the following line if you wish to use Identity and SO_Provider 
    4 # from turbogears.identity.soprovider import TG_User, TG_Group, TG_Permission 
     7#if $identity == "sqlobject" 
     8from turbogears import identity 
     9#end if 
    510 
    611hub = PackageHub("${package}") 
     
    914# class YourDataClass(SQLObject): 
    1015#     pass 
     16 
     17 
     18#if $identity=="sqlobject" 
     19 
     20class VisitIdentity(SQLObject): 
     21    visit_key = StringCol( length=40, alternateID=True, 
     22                          alternateMethodName="by_visit_key" ) 
     23    user_id = IntCol() 
     24 
     25 
     26class Group(SQLObject): 
     27    """ 
     28    An ultra-simple group definition. 
     29    """ 
     30     
     31    # names like "Group" and "Order" are reserved words in SQL 
     32    # so we set the name to something safe for SQL 
     33    class sqlmeta: 
     34        table="tg_group" 
     35     
     36    group_name = UnicodeCol( length=16, alternateID=True, 
     37                            alternateMethodName="by_group_name" ) 
     38    display_name = UnicodeCol( length=255 ) 
     39    created = DateTimeCol( default=datetime.now ) 
     40 
     41    # collection of all users belonging to this group 
     42    users = RelatedJoin( "User", intermediateTable="user_group", 
     43                        joinColumn="group_id", otherColumn="user_id" ) 
     44 
     45    # collection of all permissions for this group 
     46    permissions = RelatedJoin( "Permission", joinColumn="group_id",  
     47                              intermediateTable="group_permission", 
     48                              otherColumn="permission_id" ) 
     49 
     50 
     51class User(SQLObject): 
     52    """ 
     53    Reasonably basic User definition. Probably would want additional attributes. 
     54    """ 
     55    user_name = UnicodeCol( length=16, alternateID=True, 
     56                           alternateMethodName="by_user_name" ) 
     57    email_address = UnicodeCol( length=255, alternateID=True, 
     58                               alternateMethodName="by_email_address" ) 
     59    display_name = UnicodeCol( length=255 ) 
     60    password = UnicodeCol( length=40 ) 
     61    created = DateTimeCol( default=datetime.now ) 
     62 
     63    # groups this user belongs to 
     64    groups = RelatedJoin( "Group", intermediateTable="user_group", 
     65                         joinColumn="user_id", otherColumn="group_id" ) 
     66 
     67    def _get_permissions( self ): 
     68        perms = set() 
     69        for g in self.groups: 
     70            perms = perms | set(g.permissions) 
     71        return perms 
     72         
     73    def _set_password( self, cleartext_password ): 
     74        "Runs cleartext_password through the hash algorithm before saving." 
     75        hash = identity.encrypt_password(cleartext_password) 
     76        self._SO_set_password(hash) 
     77         
     78    def set_password_raw( self, password ): 
     79        "Saves the password as-is to the database." 
     80        self._SO_set_password(password) 
     81 
     82 
     83 
     84class Permission(SQLObject): 
     85    permission_name = UnicodeCol( length=16, alternateID=True, 
     86                                 alternateMethodName="by_permission_name" ) 
     87    description = UnicodeCol( length=255 ) 
     88     
     89    groups = RelatedJoin( "Group", 
     90                        intermediateTable="group_permission", 
     91                         joinColumn="permission_id",  
     92                         otherColumn="group_id" ) 
     93 
     94 
     95#else if $identity=="sqlalchemy" 
     96from sqlalchemy.ext.activemapper import * 
     97 
     98# tables for SQLAlchemy identity 
     99user_group = Table( "user_group", __engine__,  
     100                      Column( "user_id", Integer, 
     101                              ForeignKey("user.user_id"), 
     102                              primary_key=True ), 
     103                      Column( "group_id", Integer, 
     104                              ForeignKey("group.group_id"), 
     105                              primary_key=True ) ) 
     106                       
     107group_permission = Table( "group_permission", __engine__, 
     108                            Column( "group_id", Integer, 
     109                                    ForeignKey("group.group_id"), 
     110                                    primary_key=True ), 
     111                            Column( "permission_id", Integer, 
     112                                ForeignKey("permission.permission_id"), 
     113                                    primary_key=True ) ) 
     114 
     115 
     116class VisitIdentity(ActiveMapper): 
     117    class mapping: 
     118        __table__="visit_identity" 
     119        visit_key = column( String, # foreign_key="visit.visit_key", 
     120                          primary_key=True ) 
     121        user_id = column( Integer, foreign_key="user.user_id", index=True ) 
     122 
     123 
     124class Group(ActiveMapper): 
     125    """ 
     126    An ultra-simple group definition. 
     127    """ 
     128    class mapping: 
     129        __table__="tg_group" 
     130        group_id = column( Integer, primary_key=True ) 
     131        group_name = column( Unicode(16), unique=True ) 
     132        display_name = column( Unicode(255) ) 
     133        created = column( DateTime, default=datetime.now ) 
     134 
     135        users = many_to_many( "User", user_group, backref="groups" ) 
     136        permissions = many_to_many( "Permission", group_permission, 
     137                                   backref="groups" ) 
     138 
     139 
     140class User(ActiveMapper): 
     141    """ 
     142    Reasonably basic User definition. Probably would want additional attributes. 
     143    """ 
     144    class mapping: 
     145        __table__="user" 
     146        user_id = column( Integer, primary_key=True ) 
     147        user_name = column( Unicode(16), unique=True ) 
     148        email_address = column( Unicode(255), unique=True ) 
     149        display_name = column( Unicode(255) ) 
     150        password = column( Unicode(40) ) 
     151        created = column( DateTime, default=datetime.now ) 
     152 
     153        groups = many_to_many( "Group", user_group, backref="users" ) 
     154 
     155    @property 
     156    def permissions( self ): 
     157        perms = set() 
     158        for g in self.groups: 
     159            perms = perms | set(g.permissions) 
     160        return perms 
     161         
     162 
     163class Permission(ActiveMapper): 
     164    class mapping: 
     165        __table__="permission" 
     166        permission_id = column( Integer, primary_key=True ) 
     167        permission_name = column( Unicode(16), unique=True ) 
     168        description = column( Unicode(255) ) 
     169         
     170        groups = many_to_many( "Group", group_permission, 
     171                              backref="permmissions" ) 
     172#end if 
  • branches/1.0/turbogears/qstemplates/quickstart/+package+/tests/test_model.py_tmpl

    r1107 r1252  
    66 
    77from turbogears import testutil 
    8 #from ${package}.model import YourDataClass 
    9 #from turbogears.identity.soprovider import TG_User 
     8# from ${package}.model import YourDataClass, User 
    109 
    1110# database.set_db_uri("sqlite:///:memory:") 
     
    1312# class testTG_User(testutil.DBTest): 
    1413#     def get_model(self): 
    15 #         return TG_User 
     14#         return User 
    1615# 
    1716#     def test_creation(self): 
    1817#         "Object creation should set the name" 
    19 #         obj = TG_User(user_name = "creosote", 
     18#         obj = User(user_name = "creosote", 
    2019#                       email_address = "spam@python.not", 
    2120#                       display_name = "Mr Creosote",