Changeset - a26f48ad7a8a
[Not reviewed]
default
0 7 0
Marcin Kuzminski - 15 years ago 2010-07-27 14:53:22
marcin@python-works.com
fixes issue #16 reimplementation of database repository, for using generic pk instead of repo naming as pk. Which caused to many problems.
Fixed issue when redirecting after repo name change to 404.
Removed update hook from basic app setup
7 files changed with 66 insertions and 52 deletions:
0 comments (0 inline, 0 general)
pylons_app/controllers/settings.py
Show inline comments
 
@@ -8,42 +8,43 @@
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied 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 this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on June 30, 2010
 
settings controller for pylons
 
@author: marcink
 
"""
 
from formencode import htmlfill
 
from pylons import tmpl_context as c, request, url
 
from pylons.controllers.util import redirect
 
from pylons.i18n.translation import _
 
from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.utils import invalidate_cache
 
from pylons_app.model.forms import RepoSettingsForm
 
from pylons_app.model.repo_model import RepoModel
 
import formencode
 
import logging
 
import pylons_app.lib.helpers as h
 
import traceback
 
"""
 
Created on June 30, 2010
 
settings controller for pylons
 
@author: marcink
 
"""
 

	
 
log = logging.getLogger(__name__)
 

	
 
class SettingsController(BaseController):
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAllDecorator('repository.admin')           
 
    def __before__(self):
 
        super(SettingsController, self).__before__()
 
        
 
    def index(self, repo_name):
 
        repo_model = RepoModel()
 
        c.repo_info = repo = repo_model.get(repo_name)
 
@@ -63,36 +64,37 @@ class SettingsController(BaseController)
 
            defaults.update({'perm_%s' % p.user.username: 
 
                             p.permission.permission_name})
 
            
 
        return htmlfill.render(
 
            render('settings/repo_settings.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )  
 

	
 
    def update(self, repo_name):
 
        repo_model = RepoModel()
 
        changed_name = repo_name
 
        _form = RepoSettingsForm(edit=True, old_data={'repo_name':repo_name})()
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.update(repo_name, form_result)
 
            invalidate_cache('cached_repo_list')
 
            h.flash(_('Repository %s updated succesfully' % repo_name),
 
                    category='success')
 
                           
 
            changed_name = form_result['repo_name']               
 
        except formencode.Invalid as errors:
 
            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})
 
            return htmlfill.render(
 
                render('settings/repo_settings.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8") 
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('error occured during update of repository %s') \
 
                    % form_result['repo_name'], category='error')
 
                    % repo_name, category='error')
 
                    
 
        return redirect(url('repo_settings_home', repo_name=form_result['repo_name']))
 
        return redirect(url('repo_settings_home', repo_name=changed_name))
pylons_app/lib/auth.py
Show inline comments
 
@@ -97,81 +97,85 @@ def set_available_permissions(config):
 
    try:
 
        sa = meta.Session
 
        all_perms = sa.query(Permission).all()
 
    finally:
 
        meta.Session.remove()
 
    
 
    config['available_permissions'] = [x.permission_name for x in all_perms]
 

	
 
def set_base_path(config):
 
    config['base_path'] = config['pylons.app_globals'].base_path
 
        
 
def fill_perms(user):
 
    """
 
    Fills user permission attribute with permissions taken from database
 
    @param user:
 
    """
 
    
 
    sa = meta.Session
 
    user.permissions['repositories'] = {}
 
    
 
    #first fetch default permissions
 
    default_perms = sa.query(Repo2Perm, Repository, Permission)\
 
        .join((Repository, Repo2Perm.repository == Repository.repo_name))\
 
        .join((Repository, Repo2Perm.repository_id == Repository.repo_id))\
 
        .join((Permission, Repo2Perm.permission_id == Permission.permission_id))\
 
        .filter(Repo2Perm.user_id == sa.query(User).filter(User.username == 
 
                                            'default').one().user_id).all()
 

	
 
    if user.is_admin:
 
        user.permissions['global'] = set(['hg.admin'])
 
        #admin have all rights full
 
        for perm in default_perms:
 
            p = 'repository.admin'
 
            user.permissions['repositories'][perm.Repo2Perm.repository] = p
 
            user.permissions['repositories'][perm.Repo2Perm.repository.repo_name] = p
 
    
 
    else:
 
        user.permissions['global'] = set()
 
        for perm in default_perms:
 
            if perm.Repository.private:
 
                #disable defaults for private repos,
 
                p = 'repository.none'
 
            elif perm.Repository.user_id == user.user_id:
 
                #set admin if owner
 
                p = 'repository.admin'
 
            else:
 
                p = perm.Permission.permission_name
 
                
 
            user.permissions['repositories'][perm.Repo2Perm.repository] = p
 
            user.permissions['repositories'][perm.Repo2Perm.repository.repo_name] = p
 
                                                
 
        
 
        user_perms = sa.query(Repo2Perm, Permission, Repository)\
 
            .join((Repository, Repo2Perm.repository == Repository.repo_name))\
 
            .join((Repository, Repo2Perm.repository_id == Repository.repo_id))\
 
            .join((Permission, Repo2Perm.permission_id == Permission.permission_id))\
 
            .filter(Repo2Perm.user_id == user.user_id).all()
 
        #overwrite userpermissions with defaults
 
        for perm in user_perms:
 
            #set write if owner
 
            if perm.Repository.user_id == user.user_id:
 
                p = 'repository.write'
 
            else:
 
                p = perm.Permission.permission_name
 
            user.permissions['repositories'][perm.Repo2Perm.repository] = p
 
            user.permissions['repositories'][perm.Repo2Perm.repository.repo_name] = p
 
    meta.Session.remove()         
 
    return user
 
    
 
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:
 
        user = fill_perms(user)
 

	
 
    session['hg_app_user'] = user
 
    session.save()
 
    return user
 
        
 
#===============================================================================
 
# CHECK DECORATORS
 
#===============================================================================
 
class LoginRequired(object):
 
    """
 
    Must be logged in to execute this function else redirect to login page
 
    """
 
   
pylons_app/lib/db_manage.py
Show inline comments
 
@@ -117,25 +117,25 @@ class DbManage(object):
 
        
 
        paths = HgAppUi()
 
        paths.ui_section = 'paths'
 
        paths.ui_key = '/'
 
        paths.ui_value = os.path.join(path, '*')
 
        
 
        
 
        hgsettings = HgAppSettings()
 
        hgsettings.app_auth_realm = 'hg-app authentication'
 
        hgsettings.app_title = 'hg-app'
 
        
 
        try:
 
            self.sa.add(hooks)
 
            #self.sa.add(hooks)
 
            self.sa.add(web1)
 
            self.sa.add(web2)
 
            self.sa.add(web3)
 
            self.sa.add(web4)
 
            self.sa.add(paths)
 
            self.sa.add(hgsettings)
 
            self.sa.commit()
 
        except:
 
            self.sa.rollback()
 
            raise        
 
        log.info('created ui config')
 
                    
pylons_app/lib/utils.py
Show inline comments
 
@@ -196,25 +196,25 @@ class EmptyChangeset(BaseChangeset):
 
def repo2db_mapper(initial_repo_list, remove_obsolete=False):
 
    """
 
    maps all found repositories into db
 
    """
 
    from pylons_app.model.repo_model import RepoModel
 
    
 
    sa = meta.Session
 
    user = sa.query(User).filter(User.admin == True).first()
 
    
 
    rm = RepoModel()
 
    
 
    for name, repo in initial_repo_list.items():
 
        if not sa.query(Repository).get(name):
 
        if not sa.query(Repository).filter(Repository.repo_name == name).scalar():
 
            log.info('repository %s not found creating default', name)
 
                
 
            form_data = {
 
                         'repo_name':name,
 
                         'description':repo.description if repo.description != 'unknown' else \
 
                                        'auto description for %s' % name,
 
                         'private':False
 
                         }
 
            rm.create(form_data, user, just_db=True)
 

	
 

	
 
    if remove_obsolete:
pylons_app/model/db.py
Show inline comments
 
@@ -45,42 +45,43 @@ class UserLog(Base):
 
    __table_args__ = {'useexisting':True}
 
    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)
 
    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)
 
    __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
 
    repo_id = Column("repo_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    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("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', 'repository'), {'useexisting':True})
 
    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'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) 
 
    repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None) 
 
    
 
    user = relation('User')
 
    permission = relation('Permission')
 
    
 
    repository = relation('Repository')
pylons_app/model/forms.py
Show inline comments
 
@@ -155,28 +155,27 @@ class ValidRepoUser(formencode.validator
 
                                     value, state)
 
        meta.Session.remove()            
 
        return self.user_db.user_id
 

	
 
def ValidRepoName(edit, old_data):    
 
    class _ValidRepoName(formencode.validators.FancyValidator):
 
            
 
        def to_python(self, value, state):
 
            slug = h.repo_name_slug(value)
 
            if slug in ['_admin']:
 
                raise formencode.Invalid(_('This repository name is disallowed'),
 
                                         value, state)
 
            
 
            if old_data.get('repo_name') != value or not edit:    
 
                sa = meta.Session
 
                if sa.query(Repository).get(slug):
 
                if sa.query(Repository).filter(Repository.repo_name == slug).scalar():
 
                    raise formencode.Invalid(_('This repository already exists') ,
 
                                             value, state)
 
                meta.Session.remove()
 
            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):
pylons_app/model/repo_model.py
Show inline comments
 
@@ -7,145 +7,153 @@
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied 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 this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on Jun 5, 2010
 
model for handling repositories actions
 
@author: marcink
 
"""
 
from pylons_app.model.meta import Session
 
from datetime import datetime
 
from pylons import app_globals as g
 
from pylons_app.lib.utils import check_repo
 
from pylons_app.model.db import Repository, Repo2Perm, User, Permission
 
import shutil
 
from pylons_app.model.meta import Session
 
import logging
 
import os
 
from datetime import datetime
 
from pylons_app.lib.utils import check_repo
 
from pylons import app_globals as g
 
import shutil
 
import traceback
 
import logging
 
log = logging.getLogger(__name__)
 

	
 
class RepoModel(object):
 
    
 
    def __init__(self):
 
        self.sa = Session()
 
    
 
    def get(self, id):
 
        return self.sa.query(Repository).get(id)
 
        return self.sa.query(Repository).filter(Repository.repo_name == id).scalar()
 
        
 
    def get_users_js(self):
 
        
 
        users = self.sa.query(User).filter(User.active == True).all()
 
        u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
 
        users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
 
                                                    u.lastname, u.username) 
 
                                        for u in users])
 
        return users_array        
 
        
 
    
 
    def update(self, repo_id, form_data):
 
    def update(self, repo_name, form_data):
 
        try:
 
            if repo_id != form_data['repo_name']:
 
                #rename our data
 
                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()
 
                        .filter(Repo2Perm.repository == self.get(repo_name))\
 
                        .one()
 
                
 
                r2p.permission_id = self.sa.query(Permission).filter(
 
                                                Permission.permission_name == 
 
                                                perm).one().permission_id
 
                self.sa.add(r2p)
 
            
 
            #set new permissions
 
            for username, perm in form_data['perms_new']:
 
                r2p = Repo2Perm()
 
                r2p.repository = repo_id
 
                r2p.repository = self.get(repo_name)
 
                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
 
                                        Permission.permission_name == perm)\
 
                                        .one().permission_id
 
                self.sa.add(r2p)
 
                                    
 
            
 
            #update current repo
 
            cur_repo = self.get(repo_name)
 
             
 
            for k, v in form_data.items():
 
                if k == 'user':
 
                    cur_repo.user_id = v
 
                else:
 
                    setattr(cur_repo, k, v)
 
                                                        
 
            self.sa.add(cur_repo)
 
            
 
            if repo_name != form_data['repo_name']:
 
                #rename our data
 
                self.__rename_repo(repo_name, form_data['repo_name'])            
 
            
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise    
 
    
 
    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()
 
            default_perm = 'repository.none' if form_data['private'] \
 
                                                        else 'repository.read'
 
            repo2perm.permission_id = self.sa.query(Permission)\
 
                    .filter(Permission.permission_name == default_perm)\
 
                    .one().permission_id
 
                        
 
            repo2perm.repository = repo_name
 
            repo2perm.repository_id = new_repo.repo_id
 
            repo2perm.user_id = self.sa.query(User)\
 
                    .filter(User.username == 'default').one().user_id 
 
            
 
            self.sa.add(repo2perm)
 
            self.sa.commit()
 
            if not just_db:
 
                self.__create_repo(repo_name)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise    
 
                     
 
    def delete(self, repo):
 
        try:
 
            self.sa.delete(repo)
 
            self.sa.commit()
 
            self.__delete_repo(repo.repo_name)
 
        except:
 
            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.query(Repo2Perm)\
 
                .filter(Repo2Perm.repository == self.get(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):
 
            log.info('creating repo %s in %s', repo_name, repo_path)
 
            from vcs.backends.hg import MercurialRepository
 
            MercurialRepository(repo_path, create=True)
0 comments (0 inline, 0 general)