changeset 296:29370bb76fa6

first permissions commit: added permission managment on repository edit. Changed db rmissions, validators.
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 25 Jun 2010 02:09:33 +0200
parents 248642ed1912
children a074dec6ee40
files pylons_app/controllers/repos.py pylons_app/lib/db_manage.py pylons_app/model/db.py pylons_app/model/forms.py pylons_app/model/repo_model.py pylons_app/templates/admin/repos/repo_edit.html
diffstat 6 files changed, 198 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/pylons_app/controllers/repos.py	Fri Jun 25 02:06:45 2010 +0200
+++ b/pylons_app/controllers/repos.py	Fri Jun 25 02:09:33 2010 +0200
@@ -107,10 +107,11 @@
             form_result = _form.to_python(dict(request.POST))
             repo_model.update(id, form_result)
             invalidate_cache('cached_repo_list')
-            h.flash(_('Repository updated succesfully'), category='success')
+            h.flash(_('Repository %s updated succesfully' % id), category='success')
                            
         except formencode.Invalid as errors:
             c.repo_info = repo_model.get(id)
+            errors.value.update({'user':c.repo_info.user.username})
             c.form_errors = errors.error_dict
             return htmlfill.render(
                  render('admin/repos/repo_edit.html'),
@@ -166,7 +167,12 @@
         
             return redirect(url('repos'))        
         defaults = c.repo_info.__dict__
-        defaults.update({'user':c.repo_info.user.username})        
+        defaults.update({'user':c.repo_info.user.username})
+        
+        for p in c.repo_info.repo2perm:
+            defaults.update({'perm_%s' % p.user.username: 
+                             p.permission.permission_name})
+                
         return htmlfill.render(
             render('admin/repos/repo_edit.html'),
             defaults=defaults,
--- a/pylons_app/lib/db_manage.py	Fri Jun 25 02:06:45 2010 +0200
+++ b/pylons_app/lib/db_manage.py	Fri Jun 25 02:09:33 2010 +0200
@@ -80,12 +80,25 @@
         self.create_user(username, password, True)
         
     def create_user(self, username, password, admin=False):
+        
+        log.info('creating default user')
+        #create default user for handling default permissions.
+        def_user = User()
+        def_user.username = 'default'
+        def_user.password = 'default'
+        def_user.name = 'default'
+        def_user.lastname = 'default'
+        def_user.email = 'default@default'
+        def_user.admin = False
+        def_user.active = False
+        
+        self.sa.add(def_user)
+        
         log.info('creating administrator user %s', username)
-        
         new_user = User()
         new_user.username = username
         new_user.password = get_crypt_password(password)
-        new_user.name = 'Admin'
+        new_user.name = 'Hg'
         new_user.lastname = 'Admin'
         new_user.email = 'admin@localhost'
         new_user.admin = admin
@@ -100,8 +113,11 @@
     
     def create_permissions(self):
         #module.(access|create|change|delete)_[name]
-        perms = [('admin.access_home', 'Access to admin user view'),
-                 
+        #module.(read|write|owner)
+        perms = [('repository.none', 'Repository no access'),
+                 ('repository.read', 'Repository read access'),
+                 ('repository.write', 'Repository write access'),
+                 ('repository.admin', 'Repository admin access'),
                  ]
         
         for p in perms:
--- a/pylons_app/model/db.py	Fri Jun 25 02:06:45 2010 +0200
+++ b/pylons_app/model/db.py	Fri Jun 25 02:09:33 2010 +0200
@@ -28,28 +28,44 @@
 class UserLog(Base): 
     __tablename__ = 'user_logs'
     __table_args__ = {'useexisting':True}
-    user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=1)
+    user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
-    repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 
+    repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None)
     action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
     
     user = relation('User')
-
+    
 class Repository(Base):
     __tablename__ = 'repositories'
+    __table_args__ = {'useexisting':True}
     repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
     private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
     description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    
     user = relation('User')
+    repo2perm = relation('Repo2Perm', cascade='all')
     
 class Permission(Base):
     __tablename__ = 'permissions'
     __table_args__ = {'useexisting':True}
-    permission_id = Column("id", INTEGER(), nullable=False, unique=True, default=None, primary_key=1)
+    permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
     permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     
     def __repr__(self):
         return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
+
+class Repo2Perm(Base):
+    __tablename__ = 'repo_to_perm'
+    __table_args__ = (UniqueConstraint('user_id', 'permission_id', 'repository'), {'useexisting':True})
+    repo2perm_id = Column("repo2perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
+    user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
+    permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
+    repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None) 
+    
+    user = relation('User')
+    permission = relation('Permission')
+    
--- a/pylons_app/model/forms.py	Fri Jun 25 02:06:45 2010 +0200
+++ b/pylons_app/model/forms.py	Fri Jun 25 02:09:33 2010 +0200
@@ -55,7 +55,8 @@
 class ValidUsername(formencode.validators.FancyValidator):
 
     def validate_python(self, value, state):
-        pass
+        if value in ['default', 'new_user']:
+            raise formencode.Invalid(_('Invalid username'), value, state)
     
 class ValidPassword(formencode.validators.FancyValidator):
     
@@ -145,6 +146,39 @@
                         
             return slug 
     return _ValidRepoName
+
+class ValidPerms(formencode.validators.FancyValidator):
+    messages = {'perm_new_user_name':_('This username is not valid')}
+    
+    def to_python(self, value, state):
+        perms_update = []
+        perms_new = []
+        #build a list of permission to update and new permission to create
+        for k, v in value.items():
+            print k, v
+            if k.startswith('perm_'):
+                if  k.startswith('perm_new_user'):
+                    new_perm = value.get('perm_new_user', False)
+                    new_user = value.get('perm_new_user_name', False)
+                    if new_user and new_perm:
+                        if (new_user, new_perm) not in perms_new:
+                            perms_new.append((new_user, new_perm))
+                else:
+                    perms_update.append((k[5:], v))
+                #clear from form list
+                #del value[k]
+        value['perms_updates'] = perms_update
+        value['perms_new'] = perms_new
+        sa = meta.Session
+        for k, v in perms_new:
+            try:
+                self.user_db = sa.query(User).filter(User.username == k).one()
+            except Exception:
+                msg = self.message('perm_new_user_name',
+                                     state=State_obj)
+                raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})            
+        return value
+                
 #===============================================================================
 # FORMS        
 #===============================================================================
@@ -192,7 +226,7 @@
 def RepoForm(edit=False):
     class _RepoForm(formencode.Schema):
         allow_extra_fields = True
-        filter_extra_fields = True
+        filter_extra_fields = False
         repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit))
         description = UnicodeString(strip=True, min=3, not_empty=True)
         private = StringBoolean(if_missing=False)
@@ -200,4 +234,5 @@
         if edit:
             user = All(Int(not_empty=True), ValidRepoUser)
         
+        chained_validators = [ValidPerms]
     return _RepoForm
--- a/pylons_app/model/repo_model.py	Fri Jun 25 02:06:45 2010 +0200
+++ b/pylons_app/model/repo_model.py	Fri Jun 25 02:09:33 2010 +0200
@@ -23,12 +23,13 @@
 @author: marcink
 """
 from pylons_app.model.meta import Session
-from pylons_app.model.db import Repository
+from pylons_app.model.db import Repository, Repo2Perm, User, Permission
 import shutil
 import os
 from datetime import datetime
 from pylons_app.lib.utils import check_repo
 from pylons import app_globals as g
+import traceback
 import logging
 log = logging.getLogger(__name__)
 
@@ -41,36 +42,73 @@
         return self.sa.query(Repository).get(id)
         
     
-    def update(self, id, form_data):
+    def update(self, repo_id, form_data):
         try:
-            if id != form_data['repo_name']:
-                self.__rename_repo(id, form_data['repo_name'])
-            cur_repo = self.sa.query(Repository).get(id)
+            if repo_id != form_data['repo_name']:
+                self.__rename_repo(repo_id, form_data['repo_name'])
+            cur_repo = self.sa.query(Repository).get(repo_id)
             for k, v in form_data.items():
                 if k == 'user':
                     cur_repo.user_id = v
                 else:
                     setattr(cur_repo, k, v)
+            
+            #update permissions
+            for username, perm in form_data['perms_updates']:
+                r2p = self.sa.query(Repo2Perm)\
+                        .filter(Repo2Perm.user == self.sa.query(User)\
+                                .filter(User.username == username).one())\
+                        .filter(Repo2Perm.repository == repo_id).one()
                 
+                r2p.permission_id = self.sa.query(Permission).filter(
+                                                Permission.permission_name == 
+                                                perm).one().permission_id
+                self.sa.add(r2p)
+            
+            for username, perm in form_data['perms_new']:
+                r2p = Repo2Perm()
+                r2p.repository = repo_id
+                r2p.user = self.sa.query(User)\
+                                .filter(User.username == username).one()
+                
+                r2p.permission_id = self.sa.query(Permission).filter(
+                                                Permission.permission_name == 
+                                                perm).one().permission_id
+                self.sa.add(r2p)
+                                    
             self.sa.add(cur_repo)
             self.sa.commit()
-        except Exception as e:
-            log.error(e)
+        except:
+            log.error(traceback.format_exc())
             self.sa.rollback()
             raise    
     
-    def create(self, form_data, cur_user):
+    def create(self, form_data, cur_user, just_db=False):
         try:
+            repo_name = form_data['repo_name']
             new_repo = Repository()
             for k, v in form_data.items():
                 setattr(new_repo, k, v)
                 
             new_repo.user_id = cur_user.user_id
             self.sa.add(new_repo)
+
+            #create default permission
+            repo2perm = Repo2Perm()
+            repo2perm.permission_id = self.sa.query(Permission)\
+                    .filter(Permission.permission_name == 'repository.read')\
+                    .one().permission_id
+                        
+            repo2perm.repository = repo_name
+            repo2perm.user_id = self.sa.query(User)\
+                    .filter(User.username == 'default').one().user_id 
+            
+            self.sa.add(repo2perm)
             self.sa.commit()
-            self.__create_repo(form_data['repo_name'])
-        except Exception as e:
-            log.error(e)
+            if not just_db:
+                self.__create_repo(repo_name)
+        except:
+            log.error(traceback.format_exc())
             self.sa.rollback()
             raise    
                      
@@ -79,8 +117,8 @@
             self.sa.delete(repo)
             self.sa.commit()
             self.__delete_repo(repo.repo_name)
-        except Exception as e:
-            log.error(e)
+        except:
+            log.error(traceback.format_exc())
             self.sa.rollback()
             raise
        
@@ -103,4 +141,5 @@
         #disable hg 
         shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
         #disable repo
-        shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s-%s' % (datetime.today(), id)))
+        shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
+                                          % (datetime.today(), name)))
--- a/pylons_app/templates/admin/repos/repo_edit.html	Fri Jun 25 02:06:45 2010 +0200
+++ b/pylons_app/templates/admin/repos/repo_edit.html	Fri Jun 25 02:09:33 2010 +0200
@@ -39,11 +39,71 @@
         		<td>${self.get_form_error('user')}</td>
         	</tr>
         	<tr>
+        		<td>${_('Permissions')}</td>
+        		<td>
+        			<table>
+        				<tr>
+        					<td>${_('none')}</td>
+        					<td>${_('read')}</td>
+        					<td>${_('write')}</td>
+        					<td>${_('admin')}</td>
+        					<td>${_('user')}</td>
+        				</tr>
+        				
+        				%for r2p in c.repo_info.repo2perm:
+	        				<tr>
+	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
+	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
+	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
+	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
+	        					<td>${r2p.user.username}</td>
+	        				</tr>
+						%endfor
+
+						
+						<%
+							
+							if not hasattr(c,'form_errors'):
+								d = 'display:none;'
+							else:
+								d=''
+						%>
+
+        				<tr id="add_perm_input" style="${d}">
+        					<td>${h.radio('perm_new_user','repository.none')}</td>
+        					<td>${h.radio('perm_new_user','repository.read')}</td>
+        					<td>${h.radio('perm_new_user','repository.write')}</td>
+        					<td>${h.radio('perm_new_user','repository.admin')}</td>
+        					<td>${h.text('perm_new_user_name',size=10)}</td>
+        					<td>${self.get_form_error('perm_new_user_name')}</td>     					
+        				</tr>
+        				<tr>
+        					<td colspan="4">
+        						<span id="add_perm" class="add_icon" style="cursor: pointer;">
+        						${_('Add another user')}
+        						</span>
+        					</td>
+        				</tr>
+        			</table>
+        		</td>
+        		
+        	</tr>
+        	<tr>
         		<td></td>
         		<td>${h.submit('update','update')}</td>
         	</tr>
         	        	        	
         </table>
         ${h.end_form()}
+        <script type="text/javascript">
+        	YAHOO.util.Event.onDOMReady(function(){
+				var D = YAHOO.util.Dom;
+				YAHOO.util.Event.addListener('add_perm','click',function(){
+					D.setStyle('add_perm_input','display','');
+					D.setStyle('add_perm','opacity','0.6');
+					D.setStyle('add_perm','cursor','default');
+				});
+            });
+        </script>
     </div>
 </%def>