Changeset - 07e56179633e
[Not reviewed]
beta
0 9 0
Marcin Kuzminski - 14 years ago 2011-11-26 16:51:03
marcin@python-works.com
- fixes celery sqlalchemy session issues for async forking
- summary page css fixes
- speed optimizations
9 files changed with 63 insertions and 59 deletions:
0 comments (0 inline, 0 general)
rhodecode/lib/auth.py
Show inline comments
 
@@ -256,97 +256,97 @@ def login_container_auth(username):
 
              user.username)
 
    return user
 

	
 
def get_container_username(environ, config):
 
    username = None
 

	
 
    if str2bool(config.get('container_auth_enabled', False)):
 
        from paste.httpheaders import REMOTE_USER
 
        username = REMOTE_USER(environ)
 

	
 
    if not username and str2bool(config.get('proxypass_auth_enabled', False)):
 
        username = environ.get('HTTP_X_FORWARDED_USER')
 

	
 
    if username:
 
        # Removing realm and domain from username
 
        username = username.partition('@')[0]
 
        username = username.rpartition('\\')[2]
 
        log.debug('Received username %s from container', username)
 

	
 
    return username
 

	
 
class  AuthUser(object):
 
    """
 
    A simple object that handles all attributes of user in RhodeCode
 

	
 
    It does lookup based on API key,given user, or user present in session
 
    Then it fills all required information for such user. It also checks if
 
    anonymous access is enabled and if so, it returns default user as logged
 
    in
 
    """
 

	
 
    def __init__(self, user_id=None, api_key=None, username=None):
 

	
 
        self.user_id = user_id
 
        self.api_key = None
 
        self.username = username
 

	
 
        self.name = ''
 
        self.lastname = ''
 
        self.email = ''
 
        self.is_authenticated = False
 
        self.admin = False
 
        self.permissions = {}
 
        self._api_key = api_key
 
        self.propagate_data()
 

	
 
    def propagate_data(self):
 
        user_model = UserModel()
 
        self.anonymous_user = User.get_by_username('default')
 
        self.anonymous_user = User.get_by_username('default', cache=True)
 
        is_user_loaded = False
 

	
 
        # try go get user by api key
 
        if self._api_key and self._api_key != self.anonymous_user.api_key:
 
            log.debug('Auth User lookup by API KEY %s', self._api_key)
 
            is_user_loaded = user_model.fill_data(self, api_key=self._api_key)
 
        # lookup by userid    
 
        elif (self.user_id is not None and
 
              self.user_id != self.anonymous_user.user_id):
 
            log.debug('Auth User lookup by USER ID %s', self.user_id)
 
            is_user_loaded = user_model.fill_data(self, user_id=self.user_id)
 
        # lookup by username    
 
        elif self.username:
 
            log.debug('Auth User lookup by USER NAME %s', self.username)
 
            dbuser = login_container_auth(self.username)
 
            if dbuser is not None:
 
                for k, v in dbuser.get_dict().items():
 
                    setattr(self, k, v)
 
                self.set_authenticated()
 
                is_user_loaded = True
 

	
 
        if not is_user_loaded:
 
            # if we cannot authenticate user try anonymous
 
            if self.anonymous_user.active is True:
 
                user_model.fill_data(self, user_id=self.anonymous_user.user_id)
 
                # then we set this user is logged in
 
                self.is_authenticated = True
 
            else:
 
                self.user_id = None
 
                self.username = None
 
                self.is_authenticated = False
 

	
 
        if not self.username:
 
            self.username = 'None'
 

	
 
        log.debug('Auth User is now %s', self)
 
        user_model.fill_perms(self)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
    def __repr__(self):
 
        return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
 
@@ -443,98 +443,96 @@ class NotAnonymous(object):
 
    def __wrapper(self, func, *fargs, **fkwargs):
 
        cls = fargs[0]
 
        self.user = cls.rhodecode_user
 

	
 
        log.debug('Checking if user is not anonymous @%s', cls)
 

	
 
        anonymous = self.user.username == 'default'
 

	
 
        if anonymous:
 
            p = url.current()
 

	
 
            import rhodecode.lib.helpers as h
 
            h.flash(_('You need to be a registered user to '
 
                      'perform this action'),
 
                    category='warning')
 
            return redirect(url('login_home', came_from=p))
 
        else:
 
            return func(*fargs, **fkwargs)
 

	
 

	
 
class PermsDecorator(object):
 
    """Base class for controller decorators"""
 

	
 
    def __init__(self, *required_perms):
 
        available_perms = config['available_permissions']
 
        for perm in required_perms:
 
            if perm not in available_perms:
 
                raise Exception("'%s' permission is not defined" % perm)
 
        self.required_perms = set(required_perms)
 
        self.user_perms = None
 

	
 
    def __call__(self, func):
 
        return decorator(self.__wrapper, func)
 

	
 
    def __wrapper(self, func, *fargs, **fkwargs):
 
        cls = fargs[0]
 
        self.user = cls.rhodecode_user
 
        self.user_perms = self.user.permissions
 
        log.debug('checking %s permissions %s for %s %s',
 
           self.__class__.__name__, self.required_perms, cls,
 
               self.user)
 

	
 
        if self.check_permissions():
 
            log.debug('Permission granted for %s %s', cls, self.user)
 
            return func(*fargs, **fkwargs)
 

	
 
        else:
 
            log.warning('Permission denied for %s %s', cls, self.user)
 

	
 

	
 
            anonymous = self.user.username == 'default'
 

	
 
            if anonymous:
 
                p = url.current()
 

	
 
                import rhodecode.lib.helpers as h
 
                h.flash(_('You need to be a signed in to '
 
                          'view this page'),
 
                        category='warning')
 
                return redirect(url('login_home', came_from=p))
 

	
 
            else:
 
                # redirect with forbidden ret code
 
                return abort(403)
 

	
 
    def check_permissions(self):
 
        """Dummy function for overriding"""
 
        raise Exception('You have to write this function in child class')
 

	
 

	
 
class HasPermissionAllDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for all given predicates. All of them
 
    have to be meet in order to fulfill the request
 
    """
 

	
 
    def check_permissions(self):
 
        if self.required_perms.issubset(self.user_perms.get('global')):
 
            return True
 
        return False
 

	
 

	
 
class HasPermissionAnyDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for any of given predicates. In order to
 
    fulfill the request any of predicates must be meet
 
    """
 

	
 
    def check_permissions(self):
 
        if self.required_perms.intersection(self.user_perms.get('global')):
 
            return True
 
        return False
 

	
 

	
 
class HasRepoPermissionAllDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for all given predicates for specific
 
    repository. All of them have to be meet in order to fulfill the request
 
@@ -542,98 +540,97 @@ class HasRepoPermissionAllDecorator(Perm
 

	
 
    def check_permissions(self):
 
        repo_name = get_repo_slug(request)
 
        try:
 
            user_perms = set([self.user_perms['repositories'][repo_name]])
 
        except KeyError:
 
            return False
 
        if self.required_perms.issubset(user_perms):
 
            return True
 
        return False
 

	
 

	
 
class HasRepoPermissionAnyDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for any of given predicates for specific
 
    repository. In order to fulfill the request any of predicates must be meet
 
    """
 

	
 
    def check_permissions(self):
 
        repo_name = get_repo_slug(request)
 

	
 
        try:
 
            user_perms = set([self.user_perms['repositories'][repo_name]])
 
        except KeyError:
 
            return False
 
        if self.required_perms.intersection(user_perms):
 
            return True
 
        return False
 

	
 

	
 
#==============================================================================
 
# CHECK FUNCTIONS
 
#==============================================================================
 
class PermsFunction(object):
 
    """Base function for other check functions"""
 

	
 
    def __init__(self, *perms):
 
        available_perms = config['available_permissions']
 

	
 
        for perm in perms:
 
            if perm not in available_perms:
 
                raise Exception("'%s' permission in not defined" % perm)
 
        self.required_perms = set(perms)
 
        self.user_perms = None
 
        self.granted_for = ''
 
        self.repo_name = None
 

	
 
    def __call__(self, check_Location=''):
 
        cookie_store = session.get('rhodecode_user')
 
        user = AuthUser.from_cookie_store(cookie_store)
 
        user = request.user
 
        if not user:
 
            return False
 
        self.user_perms = user.permissions
 
        self.granted_for = user
 
        log.debug('checking %s %s %s', self.__class__.__name__,
 
                  self.required_perms, user)
 

	
 
        if self.check_permissions():
 
            log.debug('Permission granted %s @ %s', self.granted_for,
 
                      check_Location or 'unspecified location')
 
            return True
 

	
 
        else:
 
            log.warning('Permission denied for %s @ %s', self.granted_for,
 
                        check_Location or 'unspecified location')
 
            return False
 

	
 
    def check_permissions(self):
 
        """Dummy function for overriding"""
 
        raise Exception('You have to write this function in child class')
 

	
 

	
 
class HasPermissionAll(PermsFunction):
 
    def check_permissions(self):
 
        if self.required_perms.issubset(self.user_perms.get('global')):
 
            return True
 
        return False
 

	
 

	
 
class HasPermissionAny(PermsFunction):
 
    def check_permissions(self):
 
        if self.required_perms.intersection(self.user_perms.get('global')):
 
            return True
 
        return False
 

	
 

	
 
class HasRepoPermissionAll(PermsFunction):
 

	
 
    def __call__(self, repo_name=None, check_Location=''):
 
        self.repo_name = repo_name
 
        return super(HasRepoPermissionAll, self).__call__(check_Location)
 

	
 
    def check_permissions(self):
 
        if not self.repo_name:
 
            self.repo_name = get_repo_slug(request)
 

	
 
        try:
 
            self.user_perms = set([self.user_perms['reposit'
rhodecode/lib/base.py
Show inline comments
 
@@ -7,89 +7,90 @@ import time
 
from pylons import config, tmpl_context as c, request, session, url
 
from pylons.controllers import WSGIController
 
from pylons.controllers.util import redirect
 
from pylons.templating import render_mako as render
 

	
 
from rhodecode import __version__, BACKENDS
 

	
 
from rhodecode.lib import str2bool
 
from rhodecode.lib.auth import AuthUser, get_container_username
 
from rhodecode.lib.utils import get_repo_slug
 
from rhodecode.model import meta
 

	
 
from rhodecode.model.db import Repository
 
from rhodecode.model.notification import NotificationModel
 
from rhodecode.model.scm import ScmModel
 

	
 
log = logging.getLogger(__name__)
 

	
 
class BaseController(WSGIController):
 

	
 
    def __before__(self):
 
        c.rhodecode_version = __version__
 
        c.rhodecode_name = config.get('rhodecode_title')
 
        c.use_gravatar = str2bool(config.get('use_gravatar'))
 
        c.ga_code = config.get('rhodecode_ga_code')
 
        c.repo_name = get_repo_slug(request)
 
        c.backends = BACKENDS.keys()
 
        c.unread_notifications = NotificationModel()\
 
                        .get_unread_cnt_for_user(c.rhodecode_user.user_id)
 
        self.cut_off_limit = int(config.get('cut_off_limit'))
 

	
 
        self.sa = meta.Session()
 
        self.scm_model = ScmModel(self.sa)
 

	
 
    def __call__(self, environ, start_response):
 
        """Invoke the Controller"""
 
        # WSGIController.__call__ dispatches to the Controller method
 
        # the request is routed to. This routing information is
 
        # available in environ['pylons.routes_dict']
 
        start = time.time()
 
        try:
 
            # make sure that we update permissions each time we call controller
 
            api_key = request.GET.get('api_key')
 
            cookie_store = session.get('rhodecode_user') or {}
 
            user_id = cookie_store.get('user_id', None)
 
            username = get_container_username(environ, config)
 

	
 
            auth_user = AuthUser(user_id, api_key, username)
 
            request.user = auth_user
 
            self.rhodecode_user = c.rhodecode_user = auth_user
 
            if not self.rhodecode_user.is_authenticated and \
 
                       self.rhodecode_user.user_id is not None:
 
                self.rhodecode_user\
 
                    .set_authenticated(cookie_store.get('is_authenticated'))
 

	
 
            session['rhodecode_user'] = self.rhodecode_user.get_cookie_store()
 
            session.save()
 
            return WSGIController.__call__(self, environ, start_response)
 
        finally:
 
            log.debug('Request time: %.3fs' % (time.time() - start))
 
            meta.Session.remove()
 

	
 

	
 
class BaseRepoController(BaseController):
 
    """
 
    Base class for controllers responsible for loading all needed data for
 
    repository loaded items are
 

	
 
    c.rhodecode_repo: instance of scm repository
 
    c.rhodecode_db_repo: instance of db
 
    c.repository_followers: number of followers
 
    c.repository_forks: number of forks
 
    """
 

	
 
    def __before__(self):
 
        super(BaseRepoController, self).__before__()
 
        if c.repo_name:
 

	
 
            c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
 
            c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
 

	
 
            if c.rhodecode_repo is None:
 
                log.error('%s this repository is present in database but it '
 
                          'cannot be created as an scm instance', c.repo_name)
 

	
 
                redirect(url('home'))
 

	
 
            c.repository_followers = self.scm_model.get_followers(c.repo_name)
 
            c.repository_forks = self.scm_model.get_forks(c.repo_name)
 

	
rhodecode/lib/celerylib/tasks.py
Show inline comments
 
@@ -277,98 +277,98 @@ def send_password_link(user_email):
 
@task(ignore_result=True)
 
def reset_user_password(user_email):
 
    from rhodecode.lib import auth
 

	
 
    log = get_logger(reset_user_password)
 

	
 
    try:
 
        try:
 
            sa = get_session()
 
            user = User.get_by_email(user_email)
 
            new_passwd = auth.PasswordGenerator().gen_password(8,
 
                             auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
 
            if user:
 
                user.password = auth.get_crypt_password(new_passwd)
 
                user.api_key = auth.generate_api_key(user.username)
 
                sa.add(user)
 
                sa.commit()
 
                log.info('change password for %s', user_email)
 
            if new_passwd is None:
 
                raise Exception('unable to generate new password')
 
        except:
 
            log.error(traceback.format_exc())
 
            sa.rollback()
 

	
 
        run_task(send_email, user_email,
 
                 'Your new password',
 
                 'Your new RhodeCode password:%s' % (new_passwd))
 
        log.info('send new password mail to %s', user_email)
 

	
 
    except:
 
        log.error('Failed to update user password')
 
        log.error(traceback.format_exc())
 

	
 
    return True
 

	
 

	
 
@task(ignore_result=True)
 
def send_email(recipients, subject, body, html_body=''):
 
    """
 
    Sends an email with defined parameters from the .ini files.
 

	
 
    :param recipients: list of recipients, it this is empty the defined email
 
        address from field 'email_to' is used instead
 
    :param subject: subject of the mail
 
    :param body: body of the mail
 
    :param html_body: html version of body
 
    """
 
    log = get_logger(send_email)
 
    sa = get_session()
 
    email_config = config
 

	
 
    subject = "%s %s" % (email_config.get('email_prefix'), subject)
 
    if not recipients:
 
        # if recipients are not defined we send to email_config + all admins
 
        admins = [u.email for u in User.query()
 
                  .filter(User.admin == True).all()]
 
        recipients = [email_config.get('email_to')] + admins
 

	
 
    mail_from = email_config.get('app_email_from', 'RhodeCode')
 
    user = email_config.get('smtp_username')
 
    passwd = email_config.get('smtp_password')
 
    mail_server = email_config.get('smtp_server')
 
    mail_port = email_config.get('smtp_port')
 
    tls = str2bool(email_config.get('smtp_use_tls'))
 
    ssl = str2bool(email_config.get('smtp_use_ssl'))
 
    debug = str2bool(config.get('debug'))
 
    smtp_auth = email_config.get('smtp_auth')
 

	
 
    try:
 
        m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
 
                       mail_port, ssl, tls, debug=debug)
 
        m.send(recipients, subject, body, html_body)
 
    except:
 
        log.error('Mail sending failed')
 
        log.error(traceback.format_exc())
 
        return False
 
    return True
 

	
 

	
 
@task(ignore_result=True)
 
def create_repo_fork(form_data, cur_user):
 
    """
 
    Creates a fork of repository using interval VCS methods
 
    
 
    :param form_data:
 
    :param cur_user:
 
    """
 
    from rhodecode.model.repo import RepoModel
 

	
 
    log = get_logger(create_repo_fork)
 

	
 
    Session = get_session()
 
    base_path = Repository.base_path()
 

	
 
    RepoModel(Session).create(form_data, cur_user, just_db=True, fork=True)
 

	
 
    alias = form_data['repo_type']
 
    org_repo_name = form_data['org_path']
 
    source_repo_path = os.path.join(base_path, org_repo_name)
rhodecode/lib/celerypylons/commands.py
Show inline comments
 
import rhodecode
 
from rhodecode.lib.utils import BasePasterCommand, Command
 
from celery.app import app_or_default
 
from celery.bin import camqadm, celerybeat, celeryd, celeryev
 

	
 
from rhodecode.lib import str2bool
 

	
 
__all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand',
 
           'CAMQPAdminCommand', 'CeleryEventCommand']
 

	
 

	
 
class CeleryCommand(BasePasterCommand):
 
    """Abstract class implements run methods needed for celery
 

	
 
    Starts the celery worker that uses a paste.deploy configuration
 
    file.
 
    """
 

	
 
    def update_parser(self):
 
        """
 
        Abstract method.  Allows for the class's parser to be updated
 
        before the superclass's `run` method is called.  Necessary to
 
        allow options/arguments to be passed through to the underlying
 
        celery command.
 
        """
 

	
 
        cmd = self.celery_command(app_or_default())
 
        for x in cmd.get_options():
 
            self.parser.add_option(x)
 

	
 
    def command(self):
 
        from pylons import config
 
        try:
 
            CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
 
        except KeyError:
 
            CELERY_ON = False
 

	
 
        if CELERY_ON == False:
 
            raise Exception('Please enable celery_on in .ini config '
 
                            'file before running celeryd')
 

	
 
        rhodecode.CELERY_ON = CELERY_ON
 
        cmd = self.celery_command(app_or_default())
 
        return cmd.run(**vars(self.options))
 

	
 
class CeleryDaemonCommand(CeleryCommand):
 
    """Start the celery worker
 

	
 
    Starts the celery worker that uses a paste.deploy configuration
 
    file.
 
    """
 
    usage = 'CONFIG_FILE [celeryd options...]'
 
    summary = __doc__.splitlines()[0]
 
    description = "".join(__doc__.splitlines()[2:])
 

	
 
    parser = Command.standard_parser(quiet=True)
 
    celery_command = celeryd.WorkerCommand
 

	
 

	
 
class CeleryBeatCommand(CeleryCommand):
 
    """Start the celery beat server
 

	
 
    Starts the celery beat server using a paste.deploy configuration
 
    file.
 
    """
 
    usage = 'CONFIG_FILE [celerybeat options...]'
 
    summary = __doc__.splitlines()[0]
 
    description = "".join(__doc__.splitlines()[2:])
 

	
 
    parser = Command.standard_parser(quiet=True)
 
    celery_command = celerybeat.BeatCommand
 

	
 

	
 
class CAMQPAdminCommand(CeleryCommand):
 
    """CAMQP Admin
 

	
 
    CAMQP celery admin tool.
 
    """
 
    usage = 'CONFIG_FILE [camqadm options...]'
 
    summary = __doc__.splitlines()[0]
 
    description = "".join(__doc__.splitlines()[2:])
 

	
 
    parser = Command.standard_parser(quiet=True)
 
    celery_command = camqadm.AMQPAdminCommand
 

	
 
class CeleryEventCommand(CeleryCommand):
 
    """Celery event command.
 

	
 
    Capture celery events.
 
    """
rhodecode/model/db.py
Show inline comments
 
@@ -326,107 +326,106 @@ class User(Base, BaseModel):
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % email))
 
        return q.scalar()
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 

	
 
        self.last_login = datetime.datetime.now()
 
        Session().add(self)
 
        Session().commit()
 
        log.debug('updated user %s lastlogin', self.username)
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = {'extend_existing':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('users.user_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 
    repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(length=1200000, 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)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = {'extend_existing':True}
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 

	
 
    def __repr__(self):
 
        return '<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.users_group_name.ilike(group_name))
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.users_group_name == group_name)
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache("sql_cache_short",
 
                                          "get_user_%s" % group_name))
 
        return gr.scalar()
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_user_%s" % group_name))
 
        return q.scalar()
 

	
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    @classmethod
 
    def create(cls, form_data):
 
        try:
 
            new_users_group = cls()
 
            for k, v in form_data.items():
 
                setattr(new_users_group, k, v)
 

	
 
            Session().add(new_users_group)
 
            Session().commit()
 
            return new_users_group
 
        except:
 
            log.error(traceback.format_exc())
 
            Session().rollback()
 
            raise
 

	
 
    @classmethod
 
    def update(cls, users_group_id, form_data):
 

	
 
        try:
 
            users_group = cls.get(users_group_id, cache=False)
 

	
 
            for k, v in form_data.items():
 
                if k == 'users_group_members':
 
                    users_group.members = []
 
                    Session().flush()
 
                    members_list = []
 
                    if v:
 
                        v = [v] if isinstance(v, basestring) else v
 
                        for u_id in set(v):
 
                            member = UsersGroupMember(users_group_id, u_id)
 
                            members_list.append(member)
 
                    setattr(users_group, 'members', members_list)
 
                setattr(users_group, k, v)
 

	
 
            Session().add(users_group)
 
            Session().commit()
 
        except:
 
            log.error(traceback.format_exc())
 
@@ -490,99 +489,99 @@ class Repository(Base, BaseModel):
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
 

	
 
    logs = relationship('UserLog', cascade='all')
 

	
 
    def __repr__(self):
 
        return "<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.repo_id, self.repo_name)
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return '/'
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.one()
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              cls.url_sep())
 
        q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        q = Session().query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    def groups_with_parents(self):
 
        groups = []
 
        if self.group is None:
 
            return groups
 

	
 
        cur_gr = self.group
 
        groups.insert(0, cur_gr)
 
        while 1:
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            groups.insert(0, gr)
 

	
 
        return groups
 

	
 
    @property
 
    def groups_and_repo(self):
 
        return self.groups_with_parents, self.just_name
 

	
 
    @LazyProperty
 
    def repo_path(self):
 
        """
 
        Returns base full path for that repository means where it actually
 
        exists on a filesystem
 
        """
 
        q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              Repository.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def repo_full_path(self):
 
        p = [self.repo_path]
 
        # we need to split the name by / since this is how we store the
 
        # names in the database, but that eventually needs to be converted
 
        # into a valid system path
 
        p += self.repo_name.split(Repository.url_sep())
 
        return os.path.join(*p)
 

	
 
    def get_new_name(self, repo_name):
 
@@ -804,117 +803,129 @@ class RepoGroup(Base, BaseModel):
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query().filter(Repository.group == self)
 

	
 
    @property
 
    def repositories_recursive_count(self):
 
        cnt = self.repositories.count()
 

	
 
        def children_count(group):
 
            cnt = 0
 
            for child in group.children:
 
                cnt += child.repositories.count()
 
                cnt += children_count(child)
 
            return cnt
 

	
 
        return cnt + children_count(self)
 

	
 

	
 
    def get_new_name(self, group_name):
 
        """
 
        returns new full group name based on parent and new name
 

	
 
        :param group_name:
 
        """
 
        path_prefix = (self.parent_group.full_path_splitted if
 
                       self.parent_group else [])
 
        return RepoGroup.url_sep().join(path_prefix + [group_name])
 

	
 

	
 
class Permission(Base, BaseModel):
 
    __tablename__ = 'permissions'
 
    __table_args__ = {'extend_existing':True}
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __repr__(self):
 
        return "<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.permission_id, self.permission_name)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id, cache=True):
 
        q = Session().query(UserRepoToPerm, Repository, cls)\
 
            .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
            .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
            .filter(UserRepoToPerm.user_id == default_user_id)
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short", "get_default_perms"))
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
 
    repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
 
    user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 
    permission = relationship('Permission', lazy='joined')
 

	
 
    @classmethod
 
    def has_perm(cls, user_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        return cls.query().filter(cls.user_id == user_id)\
 
            .filter(cls.permission == perm).scalar() is not None
 

	
 
    @classmethod
 
    def grant_perm(cls, user_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        new = cls()
 
        new.user_id = user_id
 
        new.permission = perm
 
        try:
 
            Session().add(new)
 
            Session().commit()
 
        except:
 
            Session().rollback()
 

	
 

	
 
    @classmethod
 
    def revoke_perm(cls, user_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        try:
 
            obj = cls.query().filter(cls.user_id == user_id)\
 
                    .filter(cls.permission == perm).one()
 
            Session().delete(obj)
 
            Session().commit()
 
        except:
 
            Session().rollback()
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
rhodecode/model/scm.py
Show inline comments
 
@@ -31,134 +31,130 @@ from vcs import get_backend
 
from vcs.exceptions import RepositoryError
 
from vcs.utils.lazy import LazyProperty
 
from vcs.nodes import FileNode
 

	
 
from rhodecode import BACKENDS
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib import safe_str
 
from rhodecode.lib.auth import HasRepoPermissionAny
 
from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
 
    action_logger, EmptyChangeset
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
 
    UserFollowing, UserLog, User
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UserTemp(object):
 
    def __init__(self, user_id):
 
        self.user_id = user_id
 

	
 
    def __repr__(self):
 
        return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
 

	
 

	
 
class RepoTemp(object):
 
    def __init__(self, repo_id):
 
        self.repo_id = repo_id
 

	
 
    def __repr__(self):
 
        return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
 

	
 
class CachedRepoList(object):
 

	
 
    def __init__(self, db_repo_list, repos_path, order_by=None):
 
        self.db_repo_list = db_repo_list
 
        self.repos_path = repos_path
 
        self.order_by = order_by
 
        self.reversed = (order_by or '').startswith('-')
 

	
 
    def __len__(self):
 
        return len(self.db_repo_list)
 

	
 
    def __repr__(self):
 
        return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
 

	
 
    def __iter__(self):
 
        for dbr in self.db_repo_list:
 

	
 
            scmr = dbr.scm_instance_cached
 

	
 
            # check permission at this level
 
            if not HasRepoPermissionAny('repository.read', 'repository.write',
 
                                        'repository.admin')(dbr.repo_name,
 
                                                            'get repo check'):
 
                continue
 

	
 
            if scmr is None:
 
                log.error('%s this repository is present in database but it '
 
                          'cannot be created as an scm instance',
 
                          dbr.repo_name)
 
                continue
 

	
 
            last_change = scmr.last_change
 
            tip = h.get_changeset_safe(scmr, 'tip')
 

	
 
            tmp_d = {}
 
            tmp_d['name'] = dbr.repo_name
 
            tmp_d['name_sort'] = tmp_d['name'].lower()
 
            tmp_d['description'] = dbr.description
 
            tmp_d['description_sort'] = tmp_d['description']
 
            tmp_d['last_change'] = last_change
 
            tmp_d['last_change_sort'] = time.mktime(last_change \
 
                                                    .timetuple())
 
            tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
 
            tmp_d['tip'] = tip.raw_id
 
            tmp_d['tip_sort'] = tip.revision
 
            tmp_d['rev'] = tip.revision
 
            tmp_d['contact'] = dbr.user.full_contact
 
            tmp_d['contact_sort'] = tmp_d['contact']
 
            tmp_d['owner_sort'] = tmp_d['contact']
 
            tmp_d['repo_archives'] = list(scmr._get_archives())
 
            tmp_d['last_msg'] = tip.message
 
            tmp_d['author'] = tip.author
 
            tmp_d['dbrepo'] = dbr.get_dict()
 
            tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork \
 
                                                                    else {}
 
            tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
 
            yield tmp_d
 

	
 
class ScmModel(BaseModel):
 
    """
 
    Generic Scm Model
 
    """
 

	
 
    @LazyProperty
 
    def repos_path(self):
 
        """
 
        Get's the repositories root path from database
 
        """
 

	
 
        q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
 

	
 
        return q.ui_value
 

	
 
    def repo_scan(self, repos_path=None):
 
        """
 
        Listing of repositories in given path. This path should not be a
 
        repository itself. Return a dictionary of repository objects
 

	
 
        :param repos_path: path to directory containing repositories
 
        """
 

	
 
        log.info('scanning for repositories in %s', repos_path)
 

	
 
        if repos_path is None:
 
            repos_path = self.repos_path
 

	
 
        baseui = make_ui('db')
 
        repos_list = {}
 

	
 
        for name, path in get_filesystem_repos(repos_path, recursive=True):
 

	
 
            # name need to be decomposed and put back together using the /
 
            # since this is internal storage separator for rhodecode
 
            name = Repository.url_sep().join(name.split(os.sep))
 

	
 
            try:
 
                if name in repos_list:
 
                    raise RepositoryError('Duplicate repository name %s '
 
                                          'found in %s' % (name, path))
 
                else:
 

	
 
                    klass = get_backend(path[0])
 

	
 
                    if path[0] == 'hg' and path[0] in BACKENDS.keys():
rhodecode/model/user.py
Show inline comments
 
@@ -44,143 +44,143 @@ from sqlalchemy.orm import joinedload
 
log = logging.getLogger(__name__)
 

	
 
PERM_WEIGHTS = {'repository.none': 0,
 
                'repository.read': 1,
 
                'repository.write': 3,
 
                'repository.admin': 3}
 

	
 

	
 
class UserModel(BaseModel):
 

	
 
    def get(self, user_id, cache=False):
 
        user = self.sa.query(User)
 
        if cache:
 
            user = user.options(FromCache("sql_cache_short",
 
                                          "get_user_%s" % user_id))
 
        return user.get(user_id)
 

	
 
    def get_by_username(self, username, cache=False, case_insensitive=False):
 

	
 
        if case_insensitive:
 
            user = self.sa.query(User).filter(User.username.ilike(username))
 
        else:
 
            user = self.sa.query(User)\
 
                .filter(User.username == username)
 
        if cache:
 
            user = user.options(FromCache("sql_cache_short",
 
                                          "get_user_%s" % username))
 
        return user.scalar()
 

	
 
    def get_by_api_key(self, api_key, cache=False):
 
        return User.get_by_api_key(api_key, cache)
 

	
 
    def create(self, form_data):
 
        try:
 
            new_user = User()
 
            for k, v in form_data.items():
 
                setattr(new_user, k, v)
 

	
 
            new_user.api_key = generate_api_key(form_data['username'])
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
            return new_user
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 

	
 
    def create_or_update(self, username, password, email, name, lastname, 
 
    def create_or_update(self, username, password, email, name, lastname,
 
                         active=True, admin=False, ldap_dn=None):
 
        """
 
        Creates a new instance if not found, or updates current one
 
        
 
        :param username:
 
        :param password:
 
        :param email:
 
        :param active:
 
        :param name:
 
        :param lastname:
 
        :param active:
 
        :param admin:
 
        :param ldap_dn:
 
        """
 
        
 

	
 
        from rhodecode.lib.auth import get_crypt_password
 
        
 

	
 
        log.debug('Checking for %s account in RhodeCode database', username)
 
        user = User.get_by_username(username, case_insensitive=True)
 
        if user is None:
 
            log.debug('creating new user %s', username)            
 
            log.debug('creating new user %s', username)
 
            new_user = User()
 
        else:
 
            log.debug('updating user %s', username)            
 
            log.debug('updating user %s', username)
 
            new_user = user
 
            
 

	
 
        try:
 
            new_user.username = username
 
            new_user.admin = admin
 
            new_user.password = get_crypt_password(password)
 
            new_user.api_key = generate_api_key(username)
 
            new_user.email = email
 
            new_user.active = active
 
            new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
 
            new_user.name = name
 
            new_user.lastname = lastname
 

	
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
            return new_user
 
        except (DatabaseError,):
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 
    
 
    
 

	
 

	
 
    def create_for_container_auth(self, username, attrs):
 
        """
 
        Creates the given user if it's not already in the database
 
        
 
        :param username:
 
        :param attrs:
 
        """
 
        if self.get_by_username(username, case_insensitive=True) is None:
 

	
 
            # autogenerate email for container account without one
 
            generate_email = lambda usr: '%s@container_auth.account' % usr
 

	
 
            try:
 
                new_user = User()
 
                new_user.username = username
 
                new_user.password = None
 
                new_user.api_key = generate_api_key(username)
 
                new_user.email = attrs['email']
 
                new_user.active = attrs.get('active', True)
 
                new_user.name = attrs['name'] or generate_email(username)
 
                new_user.lastname = attrs['lastname']
 

	
 
                self.sa.add(new_user)
 
                self.sa.commit()
 
                return new_user
 
            except (DatabaseError,):
 
                log.error(traceback.format_exc())
 
                self.sa.rollback()
 
                raise
 
        log.debug('User %s already exists. Skipping creation of account'
 
                  ' for container auth.', username)
 
        return None
 

	
 
    def create_ldap(self, username, password, user_dn, attrs):
 
        """
 
        Checks if user is in database, if not creates this user marked
 
        as ldap user
 
        
 
        :param username:
 
        :param password:
 
        :param user_dn:
 
        :param attrs:
 
        """
 
        from rhodecode.lib.auth import get_crypt_password
 
        log.debug('Checking for such ldap account in RhodeCode database')
 
        if self.get_by_username(username, case_insensitive=True) is None:
 

	
 
            # autogenerate email for ldap account without one
 
@@ -309,167 +309,163 @@ class UserModel(BaseModel):
 
        """
 
        Fetches auth_user by user_id,or api_key if present.
 
        Fills auth_user attributes with those taken from database.
 
        Additionally set's is_authenitated if lookup fails
 
        present in database
 

	
 
        :param auth_user: instance of user to set attributes
 
        :param user_id: user id to fetch by
 
        :param api_key: api key to fetch by
 
        """
 
        if user_id is None and api_key is None:
 
            raise Exception('You need to pass user_id or api_key')
 

	
 
        try:
 
            if api_key:
 
                dbuser = self.get_by_api_key(api_key)
 
            else:
 
                dbuser = self.get(user_id)
 

	
 
            if dbuser is not None and dbuser.active:
 
                log.debug('filling %s data', dbuser)
 
                for k, v in dbuser.get_dict().items():
 
                    setattr(auth_user, k, v)
 
            else:
 
                return False
 

	
 
        except:
 
            log.error(traceback.format_exc())
 
            auth_user.is_authenticated = False
 
            return False
 

	
 
        return True
 

	
 
    def fill_perms(self, user):
 
        """
 
        Fills user permission attribute with permissions taken from database
 
        works for permissions given for repositories, and for permissions that
 
        are granted to groups
 

	
 
        :param user: user instance to fill his perms
 
        """
 

	
 
        user.permissions['repositories'] = {}
 
        user.permissions['global'] = set()
 

	
 
        #======================================================================
 
        # fetch default permissions
 
        #======================================================================
 
        default_user = User.get_by_username('default')
 
        default_user = User.get_by_username('default', cache=True)
 
        default_user_id = default_user.user_id
 

	
 
        default_perms = self.sa.query(UserRepoToPerm, Repository, Permission)\
 
            .join((Repository, UserRepoToPerm.repository_id ==
 
                   Repository.repo_id))\
 
            .join((Permission, UserRepoToPerm.permission_id ==
 
                   Permission.permission_id))\
 
            .filter(UserRepoToPerm.user == default_user).all()
 
        default_perms = Permission.get_default_perms(default_user_id)
 

	
 
        if user.is_admin:
 
            #==================================================================
 
            # #admin have all default rights set to admin
 
            #==================================================================
 
            user.permissions['global'].add('hg.admin')
 

	
 
            for perm in default_perms:
 
                p = 'repository.admin'
 
                user.permissions['repositories'][perm.UserRepoToPerm.
 
                                                 repository.repo_name] = p
 

	
 
        else:
 
            #==================================================================
 
            # set default permissions
 
            #==================================================================
 
            uid = user.user_id
 

	
 
            #default global
 
            default_global_perms = self.sa.query(UserToPerm)\
 
                .filter(UserToPerm.user == default_user)
 
                .filter(UserToPerm.user_id == default_user_id)
 

	
 
            for perm in default_global_perms:
 
                user.permissions['global'].add(perm.permission.permission_name)
 

	
 
            #default for repositories
 
            for perm in default_perms:
 
                if perm.Repository.private and not (perm.Repository.user_id ==
 
                                                    uid):
 
                    #diself.sable defaults for private repos,
 
                    #disable defaults for private repos,
 
                    p = 'repository.none'
 
                elif perm.Repository.user_id == uid:
 
                    #set admin if owner
 
                    p = 'repository.admin'
 
                else:
 
                    p = perm.Permission.permission_name
 

	
 
                user.permissions['repositories'][perm.UserRepoToPerm.
 
                                                 repository.repo_name] = p
 

	
 
            #==================================================================
 
            # overwrite default with user permissions if any
 
            #==================================================================
 

	
 
            #user global
 
            user_perms = self.sa.query(UserToPerm)\
 
                    .options(joinedload(UserToPerm.permission))\
 
                    .filter(UserToPerm.user_id == uid).all()
 

	
 
            for perm in user_perms:
 
                user.permissions['global'].add(perm.permission.
 
                                               permission_name)
 

	
 
            #user repositories
 
            user_repo_perms = self.sa.query(UserRepoToPerm, Permission,
 
                                            Repository)\
 
                .join((Repository, UserRepoToPerm.repository_id ==
 
                       Repository.repo_id))\
 
                .join((Permission, UserRepoToPerm.permission_id ==
 
                       Permission.permission_id))\
 
                .filter(UserRepoToPerm.user_id == uid).all()
 

	
 
            for perm in user_repo_perms:
 
                # set admin if owner
 
                if perm.Repository.user_id == uid:
 
                    p = 'repository.admin'
 
                else:
 
                    p = perm.Permission.permission_name
 
                user.permissions['repositories'][perm.UserRepoToPerm.
 
                                                 repository.repo_name] = p
 

	
 
            #==================================================================
 
            # check if user is part of groups for this repository and fill in
 
            # (or replace with higher) permissions
 
            #==================================================================
 

	
 
            #users group global
 
            # users group global
 
            user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
 
                .options(joinedload(UsersGroupToPerm.permission))\
 
                .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
 
                       UsersGroupMember.users_group_id))\
 
                .filter(UsersGroupMember.user_id == uid).all()
 

	
 
            for perm in user_perms_from_users_groups:
 
                user.permissions['global'].add(perm.permission.permission_name)
 

	
 
            #users group repositories
 
            # users group repositories
 
            user_repo_perms_from_users_groups = self.sa.query(
 
                                                UsersGroupRepoToPerm,
 
                                                Permission, Repository,)\
 
                .join((Repository, UsersGroupRepoToPerm.repository_id ==
 
                       Repository.repo_id))\
 
                .join((Permission, UsersGroupRepoToPerm.permission_id ==
 
                       Permission.permission_id))\
 
                .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
 
                       UsersGroupMember.users_group_id))\
 
                .filter(UsersGroupMember.user_id == uid).all()
 

	
 
            for perm in user_repo_perms_from_users_groups:
 
                p = perm.Permission.permission_name
 
                cur_perm = user.permissions['repositories'][perm.
 
                                                    UsersGroupRepoToPerm.
 
                                                    repository.repo_name]
 
                #overwrite permission only if it's greater than permission
 
                # overwrite permission only if it's greater than permission
 
                # given from other sources
 
                if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
 
                    user.permissions['repositories'][perm.UsersGroupRepoToPerm.
 
                                                     repository.repo_name] = p
 

	
 
        return user
 

	
rhodecode/public/css/style.css
Show inline comments
 
@@ -1008,97 +1008,99 @@ div.options a {
 
#content div.box-right div.form div.fields div.field div.label,
 
#content div.box-left div.form div.fields div.field div.label,
 
#content div.box-left div.form div.fields div.field div.label-summary,
 
#content div.box-right div.form div.fields div.field div.label-summary,
 
#content div.box-left div.form div.fields div.field div.label-summary
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	left: 0;
 
	width: auto;
 
	position: relative;
 
	margin: 0;
 
	padding: 0 0 8px;
 
}
 
 
#content div.box div.form div.fields div.field div.label-select {
 
	padding: 5px 0 0 5px;
 
}
 
 
#content div.box-left div.form div.fields div.field div.label-select,
 
#content div.box-right div.form div.fields div.field div.label-select
 
	{
 
	padding: 0 0 8px;
 
}
 
 
#content div.box-left div.form div.fields div.field div.label-textarea,
 
#content div.box-right div.form div.fields div.field div.label-textarea
 
	{
 
	padding: 0 0 8px !important;
 
}
 
 
#content div.box div.form div.fields div.field div.label label,div.label label
 
	{
 
	color: #393939;
 
	font-weight: 700;
 
}
 
#content div.box div.form div.fields div.field div.label label,div.label-summary label
 
    {
 
    color: #393939;
 
    font-weight: 700;
 
}
 
#content div.box div.form div.fields div.field div.input {
 
	margin: 0 0 0 200px;
 
}
 
 
#content div.box div.form div.fields div.field div.input.summary {
 
    margin: 0 0 0 110px;
 
}
 
 
#content div.box div.form div.fields div.field div.input.summary-short {
 
    margin: 0 0 0 110px;
 
}
 
#content div.box div.form div.fields div.field div.file {
 
	margin: 0 0 0 200px;
 
}
 
 
#content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input
 
	{
 
	margin: 0 0 0 0px;
 
}
 
 
#content div.box div.form div.fields div.field div.input input {
 
	background: #FFF;
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	color: #000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 7px 7px 6px;
 
}
 
 
#content div.box div.form div.fields div.field div.file input {
 
	background: none repeat scroll 0 0 #FFFFFF;
 
	border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
 
	border-style: solid;
 
	border-width: 1px;
 
	color: #000000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 7px 7px 6px;
 
}
 
 
#content div.box div.form div.fields div.field div.input input.small {
 
	width: 30%;
 
}
 
 
#content div.box div.form div.fields div.field div.input input.medium {
 
	width: 55%;
 
}
 
 
#content div.box div.form div.fields div.field div.input input.large {
 
	width: 85%;
 
}
 
 
#content div.box div.form div.fields div.field div.input input.date {
 
	width: 177px;
 
}
 
rhodecode/templates/summary/summary.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${c.repo_name} ${_('Summary')} - ${c.rhodecode_name}
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    &raquo; 
 
    ${h.link_to(c.dbrepo.just_name,h.url('summary_home',repo_name=c.repo_name))}
 
    &raquo;
 
    ${_('summary')}
 
</%def>
 

	
 
<%def name="page_nav()">
 
	${self.menu('summary')}    
 
</%def>
 

	
 
<%
 
summary = lambda n:{False:'summary'}.get(n)
 
%>
 

	
 
<%def name="main()">
 
    <%
 
    summary = lambda n:{False:'summary-short'}.get(n)
 
    %>
 
    %if c.show_stats:
 
        <div class="box box-left">
 
    %else:
 
        <div class="box">
 
    %endif
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <!-- end box / title -->
 
	<div class="form">
 
	  <div id="summary" class="fields">
 
		 
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Name')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats)">
 
			  <div class="input ${summary(c.show_stats)}">
 
                  <div style="float:right;padding:5px 0px 0px 5px">		  
 
                     %if c.rhodecode_user.username != 'default':
 
                      ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='rss_icon')}
 
                      ${h.link_to(_('ATOM'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='atom_icon')}
 
                     %else:
 
                      ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name),class_='rss_icon')}
 
                      ${h.link_to(_('ATOM'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name),class_='atom_icon')}            
 
                     %endif  
 
                  </div>
 
                  %if c.rhodecode_user.username != 'default':
 
                      %if c.following:
 
                      <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
 
                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
 
                      </span>                 
 
                      %else:
 
                      <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
 
                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
 
                      </span>
 
                      %endif
 
                  %endif:                                  
 
                 ##REPO TYPE
 
		         %if c.dbrepo.repo_type =='hg':
 
		           <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
 
		         %endif
 
		         %if c.dbrepo.repo_type =='git':
 
		           <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
 
		         %endif 
 
                            
 
                 ##PUBLIC/PRIVATE     			  
 
	             %if c.dbrepo.private:
 
	                <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
 
	             %else:
 
	                <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
 
	             %endif
 
	             
 
	              ##REPO NAME
 
			      <span class="repo_name">${h.repo_link(c.dbrepo.groups_and_repo)}</span>
 
                  
 
                  ##FORK
 
		          %if c.dbrepo.fork:
 
	            	<div style="margin-top:5px;clear:both"">
 
	            	<a href="${h.url('summary_home',repo_name=c.dbrepo.fork.repo_name)}"><img class="icon" alt="${_('public')}" title="${_('Fork of')} ${c.dbrepo.fork.repo_name}" src="${h.url('/images/icons/arrow_divide.png')}"/>
 
	            	    ${_('Fork of')} ${c.dbrepo.fork.repo_name}
 
	            	</a>
 
	            	</div>
 
		          %endif
 
		          ##REMOTE
 
				  %if c.dbrepo.clone_uri:
 
                    <div style="margin-top:5px;clear:both">
 
                    <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}"><img class="icon" alt="${_('remote clone')}" title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}" src="${h.url('/images/icons/connect.png')}"/>
 
                        ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
 
                    </a>
 
                    </div>					
 
				  %endif		            		      
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Description')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats) desc">${h.urlify_text(c.dbrepo.description)}</div>
 
			  <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.dbrepo.description)}</div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Contact')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats)">
 
			  <div class="input ${summary(c.show_stats)}">
 
			  	<div class="gravatar">
 
			  		<img alt="gravatar" src="${h.gravatar_url(c.dbrepo.user.email)}"/>
 
			  	</div>
 
			  		${_('Username')}: ${c.dbrepo.user.username}<br/>
 
			  		${_('Name')}: ${c.dbrepo.user.name} ${c.dbrepo.user.lastname}<br/>
 
			  		${_('Email')}: <a href="mailto:${c.dbrepo.user.email}">${c.dbrepo.user.email}</a>
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Last change')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats)">
 
			  <div class="input ${summary(c.show_stats)}">
 
                  <b>${'r%s:%s' % (h.get_changeset_safe(c.rhodecode_repo,'tip').revision,
 
                            h.get_changeset_safe(c.rhodecode_repo,'tip').short_id)}</b> - 
 
			      <span class="tooltip" title="${c.rhodecode_repo.last_change}">
 
			      ${h.age(c.rhodecode_repo.last_change)}</span>
 
			      ${_('by')} ${h.get_changeset_safe(c.rhodecode_repo,'tip').author} 
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Clone url')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats)">
 
			  <div class="input ${summary(c.show_stats)}">
 
			      <input type="text" id="clone_url" readonly="readonly" value="${c.rhodecode_repo.alias} clone ${c.clone_repo_url}" size="70"/>
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Trending files')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats)">
 
			  <div class="input ${summary(c.show_stats)}">
 
                %if c.show_stats:
 
			    <div id="lang_stats"></div>
 
                %else:
 
                   ${_('Statistics are disabled for this repository')} 
 
                   %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                        ${_('Statistics are disabled for this repository')} ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-button-small")}
 
                   %endif                  
 
                        ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-button-small")}
 
                   %endif
 
                %endif		   
 
			  </div>
 
			 </div>
 
			 			
 
			 <div class="field">
 
			  <div class="label-summary">
 
			      <label>${_('Download')}:</label>
 
			  </div>
 
			  <div class="input summary(c.show_stats)">
 
			  <div class="input ${summary(c.show_stats)}">
 
		        %if len(c.rhodecode_repo.revisions) == 0:
 
		          ${_('There are no downloads yet')}
 
		        %elif c.enable_downloads is False:
 
		          ${_('Downloads are disabled for this repository')}
 
                    %if h.HasPermissionAll('hg.admin')('enable downloads on from summary'):
 
                        ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-button-small")}
 
                    %endif  		          
 
		        %else:
 
			        ${h.select('download_options',c.rhodecode_repo.get_changeset().raw_id,c.download_options)}
 
			        %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
 
			             %if cnt >=1:
 
			             |
 
			             %endif
 
			             <span class="tooltip" title="${_('Download %s as %s') %('tip',archive['type'])}" 
 
			                  id="${archive['type']+'_link'}">${h.link_to(archive['type'],
 
			                h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
 
			                fname='tip'+archive['extension']),class_="archive_icon")}</span>
 
			        %endfor
 
                    <span style="vertical-align: bottom">
 
                        <input id="archive_subrepos" type="checkbox" name="subrepos"/> <span class="tooltip" title="${_('Check this to download archive with subrepos')}" >${_('with subrepos')}</span>
 
                    </span>
 
			    %endif
 
			  </div>
 
			 </div>			 			 			 
 
	  </div>		 
 
	</div>
 
</div>
 

	
 
%if c.show_stats:        
 
<div class="box box-right"  style="min-height:455px">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Commit activity by day / author')}</h5>
 
    </div>
 
    
 
    <div class="graph">
 
         <div style="padding:0 10px 10px 15px;font-size: 1.2em;">
 
         %if c.no_data:
 
           ${c.no_data_msg}
 
           %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-button-small")}
 
           %endif         
 
        %else:
 
            ${_('Loaded in')} ${c.stats_percentage} %
 
        %endif
 
        </div>  
 
        <div id="commit_history" style="width:450px;height:300px;float:left"></div>
 
        <div style="clear: both;height: 10px"></div>
0 comments (0 inline, 0 general)