changeset 299:d303aacb3349

repos crud controllers - change id into repo_name for compatability, added ajax repo perm user function variuos html fixes, permissions forms and managment fixes. Added permission fetching for each request in AuthUser instance
author Marcin Kuzminski <marcin@python-works.com>
date Mon, 28 Jun 2010 13:54:47 +0200
parents 15e96b5a2685
children 8f7b8e965fe4
files pylons_app/config/routing.py pylons_app/controllers/repos.py pylons_app/lib/auth.py pylons_app/lib/base.py pylons_app/model/forms.py pylons_app/model/repo_model.py pylons_app/templates/admin/repos/repo_add.html pylons_app/templates/admin/repos/repo_edit.html pylons_app/templates/admin/repos/repos.html pylons_app/templates/base/base.html
diffstat 10 files changed, 118 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/pylons_app/config/routing.py	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/config/routing.py	Mon Jun 28 13:54:47 2010 +0200
@@ -35,19 +35,22 @@
              action="new", conditions=dict(method=["GET"]))
         m.connect("formatted_new_repo", "/repos/new.{format}",
              action="new", conditions=dict(method=["GET"]))
-        m.connect("/repos/{id:.*}",
+        m.connect("/repos/{repo_name:.*}",
              action="update", conditions=dict(method=["PUT"]))
-        m.connect("/repos/{id:.*}",
+        m.connect("/repos/{repo_name:.*}",
              action="delete", conditions=dict(method=["DELETE"]))
-        m.connect("edit_repo", "/repos/{id:.*}/edit",
+        m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
+             action="edit", conditions=dict(method=["GET"]))
+        m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
              action="edit", conditions=dict(method=["GET"]))
-        m.connect("formatted_edit_repo", "/repos/{id:.*}.{format}/edit",
-             action="edit", conditions=dict(method=["GET"]))
-        m.connect("repo", "/repos/{id:.*}",
+        m.connect("repo", "/repos/{repo_name:.*}",
+             action="show", conditions=dict(method=["GET"]))
+        m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
              action="show", conditions=dict(method=["GET"]))
-        m.connect("formatted_repo", "/repos/{id:.*}.{format}",
-             action="show", conditions=dict(method=["GET"]))
-
+        #ajax delete repo perm user
+        m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
+             action="delete_perm_user", conditions=dict(method=["DELETE"]))
+        
     map.resource('user', 'users', path_prefix='/_admin')
     map.resource('permission', 'permissions', path_prefix='/_admin')
     
--- a/pylons_app/controllers/repos.py	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/controllers/repos.py	Mon Jun 28 13:54:47 2010 +0200
@@ -34,12 +34,9 @@
 from pylons_app.model.hg_model import HgModel
 from pylons_app.model.forms import RepoForm
 from pylons_app.model.meta import Session
-from datetime import datetime
 import formencode
 from formencode import htmlfill
 import logging
-import os
-import shutil
 log = logging.getLogger(__name__)
 
 class ReposController(BaseController):
@@ -93,24 +90,24 @@
 
         return render('admin/repos/repo_add.html')
 
-    def update(self, id):
-        """PUT /repos/id: Update an existing item"""
+    def update(self, repo_name):
+        """PUT /repos/repo_name: Update an existing item"""
         # Forms posted to this method should contain a hidden field:
         #    <input type="hidden" name="_method" value="PUT" />
         # Or using helpers:
-        #    h.form(url('repo', id=ID),
+        #    h.form(url('repo', repo_name=ID),
         #           method='put')
-        # url('repo', id=ID)
+        # url('repo', repo_name=ID)
         repo_model = RepoModel()
         _form = RepoForm(edit=True)()
         try:
             form_result = _form.to_python(dict(request.POST))
-            repo_model.update(id, form_result)
+            repo_model.update(repo_name, form_result)
             invalidate_cache('cached_repo_list')
-            h.flash(_('Repository %s updated succesfully' % id), category='success')
+            h.flash(_('Repository %s updated succesfully' % repo_name), category='success')
                            
         except formencode.Invalid as errors:
-            c.repo_info = repo_model.get(id)
+            c.repo_info = repo_model.get(repo_name)
             c.users_array = repo_model.get_users_js()
             errors.value.update({'user':c.repo_info.user.username})
             c.form_errors = errors.error_dict
@@ -123,59 +120,72 @@
                     % form_result['repo_name'], category='error')
         return redirect(url('repos'))
     
-    def delete(self, id):
-        """DELETE /repos/id: Delete an existing item"""
+    def delete(self, repo_name):
+        """DELETE /repos/repo_name: Delete an existing item"""
         # Forms posted to this method should contain a hidden field:
         #    <input type="hidden" name="_method" value="DELETE" />
         # Or using helpers:
-        #    h.form(url('repo', id=ID),
+        #    h.form(url('repo', repo_name=ID),
         #           method='delete')
-        # url('repo', id=ID)
+        # url('repo', repo_name=ID)
         
         repo_model = RepoModel()
-        repo = repo_model.get(id)
+        repo = repo_model.get(repo_name)
         if not repo:
             h.flash(_('%s repository is not mapped to db perhaps' 
                       ' it was moved or renamed  from the filesystem'
                       ' please run the application again'
-                      ' in order to rescan repositories') % id, category='error')
+                      ' in order to rescan repositories') % repo_name, category='error')
         
             return redirect(url('repos'))
         try:
             repo_model.delete(repo)            
             invalidate_cache('cached_repo_list')
-            h.flash(_('deleted repository %s') % id, category='success')
+            h.flash(_('deleted repository %s') % repo_name, category='success')
         except Exception:
-            h.flash(_('An error occured during deletion of %s') % id,
+            h.flash(_('An error occured during deletion of %s') % repo_name,
                     category='error')
         
         return redirect(url('repos'))
         
-    def show(self, id, format='html'):
-        """GET /repos/id: Show a specific item"""
-        # url('repo', id=ID)
+    def delete_perm_user(self, repo_name):
+        """
+        DELETE an existing repository permission user
+        @param repo_name:
+        """
         
-    def edit(self, id, format='html'):
-        """GET /repos/id/edit: Form to edit an existing item"""
-        # url('edit_repo', id=ID)
+        try:
+            repo_model = RepoModel()
+            repo_model.delete_perm_user(request.POST, repo_name)            
+        except Exception as e:
+            h.flash(_('An error occured during deletion of repository user'),
+                    category='error')
+        
+        
+    def show(self, repo_name, format='html'):
+        """GET /repos/repo_name: Show a specific item"""
+        # url('repo', repo_name=ID)
+        
+    def edit(self, repo_name, format='html'):
+        """GET /repos/repo_name/edit: Form to edit an existing item"""
+        # url('edit_repo', repo_name=ID)
         repo_model = RepoModel()
-        c.repo_info = repo = repo_model.get(id)
+        c.repo_info = repo = repo_model.get(repo_name)
         if not repo:
             h.flash(_('%s repository is not mapped to db perhaps' 
                       ' it was created or renamed from the filesystem'
                       ' please run the application again'
-                      ' in order to rescan repositories') % id, category='error')
+                      ' in order to rescan repositories') % repo_name, category='error')
         
             return redirect(url('repos'))        
         defaults = c.repo_info.__dict__
         defaults.update({'user':c.repo_info.user.username})
-        
         c.users_array = repo_model.get_users_js()
         
         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/auth.py	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/lib/auth.py	Mon Jun 28 13:54:47 2010 +0200
@@ -27,7 +27,7 @@
 from pylons import session, url, app_globals as g
 from pylons.controllers.util import abort, redirect
 from pylons_app.model import meta
-from pylons_app.model.db import User
+from pylons_app.model.db import User, Repo2Perm
 from sqlalchemy.exc import OperationalError
 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 import crypt
@@ -91,7 +91,18 @@
     all_perms = sa.query(Permission).all()
     config['pylons.app_globals'].available_permissions = [x.permission_name for x in all_perms]
 
-
+def get_user(session):
+    """
+    Gets user from session, and wraps permissions into user
+    @param session:
+    """
+    user = session.get('hg_app_user', AuthUser())
+    if user.is_authenticated:
+        sa = meta.Session
+        user.permissions = sa.query(Repo2Perm)\
+        .filter(Repo2Perm.user_id == user.user_id).all()
+        
+    return user
         
 #===============================================================================
 # DECORATORS
--- a/pylons_app/lib/base.py	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/lib/base.py	Mon Jun 28 13:54:47 2010 +0200
@@ -5,7 +5,7 @@
 from pylons import config, tmpl_context as c, request, session
 from pylons.controllers import WSGIController
 from pylons.templating import render_mako as render
-from pylons_app.lib.auth import LoginRequired, AuthUser
+from pylons_app.lib import auth
 from pylons_app.lib.utils import get_repo_slug
 from pylons_app.model import meta
 from pylons_app.model.hg_model import _get_repos_cached
@@ -17,7 +17,7 @@
         c.hg_app_version = __version__
         c.repos_prefix = config['hg_app_name']
         c.repo_name = get_repo_slug(request)
-        c.hg_app_user = session.get('hg_app_user', AuthUser())
+        c.hg_app_user = auth.get_user(session)
         c.cached_repo_list = _get_repos_cached()
         self.sa = meta.Session
     
--- a/pylons_app/model/forms.py	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/model/forms.py	Mon Jun 28 13:54:47 2010 +0200
@@ -155,7 +155,6 @@
         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)
@@ -164,9 +163,12 @@
                         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]
+                    usr = k[5:]                    
+                    if usr == 'default':
+                        if value['private']:
+                            #set none for default when updating to private repo
+                            v = 'repository.none'
+                    perms_update.append((usr, v))
         value['perms_updates'] = perms_update
         value['perms_new'] = perms_new
         sa = meta.Session
--- a/pylons_app/model/repo_model.py	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/model/repo_model.py	Mon Jun 28 13:54:47 2010 +0200
@@ -104,8 +104,10 @@
 
             #create default permission
             repo2perm = Repo2Perm()
+            default_perm = 'repository.none' if form_data['private'] \
+                                                        else 'repository.read'
             repo2perm.permission_id = self.sa.query(Permission)\
-                    .filter(Permission.permission_name == 'repository.read')\
+                    .filter(Permission.permission_name == default_perm)\
                     .one().permission_id
                         
             repo2perm.repository = repo_name
@@ -130,7 +132,16 @@
             log.error(traceback.format_exc())
             self.sa.rollback()
             raise
-       
+    def delete_perm_user(self, form_data, repo_name):
+        try:
+            r2p = self.sa.query(Repo2Perm).filter(Repo2Perm.repository == repo_name)\
+            .filter(Repo2Perm.user_id == form_data['user_id']).delete()
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+            raise
+           
     def __create_repo(self, repo_name):        
         repo_path = os.path.join(g.base_path, repo_name)
         if check_repo(repo_name, g.base_path):
--- a/pylons_app/templates/admin/repos/repo_add.html	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/templates/admin/repos/repo_add.html	Mon Jun 28 13:54:47 2010 +0200
@@ -30,7 +30,7 @@
         	</tr>
         	<tr>
         		<td>${_('Private')}</td>
-        		<td>${h.checkbox('private')}</td>
+        		<td>${h.checkbox('private',value="True")}</td>
         		<td>${self.get_form_error('private')}</td>
         	</tr>
         	<tr>
--- a/pylons_app/templates/admin/repos/repo_edit.html	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/templates/admin/repos/repo_edit.html	Mon Jun 28 13:54:47 2010 +0200
@@ -15,22 +15,22 @@
 </%def>
 <%def name="main()">
 	<div>
-        <h2>${_('Repositories')} - ${_('edit')}</h2>
-        ${h.form(url('repo', id=c.repo_info.repo_name),method='put')}
+        <h2>${_('Repositories')} - ${_('edit')} "${c.repo_name}"</h2>
+        ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
         <table>
         	<tr>
         		<td>${_('Name')}</td>
-        		<td>${h.text('repo_name')}</td>
+        		<td>${h.text('repo_name',size="28")}</td>
         		<td>${self.get_form_error('repo_name')}</td>
         	</tr>
         	<tr>
         		<td>${_('Description')}</td>
-        		<td>${h.textarea('description',cols=23,rows=5)}</td>
+        		<td>${h.textarea('description',cols=32,rows=5)}</td>
         		<td>${self.get_form_error('description')}</td>
         	</tr>
         	<tr>
         		<td>${_('Private')}</td>
-        		<td>${h.checkbox('private')}</td>
+        		<td>${h.checkbox('private',value="True")}</td>
         		<td>${self.get_form_error('private')}</td>
         	</tr>
         	<tr>
@@ -56,13 +56,37 @@
         				</tr>
         				
         				%for r2p in c.repo_info.repo2perm:
-	        				<tr>
+        					%if r2p.user.username =='default' and c.repo_info.private:
+        						<tr>
+									<td colspan="4">
+										<span style="font-size: 0.8em">${_('disabled for private repository')}</span></td>
+									<td>${r2p.user.username}</td>
+								</tr>
+							%else:
+	        				<tr id=${id(r2p.user.username)}>
 	        					<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>
+	        					<td>
+	        					  %if r2p.user.username !='default':
+				                  	<span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},${id(r2p.user.username)})">
+				                  		<script type="text/javascript">
+											function ajaxAction(user_id,field_id){
+												var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
+												var callback = { success:function(o){
+																YAHOO.util.Dom.get(String(field_id)).innerHTML = '<td colspan="6"></td>';
+															 }};
+												var postData = '_method=delete&user_id='+user_id; 
+												var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData); 
+						                	};
+										</script>       	
+				                  	</span>
+				                  %endif					
+	        					</td>
 	        				</tr>
+	        				%endif
 						%endfor
 						<%
 							if not hasattr(c,'form_errors'):
--- a/pylons_app/templates/admin/repos/repos.html	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/templates/admin/repos/repos.html	Mon Jun 28 13:54:47 2010 +0200
@@ -24,10 +24,10 @@
         </tr>
 	        %for cnt,repo in enumerate(c.repos_list):
 	 		<tr class="parity${cnt%2}">
-			    <td>${h.link_to(repo['name'],h.url('edit_repo',id=repo['name']))}</td>
+			    <td>${h.link_to(repo['name'],h.url('edit_repo',repo_name=repo['name']))}</td>
 		        <td>r${repo['rev']}:${repo['tip']}</td>
                 <td>
-                  ${h.form(url('repo', id=repo['name']),method='delete')}
+                  ${h.form(url('repo', repo_name=repo['name']),method='delete')}
                   	${h.submit('remove','delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
                   ${h.end_form()}
      			</td>
--- a/pylons_app/templates/base/base.html	Sat Jun 26 18:42:13 2010 +0200
+++ b/pylons_app/templates/base/base.html	Mon Jun 28 13:54:47 2010 +0200
@@ -106,7 +106,7 @@
 	            <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
 	            <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
 	            <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
-				<li>${h.link_to(_('settings'),h.url('edit_repo',id=c.repo_name))}</li>	        
+				<li>${h.link_to(_('settings'),h.url('edit_repo',repo_name=c.repo_name))}</li>	        
 	        </ul>
 		%else:
 		##Root menu